/* * NodeShape.cpp * * Copyright (C) 1999 Stephen F. White * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file "COPYING" for details); if * not, write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. */ #include #include "stdafx.h" #include "NodeShape.h" #include "Proto.h" #include "FieldValue.h" #include "SFColor.h" #include "SFFloat.h" #include "SFNode.h" #include "Node.h" #include "NodeMaterial.h" #include "Util.h" ProtoShape::ProtoShape(Scene *scene) : Proto(scene, "Shape") { appearance.set( addExposedField(SFNODE, "appearance", new SFNode(NULL), NODE_APPEARANCE)); geometry.set( addExposedField(SFNODE, "geometry", new SFNode(NULL), GEOMETRY_NODE | PARAMETRIC_GEOMETRY_NODE)); } Node * ProtoShape::create(Scene *scene) { return new NodeShape(scene, this); } NodeShape::NodeShape(Scene *scene, Proto *def) : Node(scene, def) { _appearance.set(((ProtoShape *)def)->appearance); _geometry.set(((ProtoShape *)def)->geometry); } void NodeShape::draw() { Node *appearance = ((SFNode *) getField(_appearance,true))->getValue(); Node *geometry = ((SFNode *) getField(_geometry,true))->getValue(); if (isLit()) { glEnable(GL_LIGHTING); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { glDisable(GL_LIGHTING); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); Util::myGlColor3f(1.0f, 1.0f, 1.0f); } glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_NOTEQUAL,0); if (appearance) appearance->bind(); if (geometry) { glPushName(geometry_Index()); // field geometry glPushName(0); // index 0 geometry->draw(); doSpecularPass(appearance, geometry); glPopName(); glPopName(); } if (appearance) appearance->unbind(); glEnable(GL_LIGHTING); } bool NodeShape::isLit() const { Node *appearance = ((SFNode *) getField(_appearance,true))->getValue(); return appearance != NULL && ((SFNode *) appearance->getField(_appearance,true))->getValue() != NULL; } void NodeShape::doSpecularPass(Node *appearance, Node *geometry) { if (!glIsEnabled(GL_TEXTURE_2D)) return; if (appearance != NULL) { Node *material = ((SFNode *) appearance->getField(_appearance,true))->getValue(); if (material != NULL) { const float *specular = ((NodeMaterial *) material)->specularColor()->getValue(); float transparency = ((NodeMaterial *) material)->transparency()->getValue(); if (specular[0] != 0.0f || specular[1] != 0.0f || specular[2] != 0.0f) { float s[4]; // premultiply by the transparency s[0] = specular[0] * (1.0f - transparency); s[1] = specular[1] * (1.0f - transparency); s[2] = specular[2] * (1.0f - transparency); s[3] = 1.0f; glDisable(GL_TEXTURE_2D); static float black[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, black); Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, black); Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black); Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, s); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); geometry->draw(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); } } } } void NodeShape::flip(int index) { Node *ngeometry = geometry()->getValue(); if (ngeometry != NULL) ngeometry->flip(index); } int NodeShape::countPolygons(void) { int ret = 0; Node *ngeometry = geometry()->getValue(); if (ngeometry != NULL) ret += ngeometry->countPolygons(); return ret; } int NodeShape::countPrimitives(void) { int ret = 0; Node *ngeometry = geometry()->getValue(); if (ngeometry != NULL) ret += ngeometry->countPrimitives(); return ret; }