diff --git a/src/osgPlugins/bsp/VBSPEntity.cpp b/src/osgPlugins/bsp/VBSPEntity.cpp index 6f3a68e02..a99d6cbc6 100644 --- a/src/osgPlugins/bsp/VBSPEntity.cpp +++ b/src/osgPlugins/bsp/VBSPEntity.cpp @@ -315,45 +315,45 @@ void VBSPEntity::parseParameters(std::string & entityText) } // Get the class name and process the entity appropriately - std::string className = (*param).second; - if (className.compare("worldspawn") == 0) + class_name = (*param).second; + if (class_name.compare("worldspawn") == 0) { // This is the entity that represents the main geometry of the map // (the terrain and much of the static geometry) entity_class = ENTITY_WORLDSPAWN; processWorldSpawn(); } - else if (className.compare(0, 3, "env") == 0) + else if (class_name.compare(0, 3, "env") == 0) { // This is an environmental effect (such as a fire or dust cloud) entity_class = ENTITY_ENV; processEnv(); } - else if ((className.compare("func_brush") == 0) || - (className.compare("func_illusionary") == 0) || - (className.compare("func_wall_toggle") == 0) || - (className.compare("func_breakable") == 0)) + else if ((class_name.compare("func_brush") == 0) || + (class_name.compare("func_illusionary") == 0) || + (class_name.compare("func_wall_toggle") == 0) || + (class_name.compare("func_breakable") == 0)) { // This is secondary map geometry, created along with the main // map geometry (not an external model) entity_class = ENTITY_FUNC_BRUSH; processFuncBrush(); } - else if (className.compare(0, 4, "prop") == 0) + else if (class_name.compare(0, 4, "prop") == 0) { // This is a "prop", an external model placed somewhere in the // scene entity_class = ENTITY_PROP; processProp(); } - else if (className.compare("infodecal") == 0) + else if (class_name.compare("infodecal") == 0) { // This is a decal, which applies a texture to some surface in the // scene entity_class = ENTITY_INFO_DECAL; processInfoDecal(); } - else if (className.compare(0, 4, "item") == 0) + else if (class_name.compare(0, 4, "item") == 0) { // This is an "item". Like a prop, these are external models // placed in the scene, but the specific model is determined @@ -367,19 +367,20 @@ void VBSPEntity::parseParameters(std::string & entityText) ref_ptr VBSPEntity::createBrushGeometry() { - int i; - int numGeoms; - VBSPGeometry ** vbspGeomList; - Model currentModel; - Face currentFace; - TexInfo currentTexInfo; - TexData currentTexData; - const char * texName; - char currentTexName[256]; - int currentGeomIndex; - VBSPGeometry * currentGeom; - ref_ptr entityGroup; - ref_ptr geomGroup; + int i; + int numGeoms; + VBSPGeometry ** vbspGeomList; + Model currentModel; + Face currentFace; + TexInfo currentTexInfo; + TexData currentTexData; + const char * texName; + char currentTexName[256]; + int currentGeomIndex; + VBSPGeometry * currentGeom; + ref_ptr entityGroup; + ref_ptr geomGroup; + std::stringstream groupName; // Create a list of VBSPGeometry objects for each texdata entry in the // scene. These objects will hold the necessary geometry data until we @@ -501,6 +502,10 @@ ref_ptr VBSPEntity::createBrushGeometry() } } + // Name the entity group + groupName << class_name << ":" << entity_model_index; + entityGroup->setName(groupName.str()); + // Return the group we created return entityGroup; } @@ -549,6 +554,9 @@ ref_ptr VBSPEntity::createModelGeometry() // Add the model node to the group entityGroup->addChild(modelNode.get()); + + // Set the group's name + entityGroup->setName(class_name + std::string(":") + entity_model); } else { diff --git a/src/osgPlugins/bsp/VBSPEntity.h b/src/osgPlugins/bsp/VBSPEntity.h index 8ae6da3d1..b2bcd8b44 100644 --- a/src/osgPlugins/bsp/VBSPEntity.h +++ b/src/osgPlugins/bsp/VBSPEntity.h @@ -32,6 +32,7 @@ protected: VBSPData * bsp_data; EntityClass entity_class; + std::string class_name; typedef std::pair EntityParameter; typedef std::map EntityParameters; diff --git a/src/osgPlugins/bsp/VBSPGeometry.cpp b/src/osgPlugins/bsp/VBSPGeometry.cpp index dafe74d5a..4e6f4017a 100644 --- a/src/osgPlugins/bsp/VBSPGeometry.cpp +++ b/src/osgPlugins/bsp/VBSPGeometry.cpp @@ -1,6 +1,7 @@ #include #include +#include #include "VBSPGeometry.h" @@ -647,6 +648,12 @@ ref_ptr VBSPGeometry::createGeometry() // Add the geometry to the geode geode->addDrawable(geometry.get()); + + // Now, stripify the geode to convert the POLYGON primitives to + // triangle strips + osgUtil::TriStripVisitor tsv; + geode->accept(tsv); + tsv.stripify(); } // Now do the same for the displacement surfaces (if any) diff --git a/src/osgPlugins/bsp/VBSPReader.cpp b/src/osgPlugins/bsp/VBSPReader.cpp index b38c6c081..ecb6e868f 100644 --- a/src/osgPlugins/bsp/VBSPReader.cpp +++ b/src/osgPlugins/bsp/VBSPReader.cpp @@ -745,8 +745,10 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) std::string tex2Name; ref_ptr texture; ref_ptr texture2; + ref_ptr material; ref_ptr blend; bool translucent; + double alpha; // Find the material file mtlFileName = std::string(materialName) + ".vmt"; @@ -818,6 +820,9 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) // Assume no transparency unless the properties say otherwise translucent = false; + // Assume fully opaque + alpha = 1.0; + // Read the material properties next while (!mtlFile->eof()) { @@ -858,6 +863,17 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) if ((token == "1") || (token == "true")) translucent = true; } + else if (equalCaseInsensitive(token, "$alpha")) + { + // Get the translucency setting + token = getToken(line, " \t\n\r\"", start); + + // Interpret the setting + if (!token.empty()) + { + alpha = atof(token.c_str()); + } + } // Try the next token token = getToken(line, " \t\n\r\"", start); @@ -873,6 +889,20 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) // This shader blends between two textures based on a per-vertex // attribute. This is used for displaced terrain surfaces in HL2 maps. stateSet = createBlendShader(texture.get(), texture2.get()); + + // Add a material to the state set + material = new Material(); + material->setAmbient(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setDiffuse(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setSpecular(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setShininess(Material::FRONT_AND_BACK, 1.0); + material->setEmission(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setAlpha(Material::FRONT_AND_BACK, alpha); + stateSet->setAttributeAndModes(material, StateAttribute::ON); } else if (equalCaseInsensitive(shaderName, "UnlitGeneric")) { @@ -916,6 +946,20 @@ ref_ptr VBSPReader::readMaterialFile(std::string materialName) // Create the StateSet stateSet = new StateSet(); + // Add a material to the state set + material = new Material(); + material->setAmbient(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setDiffuse(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setSpecular(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setShininess(Material::FRONT_AND_BACK, 1.0); + material->setEmission(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setAlpha(Material::FRONT_AND_BACK, alpha); + stateSet->setAttributeAndModes(material, StateAttribute::ON); + // Add the texture attribute (or disable texturing if no base texture) if (texture != NULL) { @@ -1081,8 +1125,13 @@ void VBSPReader::createScene() // If we loaded the prop correctly, add it to the scene if (propNode.valid()) { + // Add the model to the transform node, and attach the transform + // to the scene propXform->addChild(propNode.get()); group->addChild(propXform.get()); + + // Name the prop + propXform->setName(std::string("prop_static:" + propModel)); } else { diff --git a/src/osgPlugins/mdl/MDLReader.cpp b/src/osgPlugins/mdl/MDLReader.cpp index 45d7afc35..85c7c3abf 100644 --- a/src/osgPlugins/mdl/MDLReader.cpp +++ b/src/osgPlugins/mdl/MDLReader.cpp @@ -191,8 +191,10 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) std::string tex2Name; ref_ptr texture; ref_ptr texture2; + ref_ptr material; ref_ptr blend; bool translucent; + double alpha; // Find the material file mtlFileName = std::string(materialName) + ".vmt"; @@ -298,6 +300,9 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) // Assume not translucent unless the properties say otherwise translucent = false; + // Assume full opacity + alpha = 1.0; + // Read the material properties next while (!mtlFile->eof()) { @@ -341,6 +346,17 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) translucent = true; } } + else if (equalCaseInsensitive(token, "$alpha")) + { + // Get the translucency setting + token = getToken(line, " \t\n\r\"", start); + + // Interpret the setting + if (!token.empty()) + { + alpha = atof(token.c_str()); + } + } // Try the next token token = getToken(line, " \t\n\r\"", start); @@ -379,6 +395,7 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) blend = new BlendFunc(BlendFunc::SRC_ALPHA, BlendFunc::ONE_MINUS_SRC_ALPHA); stateSet->setAttributeAndModes(blend.get(), StateAttribute::ON); + stateSet->setMode(GL_BLEND, StateAttribute::ON); // Set the rendering hint for this stateset to transparent stateSet->setRenderingHint(StateSet::TRANSPARENT_BIN); @@ -387,11 +404,24 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) else { // All other shaders fall back to fixed function - // TODO: LightMappedGeneric shader // Create the StateSet stateSet = new StateSet(); + // Add a material to the state set + material = new Material(); + material->setAmbient(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setDiffuse(Material::FRONT_AND_BACK, + Vec4(1.0, 1.0, 1.0, 1.0) ); + material->setSpecular(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setShininess(Material::FRONT_AND_BACK, 1.0); + material->setEmission(Material::FRONT_AND_BACK, + Vec4(0.0, 0.0, 0.0, 1.0) ); + material->setAlpha(Material::FRONT_AND_BACK, alpha); + stateSet->setAttributeAndModes(material, StateAttribute::ON); + // Add the texture attribute (or disable texturing if no base texture) if (texture != NULL) { @@ -399,13 +429,14 @@ ref_ptr MDLReader::readMaterialFile(std::string materialName) StateAttribute::ON); // See if the material is translucent - if (translucent) + if ((translucent) || (alpha < 1.0)) { // Add the blending attribute as well blend = new BlendFunc(BlendFunc::SRC_ALPHA, BlendFunc::ONE_MINUS_SRC_ALPHA); stateSet->setAttributeAndModes(blend.get(), StateAttribute::ON); + stateSet->setMode(GL_BLEND, StateAttribute::ON); // Set the rendering hint for this stateset to transparent stateSet->setRenderingHint(StateSet::TRANSPARENT_BIN); @@ -633,14 +664,15 @@ bool MDLReader::readFile(const std::string & file) mdlRoot->addBodyPart(partNode); } - // Open the VVD file that goes with this model + // Open the VVD (vertex data) file that goes with this model vvdFile = findDataFile(getNameLessExtension(file) + ".vvd", CASE_INSENSITIVE); vvdReader = new VVDReader(); vvdReader->readFile(vvdFile); - // Open the VTX file that goes with this model (at this point, I don't - // see a reason not to always just use the DX9 version) + // Open the VTX file (index and primitive data) that goes with this model + // (at this point, I don't see a reason not to always just use the DX9 + // version) vtxFile = findDataFile(getNameLessExtension(file) + ".dx90.vtx", CASE_INSENSITIVE); vtxReader = new VTXReader(vvdReader, mdlRoot); diff --git a/src/osgPlugins/mdl/MDL_README.txt b/src/osgPlugins/mdl/MDL_README.txt index 82b607bad..cdb8dbb71 100644 --- a/src/osgPlugins/mdl/MDL_README.txt +++ b/src/osgPlugins/mdl/MDL_README.txt @@ -8,8 +8,8 @@ Overview This plugin allows .mdl files from games that make use of Valve's Source engine (Half Life 2, etc) to be loaded by OSG. -I've tested this plugin with dozens of on several HL2 models, as well as some -3rd party models. +I've tested this plugin with dozens of HL2 models, as well as some 3rd party +models. Using the Plugin