MainApplication::ComponentCollection MainApplication::addDrawDebug(MeshCollider * collider, int level) { BVHNode * root = collider->m_bvh->root(); Material * wireframe = new Material(Shader::find("shader")); wireframe->setAmbientColor(glm::vec4(1.0f)); wireframe->setWireframe(true); std::vector<BVHNode *> nodes; collectBvhs(nodes, root, level, level); int leaves = 0; ComponentCollection components; for (unsigned i = 0; i < nodes.size(); i++) { BoundingSphere * bs = nodes[i]->m_bv; if (nodes[i]->m_isLeaf) leaves++; MeshObject * sphere = new MeshObject(MeshFactory::Sphere(glm::vec4(1.0f), 10), wireframe); sphere->transform().translate(bs->c); sphere->transform().translate(collider->transform().position()); sphere->transform().scale(glm::vec3(1.0f) * bs->r); components.push_back(sphere); } Trace::info("Nodes at level %d: %d (%d leaves)\n", level, nodes.size(), leaves); return components; }
void MainApplication::draw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (ComponentIterator it = m_components.begin(); it != m_components.end(); ++it) { (*it)->draw(); } if (m_debug) { DebugIterator dit = m_debugComponents.find(m_currentLevel); if (dit != m_debugComponents.end()) { ComponentCollection components = dit->second; for (ComponentIterator it = components.begin(); it != components.end(); it++) { (*it)->draw(); } } } std::stringstream ss; ss << "Cloth Simulation Demo" << std::endl; ss << std::setiosflags(std::ios::fixed) << std::setprecision(1); ss << std::endl; if (m_help) { ss << "<Space> Start/reset simulation" << std::endl; ss << "<Enter> Toggle BVH visualization" << std::endl; ss << "<+/-> Adjust BVH visualization level"; if (m_debug) { ss << " (" << m_currentLevel << ")"; } ss << std::endl; ss << "<c> Toggle constrained corners: " << (m_constrained ? "true" : "false") << std::endl; ss << "<v> Toggle moving ball: " << (m_animate ? "true" : "false") << std::endl; ss << "<Numpad 1-9> Adjust wind speed" << std::endl; ss << "<h> Show this help (reduces fps)" << std::endl; ss << std::endl; ss << "Friction: " << SoftBody::FRICTION << std::endl; ss << "Iteration count: " << SoftBody::ITERATION_COUNT << std::endl; ss << "Cloth size: " << SoftBody::WIDTH << "x" << SoftBody::LENGTH << std::endl; } ss << "Wind: (" << SoftBody::WIND.x << ", " << SoftBody::WIND.y << ", " << SoftBody::WIND.z << ")" << std::endl; std::string text = ss.str(); display_text(text.c_str(), 10, 15); GLenum err = glGetError(); if (err != GL_NO_ERROR) Trace::error("OpenGL error: %d\n", err); }
void ComponentCollection::CopyTo(const Reflect::ElementPtr& destination) { __super::CopyTo( destination ); ComponentCollection* destCollection = Reflect::ObjectCast< ComponentCollection >( destination ); if ( destCollection ) { // Remove all attributes, we're going to bring them over manually destCollection->Clear(); // For each component in this component collection Reflect::Registry* registry = Reflect::Registry::GetInstance(); M_Component::const_iterator attrItr = m_Components.begin(); M_Component::const_iterator attrEnd = m_Components.end(); for ( ; attrItr != attrEnd; ++attrItr ) { // Create a new copy of the component and try to add it to the destination const ComponentPtr& attrib = attrItr->second; ComponentPtr destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( attrib->GetClass() ) ); if ( !CopyComponentTo( *destCollection, destAttrib, attrib ) ) { // Component could not be added to the destination collection, check sibling classes const std::set<tstring>& derived = ( registry->GetClass( attrib->GetClass()->m_Base ) )->m_Derived; std::set<tstring>::const_iterator derivedItr = derived.begin(); std::set<tstring>::const_iterator derivedEnd = derived.end(); for ( ; derivedItr != derivedEnd; ++derivedItr ) { const Reflect::Class* currentType = Reflect::Registry::GetInstance()->GetClass(*derivedItr); if ( currentType->m_TypeID != attrib->GetType() ) { destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( currentType ) ); if ( destAttrib.ReferencesObject() ) { if ( CopyComponentTo( *destCollection, destAttrib, attrib ) ) { break; } } } } } } } }
void ComponentCollection::CopyTo(Reflect::Object* object) { Base::CopyTo( object ); ComponentCollection* collection = Reflect::SafeCast< ComponentCollection >( object ); if ( collection ) { // Remove all attributes, we're going to bring them over manually collection->Clear(); // For each component in this component collection Reflect::Registry* registry = Reflect::Registry::GetInstance(); M_Component::const_iterator attrItr = m_Components.begin(); M_Component::const_iterator attrEnd = m_Components.end(); for ( ; attrItr != attrEnd; ++attrItr ) { // Create a new copy of the component and try to add it to the destination const ComponentPtr& attrib = attrItr->second; ComponentPtr destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( attrib->GetMetaClass() ) ); if ( !CopyComponentTo( *collection, destAttrib, attrib ) ) { // Component could not be added to the destination collection, check sibling classes for ( const Composite* sibling = attrib->GetMetaClass()->m_Base->m_FirstDerived; sibling; sibling = sibling->m_NextSibling ) { if ( sibling != attrib->GetMetaClass() ) { destAttrib = Reflect::AssertCast< ComponentBase >( registry->CreateInstance( Reflect::ReflectionCast< const MetaClass >( sibling ) ) ); if ( destAttrib.ReferencesObject() ) { if ( CopyComponentTo( *collection, destAttrib, attrib ) ) { break; } } } } } } } }
bool ComponentCollection::CopyComponentTo( ComponentCollection& destCollection, const ComponentPtr& destAttrib, const ComponentPtr& srcAttrib ) { bool inserted = false; Reflect::Registry* registry = Reflect::Registry::GetInstance(); tstring unused; // If there is already an component in the destination slot, or the // component is not in the destination, but is allowed to be... if ( destCollection.ValidateComponent( destAttrib, unused ) ) { // Component can be added to the destination collection, so do it! srcAttrib->CopyTo( destAttrib ); destCollection.SetComponent( destAttrib, false ); inserted = true; } else { ComponentPtr existing = destCollection.GetComponent( destAttrib->GetSlot() ); if ( existing.ReferencesObject() ) { destCollection.RemoveComponent( existing->GetSlot() ); if ( destCollection.ValidateComponent( destAttrib, unused ) ) { srcAttrib->CopyTo( destAttrib ); destCollection.SetComponent( destAttrib, false ); inserted = true; } else { destCollection.SetComponent( existing, false ); } } } return inserted; }
void MainApplication::initScene() { m_components.clear(); m_debugComponents.clear(); g_world = SoftBodyWorld(); g_body = 0; // Create wood material Material * woodMaterial = new Material(Shader::find("shader")); woodMaterial->setTexture(new Texture("resources/wood.bmp")); // Load bowl model MeshObject * bowl = new MeshObject(MeshFactory::FromFile("resources/bowl.ply"), woodMaterial); bowl->transform().translate(glm::vec3(0.0f, 2.0f, 0.0f)); bowl->transform().update(); // Load low-poly model of bowl for collision detection Mesh * lowpoly = MeshFactory::FromFile("resources/bowl-low.ply"); MeshCollider * bowlCollider = new MeshCollider(bowl); bowlCollider->m_mesh = lowpoly; bowlCollider->m_bvh = BVH::constructFromMesh(lowpoly); CollisionDetector::instance()->addCollider(bowlCollider); m_components.push_back(bowl); // Create cloth material Material * clothMaterial = new Material(Shader::find("shader")); clothMaterial->setTexture(new Texture("resources/cloth.bmp")); clothMaterial->setDiffuseColor(glm::vec4(0.8f, 0.8f, 0.8f, 1.0f)); clothMaterial->setAmbientColor(glm::vec4(0.3f, 0.3f, 0.3f, 1.0f)); clothMaterial->setSpecularColor(glm::vec4(0.5f, 0.5f, 0.5f, 1.0f)); // Create cloth mesh with attached soft body information MeshObject * cloth = SoftBody::createCloth(clothMaterial, &g_world, &g_body); cloth->transform().translate(glm::vec3(-2.5f, 5.0f, -2.5f)); cloth->transform().update(); m_components.push_back(cloth); // Create material for apple Material * appleMaterial = new Material(Shader::find("shader")); appleMaterial->setDiffuseColor(glm::vec4(0.9f)); appleMaterial->setTexture(new Texture("resources/apple.bmp")); // Load apple model from file MeshObject * apple = new MeshObject(MeshFactory::FromFile("resources/apple.ply"), appleMaterial); apple->transform().translate(glm::vec3(0.0f, 3.0f, 10.0f)); apple->transform().scale(glm::vec3(0.5f)); // Create a mathematical sphere collider for the apple SphereCollider * sphereCollider = new SphereCollider(apple); CollisionDetector::instance()->addCollider(sphereCollider); m_components.push_back(apple); // Create animator that animates the apple KeyframeAnimator<glm::vec3> * anim = new KeyframeAnimator<glm::vec3>(apple, new LinearInterpolator<glm::vec3>, apple->transform().position()); anim->addKeyframe(0.0f, glm::vec3(0.0f, 3.0f, 10.0f)); anim->addKeyframe(20000.0f, glm::vec3(0.0f, 3.0f, -10.0f)); anim->addKeyframe(40000.0f, glm::vec3(0.0f, 3.0f, 10.0f)); m_ballAnimator = anim; // Create some debug spheres for the BVH int level = 0; while (true) { ComponentCollection components = addDrawDebug(bowlCollider, level); if (components.empty()) break; m_debugComponents[level] = components; level++; } }