johnstanp

Members
  • Content count

    395
  • Joined

  • Last visited

Community Reputation

267 Neutral

About johnstanp

  • Rank
    Member
  1. Template Constructor Overriding

    [quote name='Geometrian' timestamp='1321892458' post='4886244'] Hi, I have two template constructors, sorta like:[source lang="cpp]template<typename T> my_obj(T arg0, /* more args */) { /* */ } template<typename T> my_obj(const T arg0[], /* more args */) { /* */ }[/source]The problem is, when I construct the object with an array of data, it chooses the first template constructor with T=float*, instead of choosing the second as I would expect. How do I make the compiler do what I want here? Thanks, -G [/quote] Replacing T by float*, we have: my_obj<float*> my_obj(const float * arg0, /* more args */ ) my_obj<float*> my_obj(const float* arg0[], */ more args */) If the argument is a float* and T=float*, then the first constructor is called. To have the second constructor be called when T=float*, you need to pass an array of pointers to constant floats. And you don't do that in your example. You need to specialize the template class for a pointer to a type in order to obtain what you expect. I mean you should do this: [source] template<class T> class my_obj<T*> { public: my_obj(T const * arg0, /* more args */) }; [/source] Actually to have the second constructor called when you pass an array of floats (which decays to a pointer to a float), you need to do this, if you want to keep your implementation as posted: [source] float vals[16] = {}; my_obj<float> obj(vals, /* more args */); [/source] The type you must use is T=float and not T=float*.
  2. External forces and RK4

    [quote name='JimmyDeemo' timestamp='1305837080' post='4813178'] Apologies, what i meant was 'In each derivative calculation, the momentum is just the same as the forces, because time isn't taken into account.'. I will take some time an do as you suggested. The slight hurdle i have got to get over is that your method looks a little different to mine (and the articles i followed), but i am sure its all there. Once i get my head around it i will post again. [/quote] Keep in mind that the force is the derivative of the linear momentum. We're computing the derivative of a state: that's why the derivative of the state is multiplied by a time to yield a delta state... The force is the derivative of the linear momentum with respect to time: it has the dimension of a linear momentum divided by time. So yes, the derivative of the linear momentum stay constant, but the linear momentum doesn't stay constant: just like the slope of a line is constant, but not the values of y ( y = m*x + b, with m a constant => dy/dt = m and dy/dt is constant) You may know perfectly well those notions, but using the right terms remove any possibility of confusion. P.S: State x4 isn't needed: so that line should be commented.
  3. External forces and RK4

    [quote name='JimmyDeemo' timestamp='1305832100' post='4813131'] [quote name='johnstanp' timestamp='1305822367' post='4813056'] I haven't taken a lookt at your code: it is not necessary, since I'll give a general answer. You can consider that the total force applied to the rigid body is constant between t and t+dt: this is what I do for my update function using RK4. [/quote] Thanks for your reply, as well as the code but i am afraid i find you answer quite cryptic. So let me just see if i am on the right track here. What you are saying is that for a given state of a Rigid body object, forces would be accumulated in the cycle (e.g. +thrust, -drag, etc.), when it comes to each of the four derivatives it can be considered that the forces are the same and are not influenced by the time. Is that right? So therefore the momentum is just the same as the total forces acting on the object. If i have understood that right, then that's great and I'm pretty sure i can sort my code for that. But i just wondered why this was the case? [/quote] Yes, you accumulate the forces before the update and keep the accumulator constant for the RK4 integrator (update function). The state of the rigid body is constant untill you assign the result of the integration step to it i.e untill this->state_ = u_state; But no, the momentum is not the same...Since x1 != x2 and x2 != x3 and x3 != x4 if forceAcc_ != 0. Do the computing yourself, I mean by hand, that'll be a lot more clear. This is how I understood it. Take a pen, a paper and a calculator and do it by hand. I could have used a function that computes the force for a given state of the rigid body and an instant (time), meaning that I would have known beforehand the forces that would have acted upon the body, but you would have been distracted by the details of the implementation (the use of a function pointer or a functor). If you understand this first part, then I will post a version where the force actually varies during t and t+dt. But you have to understand that unless the forces acting upon the body are known beforehand, you are the only person to actually decide how they will vary between two updates. That'll be clearer after but for now, do the previous computations with a pen and a paper.
  4. External forces and RK4

    An example of how you could implement it: [source lang="cpp"] #include <iostream> struct Vector3; struct State; struct RigidBody; struct Vector3 { float x, y, z; Vector3(); Vector3( float x, float y, float z ); Vector3 & operator+=( Vector3 const & ); Vector3 operator+( Vector3 const & )const; Vector3 & operator-=( Vector3 const & ); Vector3 operator-( Vector3 const & )const; Vector3 & operator*=( float ); Vector3 operator*( float )const; Vector3 & operator/=( float ); Vector3 operator/( float )const; Vector3 cross( Vector3 const & )const; float dot( Vector3 const & )const; }; struct State { Vector3 position_; Vector3 linear_momentum_; State & operator+=( State const & ); State operator+( State const & )const; State & operator-=( State const & ); State operator-( State const & )const; State & operator*=( float ); State operator*( float )const; State & operator/=( float ); State operator/( float )const; }; struct RigidBody { float mass_; State state_; Vector3 forceAcc_; RigidBody(); RigidBody( float mass, State const & state ); void apply_force( Vector3 const & force, Vector3 const & location ); State state_derivative( State const & state ); void update( double dt ); }; State RigidBody::state_derivative( State const & state ) { State derivative; derivative.position_ = state.linear_momentum_ / mass_; derivative.linear_momentum_ = forceAcc_; return derivative; } //the value of forceAcc doesn't change during the call to update //forceAcc(t) is constant between t and t+dt void RigidBody::update( double dt ) { // k1 = dxdt( x, t ) State k1 = state_derivative( state_ ); double hdt = dt / 2.0; //x1 = x + k1 * dt / 2; State x1 = state_ + k1 * hdt; // k2 = dxdt( x1, t + dt / 2 ); State k2( state_derivative( x1 ) ); // x2 = x + k2 * dt / 2; State x2 = state_ + k2 * hdt; // k3 = dxdt( x2, t + dt / 2 ); State k3( state_derivative( x2 ) ); // x3 = x + k3 * dt; State x3 = state_ + k3 * hdt; // k4 = dxdt( x3, t + dt ); State k4( state_derivative( x3 ) ); // x4 = x + k4 * dt; State x4 = state_ + k4 * dt; //xf = x + ( k1 + k4 ) * dt / 6 + ( k2 + k3 ) * dt / 3 State u_state = state_; u_state += ( k1 + k4 ) * ( dt / 6.0 ); u_state += ( k2 + k3 ) * ( dt / 3.0 ); state_ = u_state; } int main( int argc, char ** argv ) { return 0; } [/source]
  5. External forces and RK4

    I haven't taken a lookt at your code: it is not necessary, since I'll give a general answer. You can consider that the total force applied to the rigid body is constant between t and t+dt: this is what I do for my update function using RK4.
  6. [quote name='sirpalee' timestamp='1295532776' post='4761843'] It's not nice to give people bad coda design ideas... [/quote] Why? I simply provided code for serializing a single object. Of course, such an object shouldn't have member variables that are pointers. The better advice would be: "write for all classes that need to offer such services, two member functions for reading from and writing to a binary file if simply using the read and write methods of std::ifstream and std::ofstream cannot provide the behaviour you expect". I gave a reference where the OP will find examples of the use of binary files I/O file streams.
  7. An easier way to do things, would be: [code] template< class T > void write( std::ofstream & output, T const & instance ) { output.write ( reinterpret_cast<const char*>( &instance ), sizeof( T ) ); } template< class T > void read( std::ifstream & input, T & instance ) { input.read ( reinterpret_cast<char*>( &instance ), sizeof( T ) ); } [/code] The input and output files are binary (you can't just open them and read them like you would for a text file). There are many advantages in using binary files: the book "How to Program in C++" by Deitel & Deitel has a very enlightening chapter on this topic.
  8. Calculus Help!

    [quote name='Ziel' timestamp='1294613704' post='4756295'] 2. First, multiply out (4 + h)^3. This results in h^3 + 12h^2 + 48h + 64. Which, in the whole problem results in (h^3 + 12h^2 + 48h + 64 - 64)/h. This of course simplifies to h^2 + 12h + 48. The limit of h^2 + 12h + 48 as h approaches 0 is 48. [/quote] Another way to do it, would be to directly factorize (4+h)³ - 64. We know that a³ - b³ = ( a - b )( a² + ab + b² ). Identifying a :=( 4 + h ) and b := 4, we can write: ( 4 + h )³ - 64 = [ ( 4 + h ) - 4 ] [ ( 4 + h )² + ( 4 + h )4 + 16 ] which is equal to: h[ ( 4 + h )² + ( 4 + h )4 + 16 ] The h's are simplified and we're done with the limit.
  9. Conservation of angular velocity of a rigid body

    Quote:Original post by dante_sysu My current reference is David Baraff's "An Introduction to Physically Based Modeling: Rigid Body Simulation I -- Unconstrained Rigid Body Dynamics", which can be found at http://www.cs.cmu.edu/~baraff/sigcourse/notesd1.pdf . In the second paragraph of section 2.9 on page G13, it is stated that "If you have a body floating through space with no torque acting on it, the body's angular momentum is constant. This is not true for a body's angular velocity...". In the second paragraph , it is stated that "The tensor I(t) depends on the orientation of a body." And in the next section a formula is provided: I(t) = R(t) * I_body * Transpose(R(t)). So my guess is, for some body without external force/torque, such as a long cuboid floating in space, its inertia tensor (in world coordinate) is generally not constant over time, and since w = Invert(I(t)) * AngularMomentum, the latter of which is constant, w also varies over time. Well, you should look at the equations of motion to have an answer (that's what you partially did). The equations of motion are given by: dX(t)/dt = P(t)/M dR(t)/dt = w(t)*R(t) dP(t)/dt = F(t) dL(t)/dt = T(t) We have for the auxilliary variables: I(t) = R(t) * I_body * Transpose(R(t)) w(t) = inverse(I(t)) * L(t) If L(t) is constant and R(t) varies, then I(t) varies, and then w(t) varies... [Edited by - johnstanp on December 21, 2010 8:21:08 AM]
  10. Quote:Original post by CyanPrime Thank you very much for your answer. You're welcome.
  11. Quote:Original post by CyanPrime My bad. It's 2 points, not a triangle >_< Alright, so I got two vectors that each contain a x y and z. We'll call them a and b. I create a new point in the middle of the two points. Vector3 middle = new Vector3(//order x,y,z (max.getX() - min.getX())/2, (max.getY() - min.getY())/2, (max.getZ() - min.getZ())/2 ); To get the y angle I use the formula Math.toDegrees(Math.atan2(middle.getX(), middle.getZ())) What do you mean by "y angle"? We generally want "the angle between two vectors". If you want the angle between the vector that has the point A as its origin and the point B as its end, and the y axis, just do: Vector3 A(...); Vector3 B(...); Vector3 v( substract( B, A ) ); v.normalize(); float cosine = dot_product( v, Vector3( 0, 1, 0 ) ); float angle = std::acos( cosine ); This is easy to grasp once you know what the dot product means, and what the component of a vector along an axis means(for example v.y). P.S: the angle is not signed. It's a value between 0(radian) and pi(radians). dot_product( v, v ) = squared_length( v ). [edit] Writing everything on paper, it's easy to grasp the formula for this special case. The angle will be equal to: float angle = acos( y / std::sqrt( dot_product( v, v ) ); If you want a signed angle, you can use trigonometry: you have a right triangle, its hypothenuse being formed by v, and one of the adjacent side being formed by the projection of v into the y axis. The tangent of the angle you're looking for is: Vector3 A(...); Vector3 B(...); Vector3 v( substract( B, A ) ); float xz_projection = std::sqrt( std::( pow( v.x, 2 ) + pow( v.z, 2 ) ) ); float y_projection = v.y; float tangent = xz_projection / y_projection; So the angle is equal to: float angle = std:atan2( xz_projection / y_projection ); The angle will be a value between -pi/2 and pi/2 radians. P.S: it's always nice when an OP acknowledges a provided solution. [Edited by - johnstanp on December 7, 2010 8:52:45 AM]
  12. 2d Seperating Axis Theorem

    Quote:Original post by Daan The dot product is not the normal. You can get the normal like this: x = y2 - y1 y = -(x2 - x1) I don't think it's important which way the normal is facing for this algorithm. He could ignore the way the normal is facing but then he would need computing the projection of both polygons into the normal. When you know the normal of an edge is pointing outside the polygon, you don't have to project the polygon containing that edge on its normal. The projection of all its vertices on that normal will either be null or negative. You will just need to test if a vertex of the other polygon has a negative projection to detect a collision. That speeds up things. To project vertices, just do if the normals are all unit-long: for( int unsigned i = 0; i < polygon1.edges.size(); ++i ) { Vector2 const & normal = polygon1.edges[i].outside_normal; Vector2 const & vertex = polygon1.edges[i].origin; for( int unsigned j = 0; j < polygon2.vertices.size(); ++j ) { Vector2 temp = polygon2.vertices[i]; temp.substract(vertex); Real projection = dot_product(temp,normal); if (projection<=0) { return COLLISION; } } The candidate separating axes are the normals of the two polygons and all the cross products of a normal of the first polygon and a normal of the second. [Edited by - johnstanp on December 2, 2010 6:40:58 AM]
  13. Quote:Original post by futlib There are problably only two reasons for private member functions: 1. They are used by a friend class 2. They are not const Only the first one applies to static functions, so I guess I'm not going to see those around often. The point of making some member functions private is not to make them only accessible to friend classes. There are designs that require making a function private and it has nothing to do with the necessity of enabling accessibility for a friend class. For example, you can make the copy constructor and the overloaded assignement operator private to make a class non copyable. You decide to make a member function private generally when you think that functionality is not needed by the client or the other classes. It is certainly needed by the class, but not the others. Think of them as functions doing things that we don't need to bother with to use a class, in general. That choice has nothing to do with the "constantness" of the member function.
  14. Quote:Original post by Zahlman Quote:Original post by johnstanp We use twice the memory needed for storing the objects. Really? Approach 1: Actual array of objects for each 'row', array of pointers to rows for the main list. Cost: 1 object per object, 1 pointer per row. Approach 2: Single array of all objects, array of ints storing the starting index of each row. Cost: 1 object per object, 1 int per row. On typical 32-bit systems, ints are the same size as pointers. I was speaking of my solution: Object objects1[10] = { Object(1,2), Object(2,2), Object(3,1), Object(4,0), Object(2,-5), Object(7,0), Object(0,1), Object(18,5), Object(6,10), Object(1024,-1) }; boost::array<std::vector<Object>,3 > objects2 = { std::vector<Object>(&objects[0], &objects[3]), std::vector<Object>(&objects[4], &objects[6]), std::vector<Object>(&objects[6], &objects[9]) }; The information is stored twice...This is not exactly twice the size of the information, I admit.
  15. We use twice the memory needed for storing the objects. It would be better to do that this way: Object objects1[10] = { Object(1,2), Object(2,2), Object(3,1), Object(4,0), Object(2,-5), Object(7,0), Object(0,1), Object(18,5), Object(6,10), Object(1024,-1) }; int sizes[3] = {4,3,4}; //size of each array of objects [Edited by - johnstanp on November 23, 2010 1:41:16 PM]