Unigine::Body Class
Header: | #include <UniginePhysics.h> |
This class is used to simulate physical bodies that allow an object to participate in physical interactions. A body can have one or several collision shapes assigned and can be connected together with joints. To transform a body, one of the following functions can be used:
All of these functions take effect when physics calculations are over and flush() is performed. Only after that transformations of the body are applied to the rendered node. If a node needs to be transformed immediately after its physical body, flushTransform() is to be called.The simulation of the body can be frozen (if a setFrozen flag is set).
You can set callbacks for a body to handle certain events:
Body Class
Members
Ptr<Body> createBody(int type)
Creates a new body of the specified type.Arguments
- int type - Body type. One of the BODY_* values.
Return value
New created body smart pointer.Ptr<Body> createBody(const char * type_name)
Creates a new body of the specified type.Arguments
- const char * type_name - Body type name.
Return value
New created body smart pointer.Ptr<Body> getBody()
Returns the pointer to the Body class instance.Return value
Body instance.int setID(int id)
Sets the unique ID for the body.Arguments
- int id - Unique ID.
Return value
1 if the ID is set successfully; otherwise, 0.int getID()
Returns the unique ID of the body.Return value
Unique ID.int getType()
Returns the type of the body.Return value
One of the BODY_* pre-defined variables.const char * getTypeName()
Returns the name of the body type.Return value
Type name.const char * getTypeName(int type)
Returns the name of a body type with a given ID.Arguments
- int type - Body type ID. One of the BODY_* values.
Return value
Body type name.void setObject(const Ptr<Object> & object)
Sets an object, which the body approximates.Arguments
- const Ptr<Object> & object - Object to approximate.
Ptr<Object> getObject()
Returns the object, which is approximated with the body.Return value
Approximated object.void setEnabled(int enable)
Enables or disables physical interactions with the body.Arguments
- int enable - 1 to enable physical interactions, 0 to disable them.
int isEnabled()
Returns a value indicating if physical interactions with the body are enabled.Return value
1 if physical interactions with the body are enabled; otherwise, 0.int isEnabledSelf()
Returns a value indicating if the body is enabled.Return value
1 if the body is enabled; otherwise, 0.void setFrozen(int frozen)
Freezes or unfreezes the body. When a body is frozen, it is not simulated (though its contacts are still calculated), until a collision with a frozen body occurs or some force is applied.Arguments
- int frozen - 1 to freeze the object, 0 to unfreeze it.
int isFrozen()
Returns a value indicating if the body is frozen. When a body is frozen, it is not simulated (though its contacts are still calculated), until a collision with a frozen body occurs or some force is applied.Return value
1 if the body is frozen; otherwise, 0.void setImmovable(int immovable)
Sets a value indicating if the body is immovable (static).Arguments
- int immovable - 1 if the body is immovable (static); otherwise, 0.
int isImmovable()
Return a value indicating if the body is immovable (static).Return value
1 if the body is immovable (static); otherwise, 0.void setGravity(int gravity)
Sets a value indicating if gravity is affecting the body.Arguments
- int gravity - 1 if the body is affected by gravity; otherwise, 0.
int isGravity()
Returns a value indicating if gravity is affecting the body.Return value
1 if the body is affected by gravity; otherwise, 0.void setName(const char * name)
Sets the name of the body.Arguments
- const char * name - Name of the body.
const char * getName()
Returns the name of the body.Return value
Name of the body.void setPhysicalMask(int mask)
Sets the bit mask for interactions with physicals. Two objects interact, if they both have matching masks.Arguments
- int mask - Integer, each bit of which is a mask.
int getPhysicalMask()
Returns the bit mask for interactions with physicals. Two objects interact, if they both have matching masks.Return value
Integer, each bit of which is a mask.void setTransform(const Math::Mat4 & transform)
Sets a transformation matrix for the body (in world coordinates). This method resets body's linear and angular velocities to defaults, sets forces and torques to zeros, nullifies counted down frozen frames. It is called, for example, when the node is dragged to a new position in the editor.Arguments
- const Math::Mat4 & transform - Transformation matrix. This matrix describes position, orientation and scale of the body.
Math::Mat4 getTransform()
Returns the transformation matrix of the body (in world coordinates). This matrix describes position and orientation of the body.Return value
Transformation matrix.void setPreserveTransform(const Math::Mat4 & transform)
Sets a transformation matrix for the body (in world coordinates). This method safely preserves body's linear and angular velocities. It changes only body coordinates - all other body parameters stay the same.Arguments
- const Math::Mat4 & transform - Transformation matrix. This matrix describes position, orientation and scale of the body.
void setVelocityTransform(const Math::Mat4 & transform)
Sets a transformation matrix (in world coordinates) and computes linear and angular velocities of the body depending on its trajectory from the current position to the specified one. The time used in calculations corresponds to physics ticks. It clears forces and torques to zeros and nullifies counted down frozen frames.Arguments
- const Math::Mat4 & transform - Transformation matrix. This matrix describes position, orientation and scale of the body.
void flushTransform()
Forces to set the transformations of the body for the node.void setPosition(const Math::Vec3 & pos)
Updates the body position. Body's linear and angular velocities will be reset to 0.Arguments
- const Math::Vec3 & pos - New position in the world coordinates.
Math::Vec3 getPosition()
Returns the body position.Return value
The body position in the world coordinates.void setRotation(const Math::quat & rot)
Updates the body rotation.Arguments
- const Math::quat & rot - New rotation in the world coordinates.
Math::quat getRotation()
Returns the body rotation.Return value
The body rotation in the world coordinates.void setDirection(const Math::vec3 & dir, const Math::vec3 & up)
Updates the direction vector of the body. By default, a direction vector points along -Z axis. This function changes its direction and reorients the body.Arguments
- const Math::vec3 & dir - New direction vector in the world coordinates. The direction vector always has unit length.
- const Math::vec3 & up - New up vector in the world coordinates.
Math::vec3 getDirection()
Returns the normalized direction vector of the body. By default, a direction vector points along -Z axis. It always has an unit length.Return value
Normalized direction vector in the world coordinates.Ptr<Body> getParent()
Returns the parent of the current body.Return value
Parent body.int isChild(const Ptr<Body> & body)
Checks if a given body is a child of the current body.Arguments
- const Ptr<Body> & body - Body to check.
Return value
1 if the provided body is a child; otherwise, 0.int getNumChildren()
Returns the number of child bodies.Return value
Number of children.int findChild(const char * name)
Searches for a child body with a given name.Arguments
- const char * name - Name of the child body.
Return value
Number of the child in the list of children, if it is found; otherwise, -1.Ptr<Body> getChild(int num)
Returns a given child body.Arguments
- int num - Child number.
Return value
Corresponding body.void addShape(const Ptr<Shape> & shape, const Math::mat4 & transform)
Adds a shape to the list of shapes comprising the body.Arguments
- const Ptr<Shape> & shape - New shape to add.
- const Math::mat4 & transform - Shape transformation matrix.
void addShape(const Ptr<Shape> & shape)
Adds a shape to the list of shapes comprising the body.Arguments
- const Ptr<Shape> & shape - New shape to add.
void removeShape(const Ptr<Shape> & shape)
Removes a given shape from the body.Arguments
- const Ptr<Shape> & shape - Shape to be removed.
void removeShape(int num)
Removes a shape with a given number from the body.Arguments
- int num - Shape number.
int isShape(const Ptr<Shape> & shape)
Checks if a given shape belongs to the body.Arguments
- const Ptr<Shape> & shape - Shape to check.
Return value
1 if the shape belongs to the body; otherwise, 0.int getNumShapes()
Returns the number of shapes comprising the body.Return value
Number of shapes.int findShape(const char * name)
Searches for a shape with a given name.Arguments
- const char * name - Name of the shape.
Return value
Number of the shape in the list of shapes, if it is found; otherwise, -1.Ptr<Shape> getShape(int num)
Returns a given shape.Arguments
- int num - Shape number.
Return value
Corresponding shape object.void setShapeTransform(int num, const Math::mat4 & transform)
Sets a transformation matrix for a given shape (in local coordinates). This matrix describes position and orientation of the shape.Arguments
- int num - Shape number.
- const Math::mat4 & transform - Transformation matrix.
Math::mat4 getShapeTransform(int num)
Returns the transformation matrix of a given shape (in local coordinates). This matrix describes position and orientation of the shape.Arguments
- int num - Shape number.
Return value
Transformation matrix.void updateShapes()
Updates all shapes of the body.void addJoint(const Ptr<Joint> & joint)
Adds a joint to the body.Arguments
- const Ptr<Joint> & joint - New joint to add.
void removeJoint(const Ptr<Joint> & joint)
Removes a given joint from the body.Arguments
- const Ptr<Joint> & joint - Joint to be removed.
void removeJoint(int num)
Removes a joint with a given number from the body.Arguments
- int num - Joint number.
void insertJoint(const Ptr<Joint> & joint, int num)
Inserts a given joint at the specified position in the list of body's joints.Arguments
- const Ptr<Joint> & joint - Joint to be inserted.
- int num - Position in the list at which a joint is to be inserted.
int isJoint(const Ptr<Joint> & joint)
Checks if a given joint belongs to the body.Arguments
- const Ptr<Joint> & joint - Joint to check.
Return value
1 if the joint belongs to the body; otherwise, 0.int getNumJoints()
Returns the number of joints in the body.Return value
Number of joints.int findJoint(const char * name)
Searches for a joint with a given name.Arguments
- const char * name - Name of the joint.
Return value
Number of the joint in the list of joints, if it is found; otherwise, -1.Ptr<Joint> getJoint(int num)
Returns a given joint.Arguments
- int num - Joint number.
Return value
Corresponding joint.Ptr<Shape> getIntersection(const Math::Vec3 & p0, const Math::Vec3 & p1, int mask, Math::Vec3 * ret_point, Math::vec3 * ret_normal)
Performs tracing from the p0 point to the p1 point to find a body shape located on that line. Intersection is found only for objects with a matching mask.
Depending on the variable passed as an argument, the result can be presented as the PhysicsIntersection or PhysicsIntersectionNormal node.
Arguments
- const Math::Vec3 & p0 - Start point of the line.
- const Math::Vec3 & p1 - End point of the line.
- int mask - Intersection mask.
- Math::Vec3 * ret_point - The PhysicsIntersection node.
- Math::vec3 * ret_normal - The PhysicsIntersectionNormal node.
Return value
Reference to the first intersected shape, if found; otherwise, 0.int getNumContacts()
Returns the number of contacts in which the body participates and which it handles.To detect all contacts in which the body participates setContactCallback() should be used.
Return value
Number of contacts.int getContactID(int num)
Returns the contact ID by the contact number.Arguments
- int num - Contact number.
Return value
Contact ID.Math::Vec3 getContactPoint(int num)
Returns world coordinates of the contact point.Arguments
- int num - Contact number.
Return value
Contact point.Math::vec3 getContactNormal(int num)
Returns a normal of the contact point, in world coordinates.Arguments
- int num - Contact number.
Return value
Contact normal.Math::vec3 getContactVelocity(int num)
Returns relative velocity in the point of a given contact.Arguments
- int num - Contact number.
Return value
Velocity vector.float getContactImpulse(int num)
Returns the relative impulse arising in the point of a given contact.Arguments
- int num - Contact number.
Return value
Impulse value.float getContactTime(int num)
Returns the time when the given contact occurs. By CCD (for spheres or capsules), it returns the time starting from the current physics simulation tick to the moment when the calculated contact is bound to happen. By non-continuous collision detection, 0 is always returned.Arguments
- int num - Contact number.
Return value
Time of the calculated contact to happen in seconds.float getContactDepth(int num)
Returns the depth by which the body penetrated with an obstacle by the given contact. This distance is measured along the contact normal.Arguments
- int num - Contact number.
Return value
Penetration depth in units.float getContactFriction(int num)
Returns relative friction arising in the point of a given contact.Arguments
- int num - Contact number.
Return value
Friction value.float getContactRestitution(int num)
Returns relative restitution arising in the point of a given contact.Arguments
- int num - Contact number.
Return value
Restitution.Ptr<Body> getContactBody0(int num)
Returns the first body participating in a given contact. This is not necessarily the current body.Arguments
- int num - Contact number.
Return value
First body.Ptr<Body> getContactBody1(int num)
Returns the second body participating in a given contact. This is not necessarily the current body.Arguments
- int num - Contact number.
Return value
Second body.Ptr<Shape> getContactShape0(int num)
Returns the first shape participating in a given contact. This shape does not necessarily belong to the current body.Arguments
- int num - Contact number.
Return value
First shape.Ptr<Shape> getContactShape1(int num)
Returns the second shape participating in a given contact. This shape does not necessarily belong to the current body.Arguments
- int num - Contact number.
Return value
Second shape.Ptr<Object> getContactObject(int num)
Returns an object participating in the contact (used for collisions with non-physical object).Arguments
- int num - Contact number.
Return value
Object in contact.int getContactSurface(int num)
Returns the surface of the current object, which is in contact (used for collisions with non-physical object).Arguments
- int num - Contact number.
Return value
Surface number.void setFrozenCallback(const Ptr<FrozenCallback> & func)
Adds a callback function to be called when a given body freezes. The signature of the frozen callback function must be as follows:void frozen_callback_function_name(BodyPtr body);
You can set a callback function as follows:
setFrozenCallback(MakeCallback(frozen_callback_function_name));
Example: Setting a body frozen callback function for a certain class:
class SomeClass {
/*...*/
// body for which a frozen callback function is to be set
Unigine::BodyPtr body;
/*...*/
};
/*...*/
// callback function
void SomeClass::on_freezing(BodyPtr body)
{
// insert your code handling freezing here
}
void SomeClass::registerCallback()
{
// setting the on_freezing() function to handle freezing for the body
body->setFrozenCallback(MakeCallback(this, &SomeClass::on_freezing));
}
Arguments
- const Ptr<FrozenCallback> & func - Callback function.
void setPositionCallback(const Ptr<PositionCallback> & func)
Adds a callback function to be called when a given body moves a certain distance (rotation is not taken into account). The signature of the position callback function must be as follows:void position_callback_function_name(BodyPtr body);
You can set a callback function as follows:
setPositionCallback(MakeCallback(position_callback_function_name));
Example: Setting a body position callback function for a certain class:
class SomeClass {
/*...*/
// body for which a position callback function is to be set
Unigine::BodyPtr body;
/*...*/
};
/*...*/
// callback function
void SomeClass::on_position(BodyPtr body)
{
// insert your code handling position changes here
}
void SomeClass::registerCallback()
{
// setting the on_position() function to handle position changes for the body
body->setPositionCallback(MakeCallback(this, &SomeClass::on_position));
}
Arguments
- const Ptr<PositionCallback> & func - Callback function.
void setContactCallback(const Ptr<ContactCallback> & func)
Adds a callback function to be called when a contact with the body emerges. The body might have no information on some of its contacts with other physical bodies, as these contacts can be handled by other bodies. The contact callback function is to be used to detect all contacts in which the body participates.void contact_callback_function_name(BodyPtr body, int num);
You can set a callback function as follows:
setContactCallback(MakeCallback(contact_callback_function_name));
Example: Setting a body contact callback function for a certain class:
class SomeClass {
/*...*/
// body for which a contact callback function is to be set
Unigine::BodyPtr body;
/*...*/
};
/*...*/
// callback function
void SomeClass::on_contact(BodyPtr body, int num)
{
// insert your code handling contacts here
}
void SomeClass::registerCallback()
{
// setting the on_contact() function to handle contacts for the body
body->setContactCallback(MakeCallback(this, &SomeClass::on_contact));
}
If you want to reposition, transform, create or delete nodes captured by your callback function, you can store them in the array and then perform all necessary operations in the update():
// list of collisions that were processed by other bodies
Vector<BodyPtr> unregistered_collisions;
// flag indicating if collisions were detected
int collision_detected = 0;
/*...*/
void contact_callback(BodyPtr body, int num)
{
// collision was detected
collision_detected = 1;
// if the collision is processed by other body, adding it to the list
if (body != this_body)
unregistered_collisions.append(body);
}
/*...*/
int update()
{
if (collision_detected)
{
// resetting collision flag
collision_detected = 0;
for (int i = 0; i< body->getNumContacts(); i++)
{
// process all nodes with which collisions were registered
NodePtr node = body->getContactObject(i)->getNode();
// changing node's rotation
if (node)
node->setRotation(quat(0.0f, 1.0f, 0.0f, 90.0f));
}
for (int i = 0; i < unregistered_collisions.size(); i++)
{
// process all unregistered collisions
NodePtr node = unregistered_collisions[i]->getObject()->getNode();
// deleting a node
if (node)
Editor::get()->removeNode(node);
}
// clearing the list of unregistered collisions after processing them
unregistered_collisions.clear();
}
}
Arguments
- const Ptr<ContactCallback> & func - Callback function.
void renderContacts()
Renders contact points of the body.void renderJoints()
Renders joints in the body.void renderShapes()
Renders shapes comprising the body.void renderVisualizer()
Renders shapes, joints and contact points of the body.Ptr<Body> clone(const Ptr<Object> & object)
Clones the body and assigns a copy to a given object.Arguments
- const Ptr<Object> & object - Object, to which the copy will be assigned.
Return value
Copy of the body.void swap(const Ptr<Body> & body)
Swaps the bodies saving the pointers.Arguments
- const Ptr<Body> & body - Body to swap.
int saveState(const Ptr<Stream> & stream)
Saves the state of a given node into a binary stream.- If a node is a parent for other nodes, states of these child nodes need to be saved manually.
- To save the state from a buffer, file or a message from a socket, make sure the stream is opened. For buffers and files, you also need to set the proper position for reading.
Arguments
- const Ptr<Stream> & stream - Stream to save node state data.
Return value
1 if node state is successfully saved; otherwise, 0.int restoreState(const Ptr<Stream> & stream)
Restores the state of a given node from a binary stream.- If a node is a parent for other nodes, states of these child nodes need to be restored manually.
- To save the state into a buffer, file or a message from a socket, make sure the stream is opened. If necessary, you can set a position for writing for buffers and files.
Arguments
- const Ptr<Stream> & stream - Stream with saved node state data.