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:
Robert Osfield
2009-07-16 11:21:02 +00:00
parent a232770161
commit 9eb03d450d
6 changed files with 127 additions and 30 deletions

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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)

View File

@@ -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
{

View File

@@ -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);

View File

@@ -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