Abc::C4f AlembicPoints::GetColor(IParticleObjectExt *pExt, int particleId, TimeValue ticks) { Abc::C4f color(0.5, 0.5, 0.5, 1.0); // Go into the particle's action list INode *particleGroupNode = pExt->GetParticleGroup(particleId); Object *particleGroupObj = (particleGroupNode != NULL) ? particleGroupNode->EvalWorldState(ticks).obj : NULL; if (!particleGroupObj) { return color; } IParticleGroup *particleGroup = GetParticleGroupInterface(particleGroupObj); INode *particleActionListNode = particleGroup->GetActionList(); Object *particleActionObj = (particleActionListNode != NULL ? particleActionListNode->EvalWorldState(ticks).obj : NULL); if (!particleActionObj) { return color; } PFSimpleOperator *pSimpleOperator = NULL; // In the case of multiple shape operators in an action list, the one furthest // down the list seems to be the one that applies IPFActionList *particleActionList = GetPFActionListInterface(particleActionObj); for (int p = particleActionList->NumActions() - 1; p >= 0; p -= 1) { INode *pActionNode = particleActionList->GetAction(p); Object *pActionObj = (pActionNode != NULL ? pActionNode->EvalWorldState(ticks).obj : NULL); if (pActionObj == NULL) { continue; } if (pActionObj->ClassID() == PFOperatorDisplay_Class_ID) { pSimpleOperator = static_cast<PFSimpleOperator *>(pActionObj); break; } } if (pSimpleOperator) { IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0); Point3 c = pblock->GetPoint3(kDisplay_color); color.r = c.x; color.g = c.y; color.b = c.z; color.a = 1.0; } return color; }
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 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; }
BOOL PFOperatorInstanceShapeMXSValidator::Validate(PB2Value& v) { INode* iNode = (INode*)v.r; if (iNode == NULL) return NULL; TimeValue t = GetCOREInterface()->GetTime(); Tab<INode*> stack; stack.Append(1, &iNode, 10); while (stack.Count()) { INode *node = stack[stack.Count()-1]; stack.Delete(stack.Count()-1, 1); Object *obj = node->EvalWorldState(t).obj; if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) return TRUE; // add children to the stack for (int i = 0; i < node->NumberOfChildren(); i++) { INode *childNode = node->GetChildNode(i); if (childNode) stack.Append(1, &childNode, 10); } } return FALSE; }
Value* GMP_SaveObjAs_cf(Value** arg_list, int count) { gmpMeshLoader meshLoader; OPENFILENAME ofn; static char szFile[256]; static char szFileTitle[256]; memset(&ofn,0,sizeof(ofn)); ofn.lStructSize=sizeof(ofn); ofn.hwndOwner=GetCOREInterface()->GetMAXHWnd(); ofn.lpstrFilter="gkMesh File(*.obj)\0*.obj;\0\0"; ofn.nFilterIndex=1; ofn.lpstrFile=szFile; ofn.nMaxFile=sizeof(szFile); ofn.lpstrFileTitle=szFileTitle; ofn.nMaxFileTitle=sizeof(szFileTitle); ofn.Flags=OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_EXPLORER; // Display the Open dialog box. if (GetSaveFileName(&ofn)) { INode *node = GetCOREInterface()->GetSelNode(0); if (node) { const ObjectState& os = node->EvalWorldState(0); NullView1 view; BOOL bNeedDelete = FALSE; GeomObject* pGeoObj = NULL; if(os.obj->CanConvertToType(triObjectClassID)) { TriObject* pObj = (TriObject*)(os.obj->ConvertToType(0, triObjectClassID)); pGeoObj = (GeomObject*)pObj; } else { return &ok; } gmpMeshLoader loader; Mesh * pMesh = pGeoObj->GetRenderMesh( 0 , node , view , bNeedDelete ); TCHAR szFilename[MAX_PATH]; _tcscpy_s(szFilename, ofn.lpstrFile); Box3 box = pMesh->getBoundingBox(); float radius = (box.pmax - box.pmin).Length(); loader.SaveGeometryAsOBJ( szFilename, *pMesh, radius ); return &ok; } } return &ok; }
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; } } } }
BOOL Cal3DObjPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m, int flags) { INode *node = ip->PickNode(hWnd, m); if (node == NULL) return FALSE; Object *obj = node->EvalWorldState(0).obj; return obj->ClassID() == AudioClipClassID; }
BombObject *BombMod::GetWSMObject(TimeValue t) { if (nodeRef) { ObjectState os = nodeRef->EvalWorldState(t); assert(os.obj && os.obj->SuperClassID()==WSM_OBJECT_CLASS_ID); return (BombObject*)os.obj; } else { return NULL; } }
BOOL TriggerPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m, int flags) { INode *node = ip->PickNode(hWnd, m); if (node == NULL) return FALSE; Object *obj = node->EvalWorldState(0).obj; if ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() == Class_ID(Anchor_CLASS_ID1, Anchor_CLASS_ID2))) return FALSE; return TRUE; }
BOOL Validate(PB2Value &v) { INode *node = (INode*) v.r; if (node->TestForLoop(FOREVER,(ReferenceMaker *) mod)!=REF_SUCCEED) return FALSE; ObjectState os = node->EvalWorldState(0); //Allow only tri object derived objects if (os.obj->CanConvertToType(triObjectClassID) && os.obj->SuperClassID() != SHAPE_CLASS_ID) { return TRUE; } return FALSE; };
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; }
void DxStdMtl2::FindLights(INode * parentNode) { TimeValue t = GetCOREInterface()->GetTime(); for(int i=0; i < parentNode->NumberOfChildren(); i++) { INode * node = parentNode->GetChildNode(i); ObjectState Os = node->EvalWorldState(t); if(Os.obj && Os.obj->SuperClassID() == LIGHT_CLASS_ID) { LightCache * lc = new LightCache(this,node); sceneLights.Append(1, &lc); } FindLights(node); } }
INode *CollisionImport::ImportCollisionMesh( const vector<Vector3>& verts, const vector<Triangle>& tris, const vector<Vector3>& norms, Matrix3& tm, INode *parent ) { INode *returnNode = NULL; if ( ImpNode *node = ni.i->CreateNode() ) { TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); Mesh& mesh = triObject->GetMesh(); INode *tnode = node->GetINode(); // Vertex info { int nVertices = verts.size(); mesh.setNumVerts(nVertices); for (int i=0; i < nVertices; ++i){ Vector3 v = verts[i] * ni.bhkScaleFactor; mesh.verts[i].Set(v.x, v.y, v.z); } } // Triangles and texture vertices ni.SetTriangles(mesh, tris); //ni.SetNormals(mesh, tris, norms); MNMesh mn(mesh); mn.Transform(tm); mn.OutToTri(mesh); mesh.checkNormals(TRUE); ni.i->AddNodeToScene(node); returnNode = node->GetINode(); returnNode->EvalWorldState(0); if (parent != NULL) parent->AttachChild(tnode, 1); } return returnNode; }
static void GetSceneLights(Tab<INode*> & lights) { Interface *ip = GetCOREInterface(); TimeValue t = ip->GetTime(); INode * Root = ip->GetRootNode(); int Count = Root->NumberOfChildren(); int i=0; for( i=0; i < Count; i++) { INode * node = Root->GetChildNode(i); ObjectState Os = node->EvalWorldState(t); if(Os.obj && Os.obj->SuperClassID() == LIGHT_CLASS_ID) { lights.Append(1, &node); } } }
BOOL Validate(PB2Value &v) { INode *node = (INode*) v.r; if (node->TestForLoop(FOREVER,(ReferenceMaker *) mod)!=REF_SUCCEED) return FALSE; ObjectState os = node->EvalWorldState(0); //Allow only tri object derived objects if (os.obj->CanConvertToType(triObjectClassID) && os.obj->SuperClassID() != SHAPE_CLASS_ID) { return TRUE; } // and out objects which support the RigidBodyInterface //if (os.obj->SuperClassID() == HELPER_CLASS_ID && NULL != GetInterface(BHKRIGIDBODYINTERFACE_DESC)) { // return TRUE; //} if (os.obj->SuperClassID() == HELPER_CLASS_ID && os.obj->ClassID().PartB() == BHKRIGIDBODYCLASS_DESC.PartB() ) { return TRUE; } return FALSE; };
BOOL ProxSensorObjPick::HitTest(IObjParam *ip, HWND hWnd, ViewExp *vpt, IPoint2 m, int flags) { if ( ! vpt || ! vpt->IsAlive() ) { // why are we here? DbgAssert(!"Doing HitTest() on invalid view port!"); return FALSE; } INode *node = ip->PickNode(hWnd, m); if (node == NULL) return FALSE; Object* obj = node->EvalWorldState(0).obj; if ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() == Class_ID(ProxSensor_CLASS_ID1, ProxSensor_CLASS_ID2))) return FALSE; return TRUE; }
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; }
static SClass_ID GetNodeType(INode *node) { TimeValue t = GetCOREInterface()->GetTime(); ObjectState os = node->EvalWorldState( t, FALSE); if (os.obj) { SClass_ID id = os.obj->SuperClassID(); // if (node->IsTarget()) { if (node->IsTarget() && node->GetLookatNode() && node->GetLookatNode()->Selected()) { INode* depNode = node->GetLookatNode(); if (depNode) { ObjectState osc = depNode->EvalWorldState(t,FALSE); return osc.obj->SuperClassID(); } else return SClass_ID(0); } else return id; } else return SClass_ID(0); }
int SceneEnumProc::callback(INode *node) { char line[1024]; Object *obj = node->EvalWorldState(time).obj; strcpy(line, node->GetName()); //if(strstr(line, "Bip") != NULL) { sprintf(line, "%08X %08X", obj->SuperClassID(), obj->ClassID()); // MessageBox(NULL, line, node->GetName(), MB_OK); } if( (obj->SuperClassID() == GEOMOBJECT_CLASS_ID) && (obj->ClassID() == Class_ID(BIP_BONE_CLASS_ID, 0)) ) { Append(node, obj, OBTYPE_BONE); return TREE_CONTINUE; } if (obj->CanConvertToType(triObjectClassID)) { Append(node, obj, OBTYPE_MESH); return TREE_CONTINUE; } if (node->IsTarget()) { INode* ln = node->GetLookatNode(); if (ln) { Object *lobj = ln->EvalWorldState(time).obj; switch(lobj->SuperClassID()) { case LIGHT_CLASS_ID: Append(node, obj, OBTYPE_LTARGET); break; case CAMERA_CLASS_ID: Append(node, obj, OBTYPE_CTARGET); break; } } return TREE_CONTINUE; } switch (obj->SuperClassID()) { case HELPER_CLASS_ID: if ( obj->ClassID()==Class_ID(DUMMY_CLASS_ID,0)) Append(node, obj, OBTYPE_DUMMY); if(obj->ClassID() == Class_ID(BONE_CLASS_ID,0)) Append(node, obj, OBTYPE_BONE); break; case LIGHT_CLASS_ID: if (obj->ClassID()==Class_ID(OMNI_LIGHT_CLASS_ID,0)) Append(node, obj, OBTYPE_OMNILIGHT); else if (obj->ClassID()==Class_ID(SPOT_LIGHT_CLASS_ID,0)) Append(node, obj, OBTYPE_SPOTLIGHT); //export DIR_LIGHT and FSPOT_LIGHT???? break; case CAMERA_CLASS_ID: if (obj->ClassID()==Class_ID(LOOKAT_CAM_CLASS_ID,0)) Append(node, obj, OBTYPE_CAMERA); break; } return TREE_CONTINUE; // Keep on enumeratin'! }
int Blockporter::DoExport(const TCHAR* name, ExpInterface* ei, Interface* i, BOOL supressPrompts, DWORD options) { INode* root; //caption and message for MessagesBoxes TCHAR msg[MB_BUFFER_LENGTH]; TCHAR cap[MB_BUFFER_LENGTH]; //Get the root node root = i->GetRootNode(); //the node of our object should be a groupnode, which contains every object //we want to export i->PushPrompt(_T("Searching for Group...")); bool found = false; for(int idx = 0; idx < root->NumberOfChildren(); idx++) { if(root->GetChildNode(idx)->IsGroupHead()) { //we found our group //next step is to make the group node our new root, because every object //we want is part of this group found = true; root = root->GetChildNode(idx); break; } } if(!found) { MessageBox(nullptr, GetString(IDS_ERROR_NO_GROUP, msg), GetString(IDS_GENERAL_ERROR, cap), MB_OK | MB_ICONERROR); return 0; } //Now that we have the groupnode let's compare the fileversions if(!IsNewModelVersion(name, root->GetName())) { if(MessageBox(nullptr, GetString(IDS_VER_TO_LOW_MSG, msg), GetString(IDS_VER_TO_LOW_CAP, cap), MB_YESNO | MB_ICONEXCLAMATION) == IDNO) return 1; } i->PushPrompt(_T("Opening File")); Interface14* iface = GetCOREInterface14(); UINT code = iface->DefaultTextSaveCodePage(true); MaxSDK::Util::Path storageNamePath(name); storageNamePath.SaveBaseFile(); switch (code & MaxSDK::Util::MaxStringDataEncoding::MSDE_CP_MASK) { case CP_UTF8: mStream = _tfopen(name, _T("wt, ccs=UFT-8")); break; case MaxSDK::Util::MaxStringDataEncoding::MSDE_CP_UTF16: mStream = _tfopen(name, _T("wt, ccs=UTF-16BE")); break; default: mStream = _tfopen(name, _T("wt")); } if(!mStream) return 0; //now we have our file stream, so let's write the header i->PushPrompt(_T("Writing Header")); WriteHeader(root->GetName(), root->NumberOfChildren()); //now that we have the header written, let's iterate through the objects in the //group and export the meshes and lights INode* child; Point3 pMin(0,0,0), pMax(0,0,0); for(int idx = 0; idx < root->NumberOfChildren(); idx++) { child = root->GetChildNode(idx); i->PushPrompt(_T("Processing Object %s", child->GetName())); if(child->IsGroupHead()) { MessageBox(nullptr, GetString(IDS_ERROR_TO_MANY_GROUPS, msg), GetString(IDS_GENERAL_ERROR, cap), MB_OK | MB_ICONERROR); continue; } ObjectState os = child->EvalWorldState(0); //let's take a look at the SuperClassID of the object //so we find out if it's a mesh or a light if(!os.obj) continue; //somehow this node doesn't have an object Box3 boundBox; switch(os.obj->SuperClassID()) { case GEOMOBJECT_CLASS_ID: _ftprintf(mStream, _T("<ObjectID=%i>\n"), idx); i->PushPrompt(_T("Writing MeshData for Object %s", child->GetName())); boundBox = WriteMeshData(child, idx); pMin.x = (boundBox.Min().x < pMin.x) ? boundBox.Min().x : pMin.x; pMin.y = (boundBox.Min().y < pMin.y) ? boundBox.Min().y : pMin.y; pMax.x = (boundBox.Max().x > pMax.x) ? boundBox.Max().x : pMax.x; pMax.y = (boundBox.Max().y > pMax.y) ? boundBox.Max().y : pMax.y; i->PushPrompt(_T("Writing MaterialData for Object %s", child->GetName())); WriteMaterialData(child); _ftprintf(mStream, _T("</Object>\n")); break; //case LIGHT_CLASS_ID: // WriteLightData(child, idx); // break; } } //Write the Bounding Box _ftprintf(mStream, _T("<BoundingBox>\n")); _ftprintf(mStream, _T("\t<Min=%f,%f>\n"), pMin.x, pMin.y); _ftprintf(mStream, _T("\t<Max=%f,%f>\n"), pMax.x, pMax.y); _ftprintf(mStream, _T("</BoundingBox>\n")); //we are done exporting, so close the stream i->PushPrompt(_T("Closing file...")); fclose(mStream); MessageBox(nullptr, GetString(IDS_FINISH_MSG, msg), GetString(IDS_FINISH_CAP, cap), MB_OK | MB_ICONINFORMATION); return 1; }
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 SolidifyPW::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //TODO: Add the code for actually modifying the object meshInfo.Free(); if (os->obj->IsSubClassOf(triObjectClassID)) { TriObject *tobj = (TriObject*)os->obj; Mesh &mesh = tobj->GetMesh(); Interval iv = FOREVER; float a,oa; pblock->GetValue(pb_amount,t,a,iv); pblock->GetValue(pb_oamount,t,oa,iv); if (a == oa) oa += 0.00001f; BOOL overrideMatID; int matid; pblock->GetValue(pb_overridematid,t,overrideMatID,iv); pblock->GetValue(pb_matid,t,matid,iv); matid--; if (!overrideMatID) matid = -1; BOOL overridesg; int sg; pblock->GetValue(pb_overridesg,t,overridesg,iv); pblock->GetValue(pb_sg,t,sg,iv); if (!overridesg) sg = -1; int edgeMap; pblock->GetValue(pb_edgemap,t,edgeMap,iv); float tvOffset; pblock->GetValue(pb_tvoffset,t,tvOffset,iv); BOOL ioverrideMatID; int imatid; pblock->GetValue(pb_overrideinnermatid,t,ioverrideMatID,iv); pblock->GetValue(pb_innermatid,t,imatid,iv); imatid--; if (!ioverrideMatID) imatid = -1; BOOL ooverrideMatID; int omatid; pblock->GetValue(pb_overrideoutermatid,t,ooverrideMatID,iv); pblock->GetValue(pb_outermatid,t,omatid,iv); omatid--; if (!ooverrideMatID) omatid = -1; BOOL selEdges, selInner,selOuter; static BOOL selEdgesPrev = FALSE; static BOOL selInnerPrev = FALSE; static BOOL selOuterPrev = FALSE; BOOL updateUI = FALSE; pblock->GetValue(pb_seledges,t,selEdges,iv); pblock->GetValue(pb_selinner,t,selInner,iv); pblock->GetValue(pb_selouter,t,selOuter,iv); if (selEdges && (!selEdgesPrev)) updateUI = TRUE; if (selInner && (!selInnerPrev)) updateUI = TRUE; if (selOuter && (!selOuterPrev)) updateUI = TRUE; selEdgesPrev = selEdges; selInnerPrev = selInner; selOuterPrev = selOuter; if (selEdges || selInner|| selOuter) { mesh.dispFlags = DISP_SELFACES; mesh.selLevel = MESH_FACE; } int segments = 1; pblock->GetValue(pb_segments,t,segments,iv); if (segments < 1) segments = 1; BOOL fixupCorners; pblock->GetValue(pb_fixupcorners,t,fixupCorners,iv); BOOL autoSmooth; float smoothAngle; pblock->GetValue(pb_autosmooth,t,autoSmooth,iv); pblock->GetValue(pb_autosmoothangle,t,smoothAngle,iv); BOOL bevel; INode *node; pblock->GetValue(pb_bevel,t,bevel,iv); pblock->GetValue(pb_bevelshape,t,node,iv); PolyShape shape; if ((bevel) && node) { ObjectState nos = node->EvalWorldState(t); if (nos.obj->IsShapeObject()) { ShapeObject *pathOb = (ShapeObject*)nos.obj; if (!pathOb->NumberOfCurves()) { bevel = FALSE; } else { pathOb->MakePolyShape(t, shape,PSHAPE_BUILTIN_STEPS,TRUE); if (shape.lines[0].IsClosed()) bevel = FALSE; ; } } } DWORD selLevel = mesh.selLevel; mesh.faceSel.ClearAll(); if (bevel) meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,&shape.lines[0]); else meshInfo.MakeSolid(&mesh,segments, a,oa,matid, sg,edgeMap,tvOffset,imatid,omatid,selEdges,selInner,selOuter,fixupCorners,autoSmooth,smoothAngle,NULL); mesh.selLevel = selLevel; mesh.InvalidateTopologyCache (); for (int i = 0; i < mesh.numFaces; i++) { for (int j = 0; j < 3; j++) { int index = mesh.faces[j].v[j]; if ((index < 0) || (index >= mesh.numVerts)) DebugPrint(_T("Invalid face %d(%d) %d\n"),i,j,index); } } int numMaps = mesh.getNumMaps(); for (int mp = -NUM_HIDDENMAPS; mp < numMaps; mp++) { if (!mesh.mapSupport(mp)) continue; Point3 *uvw = mesh.mapVerts(mp); TVFace *uvwFace = mesh.mapFaces(mp); if ((uvw) && (uvwFace)) { int numberTVVerts = mesh.getNumMapVerts(mp); for (int i = 0; i < mesh.numFaces; i++) { for (int j = 0; j < 3; j++) { int index = uvwFace[i].t[j]; if ((index < 0) || (index >= numberTVVerts)) DebugPrint(_T("Invalid Map %d tvface %d(%d) %d\n"),mp,i,j,index); } } } } os->obj->UpdateValidity(GEOM_CHAN_NUM,iv); os->obj->UpdateValidity(TOPO_CHAN_NUM,iv); MeshNormalSpec *pNormSpec = (MeshNormalSpec *) mesh.GetInterface (MESH_NORMAL_SPEC_INTERFACE); if (pNormSpec && pNormSpec->GetNumFaces() > 0) { pNormSpec->SetParent(&mesh); pNormSpec->BuildNormals(); pNormSpec->ComputeNormals(); } if ((updateUI) && (ip)) { ip->PipeSelLevelChanged(); } } EnableUIControls(); }
bool NifImporter::ImportMesh(ImpNode *node, TriObject *o, NiTriBasedGeomRef triGeom, NiTriBasedGeomDataRef triGeomData, vector<Triangle>& tris) { Mesh& mesh = o->GetMesh(); INode *tnode = node->GetINode(); Matrix44 baseTM = (importBones) ? triGeom->GetLocalTransform() : triGeom->GetWorldTransform(); node->SetTransform(0,TOMATRIX3(baseTM)); // Vertex info { int nVertices = triGeomData->GetVertexCount(); vector<Vector3> vertices = triGeomData->GetVertices(); mesh.setNumVerts(nVertices); for (int i=0; i < nVertices; ++i){ Vector3 &v = vertices[i]; mesh.verts[i].Set(v.x, v.y, v.z); } } // uv texture info { int nUVSet = triGeomData->GetUVSetCount(); mesh.setNumMaps(nUVSet + 1, TRUE); int n = 0, j = 0; for (int j=0; j<nUVSet; j++){ vector<TexCoord> texCoords = triGeomData->GetUVSet(j); n = texCoords.size(); if (j == 0) { mesh.setNumTVerts(n, TRUE); for (int i=0; i<n; ++i) { TexCoord& texCoord = texCoords[i]; mesh.tVerts[i].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } mesh.setMapSupport (j + 1, TRUE); mesh.setNumMapVerts(j + 1, n, TRUE); if ( UVVert *tVerts = mesh.mapVerts(j+1) ) { for (int i=0; i<n; ++i) { TexCoord& texCoord = texCoords[i]; tVerts[i].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } } } // Triangles and texture vertices SetTriangles(mesh, tris); SetNormals(mesh, tris, triGeomData->GetNormals() ); vector<Color4> cv = triGeomData->GetColors(); ImportVertexColor(tnode, o, tris, cv, 0); if (Mtl* m = ImportMaterialAndTextures(node, triGeom)) { gi->GetMaterialLibrary().Add(m); node->GetINode()->SetMtl(m); } if (removeDegenerateFaces) mesh.RemoveDegenerateFaces(); if (removeIllegalFaces) mesh.RemoveIllegalFaces(); if (enableSkinSupport) ImportSkin(node, triGeom); if (weldVertices) WeldVertices(mesh); i->AddNodeToScene(node); INode *inode = node->GetINode(); inode->EvalWorldState(0); // attach child if (INode *parent = GetNode(triGeom->GetParent())) parent->AttachChild(inode, 1); inode->Hide(triGeom->GetVisibility() ? FALSE : TRUE); if (enableAutoSmooth){ mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE); } RegisterNode(triGeom, inode); return true; }
bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom, int v_start/*=0*/) { bool ok = true; NiSkinInstanceRef nifSkin = triGeom->GetSkinInstance(); if (!nifSkin) return false; INode *tnode = node->GetINode(); NiSkinDataRef data = nifSkin->GetSkinData(); NiSkinPartitionRef part = nifSkin->GetSkinPartition(); vector<NiNodeRef> nifBones = nifSkin->GetBones(); //create a skin modifier and add it Modifier *skinMod = GetOrCreateSkin(tnode); TriObject *triObject = GetTriObject(tnode->GetObjectRef()); Mesh& m = triObject->GetMesh(); //get the skin interface if (ISkin *skin = (ISkin *) skinMod->GetInterface(I_SKIN)){ ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA); // Set the num weights to 4. Yes its in the nif but Shon doesn't like to expose those values // and the value always seems to be 4 anyway. I'd also this be more dynamic than hard coded numbers // but I cant figure out the correct values to pass the scripting engine from here so I'm giving up. int numWeightsPerVertex = 4; #if VERSION_3DSMAX >= ((5000<<16)+(15<<8)+0) // Version 5+ IParamBlock2 *params = skinMod->GetParamBlockByID(2/*advanced*/); params->SetValue(0x7/*bone_Limit*/, 0, numWeightsPerVertex); #endif // Can get some truly bizarre animations without this in MAX with Civ4 Leaderheads #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+ BOOL ignore = TRUE; params->SetValue(0xE/*ignoreBoneScale*/, 0, ignore); #endif //RefTargetHandle advanced = skinMod->GetReference(3); //setMAXScriptValue(advanced, "bone_Limit", 0, numWeightsPerVertex); Matrix3 geom = TOMATRIX3(triGeom->GetLocalTransform()); Matrix3 m3 = TOMATRIX3(data->GetOverallTransform()); Matrix3 im3 = Inverse(m3); Matrix3 nm3 = im3 * geom; iskinImport->SetSkinTm(tnode, nm3, nm3); // ??? // Create Bone List Tab<INode*> bones; for (size_t i=0; i<nifBones.size(); ++i){ NiNodeRef bone = nifBones[i]; if (INode *boneRef = FindNode(bone)) { bones.Append(1, &boneRef); iskinImport->AddBoneEx(boneRef, TRUE); //// Set Bone Transform Matrix3 b3 = TOMATRIX3(data->GetBoneTransform(i)); Matrix3 ib3 = Inverse(b3); ib3 *= geom; iskinImport->SetBoneTm(boneRef, ib3, ib3); } } if (bones.Count() != data->GetBoneCount()) return false; ObjectState os = tnode->EvalWorldState(0); // Need to get a list of bones and weights for each vertex. vector<VertexHolder> vertexHolders; vertexHolders.resize(m.numVerts); for (int i=0, n=data->GetBoneCount();i<n; ++i){ if (INode *boneRef = bones[i]){ vector<SkinWeight> weights = data->GetBoneWeights(i); for (vector<SkinWeight>::iterator itr=weights.begin(), end=weights.end(); itr != end; ++itr){ VertexHolder& h = vertexHolders[itr->index]; h.vertIndex = itr->index; ++h.count; h.weights.Append(1, &itr->weight); h.boneNodeList.Append(1, &boneRef); } } } tnode->EvalWorldState(0); skinMod->DisableModInViews(); skinMod->EnableModInViews(); #if VERSION_3DSMAX < ((5000<<16)+(15<<8)+0) // Version 4 gi->SetCommandPanelTaskMode(TASK_MODE_MODIFY); gi->SelectNode(tnode); #endif // Assign the weights for (vector<VertexHolder>::iterator itr=vertexHolders.begin(), end=vertexHolders.end(); itr != end; ++itr){ VertexHolder& h = (*itr); if (h.count){ float sum = 0.0f; for (int i = 0; i < h.count; ++i) sum += h.weights[i]; ASSERT(fabs(sum-1.0f) < 0.001f); BOOL add = iskinImport->AddWeights(tnode, h.vertIndex, h.boneNodeList, h.weights); add = add; // What was the purpose of this? } } // This is a kludge to get skin transforms to update and avoid jumping around after modifying the transforms. // Initially they show up incorrectly but magically fix up if you go to the modifier roll up. // There is still an outstanding issue with skeleton and GetObjectTMBeforeWSM. skinMod->DisableModInViews(); skinMod->EnableModInViews(); // If BSDismembermentSkinInstance, ... if ( BSDismemberSkinInstanceRef bsdsi = DynamicCast<BSDismemberSkinInstance>(nifSkin) ) { Modifier *dismemberSkinMod = GetOrCreateBSDismemberSkin(tnode); if (IBSDismemberSkinModifier *disSkin = (IBSDismemberSkinModifier *) dismemberSkinMod->GetInterface(I_BSDISMEMBERSKINMODIFIER)){ // Evaluate node ensure the modifier data is created // ObjectState os = tnode->EvalWorldState(0); FaceMap faceMap; int nfaces = m.getNumFaces(); for ( int i=0; i<nfaces; ++i ){ Face f = m.faces[i]; faceMap[ rotate(f) ] = i; } Tab<IBSDismemberSkinModifierData*> modData = disSkin->GetModifierData(); for (int i=0; i<modData.Count(); ++i) { IBSDismemberSkinModifierData* bsdsmd = modData[i]; Tab<BSDSPartitionData> &flags = bsdsmd->GetPartitionFlags(); vector<BodyPartList> partitions = bsdsi->GetPartitions(); if (partitions.empty()) continue; //bsdsmd->SetActivePartition( partitions.size() - 1 ); // Old Code for (unsigned int j = 0; j < (partitions.size() - 1); ++j){ bsdsmd->AddPartition(); } for (unsigned int j=0; j < partitions.size(); ++j ) { flags[j].bodyPart = (DismemberBodyPartType)partitions[j].bodyPart; flags[j].partFlag = partitions[j].partFlag; } for (int j=0; j < part->GetNumPartitions(); ++j) { bsdsmd->SetActivePartition( j ); dismemberSkinMod->SelectAll(3); // ensures bitarrays are properly synced to mesh dismemberSkinMod->ClearSelection(3); vector<Triangle> triangles = part->GetTriangles(j); vector<unsigned short> map = part->GetVertexMap(j); GenericNamedSelSetList& fselSet = bsdsmd->GetFaceSelList(); if ( BitArray* fsel = fselSet.GetSetByIndex(j) ) { for (vector<Triangle>::iterator itrtri = triangles.begin(); itrtri != triangles.end(); ++itrtri) { Face f; f.setVerts( map[(*itrtri).v1], map[(*itrtri).v2], map[(*itrtri).v3] ); FaceMap::iterator fitr = faceMap.find( rotate(f) ); if (fitr != faceMap.end()) fsel->Set((*fitr).second); } } } bsdsmd->SetActivePartition( 0 ); disSkin->LocalDataChanged(); } } } } return ok; }
bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeomRef>& glist) { bool ok = true; if (glist.empty()) return false; ImpNode *node = i->CreateNode(); if(!node) return false; INode *inode = node->GetINode(); TriObject *triObject = CreateNewTriObject(); node->Reference(triObject); string name = parent->GetName(); node->SetName(wide(name).c_str()); // Texture Mesh& mesh = triObject->GetMesh(); vector< pair<int, int> > vert_range, tri_range; vector<Triangle> tris; vector<Vector3> verts; int submats = glist.size(); // Build list of vertices and triangles. Optional components like normals will be handled later. for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); // Get verts and collapse local transform into them int nVertices = triGeomData->GetVertexCount(); vector<Vector3> subverts = triGeomData->GetVertices(); Matrix44 transform = (*itr)->GetLocalTransform(); //Apply the transformations if (transform != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subverts.size(); ++i ) subverts[i] = transform * subverts[i]; } vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) ); verts.insert(verts.end(), subverts.begin(), subverts.end()); vector<Triangle> subtris = triGeomData->GetTriangles(); for (vector<Triangle>::iterator itr = subtris.begin(), end = subtris.end(); itr != end; ++itr) { (*itr).v1 += nVertices, (*itr).v2 += nVertices, (*itr).v3 += nVertices; } tri_range.push_back( pair<int,int>( tris.size(), tris.size() + subtris.size()) ); tris.insert(tris.end(), subtris.begin(), subtris.end()); } // Transform up-to-parent Matrix44 baseTM = (importBones) ? Matrix44::IDENTITY : parent->GetWorldTransform(); node->SetTransform(0,TOMATRIX3(baseTM)); // Set vertices and triangles mesh.setNumVerts(verts.size()); mesh.setNumTVerts(verts.size(), TRUE); for (int i=0, n=verts.size(); i < n; ++i){ Vector3 &v = verts[i]; mesh.verts[i].Set(v.x, v.y, v.z); } mesh.setNumFaces(tris.size()); mesh.setNumTVFaces(tris.size()); for (int submat=0; submat<submats; ++submat) { int t_start = tri_range[submat].first, t_end = tri_range[submat].second; for (int i=t_start; i<t_end; ++i) { Triangle& t = tris[i]; Face& f = mesh.faces[i]; f.setVerts(t.v1, t.v2, t.v3); f.Show(); f.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); f.setMatID(-1); TVFace& tf = mesh.tvFace[i]; tf.setTVerts(t.v1, t.v2, t.v3); } } mesh.buildNormals(); bool bSpecNorms = false; MultiMtl *mtl = NULL; int igeom = 0; for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr, ++igeom) { NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData()); int v_start = vert_range[igeom].first, v_end = vert_range[igeom].second; int t_start = tri_range[igeom].first, t_end = tri_range[igeom].second; // Normals vector<Vector3> subnorms = triGeomData->GetNormals(); Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation(); if (rotation != Matrix44::IDENTITY) { for ( unsigned int i = 0; i < subnorms.size(); ++i ) subnorms[i] = rotation * subnorms[i]; } if (!subnorms.empty()) { #if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5 // Initialize normals if necessary if (!bSpecNorms) { bSpecNorms = true; mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { specNorms->BuildNormals(); //specNorms->ClearAndFree(); //specNorms->SetNumFaces(tris.size()); //specNorms->SetNumNormals(n.size()); } } MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (NULL != specNorms) { Point3* norms = specNorms->GetNormalArray(); for (int i=0, n=subnorms.size(); i<n; i++){ Vector3& v = subnorms[i]; norms[i+v_start] = Point3(v.x, v.y, v.z); } //MeshNormalFace* pFaces = specNorms->GetFaceArray(); //for (int i=0; i<tris.size(); i++){ // Triangle& tri = tris[i]; // MeshNormalFace& face = pFaces[i+t_start]; // face.SpecifyNormalID(0, tri.v1); // face.SpecifyNormalID(1, tri.v2); // face.SpecifyNormalID(2, tri.v3); //} #if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+ specNorms->SetAllExplicit(true); #endif specNorms->CheckNormals(); } #endif } // uv texture info if (triGeomData->GetUVSetCount() > 0) { vector<TexCoord> texCoords = triGeomData->GetUVSet(0); for (int i=0, n = texCoords.size(); i<n; ++i) { TexCoord& texCoord = texCoords[i]; mesh.tVerts[i+v_start].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0); } } vector<Color4> cv = triGeomData->GetColors(); ImportVertexColor(inode, triObject, tris, cv, v_start); if ( StdMat2* submtl = ImportMaterialAndTextures(node, (*itr)) ) { if (mtl == NULL) { mtl = NewDefaultMultiMtl(); gi->GetMaterialLibrary().Add(mtl); inode->SetMtl(mtl); } // SubMatIDs do not have to be contiguous so we just use the offset mtl->SetSubMtlAndName(igeom, submtl, submtl->GetName()); for (int i=t_start; i<t_end; ++i) mesh.faces[i].setMatID(igeom); } if (enableSkinSupport) ImportSkin(node, (*itr)); } this->i->AddNodeToScene(node); inode = node->GetINode(); inode->EvalWorldState(0); for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) { // attach child if (INode *parent = GetNode((*itr)->GetParent())) parent->AttachChild(inode, 1); inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE); } if (removeDegenerateFaces) mesh.RemoveDegenerateFaces(); if (removeIllegalFaces) mesh.RemoveIllegalFaces(); if (weldVertices) WeldVertices(mesh); if (enableAutoSmooth) mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE); return ok; }
void MaxAWDExporter::ProcessGeoBlocks() { AWDTriGeom *geoBlock; AWDBlockIterator *it; int proccessed=0; it = new AWDBlockIterator(awd->get_mesh_data_blocks()); UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks()); INodeTab lNodes; while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){ INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock); if (node==NULL){ AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry."); awd->get_message_blocks()->append(newWarning); return; } lNodes.AppendNode( node ); } IGameScene* _pIgame = NULL; _pIgame = GetIGameInterface(); _pIgame->InitialiseIGame( lNodes ); it->reset(); while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){ INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock); if (node==NULL){ AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry."); awd->get_message_blocks()->append(newWarning); } else{ int exportThis=false; IGameObject * gobj = NULL; IGameMesh * igame_mesh = NULL; gobj = GetIGameInterface()->GetIGameNode(node)->GetIGameObject(); if(gobj->GetIGameType()==IGameObject::IGAME_MESH){ igame_mesh = (IGameMesh*)gobj; if (igame_mesh!=NULL){ igame_mesh->InitializeData(); if(igame_mesh->GetNumberOfFaces()>0){ exportThis=true; } } } if (exportThis){ Object *obj; obj = node->GetObjectRef(); int skinIdx; ObjectState os; IDerivedObject *derivedObject = NULL; skinIdx = IndexOfSkinMod(node->GetObjectRef(), &derivedObject); if (skinIdx >= 0) { // Flatten all modifiers up to but not including // the skin modifier. // to do: get the correct time for the neutral-pose os = derivedObject->Eval(0, skinIdx + 1); } else { // Flatten entire modifier stack // to do: get the correct time for the neutral-pose os = node->EvalWorldState(maxInterface->GetTime()); } obj = os.obj; ISkin *skin = NULL; if (derivedObject != NULL && skinIdx >= 0) { Modifier *mod = derivedObject->GetModifier(skinIdx); skin = (ISkin *)mod->GetInterface(I_SKIN); } ExportTriGeom(geoBlock,obj,node,skin, igame_mesh); RETURN_IF_ERROR; } } proccessed++; UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks()); } delete it; _pIgame->ReleaseIGame(); }
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 WMOGroupImpl::buildMaxData() { // Group Header Node INode* groupHeadNode = createGroupHeaderNode(); groupHeadNode->SetGroupHead(TRUE); groupHeadNode->SetGroupMember(FALSE); // Geoset // 一个Render Batch构造一个Node, 并且加入到组中 for (int i = 0; i < m_batchCount; ++i) { WMORenderBatch& renderBatch = m_batchData[i]; m_wmoImporter->m_logStream << "Model Geoset " << i << " Vertex Info: " << renderBatch.vertexStart << " -- " << renderBatch.vertexEnd << endl; m_wmoImporter->m_logStream << "Model Geoset " << i << " Index Info: " << renderBatch.indexStart << " -- " << renderBatch.indexCount << endl; // Triangle Mesh Object // 基本的三角形模型对象 TriObject* triObject = CreateNewTriObject(); // 创建Node, 并且设为Group Header Node的子节点 ImpNode* tmpImpNode = m_wmoImporter->m_impInterface->CreateNode(); tmpImpNode->Reference(triObject); m_wmoImporter->m_impInterface->AddNodeToScene(tmpImpNode); INode* realINode = tmpImpNode->GetINode(); realINode->SetGroupHead(FALSE); realINode->SetGroupMember(TRUE); groupHeadNode->AttachChild(realINode); m_geosetNodeList.push_back(realINode); TCHAR nodeName[256]; sprintf(nodeName, "%s_part_%03d", m_groupName.c_str(), i); realINode->SetName(nodeName); // mesh unsigned short vertexCount = renderBatch.vertexEnd - renderBatch.vertexStart + 1; unsigned int trigangleCount = renderBatch.indexCount / 3; Mesh& mesh = triObject->GetMesh(); mesh.setNumVerts(vertexCount); mesh.setNumTVerts(vertexCount, TRUE); mesh.setNumFaces(trigangleCount); mesh.setNumTVFaces(trigangleCount); // 顶点坐标和UV for (int i = 0; i < vertexCount; ++i) { mesh.verts[i] = *(Point3*)(&(m_vertexData[renderBatch.vertexStart + i])); // UV坐标反转 mesh.tVerts[i].x = m_textureCoords[renderBatch.vertexStart + i].x; mesh.tVerts[i].y = 1.0f - m_textureCoords[renderBatch.vertexStart + i].y; } // 三角形 for (unsigned int i = 0; i < trigangleCount; ++i) { Face& face = mesh.faces[i]; int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart; int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart; int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart; face.setVerts(index1, index2, index3); face.Show(); face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS); TVFace& tface = mesh.tvFace[i]; tface.setTVerts(index1, index2, index3); } // 法线 mesh.SpecifyNormals(); MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals(); if (specNorms) { specNorms->ClearAndFree(); specNorms->SetNumFaces(trigangleCount); specNorms->SetNumNormals(vertexCount); Point3* norms = specNorms->GetNormalArray(); for (int i = 0; i < vertexCount; ++i) { norms[i] = *(Point3*)(&m_normalData[renderBatch.vertexStart + i]); } MeshNormalFace* pFaces = specNorms->GetFaceArray(); for (unsigned int i = 0; i < trigangleCount; ++i) { int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart; int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart; int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart; pFaces[i].SpecifyNormalID(0, index1); pFaces[i].SpecifyNormalID(1, index2); pFaces[i].SpecifyNormalID(2, index3); } specNorms->SetAllExplicit(true); specNorms->CheckNormals(); } // 删除重复的和无效的面 mesh.RemoveDegenerateFaces(); mesh.RemoveIllegalFaces(); realINode->SetMtl(m_wmoImporter->m_materialList[renderBatch.texture]); //realINode->BackCull(FALSE); // 取消背面裁减 不是所有的Node都要取消背面裁减 realINode->EvalWorldState(0); } }
void ParticleMesherObject::PickPFEvents(HWND hWnd) { Tab<INode *> pfEvents; int numberOfNodes = 1;; TimeValue t = GetCOREInterface()->GetTime(); pfNodes.ZeroCount(); addPFNodes.ZeroCount(); for (int i = 0; i < numberOfNodes; i++) { INode *node; pblock2->GetValue(particlemesher_pick,t,node,ivalid,i); if (node) { ObjectState tos = node->EvalWorldState(t,TRUE); if (tos.obj->IsParticleSystem()) { IParticleObjectExt* epobj; epobj = (IParticleObjectExt*) tos.obj->GetInterface(PARTICLEOBJECTEXT_INTERFACE); if (epobj) { MyEnumProc dep; tos.obj->DoEnumDependents(&dep); for (int i = 0; i < dep.Nodes.Count(); i++) { Interval valid; INode *node = dep.Nodes[i]; Object *obj = node->GetObjectRef(); IParticleGroup* iPGroup = ParticleGroupInterface(obj); if (iPGroup != nullptr) { // we need to filter out the global action list events since // they do not carry any actual particle shape geometry if (iPGroup->GetParticleSystem() != iPGroup->GetActionList()) { pfNodes.Append(1, &node); } } } } } } } if (pfNodes.Count() > 0) { int iret = DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ADD_DIALOG), hWnd,AddDlgProc,(LPARAM)this); if ((iret) && (addPFNodes.Count() > 0)) { theHold.Begin(); for (int i = 0; i < addPFNodes.Count(); i++) { int index = addPFNodes[i]; INode *node = pfNodes[index]; pblock2->Append(particlemesher_pfeventlist,1,&node); } theHold.Accept(GetString(IDS_ADDEVENTS)); } } }