21 #include "phyobject.h"
23 #include "private/phyobjectprivate.h"
24 #include "private/worldprivate.h"
25 #include "motorcontrollers.h"
27 #include <QMutexLocker>
34 MaterialDB::MaterialDB( World* w ) : mats(), pmap() {
36 createMaterial(
"nonCollidable" );
37 createMaterial(
"default" );
41 if ( mats.contains( name ) ) {
44 #ifdef WORLDSIM_USE_NEWTON
45 NewtonWorld* ngdWorld = worldv->priv->world;
47 if ( name ==
"default" ) {
48 newm = NewtonMaterialGetDefaultGroupID( ngdWorld );
50 newm = NewtonMaterialCreateGroupID( ngdWorld );
52 worldv->priv->matIDs[name] = newm;
53 NewtonMaterialSetCollisionCallback( ngdWorld, newm, newm, (
void*)worldv, NULL, (WorldPrivate::processCollisionHandler) );
55 foreach( QString k, mats.values() ) {
56 int kid = worldv->priv->matIDs[k];
57 NewtonMaterialSetCollisionCallback( ngdWorld, newm, kid, (
void*)worldv, NULL, (WorldPrivate::processCollisionHandler) );
60 NewtonMaterialSetDefaultCollidable( ngdWorld, worldv->priv->matIDs[
"nonCollidable"], newm, 0 );
67 if ( !mats.contains( mat1 ) )
return;
68 if ( !mats.contains( mat2 ) )
return;
69 QString pkey = createKey( mat1, mat2 );
70 pmap[pkey].staticFriction = st;
71 pmap[pkey].dynamicFriction = kn;
72 #ifdef WORLDSIM_USE_NEWTON
73 int id1 = worldv->priv->matIDs[mat1];
74 int id2 = worldv->priv->matIDs[mat2];
75 NewtonMaterialSetDefaultFriction( worldv->priv->world, id1, id2, st, kn );
81 if ( !mats.contains( mat1 ) )
return;
82 if ( !mats.contains( mat2 ) )
return;
83 QString pkey = createKey( mat1, mat2 );
84 pmap[pkey].elasticity = el;
85 #ifdef WORLDSIM_USE_NEWTON
86 int id1 = worldv->priv->matIDs[mat1];
87 int id2 = worldv->priv->matIDs[mat2];
88 NewtonMaterialSetDefaultElasticity( worldv->priv->world, id1, id2, el );
94 if ( !mats.contains( mat1 ) )
return;
95 if ( !mats.contains( mat2 ) )
return;
96 QString pkey = createKey( mat1, mat2 );
97 pmap[pkey].softness = sf;
98 #ifdef WORLDSIM_USE_NEWTON
99 int id1 = worldv->priv->matIDs[mat1];
100 int id2 = worldv->priv->matIDs[mat2];
101 NewtonMaterialSetDefaultSoftness( worldv->priv->world, id1, id2, sf );
107 gravities[mat] = force;
111 if ( gravities.contains( mat ) ) {
112 return gravities[mat];
120 if ( !mats.contains( mat1 ) )
return;
121 if ( !mats.contains( mat2 ) )
return;
122 QString pkey = createKey( mat1, mat2 );
123 pmap[pkey].collisions = enable;
124 #ifdef WORLDSIM_USE_NEWTON
125 int id1 = worldv->priv->matIDs[mat1];
126 int id2 = worldv->priv->matIDs[mat2];
127 NewtonMaterialSetDefaultCollidable( worldv->priv->world, id1, id2, enable );
138 QString MaterialDB::createKey( QString mat1, QString mat2 ) {
140 return mat1 +
":" + mat2;
142 return mat2 +
":" + mat1;
147 : QObject(), minP(-100,-100,-100), maxP(100,100,100), objs(), jointsv(), mapObjJoints(),
158 priv =
new WorldPrivate();
160 #ifdef WORLDSIM_USE_NEWTON
161 priv->world = NewtonCreate();
162 NewtonInvalidateCache( priv->world );
163 NewtonSetWorldSize( priv->world, &
minP[0], &maxP[0] );
165 NewtonSetMinimumFrameRate( priv->world, 100 );
167 NewtonSetSolverModel( priv->world, 0 );
168 NewtonSetFrictionModel( priv->world, 0 );
186 if ( js->
owner() == NULL ) {
190 while ( !
objs.isEmpty() ) {
192 if ( obj->
owner() == NULL ) {
196 #ifdef WORLDSIM_USE_NEWTON
197 NewtonDestroy( priv->world );
207 if ( isInit )
return;
223 while( isrealtimev && timer.
tac()/1000000.0 <
timestepv ) { };
227 for( QLinkedList<WObject*>::iterator it =
objs.begin(); it !=
objs.end(); it++ ) {
231 for( QLinkedList<PhyJoint*>::iterator it =
jointsv.begin(); it !=
jointsv.end(); it++ ) {
237 #ifdef WORLDSIM_USE_NEWTON
241 for( QLinkedList<WObject*>::iterator it =
objs.begin(); it !=
objs.end(); it++ ) {
245 for( QLinkedList<PhyJoint*>::iterator it =
jointsv.begin(); it !=
jointsv.end(); it++ ) {
254 if ( isFinish )
return;
262 if ( state == playingS )
return timerId;
263 if ( timerId != 0 )
return timerId;
265 timerId = startTimer( 0 );
271 if ( timerId != 0 ) killTimer( timerId );
280 if ( timerId != 0 ) killTimer( timerId );
292 switch( e->type() ) {
337 #ifdef WORLDSIM_USE_NEWTON
338 NewtonSetMinimumFrameRate( priv->world, frames );
355 blockSignals(
true );
356 bool b = isrealtimev;
362 blockSignals(
false );
372 if ( obj->
name() ==
name )
return obj;
386 nobjs.insert( qMakePair( obj1, obj2 ) );
387 nobjs.insert( qMakePair( obj2, obj1 ) );
391 nobjs.remove( qMakePair( obj1, obj2 ) );
392 nobjs.remove( qMakePair( obj2, obj1 ) );
396 #ifdef WORLDSIM_USE_NEWTON
397 if ( model ==
"exact" ) {
398 NewtonSetSolverModel( priv->world, 0 );
399 }
else if ( model ==
"linear" ) {
400 NewtonSetSolverModel( priv->world, 1 );
406 #ifdef WORLDSIM_USE_NEWTON
407 if ( model ==
"exact" ) {
408 NewtonSetFrictionModel( priv->world, 0 );
409 }
else if ( model ==
"linear" ) {
410 NewtonSetFrictionModel( priv->world, 1 );
416 #ifdef WORLDSIM_USE_NEWTON
417 numThreads =
max( 1, numThreads );
418 NewtonSetThreadsCount( priv->world, numThreads );
425 #ifdef WORLDSIM_USE_NEWTON
426 NewtonSetWorldSize( priv->world, &
minP[0], &maxP[0] );
436 void World::pushObject(
WObject* phy ) {
437 objs.push_back( phy );
441 void World::popObject( WObject* phy ) {
442 const int numRemoved =
objs.removeAll( phy );
443 if ( numRemoved == 1 ) {
446 PhyObject*
const phyObject =
dynamic_cast<PhyObject*
>(phy);
447 if ( ( phyObject != NULL ) && ( cmap.contains( phyObject ) ) ) {
448 const contactVec &cvec = cmap[ phyObject ];
449 foreach ( Contact c, cvec ) {
450 contactVec &otherCVec = cmap[ c.collide ];
451 contactVec::iterator it = otherCVec.begin();
452 while ( it != otherCVec.end() ) {
453 if ( it->collide == phyObject ) {
454 it = otherCVec.erase( it );
459 if ( otherCVec.isEmpty() ) {
461 cmap.remove( c.collide );
464 cmap.remove( phyObject );
469 else if (numRemoved > 1) {
470 qDebug(
"INTERNAL ERROR: more than one object with the same address found in the World::objs list" );
475 void World::pushJoint( PhyJoint* phy ) {
478 if ( phy->parent() ) {
484 void World::popJoint( PhyJoint* phy ) {
485 const int numRemoved =
jointsv.removeAll( phy );
486 if ( numRemoved == 1 ) {
489 if ( phy->parent() ) {
496 else if (numRemoved > 1) {
497 qDebug(
"INTERNAL ERROR: more than one joint with the same address found in the World::jointsv list" );
503 #ifdef WORLDSIM_USE_NEWTON
505 NewtonInvalidateCache( priv->world );
527 #ifdef WORLDSIM_USE_NEWTON
529 real *
const tmp_data =
new real[2 * 3 * maxContacts + maxContacts];
530 real *
const tmp_contacts = &tmp_data[0 * 3 * maxContacts];
531 real *
const tmp_normals = &tmp_data[1 * 3 * maxContacts];
532 real *
const tmp_penetra = &tmp_data[2 * 3 * maxContacts];
537 const int numContacts = NewtonCollisionCollide( priv->world, maxContacts, obj1->
priv->collision, &t1[0][0], obj2->
priv->collision, &t2[0][0], tmp_contacts, tmp_normals, tmp_penetra, 0 );
540 if (contacts != NULL) {
541 contacts->resize(numContacts);
542 for (
int i = 0; i < numContacts; i++) {
543 (*contacts)[i].x = tmp_contacts[0 + i * 3];
544 (*contacts)[i].y = tmp_contacts[1 + i * 3];
545 (*contacts)[i].z = tmp_contacts[2 + i * 3];
548 if (normals != NULL) {
549 normals->resize(numContacts);
550 for (
int i = 0; i < numContacts; i++) {
551 (*normals)[i].x = tmp_normals[0 + i * 3];
552 (*normals)[i].y = tmp_normals[1 + i * 3];
553 (*normals)[i].z = tmp_normals[2 + i * 3];
556 if (penetra != NULL) {
557 penetra->resize(numContacts);
558 for (
int i = 0; i < numContacts; i++) {
559 (*penetra)[i] = tmp_penetra[i];
564 return (numContacts != 0);
571 return checkContacts( obj1, obj2, maxContacts, contacts, NULL, NULL);
573 if (!cmap.contains(obj1)) {
578 const contactVec& c = cmap[obj1];
579 bool collision =
false;
580 if (contacts != NULL) {
585 for (
int i = 0; i < c.size(); i++) {
586 if (c[i].collide == obj2) {
588 if ((contacts != NULL) && (contacts->size() < maxContacts)) {
590 contacts->append(c[i].worldPos);
601 #ifdef WORLDSIM_USE_NEWTON
609 const real contact = NewtonCollisionRayCast(obj->
priv->collision, &localStart[0], &localEnd[0], n, &attribute);
611 if (normal != NULL) {
625 #ifdef WORLDSIM_USE_NEWTON
626 WorldPrivate::WorldRayCastCallbackUserData data(start, end, onlyClosest, ignoredObjs);
629 NewtonWorldRayCast(priv->world, &start[0], &end[0], WorldPrivate::worldRayFilterCallback, &data, NULL);
633 return rayCastHitVector();
651 #ifdef WORLDSIM_USE_NEWTON
655 int ret = NewtonCollisionClosestPoint( priv->world,
656 objA->
priv->collision, &t1[0][0],
657 objB->
priv->collision, &t2[0][0],
658 &pointA[0], &pointB[0], &normal[0], 0 );