bool AnimationPreview::onPreRender() { if (!_model) return false; // Set the animation to play model::ModelNodePtr model = Node_getModel(_model); dynamic_cast<md5::IMD5Model&>(model->getIModel()).updateAnim(_renderSystem->getTime()); return true; }
void AnimationPreview::setAnim(const md5::IMD5AnimPtr& anim) { _anim = anim; if (!_model) { return; } // Set the animation to play model::ModelNodePtr model = Node_getModel(_model); dynamic_cast<md5::IMD5Model&>(model->getIModel()).setAnim(_anim); }
void ModelSelector::showInfoForSelectedModel() { // Prepare to populate the info table _infoTable->Clear(); // Get the model name, if this is blank we are looking at a directory, // so leave the table empty std::string mName = getSelectedValue(_columns.vfspath); if (mName.empty()) return; // Get the skin if set std::string skinName = getSelectedValue(_columns.skin); // Pass the model and skin to the preview widget _modelPreview->setModel(mName); _modelPreview->setSkin(skinName); // Check that the model is actually valid by querying the IModelPtr // returned from the preview widget. scene::INodePtr mdl = _modelPreview->getModelNode(); if (!mdl) { return; // no valid model } model::ModelNodePtr modelNode = Node_getModel(mdl); if (!modelNode) { return; } // Update the text in the info table const model::IModel& model = modelNode->getIModel(); _infoTable->Append(_("Model name"), mName); _infoTable->Append(_("Skin name"), skinName); _infoTable->Append(_("Total vertices"), string::to_string(model.getVertexCount())); _infoTable->Append(_("Total polys"), string::to_string(model.getPolyCount())); _infoTable->Append(_("Material surfaces"), string::to_string(model.getSurfaceCount())); // Add the list of active materials _materialsList->clear(); const model::StringList& matList(model.getActiveMaterials()); std::for_each( matList.begin(), matList.end(), boost::bind(&MaterialsList::addMaterial, _materialsList, _1) ); }
void ModelExporter::processNodes() { AABB bounds = calculateModelBounds(); if (_centerObjects) { // Depending on the center point, we need to use the object bounds // or just the translation towards the user-defined origin, ignoring bounds _centerTransform = _useOriginAsCenter ? Matrix4::getTranslation(-_origin) : Matrix4::getTranslation(-bounds.origin); } for (const scene::INodePtr& node : _nodes) { if (Node_isModel(node)) { model::ModelNodePtr modelNode = Node_getModel(node); // Push the geometry into the exporter model::IModel& model = modelNode->getIModel(); Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform); for (int s = 0; s < model.getSurfaceCount(); ++s) { const model::IModelSurface& surface = model.getSurface(s); if (isExportableMaterial(surface.getActiveMaterial())) { _exporter->addSurface(surface, exportTransform); } } } else if (Node_isBrush(node)) { processBrush(node); } else if (Node_isPatch(node)) { processPatch(node); } else if (_exportLightsAsObjects && Node_getLightNode(node)) { processLight(node); } } }
void ModelPreview::setSkin(const std::string& skin) { // Load and apply the skin, checking first to make sure the model is valid // and not null if (_modelNode != NULL) { model::ModelNodePtr model = Node_getModel(_modelNode); if (model) { ModelSkin& mSkin = GlobalModelSkinCache().capture(skin); model->getIModel().applySkin(mSkin); } } // Redraw queueDraw(); }
scene::INodePtr ModelCache::getModelNode(const std::string& modelPath) { // Check if we have a reference to a modeldef IModelDefPtr modelDef = GlobalEntityClassManager().findModel(modelPath); // The actual model path (is usually the same as the incoming modelPath) std::string actualModelPath(modelPath); if (modelDef != NULL) { // We have a valid modelDef, override the model path actualModelPath = modelDef->mesh; } // Get the extension of this model std::string type = actualModelPath.substr(actualModelPath.rfind(".") + 1); if (type == "prt") { // This is a particle, pass the call to the Particles Manager return GlobalParticlesManager().createParticleNode(actualModelPath); } // Get a suitable model loader ModelLoaderPtr modelLoader = getModelLoaderForType(type); // Try to construct a model node using the suitable loader scene::INodePtr node = modelLoader->loadModel(actualModelPath); if (node) { // For MD5 models, apply the idle animation by default if (modelDef) { model::ModelNodePtr modelNode = Node_getModel(node); if (!modelNode) { return node; } // Set the animation to play try { md5::IMD5Model& md5model = dynamic_cast<md5::IMD5Model&>(modelNode->getIModel()); // Look up the "idle" anim if there is one IModelDef::Anims::const_iterator found = modelDef->anims.find("idle"); if (found != modelDef->anims.end()) { // Load the anim md5::IMD5AnimPtr anim = GlobalAnimationCache().getAnim(found->second); if (anim) { md5model.setAnim(anim); md5model.updateAnim(0); } } } catch (std::bad_cast&) { // not an MD5 model, do nothing } } // Model load was successful return node; } // The model load failed, let's return the NullModel // This call should never fail, i.e. the returned model is non-NULL return NullModelLoader::InstancePtr()->loadModel(actualModelPath); }
// Set the model, this also resets the camera void AnimationPreview::setModelNode(const scene::INodePtr& node) { // Ensure that this is an MD5 model node model::ModelNodePtr model = Node_getModel(node); if (!model) { rError() << "AnimationPreview::setModelNode: node is not a model." << std::endl; _model.reset(); return; } // Set up the scene if (!_entity) { setupSceneGraph(); } try { dynamic_cast<const md5::IMD5Model&>(model->getIModel()); } catch (std::bad_cast&) { rError() << "AnimationPreview::setModelNode: modelnode doesn't contain an MD5 model." << std::endl; _model.reset(); return; } if (_model) { _entity->removeChildNode(_model); } _model = node; // Set the animation to play dynamic_cast<md5::IMD5Model&>(model->getIModel()).setAnim(_anim); // AddChildNode also tells the model which renderentity it is attached to _entity->addChildNode(_model); if (_model != NULL) { // Reset preview time stopPlayback(); // Reset the rotation to the default one _rotation = Matrix4::getRotation(Vector3(0,-1,0), Vector3(0,-0.3f,1)); _rotation.multiplyBy(Matrix4::getRotation(Vector3(0,1,0), Vector3(1,-1,0))); // Use AABB to adjust camera distance const AABB& bounds = _model->localAABB(); if (bounds.isValid()) { _camDist = -5.0f * static_cast<float>(bounds.getRadius()); } else { // Bounds not valid, fall back to default _camDist = -40.0f; } // Start playback when switching particles startPlayback(); } else { stopPlayback(); } // Redraw queueDraw(); }