AlembicPoints::AlembicPoints(SceneNodePtr eNode, AlembicWriteJob * in_Job, Abc::OObject oParent) : AlembicObject(eNode, in_Job, oParent) { mNumShapeMeshes = 0; mTotalShapeMeshes = 0; //mTimeSamplesCount = 0; std::string xformName = EC_MCHAR_to_UTF8( mMaxNode->GetName() ); std::string pointsName = xformName + "Shape"; AbcG::OPoints points(GetOParent(), pointsName.c_str(), GetCurrentJob()->GetAnimatedTs()); mPointsSchema = points.getSchema(); Abc::OCompoundProperty argGeomParams = mPointsSchema.getArbGeomParams(); // create all properties mInstanceNamesProperty = Abc::OStringArrayProperty(argGeomParams, ".instancenames", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); // particle attributes mScaleProperty = Abc::OV3fArrayProperty(argGeomParams, ".scale", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mOrientationProperty = Abc::OQuatfArrayProperty(argGeomParams, ".orientation", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mAngularVelocityProperty = Abc::OQuatfArrayProperty(argGeomParams, ".angularvelocity", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mAgeProperty = Abc::OFloatArrayProperty(argGeomParams, ".age", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mMassProperty = Abc::OFloatArrayProperty(argGeomParams, ".mass", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mShapeTypeProperty = Abc::OUInt16ArrayProperty(argGeomParams, ".shapetype", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mShapeTimeProperty = Abc::OFloatArrayProperty(argGeomParams, ".shapetime", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mShapeInstanceIDProperty = Abc::OUInt16ArrayProperty(argGeomParams, ".shapeinstanceid", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); mColorProperty = Abc::OC4fArrayProperty(argGeomParams, ".color", mPointsSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); }
AlembicCamera::AlembicCamera(SceneNodePtr eNode, AlembicWriteJob *in_Job, Abc::OObject oParent) : AlembicObject(eNode, in_Job, oParent) { std::string xformName = EC_MCHAR_to_UTF8(mMaxNode->GetName()); std::string cameraName = xformName + "Shape"; AbcG::OCamera camera(GetOParent(), cameraName.c_str(), GetCurrentJob()->GetAnimatedTs()); mCameraSchema = camera.getSchema(); }
AlembicCurves::AlembicCurves(SceneNodePtr eNode, AlembicWriteJob * in_Job, Abc::OObject oParent) : AlembicObject(eNode, in_Job, oParent) { std::string xformName = EC_MCHAR_to_UTF8( mMaxNode->GetName() ); std::string curveName = xformName + "Shape"; AbcG::OCurves curves(GetOParent(),curveName,GetCurrentJob()->GetAnimatedTs()); mCurvesSchema = curves.getSchema(); // create all properties //mInTangentProperty = OV3fArrayProperty(mCurvesSchema.getArbGeomParams(), ".inTangent", mCurvesSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); //mOutTangentProperty = OV3fArrayProperty(mCurvesSchema.getArbGeomParams(), ".outTangent", mCurvesSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); //mRadiusProperty = OFloatArrayProperty(mCurvesSchema.getArbGeomParams(), ".radius", mCurvesSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); //mColorProperty = OC4fArrayProperty(mCurvesSchema.getArbGeomParams(), ".color", mCurvesSchema.getMetaData(), GetCurrentJob()->GetAnimatedTs() ); }
bool AlembicPoints::Save(double time, bool bLastFrame) { ESS_PROFILE_FUNC(); // Note: Particles are always considered to be animated even though // the node does not have the IsAnimated() flag. // Extract our particle emitter at the given time TimeValue ticks = GetTimeValueFromFrame(time); Object *obj = mMaxNode->EvalWorldState(ticks).obj; SaveMetaData(mMaxNode, this); SimpleParticle* pSimpleParticle = (SimpleParticle*)obj->GetInterface(I_SIMPLEPARTICLEOBJ); IPFSystem* ipfSystem = GetPFSystemInterface(obj); IParticleObjectExt* particlesExt = GetParticleObjectExtInterface(obj); #ifdef THINKING_PARTICLES ParticleMat* pThinkingParticleMat = NULL; TP_MasterSystemInterface* pTPMasterSystemInt = NULL; if(obj->CanConvertToType(MATTERWAVES_CLASS_ID)) { pThinkingParticleMat = reinterpret_cast<ParticleMat*>(obj->ConvertToType(ticks, MATTERWAVES_CLASS_ID)); pTPMasterSystemInt = reinterpret_cast<TP_MasterSystemInterface*>(obj->GetInterface(IID_TP_MASTERSYSTEM)); } #endif const bool bAutomaticInstancing = GetCurrentJob()->GetOption("automaticInstancing"); if( #ifdef THINKING_PARTICLES !pThinkingParticleMat && #endif !particlesExt && !pSimpleParticle){ return false; } //We have to put the particle system into the renders state so that PFOperatorMaterialFrequency::Proceed will set the materialID channel //Note: settting the render state to true breaks the shape node instancing export bool bRenderStateForced = false; if(bAutomaticInstancing && ipfSystem && !ipfSystem->IsRenderState()){ ipfSystem->SetRenderState(true); bRenderStateForced = true; } int numParticles = 0; #ifdef THINKING_PARTICLES if(pThinkingParticleMat){ numParticles = pThinkingParticleMat->NumParticles(); } else #endif if(particlesExt){ particlesExt->UpdateParticles(mMaxNode, ticks); numParticles = particlesExt->NumParticles(); } else if(pSimpleParticle){ pSimpleParticle->Update(ticks, mMaxNode); numParticles = pSimpleParticle->parts.points.Count(); } // Store positions, velocity, width/size, scale, id, bounding box std::vector<Abc::V3f> positionVec; std::vector<Abc::V3f> velocityVec; std::vector<Abc::V3f> scaleVec; std::vector<float> widthVec; std::vector<float> ageVec; std::vector<float> massVec; std::vector<float> shapeTimeVec; std::vector<Abc::uint64_t> idVec; std::vector<Abc::uint16_t> shapeTypeVec; std::vector<Abc::uint16_t> shapeInstanceIDVec; std::vector<Abc::Quatf> orientationVec; std::vector<Abc::Quatf> angularVelocityVec; std::vector<Abc::C4f> colorVec; positionVec.reserve(numParticles); velocityVec.reserve(numParticles); scaleVec.reserve(numParticles); widthVec.reserve(numParticles); ageVec.reserve(numParticles); massVec.reserve(numParticles); shapeTimeVec.reserve(numParticles); idVec.reserve(numParticles); shapeTypeVec.reserve(numParticles); shapeInstanceIDVec.reserve(numParticles); orientationVec.reserve(numParticles); angularVelocityVec.reserve(numParticles); colorVec.reserve(numParticles); //std::vector<std::string> instanceNamesVec; Abc::Box3d bbox; bool constantPos = true; bool constantVel = true; bool constantScale = true; bool constantWidth = true; bool constantAge = true; bool constantOrientation = true; bool constantAngularVel = true; bool constantColor = true; if(bAutomaticInstancing){ SetMaxSceneTime(ticks); } //The MAX interfaces return everything in world coordinates, //so we need to multiply the inverse the node world transform matrix Matrix3 nodeWorldTM = mMaxNode->GetObjTMAfterWSM(ticks); // Convert the max transform to alembic Matrix3 alembicMatrix; ConvertMaxMatrixToAlembicMatrix(nodeWorldTM, alembicMatrix); Abc::M44d nodeWorldTrans( alembicMatrix.GetRow(0).x, alembicMatrix.GetRow(0).y, alembicMatrix.GetRow(0).z, 0, alembicMatrix.GetRow(1).x, alembicMatrix.GetRow(1).y, alembicMatrix.GetRow(1).z, 0, alembicMatrix.GetRow(2).x, alembicMatrix.GetRow(2).y, alembicMatrix.GetRow(2).z, 0, alembicMatrix.GetRow(3).x, alembicMatrix.GetRow(3).y, alembicMatrix.GetRow(3).z, 1); Abc::M44d nodeWorldTransInv = nodeWorldTrans.inverse(); //ESS_LOG_WARNING("tick: "<<ticks<<" numParticles: "<<numParticles<<"\n"); ExoNullView nullView; particleGroupInterface groupInterface(particlesExt, obj, mMaxNode, &nullView); { ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop"); for (int i = 0; i < numParticles; ++i) { Abc::V3f pos(0.0); Abc::V3f vel(0.0); Abc::V3f scale(1.0); Abc::C4f color(0.5, 0.5, 0.5, 1.0); float age = 0; Abc::uint64_t id = 0; Abc::Quatd orientation(0.0, 0.0, 1.0, 0.0); Abc::Quatd spin(0.0, 0.0, 1.0, 0.0); // Particle size is a uniform scale multiplier in XSI. In Max, I need to learn where to get this // For now, we'll just default to 1 float width = 1.0f; ShapeType shapetype = ShapeType_Point; float shapeInstanceTime = (float)time; Abc::uint16_t shapeInstanceId = 0; #ifdef THINKING_PARTICLES if(pThinkingParticleMat){ if(pTPMasterSystemInt->IsAlive(i) == FALSE){ continue; } //TimeValue ageValue = particlesExt->GetParticleAgeByIndex(i); TimeValue ageValue = pTPMasterSystemInt->Age(i); if(ageValue == -1){ continue; } ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles"); age = (float)GetSecondsFromTimeValue(ageValue); //pos = ConvertMaxPointToAlembicPoint(*particlesExt->GetParticlePositionByIndex(i)); pos = ConvertMaxPointToAlembicPoint(pTPMasterSystemInt->Position(i)); //vel = ConvertMaxVectorToAlembicVector(*particlesExt->GetParticleSpeedByIndex(i) * TIME_TICKSPERSEC); vel = ConvertMaxVectorToAlembicVector(pTPMasterSystemInt->Velocity(i) * TIME_TICKSPERSEC); scale = ConvertMaxScaleToAlembicScale(pTPMasterSystemInt->Scale(i)); scale *= pTPMasterSystemInt->Size(i); //ConvertMaxEulerXYZToAlembicQuat(*particlesExt->GetParticleOrientationByIndex(i), orientation); Matrix3 alignmentMatMax = pTPMasterSystemInt->Alignment(i); Abc::M44d alignmentMat; ConvertMaxMatrixToAlembicMatrix(alignmentMatMax, alignmentMat); /*alignmentMat = Abc::M44d( alignmentMatMax.GetRow(0).x, alignmentMatMax.GetRow(0).y, alignmentMatMax.GetRow(0).z, 0, alignmentMatMax.GetRow(1).x, alignmentMatMax.GetRow(1).y, alignmentMatMax.GetRow(1).z, 0, alignmentMatMax.GetRow(2).x, alignmentMatMax.GetRow(2).y, alignmentMatMax.GetRow(2).z, 0, alignmentMatMax.GetRow(3).x, alignmentMatMax.GetRow(3).y, alignmentMatMax.GetRow(3).z, 1);*/ //orientation = ConvertMaxQuatToAlembicQuat(extracctuat(alignmentMat), true); alignmentMat = alignmentMat * nodeWorldTransInv; orientation = extractQuat(alignmentMat); //ConvertMaxAngAxisToAlembicQuat(*particlesExt->GetParticleSpinByIndex(i), spin); ConvertMaxAngAxisToAlembicQuat(pTPMasterSystemInt->Spin(i), spin); id = particlesExt->GetParticleBornIndex(i); //seems to always return 0 //int nPid = pThinkingParticleMat->ParticleID(i); int nMatId = -1; Matrix3 meshTM; meshTM.IdentityMatrix(); BOOL bNeedDelete = FALSE; BOOL bChanged = FALSE; Mesh* pMesh = NULL; { ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles - GetParticleRenderMesh"); pMesh = pThinkingParticleMat->GetParticleRenderMesh(ticks, mMaxNode, nullView, bNeedDelete, i, meshTM, bChanged); } if(pMesh){ ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - ThinkingParticles - CacheShapeMesh"); meshInfo mi = CacheShapeMesh(pMesh, bNeedDelete, meshTM, nMatId, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime); Abc::V3d min = pos + mi.bbox.min; Abc::V3d max = pos + mi.bbox.max; bbox.extendBy(min); bbox.extendBy(max); } else{ shapetype = ShapeType_Point; } } else #endif if(particlesExt && ipfSystem){ TimeValue ageValue = particlesExt->GetParticleAgeByIndex(i); if(ageValue == -1){ continue; } age = (float)GetSecondsFromTimeValue(ageValue); pos = ConvertMaxPointToAlembicPoint(*particlesExt->GetParticlePositionByIndex(i)); vel = ConvertMaxVectorToAlembicVector(*particlesExt->GetParticleSpeedByIndex(i) * TIME_TICKSPERSEC); scale = ConvertMaxScaleToAlembicScale(*particlesExt->GetParticleScaleXYZByIndex(i)); ConvertMaxEulerXYZToAlembicQuat(*particlesExt->GetParticleOrientationByIndex(i), orientation); ConvertMaxAngAxisToAlembicQuat(*particlesExt->GetParticleSpinByIndex(i), spin); //age = (float)GetSecondsFromTimeValue(particlesExt->GetParticleAgeByIndex(i)); id = particlesExt->GetParticleBornIndex(i); if(bAutomaticInstancing){ int nMatId = -1; if(ipfSystem){ if( groupInterface.setCurrentParticle(ticks, i) ){ nMatId = groupInterface.getCurrentMtlId(); } else{ ESS_LOG_WARNING("Error: cound retrieve material ID for particle mesh "<<i); } } Matrix3 meshTM; meshTM.IdentityMatrix(); BOOL bNeedDelete = FALSE; BOOL bChanged = FALSE; Mesh* pMesh = pMesh = particlesExt->GetParticleShapeByIndex(i); if(pMesh){ meshInfo mi = CacheShapeMesh(pMesh, bNeedDelete, meshTM, nMatId, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime); Abc::V3d min = pos + mi.bbox.min; Abc::V3d max = pos + mi.bbox.max; bbox.extendBy(min); bbox.extendBy(max); } else{ shapetype = ShapeType_Point; } } else{ GetShapeType(particlesExt, i, ticks, shapetype, shapeInstanceId, shapeInstanceTime); } color = GetColor(particlesExt, i, ticks); } else if(pSimpleParticle){ if( ! pSimpleParticle->parts.Alive( i ) ) { continue; } pos = ConvertMaxPointToAlembicPoint(pSimpleParticle->ParticlePosition(ticks, i)); vel = ConvertMaxVectorToAlembicVector(pSimpleParticle->ParticleVelocity(ticks, i)); //simple particles have no scale? //simple particles have no orientation? age = (float)GetSecondsFromTimeValue( pSimpleParticle->ParticleAge(ticks, i) ); //simple particles have born index width = pSimpleParticle->ParticleSize(ticks, i); Abc::V3d min(pos.x - width/2, pos.y - width/2, pos.z - width/2); Abc::V3d max(pos.x + width/2, pos.y + width/2, pos.z + width/2); bbox.extendBy(min); bbox.extendBy(max); } { ESS_PROFILE_SCOPE("AlembicPoints::SAVE - numParticlesLoop - end loop save"); //move everything from world space to local space pos = pos * nodeWorldTransInv; Abc::V4f vel4(vel.x, vel.y, vel.z, 0.0); vel4 = vel4 * nodeWorldTransInv; vel.setValue(vel4.x, vel4.y, vel4.z); //scale = scale * nodeWorldTransInv; //orientation = Abc::extractQuat(orientation.toMatrix44() * nodeWorldTransInv); //spin = Abc::extractQuat(spin.toMatrix44() * nodeWorldTransInv); bbox.extendBy( pos ); positionVec.push_back( pos ); velocityVec.push_back( vel ); scaleVec.push_back( scale ); widthVec.push_back( width ); ageVec.push_back( age ); idVec.push_back( id ); orientationVec.push_back( orientation ); angularVelocityVec.push_back( spin ); shapeTypeVec.push_back( shapetype ); shapeInstanceIDVec.push_back( shapeInstanceId ); shapeTimeVec.push_back( shapeInstanceTime ); colorVec.push_back( color ); constantPos &= (pos == positionVec[0]); constantVel &= (vel == velocityVec[0]); constantScale &= (scale == scaleVec[0]); constantWidth &= (width == widthVec[0]); constantAge &= (age == ageVec[0]); constantOrientation &= (orientation == orientationVec[0]); constantAngularVel &= (spin == angularVelocityVec[0]); constantColor &= (color == colorVec[0]); // Set the archive bounding box // Positions for particles are already cnsider to be in world space if (mJob) { mJob->GetArchiveBBox().extendBy(pos); } } } } // if (numParticles > 1) // { // ESS_PROFILE_SCOPE("AlembicPoints::Save - vectorResize"); // if (constantPos) { positionVec.resize(1); } // if (constantVel) { velocityVec.resize(1); } // if (constantScale) { scaleVec.resize(1); } // if (constantWidth) { widthVec.resize(1); } // if (constantAge) { ageVec.resize(1); } // if (constantOrientation){ orientationVec.resize(1); } // if (constantAngularVel) { angularVelocityVec.resize(1); } //if (constantColor) { colorVec.resize(1); } // } { ESS_PROFILE_SCOPE("AlembicPoints::Save - sample writing"); // Store the information into our properties and points schema Abc::P3fArraySample positionSample( positionVec); Abc::P3fArraySample velocitySample(velocityVec); Abc::P3fArraySample scaleSample(scaleVec); Abc::FloatArraySample widthSample(widthVec); Abc::FloatArraySample ageSample(ageVec); Abc::FloatArraySample massSample(massVec); Abc::FloatArraySample shapeTimeSample(shapeTimeVec); Abc::UInt64ArraySample idSample(idVec); Abc::UInt16ArraySample shapeTypeSample(shapeTypeVec); Abc::UInt16ArraySample shapeInstanceIDSample(shapeInstanceIDVec); Abc::QuatfArraySample orientationSample(orientationVec); Abc::QuatfArraySample angularVelocitySample(angularVelocityVec); Abc::C4fArraySample colorSample(colorVec); mScaleProperty.set(scaleSample); mAgeProperty.set(ageSample); mMassProperty.set(massSample); mShapeTimeProperty.set(shapeTimeSample); mShapeTypeProperty.set(shapeTypeSample); mShapeInstanceIDProperty.set(shapeInstanceIDSample); mOrientationProperty.set(orientationSample); mAngularVelocityProperty.set(angularVelocitySample); mColorProperty.set(colorSample); mPointsSample.setPositions(positionSample); mPointsSample.setVelocities(velocitySample); mPointsSample.setWidths(AbcG::OFloatGeomParam::Sample(widthSample, AbcG::kVertexScope)); mPointsSample.setIds(idSample); mPointsSample.setSelfBounds(bbox); mPointsSchema.getChildBoundsProperty().set( bbox); mPointsSchema.set(mPointsSample); } mNumSamples++; //mInstanceNames.pop_back(); if(bAutomaticInstancing){ saveCurrentFrameMeshes(); } if(bRenderStateForced){ ipfSystem->SetRenderState(false); } if(bLastFrame){ ESS_PROFILE_SCOPE("AlembicParticles::Save - save instance names property"); std::vector<std::string> instanceNames(mNumShapeMeshes); for(faceVertexHashToShapeMap::iterator it = mShapeMeshCache.begin(); it != mShapeMeshCache.end(); it++){ std::stringstream pathStream; pathStream << "/" << it->second.name<< "/" << it->second.name <<"Shape"; instanceNames[it->second.nMeshInstanceId] = pathStream.str(); } //for some reason the .dims property is not written when there is exactly one entry if we don't push an empty string //having an extra unreferenced entry seems to be harmless instanceNames.push_back(""); mInstanceNamesProperty.set(Abc::StringArraySample(instanceNames)); } return true; }
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."); } }
//we have to save out all mesh encountered on the current frame of this object immediately, because //the pointers will no longer be valid when the object is evaluated at a new time void AlembicPoints::saveCurrentFrameMeshes() { ESS_PROFILE_FUNC(); for(int i=0; i<mMeshesToSaveForCurrentFrame.size(); i++){ //TODO: save immediately instead accumulating in a vector meshInfo* mi = mMeshesToSaveForCurrentFrame[i]; if(mi->pMesh){ Mesh* pMesh = mi->pMesh; //mi->pMesh = NULL;//each mesh only needs to be saved once //Matrix3 worldTrans; //worldTrans.IdentityMatrix(); CommonOptions options; options.SetOption("exportNormals", mJob->GetOption("exportNormals")); options.SetOption("exportMaterialIds", mJob->GetOption("exportMaterialIds")); //gather the mesh data mi->meshTM.IdentityMatrix(); IntermediatePolyMesh3DSMax finalPolyMesh; { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - finalPolyMesh.Save"); Imath::M44f transform44f; ConvertMaxMatrixToAlembicMatrix( mi->meshTM, transform44f ); SceneNodeMaxParticlesPtr inputSceneNode(new SceneNodeMaxParticles(pMesh, NULL, mi->nMatId)); finalPolyMesh.Save(inputSceneNode, transform44f, options, 0.0); } AbcG::OPolyMeshSchema::Sample meshSample; AbcG::OPolyMeshSchema meshSchema; { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - save xforms, bbox, geo, topo"); //save out the mesh xForm //std::string xformName = mi->name + "Xfo"; AbcG::OXform xform(mJob->GetArchive().getTop(), mi->name, GetCurrentJob()->GetAnimatedTs()); AbcG::OXformSchema& xformSchema = xform.getSchema();//mi->xformSchema; std::string meshName = mi->name + "Shape"; AbcG::OPolyMesh mesh(xform, meshName, GetCurrentJob()->GetAnimatedTs()); meshSchema = mesh.getSchema(); AbcG::XformSample xformSample; Matrix3 alembicMatrix; alembicMatrix.IdentityMatrix(); alembicMatrix.SetTrans(Point3(-10000.0f, -10000.0f, -10000.0f)); Abc::M44d iMatrix; ConvertMaxMatrixToAlembicMatrix(alembicMatrix, iMatrix); xformSample.setMatrix(iMatrix); xformSchema.set(xformSample); //update the archive bounding box Abc::Box3d bbox; bbox.min = finalPolyMesh.bbox.min * iMatrix; bbox.max = finalPolyMesh.bbox.max * iMatrix; mJob->GetArchiveBBox().extendBy(bbox); //save out the mesh data meshSample.setPositions(Abc::P3fArraySample(finalPolyMesh.posVec)); meshSample.setSelfBounds(finalPolyMesh.bbox); meshSchema.getChildBoundsProperty().set(finalPolyMesh.bbox); meshSample.setFaceCounts(Abc::Int32ArraySample(finalPolyMesh.mFaceCountVec)); meshSample.setFaceIndices(Abc::Int32ArraySample(finalPolyMesh.mFaceIndicesVec)); } if(mJob->GetOption("validateMeshTopology")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - validateMeshTopology"); mJob->mMeshErrors += validateAlembicMeshTopo(finalPolyMesh.mFaceCountVec, finalPolyMesh.mFaceIndicesVec, mi->name); } if(mJob->GetOption("exportNormals")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - exportNormals"); AbcG::ON3fGeomParam::Sample normalSample; normalSample.setScope(AbcG::kFacevaryingScope); normalSample.setVals(Abc::N3fArraySample(finalPolyMesh.mIndexedNormals.values)); normalSample.setIndices(Abc::UInt32ArraySample(finalPolyMesh.mIndexedNormals.indices)); meshSample.setNormals(normalSample); } if(mJob->GetOption("exportMaterialIds")){ ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes - exportMaterialIds"); Abc::OUInt32ArrayProperty mMatIdProperty = Abc::OUInt32ArrayProperty(meshSchema, ".materialids", meshSchema.getMetaData(), mJob->GetAnimatedTs()); mMatIdProperty.set(Abc::UInt32ArraySample(finalPolyMesh.mMatIdIndexVec)); for ( facesetmap_it it=finalPolyMesh.mFaceSets.begin(); it != finalPolyMesh.mFaceSets.end(); it++) { std::stringstream nameStream; int nMaterialId = it->first+1; nameStream<<it->second.name<<"_"<<nMaterialId; std::vector<Abc::int32_t>& faceSetVec = it->second.faceIds; AbcG::OFaceSet faceSet = meshSchema.createFaceSet(nameStream.str()); AbcG::OFaceSetSchema::Sample faceSetSample(Abc::Int32ArraySample(&faceSetVec.front(), faceSetVec.size())); faceSet.getSchema().set(faceSetSample); } } if(mJob->GetOption("exportUVs")){ //TODO... } { ESS_PROFILE_SCOPE("AlembicPoints::saveCurrentFrameMeshes meshSchema.set"); meshSchema.set(meshSample); } if(mi->bNeedDelete){ delete mi->pMesh; mi->bNeedDelete = FALSE; } mi->pMesh = NULL; } } mMeshesToSaveForCurrentFrame.clear(); }
int ServerQAction(int *addr, short *port, int *op, int *flags, int *jobid, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6, void *p7, void *p8) { int status; switch (*op) { case SrvRemoveLast: { status = RemoveLast(); break; } case SrvAbort: { ServerSetDetailProc(0); KillThread(); AbortJob(GetCurrentJob()); ReleaseCurrentJob(); SetCurrentJob(0); if (*(int *)p1) { SrvJob *job; while ((job = NextJob(0)) != 0) AbortJob(job); } status = StartThread(); break; } case SrvAction: { SrvActionJob job; job.h.addr = MdsGetClientAddr(); job.h.port = *port; job.h.op = *op; job.h.length = sizeof(job); job.h.flags = *flags; job.h.jobid = *jobid; job.tree = strcpy(malloc(strlen((char *)p1)+1),(char *)p1); job.shot = *(int *)p2; job.nid = *(int *)p3; status = QJob((SrvJob *)&job); break; } case SrvClose: { SrvCloseJob job; job.h.addr = MdsGetClientAddr(); job.h.port = *port; job.h.op = *op; job.h.length = sizeof(job); job.h.flags = *flags; job.h.jobid = *jobid; status = QJob((SrvJob *)&job); break; } case SrvCreatePulse: { SrvCreatePulseJob job; job.h.addr = MdsGetClientAddr(); job.h.port = *port; job.h.op = *op; job.h.length = sizeof(job); job.h.flags = *flags; job.h.jobid = *jobid; job.tree = strcpy(malloc(strlen((char *)p1)+1),(char *)p1); job.shot = *(int *)p2; status = QJob((SrvJob *)&job); break; } case SrvSetLogging: { Logging = *(int *)p1; break; } case SrvCommand: { SrvCommandJob job; job.h.addr = MdsGetClientAddr(); job.h.port = *port; job.h.op = *op; job.h.length = sizeof(job); job.h.flags = *flags; job.h.jobid = *jobid; job.table = strcpy(malloc(strlen((char *)p1)+1),(char *)p1); job.command = strcpy(malloc(strlen((char *)p2)+1),(char *)p2); status = QJob((SrvJob *)&job); break; } case SrvMonitor: { SrvMonitorJob job; job.h.addr = MdsGetClientAddr(); job.h.port = *port; job.h.op = *op; job.h.length = sizeof(job); job.h.flags = *flags; job.h.jobid = *jobid; job.tree = strcpy(malloc(strlen((char *)p1)+1),(char *)p1); job.shot = *(int *)p2; job.phase = *(int *)p3; job.nid = *(int *)p4; job.on = *(int *)p5; job.mode = *(int *)p6; job.server = strcpy(malloc(strlen((char *)p7)+1),(char *)p7); job.status = *(int *)p8; status = QJob((SrvJob *)&job); break; } case SrvShow: { status = ShowCurrentJob((struct descriptor_xd *)p1); break; } case SrvStop: { printf("%s, Server stop requested\n",Now()); exit(0); break; } } return status; }