#include <vuAllocTracer.h>
#include <vrMaterial.h>
#include <vpApp.h>
#include <vpObject.h>
// track memory leaks
vuAllocTracer m_allocTracer;
// the main application class
class myApp : public vpApp {
public:
/**
* Constructor
*/
myApp()
{
}
/**
* Destructor
*/
~myApp()
{
// unreference member variables which cache Vega Prime class instances
}
/**
* Configure my app
*/
int configure() {
// pre-configuration
// register our representation w/ the system. This needs to be done
// before configure is called.
m_representationIndex = vsChannel::registerRepresentation(
"my representation");
// configure vega prime system first
vpApp::configure();
// post-configuration
// Increase the reference count by one for all member variables which
// cache the Vega Prime class instances.
//
// All VSG/Vega Prime class instances are referenced counted.
// The initial reference count is 0 after the instance is created.
// When the reference count is smaller or equal to 0 in unref(),
// the instance will be deleted automatically. Increasing reference
// count here for all member variables will guarantee that they will
// not be deleted until myApp is deleted.
// our objective here is to add color tables to the esprit model, but
// not the town model. Since we're trying to change the color of the
// car, we'll only change the geometries that comprise the body of the
// model, and leave the remaining geometries unchanged. In this way,
// we give the esprit the appearance of a red paint job w/o making the
// tires red, etc.. To accomplish this, we've gone into Creator and
// identified the colors of the material used for the car body and then
// we'll identify which geometries correspond to the body by comparing
// these values against their material properties.
// the material properties of the car body obtained from Creator
vuVec4<float> ambientDesired(0.305f, 0.478f, 0.689f, 1.0f);
vuVec4<float> diffuseDesired(0.305f, 0.478f, 0.689f, 1.0f);
vuVec4<float> specularDesired(0.941f, 0.941f, 0.588f, 1.0f);
vuVec4<float> emissiveDesired(0.0f, 0.0f, 0.0f, 1.0f);
float specularExponentDesired = 60.0f;
// iterate through all of the geometries for the esprit
vpObject *object = vpObject::find("esprit");
assert(object);
int numColors;
float specularExponentActual, tolerance = 0.01f;
vuVec4<float> ambientActual, diffuseActual, specularActual;
vuVec4<float> emissiveActual,*colorDst, *colorSrc;
vrGeometry::Binding binding;
vrGeometry *geometryDst, *geometrySrc;
vsGeometry *geometryNode;
vrMaterial *material;
const vrMaterial::Element *cmep;
vrState *state;
vpObject::const_iterator_geometry it, ite = object->end_geometry();
for (it=object->begin_geometry();it!=ite;++it) {
// always check the class type first when using the geometry
// iterators. You can't do a safe cast w/o checking the type.
if ((*it)->isOfClassType(vsGeometry::getStaticClassType())) {
// get the material element from the state and obtain it's
// values for comparison
geometryNode = static_cast<vsGeometry *>(*it);
state = geometryNode->getState();
cmep = vrGetElement(state, vrMaterial::Element::Id);
if ((cmep != NULL) &&
((material = cmep->m_material) != NULL)) {
material->getColor(vrMaterial::COLOR_AMBIENT,
&ambientActual[0], &ambientActual[1],
&ambientActual[2], &ambientActual[3]);
material->getColor(vrMaterial::COLOR_DIFFUSE,
&diffuseActual[0], &diffuseActual[1],
&diffuseActual[2], &diffuseActual[3]);
material->getColor(vrMaterial::COLOR_SPECULAR,
&specularActual[0], &specularActual[1],
&specularActual[2], &specularActual[3]);
material->getColor(vrMaterial::COLOR_EMISSIVE,
&emissiveActual[0], &emissiveActual[1],
&emissiveActual[2], &emissiveActual[3]);
specularExponentActual = material->getSpecularExponent();
}
// add an alternate color representation for all geometry
// that is using our target material. To do this we'll create
// a new geometry that is a copy of the source, except that it
// has an different color array, and add this to the geometry
// node at our representation index. For our purposes we'll
// share the state w/ the original representation.
geometrySrc = geometryNode->getGeometry();
if ((geometrySrc != NULL) &&
((colorSrc = geometrySrc->getColors(&binding)) != NULL) &&
(material != NULL) &&
(ambientActual.compare(ambientDesired, tolerance)) &&
(diffuseActual.compare(diffuseDesired, tolerance)) &&
(specularActual.compare(specularDesired, tolerance)) &&
(emissiveActual.compare(emissiveDesired, tolerance)) &&
(vuAbsLT(specularExponentActual - specularExponentDesired, tolerance))) {
geometryDst = new vrGeometry();
vsgu::copy(geometryDst, geometrySrc);
numColors = geometrySrc->getNumColors();
colorDst = vuAllocArray<vuVec4<float> >::malloc(numColors);
for (int i=0;i<numColors;i++)
colorDst[i].set(1.0f, 0.0f, 0.0f, colorSrc[i][3]);
geometryDst->setColors(colorDst, binding);
geometryNode->setGeometry(geometryDst, m_representationIndex);
geometryNode->setState(geometryNode->getState(), m_representationIndex);
}
}
}
// look at our alternate representation by default
vpChannel *channel = *vpChannel::begin();
channel->setRepresentationIndex(m_representationIndex);
return vsgu::SUCCESS;
}
/**
* unconfigure the application
*/
virtual int unconfigure()
{
// unregister our representation w/ the system
vsChannel::unregisterRepresentation("my representation");
// call the base class unconfigure
return vpApp::unconfigure();
}
/**
* Override keyboard input
*/
virtual void onKeyInput(vrWindow::Key key, int mod)
{
vpChannel *channel = *vpChannel::begin();
switch (key) {
case vrWindow::KEY_SPACE: // toggle between the two representations
if (channel->getRepresentationIndex() == m_representationIndex) {
channel->setRepresentationIndex(0);
printf("using representation 0\n");
}
else {
channel->setRepresentationIndex(m_representationIndex);
printf("using representation %d\n", m_representationIndex);
}
break;
default:
vpApp::onKeyInput(key, mod);
break;
}
}
private:
// our representation index
int m_representationIndex;
};
int main(int argc, char *argv[])
{
// initialize vega pr