/**
	 * Copy constructor. 
	 * 
	 * @param other the SimpleLightSource object to copy.
	 */
	SimpleLightSource::SimpleLightSource(const SimpleLightSource &other) 
	: Object(), ValueChangedListener(), LightSource(other), 
		mReferenceObjectName(0), mLocalPosition(0), mReferenceObject(0),
		mDistributionType(other.mDistributionType),
		mSwitchYZAxes(other.mSwitchYZAxes)
	{
		mRadius = dynamic_cast<DoubleValue*>
			(getParameter("Radius"));
		mCenterBrightness = dynamic_cast<DoubleValue*>
			(getParameter("CenterBrightness"));
		mLightColor = dynamic_cast<ColorValue*>
			(getParameter("LightColor"));
		mHideLightCone = dynamic_cast<BoolValue*>
			(getParameter("HideLightCone"));
		mReferenceObjectName = dynamic_cast<StringValue*>
			(getParameter("ReferenceObject"));
		mLocalPosition = dynamic_cast<Vector3DValue*>
			(getParameter("LocalPosition"));
		mDistributionType = dynamic_cast<IntValue*>
			(getParameter("DistributionType"));

		mOutputValues.clear();
		mInputValues.clear();
		
		createCollisionObject();
		updateLightCone();
	}
	/**
	 * Constructs a new SimpleLightSource.
	 */
	SimpleLightSource::SimpleLightSource(
			const QString &name, double brightness, double radius, int type)
	: LightSource(name, type), mRadius(0), mLightColor(0),
		mHideLightCone(0), mReferenceObjectName(0),
		mLocalPosition(0), mReferenceObject(0),
		mDistributionType(0), mSwitchYZAxes(0)
	{
		mRadius = new DoubleValue(Math::max(0.0,radius));
		mCenterBrightness = new DoubleValue(brightness);
		mLightColor = new ColorValue("yellow");
		mHideLightCone = new BoolValue(false);
		mReferenceObjectName = new StringValue("");
		mLocalPosition = new Vector3DValue(0.0, 0.0, 0.0);
		mDistributionType = new IntValue(0);
		
		mRadius->setDescription(
				"Radius of light around the light source's center");
		mCenterBrightness->setDescription(
				"The light source's brightness at center");
		mLightColor->setDescription(
				"The color of the light for visualization/simulation");
		mHideLightCone->setDescription(
				"If set to True, the light cone is hidden in the simulation");
		mReferenceObjectName->setDescription(
				"The name on another simulation object "
				"to attach the light source to");
		mLocalPosition->setDescription(
				"Position of the light source in the simulation environment");
		mDistributionType->setDescription("The type of light distribution:\n"
										   "0: homogeneous distribution\n"
										   "1: linear decay from center\n"
										   "2: Quadratic decay from center\n"
										   "3: Cubic decay from the center");
		
		addParameter("Radius", mRadius);
		addParameter("CenterBrightness", mCenterBrightness);
		addParameter("LightColor", mLightColor);
		addParameter("HideLightCone", mHideLightCone);
		addParameter("ReferenceObject", mReferenceObjectName);
		addParameter("LocalPosition", mLocalPosition);
		addParameter("DistributionType", mDistributionType);
		
		Physics::getPhysicsManager();
		
		if(mSwitchYZAxes == 0) {
			mSwitchYZAxes = Core::getInstance()->getValueManager()->
				getBoolValue(SimulationConstants::VALUE_SWITCH_YZ_AXES);
		}
		
		createCollisionObject();
		updateLightCone();
	}
Exemple #3
0
SphereObstacle::SphereObstacle(std::string name, 
		                       double pos_x, 
		                       double pos_y, 
		                       double pos_z, 
		                       double radius, 
		                       const Terrain &terrain):
	Obstacle(name, terrain),
	pos_x_(pos_x),
	pos_y_(pos_y),
	pos_z_(pos_z),
	radius_(radius){
	createCollisionObject();
}
/**
 * Method is used to detect collision. Use Bounding Box algorithm.
 */
