void AlembicPoints::ReadShapeFromOperator( IParticleGroup *particleGroup, PFSimpleOperator *pSimpleOperator, int particleId, TimeValue ticks, ShapeType &type, Abc::uint16_t &instanceId, float &animationTime) { if(!pSimpleOperator){ return; } if (pSimpleOperator->ClassID() == PFOperatorSimpleShape_Class_ID) { IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0); int nShapeId = pblock->GetInt(PFlow_kSimpleShape_shape, ticks); switch(nShapeId) { case PFlow_kSimpleShape_shape_pyramid: type = ShapeType_Cone; break; case PFlow_kSimpleShape_shape_cube: type = ShapeType_Box; break; case PFlow_kSimpleShape_shape_sphere: type = ShapeType_Sphere; break; case PFlow_kSimpleShape_shape_vertex: type = ShapeType_Point; break; default: type = ShapeType_Point; } } else if (pSimpleOperator->ClassID() == PFOperatorShapeLib_Class_ID) { IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0); int nDimension = pblock->GetInt(PFlow_kShapeLibary_dimensionType, ticks); if(nDimension == PFlow_kShapeLibrary_dimensionType_2D){ int n2DShapeId = pblock->GetInt(PFlow_kShapeLibary_2DType, ticks); if( n2DShapeId == PFlow_kShapeLibrary_dimensionType_2D_square){ type = ShapeType_Rectangle; } else{ ESS_LOG_INFO("Unsupported shape type."); type = ShapeType_Point; } } else if(nDimension == PFlow_kShapeLibrary_dimensionType_3D){ int n3DShapeId = pblock->GetInt(PFlow_kShapeLibary_3DType, ticks); if(n3DShapeId == PFlow_kShapeLibary_3DType_cube){ type = ShapeType_Box; } else if(n3DShapeId == PFlow_kShapeLibary_3DType_Sphere20sides || n3DShapeId == PFlow_kShapeLibary_3DType_Sphere80sides){ type = ShapeType_Sphere; } else{ ESS_LOG_INFO("Unsupported shape type."); type = ShapeType_Point; } //ShapeType_Cylinder unsupported //ShapeType_Cone unsupported //ShapeType_Disc unsupported //ShapeType_NbElements unsupported } else{ ESS_LOG_INFO("Unknown dimension."); type = ShapeType_Point; } //int nNumParams = pblock->NumParams(); //for(int i=0; i<nNumParams; i++){ // ParamID id = pblock->IndextoID(i); // MSTR paramStr = pblock->GetLocalName(id, 0); // int n = 0; // //} } else if (pSimpleOperator->ClassID() == PFOperatorInstanceShape_Class_ID) { // Assign animation time and shape here IParamBlock2 *pblock = pSimpleOperator->GetParamBlockByID(0); INode *pNode = pblock->GetINode(PFlow_kInstanceShape_objectMaxscript, ticks); if (pNode == NULL || pNode->GetName() == NULL) { return; } type = ShapeType_Instance; bool bFlatten = GetCurrentJob()->GetOption("flattenHierarchy"); std::string nodePath = getNodeAlembicPath( EC_MCHAR_to_UTF8( pNode->GetName() ), bFlatten); // Find if the name is alerady registered, otherwise add it to the list // instanceId = FindInstanceName(nodePath); // if (instanceId == USHRT_MAX) // { //mInstanceNames.push_back(nodePath); // instanceId = (Abc::uint16_t)mInstanceNames.size()-1; // } // Determine if we have an animated shape BOOL animatedShape = pblock->GetInt(PFlow_kInstanceShape_animatedShape); BOOL acquireShape = pblock->GetInt(PFlow_kInstanceShape_acquireShape); if (!animatedShape && !acquireShape) { return; } // Get the necesary particle channels to grab the current time values ::IObject *pCont = particleGroup->GetParticleContainer(); if (!pCont) { return; } // Get synch values that we are interested in fromt the param block int syncType = pblock->GetInt(PFlow_kInstanceShape_syncType); BOOL syncRandom = pblock->GetInt(PFlow_kInstanceShape_syncRandom); IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if (chTime == NULL) { return; // can't find particle times in the container } IChannelContainer* chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) { return; // can't get access to ChannelContainer interface } IParticleChannelPTVR* chBirthTime = NULL; IParticleChannelPTVR* chEventStartR = NULL; bool initEventStart = false; if (syncType == PFlow_kInstanceShape_syncBy_particleAge) { chBirthTime = GetParticleChannelBirthTimeRInterface(pCont); if (chBirthTime == NULL) { return; // can't read particle age } } else if (syncType == PFlow_kInstanceShape_syncBy_eventStart) { chEventStartR = GetParticleChannelEventStartRInterface(pCont); if (chEventStartR == NULL) { return; // can't read event start time } } IParticleChannelIntR* chLocalOffR = NULL; bool initLocalOff = false; // acquire LocalOffset particle channel; if not present then create it. if (syncRandom) { chLocalOffR = (IParticleChannelIntR*)chCont->GetPrivateInterface(PARTICLECHANNELLOCALOFFSETR_INTERFACE, pSimpleOperator); } // get new shape from the source PreciseTimeValue time = chTime->GetValue(particleId); switch(syncType) { case PFlow_kInstanceShape_syncBy_absoluteTime: break; case PFlow_kInstanceShape_syncBy_particleAge: time -= chBirthTime->GetValue(particleId); break; case PFlow_kInstanceShape_syncBy_eventStart: time -= chEventStartR->GetValue(particleId); break; default: break; } if (syncRandom) { if (chLocalOffR != NULL) time += chLocalOffR->GetValue(particleId); } //timeValueMap::iterator it = mTimeValueMap.find(time); //if( it != mTimeValueMap.end() ){ // ESS_LOG_WARNING("sampleTime already seen."); //} //else{ // mTimeValueMap[time] = true; // mTimeSamplesCount++; // ESS_LOG_WARNING("sampleTime: "<<(float)time<<" totalSamples: "<<mTimeSamplesCount); //} TimeValue t = TimeValue(time); animationTime = (float)GetSecondsFromTimeValue(t); } else if (pSimpleOperator->ClassID() == PFOperatorMarkShape_Class_ID) { ESS_LOG_INFO("Shape Mark operator not supported."); } else if (pSimpleOperator->ClassID() == PFOperatorFacingShape_Class_ID) { ESS_LOG_INFO("Shape Facing operator not supported."); } }
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; }