From Jason Daly, "These are some fixes to the mdl and bsp plugins to handle transparency and lighting better, plus a few other tweaks."
This commit is contained in:
@@ -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<Group> 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<Group> entityGroup;
|
||||
ref_ptr<Group> 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<Group> entityGroup;
|
||||
ref_ptr<Group> 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<Group> 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<Group> 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
|
||||
{
|
||||
|
||||
@@ -32,6 +32,7 @@ protected:
|
||||
VBSPData * bsp_data;
|
||||
|
||||
EntityClass entity_class;
|
||||
std::string class_name;
|
||||
|
||||
typedef std::pair<std::string, std::string> EntityParameter;
|
||||
typedef std::map<std::string, std::string> EntityParameters;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <osg/Geode>
|
||||
#include <osgUtil/TriStripVisitor>
|
||||
|
||||
#include "VBSPGeometry.h"
|
||||
|
||||
@@ -647,6 +648,12 @@ ref_ptr<Group> 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)
|
||||
|
||||
@@ -745,8 +745,10 @@ ref_ptr<StateSet> VBSPReader::readMaterialFile(std::string materialName)
|
||||
std::string tex2Name;
|
||||
ref_ptr<Texture> texture;
|
||||
ref_ptr<Texture> texture2;
|
||||
ref_ptr<Material> material;
|
||||
ref_ptr<BlendFunc> blend;
|
||||
bool translucent;
|
||||
double alpha;
|
||||
|
||||
// Find the material file
|
||||
mtlFileName = std::string(materialName) + ".vmt";
|
||||
@@ -818,6 +820,9 @@ ref_ptr<StateSet> 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<StateSet> 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<StateSet> 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<StateSet> 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
|
||||
{
|
||||
|
||||
@@ -191,8 +191,10 @@ ref_ptr<StateSet> MDLReader::readMaterialFile(std::string materialName)
|
||||
std::string tex2Name;
|
||||
ref_ptr<Texture> texture;
|
||||
ref_ptr<Texture> texture2;
|
||||
ref_ptr<Material> material;
|
||||
ref_ptr<BlendFunc> blend;
|
||||
bool translucent;
|
||||
double alpha;
|
||||
|
||||
// Find the material file
|
||||
mtlFileName = std::string(materialName) + ".vmt";
|
||||
@@ -298,6 +300,9 @@ ref_ptr<StateSet> 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<StateSet> 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<StateSet> 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<StateSet> 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<StateSet> 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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user