INode* PatchDeformPW::GetNodeFromModContext(LocalPatchData *smd) { int i; PatchEnumProc dep; DoEnumDependents(&dep); for ( i = 0; i < dep.Nodes.Count(); i++) { INode *node = dep.Nodes[i]; BOOL found = FALSE; if (node) { Object* obj = node->GetObjectRef(); if ( RecursePipeAndMatch(smd,obj) ) { return node; } // look at the SkinWrapMesh.cpp code here.... } } return NULL; }
static INode *FindObjectsNode(ReferenceTarget *ths, Object *obj) { if (NULL == ths) { return NULL; } DependentIterator di(ths); ReferenceMaker* maker = NULL; while ((maker = di.Next()) != NULL) { if (maker->SuperClassID()==BASENODE_CLASS_ID) { // Verify that we are this node's object INode *node = (INode*)maker; Object *nobj = node->GetObjectRef(); if (nobj) nobj = nobj->FindBaseObject(); if (nobj==obj) return (INode*)maker; } if (maker->IsRefTarget()) { INode *node = FindObjectsNode((ReferenceTarget*)maker, obj); if (node) return node; } } return NULL; }
static void DoNotifyNodeUnHide(void *param, NotifyInfo *info) { int code = info->intcode; INode *node = (INode*)info->callParam; if (Object* obj = node->GetObjectRef()) { // Look for messages in network\Max.log // MAXScript_interface->Log()->LogEntry(SYSLOG_DEBUG, NO_DIALOG, "NifTools Max Plugin", // "Entered DoNotifyNodeUnHide; node is -%s- and class ID is %ld\n", node->GetName(), obj->ClassID().PartA()); if (obj->ClassID() == BHKLISTOBJECT_CLASS_ID) { const int PB_MESHLIST = 1; IParamBlock2* pblock2 = obj->GetParamBlockByID(0); int nBlocks = pblock2->Count(PB_MESHLIST); for (int i = 0;i < pblock2->Count(PB_MESHLIST); i++) { INode *tnode = nullptr; pblock2->GetValue(PB_MESHLIST,0,tnode,FOREVER,i); if (tnode != nullptr) { tnode->Hide(FALSE); } } } } }
void PolyOpExtrudeAlongSpline::GetValues (IParamBlock2 *pblock, TimeValue t, Interval & ivalid) { PolyOperation::GetValues (pblock, t, ivalid); // Special case for the spline & transform. if (!mSplineValidity.InInterval (t)) { mSplineValidity.SetInfinite (); INode *pSplineNode; pblock->GetValue (kEPExtrudeSpline, t, pSplineNode, mSplineValidity); if (pSplineNode == NULL) mpSpline = NULL; else { bool del = FALSE; SplineShape *pSplineShape = NULL; ObjectState os = pSplineNode->GetObjectRef()->Eval(t); if (os.obj->IsSubClassOf(splineShapeClassID)) pSplineShape = (SplineShape *) os.obj; else { if (!os.obj->CanConvertToType(splineShapeClassID)) return; pSplineShape = (SplineShape*)os.obj->ConvertToType (t, splineShapeClassID); if (pSplineShape!=os.obj) del = TRUE; } BezierShape & bezShape = pSplineShape->GetShape(); Matrix3 mSplineXfm = pSplineNode->GetObjectTM (t, &mSplineValidity); if (mpSpline != NULL) delete mpSpline; mpSpline = new Spline3D(*bezShape.GetSpline(0)); if (del) delete pSplineShape; } } ivalid &= mSplineValidity; }
void CreateMorphMode::Begin(INode *n,IObjParam *i) { ReplaceReference(0,n); svNode = node; assert(node); ip = i; proc.Init(ip); theHold.Begin(); theHold.Put(new CreateMorphRestore); obj = new MorphObject; theHold.Put(new CreateMorphNotify(obj,1)); TSTR name = TSTR(_T("M_")) + node->GetName(); SetMorphTargetPacket pckt(node->GetObjectRef(),name); obj->morphCont->SetValue(0,&pckt); node->SetObjectRef(obj); theHold.Put(new CreateMorphNotify(obj,0)); theHold.Accept(IDS_DS_CREATE); obj->BeginEditParams(i,BEGIN_EDIT_CREATE,NULL); }
BOOL Validate(PB2Value &v) { INode *node = (INode*) v.r; Object *obj = node->GetObjectRef(); if (obj->ClassID() != DELEG_CLASSID) return FALSE; return TRUE; };
void AlembicImport_TimeControl( alembic_importoptions &options ) { if(!options.loadTimeControl){ return; } // check if an Alembic Time Control already exists in the scene. BOOL alreadyExists = ExecuteMAXScriptScript( _T( "select $Alembic_Time_Control" ), TRUE ); if( alreadyExists != 0 ) { if( GetCOREInterface()->GetSelNodeCount() > 0 ) { INode *pSelectedNode = GetCOREInterface()->GetSelNode( 0 ); HelperObject *pSelectedHelper = static_cast<HelperObject*>( pSelectedNode->GetObjectRef() ); options.pTimeControl = pSelectedHelper; return; } } // Create the xform modifier HelperObject *pHelper = static_cast<HelperObject*> (GetCOREInterface()->CreateInstance(HELPER_CLASS_ID, ALEMBIC_TIME_CONTROL_HELPER_CLASSID)); TimeValue zero( 0 ); // Set the alembic id pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "current" ), zero, 0.0f ); pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "offset" ), zero, 0.0f ); pHelper->GetParamBlockByID( 0 )->SetValue( GetParamIdByName( pHelper, 0, "factor" ), zero, 1.0f ); // Create the object node INode *node = GET_MAX_INTERFACE()->CreateObjectNode(pHelper, pHelper->GetObjectName() ); // Add the new inode to our current scene list SceneEntry *pEntry = options.sceneEnumProc.Append(node, pHelper, OBTYPE_CURVES, &std::string( EC_MCHAR_to_UTF8( node->GetName() ) ) ); options.currentSceneList.Append(pEntry); //GET_MAX_INTERFACE()->SelectNode( node ); //std::string nodeName = EC_MCHAR_to_UTF8( node->GetName() ); //char szBuffer[10000]; //sprintf_s( szBuffer, 10000, // "$'%s'.current.controller = float_expression()\n" // "$'%s'.current.controller.setExpression \"S\"\n" // "$'%s'.offset.controller = bezier_float()\n" // "$'%s'.factor.controller = bezier_float()\n" // , nodeName.c_str(), nodeName.c_str(), nodeName.c_str(), nodeName.c_str() ); //ExecuteMAXScriptScript( EC_UTF8_to_TCHAR( szBuffer ) ); options.pTimeControl = pHelper; }
BOOL PickTarget::HitTest( IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags) { INode *node = ip->PickNode(hWnd,m,this); if (node) { if (mo->morphCont->ValidTarget( mo->ip->GetTime(), node->GetObjectRef())) { return TRUE; } } return FALSE; }
void PatchDeformPW::SetResampleModContext(BOOL resample) { PatchEnumProc dep; DoEnumDependents(&dep); for ( int i = 0; i < dep.Nodes.Count(); i++) { INode *node = dep.Nodes[i]; BOOL found = FALSE; if (node) { Object* obj = node->GetObjectRef(); RecursePipeAndMatch2(this,obj,resample) ; } } }
BOOL SWrapPickOperand::HitTest( IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags) { INode *node = ip->PickNode(hWnd,m,this); if (node) { ObjectState os = node->GetObjectRef()->Eval(ip->GetTime()); if (!IsGEOM(os.obj)) { node = NULL; return FALSE; } node->BeginDependencyTest(); po->NotifyDependents(FOREVER,0,REFMSG_TEST_DEPENDENCY); if (node->EndDependencyTest()) return FALSE; } return node ? TRUE : FALSE; }
BOOL PickTarget::Pick(IObjParam *ip,ViewExp *vpt) { if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } INode *node = vpt->GetClosestHit(); assert(node); if (mo->morphCont-> ValidTarget( mo->ip->GetTime(), node->GetObjectRef())) { mo->AddNewTarget(node,mo->ip->GetTime(),mo->AddTargMethod()); mo->SetupTargetList(); ip->RedrawViews(ip->GetTime()); } return FALSE; }
Point3 Jiggle::GetDynamicsForces(TimeValue t, Point3 pos, Point3 vel) { INode *aforce; Point3 f(0.0f,0.0f,0.0f); for( int i=0;i<force_pb->Count(jig_force_node);i++) { Interval for_ever = FOREVER; force_pb->GetValue(jig_force_node, 0, aforce, for_ever, i); if (aforce) { Object* obref = aforce->GetObjectRef(); ForceField* ff = NULL; if (obref != NULL) { WSMObject* wsmObj = static_cast<WSMObject*>(obref->GetInterface(I_WSMOBJECT)); if (NULL == wsmObj && WSM_OBJECT_CLASS_ID == obref->SuperClassID()) { wsmObj = static_cast<WSMObject*>(obref); } if (wsmObj != NULL) { ff = wsmObj->GetForceField(aforce); } } if (ff) { f += ff->Force(t, pos, vel, 0); ff->DeleteThis(); } } } return f; }
void ResetXForm::ResetNodes(const INodeTab& nodesToReset) { Interface *ip = GetCOREInterface(); for (int i = 0; i < nodesToReset.Count(); i++) { INode *node = nodesToReset[i]; if (!node || node->IsGroupMember() || node->IsGroupHead()) continue; if (SelectedAncestor(node)) continue; Matrix3 ntm, ptm, rtm(1), piv(1), tm; // Get Parent and Node TMs ntm = node->GetNodeTM(ip->GetTime()); ptm = node->GetParentTM(ip->GetTime()); // Compute the relative TM ntm = ntm * Inverse(ptm); // The reset TM only inherits position rtm.SetTrans(ntm.GetTrans()); // Set the node TM to the reset TM tm = rtm*ptm; node->SetNodeTM(ip->GetTime(), tm); // Compute the pivot TM piv.SetTrans(node->GetObjOffsetPos()); PreRotateMatrix(piv,node->GetObjOffsetRot()); ApplyScaling(piv,node->GetObjOffsetScale()); // Reset the offset to 0 node->SetObjOffsetPos(Point3(0,0,0)); node->SetObjOffsetRot(IdentQuat()); node->SetObjOffsetScale(ScaleValue(Point3(1,1,1))); // Take the position out of the matrix since we don't reset position ntm.NoTrans(); // Apply the offset to the TM ntm = piv * ntm; // Apply a derived object to the node's object Object *obj = node->GetObjectRef(); IDerivedObject *dobj = CreateDerivedObject(obj); // Create an XForm mod SimpleMod *mod = (SimpleMod*)ip->CreateInstance( OSM_CLASS_ID, Class_ID(CLUSTOSM_CLASS_ID,0)); // Apply the transformation to the mod. SetXFormPacket pckt(ntm); mod->tmControl->SetValue(ip->GetTime(),&pckt); // Add the modifier to the derived object. dobj->SetAFlag(A_LOCK_TARGET); // RB 3/11/99: When the macro recorder is on the derived object will get deleted unless it is locked. dobj->AddModifier(mod); dobj->ClearAFlag(A_LOCK_TARGET); // Replace the node's object node->SetObjectRef(dobj); } // Why on earth were we clearing the undo stack? // GetSystemSetting(SYSSET_CLEAR_UNDO); ip->RedrawViews(ip->GetTime()); SetSaveRequiredFlag(TRUE); }
//--------------------------------------------------------------- void LightExporter::exportLight( ExportNode* exportNode ) { if ( !exportNode->getIsInVisualScene() ) return; String lightId = getLightId(*exportNode); INode * iNode = exportNode->getINode(); LightObject* lightObject = (LightObject*) (iNode->GetObjectRef()); if ( !lightObject ) return; if ( mDocumentExporter->isExportedObject(ObjectIdentifier(lightObject)) ) return; mDocumentExporter->insertExportedObject(ObjectIdentifier(lightObject), exportNode); // Retrieve the target node, if we are not baking matrices. // Baked matrices must always sample the transform! ULONG ClassId = lightObject->ClassID().PartA(); bool isTargeted = !mDocumentExporter->getOptions().getBakeMatrices() && (ClassId == SPOT_LIGHT_CLASS_ID || ClassId == TDIR_LIGHT_CLASS_ID); INode* targetNode = isTargeted ? iNode->GetTarget() : 0; // some lights are not supported at all switch (ClassId) { case FSPOT_LIGHT_CLASS_ID: case SPOT_LIGHT_CLASS_ID: case DIR_LIGHT_CLASS_ID: case TDIR_LIGHT_CLASS_ID: case SKY_LIGHT_CLASS_ID_PART_A: case OMNI_LIGHT_CLASS_ID: break; default: return; } // Determine the light's type bool isSpot = false; bool isDirectional = false; bool isPoint = false; bool isSky = false; COLLADASW::Light::LightType lightType; switch (ClassId) { case FSPOT_LIGHT_CLASS_ID: case SPOT_LIGHT_CLASS_ID: lightType = COLLADASW::Light::SPOT; isSpot = true; break; case DIR_LIGHT_CLASS_ID: case TDIR_LIGHT_CLASS_ID: lightType = COLLADASW::Light::DIRECTIONAL; isDirectional = true; break; case SKY_LIGHT_CLASS_ID_PART_A: lightType = COLLADASW::Light::POINT; isSky = true; break; case OMNI_LIGHT_CLASS_ID: lightType = COLLADASW::Light::POINT; isPoint = true; break; } COLLADASW::Light * colladaLight = 0; switch ( lightType ) { case COLLADASW::Light::DIRECTIONAL: colladaLight = new COLLADASW::DirectionalLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; case COLLADASW::Light::POINT: colladaLight = new COLLADASW::PointLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; case COLLADASW::Light::SPOT: colladaLight = new COLLADASW::SpotLight(COLLADASW::LibraryLights::mSW, lightId, COLLADASW::Utils::checkNCName(NativeString(exportNode->getINode()->GetName()))); break; } // Retrieve the parameter block IParamBlock* parameters = 0; IParamBlock2* parametersSky = 0; if (isSky) parametersSky = (IParamBlock2*) lightObject->GetReference(MaxLight::PBLOCK_REF_SKY); else parameters = (IParamBlock*) lightObject->GetReference(MaxLight::PBLOCK_REF); if (!parameters && !parametersSky) { delete colladaLight; return; } if (parameters) { bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parameters, MaxLight::PB_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 ); colladaLight->setColor(EffectExporter::maxColor2Color(parameters->GetColor(MaxLight::PB_COLOR)), hasAnimatedColor); } else if (parametersSky ) { bool hasAnimatedColor = mAnimationExporter->addAnimatedParameter(parametersSky, MaxLight::PB_SKY_COLOR, lightId, colladaLight->getColorDefaultSid(), 0 ); colladaLight->setColor(EffectExporter::maxColor2Color(parametersSky->GetColor(MaxLight::PB_SKY_COLOR)), hasAnimatedColor); } if (isSpot || isPoint) { int decayFunction = parameters->GetInt(isPoint ? MaxLight::PB_DECAY : MaxLight::PB_OMNIDECAY, mDocumentExporter->getOptions().getAnimationStart()); switch (decayFunction) { case 1: colladaLight->setConstantAttenuation(0.0f); colladaLight->setLinearAttenuation(1.0f); break; case 2: colladaLight->setConstantAttenuation(0.0f); colladaLight->setQuadraticAttenuation(1.0f); break; case 0: default: colladaLight->setConstantAttenuation(1.0f); break; } } else if (isSky) { colladaLight->setConstantAttenuation(1.0f); } setExtraTechnique(colladaLight); if ( parameters ) addParamBlockAnimatedExtraParameters(LIGHT_ELEMENT, LIGHT_PARAMETERS, LIGHT_PARAMETER_COUNT, parameters, lightId); else addParamBlockAnimatedExtraParameters(SKYLIGHT_ELEMENT, SKYLIGHT_PARAMETERS, SKYLIGHT_PARAMETER_COUNT, parametersSky, lightId); // add all the information to extra tag, that are not contained in IParamBlock if (isSpot || isDirectional || isPoint) { GenLight* light = (GenLight*)(lightObject); if (!light) { delete colladaLight; return; } // Export the overshoot flag for directional lights if (isDirectional || isSpot) { addExtraChildParameter(LIGHT_ELEMENT, OVERSHOOT_PARAMETER, light->GetOvershoot() != false); } addExtraChildParameter(LIGHT_ELEMENT, DECAY_TYPE_PARAMETER, (int)light->GetDecayType()); addExtraChildParameter(LIGHT_ELEMENT, USE_NEAR_ATTENUATION_PARAMETER, (light->GetUseAttenNear() != false)); addExtraChildParameter(LIGHT_ELEMENT, USE_FAR_ATTENUATION_PARAMETER, (light->GetUseAtten() != false)); exportShadowParameters(light); if (light->GetProjector()) { Texmap* projectorMap = light->GetProjMap(); if (projectorMap) { String imageId = exportTexMap(projectorMap); if ( !imageId.empty() ) { addExtraChildParameter(LIGHT_ELEMENT, LIGHT_MAP_ELEMENT, "#" + imageId); } } } } else // isSky { Texmap *colorMap = parametersSky->GetTexmap(MaxLight::PB_SKY_COLOR_MAP, mDocumentExporter->getOptions().getAnimationStart()); String imageId = exportTexMap(colorMap); if ( !imageId.empty()) { addExtraChildParameter(SKYLIGHT_ELEMENT, SKYLIGHT_COLORMAP_ELEMENT, "#" + imageId); } } addLight(*colladaLight); delete colladaLight; }
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; }
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 Import::ApplyModifiers (dScene& scene, const MaxNodeChache& maxNodeCache) { dScene::Iterator iter (scene); for (iter.Begin(); iter; iter ++) { dScene::dTreeNode* meshNode = iter.GetNode(); dNodeInfo* info = scene.GetInfoFromNode(meshNode); if (info->IsType(dGeometryNodeInfo::GetRttiType())) { dScene::dTreeNode* skinModifierNode = NULL; for (void* ptr = scene.GetFirstChild(meshNode); ptr; ptr = scene.GetNextChild(meshNode, ptr)) { dScene::dTreeNode* node = scene.GetNodeFromLink(ptr); dNodeInfo* info = scene.GetInfoFromNode(node); if (info->GetTypeId() == dGeometryNodeSkinModifierInfo::GetRttiType()) { skinModifierNode = node; break; } } if (skinModifierNode) { //create a skin modifier and add it Modifier* skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA); INode* maxNode = maxNodeCache.Find(meshNode)->GetInfo(); _ASSERTE (maxNode); IDerivedObject *derob = NULL; Object* obj = maxNode->GetObjectRef(); if(obj->SuperClassID() != GEN_DERIVOB_CLASS_ID) { derob = CreateDerivedObject(obj); maxNode->SetObjectRef(derob); } else { derob = (IDerivedObject*) obj; } derob->AddModifier(skinMod); dGeometryNodeSkinModifierInfo* skinModifier = (dGeometryNodeSkinModifierInfo*) scene.GetInfoFromNode(skinModifierNode); dMatrix matrix (skinModifier->m_shapeBindMatrix); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetSkinTm(maxNode, bindPoseMatrix, bindPoseMatrix); int maxNodeCount = 0; INode* maxNodes[1024]; for (void* ptr = scene.GetFirstChild(skinModifierNode); ptr; ptr = scene.GetNextChild(skinModifierNode, ptr)) { dScene::dTreeNode* boneNode = scene.GetNodeFromLink(ptr); INode* skelBone = maxNodeCache.Find(boneNode)->GetInfo(); maxNodes[maxNodeCount] = skelBone; maxNodeCount ++; skelBone->SetBoneNodeOnOff(TRUE, 0); skelBone->BoneAsLine(TRUE); skelBone->ShowBone(1); if (iskinImport->AddBoneEx(skelBone, TRUE)) { dSceneNodeInfo* sceneNode = (dSceneNodeInfo*) scene.GetInfoFromNode(boneNode); dMatrix matrix (sceneNode->GetTransform()); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetBoneTm(skelBone, bindPoseMatrix, bindPoseMatrix); } } // must evaluate the node after adding bones maxNode->EvalWorldState(0); for (int i = 0; i < skinModifier->m_vertexCount; i ++) { Tab<float> weightList; Tab<INode*> boneNodeList; for (int j = 0; j < 4; j ++) { if (skinModifier->m_vertexWeights[i][j] > 1.0e-5f) { int boneIndex = skinModifier->m_boneWeightIndex[i].m_index[j]; INode *skelBone = maxNodes[boneIndex]; _ASSERTE (skelBone); boneNodeList.Append (1, &skelBone); weightList.Append (1, &skinModifier->m_vertexWeights[i][j]); } } iskinImport->AddWeights(maxNode, i, boneNodeList, weightList); } } } } }
/** * @brief * Constructor */ PLSceneNode::PLSceneNode(PLSceneContainer *pContainer, IGameNode *pIGameNode, const String &sName, EType nType, const String &sClassName) : m_pContainer(pContainer), m_pIGameNode(pIGameNode), m_sName(sName), m_nType(nType), m_sClassName(sClassName), m_sFlags(""), m_vPos(0.0f, 0.0f, 0.0f), m_vRot(0.0f, 0.0f, 0.0f), m_vScale(1.0f, 1.0f, 1.0f), m_nIsRotationFlipped(-1) { // Check some universal flags INode *pMaxNode = GetMaxNode(); if (pMaxNode) { // If this is not a container... TSTR sString; // Check whether the default PixelLight class is changed if (pMaxNode->GetUserPropString(_T("Class"), sString)) { m_sClassName = sString; // Erase all '"' int i = m_sClassName.IndexOf("\""); while (i >= 0) { m_sClassName.Delete(i, 1); i = m_sClassName.IndexOf("\""); } } // Is this 3ds Max node frozen? if (pMaxNode->IsFrozen()) AddFlag("Frozen"); // Is this 3ds Max node invisible? if (pMaxNode->IsHidden() || !pMaxNode->Renderable()) AddFlag("Invisible"); // Is this 3ds Max node excluded from lighting? INodeGIProperties *pINodeGIProperties = static_cast<INodeGIProperties*>(pMaxNode->GetInterface(NODEGIPROPERTIES_INTERFACE)); if (pINodeGIProperties && pINodeGIProperties->GIGetIsExcluded()) AddFlag("NoLighting"); { // Get the world space bounding box of the scene node. Because this is not 'trival' we're using // the sample code from "3dsMaxSDK.chm" (3ds Max SDK) -> "The Pipeline and the INode TM Methods" // to get it working correctly. ::Object *pMaxObject = pMaxNode->GetObjectRef(); if (pMaxObject) { TimeValue t = 0; Matrix3 mat; // The Object TM // Determine if the object is in world space or object space // so we can get the correct TM. We can check this by getting // the Object TM after the world space modifiers have been // applied. It the matrix returned is the identity matrix the // points of the object have been transformed into world space. if (pMaxNode->GetObjTMAfterWSM(t).IsIdentity()) { // It's in world space, so put it back into object // space. We can do this by computing the inverse // of the matrix returned before any world space // modifiers were applied. mat = Inverse(pMaxNode->GetObjTMBeforeWSM(t)); } else { // It's in object space, get the Object TM mat = pMaxNode->GetObjectTM(t); } // Get the bound box, and affect it by just the scaling portion pMaxObject->GetDeformBBox(t, m_cBoundingBox, &mat); } } // We really need to flip the coordinates to OpenGL style m_cBoundingBox.pmin = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmin); m_cBoundingBox.pmax = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmax); // Validate minimum/maximum - I already had situations with incorrect values causing problems! PLTools::ValidateMinimumMaximum(m_cBoundingBox); } // Get the position, rotation and scale GetPosRotScale(m_vPos, m_vRot, m_vScale); }
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 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)); } } }
void BlobMesh::PickPFEvents(HWND hWnd) { Tab<INode *> pfEvents; int numberOfNodes = pblock2->Count(pb_nodelist); TimeValue t = GetCOREInterface()->GetTime(); pfNodes.ZeroCount(); addPFNodes.ZeroCount(); for (int i = 0; i < numberOfNodes; i++) { INode *node; pblock2->GetValue(pb_nodelist,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(false); tos.obj->DoEnumDependents(&dep); for (int i = 0; i < dep.Nodes.Count(); i++) { Interval valid; INode *node = dep.Nodes[i]; Object *obj = node->GetObjectRef(); if ((obj) && (obj->GetInterface(PARTICLEGROUP_INTERFACE)) ) { 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(pb_pfeventlist,1,&node); } theHold.Accept(GetString(IDS_ADDEVENTS)); } } }
/** * @brief * Adds a 3ds Max node to the scene */ bool PLSceneContainer::AddIGameNode(IGameNode &cIGameNode) { // Unknown node type by default EType nType = TypeUnknown; // Is there a '.' within the node name? If yes, replace it by '-'. String sName = cIGameNode.GetName(); int nIndex = sName.IndexOf("."); if (nIndex >= 0) { g_pLog->LogFLine(PLLog::Warning, "Node name '%s' has '.' within it, '.' is replaced by '-' automatically", cIGameNode.GetName()); char *pszName = const_cast<char*>(sName.GetASCII()) + nIndex; while (*pszName != '\0') { if (*pszName == '.') *pszName = '-'; pszName++; } } const char *pszName = sName.GetASCII(); // Look for 'cell_' (cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>) String sSceneCellName, sTargetSceneCellName, sSceneNodeName, sMeshName; if (!_strnicmp(pszName, "cell_", 5)) { // Get the name of the cell const char *pszNameT = pszName += 5; // Check for '\0' if (*pszNameT == '\0') { g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. <cell name> is missing!", cIGameNode.GetName()); sSceneCellName = "?"; sMeshName = "?"; sSceneNodeName = "?"; } else { // Read the cell name while (*pszNameT != '_' && *pszNameT != '\0') pszNameT++; sSceneCellName.Insert(pszName, 0, pszNameT-pszName); // Check for '_' if (*pszNameT != '_') { g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. <mesh name>/<instance name> is missing!", cIGameNode.GetName()); sMeshName = "?"; sSceneNodeName = "?"; } else { // Skip '_' pszNameT++; // Get the name of the node/mesh pszName = pszNameT; while (*pszNameT != '_' && *pszNameT != '\0') pszNameT++; sMeshName.Insert(pszName, 0, pszNameT-pszName); // Check for '_' if (*pszNameT != '_') { // Check for spaces within the mesh name CheckAndCorrectName(sMeshName, cIGameNode.GetName(), "mesh"); // cell_<cell name>_<node name> is used so node name = mesh name sSceneNodeName = sMeshName; // Construct a 'save' mesh name later if the final scene node name is known... sMeshName = ""; } else { // Skip '_' pszNameT++; // Get the name of the scene node sSceneNodeName = sMeshName+"_"; pszName = pszNameT; while (*pszNameT != '_' && *pszNameT != '\0') pszNameT++; sSceneNodeName.Insert(pszName, sSceneNodeName.GetLength(), pszNameT-pszName); // Is there an instance name? - No log hint because people find this behavior annoying... // if (!(pszNameT-pszName)) // g_pLog->LogFLine(PLLog::Hint, "Node name '%s' does not follow the name convention cell_<cell name>_<mesh name>_<instance name>. <instance name> is missing!", cIGameNode.GetName()); // Check for spaces and tabs within the mesh and node names CheckAndCorrectName(sMeshName, cIGameNode.GetName(), "mesh"); CheckAndCorrectName(sSceneNodeName, cIGameNode.GetName(), "node"); } } } // Check for spaces/tabs within the cell name CheckAndCorrectName(sSceneCellName, cIGameNode.GetName(), "cell"); // Look for 'portal_' (portal_<from cell>_<to cell>) } else if (!_strnicmp(pszName, "portal_", 7)) { // Get the name of the cell, the cell-portal is a scene node of this cell :) const char *pszNameT = pszName += 7; // Check for '\0' if (*pszNameT == '\0') { g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention portal_<from cell>_<to cell>. <from cell> is missing!", cIGameNode.GetName()); sSceneCellName = "?"; sTargetSceneCellName = "?"; } else { // Read the cell name while (*pszNameT != '_' && *pszNameT != '\0') pszNameT++; sSceneCellName.Insert(pszName, 0, pszNameT-pszName); // Check for '_' if (*pszNameT != '_') { g_pLog->LogFLine(PLLog::Error, "Node name '%s' does not follow the name convention portal_<from cell>_<to cell>. <to cell> is missing!", cIGameNode.GetName()); sTargetSceneCellName = "?"; } else { // Skip '_' pszNameT++; // Get the name of the target cell pszName = pszNameT; while (*pszNameT != '_' && *pszNameT != '\0') pszNameT++; sTargetSceneCellName.Insert(pszName, 0, pszNameT-pszName); } } // Check for spaces/tabs within the names CheckAndCorrectName(sSceneCellName, cIGameNode.GetName(), "cell"); CheckAndCorrectName(sTargetSceneCellName, cIGameNode.GetName(), "target cell"); // Get the name of the scene node sSceneNodeName = "CellPortalTo_"; sSceneNodeName += sTargetSceneCellName; // Get the 'real' target cell name - in our case, this cell MUST be within the parent container... sTargetSceneCellName = "Parent." + sTargetSceneCellName; // Set the correct scene node type nType = TypeCellPortal; // Look for 'antiportal_' (antiportal_<name>) } else if (!_strnicmp(pszName, "antiportal_", 11)) { // Get the name of the anti-portal) sSceneNodeName = String("AntiPortal_") + (pszName += 11); // Set the correct scene node type nType = TypeAntiPortal; // ... } else { // No log hint because people find this behavior annoying... // g_pLog->LogFLine(PLLog::Hint, "Node name '%s' does not follow the name convention cell_<cell name>_<node name> or cell_<cell name>_<mesh name>_<instance name>. Node is added to the scene root.", cIGameNode.GetName()); // Set scene node name sSceneNodeName = pszName; } // Check whether the scene cell and node names are valid if (sSceneCellName.CompareNoCase("This")) { sSceneCellName += '-'; g_pLog->LogFLine(PLLog::Warning, "'This' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII()); } if (sSceneCellName.CompareNoCase("Root")) { sSceneCellName += '-'; g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII()); } if (sSceneCellName.CompareNoCase("Parent")) { sSceneCellName += '-'; g_pLog->LogFLine(PLLog::Warning, "'Parent' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneCellName.GetASCII()); } if (sSceneNodeName.CompareNoCase("This")) { sSceneNodeName += '-'; g_pLog->LogFLine(PLLog::Warning, "'This' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII()); } if (sSceneNodeName.CompareNoCase("Root")) { sSceneNodeName += '-'; g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII()); } if (sSceneNodeName.CompareNoCase("Parent")) { sSceneNodeName += '-'; g_pLog->LogFLine(PLLog::Warning, "'Root' is NOT allowed as node name. (3ds Max node '%s') Name is changed into '%s' ", cIGameNode.GetName(), sSceneNodeName.GetASCII()); } // Get cell, this scene node is in PLSceneCell *pCell = GetCell(sSceneCellName, cIGameNode); // The exporter isn't case sensitive, but compare the 'real' cell names just for sure :) if (pCell && pCell->GetName() != sSceneCellName) g_pLog->LogFLine(PLLog::Warning, "Node '%s' is within the cell '%s', but '%s' was written -> It's recommended to take care of lower/upper case!", cIGameNode.GetName(), pCell->GetName().GetASCII(), sSceneCellName.GetASCII()); // Get the container the new scene node is created in. If no cell was found, create the scene node // within THIS container. PLSceneContainer *pContainer = pCell ? pCell : this; // Check whether there's already an scene node with this name, if so, rename it and write a warning // into the log String sSceneNodeNameLower = sSceneNodeName; sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values! std::map<String, PLSceneNode*>::iterator pIterator = pContainer->m_mapNodes.find(sSceneNodeNameLower); if (pIterator != pContainer->m_mapNodes.end()) { String sNewName; int nConflictIndex = 1; // Find an unused scene node name do { sNewName = sSceneNodeName; sNewName += "_Conflict_"; sNewName += PLTools::ToString(nConflictIndex); nConflictIndex++; sSceneNodeNameLower = sNewName; sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values! pIterator = pContainer->m_mapNodes.find(sSceneNodeNameLower); } while (pIterator != pContainer->m_mapNodes.end()); // Write a log message g_pLog->LogFLine(PLLog::Warning, "'%s': There's already a scene node with the name '%s' within the container '%s' -> Changed name into '%s'", cIGameNode.GetName(), sSceneNodeName.GetASCII(), sSceneCellName.GetASCII(), sNewName.GetASCII()); // Set the new name sSceneNodeName = sNewName; } // Construct a 'save' mesh name... if (!sMeshName.GetLength()) sMeshName = sSceneCellName.GetLength() ? sSceneCellName + '_' + sSceneNodeName : sSceneNodeName; // Are there any children? If yes, we need to create a container for this node containing THIS node AND the children... if (cIGameNode.GetChildCount()) { PLSceneContainer *pNewContainer = new PLSceneContainer(pContainer, sSceneNodeName); // Register the new scene node pContainer->m_lstSceneNodes.push_back(pNewContainer); sSceneNodeNameLower = sSceneNodeName; sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values! pContainer->m_mapNodes.insert(std::make_pair(sSceneNodeNameLower, pNewContainer)); // The new container becomes the current container pContainer = pNewContainer; // [TODO] Update the statistics // pContainer->m_sStatistics.nNumOfUnknown++; // GetScene().m_sSceneStatistics.nNumOfUnknown++; } // Create the scene node... PLSceneNode *pSceneNode = nullptr; INode *pMaxNode = cIGameNode.GetMaxNode(); if (pMaxNode) { Object *pMaxObject = pMaxNode->GetObjectRef(); if (pMaxObject) { // Get 'real' 3ds Max object (we really need to do this) while (pMaxObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) pMaxObject = static_cast<IDerivedObject*>(pMaxObject)->GetObjRef(); // Check the type of the object switch (pMaxObject->SuperClassID()) { case LIGHT_CLASS_ID: // Create the scene node pSceneNode = new PLSceneLight(*pContainer, cIGameNode, sSceneNodeName); // Update the statistics pContainer->m_sStatistics.nNumOfLights++; GetScene().m_sSceneStatistics.nNumOfLights++; break; case GEOMOBJECT_CLASS_ID: // Is this a cell-portal? if (nType == TypeCellPortal) { // Create the scene node pSceneNode = new PLSceneCellPortal(*pContainer, cIGameNode, sSceneNodeName, sTargetSceneCellName); // Update the number of outgoing cell-portals if (pContainer->GetType() == TypeCell) { static_cast<PLSceneCell*>(pContainer)->m_lstOutgoingCellPortals.push_back(static_cast<PLSceneCellPortal*>(pSceneNode)); // ?? There's something totally wrong! ?? } else { g_pLog->LogFLine(PLLog::Warning, "'%s': This cell-portal is within the container '%s', but cell-portals should only be within cells!", cIGameNode.GetName(), sTargetSceneCellName.GetASCII()); } // Update the statistics pContainer->m_sStatistics.nNumOfCellPortals++; GetScene().m_sSceneStatistics.nNumOfCellPortals++; // Is this a anti-portal? } else if (nType == TypeAntiPortal) { // Create the scene node pSceneNode = new PLSceneAntiPortal(*pContainer, cIGameNode, sSceneNodeName); // Update the statistics pContainer->m_sStatistics.nNumOfAntiPortals++; GetScene().m_sSceneStatistics.nNumOfAntiPortals++; } else { // [TODO] Add rename to mesh node... // Create the scene node pSceneNode = new PLSceneObject(*pContainer, cIGameNode, sSceneNodeName, GetScene().AddMesh(cIGameNode, sMeshName)); // Update the statistics pContainer->m_sStatistics.nNumOfObjects++; GetScene().m_sSceneStatistics.nNumOfObjects++; } break; case SHAPE_CLASS_ID: // Create the scene node pSceneNode = new PLSceneSpline(*pContainer, cIGameNode, sSceneNodeName); // We do not need to update the statistics... break; case CAMERA_CLASS_ID: // Create the scene node pSceneNode = new PLSceneCamera(*pContainer, cIGameNode, sSceneNodeName); // Update the statistics pContainer->m_sStatistics.nNumOfCameras++; GetScene().m_sSceneStatistics.nNumOfCameras++; break; case HELPER_CLASS_ID: // Create the scene node pSceneNode = new PLSceneHelper(*pContainer, cIGameNode, sSceneNodeName); // Update the statistics pContainer->m_sStatistics.nNumOfHelpers++; GetScene().m_sSceneStatistics.nNumOfHelpers++; break; default: // Create the scene node pSceneNode = new PLSceneUnknown(*pContainer, cIGameNode, sSceneNodeName); // Update the statistics pContainer->m_sStatistics.nNumOfUnknown++; GetScene().m_sSceneStatistics.nNumOfUnknown++; break; } } } // Valid scene node? if (pSceneNode) { // Are there any children? If yes, we need to create a container for this node containing THIS node AND the children... if (cIGameNode.GetChildCount()) { // Setup the scene container pContainer->m_bFixedCenter = true; pContainer->m_vCenter.Set(0.0f, 0.0f, 0.0f); pContainer->m_vPos = pSceneNode->m_vPos; pContainer->m_vRot = pSceneNode->m_vRot; // Setup the scene node 'creating' the scene container pSceneNode->m_vPos.Set(0.0f, 0.0f, 0.0f); pSceneNode->m_vRot.Set(0.0f, 0.0f, 0.0f); } // Register the new scene node pContainer->m_lstSceneNodes.push_back(pSceneNode); sSceneNodeNameLower = sSceneNodeName; sSceneNodeNameLower.ToLower(); // Do ONLY use lower case, else the hashing will NOT return the same values! pContainer->m_mapNodes.insert(std::make_pair(sSceneNodeNameLower, pSceneNode)); { // Add to 3ds Max node to PL node map String sKey = String::Format("%19p", cIGameNode.GetMaxNode()); GetScene().m_mapMaxToPLNodes.insert(std::make_pair(sKey, pSceneNode)); } // Loop through all child nodes for (int nNode=0; nNode<cIGameNode.GetChildCount(); nNode++) { IGameNode *pIGameNode = cIGameNode.GetNodeChild(nNode); if (pIGameNode) { g_pLog->LogFLine(PLLog::Scene, "Found 3ds Max child node: %s", pIGameNode->GetName()); pContainer->AddIGameNode(*pIGameNode); } } // Done return true; } // Error! return false; }
bool PFOperatorForceSpaceWarp::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { // acquire all necessary channels, create additional if needed IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if(chAmount == NULL) return false; int iQuant = chAmount->Count(); if (iQuant < 1) return true; // no particles to proceed IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if (chNew == NULL) return false; IParticleChannelIDR* chID = GetParticleChannelIDRInterface(pCont); if (chID == NULL) return false; IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if(chTime == NULL) return false; IParticleChannelPTVR* chAge = GetParticleChannelBirthTimeRInterface(pCont); if(chAge == NULL) return false; // the channel of interest speed bool initSpeed = false; //channel does not exist so make it and note that we have to fill it out IParticleChannelPoint3W* chSpeedW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELSPEEDW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELSPEEDR_INTERFACE, PARTICLECHANNELSPEEDW_INTERFACE, true, actionNode, NULL, &initSpeed); IParticleChannelPoint3R* chSpeed = GetParticleChannelSpeedRInterface(pCont); if ((chSpeedW == NULL) || (chSpeed == NULL)) return false; bool initPosition = false; IParticleChannelPoint3W* chPosW = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELPOSITIONW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELPOSITIONR_INTERFACE, PARTICLECHANNELPOSITIONW_INTERFACE, true, actionNode, NULL, &initPosition); IParticleChannelPoint3R* chPos = GetParticleChannelPositionRInterface(pCont); if ((chPosW == NULL) || (chPos == NULL)) return false; bool useScript = ((scriptPBlock()->GetInt(kForceSpaceWarp_useScriptWiring, 0) != 0) && (scriptPBlock()->GetInt(kForceSpaceWarp_useFloat, 0) == kForceSpaceWarp_useFloat_influence)); IParticleChannelFloatR* chFloat = NULL; if (useScript) { chFloat = GetParticleChannelMXSFloatRInterface(pCont); if (chFloat == NULL) return false; } int timeType = kAbsoluteTime; _pblock()->GetValue(kForceSpaceWarp_Sync,0, timeType, FOREVER); IParticleChannelPTVR* chEventStart = NULL; IParticleChannelPTVW* chEventStartW = NULL; bool initEventStart = false; if (timeType == kEventDuration) { chEventStartW = (IParticleChannelPTVW*) chCont->EnsureInterface(PARTICLECHANNELEVENTSTARTW_INTERFACE, ParticleChannelPTV_Class_ID, true, PARTICLECHANNELEVENTSTARTR_INTERFACE, PARTICLECHANNELEVENTSTARTW_INTERFACE, false, actionNode, NULL, &initEventStart); chEventStart = GetParticleChannelEventStartRInterface(pCont); if ((chEventStart == NULL) || (chEventStartW == NULL)) return false; } int overlapping = pblock()->GetInt(kForceSpaceWarp_Overlapping, 0); // collecting force fields Tab<ForceField*> ff; ForceField* curFF; int i, j; for(i=0; i<pblock()->Count(kForceSpaceWarp_ForceNodeList); i++) { INode* node = pblock()->GetINode(kForceSpaceWarp_ForceNodeList, 0, i); if (node == NULL) continue; Object* ob = GetPFObject(node->GetObjectRef()); if (ob == NULL) continue; if (ob->SuperClassID() == WSM_OBJECT_CLASS_ID) { WSMObject* obref = (WSMObject*)ob; curFF = obref->GetForceField(node); if (curFF != NULL) { if (ob->ClassID() == CS_VFIELDOBJECT_CLASS_ID) { // CS VectorField SW doesn't init properly partobj on GetForceField // this is a quick fix for that (bayboro 3/6/2003) CS_VectorField* vf = (CS_VectorField*)curFF; vf->partobj = GetParticleInterface(pSystem); } ff.Append(1, &curFF); } } } if (ff.Count() == 0) return true; // no force fields // some calls for a reference node TM may initiate REFMSG_CHANGE notification // we have to ignore that while processing the particles bool wasIgnoring = IsIgnoringRefNodeChange(); if (!wasIgnoring) SetIgnoreRefNodeChange(); float influence = 0.0f; for(i = 0; i < iQuant; i++) { TimeValue t = 0; if (timeType == kAbsoluteTime) t = chTime->GetValue(i).TimeValue(); else if (timeType == kParticleAge) t = chTime->GetValue(i).TimeValue() - chAge->GetValue(i).TimeValue(); else { if (initEventStart && chNew->IsNew(i)) chEventStartW->SetValue(i, chTime->GetValue(i)); t = chTime->GetValue(i).TimeValue() - chEventStart->GetValue(i).TimeValue(); } if (useScript) { influence = chFloat->GetValue(i); } else { influence = GetPFFloat(pblock(), kForceSpaceWarp_Influence, t); } Point3 v(0.0f,0.0f,0.0f); if (!initSpeed || !chNew->IsNew(i)) //if we created a speed channel the channel incoming is bogus so just use 0,0,0 ad default v = chSpeed->GetValue(i); Point3 p(0.0f,0.0f,0.0f); if (!initPosition || !chNew->IsNew(i)) //if we created a pos channel the channel incoming is bogus so just use 0,0,0 ad default p = chPos->GetValue(i); Point3 force = Point3::Origin; for(j=0; j<ff.Count(); j++) { // buffer vectors to guard true position and speed from malicious force Point3 pp = p; Point3 vv = v; Point3 nextForce = ff[j]->Force(t,pp,vv,chID->GetParticleBorn(i)) * influence; float lenSq = LengthSquared(nextForce); if (lenSq <= 0.0f) continue; // not a valid force if (overlapping == kForceSpaceWarp_Overlapping_additive) { force += nextForce; } else { if (lenSq > LengthSquared(force)) force = nextForce; } // p = pp; // v = vv; } v += force * float(timeEnd - chTime->GetValue(i)); chPosW->SetValue(i, p); chSpeedW->SetValue(i, v); } for(i=0; i<ff.Count(); i++) if (ff[i] != NULL) ff[i]->DeleteThis(); if (!wasIgnoring) ClearIgnoreRefNodeChange(); return true; }
//--------------------------------------------------------------- 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; } }