const Vector & SSPquadUP::getResistingForceIncInertia() { // terms stemming from acceleration const Vector &accel1 = theNodes[0]->getTrialAccel(); const Vector &accel2 = theNodes[1]->getTrialAccel(); const Vector &accel3 = theNodes[2]->getTrialAccel(); const Vector &accel4 = theNodes[3]->getTrialAccel(); // compute current resisting force this->getResistingForce(); // compute mass matrix this->getMass(); Vector a(12); a(0) = accel1(0); a(1) = accel1(1); a(2) = accel1(2); a(3) = accel2(0); a(4) = accel2(1); a(5) = accel2(2); a(6) = accel3(0); a(7) = accel3(1); a(8) = accel3(2); a(9) = accel4(0); a(10) = accel4(1); a(11) = accel4(2); mInternalForces.addMatrixVector(1.0, mMass, a, 1.0); // terms stemming from velocity const Vector &vel1 = theNodes[0]->getTrialVel(); const Vector &vel2 = theNodes[1]->getTrialVel(); const Vector &vel3 = theNodes[2]->getTrialVel(); const Vector &vel4 = theNodes[3]->getTrialVel(); Vector v(12); v(0) = vel1(0); v(1) = vel1(1); v(2) = vel1(2); v(3) = vel2(0); v(4) = vel2(1); v(5) = vel2(2); v(6) = vel3(0); v(7) = vel3(1); v(8) = vel3(2); v(9) = vel4(0); v(10) = vel4(1); v(11) = vel4(2); // compute damping matrix this->getDamp(); mInternalForces.addMatrixVector(1.0, mDamp, v, 1.0); return mInternalForces; }
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; }
const Vector& FourNodeQuadUP::getResistingForceIncInertia() { int i, j, k; const Vector &accel1 = nd1Ptr->getTrialAccel(); const Vector &accel2 = nd2Ptr->getTrialAccel(); const Vector &accel3 = nd3Ptr->getTrialAccel(); const Vector &accel4 = nd4Ptr->getTrialAccel(); static double a[12]; a[0] = accel1(0); a[1] = accel1(1); a[2] = accel1(2); a[3] = accel2(0); a[4] = accel2(1); a[5] = accel2(2); a[6] = accel3(0); a[7] = accel3(1); a[8] = accel3(2); a[9] = accel4(0); a[10] = accel4(1); a[11] = accel4(2); // Compute the current resisting force this->getResistingForce(); //opserr<<"K "<<P<<endln; // Compute the mass matrix this->getMass(); for (i = 0; i < 12; i++) { for (j = 0; j < 12; j++) P(i) += K(i,j)*a[j]; } //opserr<<"K+M "<<P<<endln; // dynamic seepage force /*for (i = 0, k = 0; i < 4; i++, k += 3) { // loop over integration points for (j = 0; j < 4; j++) { P(i+2) -= rho*dvol[j]*(shp[2][i][j]*a[k]*perm[0]*shp[0][i][j] +shp[2][i][j]*a[k+1]*perm[1]*shp[1][i][j]); } }*/ //opserr<<"K+M+fb "<<P<<endln; const Vector &vel1 = nd1Ptr->getTrialVel(); const Vector &vel2 = nd2Ptr->getTrialVel(); const Vector &vel3 = nd3Ptr->getTrialVel(); const Vector &vel4 = nd4Ptr->getTrialVel(); a[0] = vel1(0); a[1] = vel1(1); a[2] = vel1(2); a[3] = vel2(0); a[4] = vel2(1); a[5] = vel2(2); a[6] = vel3(0); a[7] = vel3(1); a[8] = vel3(2); a[9] = vel4(0); a[10] = vel4(1); a[11] = vel4(2); this->getDamp(); for (i = 0; i < 12; i++) { for (j = 0; j < 12; j++) { P(i) += K(i,j)*a[j]; } } //opserr<<"final "<<P<<endln; return P; }