void CollisionDetector::detectCollision()
{
    vector< boost::shared_ptr<SceneEntity> >* scene = gameScene->getWorldScene();

    unsigned int size = scene->size();

    for(unsigned int i = 0; i < size; ++i)
    {
        BoundingBox firstBox;
        firstBox.max =  scene->at(i).get()->getBoundingBox()->max;
        firstBox.min =  scene->at(i).get()->getBoundingBox()->min;
        firstBox.max += scene->at(i).get()->position;
        firstBox.min += scene->at(i).get()->position;

        bool firstHaveCollided = scene->at(i).get()->haveCollided;

        for(unsigned int j = 3; j < size; ++j)
        {
            if(i == j)
                continue;

            BoundingBox secondBox;
            bool secondHaveCollided = scene->at(j).get()->haveCollided;

            secondBox.max =  scene->at(j).get()->getBoundingBox()->max;
            secondBox.min =  scene->at(j).get()->getBoundingBox()->min;
            secondBox.max += scene->at(j).get()->position;
            secondBox.min += scene->at(j).get()->position;

            Faction atypeID_1 = scene->at(i).get()->faction;
            Faction atypeID_2 = scene->at(j).get()->faction;

            if(isCollision(firstBox,secondBox))
            {
                scene->at(i).get()->haveCollided = true;
                scene->at(j).get()->haveCollided = true;
                //handler->collisionCollection.push_back(Collision(scene->at(j).get()->position,i,j));
                Faction typeID_1 = scene->at(i).get()->faction;
                Faction typeID_2 = scene->at(j).get()->faction;

                handler->collisionCollection.push_back(
                    createCollisionObject(typeID_1, typeID_2, scene->at(j).get()->position, i, j, gameScene));
            }
        }
    }
}
bool	btBulletWorldImporter::convertAllObjects(  bParse::btBulletFile* bulletFile2)
{
	int i;
	
	for (i=0;i<bulletFile2->m_bvhs.size();i++)
	{
		btOptimizedBvh* bvh = createOptimizedBvh();

		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i];
			bvh->deSerializeDouble(*bvhData);
		} else
		{
			btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i];
			bvh->deSerializeFloat(*bvhData);
		}
		m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh);
	}



	btHashMap<btHashPtr,btCollisionShape*>	shapeMap;

	for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
	{
		btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
		btCollisionShape* shape = convertCollisionShape(shapeData);
		if (shape)
		{
	//		printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
			shapeMap.insert(shapeData,shape);
		}

		if (shape&& shapeData->m_name)
		{
			char* newname = duplicateName(shapeData->m_name);
			m_objectNameMap.insert(shape,newname);
			m_nameShapeMap.insert(newname,shape);
		}
	}

	btHashMap<btHashPtr,btCollisionObject*>	bodyMap;

	for (i=0;i<bulletFile2->m_rigidBodies.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
			btVector3 localInertia;
			localInertia.setZero();
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform);
			//	startTransform.setBasis(btMatrix3x3::getIdentity());
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				if (shape->isNonMoving())
				{
					mass = 0.f;
				}

				if (mass)
				{
					shape->calculateLocalInertia(mass,localInertia);
				}
				bool isDynamic = mass!=0.f;
				
				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name);
#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
	
		} else
		{
			btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
			btVector3 localInertia;
			localInertia.setZero();
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform);
			//	startTransform.setBasis(btMatrix3x3::getIdentity());
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				if (shape->isNonMoving())
				{
					mass = 0.f;
				}
				if (mass)
				{
					shape->calculateLocalInertia(mass,localInertia);
				}
				bool isDynamic = mass!=0.f;
				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name);
#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
		}
	}

	for (i=0;i<bulletFile2->m_collisionObjects.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeDouble(colObjData->m_worldTransform);
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);

#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
	
		} else
		{
			btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeFloat(colObjData->m_worldTransform);
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);

