Inheriting from cpPivotJoint
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Inheriting from cpPivotJoint
Today I tried to make a joint that inherits from cpPivotJoint, but I ran into a couple of snags. There isn't really any elegant way to supply my own cpJointClass object, and calling the inherited preStep and applyImpulse functions is not possible.
May I propose something like the attached patch? It just exposes a couple of static functions and slightly modifies the interaction between the new and init functions.
It touches only cpPivotJoint, but if you like it, I can make a new patch which does the same to all the joints.
May I propose something like the attached patch? It just exposes a couple of static functions and slightly modifies the interaction between the new and init functions.
It touches only cpPivotJoint, but if you like it, I can make a new patch which does the same to all the joints.
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Inheriting from cpPivotJoint
I was thinking about this too. I think the best way to handle this is to split the "class" definitions out into another header. That way you can copy the struct and replace functions that you want without having to make the joint functions visible. Not quite as elegant as real OO, but it could easily be wrapped by any OO or non OO language.
I'll take a look at your patch after work.
I'll take a look at your patch after work.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Re: Inheriting from cpPivotJoint
Yeah, I see what you mean. The joint functions are currently private, my patch makes them public, but we really want them to be protected, to use c++ terms.
One more thing I thought of, by the way. Should we add a destructor function to the cpJointClass? It could be that someone would like to do some cleaning up as their joint dies.
One more thing I thought of, by the way. Should we add a destructor function to the cpJointClass? It could be that someone would like to do some cleaning up as their joint dies.
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Inheriting from cpPivotJoint
Well, I guess this is as good as any time to share my future plans for programable constraints within Chipmunk and how joints fit in with that.
Constraints control how to rigid bodies are supposed to move in relation to one another. Both collision contacts and joints are examples of constraints. Those are the most obvious kinds of constraints as they are largely based on (and actively correct) the position. There are other sorts of constraints that would be very useful as well.
By making it simple to extend existing constraints and to program new ones, it would be a good way for the community to share code. It would help people modularize and share many bits of code that would otherwise simply be written inside the update loop.
Constraints control how to rigid bodies are supposed to move in relation to one another. Both collision contacts and joints are examples of constraints. Those are the most obvious kinds of constraints as they are largely based on (and actively correct) the position. There are other sorts of constraints that would be very useful as well.
- Accurate Drag - The "damping" parameter of a cpSpace is not accurate substitute for drag.
- Accurate Damped Springs - While spring forces are not a constraint, the damping is because it changes based on the relative velocity of the two attached objects. Applying these forces manually once per step is not only annoying, but inaccurate.
- Motors - A motor supplies a force or a torque that is dependent on the current speed it already is moving by.
- Force Limited Joints - Give a normal joint a maximum force that it can use to correct itself. A useful step towards breakable joints or mouse control.
- Simple Machines - Many simple machines are costly to simulate. Consider a crank with a rope. You could simulate the rope being wound around the crank, but that would be wasteful if you only wanted the result and not a fully interactive rope. By constraining the torque and rotation of one body to a force and distance applied to another, you have a drawbridge controlled by a wheel. Jam the wheel to stop the draw bridge.
- Top-Down Friction - Not sure if there is a better name for this. Currently Chipmunk works really well for games viewed from the side, but not from the top. You can simulate a coin rolling across a table on it's edge, but not sliding on it's face.
- Rolling friction - In the real world objects sliding against each other come to a stop because there is friction. A rolling object comes to a stop because it loses energy from deforming where it touches the ground. This might be a bit of a stretch as it would have to link itself to the contact constraint somehow.
By making it simple to extend existing constraints and to program new ones, it would be a good way for the community to share code. It would help people modularize and share many bits of code that would otherwise simply be written inside the update loop.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Re: Inheriting from cpPivotJoint
This sounds very promising. I'm especially looking forward to the top-down constraints you mentioned. I did actually try to implement top-down friction joints for a racing game some time ago, but it turns out I suck at math and physics .
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Re: Inheriting from cpPivotJoint
Were you able to find a way to do this? I've thought about it, and the only way I can see might work, would be to make a getter function for each of the joint classes. Something like:slembcke wrote:I was thinking about this too. I think the best way to handle this is to split the "class" definitions out into another header. That way you can copy the struct and replace functions that you want without having to make the joint functions visible. Not quite as elegant as real OO, but it could easily be wrapped by any OO or non OO language.
Code: Select all
const cpJointClass *GetPivotJointClass() {
static cpJointClass *pivotJointClass = NULL;
if (!pivotJointClass) {
pivotJointClass = malloc(sizeof(cpJointClass));
memcpy(pivotJointClass, GetJointClass(), sizeof(cpJointClass));
pivotJointClass->type = CP_PIVOT_JOINT;
pivotJointClass->preStep = pivotJointPreStep;
pivotJointClass->applyImpulse = pivotJointApplyImpulse;
}
return pivotJointClass;
}
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Inheriting from cpPivotJoint
You can declare the struct in the header using an extern and define it in the C code making use of the static functions in scope.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Re: Inheriting from cpPivotJoint
I did consider the following example, involving the joint cpFooJoint, which inherits from cpPivotJoint and overrides the preStep function, but not the applyImpulse function:
in cpJoint.h
in cpJoint.c
in cpFooJoint.c
The problem with this approach is that the order in which cpPivotJointClass and cpFooJointClass are initialized is undefined (please correct me on this if I'm wrong), so this approach would fail for some people, but not for everyone. Depending on the mood of their linker.
I don't know what approach you had in mind, but I thought I should warn you about this potential trap.
in cpJoint.h
Code: Select all
extern const cpJointClass cpPivotJointClass;
Code: Select all
const cpJointClass cpPivotJointClass = {
CP_PIVOT_JOINT,
pivotJointPreStep,
pivotJointApplyImpulse,
};
Code: Select all
const cpJointClass cpFooJointClass = {
CP_CUSTOM_JOINT,
fooJointPreStep,
cpPivotJointClass.applyImpulse, /* DANGER: cpPivotJointClass.applyImpulse may or may not be initialized */
};
I don't know what approach you had in mind, but I thought I should warn you about this potential trap.
- slembcke
- Site Admin
- Posts: 4166
- Joined: Tue Aug 14, 2007 7:13 pm
- Contact:
Re: Inheriting from cpPivotJoint
So I've been doing a bit of a spike today playing with some of these ideas. You can take a peek here: https://chipmunk-physics.googlecode.com ... aint-spike
- I generalized, slimmed down, and modularized the existing code.
- I removed the use of pseudo-velocities for joint correction. Joints are a bit springier now, but ultimately more flexible and programable.
- Added force limits to existing joint types. This made it easy to implement grabbing with the mouse.
- Added a proper damped spring constraint. Unlike the cpDampedSpring() function, it doesn't work with forces that you have to apply manually and reset. You simply create the spring constraint and add it to the space.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
-
- Posts: 56
- Joined: Tue Sep 11, 2007 2:30 pm
- Contact:
Re: Inheriting from cpPivotJoint
I checked out that branch, and I really like those changes. Splitting all the joints/constraints into separate files is a good idea, and making cpConstraintInit accessible from outside of cpConstraint.c does address one of the problems I had with creating my own joints (although, does it not belong in cpConstraint.h, close to cpConstraintDestroy?)
I also like how the preStep and applyImpulse functions look so much simpler now.
I started this thread as a result of discussing breakable joints in another thread. I thought I could implement a cpBreakablePivotJoint by inheriting from cpPivotJoint, and putting a test in the prestep function to see if the forces were too large. Now that you've made a breakable constraint, that particular idea is no longer useful, but there could potentially be other uses for having working inheritance. Like, maybe I want to play a sound when my breakable joint snaps. Maybe by creating a cpLoudBreakableJoint which implements the preStep function like this:
I'm not actually planning to do this, but I don't think it's an entirely ridiculous thing to do. My point is, I guess, that providing powerful and flexible mechanisms is a Good Thing, even if we don't know what people will end up using them for.
This isn't really terribly important to me, and I can certainly see that exposing the preStep and applyImpulse functions have both pros and cons, so this decision is all up to you Scott. I'm not going to complain either way.
I also like how the preStep and applyImpulse functions look so much simpler now.
I started this thread as a result of discussing breakable joints in another thread. I thought I could implement a cpBreakablePivotJoint by inheriting from cpPivotJoint, and putting a test in the prestep function to see if the forces were too large. Now that you've made a breakable constraint, that particular idea is no longer useful, but there could potentially be other uses for having working inheritance. Like, maybe I want to play a sound when my breakable joint snaps. Maybe by creating a cpLoudBreakableJoint which implements the preStep function like this:
Code: Select all
void
cpLoudBreakableJointPreStep(cpConstraint *constraint, cpFloat dt, cpFloat dt_inv)
{
cpBreakableJoint *breakable = (cpBreakableJoint *)constraint;
cpConstraint *child = breakable->child;
if (child->klass->getImpulse(child) * breakable->last_dt_inv >= constraint->maxForce){
playSound("break.wav");
}
cpBreakableJointPreStep(constraint, dt, dt_inv);
}
This isn't really terribly important to me, and I can certainly see that exposing the preStep and applyImpulse functions have both pros and cons, so this decision is all up to you Scott. I'm not going to complain either way.
Who is online
Users browsing this forum: No registered users and 22 guests