bool BsonDocument::InstantiateObject(DynamicObject::Table &t, DynamicObject &obj) { for(DynamicObject::Iterator it = t.begin();it != t.end();++it) { boost::shared_ptr<TypeInfoBase> member = obj.GetMember(it->first); if (member.get()==NULL) continue; if (member->IsArray()) { boost::shared_ptr<ArrayBase> dest = boost::dynamic_pointer_cast<ArrayBase>(member); boost::shared_ptr<ArrayBase> source = boost::dynamic_pointer_cast<ArrayBase>(it->second); if (source.get()==NULL || dest.get()==NULL) continue; size_t count = source->Count(); for(size_t i=0; i<count;++i) { boost::shared_ptr<TypeInfoBase> ps = (*source)[i]; if (ps.get()==NULL) //invalid member continue; if (ps->IsObject()) { DynamicObject::Table &h = ps->GetObject<DynamicObject>()->GetTable(); boost::shared_ptr<DynamicObject> o = ClassFactory::CreateObject(dest->ClassName); if (o.get() == NULL) continue; InstantiateObject(h, *o); boost::shared_ptr<TypeInfoBase> pBase(new TypeInfo<DynamicObject>(o)); dest->Add(pBase); } else { dest->Add(ps); } } it->second.reset(); continue; } else if (member->IsObject()) { boost::shared_ptr<TypeInfoBase> info = it->second; if (!info->IsObject()) continue; DynamicObject::Table &h = info->GetObject<DynamicObject>()->GetTable(); boost::shared_ptr<DynamicObject> o = member->GetObject<DynamicObject>(); if (o.get() != NULL) InstantiateObject(h,*o); continue; } //else boost::shared_ptr<TypeInfoBase> p = it->second; if (p->GetType()!=member->GetType()) { if (p->GetType()==typeid(double) && member->GetType()==typeid(float)) { boost::shared_ptr<double> d = p->GetObject<double>(); boost::shared_ptr<float> f = member->GetObject<float>(); *f=float(*d); } else if (p->GetType()==typeid(int64_t) && member->GetType()==typeid(uint64_t)) { boost::shared_ptr<int64_t> d = p->GetObject<int64_t>(); boost::shared_ptr<uint64_t> f = member->GetObject<uint64_t>(); *f=uint64_t(*d); } else if (p->GetType()==typeid(int) && member->GetType()==typeid(uint32_t)) { boost::shared_ptr<int> d = p->GetObject<int>(); boost::shared_ptr<uint32_t> f = member->GetObject<uint32_t>(); *f=uint32_t(*d); } } else { if (p->IsBinary()) { boost::shared_ptr<TypeInfo<Binary> > binarySource = boost::dynamic_pointer_cast<TypeInfo<Binary> >(p); boost::shared_ptr<TypeInfo<Binary> > binaryDest = boost::dynamic_pointer_cast<TypeInfo<Binary> >(member); if (binarySource.get()!=NULL && binaryDest.get()!=NULL) *binaryDest->GetObject() = *binarySource->GetObject(); } else if (p->GetType() == typeid(string)) { boost::shared_ptr<string> strSource = p->GetObject<string>(); boost::shared_ptr<string> strDest = member->GetObject<string>(); if (strSource.get()!=NULL && strDest.get()!=NULL) *strDest = *strSource; } else { if (member->GetObject().get() !=NULL && p->GetObject().get() != NULL) memcpy(member->GetObject().get(), p->GetObject().get(), p->GetSize()); } } } return true; }
void POVRayExport::exportParticle(std::ofstream& os, const shared_ptr<Particle>& p){ const auto sphere=dynamic_cast<Sphere*>(p->shape.get()); const auto capsule=dynamic_cast<Capsule*>(p->shape.get()); const auto ellipsoid=dynamic_cast<Ellipsoid*>(p->shape.get()); const auto wall=dynamic_cast<Wall*>(p->shape.get()); const auto infCyl=dynamic_cast<InfCylinder*>(p->shape.get()); const auto facet=dynamic_cast<Facet*>(p->shape.get()); // convenience const auto& n0(p->shape->nodes[0]); if(sphere) os<<"sphere{ o, "<<sphere->radius<<" "<<makeTexture(p)<<" "<<node2pov(n0)<<" }"; else if(capsule) os<<"sphere_sweep{ linear_spline, 2, <"<<-.5*capsule->shaft<<",0,0> ,"<<capsule->radius<<", <"<<.5*capsule->shaft<<",0,0> ,"<<capsule->radius<<" "<<makeTexture(p)<<" "<<node2pov(n0)<<" }"; else if(ellipsoid) os<<"sphere{ o, 1 scale "<<vec2pov(ellipsoid->semiAxes)<<" "<<makeTexture(p)<<" "<<node2pov(n0)<<" }"; else if(wall){ if((wall->glAB.isEmpty())){ os<<"plane{ "<<Vector3r::Unit(wall->axis)<<", "<<wall->nodes[0]->pos[wall->axis]; } else{ // quad, as mesh2 Vector3r a; a[wall->axis]=wall->nodes[0]->pos[wall->axis]; Vector3r b(a), c(a), d(a); short ax1((wall->axis+1)%3), ax2((wall->axis+2)%3); a[ax1]=wall->glAB.min()[0]; a[ax2]=wall->glAB.min()[1]; b[ax1]=wall->glAB.min()[0]; b[ax2]=wall->glAB.max()[1]; c[ax1]=wall->glAB.max()[0]; c[ax2]=wall->glAB.min()[1]; d[ax1]=wall->glAB.max()[0]; d[ax2]=wall->glAB.max()[1]; os<<"mesh2{ vertex_vectors { 4 "<<vec2pov(a)<<", "<<vec2pov(b)<<", "<<vec2pov(c)<<", "<<vec2pov(d)<<" } face_indices { 2, <0,2,1>, <1,2,3> }"; } os<<makeTexture(p,wallTexture)<<" }"; // will use the default if wallTexture is empty } else if(infCyl){ if(isnan(infCyl->glAB.maxCoeff())){ // infinite cylinder, use quadric for this Vector3r abc=Vector3r::Ones(); abc[infCyl->axis]=0; os<<"quadric{ "<<vec2pov(abc)<<", <0,0,0>, <0,0,0>, -1 "<<makeTexture(p)<<" "<<node2pov(n0)<<" }"; } else { #if 0 #endif // base point (global coords), first center Vector3r pBase(n0->pos); pBase[infCyl->axis]+=infCyl->glAB[0]; // axis vector (global coords), pBase+pAxis is the second center Vector3r pAxis(Vector3r::Zero()); pAxis[infCyl->axis]=infCyl->glAB[1]-infCyl->glAB[0]; // axial rotation; warn if not around the axis AngleAxisr aa(n0->ori); Vector3r axRotVecDeg(aa.axis()*aa.angle()*180./M_PI); if(aa.angle()>1e-6 && abs(aa.axis()[infCyl->axis])<.999999) LOG_WARN("#"<<p->id<<": InfCylinder rotation not aligned with its axis (cylinder axis "<<infCyl->axis<<"; rotation axis "<<aa.axis()<<", angle "<<aa.angle()<<")"); bool open=!cylCapTexture.empty(); if(open){ os<<"/*capped cylinder*/"; Vector3r normal=Vector3r::Unit(infCyl->axis); for(int i:{-1,1}){ os<<"disc{ o, "<<vec2pov(i*normal)<<", "<<infCyl->radius<<" "<<makeTexture(p,cylCapTexture)<<" rotate "<<vec2pov(axRotVecDeg)<<" translate "<<vec2pov(i<0?pBase:(pBase+pAxis).eval()); os<<" }"; } } // length of the cylinder Real cylLen=(infCyl->glAB[1]-infCyl->glAB[0]); // non-axial rotation, from +x cyl to infCyl->axis (case-by-case) Vector3r nonAxRotVec=(infCyl->axis==0?Vector3r::Zero():(infCyl->axis==1?Vector3r(0,0,90):Vector3r(0,-90,0))); // cylinder spans +x*cylLen from origin, then rotated, so that the texture is rotated as well os<<"cylinder{ o, <"<<cylLen<<",0,0>, "<<infCyl->radius<<(open?" open ":" ")<<" "<<makeTexture(p)<<" rotate "<<vec2pov(nonAxRotVec)<<" rotate "<<vec2pov(axRotVecDeg)<<" translate "<<vec2pov(pBase)<<" }"; } } else if(facet){ // halfThick ignored for now, as well as connectivity if(facet->halfThick>0){ Vector3r dp=facet->getNormal()*facet->halfThick; const Vector3r& a(facet->nodes[0]->pos); const Vector3r& b(facet->nodes[1]->pos); const Vector3r& c(facet->nodes[2]->pos); os<<"merge{ sphere_sweep{ linear_spline, 4 "<<vec2pov(a)<<", "<<facet->halfThick<<", "<<vec2pov(b)<<", "<<facet->halfThick<<", "<<vec2pov(c)<<", "<<facet->halfThick<<", "<<vec2pov(a)<<", "<<facet->halfThick<<" } triangle{"<<vec2pov(a+dp)<<", "<<vec2pov(b+dp)<<", "<<vec2pov(c+dp)<<" } triangle {"<<vec2pov(a-dp)<<", "<<vec2pov(b-dp)<<", "<<vec2pov(c-dp)<<" } "<<makeTexture(p)<<" }"; } else { os<<"triangle{ "<<vec2pov(facet->nodes[0]->pos)<<", "<<vec2pov(facet->nodes[1]->pos)<<", "<<vec2pov(facet->nodes[2]->pos)<<" "<<makeTexture(p)<<" }"; } } os<<" // id="<<p->id<<endl; }
bool ezSurfaceResource::InteractWithSurface(ezWorld* pWorld, ezGameObjectHandle hObject, const ezVec3& vPosition, const ezVec3& vSurfaceNormal, const ezVec3& vIncomingDirection, const ezTempHashedString& sInteraction, const ezUInt16* pOverrideTeamID) { const ezSurfaceInteraction* pIA = nullptr; if (!m_Interactions.TryGetValue(sInteraction.GetHash(), pIA)) { // if this type of interaction is not defined on this surface, try to find it on the base surface if (m_Descriptor.m_hBaseSurface.IsValid()) { ezResourceLock<ezSurfaceResource> pBase(m_Descriptor.m_hBaseSurface, ezResourceAcquireMode::NoFallback); return pBase->InteractWithSurface(pWorld, hObject, vPosition, vSurfaceNormal, vIncomingDirection, sInteraction, pOverrideTeamID); } return false; } // defined, but set to be empty if (!pIA->m_hPrefab.IsValid()) return false; ezResourceLock<ezPrefabResource> pPrefab(pIA->m_hPrefab, ezResourceAcquireMode::NoFallback); ezVec3 vDir; switch (pIA->m_Alignment) { case ezSurfaceInteractionAlignment::SurfaceNormal: vDir = vSurfaceNormal; break; case ezSurfaceInteractionAlignment::IncidentDirection: vDir = -vIncomingDirection; ; break; case ezSurfaceInteractionAlignment::ReflectedDirection: vDir = vIncomingDirection.GetReflectedVector(vSurfaceNormal); break; case ezSurfaceInteractionAlignment::ReverseSurfaceNormal: vDir = -vSurfaceNormal; break; case ezSurfaceInteractionAlignment::ReverseIncidentDirection: vDir = vIncomingDirection; ; break; case ezSurfaceInteractionAlignment::ReverseReflectedDirection: vDir = -vIncomingDirection.GetReflectedVector(vSurfaceNormal); break; } vDir.Normalize(); ezVec3 vTangent = vDir.GetOrthogonalVector().GetNormalized(); // random rotation around the spawn direction { double randomAngle = pWorld->GetRandomNumberGenerator().DoubleInRange(0.0, ezMath::BasicType<double>::Pi() * 2.0); ezMat3 rotMat; rotMat.SetRotationMatrix(vDir, ezAngle::Radian((float)randomAngle)); vTangent = rotMat * vTangent; } if (pIA->m_Deviation > ezAngle::Radian(0.0f)) { ezAngle maxDeviation; /// \todo do random deviation, make sure to clamp max deviation angle switch (pIA->m_Alignment) { case ezSurfaceInteractionAlignment::IncidentDirection: case ezSurfaceInteractionAlignment::ReverseReflectedDirection: { const float fCosAngle = vDir.Dot(-vSurfaceNormal); const float fMaxDeviation = ezMath::BasicType<float>::Pi() - ezMath::ACos(fCosAngle).GetRadian(); maxDeviation = ezMath::Min(pIA->m_Deviation, ezAngle::Radian(fMaxDeviation)); } break; case ezSurfaceInteractionAlignment::ReflectedDirection: case ezSurfaceInteractionAlignment::ReverseIncidentDirection: { const float fCosAngle = vDir.Dot(vSurfaceNormal); const float fMaxDeviation = ezMath::BasicType<float>::Pi() - ezMath::ACos(fCosAngle).GetRadian(); maxDeviation = ezMath::Min(pIA->m_Deviation, ezAngle::Radian(fMaxDeviation)); } break; default: maxDeviation = pIA->m_Deviation; break; } const ezAngle deviation = ezAngle::Radian((float)pWorld->GetRandomNumberGenerator().DoubleMinMax(-maxDeviation.GetRadian(), maxDeviation.GetRadian())); // tilt around the tangent (we don't want to compute another random rotation here) ezMat3 matTilt; matTilt.SetRotationMatrix(vTangent, deviation); vDir = matTilt * vDir; } // finally compute the bi-tangent const ezVec3 vBiTangent = vDir.CrossRH(vTangent); ezMat3 mRot; mRot.SetColumn(0, vDir); // we always use X as the main axis, so align X with the direction mRot.SetColumn(1, vTangent); mRot.SetColumn(2, vBiTangent); ezTransform t; t.m_vPosition = vPosition; t.m_qRotation.SetFromMat3(mRot); t.m_vScale.Set(1.0f); // attach to dynamic objects ezGameObjectHandle hParent; ezGameObject* pObject = nullptr; if (pWorld->TryGetObject(hObject, pObject) && pObject->IsDynamic()) { hParent = hObject; t.SetLocalTransform(pObject->GetGlobalTransform(), t); } ezHybridArray<ezGameObject*, 8> rootObjects; pPrefab->InstantiatePrefab(*pWorld, t, hParent, &rootObjects, pOverrideTeamID, nullptr); if (pObject != nullptr && pObject->IsDynamic()) { ezMsgOnlyApplyToObject msg; msg.m_hObject = hParent; for (auto pRootObject : rootObjects) { pRootObject->PostMessageRecursive(msg, ezObjectMsgQueueType::AfterInitialized); } } return true; }