Steven M. Niles
Vice President
Tenet Networks
(619) 723-4079
[email protected]
http://www.tenet.net
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// QvTraverse.cpp
/*
Copyright 1995 by Tenet Networks, Inc.
Carlsbad, California, USA. All rights reserved.
Redistribution and use of this software, with or without modification, is
permitted provided that the following conditions are met:
1. Redistributions of this software must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <QvElement.h>
#include <QvNodes.h>
#include <QvState.h>
#ifdef WIN32
#include <QvUnknownNode.h>
#endif
#include <iostream.h>
static int indent = 0;
static void
announce(const char *className)
{
for (int i = 0; i < indent; i++)
cout << "\t";
cout << className << " {\n";
}
#define ANNOUNCE(className) announce(QV__QUOTE(className))
#define DEFAULT_TRAVERSE(className) \
void \
className::traverse(QvState *) \
{ \
ANNOUNCE(className); \
}
static void end_brack( )
{
for (int i = 0; i < indent; i++)
cout << "\t";
cout << "}\n";
}
#define END_BRACK end_brack( );
void tab_in(int in)
{
for (int i = 0; i < in; i++) cout << "\t";
}
void print_bitmask(QvSFEnum enm)
{
int out_vals_written = 0, all_val;
QvName all("ALL");
enm.findEnumValue(all, all_val);
if (enm.value == all_val)
cout << "\tALL\n";
else {
cout << "\t(";
for (int i = 0; i < enm.numEnums-1; i++) {
if (enm.enumValues[i] & enm.value) {
if (out_vals_written++) cout << " | ";
cout << (char *)enm.enumNames[i].getString( );
}
}
cout << ")\n";
}
}
void print_enum(QvSFEnum enm)
{
if (enm.isDefault( ))
cout << "DEFAULT\n";
else {
for (int i = 0; i < enm.numEnums; i++)
if (enm.enumValues[i] == enm.value) {
cout << (char *)enm.enumNames[i].getString( ) << "\n";
break;
}
}
}
#define MFIELD(fieldNm, grouping) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t["; \
for (i = 0; i < fieldNm.num * grouping; i++) { \
if (i && (grouping != 1) && (i % grouping == 0)) cout << ","; \
cout << " " << fieldNm.values[i]; \
} \
cout << "]\n"; \
}
#define BITMASK(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
if (fieldNm.numEnums) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm); \
print_bitmask(fieldNm); \
} \
}
#define FIXEDARRAYFIELD(fieldNm, grouping) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t"; \
for (i = 0; i < grouping; i++) { \
cout << fieldNm.value[i] << " "; \
} \
cout << "\n"; \
}
#define FIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t" << fieldNm.value << "\n"; \
}
#define STRINGFIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t" \
<< "\"" << fieldNm.value.getString( ) << "\"\n"; \
}
#define ENUMFIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
if (fieldNm.numEnums) { \
tab_in( indent); \
cout << QV__QUOTE(fieldNm) << "\t"; \
print_enum(fieldNm); \
} \
}
#define ROTATIONFIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t"; \
for (i = 0; i < 3 ; i++) \
cout << fieldNm.axis[i] << " "; \
cout << fieldNm.angle << "\n"; \
}
#define MATRIXFIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t"; \
for (i = 0; i < 4; i++) \
for (int j = 0; j < 4; j++) \
cout << fieldNm.value[i][j] << " "; \
cout << "\n"; \
}
#define BOOLFIELD(fieldNm) \
if (!(fieldNm.isDefault( ))) { \
tab_in( indent ); \
cout << QV__QUOTE(fieldNm) << "\t" << \
(fieldNm.value ? "TRUE" : "FALSE") << "\n"; \
}
//////////////////////////////////////////////////////////////////////////////
//
// Groups.
//
//////////////////////////////////////////////////////////////////////////////
void
QvGroup::traverse(QvState *state)
{
ANNOUNCE(Group);
indent++;
for (int i = 0; i < getNumChildren(); i++)
getChild(i)->traverse(state);
END_BRACK;
indent--;
}
void
QvLevelOfDetail::traverse(QvState *state)
{
int i;
ANNOUNCE(LevelOfDetail);
indent++;
MFIELD(screenArea,1)
// ??? In a real implementation, this would choose a child based
// ??? on the projected screen areas.
if (getNumChildren() > 0)
getChild(0)->traverse(state);
END_BRACK;
indent--;
}
void
QvSeparator::traverse(QvState *state)
{
ANNOUNCE(Separator);
state->push();
indent++;
ENUMFIELD(renderCulling)
for (int i = 0; i < getNumChildren(); i++)
getChild(i)->traverse(state);
state->pop();
END_BRACK;
indent--;
}
void
QvSwitch::traverse(QvState *state)
{
ANNOUNCE(Switch);
indent++;
FIELD(whichChild)
int which = whichChild.value;
if (which == QV_SWITCH_NONE)
;
else if (which == QV_SWITCH_ALL)
for (int i = 0; i < getNumChildren(); i++)
getChild(i)->traverse(state);
else
if (which < getNumChildren())
getChild(which)->traverse(state);
END_BRACK;
indent--;
}
void
QvTransformSeparator::traverse(QvState *state)
{
ANNOUNCE(TransformSeparator);
// We need to "push" just the transformation stack. We'll
// accomplish this by just pushing a no-op transformation onto
// that stack. When we "pop", we'll restore that stack to its
// previous state.
QvElement *markerElt = new QvElement;
markerElt->data = this;
markerElt->type = QvElement::NoOpTransform;
state->addElement(QvState::TransformationIndex, markerElt);
indent++;
for (int i = 0; i < getNumChildren(); i++)
getChild(i)->traverse(state);
// Now do the "pop"
while (state->getTopElement(QvState::TransformationIndex) != markerElt)
state->popElement(QvState::TransformationIndex);
END_BRACK;
indent--;
}
//////////////////////////////////////////////////////////////////////////////
//
// Properties.
//
//////////////////////////////////////////////////////////////////////////////
#define DO_PROPERTY(className, stackIndex, propName) \
void \
className::traverse(QvState *state) \
{ \
int i; \
ANNOUNCE(propName); \
QvElement *elt = new QvElement; \
elt->data = this; \
state->addElement(QvState::stackIndex, elt); \
indent++;
#define DO_TYPED_PROPERTY(className, stackIndex, eltType) \
void \
className::traverse(QvState *state) \
{ \
int i; \
ANNOUNCE(eltType); \
QvElement *elt = new QvElement; \
elt->data = this; \
elt->type = QvElement::eltType; \
state->addElement(QvState::stackIndex, elt); \
indent++;
#define END_PROPERTY \
END_BRACK; \
indent--; \
}
DO_PROPERTY(QvCoordinate3, Coordinate3Index, Coordinate3)
MFIELD(point, 3);
END_PROPERTY
DO_PROPERTY(QvMaterial, MaterialIndex, Material)
MFIELD(ambientColor, 3);
MFIELD(diffuseColor, 3);
MFIELD(specularColor, 3);
MFIELD(emissiveColor, 3);
MFIELD(shininess, 1);
MFIELD(transparency, 1);
END_PROPERTY
DO_PROPERTY(QvMaterialBinding, MaterialBindingIndex, MaterialBinding)
ENUMFIELD(value);
END_PROPERTY
DO_PROPERTY(QvNormal, NormalIndex, Normal)
MFIELD(vector, 3);
END_PROPERTY
DO_PROPERTY(QvNormalBinding, NormalBindingIndex, NormalBinding)
ENUMFIELD(value);
END_PROPERTY
DO_PROPERTY(QvShapeHints, ShapeHintsIndex, ShapeHints)
ENUMFIELD(vertexOrdering);
ENUMFIELD(shapeType);
ENUMFIELD(faceType);
FIELD(creaseAngle);
END_PROPERTY
DO_PROPERTY(QvTextureCoordinate2, TextureCoordinate2Index, TextureCoordinate2)
MFIELD(point, 2);
END_PROPERTY
DO_PROPERTY(QvTexture2, Texture2Index, Texture2)
STRINGFIELD(filename);
// This has not been implemented by QvLib yet TBA
// IMAGEFIELD(image)
ENUMFIELD(wrapS);
ENUMFIELD(wrapT);
END_PROPERTY
DO_PROPERTY(QvTexture2Transform, Texture2TransformationIndex, Texture2Transformation)
FIXEDARRAYFIELD(translation, 2);
FIELD(rotation);
FIXEDARRAYFIELD(scaleFactor, 2);
FIXEDARRAYFIELD(center, 2);
END_PROPERTY
DO_TYPED_PROPERTY(QvDirectionalLight, LightIndex, DirectionalLight)
BOOLFIELD(on);
FIELD(intensity);
FIXEDARRAYFIELD(color, 3);
FIXEDARRAYFIELD(direction,3);
END_PROPERTY
DO_TYPED_PROPERTY(QvPointLight, LightIndex, PointLight)
BOOLFIELD(on);
FIELD(intensity);
FIXEDARRAYFIELD(color, 3);
FIXEDARRAYFIELD(location,3);
END_PROPERTY
DO_TYPED_PROPERTY(QvSpotLight, LightIndex, SpotLight)
BOOLFIELD(on);
FIELD(intensity);
FIXEDARRAYFIELD(color, 3);
FIXEDARRAYFIELD(location,3);
FIXEDARRAYFIELD(direction,3);
FIELD(dropOffRate);
FIELD(cutOffAngle);
END_PROPERTY
DO_TYPED_PROPERTY(QvOrthographicCamera, CameraIndex, OrthographicCamera)
FIXEDARRAYFIELD(position,3);
ROTATIONFIELD(orientation);
FIELD(focalDistance);
FIELD(height);
END_PROPERTY
DO_TYPED_PROPERTY(QvPerspectiveCamera, CameraIndex, PerspectiveCamera)
FIXEDARRAYFIELD(position,3);
ROTATIONFIELD(orientation);
FIELD(focalDistance);
FIELD(heightAngle);
END_PROPERTY
DO_TYPED_PROPERTY(QvTransform, TransformationIndex, Transform)
FIXEDARRAYFIELD(translation,3);
ROTATIONFIELD(rotation);
FIXEDARRAYFIELD(scaleFactor,3);
ROTATIONFIELD(scaleOrientation);
FIXEDARRAYFIELD(center,3);
END_PROPERTY
DO_TYPED_PROPERTY(QvRotation, TransformationIndex, Rotation)
ROTATIONFIELD(rotation);
END_PROPERTY
DO_TYPED_PROPERTY(QvMatrixTransform, TransformationIndex, MatrixTransform)
MATRIXFIELD(matrix);
END_PROPERTY
DO_TYPED_PROPERTY(QvTranslation, TransformationIndex, Translation)
FIXEDARRAYFIELD(translation,3);
END_PROPERTY
DO_TYPED_PROPERTY(QvScale, TransformationIndex, Scale)
FIXEDARRAYFIELD(scaleFactor,3);
END_PROPERTY
//////////////////////////////////////////////////////////////////////////////
//
// Shapes.
//
//////////////////////////////////////////////////////////////////////////////
#define DO_SHAPE(classNm, name) \
void classNm::traverse( QvState *state ) \
{ \
int i; \
ANNOUNCE(name); \
indent++;
#define END_SHAPE \
END_BRACK; \
indent--; \
}
DO_SHAPE(QvCube, Cube)
FIELD(width);
FIELD(height);
FIELD(depth);
END_SHAPE
DO_SHAPE(QvCone, Cone)
BITMASK(parts);
FIELD(bottomRadius);
FIELD(height);
END_SHAPE
DO_SHAPE(QvCylinder, Cylinder)
BITMASK(parts);
FIELD(radius);
FIELD(height);
END_SHAPE
DO_SHAPE(QvIndexedFaceSet, IndexedFaceSet)
MFIELD(coordIndex, 1);
MFIELD(materialIndex, 1);
MFIELD(normalIndex, 1);
MFIELD(textureCoordIndex, 1);
END_SHAPE
DO_SHAPE(QvIndexedLineSet, IndexedLineSet)
MFIELD(coordIndex, 1);
MFIELD(materialIndex, 1);
MFIELD(normalIndex, 1);
MFIELD(textureCoordIndex, 1);
END_SHAPE
DO_SHAPE(QvPointSet, PointSet)
FIELD(startIndex);
FIELD(numPoints);
END_SHAPE
DO_SHAPE(QvSphere, Sphere)
FIELD(radius);
END_SHAPE
//
// Not really a shape, but this does what it's supposed to.
//
DO_SHAPE(QvInfo, Info)
STRINGFIELD(string)
END_SHAPE;
//////////////////////////////////////////////////////////////////////////////
//
// WWW-specific nodes.
//
//////////////////////////////////////////////////////////////////////////////
#define DO_WWW(className, propName) \
void \
className::traverse(QvState *state) \
{ \
int i; \
ANNOUNCE(propName); \
indent++;
#define END_WWW \
if (getNumChildren() > 0) \
getChild(0)->traverse(state); \
END_BRACK \
indent--; \
}
DO_WWW(QvWWWAnchor, WWWAnchor)
STRINGFIELD(name)
ENUMFIELD(map)
END_WWW
DO_WWW(QvWWWInline, WWWInline)
STRINGFIELD(name)
FIXEDARRAYFIELD(bboxSize, 3)
FIXEDARRAYFIELD(bboxCenter, 3)
END_WWW
//////////////////////////////////////////////////////////////////////////////
//
// Default traversal methods. These nodes have no effects during traversal.
//
//////////////////////////////////////////////////////////////////////////////
DEFAULT_TRAVERSE(QvUnknownNode)
//////////////////////////////////////////////////////////////////////////////
#undef ANNOUNCE
#undef END_BRACK
#undef DEFAULT_TRAVERSE
#undef DO_PROPERTY
#undef DO_SHAPE
#undef DO_TYPED_PROPERTY
#undef DO_WWW
#undef END_SHAPE
#undef END_PROPERTY
#undef END_WWW
#undef FIELD
#undef MFIELD
#undef BITMASK
#undef END_BRACK
#undef MATRIXFIELD
Steven M. Niles
Vice President
Tenet Networks
(619) 723-4079
[email protected]
http://www.catalog.com/tenet