#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
		}
		
		printf("bla");
	}

	
	for (i=0;i<bulletFile2->m_constraints.size();i++)
	{
		btTypedConstraintData* constraintData = (btTypedConstraintData*)bulletFile2->m_constraints[i];
		btCollisionObject** colAptr = bodyMap.find(constraintData->m_rbA);
		btCollisionObject** colBptr = bodyMap.find(constraintData->m_rbB);

		btRigidBody* rbA = 0;
		btRigidBody* rbB = 0;

		if (colAptr)
		{
			rbA = btRigidBody::upcast(*colAptr);
			if (!rbA)
				rbA = &getFixedBody();
		}
		if (colBptr)
		{
			rbB = btRigidBody::upcast(*colBptr);
			if (!rbB)
				rbB = &getFixedBody();
		}
				
		btTypedConstraint* constraint = 0;

		switch (constraintData->m_objectType)
		{
		case POINT2POINT_CONSTRAINT_TYPE:
			{
				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
				{
					btPoint2PointConstraintDoubleData* p2pData = (btPoint2PointConstraintDoubleData*)constraintData;
					if (rbA && rbB)
					{					
						btVector3 pivotInA,pivotInB;
						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
						pivotInB.deSerializeDouble(p2pData->m_pivotInB);
						constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
					} else
					{
						btVector3 pivotInA;
						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
						constraint = createPoint2PointConstraint(*rbA,pivotInA);
					}
				} else
				{
					btPoint2PointConstraintFloatData* p2pData = (btPoint2PointConstraintFloatData*)constraintData;
					if (rbA&& rbB)
					{					
						btVector3 pivotInA,pivotInB;
						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
						pivotInB.deSerializeFloat(p2pData->m_pivotInB);
						constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
					
					} else
					{
						btVector3 pivotInA;
						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
						constraint = createPoint2PointConstraint(*rbA,pivotInA);
					}

				}

				break;
			}
		case HINGE_CONSTRAINT_TYPE:
			{
				btHingeConstraint* hinge = 0;

				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
				{
					btHingeConstraintDoubleData* hingeData = (btHingeConstraintDoubleData*)constraintData;
					if (rbA&& rbB)
					{
						btTransform rbAFrame,rbBFrame;
						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
						rbBFrame.deSerializeDouble(hingeData->m_rbBFrame);
						hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
					} else
					{
						btTransform rbAFrame;
						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
						hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
					}
					if (hingeData->m_enableAngularMotor)
					{
						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
					}
					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
				} else
				{
					btHingeConstraintFloatData* hingeData = (btHingeConstraintFloatData*)constraintData;
					if (rbA&& rbB)
					{
						btTransform rbAFrame,rbBFrame;
						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
						rbBFrame.deSerializeFloat(hingeData->m_rbBFrame);
						hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
					} else
					{
						btTransform rbAFrame;
						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
						hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
					}
					if (hingeData->m_enableAngularMotor)
					{
						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
					}
					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
				}

				constraint = hinge;
				break;

			}
		case CONETWIST_CONSTRAINT_TYPE:
			{
				btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData;
				btConeTwistConstraint* coneTwist = 0;
				
				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
					rbBFrame.deSerializeFloat(coneData->m_rbBFrame);
					coneTwist = createConeTwistConstraint(*rbA,*rbB,rbAFrame,rbBFrame);
				} else
				{
					btTransform rbAFrame;
					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
					coneTwist = createConeTwistConstraint(*rbA,rbAFrame);
				}
				coneTwist->setLimit(coneData->m_swingSpan1,coneData->m_swingSpan2,coneData->m_twistSpan,coneData->m_limitSoftness,coneData->m_biasFactor,coneData->m_relaxationFactor);
				coneTwist->setDamping(coneData->m_damping);
				
				constraint = coneTwist;
				break;
			}

		case D6_CONSTRAINT_TYPE:
			{
				btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData;
				btGeneric6DofConstraint* dof = 0;

				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(dofData->m_rbAFrame);
					rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
					dof = createGeneric6DofConstraint(*rbA,*rbB,rbAFrame,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
				} else
				{
					if (rbB)
					{
						btTransform rbBFrame;
						rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
						dof = createGeneric6DofConstraint(*rbB,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
					} else
					{
						printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n");
					}
				}

				if (dof)
				{
					btVector3 angLowerLimit,angUpperLimit, linLowerLimit,linUpperlimit;
					angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit);
					angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit);
					linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit);
					linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit);
					
					dof->setAngularLowerLimit(angLowerLimit);
					dof->setAngularUpperLimit(angUpperLimit);
					dof->setLinearLowerLimit(linLowerLimit);
					dof->setLinearUpperLimit(linUpperlimit);
				}

				constraint = dof;
				break;
			}
		case SLIDER_CONSTRAINT_TYPE:
			{
				btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData;
				btSliderConstraint* slider = 0;
				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(sliderData->m_rbAFrame);
					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
					slider = createSliderConstraint(*rbA,*rbB,rbAFrame,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
				} else
				{
					btTransform rbBFrame;
					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
					slider = createSliderConstraint(*rbB,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
				}
				slider->setLowerLinLimit(sliderData->m_linearLowerLimit);
				slider->setUpperLinLimit(sliderData->m_linearUpperLimit);
				slider->setLowerAngLimit(sliderData->m_angularLowerLimit);
				slider->setUpperAngLimit(sliderData->m_angularUpperLimit);
				slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame!=0);
				constraint = slider;
				break;
			}
		
		default:
			{
				printf("unknown constraint type\n");
			}
		};

		if (constraint)
		{
			constraint->setDbgDrawSize(constraintData->m_dbgDrawSize);
			if (constraintData->m_name)
			{
				char* newname = duplicateName(constraintData->m_name);
				m_nameConstraintMap.insert(newname,constraint);
				m_objectNameMap.insert(constraint,newname);
			}
			if(m_dynamicsWorld)
				m_dynamicsWorld->addConstraint(constraint,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
		}
		
	}

	return true;
}
bool	btBulletWorldImporter::convertAllObjects(  bParse::btBulletFile* bulletFile2)
{

	m_shapeMap.clear();
	m_bodyMap.clear();

	int i;
	
	for (i=0;i<bulletFile2->m_bvhs.size();i++)
	{
		btOptimizedBvh* bvh = createOptimizedBvh();

		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i];
			bvh->deSerializeDouble(*bvhData);
		} else
		{
			btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i];
			bvh->deSerializeFloat(*bvhData);
		}
		m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh);
	}



	

	for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
	{
		btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
		btCollisionShape* shape = convertCollisionShape(shapeData);
		if (shape)
		{
	//		printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
			m_shapeMap.insert(shapeData,shape);
		}

		if (shape&& shapeData->m_name)
		{
			char* newname = duplicateName(shapeData->m_name);
			m_objectNameMap.insert(shape,newname);
			m_nameShapeMap.insert(newname,shape);
		}
	}

	


	
	for (int i=0;i<bulletFile2->m_dynamicsWorldInfo.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btDynamicsWorldDoubleData* solverInfoData = (btDynamicsWorldDoubleData*)bulletFile2->m_dynamicsWorldInfo[i];
			btContactSolverInfo solverInfo;

			btVector3 gravity;
			gravity.deSerializeDouble(solverInfoData->m_gravity);

			solverInfo.m_tau = btScalar(solverInfoData->m_solverInfo.m_tau);
			solverInfo.m_damping = btScalar(solverInfoData->m_solverInfo.m_damping);
			solverInfo.m_friction = btScalar(solverInfoData->m_solverInfo.m_friction);
			solverInfo.m_timeStep = btScalar(solverInfoData->m_solverInfo.m_timeStep);

			solverInfo.m_restitution = btScalar(solverInfoData->m_solverInfo.m_restitution);
			solverInfo.m_maxErrorReduction = btScalar(solverInfoData->m_solverInfo.m_maxErrorReduction);
			solverInfo.m_sor = btScalar(solverInfoData->m_solverInfo.m_sor);
			solverInfo.m_erp = btScalar(solverInfoData->m_solverInfo.m_erp);

			solverInfo.m_erp2 = btScalar(solverInfoData->m_solverInfo.m_erp2);
			solverInfo.m_globalCfm = btScalar(solverInfoData->m_solverInfo.m_globalCfm);
			solverInfo.m_splitImpulsePenetrationThreshold = btScalar(solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold);
			solverInfo.m_splitImpulseTurnErp = btScalar(solverInfoData->m_solverInfo.m_splitImpulseTurnErp);
		
			solverInfo.m_linearSlop = btScalar(solverInfoData->m_solverInfo.m_linearSlop);
			solverInfo.m_warmstartingFactor = btScalar(solverInfoData->m_solverInfo.m_warmstartingFactor);
			solverInfo.m_maxGyroscopicForce = btScalar(solverInfoData->m_solverInfo.m_maxGyroscopicForce);
			solverInfo.m_singleAxisRollingFrictionThreshold = btScalar(solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold);
		
			solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
			solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
			solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
			solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
		
			solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;

			setDynamicsWorldInfo(gravity,solverInfo);
		} else
		{
			btDynamicsWorldFloatData* solverInfoData = (btDynamicsWorldFloatData*)bulletFile2->m_dynamicsWorldInfo[i];
			btContactSolverInfo solverInfo;

			btVector3 gravity;
			gravity.deSerializeFloat(solverInfoData->m_gravity);

			solverInfo.m_tau = solverInfoData->m_solverInfo.m_tau;
			solverInfo.m_damping = solverInfoData->m_solverInfo.m_damping;
			solverInfo.m_friction = solverInfoData->m_solverInfo.m_friction;
			solverInfo.m_timeStep = solverInfoData->m_solverInfo.m_timeStep;

			solverInfo.m_restitution = solverInfoData->m_solverInfo.m_restitution;
			solverInfo.m_maxErrorReduction = solverInfoData->m_solverInfo.m_maxErrorReduction;
			solverInfo.m_sor = solverInfoData->m_solverInfo.m_sor;
			solverInfo.m_erp = solverInfoData->m_solverInfo.m_erp;

			solverInfo.m_erp2 = solverInfoData->m_solverInfo.m_erp2;
			solverInfo.m_globalCfm = solverInfoData->m_solverInfo.m_globalCfm;
			solverInfo.m_splitImpulsePenetrationThreshold = solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold;
			solverInfo.m_splitImpulseTurnErp = solverInfoData->m_solverInfo.m_splitImpulseTurnErp;
		
			solverInfo.m_linearSlop = solverInfoData->m_solverInfo.m_linearSlop;
			solverInfo.m_warmstartingFactor = solverInfoData->m_solverInfo.m_warmstartingFactor;
			solverInfo.m_maxGyroscopicForce = solverInfoData->m_solverInfo.m_maxGyroscopicForce;
			solverInfo.m_singleAxisRollingFrictionThreshold = solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold;
		
			solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations;
			solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode;
			solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold;
			solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize;
		
			solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse;

			setDynamicsWorldInfo(gravity,solverInfo);
		}
	}


	for (i=0;i<bulletFile2->m_rigidBodies.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
			convertRigidBodyDouble(colObjData);
		} else
		{
			btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
			convertRigidBodyFloat(colObjData);
		}

		
	}

	for (i=0;i<bulletFile2->m_collisionObjects.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
				startTransform.deSerializeDouble(colObjData->m_worldTransform);
				
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
				body->setFriction(btScalar(colObjData->m_friction));
				body->setRestitution(btScalar(colObjData->m_restitution));
				
#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				m_bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
	
		} else
		{
			btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
				startTransform.deSerializeFloat(colObjData->m_worldTransform);
				
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);

