int BonesDefMod::GetMirrorBone(Point3 center, int axis) { //get current bone INode *node = BoneData[ModeBoneIndex].Node; if (node) { //get tm Matrix3 iMirrorTM(1); iMirrorTM.SetRow(3,center); iMirrorTM = Inverse(iMirrorTM); TimeValue t = GetCOREInterface()->GetTime(); Matrix3 tm = node->GetNodeTM(t); Point3 mirrorPoint = Point3(0.0f,0.0f,0.0f) * tm; mirrorPoint = mirrorPoint * iMirrorTM; //mirror its location mirrorPoint[axis] *= -1.0f; //loop through all the bones int closestBone = -1; float closestDist= 0.0f; Box3 bounds; bounds.Init(); for (int i = 0; i < BoneData.Count(); i++) { node = BoneData[i].Node; //get there tm if ((node) && (i!=ModeBoneIndex)) { //find closest bone tm = node->GetNodeTM(t); Point3 bonePoint = Point3(0.0f,0.0f,0.0f) * tm; bonePoint = bonePoint * iMirrorTM; bounds += bonePoint; float dist = Length(bonePoint-mirrorPoint); if ( (closestBone == -1) || (dist < closestDist) ) { closestDist = dist; closestBone = i; } } } float threshold = Length(bounds.pmax-bounds.pmin)/100.0f; if (closestDist < threshold) return closestBone; } return -1; }
BOOL plDistributor::ISpaceClear(int iRepNode, const Matrix3& l2w, Box3& clearBox, plMeshCacheTab& cache) const { if( !fDistTree ) return true; // If we have high isolation, // clearBox = Box3(Point3(-fSpacing*0.5f, -fSpacing*0.5f, 0), Point3(fSpacing*0.5f, fSpacing*0.5f, fSpacing)); // Else if we have medium isolation // clearBox = cache[iRepNode]->getBoundingBox(); // The mesh's bounds // Else if we have low isolation or None isolation // clearBox = Box3(Point3(-kSmallSpace, -kSmallSpace, 0), Point3(kSmallSpace, kSmallSpace, kSmallSpace)); // kSmallSpace ~= 0.5f or one or something // We want to set up the box (for high, low and none) in Post OTM space. So instead of multiplying // by l2w, we want to multiply box = box * invOTM * l2w (because l2w already has OTM folded in). When using // the mesh bounds (Medium), l2w is the right transform. // objectTM = otm * nodeTM // invOTM * objectTM = nodeTM // invOTM = nodeTM * invObjectTM const float kSmallSpace = 0.5f; switch( fIsolation ) { case kIsoHigh: { INode* repNode = fRepNodes[iRepNode]; Matrix3 objectTM = repNode->GetObjectTM(TimeValue(0)); Matrix3 nodeTM = repNode->GetNodeTM(TimeValue(0)); Matrix3 invOTM = nodeTM * Inverse(objectTM); clearBox = Box3(Point3(-fSpacing*0.5f, -fSpacing*0.5f, 0.f), Point3(fSpacing*0.5f, fSpacing*0.5f, fSpacing)); clearBox = clearBox * invOTM; } break; case kIsoMedium: clearBox = cache[iRepNode].fMesh->getBoundingBox(); // The mesh's bounds break; case kIsoLow: case kIsoNone: default: { INode* repNode = fRepNodes[iRepNode]; Matrix3 objectTM = repNode->GetObjectTM(TimeValue(0)); Matrix3 nodeTM = repNode->GetNodeTM(TimeValue(0)); Matrix3 invOTM = nodeTM * Inverse(objectTM); clearBox = Box3(Point3(-kSmallSpace, -kSmallSpace, 0.f), Point3(kSmallSpace, kSmallSpace, kSmallSpace)); clearBox = clearBox * invOTM; } break; } clearBox = clearBox * l2w; return fDistTree->BoxClear(clearBox, fFade); }
void bhkProxyObject::BuildColCapsule() { proxyMesh.FreeAll(); MeshDelta md(proxyMesh); for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) { INode *tnode = NULL; pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i); if (tnode) { ObjectState os = tnode->EvalWorldState(0); Matrix3 wm = tnode->GetNodeTM(0); TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); if (tri) { Mesh& mesh = tri->GetMesh(); MeshDelta tmd (mesh); md.AttachMesh(proxyMesh, mesh, wm, 0); md.Apply(proxyMesh); } } } Point3 pt1 = Point3::Origin; Point3 pt2 = Point3::Origin; float r1 = 0.0; float r2 = 0.0; if (proxyMesh.getNumVerts() > 3) // Doesn't guarantee that the mesh is not a plane. { CalcCapsule(proxyMesh, pt1, pt2, r1, r2); BuildCapsule(proxyMesh, pt1, pt2, r1, r2); } proxyPos = Point3::Origin; forceRedraw = true; }
void MembraneVertexShader::GetCameraPosition(Point3 &Pos) { Interface *ip = GetCOREInterface(); INode *pObj; Matrix3 objTM; Pos.x = 0.0f; Pos.y = 0.0f; Pos.z = -200.0f; INode *pRoot =ip->GetRootNode(); int numNodes = pRoot->NumberOfChildren(); for( int ctr = 0; ctr < numNodes; ctr++) { pObj = pRoot->GetChildNode(ctr); // The ObjectState is a 'thing' that flows down the pipeline containing // all information about the object. By calling EvalWorldState() we tell // max to eveluate the object at end of the pipeline. ObjectState os = pObj->EvalWorldState(ip->GetTime()); // The obj member of ObjectState is the actual object we will export. if (os.obj) { // We look at the super class ID to determine the type of the object. switch(os.obj->SuperClassID()) { case CAMERA_CLASS_ID: objTM = pObj->GetNodeTM(ip->GetTime()); Pos = objTM.GetTrans(); break; } } } }
void bhkProxyObject::BuildColConvex() { proxyMesh.FreeAll(); MeshDelta md(proxyMesh); for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) { INode *tnode = NULL; pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i); if (tnode) { ObjectState os = tnode->EvalWorldState(0); Matrix3 wm = tnode->GetNodeTM(0); TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); if (tri) { Mesh& mesh = tri->GetMesh(); MeshDelta tmd (mesh); md.AttachMesh(proxyMesh, mesh, wm, 0); md.Apply(proxyMesh); } } } compute_convex_hull(proxyMesh, proxyMesh); BuildOptimize(proxyMesh); proxyPos = Point3::Origin; forceRedraw = true; }
void bhkProxyObject::BuildColBox() { Box3 box; box.Init(); for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) { INode *tnode = NULL; pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i); if (tnode) { ObjectState os = tnode->EvalWorldState(0); Matrix3 wm = tnode->GetNodeTM(0); TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); if (tri) { Box3 box2; box2.Init(); Mesh& mesh = tri->GetMesh(); CalcAxisAlignedBox(mesh, box2, &wm); box += box2; } } } BuildBox(proxyMesh, box.Max().y-box.Min().y, box.Max().x-box.Min().x, box.Max().z-box.Min().z); MNMesh mn(proxyMesh); Matrix3 tm(true); tm.SetTranslate(box.Center()); mn.Transform(tm); mn.OutToTri(proxyMesh); //proxyPos = box.Center(); proxyPos = Point3::Origin; forceRedraw = true; }
//================================================================= // Methods for CollectNodesTEP // int CollectNodesTEP::callback(INode *node) { INode *pnode = node; // Hungarian ASSERT_MBOX(!(pnode)->IsRootNode(), "Encountered a root node!"); if (::FNodeMarkedToSkip(pnode)) return TREE_CONTINUE; // Get pre-stored "index" int iNode = ::GetIndexOfINode(pnode); ASSERT_MBOX(iNode >= 0 && iNode <= m_phec->m_imaxnodeMac-1, "Bogus iNode"); // Get name, store name in array TSTR strNodeName(pnode->GetName()); strcpy(m_phec->m_rgmaxnode[iNode].szNodeName, (char*)strNodeName); // Get Node's time-zero Transformation Matrices m_phec->m_rgmaxnode[iNode].mat3NodeTM = pnode->GetNodeTM(0/*TimeValue*/); m_phec->m_rgmaxnode[iNode].mat3ObjectTM = pnode->GetObjectTM(0/*TimeValue*/); // I'll calculate this later m_phec->m_rgmaxnode[iNode].imaxnodeParent = SmdExportClass::UNDESIRABLE_NODE_MARKER; return TREE_CONTINUE; }
Matrix3 plDistributor::IOTM(int iRepNode) const { // objectTM = otm * nodeTM // objectTM * Inverse(nodeTM) = otm INode* repNode = fRepNodes[iRepNode]; Matrix3 objectTM = repNode->GetObjectTM(TimeValue(0)); Matrix3 nodeTM = repNode->GetNodeTM(TimeValue(0)); Matrix3 OTM = objectTM * Inverse(nodeTM); return OTM; }
Matrix3 plDistributor::IInvOTM(int iRepNode) const { // objectTM = otm * nodeTM // invOTM * objectTM = nodeTM // invOTM = nodeTM * invObjectTM INode* repNode = fRepNodes[iRepNode]; Matrix3 objectTM = repNode->GetObjectTM(TimeValue(0)); Matrix3 nodeTM = repNode->GetNodeTM(TimeValue(0)); Matrix3 invOTM = nodeTM * Inverse(objectTM); return invOTM; }
//================================================================= // 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; }
BOOL PickControlNode::Pick(IObjParam *ip,ViewExp *vpt) { if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } INode *node = vpt->GetClosestHit(); if (node) { // RB 3/1/99: This should use the node tm not the object TM. See ModifyObject() imp. Matrix3 ourTM,ntm = node->GetNodeTM(GetCOREInterface()->GetTime()); //node->GetObjectTM(ip->GetTime()); ModContextList mcList; INodeTab nodes; ip->GetModContexts(mcList,nodes); if (nodes.Count()) { ourTM = nodes[0]->GetObjectTM(GetCOREInterface()->GetTime()); ourTM = Inverse(ourTM); Box3 bounds; bounds.Init(); ObjectState os = node->EvalWorldState(GetCOREInterface()->GetTime()); ViewExp& vp = GetCOREInterface()->GetActiveViewExp(); if ( ! vp.IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } os.obj->GetWorldBoundBox(GetCOREInterface()->GetTime(), node, vp.ToPointer(), bounds ); Point3 min = bounds.pmin * ourTM; Point3 max = bounds.pmax * ourTM; theHold.Begin(); mod->pblock2->SetValue(particlemesher_customboundsa,0,min); mod->pblock2->SetValue(particlemesher_customboundsb,0,max); theHold.Accept(GetString(IDS_BOUNDS)); mod->NotifyDependents(FOREVER,0,REFMSG_CHANGE); mod->UpdateUI(); } nodes.DisposeTemporary(); } return TRUE; }
Matrix3 Exporter::getObjectTransform(INode *node, TimeValue t, bool local) { Matrix3 tm = node->GetObjTMAfterWSM(t); if (local) { INode *parent = node->GetParentNode(); if (parent != NULL) { Matrix3 pm = parent->GetNodeTM(t); pm.Invert(); tm *= pm; } } return tm; }
// REAPPLYANIMATION // Now that we've reparented a node within the hierarchy, re-apply all its animation. void ReapplyAnimation(INode *node, plSampleVec *samples) { Control *controller = node->GetTMController(); Control *rotControl = NewDefaultRotationController(); // we set the default rotation controller type above in RemoveBiped() Control *posControl = NewDefaultPositionController(); // '' '' Control *scaleControl = NewDefaultScaleController(); // '' '' controller->SetRotationController(rotControl); controller->SetPositionController(posControl); controller->SetScaleController(scaleControl); for(int i = 0; i < samples->size(); i++) { nodeTMInfo *info = (*samples)[i]; Matrix3 m = info->fMat3; TimeValue t = info->fTime; #if 1 node->SetNodeTM(t, m); #else AffineParts parts; INode *parent = node->GetParentNode(); Matrix3 parentTM = parent->GetNodeTM(t); Matrix3 invParentTM = Inverse(parentTM); m *= invParentTM; decomp_affine(m, &parts); Quat q(parts.q.x, parts.q.y, parts.q.z, parts.q.w); Point3 p(parts.t.x, parts.t.y, parts.t.z); rotControl->SetValue(t, q); posControl->SetValue(t, p); #endif } IKeyControl *posKeyCont = GetKeyControlInterface(posControl); IKeyControl *scaleKeyCont = GetKeyControlInterface(scaleControl); ReduceKeys<ILinPoint3Key>(node, posKeyCont); EliminateScaleKeys(node, scaleKeyCont); // grrrr ReduceKeys<ILinScaleKey>(node, scaleKeyCont); }
// Clone the replicant and set its transform appropriately. Should set the plMaxNode property // that the node's spans are collapseable? No, we'll make a separate component for that. void plDistributor::IReplicate(Matrix3& l2w, int iRepNode, plDistribInstTab& reps, plMeshCache& mCache) const { INode* repNode = fRepNodes[iRepNode]; plDistribInstance inst; inst.fNode = repNode; inst.fNodeTM = l2w; inst.fObjectTM = repNode->GetObjectTM(TimeValue(0)) * Inverse(repNode->GetNodeTM(TimeValue(0))) * l2w; inst.fMesh = mCache.fMesh; inst.fFlex = mCache.fFlex; inst.fFade = fFade; inst.fBone = fBone; inst.fRigid = fRigid; reps.Append(1, &inst); }
void bhkProxyObject::BuildColOBB() { proxyMesh.FreeAll(); MeshDelta md(proxyMesh); for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) { INode *tnode = NULL; pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i); if (tnode) { ObjectState os = tnode->EvalWorldState(0); Matrix3 wm = tnode->GetNodeTM(0); TriObject *tri = (TriObject *)os.obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); if (tri) { Mesh& mesh = tri->GetMesh(); MeshDelta tmd (mesh); md.AttachMesh(proxyMesh, mesh, wm, 0); md.Apply(proxyMesh); } } } Matrix3 rtm(true); Point3 center = Point3::Origin;; float udim = 0.0f, vdim = 0.0f, ndim = 0.0f; if (proxyMesh.getNumVerts() > 3) // Doesn't guarantee that the mesh is not a plane. { // First build a convex mesh to put the box around; // the method acts oddly if extra vertices are present. BuildColConvex(); CalcOrientedBox(proxyMesh, udim, vdim, ndim, center, rtm); BuildBox(proxyMesh, vdim, udim, ndim); } MNMesh mn(proxyMesh); mn.Transform(rtm); mn.OutToTri(proxyMesh); proxyPos = Point3::Origin; forceRedraw = true; }
Matrix3 Jiggle::GetCurrentTM(TimeValue t) { INode* baseNode = NULL; baseNode = selfNode; Matrix3 selfTM; Point3 pos = Point3(0.0f,0.0f,0.0f); Interval for_ever = FOREVER; posCtrl->GetValue(t, pos, for_ever, CTRL_ABSOLUTE); if (baseNode != NULL ) { selfTM = baseNode->GetNodeTM(t); selfTM.SetTrans(selfTM * pos); } else { selfTM.IdentityMatrix(); selfTM.SetTrans(pos); } return selfTM; }
//--------------------------------------------------------------------------- // // This implementation of NfGetLocalTM removes all scales from the returned // Matrix3, but also stores them in the parameter pScaleOut (if specified) // so that they can be pushed down to the geometry level. // Matrix3 U2MaxSceneExport::GetLocalTM(INode* pMaxNode, TimeValue t) { Matrix3 localScaleTM; INode* pParent = pMaxNode->GetParentNode(); if(pParent) { Matrix3 parentTM = pParent->GetNodeTM(t); Matrix3 thisTM = pMaxNode->GetNodeTM(t); localScaleTM = thisTM * Inverse(parentTM); } else localScaleTM.IdentityMatrix(); Matrix3 localNoScaleTM; localNoScaleTM = UniformMatrix(localScaleTM); return localNoScaleTM; }
//From SpringSysClient //************************************************* Tab<Matrix3> Jiggle::GetForceMatrices(TimeValue t) { Tab<Matrix3> tms; INode* node; Matrix3 parentTM; parentTM = GetCurrentTM(t); tms.Append(1, &parentTM); for (int x=1;x<dyn_pb->Count(jig_control_node); x++) { Interval for_ever = FOREVER; dyn_pb->GetValue(jig_control_node, 0, node, for_ever, x); if (node) { Matrix3 mat = node->GetNodeTM(t); tms.Append(1, &mat); } } return tms; }
Matrix3 CActionExporter::get_bone_tm(CSkeletonExporter* pSkeleton,int boneIndex,unsigned int iMaxTime) { sMaxBoneNode_t bone = pSkeleton->m_MaxBones[boneIndex]; Matrix3 boneInitMTInv; if(G_MaxEnv().m_bUseBeforeSkeletonPose) boneInitMTInv = bone.m_SkinInitMT; else boneInitMTInv = bone.m_InitNodeTM0; boneInitMTInv.Invert(); INode* pNode = bone.m_pNode; Matrix3 BoneTM = boneInitMTInv * pNode->GetNodeTM(iMaxTime); //>GetNodeTM(iMaxTime); Point3 Trans = BoneTM.GetTrans(); BoneTM.NoTrans(); //对骨骼进行缩放 Trans.x *= pSkeleton->m_fScale; Trans.y *= pSkeleton->m_fScale; Trans.z *= pSkeleton->m_fScale; BoneTM.SetTrans(Trans); return BoneTM; }
int CMaxAnimationImport::DoImport( const TCHAR* name, ImpInterface* ii, Interface* i, BOOL suppressPrompts) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HWND window = i->GetMAXHWnd(); CFileDialog fileDialog(TRUE, "xsf", 0, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, CWnd::FromHandle(window)); if (fileDialog.DoModal() != IDOK) { return IMPEXP_CANCEL; } CString skeleton = fileDialog.GetPathName(); CalCoreSkeletonPtr skel = CalLoader::loadCoreSkeleton(std::string(skeleton)); if (!skel) { MessageBox( window, "Loading skeleton file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } CalCoreAnimationPtr anim = CalLoader::loadCoreAnimation(name); if (!anim) { MessageBox( window, "Loading animation file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } // Get the pose information in the animation const std::vector<CalTransform>& poses = anim->getPoses(); unsigned int num_poses = poses.size() / anim->getTrackCount(); // Calculate the time_per_frame incorrectly since the duration for animations // is stored incorrectly. float time_per_frame = anim->getDuration() / num_poses; // Import each track for (unsigned track_id = 0; track_id < anim->getTrackCount(); ++track_id) { // Get the core bone mapped to the animation int bone_id = anim->getBoneAssignment(track_id); CalCoreBone* bone = skel->getCoreBone(bone_id); if (!bone) continue; // Get the max node for the bone INode* node = i->GetINodeByName(bone->getName().c_str()); if (!node) continue; SuspendAnimate(); AnimateOn(); // Add each pose keyframe in the track float keyframe_time = 0.0f; for (unsigned keyframe_index = 0; keyframe_index < num_poses; ++keyframe_index) { // Get the keyframe data const CalTransform& pose_coord_sys = poses[(keyframe_index * anim->getTrackCount()) + track_id]; const CalVector &kf_v = pose_coord_sys.getTranslation(); const CalQuaternion &kf_q = pose_coord_sys.getRotation(); TimeValue time = SecToTicks(keyframe_time); // Convert to Max math Matrix3 tm; tm.IdentityMatrix(); Quat(kf_q.x, kf_q.y, kf_q.z, kf_q.w).MakeMatrix(tm); tm.SetTrans(Point3(kf_v.x, kf_v.y, kf_v.z)); // Convert the transform to world space INode* parent = node->GetParentNode(); if (parent) { tm *= parent->GetNodeTM(time); } // Set the new transform on the node node->SetNodeTM(time, tm); keyframe_time += time_per_frame; } ResumeAnimate(); /* typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); int mapsize = sizeof(keys); int size = keys.size(); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { Point3 p; CalCoreKeyframe* kf = mi->second; p.x = kf->getTranslation().x; p.y = kf->getTranslation().y; p.z = kf->getTranslation().z; pos->SetValue(SecToTicks(mi->first), &p); } */ /* IKeyControl* kc = GetKeyControlInterface(pos); if (!kc) continue; typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); kc->SetNumKeys(keys.size()); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { ITCBPoint3Key key; key.time = SecToTicks(mi->first); key.tens = 0; key.cont = 0; key.bias = 0; key.easeIn = 25.0; key.easeOut = 25.0; key.val.x = mi->second->getTranslation().x; key.val.y = mi->second->getTranslation().y; key.val.z = mi->second->getTranslation().z; kc->SetKey(idx++, &key); } kc->SortKeys(); */ } return IMPEXP_SUCCESS; }
void ParticleMesherObject::BuildMesh(TimeValue t) { //check if render time //get node //mkae ivalid interesect with the int isRendering = 0; ivalid = FOREVER; TimeValue offset; float foffset; Interval iv; pblock2->GetValue(particlemesher_time, 0, foffset, iv); foffset = -foffset; pblock2->GetValue(particlemesher_radius, 0, radius, iv); foffset *= GetTicksPerFrame(); offset = (TimeValue) foffset; // pblock2->GetValue(particlemesher_time, 0, foffset, iv); if ((lastTime == t) ) { ivalid.Set(t,t); return; } pblock2->GetValue(particlemesher_rendertimeonly, 0, isRendering, ivalid); isRendering = !isRendering; if ((isRendering) || (TestAFlag(A_RENDER))) { INode *node=NULL; pblock2->GetValue(particlemesher_pick, 0, node, ivalid); BOOL reevalGroup = FALSE; if ((node != NULL) && (node->IsGroupHead()) ) { for (int ch=0;ch<node->NumberOfChildren();ch++) { INode *cnode= node->GetChildNode(ch); Interval iv; Matrix3 tm=cnode->GetObjectTM(t,&iv); if (cnode->IsGroupMember()) { reevalGroup = TRUE; for (int groupCount = 0; groupCount < pblock2->Count(particlemesher_extranodes); groupCount++) { INode *extraNode = pblock2->GetINode(particlemesher_extranodes,t,ch); if (cnode == extraNode) { reevalGroup = FALSE; groupCount = pblock2->Count(particlemesher_extranodes); } } if (reevalGroup) ch=node->NumberOfChildren(); } } if (reevalGroup) { tmList.ZeroCount(); pblock2->ZeroCount(particlemesher_extranodes); for (int ch=0;ch<node->NumberOfChildren();ch++) { INode *cnode= node->GetChildNode(ch); Interval iv; Matrix3 tm=cnode->GetObjectTM(t,&iv); if (cnode->IsGroupMember()) { pblock2->Append(particlemesher_extranodes,1,&cnode); tmList.Append(1,&tm); } } } } if (node) { if ( (node->IsGroupHead()) && (pblock2->Count(particlemesher_extranodes)!=0)) { int ct = 0; Matrix3 ident(1), inverseTm(1); mesh.setNumVerts(0); mesh.setNumFaces(0); for (int ch=0;ch<pblock2->Count(particlemesher_extranodes);ch++) { INode *cnode = pblock2->GetINode(particlemesher_extranodes,t,ch); if (cnode) { Object *pobj = cnode->EvalWorldState(t+offset).obj; if ( (pobj->SuperClassID() == GEOMOBJECT_CLASS_ID) || (pobj->SuperClassID() == SHAPE_CLASS_ID) ) { BOOL needDel; NullView nullView; Mesh *msh = ((GeomObject*)pobj)->GetRenderMesh(t+offset,cnode,nullView,needDel); Mesh tmsh = *msh; ivalid &= pobj->ObjectValidity(t+offset); Matrix3 tm(1); if (ch < tmList.Count()) tm = tmList[ch]; for (int v = 0; v < msh->numVerts; v++) { tmsh.verts[v] = tmsh.verts[v] * tm; } if (tmsh.numVerts != 0) { if (ct ==0) { mesh = tmsh; } else mesh = mesh + tmsh; ct++; } if (needDel) delete msh; } } } mesh.InvalidateTopologyCache(); } else { // Object *tobj = node->GetObjectRef(); // macroRecorder->FunctionCall(_T("time"), 1, 0, mr_int, t); // macroRecorder->EmitScript(); ObjectState os = node->EvalWorldState(t+offset); IParticleObjectExt* epobj; epobj = (IParticleObjectExt*) os.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE); if (os.obj->IsParticleSystem() && epobj) { if (epobj) { BOOL useAllPFEvents; pblock2->GetValue(particlemesher_useallpf,0,useAllPFEvents,FOREVER); pfNodes.ZeroCount(); INode *basenode=NULL; pblock2->GetValue(particlemesher_pick, 0, basenode, ivalid); tmList.ZeroCount(); if (useAllPFEvents) { MyEnumProc dep; os.obj->DoEnumDependents(&dep); for (int i = 0; i < dep.Nodes.Count(); i++) { Interval valid; INode *node = dep.Nodes[i]; Object *obj = node->GetObjectRef(); if (ParticleGroupInterface(obj) != nullptr) { pfNodes.Append(1,&node); Matrix3 tm = node->GetNodeTM(t+offset); tmList.Append(1,&tm); } } } else { int ct = pblock2->Count(particlemesher_pfeventlist); for (int i = 0; i < ct; i++) { INode *node; pblock2->GetValue(particlemesher_pfeventlist,t,node,FOREVER,i); if (node) { Object *obj = node->GetObjectRef(); if (ParticleGroupInterface(obj) != nullptr) { pfNodes.Append(1,&node); Matrix3 tm(1);// = basenode->GetNodeTM(t+offset); Matrix3 ntm = node->GetObjectTM(t+offset); tm = ntm; tmList.Append(1,&ntm); } } } } mesh.setNumVerts(0); mesh.setNumFaces(0); int ct = 0; for (int ch=0;ch< pfNodes.Count();ch++) { INode *cnode = pfNodes[ch]; if (cnode) { Object *pobj = cnode->EvalWorldState(t+offset).obj; if ( (pobj->SuperClassID() == GEOMOBJECT_CLASS_ID) || (pobj->SuperClassID() == SHAPE_CLASS_ID) ) { BOOL needDel; NullView nullView; Mesh *msh = ((GeomObject*)pobj)->GetRenderMesh(t+offset,cnode,nullView,needDel); Mesh tmsh = *msh; ivalid &= pobj->ObjectValidity(t+offset); Matrix3 tm(1); if (ch < tmList.Count()) tm = tmList[ch]; for (int v = 0; v < msh->numVerts; v++) { tmsh.verts[v] = tmsh.verts[v] * tm; } if (tmsh.numVerts != 0) { if (ct ==0) { mesh = tmsh; } else { Mesh tempMesh = mesh; CombineMeshes(mesh, tempMesh, tmsh); } ct++; } if (needDel) delete msh; } } } mesh.InvalidateTopologyCache(); } } else if ( (os.obj->SuperClassID() == GEOMOBJECT_CLASS_ID) || (os.obj->SuperClassID() == SHAPE_CLASS_ID) ) { BOOL needDel; NullView nullView; Mesh *msh = ((GeomObject*)os.obj)->GetRenderMesh(t+offset,node,nullView,needDel); ivalid &= os.obj->ObjectValidity(t); if (msh) { mesh = *msh; mesh.InvalidateTopologyCache(); if (needDel) delete msh; } } } lastTime = t; } else { //build proxy mesh if (node == NULL) { mesh.setNumVerts(5); mesh.setNumFaces(8); mesh.setNumMaps(2); mesh.setNumMapVerts(0, 0); mesh.setNumMapVerts(1, 0); mesh.setNumMapFaces(0, 0); mesh.setNumMapFaces(1, 0); mesh.setVert(0, Point3(-radius,-radius, 0.0f)); mesh.setVert(1, Point3( radius,-radius, 0.0f)); mesh.setVert(2, Point3( radius, radius, 0.0f)); mesh.setVert(3, Point3(-radius, radius, 0.0f)); // mesh.setVert(4, Point3(0.0f, 0.0f, 0.0f)); mesh.setVert(4, Point3(0.0f, 0.0f, radius)); mesh.faces[0].setEdgeVisFlags(1,0,1); mesh.faces[0].setSmGroup(1); mesh.faces[0].setVerts(0,1,3); mesh.faces[1].setEdgeVisFlags(1,1,0); mesh.faces[1].setSmGroup(1); mesh.faces[1].setVerts(1,2,3); mesh.faces[2].setEdgeVisFlags(1,1,1); mesh.faces[2].setSmGroup(1); mesh.faces[2].setVerts(0,4,1); mesh.faces[3].setEdgeVisFlags(1,1,1); mesh.faces[3].setSmGroup(1); mesh.faces[3].setVerts(1,4,0); mesh.faces[4].setEdgeVisFlags(1,1,1); mesh.faces[4].setSmGroup(1); mesh.faces[4].setVerts(2,4,3); mesh.faces[5].setEdgeVisFlags(1,1,1); mesh.faces[5].setSmGroup(1); mesh.faces[5].setVerts(3,4,2); mesh.faces[6].setEdgeVisFlags(1,0,1); mesh.faces[6].setSmGroup(1); mesh.faces[6].setVerts(3,1,0); mesh.faces[7].setEdgeVisFlags(1,1,0); mesh.faces[7].setSmGroup(1); mesh.faces[7].setVerts(3,2,1); } } } else { //build proxy mesh //build proxy mesh INode *node=NULL; pblock2->GetValue(particlemesher_pick, 0, node, ivalid); // if (node == NULL) { mesh.setNumVerts(5); mesh.setNumFaces(8); mesh.setNumMaps(2); mesh.setNumMapVerts(0, 0); mesh.setNumMapVerts(1, 0); mesh.setNumMapFaces(0, 0); mesh.setNumMapFaces(1, 0); mesh.setVert(0, Point3(-radius,-radius, 0.0f)); mesh.setVert(1, Point3( radius,-radius, 0.0f)); mesh.setVert(2, Point3( radius, radius, 0.0f)); mesh.setVert(3, Point3(-radius, radius, 0.0f)); // mesh.setVert(4, Point3(0.0f, 0.0f, 0.0f)); mesh.setVert(4, Point3(0.0f, 0.0f, radius)); mesh.faces[0].setEdgeVisFlags(1,0,1); mesh.faces[0].setSmGroup(1); mesh.faces[0].setVerts(0,1,3); mesh.faces[1].setEdgeVisFlags(1,1,0); mesh.faces[1].setSmGroup(1); mesh.faces[1].setVerts(1,2,3); mesh.faces[2].setEdgeVisFlags(1,1,1); mesh.faces[2].setSmGroup(1); mesh.faces[2].setVerts(0,4,1); mesh.faces[3].setEdgeVisFlags(1,1,1); mesh.faces[3].setSmGroup(1); mesh.faces[3].setVerts(1,4,0); mesh.faces[4].setEdgeVisFlags(1,1,1); mesh.faces[4].setSmGroup(1); mesh.faces[4].setVerts(2,4,3); mesh.faces[5].setEdgeVisFlags(1,1,1); mesh.faces[5].setSmGroup(1); mesh.faces[5].setVerts(3,4,2); mesh.faces[6].setEdgeVisFlags(1,0,1); mesh.faces[6].setSmGroup(1); mesh.faces[6].setVerts(3,1,0); mesh.faces[7].setEdgeVisFlags(1,1,0); mesh.faces[7].setSmGroup(1); mesh.faces[7].setVerts(3,2,1); } } mesh.InvalidateTopologyCache(); }
void Lighting::UpdateLights() { Matrix3 Mat; int i; ObjectState Os; LightObject *LightObj; LightState Ls; RenderLight Light; TimeValue Time = GetCOREInterface()->GetTime(); Interval valid; Point3 Pos,Target; m_Lights.clear(); for(i=0;i<sceneLights.Count();i++) { INode * Node = sceneLights[i]; Os = Node->EvalWorldState(Time); if(Os.obj ) { LightObj = (LightObject *)Os.obj; LightObj->EvalLightState(Time,valid,&Ls); Mat = Node->GetNodeTM(Time); Pos = Mat.GetTrans(); Light.m_Angle = Ls.hotsize; if(Light.m_Angle < 2.0f) { Light.m_Angle = 2.0f; } Mat = Node->GetNodeTM(Time); Light.m_Dir = Mat.GetRow(2); Light.m_Type = (RenderLightType)Ls.type; Light.m_Pos = Pos; Light.m_Dir = Light.m_Dir.Normalize(); Light.m_Color = Ls.color * Ls.intens; if(Ls.useAtten) { Light.m_Atten = true; if(Ls.attenStart <= 0.0f) { Light.m_InnerRange = 1.0f; } else { Light.m_InnerRange = 1.0f / (Ls.attenStart * 2.0f); } if(Ls.attenEnd <= 0.0f) { Light.m_OuterRange = 0.0f; } else { Light.m_OuterRange = 1.0f / (Ls.attenEnd * 2.0f); } } else { Light.m_Atten = false; Light.m_InnerRange = 0.1f; Light.m_OuterRange = 0.00001f; } m_Lights.push_back(Light); } } }
CInstanceGroup* CExportNel::buildInstanceGroup(const vector<INode*>& vectNode, vector<INode*>& resultInstanceNode, TimeValue tvTime) { // Extract from the node the name, the transformations and the parent CInstanceGroup::TInstanceArray aIGArray; uint32 i, nNumIG; uint32 j,k,m; aIGArray.empty (); resultInstanceNode.empty (); aIGArray.resize (vectNode.size()); resultInstanceNode.resize (vectNode.size()); int nNbInstance = 0; for (i = 0; i < vectNode.size(); ++i) { INode *pNode = vectNode[i]; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { ++nNbInstance; } } // Check integrity of the hierarchy and set the parents std::vector<INode*>::const_iterator it = vectNode.begin(); nNumIG = 0; for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone( *pNode, tvTime )) if (CExportNel::isMesh( *pNode, tvTime ) || CExportNel::isDummy(*pNode, tvTime)) { aIGArray[nNumIG].DontAddToScene = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_DONT_ADD_TO_SCENE, 0)?true:false; aIGArray[nNumIG].InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, ""); resultInstanceNode[nNumIG] = pNode; if (aIGArray[nNumIG].InstanceName == "") // no instance name was set, takes the node name instead { aIGArray[nNumIG].InstanceName = pNode->GetName(); } // Visible? always true, but if special flag for camera collision sint appDataCameraCol= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_CAMERA_COLLISION_MESH_GENERATION, 0); aIGArray[nNumIG].Visible= appDataCameraCol!=3; INode *pParent = pNode->GetParentNode(); // Set the DontCastShadow flag. aIGArray[nNumIG].DontCastShadow= pNode->CastShadows()==0; // Set the Special DontCastShadow flag. aIGArray[nNumIG].DontCastShadowForInterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_INTERIOR, BST_UNCHECKED)?true:false; aIGArray[nNumIG].DontCastShadowForExterior= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_LIGHT_DONT_CAST_SHADOW_EXTERIOR, BST_UNCHECKED)?true:false; // Is the pNode has the root node for parent ? if( pParent->IsRootNode() == 0 ) { // Look if the parent is in the selection int nNumIG2 = 0; for (j = 0; j < vectNode.size(); ++j) { INode *pNode2 = vectNode[j]; int nAccelType2 = CExportNel::getScriptAppData (pNode2, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType2&3) == 0) // If not an accelerator if (!RPO::isZone( *pNode2, tvTime )) if (CExportNel::isMesh( *pNode2, tvTime )) { if (pNode2 == pParent) break; ++nNumIG2; } } if (nNumIG2 == nNbInstance) { // The parent is not selected ! link to root aIGArray[nNumIG].nParent = -1; } else { aIGArray[nNumIG].nParent = nNumIG2; } } else { aIGArray[nNumIG].nParent = -1; } ++nNumIG; } } aIGArray.resize( nNumIG ); resultInstanceNode.resize( nNumIG ); // Build the array of node vGlobalPos = CVector(0,0,0); nNumIG = 0; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { CVector vScaleTemp; CQuat qRotTemp; CVector vPosTemp; // Get Nel Name for the object. aIGArray[nNumIG].Name= CExportNel::getNelObjectName(*pNode); //Get the local transformation matrix Matrix3 nodeTM = pNode->GetNodeTM(0); INode *pParent = pNode->GetParentNode(); Matrix3 parentTM = pParent->GetNodeTM(0); Matrix3 localTM = nodeTM*Inverse(parentTM); // Extract transformations CExportNel::decompMatrix (vScaleTemp, qRotTemp, vPosTemp, localTM); aIGArray[nNumIG].Rot = qRotTemp; aIGArray[nNumIG].Pos = vPosTemp; aIGArray[nNumIG].Scale = vScaleTemp; vGlobalPos += vPosTemp; ++nNumIG; } } // todo Make this work (precision): /* vGlobalPos = vGlobalPos / nNumIG; for (i = 0; i < nNumIG; ++i) aIGArray[i].Pos -= vGlobalPos; */ vGlobalPos = CVector(0,0,0); // Temporary !!! // Accelerator Portal/Cluster part //================= // Creation of all the clusters vector<CCluster> vClusters; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, NEL3D_APPDATA_ACCEL_DEFAULT); bool bFatherVisible = nAccelType&NEL3D_APPDATA_ACCEL_FATHER_VISIBLE?true:false; bool bVisibleFromFather = nAccelType&NEL3D_APPDATA_ACCEL_VISIBLE_FROM_FATHER?true:false; bool bAudibleLikeVisible = (nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_NOT_LIKE_VISIBLE)?false:true; bool bFatherAudible = bAudibleLikeVisible ? bFatherVisible : nAccelType&NEL3D_APPDATA_ACCEL_FATHER_AUDIBLE?true:false; bool bAudibleFromFather = bAudibleLikeVisible ? bVisibleFromFather : nAccelType&NEL3D_APPDATA_ACCEL_AUDIBLE_FROM_FATHER?true:false; if ((nAccelType&NEL3D_APPDATA_ACCEL_TYPE) == NEL3D_APPDATA_ACCEL_CLUSTER) // If cluster if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh(*pNode, tvTime)) { CCluster clusterTemp; std::string temp; temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_SOUND_GROUP, "no sound"); clusterTemp.setSoundGroup(temp != "no sound" ? temp : ""); temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_ENV_FX, "no fx"); clusterTemp.setEnvironmentFx(temp != "no fx" ? temp : ""); CMesh::CMeshBuild *pMB; CMeshBase::CMeshBaseBuild *pMBB; pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); for (j = 0; j < pMB->Faces.size(); ++j) { if (!clusterTemp.makeVolume (pMB->Vertices[pMB->Faces[j].Corner[0].Vertex], pMB->Vertices[pMB->Faces[j].Corner[1].Vertex], pMB->Vertices[pMB->Faces[j].Corner[2].Vertex]) ) { // ERROR : The volume is not convex !!! char tam[256]; sprintf(tam,"ERROR: The cluster %s is not convex.",vectNode[i]->GetName()); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } } clusterTemp.FatherVisible = bFatherVisible; clusterTemp.VisibleFromFather = bVisibleFromFather; clusterTemp.FatherAudible = bFatherAudible; clusterTemp.AudibleFromFather = bAudibleFromFather; clusterTemp.Name = pNode->GetName(); vClusters.push_back (clusterTemp); delete pMB; delete pMBB; } } // Creation of all the portals vector<CPortal> vPortals; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 1) // If Portal if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh(*pNode, tvTime)) { CPortal portalTemp; std::string temp; temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OCC_MODEL, "no occlusion"); portalTemp.setOcclusionModel(temp != "no occlusion" ? temp : ""); temp = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_OPEN_OCC_MODEL, "no occlusion"); portalTemp.setOpenOcclusionModel(temp != "no occlusion" ? temp : ""); CMesh::CMeshBuild *pMB; CMeshBase::CMeshBaseBuild *pMBB; pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); vector<sint32> poly; vector<bool> facechecked; facechecked.resize (pMB->Faces.size()); for (j = 0; j < pMB->Faces.size(); ++j) facechecked[j] = false; poly.push_back(pMB->Faces[0].Corner[0].Vertex); poly.push_back(pMB->Faces[0].Corner[1].Vertex); poly.push_back(pMB->Faces[0].Corner[2].Vertex); facechecked[0] = true; for (j = 0; j < pMB->Faces.size(); ++j) if (!facechecked[j]) { bool found = false; for(k = 0; k < 3; ++k) { for(m = 0; m < poly.size(); ++m) { if ((pMB->Faces[j].Corner[k].Vertex == poly[m]) && (pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[(m+1)%poly.size()])) { found = true; break; } if ((pMB->Faces[j].Corner[(k+1)%3].Vertex == poly[m]) && (pMB->Faces[j].Corner[k].Vertex == poly[(m+1)%poly.size()])) { found = true; break; } } if (found) break; } if (found) { // insert an empty space in poly between m and m+1 poly.resize (poly.size()+1); for (uint32 a = poly.size()-2; a > m; --a) poly[a+1] = poly[a]; poly[m+1] = pMB->Faces[j].Corner[(k+2)%3].Vertex; facechecked[j] = true; j = 0; } } vector<CVector> polyv; polyv.resize (poly.size()); for (j = 0; j < poly.size(); ++j) polyv[j] = pMB->Vertices[poly[j]]; if (!portalTemp.setPoly (polyv)) { // ERROR : Poly not convex, or set of vertices not plane char tam[256]; sprintf(tam,"ERROR: The portal %s is not convex.",vectNode[i]->GetName()); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } if (nAccelType&16) // is dynamic portal ? { string InstanceName = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_INSTANCE_NAME, ""); if (!InstanceName.empty()) portalTemp.setName (InstanceName); else portalTemp.setName (string(pNode->GetName())); } // Check if portal has 2 cluster int nNbCluster = 0; for (j = 0; j < vClusters.size(); ++j) { bool bPortalInCluster = true; for (k = 0; k < polyv.size(); ++k) if (!vClusters[j].isIn (polyv[k]) ) { bPortalInCluster = false; break; } if (bPortalInCluster) ++nNbCluster; } if (nNbCluster != 2) { // ERROR char tam[256]; sprintf(tam,"ERROR: The portal %s has not 2 clusters but %d",vectNode[i]->GetName(), nNbCluster); //MessageBox(NULL,tam,"Error",MB_OK|MB_ICONERROR); nlwarning(tam); } vPortals.push_back (portalTemp); delete pMB; delete pMBB; } } // Link instance to clusters (an instance has a list of clusters) nNumIG = 0; it = vectNode.begin(); for (i = 0; i < (sint)vectNode.size(); ++i, ++it) { INode *pNode = *it; int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32); if ((nAccelType&3) == 0) // If not an accelerator if (!RPO::isZone (*pNode, tvTime)) if (CExportNel::isMesh (*pNode, tvTime) || CExportNel::isDummy(*pNode, tvTime)) { if (nAccelType&32) // Is the flag clusterize set ? { // Test against all clusters // The list of vertices used to test against cluster std::vector<NLMISC::CVector> *testVertices; std::vector<NLMISC::CVector> FXVertices; // Used only if the obj is a fx. It contains the corners of the bbox. bool buildMeshBBox = true; /** If it is a mesh, we build its bbox and transform in world * If it is a FX, we read its bbox from its shape * If we can't read it, we use the bbox of the fx helper in max */ Object *obj = pNode->EvalWorldState(tvTime).obj; // Check if there is an object if (obj) { Class_ID clid = obj->ClassID(); // is the object a particle system ? if (clid.PartA() == NEL_PARTICLE_SYSTEM_CLASS_ID) { // build the shape from the file name std::string objName = CExportNel::getNelObjectName(*pNode); if (!objName.empty()) { NL3D::CShapeStream ss; NLMISC::CIFile iF; if (iF.open(objName.c_str())) { try { iF.serial(ss); NL3D::CParticleSystemShape *pss = dynamic_cast<NL3D::CParticleSystemShape *>(ss.getShapePointer()); if (!pss) { nlwarning("ERROR: Node %s shape is not a FX", CExportNel::getName(*pNode).c_str()); } else { NLMISC::CAABBox bbox; pss->getAABBox(bbox); // transform in world Matrix3 xForm = pNode->GetNodeTM(tvTime); NLMISC::CMatrix nelXForm; CExportNel::convertMatrix(nelXForm, xForm); bbox = NLMISC::CAABBox::transformAABBox(nelXForm, bbox); // store vertices of the bbox in the list FXVertices.reserve(8); for(uint k = 0; k < 8; ++k) { FXVertices.push_back(CVector(((k & 1) ? 1 : -1) * bbox.getHalfSize().x + bbox.getCenter().x, ((k & 2) ? 1 : -1) * bbox.getHalfSize().y + bbox.getCenter().y, ((k & 4) ? 1 : -1) * bbox.getHalfSize().z + bbox.getCenter().z)); } // testVertices = &FXVertices; buildMeshBBox = false; } delete ss.getShapePointer(); } catch (NLMISC::Exception &e) { nlwarning(e.what()); } } if (buildMeshBBox) { nlwarning("ERROR: Can't get bbox of a particle system from its shape, using helper bbox instead"); } } } } CMesh::CMeshBuild *pMB = NULL; CMeshBase::CMeshBaseBuild *pMBB = NULL; if (buildMeshBBox) { pMB = createMeshBuild (*pNode, tvTime, pMBB); convertToWorldCoordinate( pMB, pMBB ); testVertices = &pMB->Vertices; } for(k = 0; k < vClusters.size(); ++k) { bool bMeshInCluster = false; for(j = 0; j < testVertices->size(); ++j) { if (vClusters[k].isIn ((*testVertices)[j])) { bMeshInCluster = true; break; } } if (bMeshInCluster) { aIGArray[nNumIG].Clusters.push_back (k); } } // debug purpose : to remove if (vClusters.size() > 0) if (aIGArray[nNumIG].Clusters.size() == 0) { char tam[256]; sprintf(tam,"ERROR: Object %s is not attached to any cluster\nbut his flag clusterize is set", pNode->GetName()); //MessageBox(NULL, tam, "Warning", MB_OK); nlwarning(tam); } // debug purpose : to remove delete pMB; delete pMBB; } ++nNumIG; } // debug purpose : to remove /* if ((nAccelType&3) == 0) // If not an accelerator if (!(nAccelType&32)) { char tam[256]; sprintf(tam,"Object %s is not clusterized", pNode->GetName()); MessageBox(NULL, tam, "Info", MB_OK); } */ // debug purpose : to remove } // PointLight part //================= bool sunLightEnabled= false; sint nNumPointLight = 0; vector<CPointLightNamed> pointLights; pointLights.resize(vectNode.size()); // For all nodes for (i = 0; i < (sint)vectNode.size(); ++i) { INode *pNode = vectNode[i]; SLightBuild sLightBuild; // If it is a Max Light. if ( sLightBuild.canConvertFromMaxLight(pNode, tvTime) ) { // And if this light is checked to realtime export int nRTExport= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_REALTIME_LIGHT, BST_CHECKED); if(nRTExport == BST_CHECKED) { // get Max Light info. sLightBuild.convertFromMaxLight(pNode, tvTime); // Skip if LightDir if(sLightBuild.Type != SLightBuild::LightDir) { // Fill PointLight Info. NL3D::CPointLightNamed &plNamed= pointLights[nNumPointLight]; // Position plNamed.setPosition(sLightBuild.Position); // Attenuation plNamed.setupAttenuation(sLightBuild.rRadiusMin, sLightBuild.rRadiusMax); // Colors // Ensure A=255 for localAmbient to work. NLMISC::CRGBA ambient= sLightBuild.Ambient; ambient.A= 255; plNamed.setDefaultAmbient(ambient); plNamed.setAmbient(ambient); plNamed.setDefaultDiffuse(sLightBuild.Diffuse); plNamed.setDiffuse(sLightBuild.Diffuse); plNamed.setDefaultSpecular(sLightBuild.Specular); plNamed.setSpecular(sLightBuild.Specular); // GroupName. plNamed.AnimatedLight = sLightBuild.AnimatedLight; plNamed.LightGroup = sLightBuild.LightGroup; // Which light type?? if(sLightBuild.bAmbientOnly || sLightBuild.Type== SLightBuild::LightAmbient) { plNamed.setType(CPointLight::AmbientLight); // Special ambient info int nRTAmbAdd= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_REALTIME_AMBIENT_ADD_SUN, BST_UNCHECKED); plNamed.setAddAmbientWithSun(nRTAmbAdd==BST_CHECKED); } else if(sLightBuild.Type== SLightBuild::LightPoint) { plNamed.setType(CPointLight::PointLight); } else if(sLightBuild.Type== SLightBuild::LightSpot) { plNamed.setType(CPointLight::SpotLight); // Export Spot infos. plNamed.setupSpotDirection(sLightBuild.Direction); plNamed.setupSpotAngle(sLightBuild.rHotspot, sLightBuild.rFallof); } else { // What??? nlstop; } // inc Size ++nNumPointLight; } } // if this light is a directionnal and checked to export as Sun Light int nExportSun= CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_EXPORT_AS_SUN_LIGHT, BST_UNCHECKED); if(nExportSun== BST_CHECKED) { // get Max Light info. sLightBuild.convertFromMaxLight(pNode, tvTime); // Skip if not dirLight. if(sLightBuild.Type == SLightBuild::LightDir) sunLightEnabled= true; } } } // Good size pointLights.resize(nNumPointLight); // Build the ig //================= CInstanceGroup* pIG = new CInstanceGroup; // Link portals and clusters and create meta cluster if one pIG->build (vGlobalPos, aIGArray, vClusters, vPortals, pointLights); // IG touched by sun ?? pIG->enableRealTimeSunContribution(sunLightEnabled); return pIG; }
//--------------------------------------------------------------- void CameraExporter::exportCamera( ExportNode* exportNode ) { if ( !exportNode->getIsInVisualScene() ) return; String cameraId = getCameraId(*exportNode); INode* iNode = exportNode->getINode(); CameraObject* camera = (CameraObject*)iNode->GetObjectRef(); INode* targetNode = ( camera->ClassID().PartA() == LOOKAT_CAM_CLASS_ID) ? iNode->GetTarget() : 0; if ( camera ) { if ( mDocumentExporter->isExportedObject(ObjectIdentifier(camera)) ) return; mDocumentExporter->insertExportedObject(ObjectIdentifier(camera), exportNode); // Retrieve the camera parameters block IParamBlock* parameters = (IParamBlock*) camera->GetReference(MaxCamera::PBLOCK_REF); COLLADASW::BaseOptic * optics = 0; if ( camera->IsOrtho() ) { optics = new COLLADASW::OrthographicOptic(COLLADASW::LibraryCameras::mSW); // Calculate the target distance for FOV calculations float targetDistance; if ( targetNode ) { Point3 targetTrans = targetNode->GetNodeTM(mDocumentExporter->getOptions().getAnimationStart()).GetTrans(); Point3 cameraTrans = iNode->GetNodeTM(mDocumentExporter->getOptions().getAnimationStart()).GetTrans(); targetDistance = (targetTrans - cameraTrans).Length(); } else { targetDistance = camera->GetTDist(mDocumentExporter->getOptions().getAnimationStart()); } ConversionInverseOrthoFOVFunctor conversionInverseOrthoFOVFunctor(targetDistance); if ( AnimationExporter::isAnimated(parameters, MaxCamera::FOV) ) { optics->setXMag(conversionInverseOrthoFOVFunctor(parameters->GetFloat(MaxCamera::FOV)), XMAG_SID); mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FOV, cameraId, XMAG_SID, 0, true, &conversionInverseOrthoFOVFunctor); } else { optics->setXMag(conversionInverseOrthoFOVFunctor(parameters->GetFloat(MaxCamera::FOV))); } } else { optics = new COLLADASW::PerspectiveOptic(COLLADASW::LibraryCameras::mSW); if ( AnimationExporter::isAnimated(parameters, MaxCamera::FOV) ) { optics->setXFov(COLLADASW::MathUtils::radToDegF(parameters->GetFloat(MaxCamera::FOV)), XFOV_SID); mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FOV, cameraId, XFOV_SID, 0, true, &ConversionFunctors::radToDeg); } else { optics->setXFov(COLLADASW::MathUtils::radToDegF(parameters->GetFloat(MaxCamera::FOV))); } } bool hasAnimatedZNear = mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::NEAR_CLIP, cameraId, optics->getZNearDefaultSid(), 0); optics->setZNear(parameters->GetFloat(MaxCamera::NEAR_CLIP), hasAnimatedZNear); bool hasAnimatedZFar = mAnimationExporter->addAnimatedParameter(parameters, MaxCamera::FAR_CLIP, cameraId, optics->getZFarDefaultSid(), 0); optics->setZFar(parameters->GetFloat(MaxCamera::FAR_CLIP), hasAnimatedZFar); #ifdef UNICODE String exportNodeName = COLLADABU::StringUtils::wideString2utf8String(exportNode->getINode()->GetName()); COLLADASW::Camera colladaCamera(COLLADASW::LibraryCameras::mSW, optics, cameraId, COLLADASW::Utils::checkNCName(exportNodeName)); #else COLLADASW::Camera colladaCamera(COLLADASW::LibraryCameras::mSW, optics, cameraId, COLLADASW::Utils::checkNCName(exportNode->getINode()->GetName())); #endif setExtraTechnique(&colladaCamera); // Retrieve the camera target if ( targetNode ) { ExportNode* targetExportNode = mExportSceneGraph->getExportNode(targetNode); addExtraParameter(EXTRA_PARAMETER_TARGET, "#" + targetExportNode->getId()); } if (camera->GetMultiPassEffectEnabled(0, FOREVER)) { IMultiPassCameraEffect *multiPassCameraEffect = camera->GetIMultiPassCameraEffect(); if (multiPassCameraEffect) { Class_ID id = multiPassCameraEffect->ClassID(); // the camera could have both effects, but not in Max if (id == FMULTI_PASS_MOTION_BLUR_CLASS_ID) { IParamBlock2 *parameters = multiPassCameraEffect->GetParamBlock(0); if (parameters ) { addParamBlockAnimatedExtraParameters(MOTION_BLUR_ELEMENT, MOTION_BLUR_PARAMETERS, MOTION_BLUR_PARAMETER_COUNT, parameters, cameraId); } } else if (id == FMULTI_PASS_DOF_CLASS_ID) { IParamBlock2 *parameters = multiPassCameraEffect->GetParamBlock(0); if (parameters ) { addParamBlockAnimatedExtraParameters(DEPTH_OF_FIELD_ELEMENT, DEPTH_OF_FIELD_PARAMETERS, DEPTH_OF_FIELD_PARAMETER_COUNT, parameters, cameraId); addExtraParameter(TARGETDISTANCE_PARAMETER, camera->GetTDist(0)); } } } } addCamera(colladaCamera); delete optics; } }
void SkeletonExporter::export_camera(INode *node) { Control *c; int size_key; float camera_znear, camera_zfar; CameraState cs; // Interval valid = FOREVER; ObjectState os; CameraObject *cam; GenCamera *gencam; float roll0; Matrix3 mat; Point3 row; os = node->EvalWorldState(0); cam = (CameraObject *)os.obj; gencam = (GenCamera *)os.obj; if (gencam->Type() != TARGETED_CAMERA) { fprintf(fTXT, "Only targeted camera are supported!\n\n"); return; } fprintf(fTXT, "Targeted camera found\n"); write_chunk_header(fA3D, TARGETED_CAMERA_ID, node->GetName(), 40); if (makeRAY) write_chunk_header(fRAY, TARGETED_CAMERA_ID, node->GetName(), 40); INode* target = node->GetTarget(); fprintf(fTXT, "Name : %s\n", node->GetName()); cam->EvalCameraState(0, FOREVER, &cs); // ------------------ salviamo znear e zfar ---------------------- camera_znear=2; camera_zfar=2000; if (cs.manualClip) { camera_znear=cs.hither; camera_zfar=cs.yon; } fprintf(fTXT, "Znear = %f \n", camera_znear); fwrite(&camera_znear, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&camera_znear, sizeof(float), 1, fRAY); fprintf(fTXT, "Zfar = %f \n", camera_zfar); fwrite(&camera_zfar, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&camera_zfar, sizeof(float), 1, fRAY); // ----------------- salviamo l'angolo di FOV -------------------- fprintf(fTXT, "FOV (rad) = %f \n", cs.fov); fwrite(&cs.fov, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&cs.fov, sizeof(float), 1, fRAY); // ------------------ salviamo l'angolo di roll ------------------ c=node->GetTMController()->GetRollController(); c->GetValue(0, &roll0, FOREVER); fprintf(fTXT, "Roll (rad) = %f \n", roll0); fwrite(&roll0, sizeof(float), 1, fA3D); if (makeRAY) fwrite(&roll0, sizeof(float), 1, fRAY); // salviamo la posizione nel mondo mat = node->GetNodeTM(0); row = mat.GetRow(3); fprintf(fTXT, "Camera world position : x=%f, y=%f, z=%f\n", row.x, row.y, row.z); write_point3(&row, fA3D); if (makeRAY) write_point3(&row, fRAY); // --------- salviamo la posizione del target nel mondo ---------- if (target) { mat = target->GetNodeTM(0); row = mat.GetRow(3); fprintf(fTXT, "Target world position : x=%f, y=%f, z=%f\n", row.x, row.y, row.z); write_point3(&row, fA3D); if (makeRAY) write_point3(&row, fRAY); } // esportiamo l'animazione della posizione della camera // se ci sono un numero di key > 0 c=node->GetTMController()->GetPositionController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Camera position track present."); write_chunk_header(fA3D, POSITION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_point3_track(c, 1, fA3D); if (makeRAY) write_chunk_header(fRAY, POSITION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_point3_track(c, 1, fRAY); } // ----- esportiamo l'animazione della posizione del target ------ if (target) { c=target->GetTMController()->GetPositionController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Target position track present."); write_chunk_header(fA3D, CAMERA_TARGET_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_point3_track(c, 1, fA3D); if (makeRAY) write_chunk_header(fRAY, CAMERA_TARGET_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_point3_track(c, 1, fRAY); } } // --------------- esportiamo le tracce di FOV ------------------- c=gencam->GetFOVControl(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Camera FOV track present."); write_chunk_header(fA3D, CAMERA_FOV_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); // radianti if (makeRAY) write_chunk_header(fRAY, CAMERA_FOV_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_float_track(c, 1, fRAY); // radianti } // --------------- esportiamo le tracce di roll ------------------ c=node->GetTMController()->GetRollController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Camera roll track present."); write_chunk_header(fA3D, CAMERA_ROLL_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); // radianti if (makeRAY) write_chunk_header(fRAY, CAMERA_ROLL_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); if (makeRAY) export_float_track(c, 1, fRAY); // radianti } fprintf(fTXT, "\n\n--------------------------------------------------\n"); }
int CMaxAnimationImport::DoImport( const TCHAR* name, ImpInterface* ii, Interface* i, BOOL suppressPrompts) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HWND window = i->GetMAXHWnd(); CFileDialog fileDialog(TRUE, "xsf", 0, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 0, CWnd::FromHandle(window)); if (fileDialog.DoModal() != IDOK) { return IMPEXP_CANCEL; } CString skeleton = fileDialog.GetPathName(); cal3d::RefPtr<CalCoreSkeleton> skel = CalLoader::loadCoreSkeleton(std::string(skeleton)); if (!skel) { MessageBox( window, "Loading skeleton file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } cal3d::RefPtr<CalCoreAnimation> anim = CalLoader::loadCoreAnimation(name); if (!anim) { MessageBox( window, "Loading animation file failed", "Import Cal3D Animation", MB_OK | MB_ICONERROR); return IMPEXP_FAIL; } typedef std::list<CalCoreTrack*> CoreTrackList; CoreTrackList& trackList = anim->getListCoreTrack(); for (CoreTrackList::iterator itr = trackList.begin(); itr != trackList.end(); ++itr) { CalCoreTrack* track = *itr; int boneId = track->getCoreBoneId(); CalCoreBone* bone = skel->getCoreBone(boneId); if (!bone) continue; INode* node = i->GetINodeByName(bone->getName().c_str()); if (!node) continue; unsigned kfCount = track->getCoreKeyframeCount(); SuspendAnimate(); AnimateOn(); for (unsigned i = 0; i < kfCount; ++i) { CalCoreKeyframe* kf = track->getCoreKeyframe(i); CalQuaternion kf_q = kf->getRotation(); CalVector kf_v = kf->getTranslation(); TimeValue time = SecToTicks(kf->getTime()); Matrix3 tm; tm.IdentityMatrix(); Quat(kf_q.x, kf_q.y, kf_q.z, kf_q.w).MakeMatrix(tm); tm.SetTrans(Point3(kf_v.x, kf_v.y, kf_v.z)); INode* parent = node->GetParentNode(); if (parent) { tm *= parent->GetNodeTM(time); } node->SetNodeTM(time, tm); } ResumeAnimate(); /* typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); int mapsize = sizeof(keys); int size = keys.size(); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { Point3 p; CalCoreKeyframe* kf = mi->second; p.x = kf->getTranslation().x; p.y = kf->getTranslation().y; p.z = kf->getTranslation().z; pos->SetValue(SecToTicks(mi->first), &p); } */ /* IKeyControl* kc = GetKeyControlInterface(pos); if (!kc) continue; typedef std::map<float, CalCoreKeyframe*> KeyMap; KeyMap& keys = track->getMapCoreKeyframe(); kc->SetNumKeys(keys.size()); int idx = 0; for (KeyMap::iterator mi = keys.begin(); mi != keys.end(); ++mi) { ITCBPoint3Key key; key.time = SecToTicks(mi->first); key.tens = 0; key.cont = 0; key.bias = 0; key.easeIn = 25.0; key.easeOut = 25.0; key.val.x = mi->second->getTranslation().x; key.val.y = mi->second->getTranslation().y; key.val.z = mi->second->getTranslation().z; kc->SetKey(idx++, &key); } kc->SortKeys(); */ } return IMPEXP_SUCCESS; }
void RBExport::ProcessCamera( INode* node ) { if (m_pConfig->m_bExportCameras == false) { return; } ObjectState os = node->EvalWorldState( m_CurTime ); Object* pCurObject = os.obj; if (!pCurObject) return; CameraObject* camObj = (CameraObject*)pCurObject; Interval validIvl; CameraState cs; RefResult res = camObj->EvalCameraState( m_CurTime, validIvl, &cs ); if ( res != REF_SUCCEED) { Err( "Error processing camera <%s>", node->GetName() ); return; } Info( "Processing camera <%s>", node->GetName() ); Matrix3 camTM = c_CamFlipTM*node->GetNodeTM( m_CurTime ); Matrix3 parentTM; INode* pParent = node->GetParentNode(); if (pParent && !pParent->IsRootNode()) { parentTM = pParent->GetNodeTM( m_CurTime ); } else { parentTM = c_IdentityTM; } parentTM = c_FlipTM*parentTM; camTM = camTM*Inverse( parentTM ); JCamera* pCamera = new JCamera(); pCamera->SetWorldTM( Convert( camTM ) ); float aspect = ((float)m_pInterface->GetRendWidth())/((float)m_pInterface->GetRendHeight()); float zn = cs.nearRange; float zf = cs.farRange; float fov = cs.fov; if (zn < c_FltEpsilon) zn = 1.0f; pCamera->SetOrtho ( cs.isOrtho == TRUE ); pCamera->SetZNear ( zn ); pCamera->SetZFar ( zf ); pCamera->SetAspect ( aspect ); if (cs.isOrtho) { float vVol = 2.0f * cs.tdist * tan( cs.fov * 0.5f ); pCamera->SetFOVx( vVol ); } else { pCamera->SetFOVx( RadToDeg( fov ) ); } pCamera->SetName( node->GetName() ); // insert camera as the first node in the model m_pModel->AddChild( pCamera, 0 ); } // RBExport::ProcessCamera
bool MeshExpUtility::SaveSkinKeys(const char* n){ CFS_Memory F; int FramesPerSecond = GetFrameRate(); int TicksPerFrame = GetTicksPerFrame(); int FirstTick = ip->GetAnimRange().Start(); int LastTick = ip->GetAnimRange().End(); Point3 v; Matrix3 tm; // Write signature and version char S[MAX_PATH]; sprintf(S, "KEYEXP 3.0"); F.Wstring(S); INode *node; ObjectEntry *Current; //----------------------------------------------------------------------- // Count bones and report int NumBones = 0; Current = theObjects->head; while(Current) { /* if(Current->entry->type != OBTYPE_BONE) { Current = Current->next; continue; } */ NumBones++; Current = Current->next; } sprintf(S, "Number of Bones = %d", NumBones); F.Wstring(S); ELog.Msg(mtInformation,S); //----------------------------------------------------------------------- // Write out necessary data for motion keys sprintf(S, "Key Data"); F.Wstring(S); TimeValue t; Quat qq; Point3 tp, sp; INode* parent; Matrix3 tmp; sprintf(S, "%d %d %d", FirstTick / TicksPerFrame, LastTick / TicksPerFrame, FramesPerSecond); F.Wstring(S); Current = theObjects->head; while(Current){ /* if(Current->entry->type != OBTYPE_BONE) { Current = Current->next; continue; } */ Matrix3 tm; node = Current->entry->node; sprintf(S, "Node: %s", node->GetName()); F.Wstring(S); ELog.Msg(mtInformation,S); // Print notetrack info { int NumNT, n, i, j, NumNotes; NoteTrack* pNT; DefNoteTrack* pDNT; NoteKey* pNK; NumNT = node->NumNoteTracks(); // count all of the notes on all of the notetracks NumNotes = 0; for(n=0;n<NumNT;n++){ pNT = node->GetNoteTrack(n); if(pNT->ClassID() == Class_ID(NOTETRACK_CLASS_ID, 0)){ pDNT = (DefNoteTrack*)pNT; j = pDNT->NumKeys(); for(i=0;i<j;i++){ pNK = pDNT->keys[i]; if( (pNK->time >= FirstTick) && (pNK->time <= LastTick) ) NumNotes++; } } } sprintf(S, "Number of Notes = %d", NumNotes); F.Wstring(S); for(n=0;n<NumNT;n++){ pNT = node->GetNoteTrack(n); if(pNT->ClassID() == Class_ID(NOTETRACK_CLASS_ID, 0)){ pDNT = (DefNoteTrack*)pNT; j = pDNT->NumKeys(); for(i=0;i<j;i++){ pNK = pDNT->keys[i]; if( (pNK->time >= FirstTick) && (pNK->time <= LastTick) ){ sprintf(S, "%d: %s", (pNK->time - FirstTick) / TicksPerFrame, pNK->note); F.Wstring(S); } } } } } for(t=FirstTick;t<=LastTick;t+=TicksPerFrame){ tm = node->GetNodeTM(t); DecomposeMatrix(tm, tp, qq, sp); qq.MakeMatrix (tm); tm.SetTrans (tp); parent = node->GetParentNode(); if(parent){ tmp = parent->GetNodeTM(t); DecomposeMatrix(tmp, tp, qq, sp); qq.MakeMatrix(tmp); tmp.SetTrans(tp); tmp = Inverse(tmp); tm *= tmp; } DecomposeMatrix(tm, tp, qq, sp); sprintf(S,"%f %f %f %f",qq.x, qq.y, qq.z, qq.w); F.Wstring(S); sprintf(S,"%f %f %f",tp.x,tp.y,tp.z); F.Wstring(S); /* // Euler angles Point3 E; QuatToEuler (Quat(tm), E); fprintf (f,"%f %f %f",E.x,E.y,E.z); // Translate DecomposeMatrix (tm, tp, qq, sp); fprintf (f,"%f %f %f",tp.x,tp.y,tp.z); */ // Matrix3fprint(f, tm); } Current = Current->next; } sprintf(S, "Key Data Complete"); F.Wstring(S); ELog.Msg(mtInformation,S); F.SaveTo(n,0); return true; }
bool LuxMaxCamera::exportCamera(float lensRadius, luxcore::Scene &scene) { INode* camNode = GetCOREInterface9()->GetActiveViewExp().GetViewCamera(); if (camNode == NULL) { MessageBox(0, L"Set active view to a target camera and render again.", L"Error!", MB_OK); return false; } else { CameraObject* cameraPtr = (CameraObject *)camNode->EvalWorldState(GetCOREInterface()->GetTime()).obj; float v = 0.0f; float FOV = 0; float focaldistance = 0; Interval ivalid = FOREVER; IParamBlock2 *pBlock = camNode->GetParamBlock(0); IParamBlock2* pblock2; if (v > 0.0f) { MessageBox(0, L"LuxCam modifier selected.", L"Error!", MB_OK); return false; } if (cameraPtr->ClassID() == MAX2016_PHYSICAL_CAMERA) { IPhysicalCamera* physicalCamera = dynamic_cast<IPhysicalCamera*>(camNode->EvalWorldState(GetCOREInterface()->GetTime()).obj); FOV = physicalCamera->GetFOV(GetCOREInterface()->GetTime(), FOREVER) * 180 / PI; focaldistance = physicalCamera->GetTDist(GetCOREInterface()->GetTime(), FOREVER); } else { FOV = cameraPtr->GetFOV(GetCOREInterface()->GetTime(), FOREVER) * 180 / PI; focaldistance = cameraPtr->GetTDist(GetCOREInterface()->GetTime(), FOREVER); } ::Point3 camTrans = camNode->GetNodeTM(GetCOREInterface()->GetTime()).GetTrans(); INode* NewCam = camNode; ::Matrix3 targetPos; NewCam->GetTargetTM(GetCOREInterface()->GetTime(), targetPos); float aspectratio = GetCOREInterface11()->GetImageAspRatio(); if (aspectratio < 1) FOV = 2.0f * ((180 / PI) *(atan(tan((PI / 180)*(FOV / 2.0f)) / aspectratio))); mprintf(L"Rendering with camera: : %s\n", camNode->GetName()); scene.Parse( Property("scene.camera.lookat.orig")(camTrans.x, camTrans.y, camTrans.z) << Property("scene.camera.lookat.target")(targetPos.GetTrans().x, targetPos.GetTrans().y, targetPos.GetTrans().z) << Property("scene.camera.fieldofview")(FOV) << Property("scene.camera.lensradius")(lensRadius) << //Property("scene.camera.focaldistance")(cameraPtr->GetTDist(GetCOREInterface()->GetTime(), FOREVER)) << Property("scene.camera.focaldistance")(focaldistance) << Property("scene.camera.shutteropen")(0.0f) << Property("scene.camera.shutterclose")(1.615f) ); return true; } }
void NifImporter::AlignBiped(IBipMaster* master, NiNodeRef node) { #ifdef USE_BIPED NiNodeRef parent = node->GetParent(); string name = node->GetName(); vector<NiAVObjectRef> children = node->GetChildren(); vector<NiNodeRef> childNodes = DynamicCast<NiNode>(children); TSTR s1 = FormatText("Processing %s:", name.c_str()); TSTR s2 = FormatText("Processing %s:", name.c_str()); INode *bone = GetNode(node); if (bone != NULL) { if (uncontrolledDummies) BuildControllerRefList(node, ctrlCount); Matrix44 m4 = node->GetWorldTransform(); Vector3 pos; Matrix33 rot; float scale; m4.Decompose(pos, rot, scale); Matrix3 m = TOMATRIX3(m4); Point3 p = m.GetTrans(); Quat q(m); s1 += FormatText(" ( %s)", PrintMatrix3(m).data()); if (strmatch(name, master->GetRootName())) { // Align COM //PosRotScaleNode(bone, p, q, 1.0f, prsPos); PosRotScaleBiped(master, bone, p, q, 1.0f, prsPos); } else if (INode *pnode = bone->GetParentNode()) { // Reparent if necessary if (!strmatch(parent->GetName(), pnode->GetName())) { if (pnode = FindNode(parent)) { bone->Detach(0); pnode->AttachChild(bone); } } // Hack to scale the object until it fits for (int i=0; i<10; ++i) { float s = CalcScale(bone, node, childNodes); if (fabs(s-1.0f) < (FLT_EPSILON*100.0f)) break; s1 += FormatText(" (%g)", s); master->SetBipedScale(TRUE, ScaleValue(Point3(s,s,s)), 0, bone); } PosRotScale prs = prsDefault; PosRotScaleBiped(master, bone, p, q, scale, prs); // Rotation with Clavicle is useless in Figure Mode using the standard interface // I was tring unsuccessfully to correct for it //if (wildcmpi("Bip?? ? Clavicle", name.c_str())) { // AngAxis a1 = CalcTransform(bone, node, childNodes); // Matrix3 tm1 = GenerateRotMatrix(a1); // Quat nq = TransformQuat(tm1, q); // PosRotScaleNode(bone, p, nq, scale, prsRot); //} } s2 += FormatText(" ( %s)", PrintMatrix3(bone->GetNodeTM(0)).data()); } else { ImportBones(node, false); } for (char *p = s1; *p != 0; ++p) if (isspace(*p)) *p = ' '; for (char *p = s2; *p != 0; ++p) if (isspace(*p)) *p = ' '; OutputDebugString(s1 + "\n"); OutputDebugString(s2 + "\n"); for (vector<NiNodeRef>::iterator itr = childNodes.begin(), end = childNodes.end(); itr != end; ++itr){ AlignBiped(master, *itr); } #endif }