To create a PhysicsJoint
, you’ll need access to both rigid bodies. I don’t know how to rewrite the stick()
method because it apparently has access to only one of them.
Suppose rigid body of the arrow is mainBody
, the rigid body of the target is closestBody
, and the point of impact is at pivotLocation
in physics-space coordinates. Then the essential code looks like this:
/*
* Create a constraint, its pivot located at the point of impact
* and its axes aligned with those of the arrow...
*/
// transform the POI to the arrow's local coordinates
Matrix3f closestMatrix = closestBody.getPhysicsRotationMatrix(null);
closestMatrix.invertLocal();
Vector3f closestOffset = closestBody.getPhysicsLocation(null);
closestOffset.negateLocal();
closestOffset.addLocal(pivotLocation);
closestMatrix.mult(closestOffset, closestOffset);
// locate the POI in the target's local coordinates
Matrix3f mainMatrix = mainBody.getPhysicsRotationMatrix(null);
closestMatrix.multLocal(mainMatrix);
float penetrationFraction = 0.35f; // for 35% penetration
Vector3f mainOffset = tipOffset.mult(1f - 2f * penetrationFraction);
New6Dof constraint = new New6Dof(mainBody, closestBody,
mainOffset, closestOffset, Matrix3f.IDENTITY, closestMatrix, RotationOrder.XYZ);
// disable all 3 rotational axes
for (int axisIndex = 0; axisIndex < 3; ++axisIndex) {
RotationMotor rMotor = constraint.getRotationMotor(axisIndex);
rMotor.setSpringEnabled(true); // necessary, but not sure why!
int dofIndex = axisIndex + 3;
constraint.set(MotorParam.UpperLimit, dofIndex, 0f);
constraint.set(MotorParam.LowerLimit, dofIndex, 0f);
}
constraint.setCollisionBetweenLinkedBodies(false);
physicsSpace.addJoint(constraint);
Game objects describe the state of the game. Spatials are objects JMonkeyEngine uses to organize a 3-D scene for rendering purposes.
In very simple games, one can get away with representing each game object as a Spatial
and storing game state in userdata or scene-graph controls. But for games of moderate to high complexity, it’s prudent to create data structures outside the scene graph to keep track of game state.
To clarify what’s a game object, imagine writing a networked game where 3-D rendering and user interface are handled entirely by the client, while interactions between players and their environment are simulated entirely by the server. In this scenario, game objects are data maintained by the server. Since the server doesn’t do any 3-D rendering, there would be no scene graph on the server and hence no spatials.
For another example, consider a simple chess game. The game state for chess basically consists of (1) whose turn it is and (2) the locations of the 32 pieces (65 possible locations for each). [In practice a bit more is needed for castling, pawn promotion, and stalemate detection.] The point is, it would be silly to embed this information in a scene graph.
A third way to think about game objects is in terms of save/restore. Game objects represent information written to stable storage at each save point. Sky textures, no. Inventory, yes.
To speed your project along, here are some tricks I developed for simulating arrow dynamics:
- Before each physics tick, apply torque to turn the long axis of the arrow toward its direction of travel. This simulates an effect of fletching and helps the motion look realistic. It also increases the likelihood that the point of impact will be the arrow’s head (not its shaft or fletchings or nock). So software can focus on the motion of the head, paying less attention to the rest.
- Before each physics tick, project the motion of the arrowhead during the upcoming timestep. (Use a sweep test with a small sphere representing the arrowhead.) This allows software to anticipate penetrations before any physics collision occurs. That’s when it’s easiest to simulate penetration.
- If an arrowhead is predicted to collide with a penetrable object, reduce the arrow’s speed to keep it from colliding during the current timestep. An opportunity to transfer some of its momentum to the target.
- Bullet’s continuous collision detection (CCD) doesn’t work well for long, skinny objects. If an arrowhead is predicted to collide with an impenetrable object, reflect the arrow’s velocity against the object’s surface and diminish the speed by 50% or so. This gives a convincing simulation of a ricochet without relying on Bullet’s CCD, which would need a large swept sphere.