#ifdef USE_INTERNAL_EDGE_UTILITY
				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
				{
					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
					if (trimesh->getTriangleInfoMap())
					{
						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
					}
				}
#endif //USE_INTERNAL_EDGE_UTILITY
				m_bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
		}
		
	}

	
	for (i=0;i<bulletFile2->m_constraints.size();i++)
	{
		btTypedConstraintData2* constraintData = (btTypedConstraintData2*)bulletFile2->m_constraints[i];
		btTypedConstraintFloatData* singleC = (btTypedConstraintFloatData*)bulletFile2->m_constraints[i];
		btTypedConstraintDoubleData* doubleC = (btTypedConstraintDoubleData*)bulletFile2->m_constraints[i];

		btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA);
		btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB);

		btRigidBody* rbA = 0;
		btRigidBody* rbB = 0;

		if (colAptr)
		{
			rbA = btRigidBody::upcast(*colAptr);
			if (!rbA)
				rbA = &getFixedBody();
		}
		if (colBptr)
		{
			rbB = btRigidBody::upcast(*colBptr);
			if (!rbB)
				rbB = &getFixedBody();
		}
		if (!rbA && !rbB)
			continue;
				
		bool isDoublePrecisionData = (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)!=0;
		
		if (isDoublePrecisionData)
		{
			if (bulletFile2->getVersion()>=282)
			{
				btTypedConstraintDoubleData* dc = (btTypedConstraintDoubleData*)constraintData;
				convertConstraintDouble(dc, rbA,rbB, bulletFile2->getVersion());
			} else
			{
				//double-precision constraints were messed up until 2.82, try to recover data...
				
				btTypedConstraintData* oldData = (btTypedConstraintData*)constraintData;
				
				convertConstraintBackwardsCompatible281(oldData, rbA,rbB, bulletFile2->getVersion());

			}
		}
		else
		{
			btTypedConstraintFloatData* dc = (btTypedConstraintFloatData*)constraintData;
			convertConstraintFloat(dc, rbA,rbB, bulletFile2->getVersion());
		}
		

	}

	return true;
}
bool	btCollisionWorldImporter::convertAllObjects( btBulletSerializedArrays* arrays)
{

	m_shapeMap.clear();
	m_bodyMap.clear();

	int i;

	for (i=0;i<arrays->m_bvhsDouble.size();i++)
	{
		btOptimizedBvh* bvh = createOptimizedBvh();
		btQuantizedBvhDoubleData* bvhData = arrays->m_bvhsDouble[i];
		bvh->deSerializeDouble(*bvhData);
		m_bvhMap.insert(arrays->m_bvhsDouble[i],bvh);
	}
	for (i=0;i<arrays->m_bvhsFloat.size();i++)
    {
        btOptimizedBvh* bvh = createOptimizedBvh();
   		btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
		bvh->deSerializeFloat(*bvhData);
		m_bvhMap.insert(arrays->m_bvhsFloat[i],bvh);
	}





	for (i=0;i<arrays->m_colShapeData.size();i++)
	{
		btCollisionShapeData* shapeData = arrays->m_colShapeData[i];
		btCollisionShape* shape = convertCollisionShape(shapeData);
		if (shape)
		{
	//		printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
			m_shapeMap.insert(shapeData,shape);
		}

		if (shape&& shapeData->m_name)
		{
			char* newname = duplicateName(shapeData->m_name);
			m_objectNameMap.insert(shape,newname);
			m_nameShapeMap.insert(newname,shape);
		}
	}


	for (i=0;i<arrays->m_collisionObjectDataDouble.size();i++)
	{
        btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
        btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
        if (shapePtr && *shapePtr)
        {
            btTransform startTransform;
            colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
            startTransform.deSerializeDouble(colObjData->m_worldTransform);

            btCollisionShape* shape = (btCollisionShape*)*shapePtr;
            btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
            body->setFriction(btScalar(colObjData->m_friction));
            body->setRestitution(btScalar(colObjData->m_restitution));

#ifdef USE_INTERNAL_EDGE_UTILITY
            if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
            {
                btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
                if (trimesh->getTriangleInfoMap())
                {
                    body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
                }
            }
#endif //USE_INTERNAL_EDGE_UTILITY
            m_bodyMap.insert(colObjData,body);
        } else
        {
            printf("error: no shape found\n");
        }
	}
	for (i=0;i<arrays->m_collisionObjectDataFloat.size();i++)
	{
        btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
        btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
        if (shapePtr && *shapePtr)
        {
            btTransform startTransform;
            colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
            startTransform.deSerializeFloat(colObjData->m_worldTransform);

            btCollisionShape* shape = (btCollisionShape*)*shapePtr;
            btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);

#ifdef USE_INTERNAL_EDGE_UTILITY
            if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
            {
                btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
                if (trimesh->getTriangleInfoMap())
                {
                    body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
                }
            }
#endif //USE_INTERNAL_EDGE_UTILITY
            m_bodyMap.insert(colObjData,body);
        } else
        {
            printf("error: no shape found\n");
        }
    }

	return true;
}
void SBCollisionManager::start()
{
#ifndef SB_NO_ODE_PHYSICS
	_singleChrCapsuleMode = getBoolAttribute("singleChrCapsuleMode");
	float jointBVLenRadRatio = (float)(getDoubleAttribute("jointBVLenRadRatio"));

	SR_CLIP(jointBVLenRadRatio, 0.001f, 1000.0f);
	_jointBVLenRadRatio = jointBVLenRadRatio;

	SBScene* scene = SmartBody::SBScene::getScene();
	SBSteerManager* steerManager = scene->getSteerManager();
	_characterRadius = (float) steerManager->getDoubleAttribute("initialConditions.radius");
	double sceneScale = scene->getDoubleAttribute("scale");
	if (sceneScale != 0.0)
	{
		_characterRadius *= (float) (1.0 / sceneScale);
	}
	_positions.clear();
	_velocities.clear();
	if (!collisionSpace)
	{
		collisionSpace = new ODECollisionSpace();

	}
	const std::vector<std::string>& characterNames = scene->getCharacterNames();
	for (std::vector<std::string>::const_iterator iter = characterNames.begin();
		 iter != characterNames.end();
		 iter++)
	{
		_positions.insert(std::pair<std::string, SrVec>((*iter), SrVec()));
		_velocities.insert(std::pair<std::string, SrVec>((*iter), SrVec()));
		SBCharacter* character = scene->getCharacter(*iter);
		if (!character->getGeomObject() || character->getGeomObject()->geomType() == "null") // no collision geometry setup for the character
		{
			if(_singleChrCapsuleMode)
			{
				//SBGeomObject* obj = new SBGeomCapsule()			
				SrBox bbox = character->getBoundingBox();	
				float yoffset = bbox.getMinimum().y - character->get_world_offset().get_translation().y;
				SrVec size = SrVec(0,_characterRadius,0);
				SBGeomObject* obj = createCollisionObject(character->getGeomObjectName(),"capsule",size,SrVec(0,yoffset,0),SrVec(0,yoffset+character->getHeight(),0));
				obj->attachToObj(character);
				addObjectToCollisionSpace(character->getGeomObjectName());
				//new SBGeomCapsule(SrVec(0,yoffset,0),SrVec(0,yoffset+character->getHeight(),0),_characterRadius);
				//character->setGeomObject(obj);
				//collisionSpace->addCollisionObjects(obj);
			}
			else // create collision capsules based on skel bones
			{
				LOG(character->getName().c_str());
				SkSkeleton* sk = character->getSkeleton();
				const std::vector<SkJoint*>& origJnts = sk->joints();
				sk->update_global_matrices();
				std::vector<SkJoint*> jnt_excld_list;
				for(unsigned int i=0; i<origJnts.size(); i++)
				{
					SkJoint* j = origJnts[i];
					SrString jname(j->jointName().c_str());
					if(jname.search("world_offset")>=0) { jnt_excld_list.push_back(j); continue; } // skip world_offset
					if(jname.search("face")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("brow")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("eye")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("nose")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("lid")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("jaw")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("tongue")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("lip")>=0)    { jnt_excld_list.push_back(j); continue; }
					if(jname.search("cheek")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("finger")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("thumb")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("index")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("middle")>=0) { jnt_excld_list.push_back(j); continue; }
					if(jname.search("pinky")>=0)  { jnt_excld_list.push_back(j); continue; }
					if(jname.search("ring")>=0)   { jnt_excld_list.push_back(j); continue; }
				}
				std::string chrName = character->getGeomObjectName();
				float chrHeight = character->getHeight();
				for(unsigned int i=0; i<origJnts.size(); i++)
				{
					SkJoint* j = origJnts[i];
					if(isJointExcluded(j, jnt_excld_list)) continue;
					SrString jname(j->jointName().c_str());
					for(int k=0; k<j->num_children(); k++)
					{
						SkJoint* j_ch = j->child(k);
						if(isJointExcluded(j_ch, jnt_excld_list)) continue;
						const SrVec& offset = j_ch->offset();
						float offset_len = offset.norm();
						float radius = offset_len / jointBVLenRadRatio;
						if(offset_len < 0.03*chrHeight) continue; // skip short bones
						std::string colObjName = chrName + ":" + j->jointName();
						if(k>0) colObjName = colObjName + ":" + boost::lexical_cast<std::string>(k);
						SBGeomObject* obj = createCollisionObject(colObjName,"capsule",SrVec(0, radius, 0),SrVec::null,offset);
						LOG("SBColMan: col primitive added: %s, len: %f, radius: %f", colObjName.c_str(), offset_len, radius);
						obj->attachToObj(dynamic_cast<SBTransformObjInterface*>(j));
						addObjectToCollisionSpace(colObjName);
					}
				}
			}
		}
	}

	const std::vector<std::string>& pawnNames = scene->getPawnNames();
	for (std::vector<std::string>::const_iterator iter = pawnNames.begin();
		 iter != pawnNames.end(); iter++)
	{
		SBPawn* pawn = scene->getPawn(*iter);
		if(pawn->getGeomObject()->geomType() != "null")
		{
			//SBGeomObject* obj = pawn->getGeomObject();
			SBGeomObject* obj = createCollisionObject(pawn->getGeomObjectName(),pawn->getGeomObject()->geomType(),pawn->getGeomObject()->getGeomSize(),SrVec::null,SrVec::null);
			obj->attachToObj(pawn);

			addObjectToCollisionSpace(pawn->getGeomObjectName());
		}
	}
#endif
}
bool	btBulletWorldImporter::loadFileFromMemory(  bParse::btBulletFile* bulletFile2)
{
	

	bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
	
	if (ok)
		bulletFile2->parse(m_verboseDumpAllTypes);
	else 
		return false;
	
	if (m_verboseDumpAllTypes)
	{
		bulletFile2->dumpChunks(bulletFile2->getFileDNA());
	}

	int i;
	btHashMap<btHashPtr,btCollisionShape*>	shapeMap;

	for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
	{
		btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
		btCollisionShape* shape = convertCollisionShape(shapeData);
		if (shape)
			shapeMap.insert(shapeData,shape);
	}

	btHashMap<btHashPtr,btCollisionObject*>	bodyMap;


	for (i=0;i<bulletFile2->m_rigidBodies.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
			btVector3 localInertia;
			localInertia.setZero();
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform);
			//	startTransform.setBasis(btMatrix3x3::getIdentity());
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				if (mass)
				{
					shape->calculateLocalInertia(mass,localInertia);
				}
				bool isDynamic = mass!=0.f;
				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape);
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
	
		} else
		{
			btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
			btVector3 localInertia;
			localInertia.setZero();
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform);
			//	startTransform.setBasis(btMatrix3x3::getIdentity());
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				if (mass)
				{
					shape->calculateLocalInertia(mass,localInertia);
				}
				bool isDynamic = mass!=0.f;
				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape);
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
		}
	}

	for (i=0;i<bulletFile2->m_collisionObjects.size();i++)
	{
		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
		{
			btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeDouble(colObjData->m_worldTransform);
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape);
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
	
		} else
		{
			btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i];
			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
			if (shapePtr && *shapePtr)
			{
				btTransform startTransform;
				startTransform.deSerializeFloat(colObjData->m_worldTransform);
				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
				btCollisionObject* body = createCollisionObject(startTransform,shape);
				bodyMap.insert(colObjData,body);
			} else
			{
				printf("error: no shape found\n");
			}
		}
		
		printf("bla");
	}

	
	for (i=0;i<bulletFile2->m_constraints.size();i++)
	{
		btTypedConstraintData* constraintData = (btTypedConstraintData*)bulletFile2->m_constraints[i];
		btCollisionObject** colAptr = bodyMap.find(constraintData->m_rbA);
		btCollisionObject** colBptr = bodyMap.find(constraintData->m_rbB);

		btRigidBody* rbA = 0;
		btRigidBody* rbB = 0;

		if (colAptr)
		{
			rbA = btRigidBody::upcast(*colAptr);
			if (!rbA)
				rbA = &getFixedBody();
		}
		if (colBptr)
		{
			rbB = btRigidBody::upcast(*colBptr);
			if (!rbB)
				rbB = &getFixedBody();
		}
				
		switch (constraintData->m_objectType)
		{
		case POINT2POINT_CONSTRAINT_TYPE:
			{
				btPoint2PointConstraint* constraint = 0;

				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
				{
					btPoint2PointConstraintDoubleData* p2pData = (btPoint2PointConstraintDoubleData*)constraintData;
					if (rbA && rbB)
					{					
						btVector3 pivotInA,pivotInB;
						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
						pivotInB.deSerializeDouble(p2pData->m_pivotInB);
						constraint = new btPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
					} else
					{
						btVector3 pivotInA;
						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
						constraint = new btPoint2PointConstraint(*rbA,pivotInA);
					}
				} else
				{
					btPoint2PointConstraintFloatData* p2pData = (btPoint2PointConstraintFloatData*)constraintData;
					if (rbA&& rbB)
					{					
						btVector3 pivotInA,pivotInB;
						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
						pivotInB.deSerializeFloat(p2pData->m_pivotInB);
						constraint = new btPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
					
					} else
					{
						btVector3 pivotInA;
						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
						constraint = new btPoint2PointConstraint(*rbA,pivotInA);
					}

				}

				m_dynamicsWorld->addConstraint(constraint,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
				constraint->setDbgDrawSize(constraintData->m_dbgDrawSize);
				break;
			}
		case HINGE_CONSTRAINT_TYPE:
			{
				btHingeConstraint* hinge = 0;

				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
				{
					btHingeConstraintDoubleData* hingeData = (btHingeConstraintDoubleData*)constraintData;
					if (rbA&& rbB)
					{
						btTransform rbAFrame,rbBFrame;
						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
						rbBFrame.deSerializeDouble(hingeData->m_rbBFrame);
						hinge = new btHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
					} else
					{
						btTransform rbAFrame;
						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
						hinge = new btHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
					}
					if (hingeData->m_enableAngularMotor)
					{
						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
					}
					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
				} else
				{
					btHingeConstraintFloatData* hingeData = (btHingeConstraintFloatData*)constraintData;
					if (rbA&& rbB)
					{
						btTransform rbAFrame,rbBFrame;
						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
						rbBFrame.deSerializeFloat(hingeData->m_rbBFrame);
						hinge = new btHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
					} else
					{
						btTransform rbAFrame;
						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
						hinge = new btHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
					}
					if (hingeData->m_enableAngularMotor)
					{
						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
					}
					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
				}
				m_dynamicsWorld->addConstraint(hinge,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
				hinge->setDbgDrawSize(constraintData->m_dbgDrawSize);
				
				
				break;

			}
		case CONETWIST_CONSTRAINT_TYPE:
			{
				btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData;
				btConeTwistConstraint* coneTwist = 0;
				
				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
					rbBFrame.deSerializeFloat(coneData->m_rbBFrame);
					coneTwist = new btConeTwistConstraint(*rbA,*rbB,rbAFrame,rbBFrame);
				} else
				{
					btTransform rbAFrame;
					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
					coneTwist = new btConeTwistConstraint(*rbA,rbAFrame);
				}
				coneTwist->setLimit(coneData->m_swingSpan1,coneData->m_swingSpan2,coneData->m_twistSpan,coneData->m_limitSoftness,coneData->m_biasFactor,coneData->m_relaxationFactor);
				coneTwist->setDamping(coneData->m_damping);
				m_dynamicsWorld->addConstraint(coneTwist,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
				coneTwist->setDbgDrawSize(constraintData->m_dbgDrawSize);


				break;
			}

		case D6_CONSTRAINT_TYPE:
			{
				btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData;
				btGeneric6DofConstraint* dof = 0;

				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(dofData->m_rbAFrame);
					rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
					dof = new btGeneric6DofConstraint(*rbA,*rbB,rbAFrame,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
				} else
				{
					btTransform rbBFrame;
					rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
					dof = new btGeneric6DofConstraint(*rbB,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
				}
				btVector3 angLowerLimit,angUpperLimit, linLowerLimit,linUpperlimit;
				angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit);
				angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit);
				linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit);
				linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit);
				
				dof->setAngularLowerLimit(angLowerLimit);
				dof->setAngularUpperLimit(angUpperLimit);
				dof->setLinearLowerLimit(linLowerLimit);
				dof->setLinearUpperLimit(linUpperlimit);

				m_dynamicsWorld->addConstraint(dof,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
				dof->setDbgDrawSize(constraintData->m_dbgDrawSize);
				break;
			}
		case SLIDER_CONSTRAINT_TYPE:
			{
				btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData;
				btSliderConstraint* slider = 0;
				if (rbA&& rbB)
				{
					btTransform rbAFrame,rbBFrame;
					rbAFrame.deSerializeFloat(sliderData->m_rbAFrame);
					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
					slider = new btSliderConstraint(*rbA,*rbB,rbAFrame,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
				} else
				{
					btTransform rbBFrame;
					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
					slider = new btSliderConstraint(*rbB,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
				}
				slider->setLowerLinLimit(sliderData->m_linearLowerLimit);
				slider->setUpperLinLimit(sliderData->m_linearUpperLimit);
				slider->setLowerAngLimit(sliderData->m_angularLowerLimit);
				slider->setUpperAngLimit(sliderData->m_angularUpperLimit);
				slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame!=0);

				m_dynamicsWorld->addConstraint(slider,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
				slider->setDbgDrawSize(constraintData->m_dbgDrawSize);

				break;
			}
		
		default:
			{
				printf("unknown constraint type\n");
			}
		};
		
	}

	return true;
}