00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "phyobject.h"
00021 #include "private/phyobjectprivate.h"
00022 #include "private/worldprivate.h"
00023
00024 namespace farsa {
00025
00026 PhyObject::PhyObject( World* w, QString name, const wMatrix& tm, bool createPrivate )
00027 : WObject( w, name, tm, false ), materialv("default") {
00028
00029 priv = new PhyObjectPrivate();
00030 worldpriv = w->priv;
00031 if ( createPrivate ) {
00032 w->pushObject( this );
00033 createPrivateObject();
00034 changedMatrix();
00035 }
00036
00037 forceAcc = wVector(0,0,0);
00038 torqueAcc = wVector(0,0,0);
00039 isKinematic = false;
00040 isStatic = false;
00041 objInertiaVec = wVector(0.0, 1.0, 1.0, 1.0);
00042 objInvInertiaVec = wVector(0.0, 1.0, 1.0, 1.0);
00043 }
00044
00045 PhyObject::~PhyObject() {
00046 #ifdef WORLDSIM_USE_NEWTON
00047 if ( priv->body != NULL ) {
00048 NewtonDestroyBody( worldpriv->world, priv->body );
00049 NewtonReleaseCollision( worldpriv->world, priv->collision );
00050 }
00051 #endif
00052 delete priv;
00053 }
00054
00055 void PhyObject::setKinematic(bool b, bool c)
00056 {
00057
00058 isKinematic = b;
00059 #ifdef WORLDSIM_USE_NEWTON
00060 if (b) {
00061
00062 NewtonBodySetTransformCallback( priv->body, 0 );
00063 NewtonBodySetForceAndTorqueCallback( priv->body, 0 );
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 if (c) {
00078
00079
00080 NewtonBodySetMassMatrix( priv->body, 0, 1, 1, 1 );
00081 } else {
00082
00083
00084 NewtonCollision* nullC = NewtonCreateNull( worldpriv->world );
00085 NewtonBodySetCollision( priv->body, nullC );
00086 NewtonReleaseCollision( worldpriv->world, nullC );
00087 }
00088 } else {
00089
00090 NewtonBodySetTransformCallback( priv->body, (PhyObjectPrivate::setTransformHandler) );
00091 NewtonBodySetForceAndTorqueCallback( priv->body, (PhyObjectPrivate::applyForceAndTorqueHandler) );
00092 NewtonBodySetFreezeState( priv->body, 0 );
00093 NewtonBodySetCollision( priv->body, priv->collision );
00094 NewtonBodySetMatrix( priv->body, &tm[0][0] );
00095
00096 if (isStatic) {
00097 NewtonBodySetMassMatrix( priv->body, 0.0, 1.0, 1.0, 1.0 );
00098 } else {
00099 NewtonBodySetMassMatrix( priv->body, objInertiaVec[0], objInertiaVec[1], objInertiaVec[2], objInertiaVec[3] );
00100 }
00101 }
00102 #endif
00103 }
00104
00105 void PhyObject::setStatic(bool b)
00106 {
00107 if (isStatic == b) return;
00108 isStatic = b;
00109 #ifdef WORLDSIM_USE_NEWTON
00110 if (b) {
00111 NewtonBodySetMassMatrix( priv->body, 0.0, 1.0, 1.0, 1.0 );
00112 } else {
00113 NewtonBodySetMassMatrix( priv->body, objInertiaVec[0], objInertiaVec[1], objInertiaVec[2], objInertiaVec[3] );
00114 }
00115 #endif
00116 }
00117
00118 void PhyObject::reset() {
00119 #ifdef WORLDSIM_USE_NEWTON
00120 wVector zero = wVector(0,0,0);
00121 forceAcc = zero;
00122 torqueAcc= zero;
00123 NewtonBodySetForce( priv->body, &forceAcc[0] );
00124 NewtonBodySetTorque( priv->body, &torqueAcc[0] );
00125 NewtonBodySetOmega( priv->body, &zero[0] );
00126 NewtonBodySetVelocity( priv->body, &zero[0] );
00127
00128 NewtonWorld* nworld = NewtonBodyGetWorld( priv->body );
00129 NewtonWorldCriticalSectionLock( nworld );
00130 for( NewtonJoint* contactList = NewtonBodyGetFirstContactJoint( priv->body ); contactList;
00131 contactList = NewtonBodyGetNextContactJoint( priv->body, contactList ) ) {
00132 void* nextContact;
00133 for( void* contact = NewtonContactJointGetFirstContact(contactList); contact; contact = nextContact ) {
00134
00135 nextContact = NewtonContactJointGetNextContact( contactList, contact );
00136 NewtonContactJointRemoveContact( contactList, contact );
00137 }
00138 }
00139 NewtonWorldCriticalSectionUnlock( nworld );
00140 #endif
00141 }
00142
00143 void PhyObject::changedMatrix() {
00144 #ifdef WORLDSIM_USE_NEWTON
00145
00146 NewtonBodySetMatrix( priv->body, &tm[0][0] );
00147 #endif
00148 }
00149
00150 void PhyObject::addForce( const wVector& force ) {
00151 forceAcc += force;
00152 }
00153
00154 void PhyObject::setForce( const wVector& force) {
00155 forceAcc = force;
00156 }
00157
00158 wVector PhyObject::force() {
00159 wVector f;
00160 #ifdef WORLDSIM_USE_NEWTON
00161 NewtonBodyGetForce( priv->body, &f[0] );
00162 #endif
00163 return f;
00164 }
00165
00166 void PhyObject::addTorque( const wVector& torque ) {
00167 torqueAcc += torque;
00168 }
00169
00170 void PhyObject::setTorque( const wVector& torque ) {
00171 torqueAcc = torque;
00172 }
00173
00174 wVector PhyObject::torque() {
00175 wVector t;
00176 #ifdef WORLDSIM_USE_NEWTON
00177 NewtonBodyGetTorque( priv->body, &t[0] );
00178 #endif
00179 return t;
00180 }
00181
00182 void PhyObject::setMassInertiaVec( const wVector& mi ) {
00183 objInertiaVec = mi;
00184 #ifdef WORLDSIM_USE_NEWTON
00185
00186 NewtonBodySetMassMatrix( priv->body, mi[0], mi[1], mi[2], mi[3] );
00187 NewtonBodyGetInvMass( priv->body, &objInvInertiaVec[0], &objInvInertiaVec[1], &objInvInertiaVec[2], &objInvInertiaVec[3]);
00188 #endif
00189 }
00190
00191 wVector PhyObject::massInertiaVec() const {
00192 return objInertiaVec;
00193 }
00194
00195 wVector PhyObject::invMassInertiaVec() const {
00196 return objInvInertiaVec;
00197 }
00198
00199 wVector PhyObject::invInertiaVec() const {
00200 wVector mi;
00201 mi[0] = objInvInertiaVec[1];
00202 mi[1] = objInvInertiaVec[2];
00203 mi[2] = objInvInertiaVec[3];
00204 mi[3] = 0.0;
00205 return mi;
00206 }
00207
00208 void PhyObject::setMass( real newmass ) {
00209 #ifdef WORLDSIM_USE_NEWTON
00210 if ( newmass < 0.0001 ) {
00211 objInertiaVec = wVector(0.0, 1.0, 1.0, 1.0);
00212 objInvInertiaVec = wVector(0.0, 1.0, 1.0, 1.0);
00213 isStatic = true;
00214 NewtonBodySetMassMatrix( priv->body, 0, 1, 1, 1 );
00215 } else {
00216 real inertia[3];
00217 real centre[3] = { 0, 0, 0 };
00218 NewtonConvexCollisionCalculateInertialMatrix( priv->collision, inertia, centre );
00219
00220 objInertiaVec = wVector(newmass, newmass*inertia[0], newmass*inertia[1], newmass*inertia[2]);
00221 NewtonBodySetMassMatrix( priv->body, objInertiaVec[0], objInertiaVec[1], objInertiaVec[2], objInertiaVec[3] );
00222
00223 NewtonBodyGetInvMass( priv->body, &objInvInertiaVec[0], &objInvInertiaVec[1], &objInvInertiaVec[2], &objInvInertiaVec[3]);
00224
00225 if (isStatic) {
00226 NewtonBodySetMassMatrix( priv->body, 0, 1, 1, 1 );
00227 }
00228 }
00229 #endif
00230 }
00231
00232 real PhyObject::mass() {
00233 return objInertiaVec[0];
00234 }
00235
00236 void PhyObject::setOmega( const wVector& omega ) {
00237 #ifdef WORLDSIM_USE_NEWTON
00238 NewtonBodySetOmega( priv->body, &omega[0] );
00239 #endif
00240 }
00241
00242 wVector PhyObject::omega() {
00243 wVector t;
00244 #ifdef WORLDSIM_USE_NEWTON
00245 NewtonBodyGetOmega( priv->body, &t[0] );
00246 #endif
00247 return t;
00248 }
00249
00250 void PhyObject::setVelocity( const wVector& velocity ) {
00251 #ifdef WORLDSIM_USE_NEWTON
00252 NewtonBodySetVelocity( priv->body, &velocity[0] );
00253 #endif
00254 }
00255
00256 wVector PhyObject::velocity() {
00257 wVector t;
00258 #ifdef WORLDSIM_USE_NEWTON
00259 NewtonBodyGetVelocity( priv->body, &t[0] );
00260 #endif
00261 return t;
00262 }
00263
00264 void PhyObject::addImpulse( const wVector& pointDeltaVeloc, const wVector& pointPosit ) {
00265 #ifdef WORLDSIM_USE_NEWTON
00266 NewtonBodyAddImpulse( priv->body, &pointDeltaVeloc[0], &pointPosit[0] );
00267 #endif
00268 }
00269
00270 void PhyObject::setMaterial( QString material ) {
00271 this->materialv = material;
00272 #ifdef WORLDSIM_USE_NEWTON
00273 if ( worldv->priv->matIDs.contains( material ) ) {
00274 NewtonBodySetMaterialGroupID( priv->body, worldv->priv->matIDs[material] );
00275 }
00276 #endif
00277 }
00278
00279 QString PhyObject::material() const {
00280 return materialv;
00281 }
00282
00283 void PhyObject::createPrivateObject() {
00284 #ifdef WORLDSIM_USE_NEWTON
00285 NewtonCollision* c = NewtonCreateNull( worldpriv->world );
00286 wMatrix initialTransformationMatrix = wMatrix::identity();
00287 priv->body = NewtonCreateBody( worldpriv->world, c, &initialTransformationMatrix[0][0] );
00288 priv->collision = NewtonBodyGetCollision( priv->body );
00289
00290 NewtonBodySetAutoSleep( priv->body, 0 );
00291 NewtonBodySetMassMatrix( priv->body, 1.0, 1.0, 1.0, 1.0 );
00292 NewtonBodySetUserData( priv->body, this );
00293
00294 NewtonBodySetTransformCallback( priv->body, (PhyObjectPrivate::setTransformHandler) );
00295 NewtonBodySetForceAndTorqueCallback( priv->body, (PhyObjectPrivate::applyForceAndTorqueHandler) );
00296 #endif
00297 }
00298
00299 }