#include "Base.h" #include "Node.h" #include "Matrix.h" #include "EncoderArguments.h" #define NODE 1 #define JOINT 2 namespace gameplay { Node::Node(void) : _childCount(0), _nextSibling(NULL), _previousSibling(NULL), _firstChild(NULL), _lastChild(NULL), _parent(NULL), _camera(NULL), _light(NULL), _model(NULL), _joint(false) { } Node::~Node(void) { } unsigned int Node::getTypeId(void) const { return NODE_ID; } const char* Node::getElementName(void) const { return "Node"; } void Node::writeBinary(FILE* file) { Object::writeBinary(file); // node type unsigned int type = _joint ? JOINT : NODE; write(type, file); write(_transform.m, 16, file); // children write(getChildCount(), file); // write number of children for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling()) { node->writeBinary(file); } // camera if (_camera != NULL) { _camera->writeBinary(file); } else { write((unsigned char)0, file); } // light if (_light != NULL && !_light->isAmbient()) { _light->writeBinary(file); } else { write((unsigned char)0, file); } // mesh if (_model != NULL) { _model->writeBinary(file); } else { writeZero(file); } generateHeightmap(); } void Node::writeText(FILE* file) { if (isJoint()) { fprintf(file, "<%s id=\"%s\" type=\"%s\">\n", getElementName(), getId().c_str(), "JOINT"); } else { fprintElementStart(file); } fprintf(file, ""); fprintfMatrix4f(file, _transform.m); fprintf(file, "\n"); // children for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling()) { node->writeText(file); } // camera if (_camera != NULL) { _camera->writeText(file); } // light if (_light != NULL && !_light->isAmbient()) { _light->writeText(file); } // mesh if (_model != NULL) { _model->writeText(file); } fprintElementEnd(file); generateHeightmap(); } void Node::generateHeightmap() { // Is this node flagged to have a heightmap generated for it? const std::vector& heightmapNodes = EncoderArguments::getInstance()->getHeightmapNodeIds(); if (std::find(heightmapNodes.begin(), heightmapNodes.end(), getId()) != heightmapNodes.end()) { Mesh* mesh = _model ? _model->getMesh() : NULL; if (mesh) { DEBUGPRINT_VARG("> Generating heightmap for node: %s\n", getId().c_str()); std::string heightmapFilename(EncoderArguments::getInstance()->getOutputPath()); heightmapFilename += "/heightmap_"; heightmapFilename += getId(); heightmapFilename += ".png"; mesh->generateHeightmap(heightmapFilename.c_str()); } } } void Node::addChild(Node* child) { // If this child is already parented, remove it from its parent if (child->_parent) { child->_parent->removeChild(child); } if (_firstChild == NULL) { // No children yet _firstChild = child; child->_previousSibling = NULL; } else { // We already have children, so append to them child->_previousSibling = _lastChild; _lastChild->_nextSibling = child; } child->_parent = this; child->_nextSibling = NULL; this->_lastChild = child; ++_childCount; } void Node::removeChild(Node* child) { // The child must have already been our child to remove it if (child->_parent != this) { return; } // Remove the child by un-linking it from our child list if (child->_nextSibling) { child->_nextSibling->_previousSibling = child->_previousSibling; } if (child->_previousSibling) { child->_previousSibling->_nextSibling = child->_nextSibling; } // Was this child our first or last child? if (child == _firstChild) { _firstChild = child->_nextSibling; } if (child == _lastChild) { _lastChild = child->_previousSibling; } // Remove parent and sibling info from the child, now that it is no longer parented child->_parent = NULL; child->_nextSibling = NULL; child->_previousSibling = NULL; --_childCount; } void Node::removeChildren() { Node* child; while ((child = _firstChild) != NULL) { removeChild(child); } } bool Node::hasChildren() const { return (_firstChild != NULL); } unsigned int Node::getChildCount() const { return _childCount; } Node* Node::getNextSibling() const { return _nextSibling; } Node* Node::getPreviousSibling() const { return _previousSibling; } Node* Node::getFirstChild() const { return _firstChild; } Node* Node::getLastChild() const { return _lastChild; } Node* Node::getParent() const { return _parent; } void Node::setCamera(Camera* camera) { _camera = camera; } void Node::setLight(Light* light) { _light = light; } void Node::setModel(Model* model) { _model = model; } const Matrix& Node::getTransformMatrix() const { return _transform; } void Node::setTransformMatrix(float matrix[]) { memcpy(_transform.m, matrix, 16 * sizeof(float)); } const Matrix& Node::getWorldMatrix() const { if (_parent) { Matrix::multiply(_parent->getWorldMatrix().m, _transform.m, _worldTransform.m); } else { memcpy(_worldTransform.m, _transform.m, 16 * sizeof(float)); } return _worldTransform; } void Node::resetTransformMatrix() { Matrix::setIdentity(_transform.m); } void Node::setIsJoint(bool value) { _joint = value; } bool Node::isJoint() { return _joint; } Camera* Node::getCamera() const { return _camera; } Light* Node::getLight() const { return _light; } Model* Node::getModel() const { if (_model) { return _model; } return NULL; } Node* Node::getFirstCameraNode() const { if (hasCamera()) { return (Node*)this; } for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling()) { Node* n = node->getFirstCameraNode(); if (n) { return n; } } return NULL; } bool Node::hasCamera() const { return _camera != NULL; } bool Node::hasLight() const { return _light != NULL; } }