void RotationMC::BeginLive(TimeValue t) { // Set the base point to the controller value at the start time. Quat q; cont->GetValue(t,&q,FOREVER,CTRL_ABSOLUTE); QuatToEuler(q,base); }
void RotationMC::BeginCapture(Interval record,TimeValue sampSize) { // Set the base point to the controller value at the start time. Quat q; cont->GetValue(record.Start(),&q,FOREVER,CTRL_ABSOLUTE); QuatToEuler(q,base); // Allocate a data buffer sampleCount = record.Duration()/sampSize + 1; data = new Point3[sampleCount]; for (int i=0; i<sampleCount; i++) data[i] = Point3(0,0,0); }
void Unreal3DExport::WriteTracking() { Tab<Point3> Loc; Tab<Quat> Quat; Tab<Point3> Euler; Loc.SetCount(FrameCount); Quat.SetCount(FrameCount); Euler.SetCount(FrameCount); for( int n=0; n<TrackedNodes.Count(); ++n ) { IGameNode* node = TrackedNodes[n]; for( int t=0; t<FrameCount; ++t ) { // Progress CheckCancel(); // Set frame int curframe = FrameStart + t; pScene->SetStaticFrame(curframe); // Write tracking GMatrix objTM = node->GetWorldTM(); Loc[t] = objTM.Translation(); Quat[t] = objTM.Rotation(); float eu[3]; QuatToEuler(Quat[t],eu); Euler[t]=Point3(eu[0],eu[1],eu[2]); Euler[t] *= 180.0f/pi; eu[1] *= -1; EulerToQuat(eu,Quat[t],EULERTYPE_YXZ); } for( int t=0; t<FrameCount; ++t ) { _ftprintf( fLog, _T("%sLoc[%d]=(X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Loc[t].x, Loc[t].y, Loc[t].z ); } for( int t=0; t<FrameCount; ++t ) { _ftprintf( fLog, _T("%sQuat[%d]=(W=%f,X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Quat[t].w, Quat[t].x, Quat[t].y, Quat[t].z ); } for( int t=0; t<FrameCount; ++t ) { _ftprintf( fLog, _T("%sEuler[%d]=(X=%f,Y=%f,Z=%f)\n"), node->GetName(), t, Euler[t].x, Euler[t].y, Euler[t].z ); } } }
//================================================================= // Methods for DumpFrameRotationsTEP // int DumpFrameRotationsTEP::callback(INode *pnode) { ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!"); if (::FNodeMarkedToSkip(pnode)) return TREE_CONTINUE; int iNode = ::GetIndexOfINode(pnode); TSTR strNodeName(pnode->GetName()); // The model's root is a child of the real "scene root" INode *pnodeParent = pnode->GetParentNode(); BOOL fNodeIsRoot = pnodeParent->IsRootNode( ); // Get Node's "Local" Transformation Matrix Matrix3 mat3NodeTM = pnode->GetNodeTM(m_tvToDump); Matrix3 mat3ParentTM = pnodeParent->GetNodeTM(m_tvToDump); mat3NodeTM.NoScale(); // Clear these out because they apparently mat3ParentTM.NoScale(); // screw up the following calculation. Matrix3 mat3NodeLocalTM = mat3NodeTM * Inverse(mat3ParentTM); Point3 rowTrans = mat3NodeLocalTM.GetTrans(); // check to see if the parent bone was mirrored. If so, mirror invert this bones position if (m_phec->m_rgmaxnode[iNode].imaxnodeParent >= 0 && m_phec->m_rgmaxnode[m_phec->m_rgmaxnode[iNode].imaxnodeParent].isMirrored) { rowTrans = rowTrans * -1.0f; } // Get the rotation (via decomposition into "affine parts", then quaternion-to-Euler) // Apparently the order of rotations returned by QuatToEuler() is X, then Y, then Z. AffineParts affparts; float rgflXYZRotations[3]; decomp_affine(mat3NodeLocalTM, &affparts); QuatToEuler(affparts.q, rgflXYZRotations); float xRot = rgflXYZRotations[0]; // in radians float yRot = rgflXYZRotations[1]; // in radians float zRot = rgflXYZRotations[2]; // in radians // Get rotations in the -2pi...2pi range xRot = ::FlReduceRotation(xRot); yRot = ::FlReduceRotation(yRot); zRot = ::FlReduceRotation(zRot); // Print rotations fprintf(m_pfile, "%3d %f %f %f %f %f %f\n", // Node:%-15s Rotation (x,y,z)\n", iNode, rowTrans.x, rowTrans.y, rowTrans.z, xRot, yRot, zRot); return TREE_CONTINUE; }
// =================================================================== void Listener::callbackUpdate() { // need to first call the superclass update method (specifically, GroupNode) // which will update _globalMatrix DSPNode::callbackUpdate(); // now, we can get the global position and orientation, and we can forward // it to SpatOSC #ifdef WITH_SPATOSC if (spinApp::Instance().hasAudioRenderer) { osg::Vec3 myPos = _globalMatrix.getTrans(); osg::Vec3 myRot = QuatToEuler(_globalMatrix.getRotate()); spatOSCListener->setPosition(myPos.x(), myPos.y(), myPos.z()); spatOSCListener->setOrientation(myRot.x(), myRot.y(), myRot.z()); } #endif }
void ConstraintsNode::applyConstrainedTranslation(osg::Vec3 v) { osg::Vec3 localPos = this->getTranslation(); osg::ref_ptr<ReferencedNode> hitNode; ReferencedNode *testNode; // with really big velocities (or small enclosures), and if the surface // doesn't damp the velocity, it's possible to get see an infinite recursion // occur. So, we keep a recursionCounter, and stop prevent this occurrence: if (++recursionCounter > 10) return; /* std::cout << std::endl << "checking for collisions" << std::endl; std::cout << "start = " << localPos.x()<<","<<localPos.y()<<","<<localPos.z() << std::endl; std::cout << "v = " << v.x()<<","<<v.y()<<","<<v.z() << std::endl; */ osg::ref_ptr<ReferencedNode> targetNode = dynamic_cast<ReferencedNode*>(_target->s_thing); if (targetNode.valid()) { // get current position (including offset from previous bounces) osg::Matrix thisMatrix = osg::computeLocalToWorld(this->currentNodePath); osg::Vec3 worldPos = thisMatrix.getTrans(); // set up intersector: osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(worldPos, worldPos + v); osgUtil::IntersectionVisitor iv(intersector.get()); // apply intersector: targetNode->accept(iv); if (intersector->containsIntersections()) { osgUtil::LineSegmentIntersector::Intersections intersections; osgUtil::LineSegmentIntersector::Intersections::iterator itr; intersections = intersector->getIntersections(); for (itr = intersections.begin(); itr != intersections.end(); ++itr) { //std::cout << "testing intersection with " << (*itr).nodePath[0]->getName() << std::endl; // first check if the hit is with our target (should be first in // the nodepath): testNode = dynamic_cast<ReferencedNode*>((*itr).nodePath[0]); if (testNode!=targetNode) continue; // The intersection has a nodepath that we have to walk down to // see which exact node has been hit. It's possible that there // are other SPIN nodes in the targetNode's subgraph that are // the real source of intersection: hitNode = 0; testNode = 0; for (unsigned int i=0; i<(*itr).nodePath.size(); i++) { testNode = dynamic_cast<ReferencedNode*>((*itr).nodePath[i]); if (testNode) hitNode = testNode; } if (hitNode.valid()) { //std::cout << id->s_name << " collision!!! with " << (*itr).drawable->getName() << "[" << (*itr).primitiveIndex << "] @ " << std::endl; //std::cout << "localHitPoint:\t" << localHitPoint.x()<<","<<localHitPoint.y()<<","<<localHitPoint.z() << std::endl; //std::cout << "localHitNormal:\t" << localHitNormal.x()<<","<<localHitNormal.y()<<","<<localHitNormal.z() << std::endl; // For BOUNCE mode, we need to check if we've intersected // with the same primitive again. This may occur since we // do recursive translations after repositioning the node at // the bounce point (and there may be numerical imprecision) // If so, we skip this intersection: if ((_mode==BOUNCE) && (lastDrawable.get()==(*itr).drawable.get()) && (lastPrimitiveIndex==(int)(*itr).primitiveIndex)) { //std::cout << "... skipping" << std::endl; continue; } else { lastDrawable=(*itr).drawable; lastPrimitiveIndex=(*itr).primitiveIndex; } osg::Vec3 localHitPoint = (*itr).getWorldIntersectPoint(); osg::Vec3 localHitNormal = (*itr).getWorldIntersectNormal(); localHitNormal.normalize(); // current direction vector: osg::Vec3 dirVec = v; dirVec.normalize(); // Find the rotation between the direction vector and the // surface normal at the hit point: osg::Quat rot; rot.makeRotate(dirVec, localHitNormal); //std::cout << "rot = " << rot.x()<<","<<rot.y()<<","<<rot.z()<<","<<rot.w() << " ... angle=" << acos(rot.w())*2 << ", indegrees=" << osg::RadiansToDegrees(acos(rot.w()))*2 << std::endl; // the surface normal may be in the opposite direction // from us. If so, we need to flip it: if (acos(rot.w()) * 2 > osg::PI_2) { localHitNormal *= -1; rot.makeRotate(dirVec, localHitNormal); //std::cout << "flipped = " << rot.x()<<","<<rot.y()<<","<<rot.z()<<","<<rot.w() << " ... angle=" << acos(rot.w())*2 << ", indegrees=" << osg::RadiansToDegrees(acos(rot.w()))*2 << std::endl; } osg::Vec3 rotEulers = QuatToEuler(rot); //std::cout << "newHitNormal:\t" << localHitNormal.x()<<","<<localHitNormal.y()<<","<<localHitNormal.z() << std::endl; if ((_mode==COLLIDE)||(_mode==COLLIDE_THRU)||(_mode==STICK)) { // Let the collisionPoint be just a bit before the real // hitpoint (to avoid numerical imprecision placing the // node behind the plane): osg::Vec3 collisionPoint = localHitPoint - (localHitNormal * 0.01); // place the node at the collision point setTranslation(collisionPoint.x(), collisionPoint.y(), collisionPoint.z()); BROADCAST(this, "ssfff", "collide", hitNode->id->s_name, osg::RadiansToDegrees(rotEulers.x()), osg::RadiansToDegrees(rotEulers.y()), osg::RadiansToDegrees(rotEulers.z())); if (_mode==COLLIDE) { // SLIDE along the hit plane with the left over energy: // ie, project the remaining vector onto the surface we // just intersected with. // // using: // cos(theta) = distToSurface / remainderVector length // double cosTheta = (dirVec * -localHitNormal) ; // dot product osg::Vec3 remainderVector = (localPos + v) - localHitPoint; double distToSurface = cosTheta * remainderVector.length(); osg::Vec3 slideVector = remainderVector + (localHitNormal * distToSurface); // pseudo-recursively apply remainder of bounce: applyConstrainedTranslation( slideVector ); } else if (_mode==COLLIDE_THRU) { // allow the node to pass thru (ie, just apply the // translation): //setTranslation(v.x(), v.y(), v.z()); osg::Vec3 newPos = localPos + v; setTranslation(newPos.x(), newPos.y(), newPos.z()); } return; } else if (_mode==BOUNCE) { // bounce returns a translation mirrored about the hit // normal to the surface // the new direction vector is a rotated version // of the original, about the localHitNormal: //osg::Vec3 newDir = (rot * 2.0) * -dirVec; osg::Vec3 newDir = (rot * (rot * -dirVec)); newDir.normalize(); //std::cout << "newDir = " << newDir.x()<<","<<newDir.y()<<","<<newDir.z() << std::endl; // amount of distance still to travel after bounce: double dist = v.length() - (localHitPoint-localPos).length(); //std::cout << "dist = " << dist << std::endl; // in node is translating (ie, changing position // independently from it's orientatino), then we need to // flip the velocity vector. if (_velocityMode == GroupNode::TRANSLATE) { osg::Vec3 newVel = newDir * _velocity.length(); setVelocity(newVel.x(), newVel.y(), newVel.z()); } // if the node is moving along it's orientation vector, // we need to update the orientation of so that it // points in 'bounced' direction else if (_velocityMode == GroupNode::MOVE) { osg::Quat newQuat; newQuat.makeRotate(osg::Vec3(0,1,0), newDir); osg::Vec3 newRot = Vec3inDegrees(QuatToEuler(newQuat)); //std::cout << "newrot = " << newRot.x()<<","<<newRot.y()<<","<<newRot.z() << std::endl; setOrientation(newRot.x(), newRot.y(), newRot.z()); } // the new position will be just a hair before hitpoint // (because numerical imprecision may place the hitpoint // slightly beyond the surface, and when we bounce the // node, we don't want to intersect with the same // surface again) double HAIR = 0.0000001; setTranslation(localHitPoint.x()-dirVec.x()*HAIR, localHitPoint.y()-dirVec.y()*HAIR, localHitPoint.z()-dirVec.z()*HAIR); //setTranslation(localHitPoint.x(), localHitPoint.y(), localHitPoint.z()); //std::cout << "rotEulers = " << osg::RadiansToDegrees(rotEulers.x())<<","<<osg::RadiansToDegrees(rotEulers.y())<<","<<osg::RadiansToDegrees(rotEulers.z()) << std::endl; BROADCAST(this, "ssfff", "bounce", hitNode->id->s_name, osg::RadiansToDegrees(rotEulers.x()), osg::RadiansToDegrees(rotEulers.y()), osg::RadiansToDegrees(rotEulers.z())); // pseudo-recursively apply remainder of bounce: applyConstrainedTranslation(newDir*dist); return; } } } } //else std::cout << "no intersections" << std::endl; } // no intersections, so just do regular translation: osg::Vec3 newPos = localPos + v; setTranslation(newPos.x(), newPos.y(), newPos.z()); }
// MilkShape 3D void ExportMS3D_M2(Attachment *att, Model *m, const char *fn, bool init) { wxFFileOutputStream f(wxString(fn, wxConvUTF8), wxT("w+b")); if (!f.IsOk()) { wxLogMessage(wxT("Error: Unable to open file '%s'. Could not export model."), fn); return; } LogExportData(wxT("MS3D"),m->modelname,wxString(fn, wxConvUTF8)); unsigned short numVerts = 0; unsigned short numFaces = 0; unsigned short numGroups = 0; ModelData *verts = NULL; GroupData *groups = NULL; //we need the initial position anyway InitCommon(att, true, verts, groups, numVerts, numGroups, numFaces); //wxLogMessage(wxT("Num Verts: %i, Num Faces: %i, Num Groups: %i"), numVerts, numFaces, numGroups); //wxLogMessage(wxT("Vert[0] BoneID: %i, Group[0].m.name = %s"),verts[0].boneid, groups[0].m->name); wxLogMessage(wxT("Init Common Complete.")); // Write the header ms3d_header_t header; strncpy(header.id, "MS3D000000", sizeof(header.id)); header.version = 4; // Header f.Write(reinterpret_cast<char *>(&header), sizeof(ms3d_header_t)); wxLogMessage(wxT("Header Data Written.")); // Vertex Count f.Write(reinterpret_cast<char *>(&numVerts), sizeof(numVerts)); //wxLogMessage(wxT("NumVerts: %i"),numVerts); // Write Vertex data? for (size_t i=0; i<numVerts; i++) { ms3d_vertex_t vert; vert.boneId = verts[i].boneid; vert.flags = 0; //SELECTED; vert.referenceCount = 0; // what the? vert.vertex[0] = verts[i].vertex.x; vert.vertex[1] = verts[i].vertex.y; vert.vertex[2] = verts[i].vertex.z; f.Write(reinterpret_cast<char *>(&vert), sizeof(ms3d_vertex_t)); } wxLogMessage(wxT("Vertex Data Written.")); // --------------------------- // Triangle Count f.Write(reinterpret_cast<char *>(&numFaces), sizeof(numFaces)); //wxLogMessage(wxT("NumFaces: %i"),numFaces); // Write Triangle Data? for (size_t i=0; i<(unsigned int)numVerts; i+=3) { ms3d_triangle_t tri; tri.flags = 0; //SELECTED; tri.groupIndex = (unsigned char)verts[i].groupIndex; tri.smoothingGroup = 1; // 1 - 32 for (ssize_t j=0; j<3; j++) { tri.vertexIndices[j] = (word)i+j; tri.s[j] = verts[i+j].tu; tri.t[j] = verts[i+j].tv; tri.vertexNormals[j][0] = verts[i+j].normal.x; tri.vertexNormals[j][1] = verts[i+j].normal.y; tri.vertexNormals[j][2] = verts[i+j].normal.z; } f.Write(reinterpret_cast<char *>(&tri), sizeof(ms3d_triangle_t)); } wxLogMessage(wxT("Triangle Data Written.")); // --------------------------- // Number of groups f.Write(reinterpret_cast<char *>(&numGroups), sizeof(numGroups)); //wxLogMessage(wxT("NumGroups: %i"),numGroups); unsigned short indiceCount = 0; for (unsigned short i=0; i<(unsigned int)numGroups; i++) { wxString groupName(wxString::Format(wxT("Geoset_%i"), i)); const char flags = 0; // SELECTED f.Write(&flags, sizeof(flags)); char name[32]; strncpy(name, groupName.mb_str(), sizeof(name)); f.Write(name, sizeof(name)); unsigned short faceCount = groups[i].p.indexCount / 3; f.Write(reinterpret_cast<char *>(&faceCount), sizeof(faceCount)); for (ssize_t k=0; k<faceCount; k++) { //triIndices[k] = indiceCount; f.Write(reinterpret_cast<char *>(&indiceCount), sizeof(indiceCount)); indiceCount++; } unsigned char gIndex = (char)i; f.Write(reinterpret_cast<char *>(&gIndex), sizeof(gIndex)); } wxLogMessage(wxT("Group Data Written.")); // Number of materials (pretty much identical to groups, each group has its own material) f.Write(reinterpret_cast<char *>(&numGroups), sizeof(numGroups)); for (unsigned short i=0; i<(unsigned int)numGroups; i++) { wxString matName(wxString::Format(wxT("Material_%i"), i)); ModelRenderPass p = groups[i].p; if (p.init(groups[i].m)) { ms3d_material_t mat; memset(mat.alphamap, '\0', sizeof(mat.alphamap)); strncpy(mat.name, matName.mb_str(), sizeof(mat.name)); mat.ambient[0] = 0.7f; mat.ambient[1] = 0.7f; mat.ambient[2] = 0.7f; mat.ambient[3] = 1.0f; mat.diffuse[0] = p.ocol.x; mat.diffuse[1] = p.ocol.y; mat.diffuse[2] = p.ocol.z; mat.diffuse[3] = p.ocol.w; mat.specular[0] = 0.0f; mat.specular[1] = 0.0f; mat.specular[2] = 0.0f; mat.specular[3] = 1.0f; mat.emissive[0] = p.ecol.x; mat.emissive[1] = p.ecol.y; mat.emissive[2] = p.ecol.z; mat.emissive[3] = p.ecol.w; mat.transparency = p.ocol.w; if (p.useEnvMap) { mat.shininess = 30.0f; mat.mode = 1; } else { mat.shininess = 0.0f; mat.mode = 0; } /* unsigned int bindtex = 0; if (groups[i].m->specialTextures[p.tex]==-1) bindtex = groups[i].m->textures[p.tex]; else bindtex = groups[i].m->replaceTextures[groups[i].m->specialTextures[p.tex]]; */ wxString texName = GetM2TextureName(m,p,i); texName << wxT(".tga"); strncpy(mat.texture, texName.mb_str(), sizeof(mat.texture)); f.Write(reinterpret_cast<char *>(&mat), sizeof(ms3d_material_t)); wxString texFilename(fn, wxConvUTF8); texFilename = texFilename.BeforeLast(SLASH); texFilename += SLASH; texFilename += texName; wxLogMessage(wxT("Exporting Image: %s"),texFilename.c_str()); SaveTexture(texFilename); } } wxLogMessage(wxT("Material Data Written.")); if (init) { float fps = 1.0f; float fCurTime = 0.0f; int totalFrames = 0; f.Write(reinterpret_cast<char *>(&fps), sizeof(fps)); f.Write(reinterpret_cast<char *>(&fCurTime), sizeof(fCurTime)); f.Write(reinterpret_cast<char *>(&totalFrames), sizeof(totalFrames)); // number of joints unsigned short numJoints = 0; f.Write(reinterpret_cast<char *>(&numJoints), sizeof(numJoints)); } else { float fps = 25.0f; float fCurTime = 0.0f; int totalFrames = ceil((m->anims[m->anim].timeEnd - m->anims[m->anim].timeStart) / 1000.0f * fps); f.Write(reinterpret_cast<char *>(&fps), sizeof(fps)); f.Write(reinterpret_cast<char *>(&fCurTime), sizeof(fCurTime)); f.Write(reinterpret_cast<char *>(&totalFrames), sizeof(totalFrames)); // number of joints unsigned short numJoints = (unsigned short)m->header.nBones; f.Write(reinterpret_cast<char *>(&numJoints), sizeof(numJoints)); for (size_t i=0; i<numJoints; i++) { ms3d_joint_t joint; int parent = m->bones[i].parent; joint.flags = 0; // SELECTED memset(joint.name, '\0', sizeof(joint.name)); snprintf(joint.name, sizeof(joint.name), "Bone_%i", i); memset(joint.parentName, '\0', sizeof(joint.parentName)); if (parent != -1) snprintf(joint.parentName, sizeof(joint.parentName), "Bone_%i", parent); joint.rotation[0] = 0; joint.rotation[1] = 0; joint.rotation[2] = 0; Vec3D p = FixPivot(m, (int)i, m->bones[i].pivot); joint.position[0] = p.x; joint.position[1] = p.y; joint.position[2] = p.z; joint.numKeyFramesRot = (unsigned short)m->bones[i].rot.data[m->anim].size(); joint.numKeyFramesTrans = (unsigned short)m->bones[i].trans.data[m->anim].size(); f.Write(reinterpret_cast<char *>(&joint), sizeof(ms3d_joint_t)); if (joint.numKeyFramesRot > 0) { ms3d_keyframe_rot_t *keyFramesRot = new ms3d_keyframe_rot_t[joint.numKeyFramesRot]; for (size_t j=0; j<joint.numKeyFramesRot; j++) { keyFramesRot[j].time = m->bones[i].rot.times[m->anim][j] / 1000.0f; Vec3D euler = QuatToEuler(m->bones[i].rot.data[m->anim][j]); keyFramesRot[j].rotation[0] = euler.x; keyFramesRot[j].rotation[1] = euler.y; keyFramesRot[j].rotation[2] = euler.z; } f.Write(reinterpret_cast<char *>(keyFramesRot), sizeof(ms3d_keyframe_rot_t) * joint.numKeyFramesRot); wxDELETEA(keyFramesRot); } if (joint.numKeyFramesTrans > 0) { ms3d_keyframe_pos_t *keyFramesTrans = new ms3d_keyframe_pos_t[joint.numKeyFramesTrans]; for (size_t j=0; j<joint.numKeyFramesTrans; j++) { keyFramesTrans[j].time = m->bones[i].trans.times[m->anim][j] / 1000.0f; keyFramesTrans[j].position[0] = m->bones[i].trans.data[m->anim][j].x; keyFramesTrans[j].position[1] = m->bones[i].trans.data[m->anim][j].y; keyFramesTrans[j].position[2] = m->bones[i].trans.data[m->anim][j].z; } f.Write(reinterpret_cast<char *>(keyFramesTrans), sizeof(ms3d_keyframe_pos_t) * joint.numKeyFramesTrans); wxDELETEA(keyFramesTrans); } } } f.Close(); wxLogMessage(wxT("Finished Milkshape Export.")); if (verts){ //wxLogMessage("verts found. Deleting..."); wxDELETEA(verts); } if (groups){ //wxLogMessage("groups found. Deleting..."); wxDELETEA(groups); } //wxLogMessage(wxT("Finished Milkshape Cleanup.\n")); }
void BulletPhysicsEngine::update() { for (U32 i = 0; i < 1024; ++i) { BulletPhysicsObject* obj = &mPhysicsObjects[i]; if ( obj->deleted ) continue; if ( obj->shouldBeDeleted ) { if ( obj->initialized ) { mDynamicsWorld->removeRigidBody(obj->_rigidBody); obj->destroy(); } obj->deleted = true; continue; } } for (U32 i = 0; i < 1024; ++i) { BulletPhysicsObject* obj = &mPhysicsObjects[i]; if ( obj->deleted ) continue; if ( !obj->initialized ) { obj->initialize(); mDynamicsWorld->addRigidBody(obj->_rigidBody); } else { // Pull updates from Physics thread. btMotionState* objMotion = obj->_rigidBody->getMotionState(); if ( objMotion ) { btTransform trans; objMotion->getWorldTransform(trans); F32 mat[16]; trans.getOpenGLMatrix(mat); obj->mPosition.set(mat[12], mat[13], mat[14]); btQuaternion rot = trans.getRotation(); obj->mRotation.set(QuatToEuler(rot.x(), rot.y(), rot.z(), rot.w())); } // Apply actions from Game thread. while ( obj->mPhysicsActions.size() > 0 ) { Physics::PhysicsAction action = obj->mPhysicsActions.front(); switch(action.actionType) { case Physics::PhysicsAction::setPosition: obj->mPosition = action.vector3Value; obj->_rigidBody->setWorldTransform(btTransform(btQuaternion(0, 0, 0, 1),btVector3(action.vector3Value.x, action.vector3Value.y, action.vector3Value.z))); obj->_rigidBody->activate(); break; case Physics::PhysicsAction::setLinearVelocity: obj->_rigidBody->setLinearVelocity(btVector3(action.vector3Value.x * 25.0f, action.vector3Value.y * 25.0f, action.vector3Value.z * 25.0f)); obj->_rigidBody->activate(); break; } obj->mPhysicsActions.pop_front(); } } } }
void RandKeysUtil::Apply() { BOOL timeMode = iu->GetMajorMode()==TVMODE_EDITTIME; BOOL fcurveMode = iu->GetMajorMode()==TVMODE_EDITFCURVE; Interval iv = iu->GetTimeSelection(); if (!doTime && !doVal) return; theHold.Begin(); // Turn animation on SuspendAnimate(); AnimateOn(); for (int i=0; i<iu->GetNumTracks(); i++) { if ((timeMode||fcurveMode) && !iu->IsSelected(i)) continue; // Get Interfaces Animatable *anim = iu->GetAnim(i); Animatable *client = iu->GetClient(i); int subNum = iu->GetSubNum(i); Control *cont = GetControlInterface(anim); IKeyControl *ikc = GetKeyControlInterface(anim); IKey *key = GetKeyPointer(anim->SuperClassID(),anim->ClassID()); if (!ikc || !cont || !key) continue; if (fcurveMode && !anim->IsCurveSelected()) continue; // Get the param dim float min = negVal, max = posVal; ParamDimension *dim = client->GetParamDimension(subNum); if (dim) { min = dim->UnConvert(min); max = dim->UnConvert(max); } for (int j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize time if (doTime) { key->time = (int)CompRand( float(key->time-negTime), float(key->time+posTime)); ikc->SetKey(j,key); } } if (doTime) ikc->SortKeys(); for (j=0; j<ikc->GetNumKeys(); j++) { // Get the key data ikc->GetKey(j,key); // Check if it's selected if (timeMode && !iv.InInterval(key->time)) continue; if (!timeMode && !(key->flags&IKEY_SELECTED)) continue; // Randomize value if (doVal) { Point3 pt, ang; Point4 p4; float f; Quat q; ScaleValue s; BOOL doX, doY, doZ, doW; doX = doY = doZ = doW = TRUE; if (!fcurveMode) { if (!(key->flags&IKEY_XSEL)) doX = FALSE; if (!(key->flags&IKEY_YSEL)) doY = FALSE; if (!(key->flags&IKEY_ZSEL)) doZ = FALSE; if (!(key->flags&IKEY_WSEL)) doW = FALSE; } switch (anim->SuperClassID()) { case CTRL_FLOAT_CLASS_ID: cont->GetValue(key->time,&f,FOREVER); f = CompRand(f-min,f+max); cont->SetValue(key->time,&f); break; case CTRL_POSITION_CLASS_ID: case CTRL_POINT3_CLASS_ID: cont->GetValue(key->time,&pt,FOREVER); if (doX) pt.x = CompRand(pt.x-min,pt.x+max); if (doY) pt.y = CompRand(pt.y-min,pt.y+max); if (doZ) pt.z = CompRand(pt.z-min,pt.z+max); cont->SetValue(key->time,&pt); break; case CTRL_POINT4_CLASS_ID: cont->GetValue(key->time,&p4,FOREVER); if (doX) p4.x = CompRand(p4.x-min,p4.x+max); if (doY) p4.y = CompRand(p4.y-min,p4.y+max); if (doZ) p4.z = CompRand(p4.z-min,p4.z+max); if (doW) p4.w = CompRand(p4.w-min,p4.w+max); cont->SetValue(key->time,&p4); break; case CTRL_ROTATION_CLASS_ID: cont->GetValue(key->time,&q,FOREVER); QuatToEuler(q, ang); ang.x = CompRand(ang.x-min,ang.x+max); ang.y = CompRand(ang.y-min,ang.y+max); ang.z = CompRand(ang.z-min,ang.z+max); EulerToQuat(ang,q); cont->SetValue(key->time,&q); break; case CTRL_SCALE_CLASS_ID: cont->GetValue(key->time,&s,FOREVER); if (doX) s.s.x = CompRand(s.s.x-min,s.s.x+max); if (doY) s.s.y = CompRand(s.s.y-min,s.s.y+max); if (doZ) s.s.z = CompRand(s.s.z-min,s.s.z+max); cont->SetValue(key->time,&s); break; } } } } ResumeAnimate(); theHold.Accept(GetString(IDS_RB_RANDOMIZEKEYS)); ip->RedrawViews(ip->GetTime()); }