From ef86d862344202ec6d3366ec1c039ccf633ebb03 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 20 Aug 2014 15:49:50 -0700 Subject: [PATCH] split out entity rendering into subclasses, improved rendering of models --- examples/editModels.js | 23 ++ interface/src/Application.cpp | 21 +- interface/src/entities/EntityTreeRenderer.cpp | 321 ++---------------- interface/src/entities/EntityTreeRenderer.h | 11 +- .../src/entities/RenderableBoxEntityItem.cpp | 119 +++++++ .../src/entities/RenderableBoxEntityItem.h | 40 +++ .../entities/RenderableModelEntityItem.cpp | 241 +++++++++++++ .../src/entities/RenderableModelEntityItem.h | 56 +++ .../entities/RenderableSphereEntityItem.cpp | 50 +++ .../src/entities/RenderableSphereEntityItem.h | 40 +++ interface/src/renderer/Model.cpp | 2 - libraries/entities/src/BoxEntityItem.cpp | 5 +- libraries/entities/src/BoxEntityItem.h | 8 +- libraries/entities/src/EntityItem.cpp | 11 +- libraries/entities/src/EntityItem.h | 74 ++-- libraries/entities/src/EntityItemProperties.h | 17 + libraries/entities/src/EntityTypes.cpp | 29 +- libraries/entities/src/EntityTypes.h | 19 +- libraries/entities/src/ModelEntityItem.cpp | 6 +- libraries/entities/src/ModelEntityItem.h | 4 +- libraries/entities/src/SphereEntityItem.cpp | 128 +++++++ libraries/entities/src/SphereEntityItem.h | 57 ++++ libraries/entities/src/todo.txt | 9 +- libraries/octree/src/Octree.cpp | 61 ---- 24 files changed, 886 insertions(+), 466 deletions(-) create mode 100644 interface/src/entities/RenderableBoxEntityItem.cpp create mode 100644 interface/src/entities/RenderableBoxEntityItem.h create mode 100644 interface/src/entities/RenderableModelEntityItem.cpp create mode 100644 interface/src/entities/RenderableModelEntityItem.h create mode 100644 interface/src/entities/RenderableSphereEntityItem.cpp create mode 100644 interface/src/entities/RenderableSphereEntityItem.h create mode 100644 libraries/entities/src/SphereEntityItem.cpp create mode 100644 libraries/entities/src/SphereEntityItem.h diff --git a/examples/editModels.js b/examples/editModels.js index 40664adb45..ab3c7ac0d4 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -1088,6 +1088,7 @@ var active; var newModel; var browser; var newBox; +var newSphere; function initToolBar() { toolBar = new ToolBar(0, 0, ToolBar.VERTICAL); // New Model @@ -1118,6 +1119,14 @@ function initToolBar() { visible: true, alpha: 0.9 }); + + newSphere = toolBar.addTool({ + imageURL: toolIconUrl + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: toolWidth, height: toolHeight, + visible: true, + alpha: 0.9 + }); } function moveOverlays() { @@ -1261,6 +1270,20 @@ function mousePressEvent(event) { print("Can't create box: Box would be out of bounds."); } + } else if (newSphere == toolBar.clicked(clickedOverlay)) { + var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE)); + + if (position.x > 0 && position.y > 0 && position.z > 0) { + Entities.addEntity({ + type: "Sphere", + position: position, + radius: radiusDefault, + color: { red: 255, green: 0, blue: 0 } + }); + } else { + print("Can't create box: Box would be out of bounds."); + } + } else if (browser == toolBar.clicked(clickedOverlay)) { var url = Window.s3Browse(".*(fbx|FBX)"); if (url == null || url == "") { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 02a05f3271..f58ed69b4e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2668,9 +2668,20 @@ void Application::updateShadowMap() { glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.1f, 4.0f); // magic numbers courtesy http://www.eecs.berkeley.edu/~ravir/6160/papers/shadowmaps.ppt - _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); - _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); - _entities.render(OctreeRenderer::SHADOW_RENDER_MODE); + { + PerformanceTimer perfTimer("avatarManager"); + _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); + } + + { + PerformanceTimer perfTimer("particles"); + _particles.render(OctreeRenderer::SHADOW_RENDER_MODE); + } + + { + PerformanceTimer perfTimer("entities"); + _entities.render(OctreeRenderer::SHADOW_RENDER_MODE); + } glDisable(GL_POLYGON_OFFSET_FILL); @@ -2867,9 +2878,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // render models... if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) { - PerformanceTimer perfTimer("models"); + PerformanceTimer perfTimer("entities"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... models..."); + "Application::displaySide() ... entities..."); _entities.render(); } diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 18b4c55272..3c5f2da38e 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -15,17 +15,34 @@ #include "InterfaceConfig.h" -#include #include +#include +#include #include "Menu.h" #include "EntityTreeRenderer.h" +#include "RenderableBoxEntityItem.h" +#include "RenderableModelEntityItem.h" +#include "RenderableSphereEntityItem.h" + + +QThread* EntityTreeRenderer::getMainThread() { + return Application::getInstance()->getEntities()->thread(); +} + EntityTreeRenderer::EntityTreeRenderer() : OctreeRenderer() { + + qDebug() << "--- Overriding Entity Factories NOW ---"; + REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory) + REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory) + qDebug() << "--- DONE Overriding Entity Factories ---"; + } EntityTreeRenderer::~EntityTreeRenderer() { @@ -40,6 +57,7 @@ void EntityTreeRenderer::clear() { void EntityTreeRenderer::clearModelsCache() { qDebug() << "EntityTreeRenderer::clearModelsCache()..."; + /* // delete the models in _knownEntityItemModels foreach(Model* model, _knownEntityItemModels) { delete model; @@ -50,12 +68,15 @@ void EntityTreeRenderer::clearModelsCache() { delete model; } _unknownEntityItemModels.clear(); + + foreach(Model* model, _entityItemModels) { + delete model; + } + _entityItemModels.clear(); + */ } void EntityTreeRenderer::init() { - //REGISTER_ENTITY_TYPE_RENDERER(Model, this->renderEntityTypeModel); - //REGISTER_ENTITY_TYPE_RENDERER(Box, this->renderEntityTypeBox); - OctreeRenderer::init(); static_cast(_tree)->setFBXService(this); } @@ -84,9 +105,10 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* en const FBXGeometry* result = NULL; if (entityItem->getType() == EntityTypes::Model) { - const ModelEntityItem* modelEntityItem = static_cast(entityItem); - - Model* model = getModel(modelEntityItem); + const RenderableModelEntityItem* constModelEntityItem = dynamic_cast(entityItem); + RenderableModelEntityItem* modelEntityItem = const_cast(constModelEntityItem); + assert(modelEntityItem); // we need this!!! + Model* model = modelEntityItem->getModel(); if (model) { result = &model->getGeometry()->getFBXGeometry(); } @@ -97,73 +119,17 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* en const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityItem) { const Model* result = NULL; if (entityItem->getType() == EntityTypes::Model) { - const ModelEntityItem* modelEntityItem = static_cast(entityItem); + const RenderableModelEntityItem* constModelEntityItem = dynamic_cast(entityItem); + RenderableModelEntityItem* modelEntityItem = const_cast(constModelEntityItem); + assert(modelEntityItem); // we need this!!! - result = getModel(modelEntityItem); + result = modelEntityItem->getModel(); } return result; } -Model* EntityTreeRenderer::getModel(const ModelEntityItem* modelEntityItem) { - Model* model = NULL; - - if (!modelEntityItem->getModelURL().isEmpty()) { - if (modelEntityItem->isKnownID()) { - if (_knownEntityItemModels.find(modelEntityItem->getID()) != _knownEntityItemModels.end()) { - model = _knownEntityItemModels[modelEntityItem->getID()]; - if (QUrl(modelEntityItem->getModelURL()) != model->getURL()) { - delete model; // delete the old model... - model = NULL; - _knownEntityItemModels.remove(modelEntityItem->getID()); - } - } - - // if we don't have a model... but our item does have a model URL - if (!model) { - // Make sure we only create new models on the thread that owns the EntityTreeRenderer - if (QThread::currentThread() != thread()) { - qDebug() << "about to call QMetaObject::invokeMethod(this, 'getModel', Qt::BlockingQueuedConnection,..."; - QMetaObject::invokeMethod(this, "getModel", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(Model*, model), Q_ARG(const ModelEntityItem*, modelEntityItem)); - qDebug() << "got it... model=" << model; - return model; - } - - model = new Model(); - model->init(); - model->setURL(QUrl(modelEntityItem->getModelURL())); - _knownEntityItemModels[modelEntityItem->getID()] = model; - } - - } else { - if (_unknownEntityItemModels.find(modelEntityItem->getCreatorTokenID()) != _unknownEntityItemModels.end()) { - model = _unknownEntityItemModels[modelEntityItem->getCreatorTokenID()]; - if (QUrl(modelEntityItem->getModelURL()) != model->getURL()) { - delete model; // delete the old model... - model = NULL; - _unknownEntityItemModels.remove(modelEntityItem->getCreatorTokenID()); - } - } - - if (!model) { - // Make sure we only create new models on the thread that owns the EntityTreeRenderer - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "getModel", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(Model*, model), Q_ARG(const ModelEntityItem*, modelEntityItem)); - return model; - } - - model = new Model(); - model->init(); - model->setURL(QUrl(modelEntityItem->getModelURL())); - _unknownEntityItemModels[modelEntityItem->getCreatorTokenID()] = model; - } - } - } - return model; -} - void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { + //PerformanceTimer perfTimer("renderElement"); args->_elementsTouched++; // actually render it here... // we need to iterate the actual entityItems of the element @@ -271,13 +237,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) if (entityItem->getGlowLevel() > 0.0f) { glower = new Glower(entityItem->getGlowLevel()); } - - if (entityItem->getType() == EntityTypes::Model) { - renderEntityTypeModel(entityItem, args); - } else if (entityItem->getType() == EntityTypes::Box) { - renderEntityTypeBox(entityItem, args); - } - + entityItem->render(args); if (glower) { delete glower; } @@ -288,217 +248,6 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) } } -void EntityTreeRenderer::renderEntityTypeModel(EntityItem* entity, RenderArgs* args) { - assert(entity->getType() == EntityTypes::Model); - - ModelEntityItem* entityItem = static_cast(entity); - bool drawAsModel = entityItem->hasModel(); - - glm::vec3 position = entityItem->getPosition() * (float)TREE_SCALE; - float radius = entityItem->getRadius() * (float)TREE_SCALE; - float size = entity->getSize() * (float)TREE_SCALE; - - if (drawAsModel) { - glPushMatrix(); - { - const float alpha = 1.0f; - - Model* model = getModel(entityItem); - - if (model) { - model->setScaleToFit(true, radius * 2.0f); - model->setSnapModelToCenter(true); - - // set the rotation - glm::quat rotation = entityItem->getRotation(); - model->setRotation(rotation); - - // set the position - model->setTranslation(position); - - // handle animations.. - if (entityItem->hasAnimation()) { - //qDebug() << "entityItem->hasAnimation()..."; - if (!entityItem->jointsMapped()) { - QStringList modelJointNames = model->getJointNames(); - entityItem->mapJoints(modelJointNames); - //qDebug() << "entityItem->mapJoints()..."; - } - - if (entityItem->jointsMapped()) { - //qDebug() << "model->setJointState()..."; - QVector frameData = entityItem->getAnimationFrame(); - for (int i = 0; i < frameData.size(); i++) { - model->setJointState(i, true, frameData[i]); - } - } - } - - // make sure to simulate so everything gets set up correctly for rendering - model->simulate(0.0f); - - // TODO: should we allow entityItems to have alpha on their models? - Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE - ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; - - if (model->isActive()) { - model->render(alpha, modelRenderMode); - } else { - // if we couldn't get a model, then just draw a sphere - glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem->getColor()[BLUE_INDEX]); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glutSolidSphere(radius, 15, 15); - glPopMatrix(); - } - - bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE; - bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds); - - if (!isShadowMode && displayModelBounds) { - - glm::vec3 unRotatedMinimum = model->getUnscaledMeshExtents().minimum; - glm::vec3 unRotatedMaximum = model->getUnscaledMeshExtents().maximum; - glm::vec3 unRotatedExtents = unRotatedMaximum - unRotatedMinimum; - - float width = unRotatedExtents.x; - float height = unRotatedExtents.y; - float depth = unRotatedExtents.z; - - Extents rotatedExtents = model->getUnscaledMeshExtents(); - calculateRotatedExtents(rotatedExtents, rotation); - - glm::vec3 rotatedSize = rotatedExtents.maximum - rotatedExtents.minimum; - - const glm::vec3& modelScale = model->getScale(); - - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - - // draw the orignal bounding cube - glColor4f(1.0f, 1.0f, 0.0f, 1.0f); - glutWireCube(size); - - // draw the rotated bounding cube - glColor4f(0.0f, 0.0f, 1.0f, 1.0f); - glPushMatrix(); - glScalef(rotatedSize.x * modelScale.x, rotatedSize.y * modelScale.y, rotatedSize.z * modelScale.z); - glutWireCube(1.0); - glPopMatrix(); - - // draw the model relative bounding box - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glScalef(width * modelScale.x, height * modelScale.y, depth * modelScale.z); - glColor3f(0.0f, 1.0f, 0.0f); - glutWireCube(1.0); - - glPopMatrix(); - - } - } else { - // if we couldn't get a model, then just draw a sphere - glColor3ub(entityItem->getColor()[RED_INDEX],entityItem->getColor()[GREEN_INDEX],entityItem->getColor()[BLUE_INDEX]); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glutSolidSphere(radius, 15, 15); - glPopMatrix(); - } - } - glPopMatrix(); - } else { - glColor3f(1.0f, 0.0f, 0.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glutSolidSphere(radius, 15, 15); - glPopMatrix(); - } -} - - -// vertex array for glDrawElements() and glDrawRangeElement() ================= -// Notice that the sizes of these arrays become samller than the arrays for -// glDrawArrays() because glDrawElements() uses an additional index array to -// choose designated vertices with the indices. The size of vertex array is now -// 24 instead of 36, but the index array size is 36, same as the number of -// vertices required to draw a cube. -GLfloat vertices2[] = { 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front) - 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right) - 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top) - -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1,v6,v7,v2 (left) - -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7,v4,v3,v2 (bottom) - 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back) - -// normal array -GLfloat normals2[] = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front) - 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right) - 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top) - -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left) - 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom) - 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back) - -// color array -GLfloat colors2[] = { 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, // v0,v1,v2,v3 (front) - 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, // v0,v3,v4,v5 (right) - 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, // v0,v5,v6,v1 (top) - 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, // v1,v6,v7,v2 (left) - 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // v7,v4,v3,v2 (bottom) - 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 }; // v4,v7,v6,v5 (back) - -// index array of vertex array for glDrawElements() & glDrawRangeElement() -GLubyte indices[] = { 0, 1, 2, 2, 3, 0, // front - 4, 5, 6, 6, 7, 4, // right - 8, 9,10, 10,11, 8, // top - 12,13,14, 14,15,12, // left - 16,17,18, 18,19,16, // bottom - 20,21,22, 22,23,20 }; // back - -void EntityTreeRenderer::renderEntityTypeBox(EntityItem* entity, RenderArgs* args) { - assert(entity->getType() == EntityTypes::Box); - glm::vec3 position = entity->getPosition() * (float)TREE_SCALE; - float size = entity->getSize() * (float)TREE_SCALE; - glm::quat rotation = entity->getRotation(); - BoxEntityItem* boxEntityItem = static_cast(entity); - - - /* - glColor3f(0.0f, 1.0f, 0.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glutSolidCube(size); - - glPopMatrix(); - */ - - // enable and specify pointers to vertex arrays - glEnableClientState(GL_NORMAL_ARRAY); - //glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glNormalPointer(GL_FLOAT, 0, normals2); - //glColorPointer(3, GL_FLOAT, 0, colors2); - glVertexPointer(3, GL_FLOAT, 0, vertices2); - - //glEnable(GL_BLEND); - - glColor3ub(boxEntityItem->getColor()[RED_INDEX], boxEntityItem->getColor()[GREEN_INDEX], boxEntityItem->getColor()[BLUE_INDEX]); - - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glScalef(size, size, size); - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); - glPopMatrix(); - - glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays - //glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - -}; - - float EntityTreeRenderer::getSizeScale() const { return Menu::getInstance()->getVoxelSizeScale(); } diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index ba44f61fcd..b9b148cdc8 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -25,8 +25,6 @@ #include "renderer/Model.h" -class ModelEntityItem; - // Generic client side Octree renderer class. class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService { Q_OBJECT @@ -58,16 +56,19 @@ public: /// clears the tree virtual void clear(); - Q_INVOKABLE Model* getModel(const ModelEntityItem* modelEntityItem); + //Q_INVOKABLE Model* getModel(const ModelEntityItem* modelEntityItem); // renderers for various types of entities void renderEntityTypeBox(EntityItem* entity, RenderArgs* args); void renderEntityTypeModel(EntityItem* entity, RenderArgs* args); + + static QThread* getMainThread(); protected: void clearModelsCache(); - QMap _knownEntityItemModels; - QMap _unknownEntityItemModels; + //QMap _knownEntityItemModels; + //QMap _unknownEntityItemModels; + //QMap _entityItemModels; }; #endif // hifi_EntityTreeRenderer_h diff --git a/interface/src/entities/RenderableBoxEntityItem.cpp b/interface/src/entities/RenderableBoxEntityItem.cpp new file mode 100644 index 0000000000..fb36efc9f3 --- /dev/null +++ b/interface/src/entities/RenderableBoxEntityItem.cpp @@ -0,0 +1,119 @@ +// +// EntityTreeRenderer.cpp +// interface/src +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "InterfaceConfig.h" + +#include +#include +#include + + +#include "Menu.h" +#include "EntityTreeRenderer.h" +#include "RenderableBoxEntityItem.h" + + + +// vertex array for glDrawElements() and glDrawRangeElement() ================= +// Notice that the sizes of these arrays become samller than the arrays for +// glDrawArrays() because glDrawElements() uses an additional index array to +// choose designated vertices with the indices. The size of vertex array is now +// 24 instead of 36, but the index array size is 36, same as the number of +// vertices required to draw a cube. +GLfloat vertices2[] = { 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front) + 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right) + 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top) + -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1,v6,v7,v2 (left) + -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7,v4,v3,v2 (bottom) + 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back) + +// normal array +GLfloat normals2[] = { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front) + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right) + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top) + -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left) + 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom) + 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back) + +// color array +GLfloat colors2[] = { 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, // v0,v1,v2,v3 (front) + 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, // v0,v3,v4,v5 (right) + 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, // v0,v5,v6,v1 (top) + 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, // v1,v6,v7,v2 (left) + 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // v7,v4,v3,v2 (bottom) + 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1 }; // v4,v7,v6,v5 (back) + +// index array of vertex array for glDrawElements() & glDrawRangeElement() +GLubyte indices[] = { 0, 1, 2, 2, 3, 0, // front + 4, 5, 6, 6, 7, 4, // right + 8, 9,10, 10,11, 8, // top + 12,13,14, 14,15,12, // left + 16,17,18, 18,19,16, // bottom + 20,21,22, 22,23,20 }; // back + + +EntityItem* RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + qDebug() << "RenderableBoxEntityItem::factory(const EntityItemID& entityItemID, const EntityItemProperties& properties)..."; + return new RenderableBoxEntityItem(entityID, properties); +} + +void RenderableBoxEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableBoxEntityItem::render"); + assert(getType() == EntityTypes::Box); + glm::vec3 position = getPosition() * (float)TREE_SCALE; + float size = getSize() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + + /* + glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glutSolidCube(size); + + glPopMatrix(); + */ + + // enable and specify pointers to vertex arrays + glEnableClientState(GL_NORMAL_ARRAY); + //glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glNormalPointer(GL_FLOAT, 0, normals2); + //glColorPointer(3, GL_FLOAT, 0, colors2); + glVertexPointer(3, GL_FLOAT, 0, vertices2); + + //glEnable(GL_BLEND); + + glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + // we need to do half the size because the geometry in the VBOs are from -1,-1,-1 to 1,1,1 + float halfSize = size/2.0f; + + glScalef(halfSize, halfSize, halfSize); + glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); + glPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays + //glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + +}; diff --git a/interface/src/entities/RenderableBoxEntityItem.h b/interface/src/entities/RenderableBoxEntityItem.h new file mode 100644 index 0000000000..5e927bf4c2 --- /dev/null +++ b/interface/src/entities/RenderableBoxEntityItem.h @@ -0,0 +1,40 @@ +// +// RenderableBoxEntityItem.h +// interface/src/entities +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderableBoxEntityItem_h +#define hifi_RenderableBoxEntityItem_h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class RenderableBoxEntityItem : public BoxEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableBoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + BoxEntityItem(entityItemID, properties) + { }; + + virtual void render(RenderArgs* args); +}; + + +#endif // hifi_RenderableBoxEntityItem_h diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp new file mode 100644 index 0000000000..2cf4aa9989 --- /dev/null +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -0,0 +1,241 @@ +// +// EntityTreeRenderer.cpp +// interface/src +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "InterfaceConfig.h" + +#include +#include +#include + + +#include "Menu.h" +#include "EntityTreeRenderer.h" +#include "RenderableModelEntityItem.h" + +EntityItem* RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + qDebug() << "RenderableModelEntityItem::factory(const EntityItemID& entityItemID, const EntityItemProperties& properties)..."; + return new RenderableModelEntityItem(entityID, properties); +} + +bool RenderableModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { + QString oldModelURL = getModelURL(); + bool somethingChanged = ModelEntityItem::setProperties(properties, forceCopy); + if (somethingChanged && oldModelURL != getModelURL()) { + _needsModelReload = true; + } + return somethingChanged; +} + +int RenderableModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + QString oldModelURL = getModelURL(); + int bytesRead = ModelEntityItem::readEntitySubclassDataFromBuffer(data, bytesLeftToRead, + args, propertyFlags, overwriteLocalData); + if (oldModelURL != getModelURL()) { + _needsModelReload = true; + } + return bytesRead; +} + + +void RenderableModelEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableModelEntityItem::render"); + assert(getType() == EntityTypes::Model); + + bool drawAsModel = hasModel(); + + glm::vec3 position = getPosition() * (float)TREE_SCALE; + float radius = getRadius() * (float)TREE_SCALE; + float size = getSize() * (float)TREE_SCALE; + + if (drawAsModel) { + glPushMatrix(); + { + const float alpha = 1.0f; + + if (!_model || _needsModelReload) { + // TODO: this getModel() appears to be about 3% of model render time. We should optimize + PerformanceTimer perfTimer("getModel"); + getModel(); + } + + if (_model) { + // handle animations.. + if (hasAnimation()) { + //qDebug() << "hasAnimation()..."; + if (!jointsMapped()) { + QStringList modelJointNames = _model->getJointNames(); + mapJoints(modelJointNames); + //qDebug() << "mapJoints()..."; + } + + if (jointsMapped()) { + //qDebug() << "_model->setJointState()..."; + QVector frameData = getAnimationFrame(); + for (int i = 0; i < frameData.size(); i++) { + _model->setJointState(i, true, frameData[i]); + } + } + } + + glm::quat rotation = getRotation(); + if (_needsSimulation && _model->isActive()) { + _model->setScaleToFit(true, radius * 2.0f); + _model->setSnapModelToCenter(true); + _model->setRotation(rotation); + _model->setTranslation(position); + + // make sure to simulate so everything gets set up correctly for rendering + { + // TODO: _model->simulate() appears to be about 28% of model render time. + // do we really need to call this every frame? I think not. Look into how to + // reduce calls to this. + PerformanceTimer perfTimer("_model->simulate"); + _model->simulate(0.0f); + } + _needsSimulation = false; + } + + // TODO: should we allow entityItems to have alpha on their models? + Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE + ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + + if (_model->isActive()) { + // TODO: this appears to be about 62% of model render time. Is there a way to call this that doesn't + // cost us as much? For example if the same model is used but rendered multiple places is it less + // expensive? + PerformanceTimer perfTimer("model->render"); + _model->render(alpha, modelRenderMode); + } else { + // if we couldn't get a model, then just draw a sphere + glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glutSolidSphere(radius, 15, 15); + glPopMatrix(); + } + + bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE; + bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds); + + if (!isShadowMode && displayModelBounds) { + PerformanceTimer perfTimer("displayModelBounds"); + + glm::vec3 unRotatedMinimum = _model->getUnscaledMeshExtents().minimum; + glm::vec3 unRotatedMaximum = _model->getUnscaledMeshExtents().maximum; + glm::vec3 unRotatedExtents = unRotatedMaximum - unRotatedMinimum; + + float width = unRotatedExtents.x; + float height = unRotatedExtents.y; + float depth = unRotatedExtents.z; + + Extents rotatedExtents = _model->getUnscaledMeshExtents(); + calculateRotatedExtents(rotatedExtents, rotation); + + glm::vec3 rotatedSize = rotatedExtents.maximum - rotatedExtents.minimum; + + const glm::vec3& modelScale = _model->getScale(); + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + + // draw the orignal bounding cube + glColor4f(1.0f, 1.0f, 0.0f, 1.0f); + glutWireCube(size); + + // draw the rotated bounding cube + glColor4f(0.0f, 0.0f, 1.0f, 1.0f); + glPushMatrix(); + glScalef(rotatedSize.x * modelScale.x, rotatedSize.y * modelScale.y, rotatedSize.z * modelScale.z); + glutWireCube(1.0); + glPopMatrix(); + + // draw the model relative bounding box + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glScalef(width * modelScale.x, height * modelScale.y, depth * modelScale.z); + glColor3f(0.0f, 1.0f, 0.0f); + glutWireCube(1.0); + + glPopMatrix(); + + } + } else { + // if we couldn't get a model, then just draw a sphere + glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glutSolidSphere(radius, 15, 15); + glPopMatrix(); + } + } + glPopMatrix(); + } else { + glColor3f(1.0f, 0.0f, 0.0f); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glutSolidSphere(radius, 15, 15); + glPopMatrix(); + } +} + +Model* RenderableModelEntityItem::getModel() { + _needsModelReload = false; // this is the reload + if (!getModelURL().isEmpty()) { + // double check our URLS match... + if (_model && QUrl(getModelURL()) != _model->getURL()) { + delete _model; // delete the old model... + _model = NULL; + _needsSimulation = true; + } + + // if we don't have a model... but our item does have a model URL + if (!_model) { + // Make sure we only create new models on the thread that owns the EntityTreeRenderer + if (QThread::currentThread() != EntityTreeRenderer::getMainThread()) { + + // TODO: how do we better handle this??? we may need this for scripting... + // possible go back to a getModel() service on the TreeRenderer, but have it take a URL + // this would allow the entity items to use that service for loading, and since the + // EntityTreeRenderer is a Q_OBJECT it can call invokeMethod() + + qDebug() << "can't call getModel() on thread other than rendering thread..."; + //qDebug() << "about to call QMetaObject::invokeMethod(this, 'getModel', Qt::BlockingQueuedConnection,..."; + //QMetaObject::invokeMethod(this, "getModel", Qt::BlockingQueuedConnection, Q_RETURN_ARG(Model*, _model)); + //qDebug() << "got it... _model=" << _model; + return _model; + } + + _model = new Model(); + _model->init(); + _model->setURL(QUrl(getModelURL())); + _needsSimulation = true; + } + } else { + // our URL is empty, we should clean up our old model + if (_model) { + delete _model; // delete the old model... + _model = NULL; + _needsSimulation = true; + } + } + return _model; +} + + + + + diff --git a/interface/src/entities/RenderableModelEntityItem.h b/interface/src/entities/RenderableModelEntityItem.h new file mode 100644 index 0000000000..b1639a3d99 --- /dev/null +++ b/interface/src/entities/RenderableModelEntityItem.h @@ -0,0 +1,56 @@ +// +// RenderableModelEntityItem.h +// interface/src/entities +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderableModelEntityItem_h +#define hifi_RenderableModelEntityItem_h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "renderer/Model.h" + +#include +#include + +class RenderableModelEntityItem : public ModelEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + ModelEntityItem(entityItemID, properties), + _model(NULL), + _needsSimulation(true), + _needsModelReload(true) { }; + + virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy); + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + virtual void somethingChangedNotification() { _needsSimulation = true; } + + virtual void render(RenderArgs* args); + Model* getModel(); +private: + Model* _model; + bool _needsSimulation; + bool _needsModelReload; +}; + +#endif // hifi_RenderableModelEntityItem_h diff --git a/interface/src/entities/RenderableSphereEntityItem.cpp b/interface/src/entities/RenderableSphereEntityItem.cpp new file mode 100644 index 0000000000..04df7c8ce2 --- /dev/null +++ b/interface/src/entities/RenderableSphereEntityItem.cpp @@ -0,0 +1,50 @@ +// +// RenderableSphereEntityItem.cpp +// interface/src +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "InterfaceConfig.h" + +#include +#include + + +#include "Menu.h" +#include "EntityTreeRenderer.h" +#include "RenderableSphereEntityItem.h" + + +EntityItem* RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + qDebug() << "RenderableSphereEntityItem::factory(const EntityItemID& entityItemID, const EntityItemProperties& properties)..."; + return new RenderableSphereEntityItem(entityID, properties); +} + +void RenderableSphereEntityItem::render(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableSphereEntityItem::render"); + assert(getType() == EntityTypes::Sphere); + glm::vec3 position = getPosition() * (float)TREE_SCALE; + float radius = getRadius() * (float)TREE_SCALE; + glm::quat rotation = getRotation(); + + + glColor3ub(getColor()[RED_INDEX], getColor()[GREEN_INDEX], getColor()[BLUE_INDEX]); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + + // TODO: we can probably get rid of this rotation until we support different radius dimensions + //glm::vec3 axis = glm::axis(rotation); + //glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glutSolidSphere(radius, 15, 15); + + glPopMatrix(); +}; diff --git a/interface/src/entities/RenderableSphereEntityItem.h b/interface/src/entities/RenderableSphereEntityItem.h new file mode 100644 index 0000000000..78880f7753 --- /dev/null +++ b/interface/src/entities/RenderableSphereEntityItem.h @@ -0,0 +1,40 @@ +// +// RenderableSphereEntityItem.h +// interface/src/entities +// +// Created by Brad Hefta-Gaub on 12/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderableSphereEntityItem_h +#define hifi_RenderableSphereEntityItem_h + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +class RenderableSphereEntityItem : public SphereEntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + RenderableSphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + SphereEntityItem(entityItemID, properties) + { }; + + virtual void render(RenderArgs* args); +}; + + +#endif // hifi_RenderableSphereEntityItem_h diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 2ec676de53..b50379b131 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1242,8 +1242,6 @@ float Model::getLimbLength(int jointIndex) const { return length; } -const int BALL_SUBDIVISIONS = 10; - void Model::renderJointCollisionShapes(float alpha) { // implement this when we have shapes for regular models } diff --git a/libraries/entities/src/BoxEntityItem.cpp b/libraries/entities/src/BoxEntityItem.cpp index ed42d9c39f..cf27bd5d71 100644 --- a/libraries/entities/src/BoxEntityItem.cpp +++ b/libraries/entities/src/BoxEntityItem.cpp @@ -56,12 +56,12 @@ EntityItemProperties BoxEntityItem::getProperties() const { return properties; } -void BoxEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool BoxEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { qDebug() << "BoxEntityItem::setProperties()..."; qDebug() << "BoxEntityItem::BoxEntityItem() properties.getModelURL()=" << properties.getModelURL(); bool somethingChanged = false; - EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class if (properties._colorChanged || forceCopy) { setColor(properties._color); @@ -83,6 +83,7 @@ void BoxEntityItem::setProperties(const EntityItemProperties& properties, bool f } setLastEdited(properties._lastEdited); } + return somethingChanged; } int BoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, diff --git a/libraries/entities/src/BoxEntityItem.h b/libraries/entities/src/BoxEntityItem.h index 2d60618b8e..b5f4521f96 100644 --- a/libraries/entities/src/BoxEntityItem.h +++ b/libraries/entities/src/BoxEntityItem.h @@ -19,12 +19,12 @@ public: static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); BoxEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - - virtual void somePureVirtualFunction() { }; // allow this class to be constructed - + + ALLOW_INSTANTIATION // This class can be instantiated + // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual void setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a16677047d..ad965c10e8 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -421,7 +421,7 @@ int EntityItem::expectedBytes() { int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { - bool wantDebug = true; + bool wantDebug = false; if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) { qDebug() << "EntityItem::readEntityDataFromBuffer()... ERROR CASE...args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU"; @@ -499,6 +499,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } _lastEdited = lastEditedFromBuffer; + + somethingChangedNotification(); // notify derived classes that something has changed + } // last updated is stored as ByteCountCoded delta from lastEdited @@ -828,7 +831,7 @@ EntityItemProperties EntityItem::getProperties() const { return properties; } -void EntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool EntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { //qDebug() << "EntityItem::setProperties()... forceCopy=" << forceCopy; //qDebug() << "EntityItem::setProperties() properties.getDamping()=" << properties.getDamping(); //qDebug() << "EntityItem::setProperties() properties.getVelocity()=" << properties.getVelocity(); @@ -886,6 +889,7 @@ void EntityItem::setProperties(const EntityItemProperties& properties, bool forc } if (somethingChanged) { + somethingChangedNotification(); // notify derived classes that something has changed bool wantDebug = false; if (wantDebug) { uint64_t now = usecTimestampNow(); @@ -895,6 +899,7 @@ void EntityItem::setProperties(const EntityItemProperties& properties, bool forc } setLastEdited(properties._lastEdited); } - + + return somethingChanged; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5df1bed843..314781bd40 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -27,15 +27,21 @@ class EntityTreeElementExtraEncodeData; -/// EntityItem class - this is the actual model item class. +#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; +#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { }; + + +/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available +/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate +/// one directly, instead you must only construct one of it's derived classes with additional features. class EntityItem { public: + DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly + EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); virtual ~EntityItem(); - - virtual void somePureVirtualFunction() = 0; // ID and EntityItemID related methods QUuid getID() const { return _id; } @@ -48,7 +54,13 @@ public: // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual void setProperties(const EntityItemProperties& properties, bool forceCopy = false); + + /// returns true is something changed + virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + + /// override this in your derived class if you'd like to be informed when something about the state of the entity + /// has changed. This will be called with properties change or when new data is loaded from a stream + virtual void somethingChangedNotification() { } quint64 getLastUpdated() const { return _lastUpdated; } /// Last simulated time of this entity universal usecs quint64 getLastEdited() const { return _lastEdited; } /// Last edited time of this entity universal usecs @@ -78,7 +90,9 @@ public: virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData) - { return 0; }; + { return 0; } + + virtual void render(RenderArgs* args) { } // by default entity items don't know how to render static int expectedBytes(); @@ -164,7 +178,7 @@ public: static const QString DEFAULT_SCRIPT; const QString& getScript() const { return _script; } void setScript(const QString& value) { _script = value; } - + protected: virtual void initFromEntityItemID(const EntityItemID& entityItemID); // maybe useful to allow subclasses to init @@ -188,52 +202,4 @@ protected: QString _script; }; -class SphereEntityItem : public EntityItem { -public: - SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - EntityItem(entityItemID, properties) { _type = EntityTypes::Sphere; } - - virtual void somePureVirtualFunction() { }; // allow this class to be constructed - - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new SphereEntityItem(entityID, properties); - } -}; - -class PlaneEntityItem : public EntityItem { -public: - PlaneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - EntityItem(entityItemID, properties) { _type = EntityTypes::Plane; } - - virtual void somePureVirtualFunction() { }; // allow this class to be constructed - - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new PlaneEntityItem(entityID, properties); - } -}; - -class CylinderEntityItem : public EntityItem { -public: - CylinderEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - EntityItem(entityItemID, properties) { _type = EntityTypes::Cylinder; } - - virtual void somePureVirtualFunction() { }; // allow this class to be constructed - - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new CylinderEntityItem(entityID, properties); - } -}; - -class PyramidEntityItem : public EntityItem { -public: - PyramidEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : - EntityItem(entityItemID, properties) { _type = EntityTypes::Pyramid; } - - virtual void somePureVirtualFunction() { }; // allow this class to be constructed - - static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - return new PyramidEntityItem(entityID, properties); - } -}; - #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 73f6cbb6d5..22ddb42003 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -180,6 +180,23 @@ public: static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes, EntityItemID& entityID, EntityItemProperties& properties); + bool positionChanged() const { return _positionChanged; } + bool radiusChanged() const { return _radiusChanged; } + bool rotationChanged() const { return _rotationChanged; } + bool massChanged() const { return _massChanged; } + bool velocityChanged() const { return _velocityChanged; } + bool gravityChanged() const { return _gravityChanged; } + bool dampingChanged() const { return _dampingChanged; } + bool lifetimeChanged() const { return _lifetimeChanged; } + bool scriptChanged() const { return _scriptChanged; } + bool colorChanged() const { return _colorChanged; } + bool modelURLChanged() const { return _modelURLChanged; } + bool animationURLChanged() const { return _animationURLChanged; } + bool animationIsPlayingChanged() const { return _animationIsPlayingChanged; } + bool animationFrameIndexChanged() const { return _animationFrameIndexChanged; } + bool animationFPSChanged() const { return _animationFPSChanged; } + bool glowLevelChanged() const { return _glowLevelChanged; } + private: void setLastEdited(quint64 lastEdited) { _lastEdited = lastEdited; } diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 8638398bfb..6e5b02a124 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -20,23 +20,19 @@ #include "BoxEntityItem.h" #include "ModelEntityItem.h" +#include "SphereEntityItem.h" QMap EntityTypes::_typeToNameMap; QMap EntityTypes::_nameToTypeMap; EntityTypeFactory EntityTypes::_factories[EntityTypes::LAST]; bool EntityTypes::_factoriesInitialized = false; -EntityTypeRenderer EntityTypes::_renderers[EntityTypes::LAST]; -bool EntityTypes::_renderersInitialized = false; const QString ENTITY_TYPE_NAME_UNKNOWN = "Unknown"; -// Register Entity Types here... +// Register Entity the default implementations of entity types here... REGISTER_ENTITY_TYPE(Model) REGISTER_ENTITY_TYPE(Box) REGISTER_ENTITY_TYPE(Sphere) -REGISTER_ENTITY_TYPE(Plane) -REGISTER_ENTITY_TYPE(Cylinder) -REGISTER_ENTITY_TYPE(Pyramid) const QString& EntityTypes::getEntityTypeName(EntityType entityType) { @@ -153,24 +149,3 @@ EntityItem* EntityTypes::constructEntityItem(const unsigned char* data, int byte return NULL; } - -bool EntityTypes::registerEntityTypeRenderer(EntityType entityType, EntityTypeRenderer renderMethod) { - if (!_renderersInitialized) { - memset(&_renderers,0,sizeof(_renderers)); - _renderersInitialized = true; - } - _renderers[entityType] = renderMethod; - - return true; -} - -void EntityTypes::renderEntityItem(EntityItem* entityItem, RenderArgs* args) { - EntityType entityType = entityItem->getType(); - EntityTypeRenderer renderMethod = _renderers[entityType]; - if (renderMethod) { - renderMethod(entityItem, args); - } -} - - - diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 290a66b815..7e9828c441 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -25,7 +25,6 @@ class EntityItemProperties; class ReadBitstreamToTreeParams; typedef EntityItem* (*EntityTypeFactory)(const EntityItemID& entityID, const EntityItemProperties& properties); -typedef void (*EntityTypeRenderer)(EntityItem* entity, RenderArgs* args); class EntityTypes { public: @@ -34,10 +33,7 @@ public: Model, Box, Sphere, - Plane, - Cylinder, - Pyramid, - LAST = Pyramid + LAST = Sphere } EntityType; static const QString& getEntityTypeName(EntityType entityType); @@ -46,16 +42,11 @@ public: static EntityItem* constructEntityItem(EntityType entityType, const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItem* constructEntityItem(const unsigned char* data, int bytesToRead, ReadBitstreamToTreeParams& args); - static bool registerEntityTypeRenderer(EntityType entityType, EntityTypeRenderer renderMethod); - static void renderEntityItem(EntityItem* entityItem, RenderArgs* args); - private: static QMap _typeToNameMap; static QMap _nameToTypeMap; static EntityTypeFactory _factories[LAST]; static bool _factoriesInitialized; - static EntityTypeRenderer _renderers[LAST]; - static bool _renderersInitialized; }; @@ -66,7 +57,13 @@ private: #define REGISTER_ENTITY_TYPE(x) static bool x##Registration = \ EntityTypes::registerEntityType(EntityTypes::x, #x, x##EntityItem::factory); -#define REGISTER_ENTITY_TYPE_RENDERER(x,y) EntityTypes::registerEntityTypeRenderer(EntityTypes::x, y); +/// Macro for registering entity types with an overloaded factory. Like using the REGISTER_ENTITY_TYPE macro: Make sure to add +/// an element to the EntityType enum with your name. But unlike REGISTER_ENTITY_TYPE, your class can be named anything +/// so long as you provide a static method passed to the macro, that takes an EnityItemID, and EntityItemProperties and +/// returns a newly constructed (heap allocated) instance of your type. e.g. The following prototype: +// static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); +#define REGISTER_ENTITY_TYPE_WITH_FACTORY(x,y) static bool x##Registration = \ + EntityTypes::registerEntityType(EntityTypes::x, #x, y); #endif // hifi_EntityTypes_h diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 7011233871..cc4ba51a88 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -63,11 +63,11 @@ EntityItemProperties ModelEntityItem::getProperties() const { return properties; } -void ModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { +bool ModelEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { //qDebug() << "ModelEntityItem::setProperties()..."; bool somethingChanged = false; - EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class if (properties._colorChanged || forceCopy) { setColor(properties._color); @@ -114,6 +114,8 @@ void ModelEntityItem::setProperties(const EntityItemProperties& properties, bool } setLastEdited(properties._lastEdited); } + + return somethingChanged; } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index b51725159a..4097328f02 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -20,11 +20,11 @@ public: ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); - virtual void somePureVirtualFunction() { }; // allow this class to be constructed + ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties() const; - virtual void setProperties(const EntityItemProperties& properties, bool forceCopy = false); + virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); // TODO: eventually only include properties changed since the params.lastViewFrustumSent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp new file mode 100644 index 0000000000..0e6914c555 --- /dev/null +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -0,0 +1,128 @@ +// +// SphereEntityItem.cpp +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#include + +#include + +#include "EntityTree.h" +#include "EntityTreeElement.h" +#include "SphereEntityItem.h" + + +EntityItem* SphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + qDebug() << "SphereEntityItem::factory(const EntityItemID& entityItemID, const EntityItemProperties& properties)..."; + return new SphereEntityItem(entityID, properties); +} + +// our non-pure virtual subclass for now... +SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : + EntityItem(entityItemID, properties) +{ + _type = EntityTypes::Sphere; + setProperties(properties); +} + +EntityItemProperties SphereEntityItem::getProperties() const { + EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class + + properties.setColor(getXColor()); + properties.setGlowLevel(getGlowLevel()); + + return properties; +} + +bool SphereEntityItem::setProperties(const EntityItemProperties& properties, bool forceCopy) { + bool somethingChanged = EntityItem::setProperties(properties, forceCopy); // set the properties in our base class + + if (properties.colorChanged() || forceCopy) { + setColor(properties.getColor()); + somethingChanged = true; + } + + if (properties.glowLevelChanged() || forceCopy) { + setGlowLevel(properties.getGlowLevel()); + somethingChanged = true; + } + + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - _lastEdited; + qDebug() << "SphereEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " _lastEdited=" << _lastEdited; + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; +} + +int SphereEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + // PROP_COLOR + if (propertyFlags.getHasProperty(PROP_COLOR)) { + rgbColor color; + if (overwriteLocalData) { + memcpy(_color, dataAt, sizeof(_color)); + } + dataAt += sizeof(color); + bytesRead += sizeof(color); + } + + + return bytesRead; +} + + +// TODO: eventually only include properties changed since the params.lastViewFrustumSent time +EntityPropertyFlags SphereEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + requestedProperties += PROP_COLOR; + return requestedProperties; +} + +void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + // PROP_COLOR + if (requestedProperties.getHasProperty(PROP_COLOR)) { + //qDebug() << "PROP_COLOR requested..."; + LevelDetails propertyLevel = packetData->startLevel(); + successPropertyFits = packetData->appendColor(getColor()); + if (successPropertyFits) { + propertyFlags |= PROP_COLOR; + propertiesDidntFit -= PROP_COLOR; + propertyCount++; + packetData->endLevel(propertyLevel); + } else { + //qDebug() << "PROP_COLOR didn't fit..."; + packetData->discardLevel(propertyLevel); + appendState = OctreeElement::PARTIAL; + } + } else { + //qDebug() << "PROP_COLOR NOT requested..."; + propertiesDidntFit -= PROP_COLOR; + } +} \ No newline at end of file diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h new file mode 100644 index 0000000000..337f229a69 --- /dev/null +++ b/libraries/entities/src/SphereEntityItem.h @@ -0,0 +1,57 @@ +// +// SphereEntityItem.h +// libraries/entities/src +// +// Created by Brad Hefta-Gaub on 12/4/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SphereEntityItem_h +#define hifi_SphereEntityItem_h + +#include "EntityItem.h" + +class SphereEntityItem : public EntityItem { +public: + static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + SphereEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); + + ALLOW_INSTANTIATION // This class can be instantiated + + // methods for getting/setting all properties of an entity + virtual EntityItemProperties getProperties() const; + virtual bool setProperties(const EntityItemProperties& properties, bool forceCopy = false); + + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const; + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + + const rgbColor& getColor() const { return _color; } + xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + + void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } + void setColor(const xColor& value) { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + } + +protected: + rgbColor _color; +}; + +#endif // hifi_SphereEntityItem_h diff --git a/libraries/entities/src/todo.txt b/libraries/entities/src/todo.txt index 3f934c0803..94dee866b5 100644 --- a/libraries/entities/src/todo.txt +++ b/libraries/entities/src/todo.txt @@ -33,6 +33,12 @@ Model properties: // // REQUIRED TO DO: + 0) render performance of models... + a) make getModel() faster... consider storing the Model* in the actual EntityItem class + b) figure out how to only call simulate when needed: + if the properties change + when animated? + 1) verify lots of models in single element works -- repro case - run editModelsExample.js -- create 10 models in the same octree element @@ -62,7 +68,6 @@ Model properties: 7) Handle the ID -> UUID swap in old files to new files 8) Test models -> attachments logic - 9) What happens if the edit properties don't fit in a single message MTU??? 10) animations not always working????? @@ -79,7 +84,6 @@ Model properties: P) unit tests? Pa) OctreeTests::modelItemTests()...???? - G) why does is the Box entity not drawn in it's bounds H) make the rotated model bounds work for other entity types? I) maybe make "hasGeometry" be a property of EntityItem base class?? @@ -237,3 +241,4 @@ Model properties: // maybe remember the extra state before removing it and if it fails, always re-add it // maybe add support for "reserving" bytes in the packet // SOLVED -- BROKEN File persistence... -- added chunking support in SVO file persistence. +// SOLVED -- G) why does is the Box entity not drawn in it's bounds diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 3b0b4d2e34..6b8dd86c60 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -236,13 +236,6 @@ OctreeElement* Octree::createMissingElement(OctreeElement* lastParentElement, co int Octree::readElementData(OctreeElement* destinationElement, const unsigned char* nodeData, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { -bool wantDebug = true; -if (wantDebug) { - qDebug() << "Octree::readElementData()"; - qDebug() << " destinationElement->getAACube()=" << destinationElement->getAACube(); - qDebug() << " bytesLeftToRead=" << bytesLeftToRead; -} - // give this destination element the child mask from the packet const unsigned char ALL_CHILDREN_ASSUMED_TO_EXIST = 0xFF; unsigned char colorInPacketMask = *nodeData; @@ -287,8 +280,6 @@ if (wantDebug) { int childIndex = 0; bytesRead += args.includeExistsBits ? sizeof(childrenInTreeMask) + sizeof(childMask) : sizeof(childMask); - //qDebug() << "Octree::readElementData()... childrenInTreeMask=" << childrenInTreeMask; - while (bytesLeftToRead - bytesRead > 0 && childIndex < NUMBER_OF_CHILDREN) { // check the exists mask to see if we have a child to traverse into @@ -324,33 +315,15 @@ if (wantDebug) { // if this is the root, and there is more data to read, allow it to read it's element data... if (destinationElement == _rootElement && rootElementHasData() && (bytesLeftToRead - bytesRead) > 0) { // tell the element to read the subsequent data - if (wantDebug) { - qDebug() << "Octree::readElementData().... reading element data for root element....."; - qDebug() << " bytesRead=" << bytesRead; - qDebug() << " bytesLeftToRead - bytesRead=" << bytesLeftToRead - bytesRead; - qDebug() << " READING ROOT DATA...."; - } - bytesRead += _rootElement->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead - bytesRead, args); } - if (wantDebug) { - qDebug() << "Octree::readElementData()"; - qDebug() << " bytesRead=" << bytesLeftToRead; - } - return bytesRead; } void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long int bufferSizeBytes, ReadBitstreamToTreeParams& args) { -bool wantDebug = true; -if (wantDebug) { - qDebug() << "Octree::readBitstreamToTree()"; - qDebug() << " bufferSizeBytes=" << bufferSizeBytes; -} - int bytesRead = 0; const unsigned char* bitstreamAt = bitstream; @@ -379,31 +352,15 @@ if (wantDebug) { int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt); -if (wantDebug) { - qDebug() << "Octree::readBitstreamToTree()"; - qDebug() << " octalCodeBytes=" << octalCodeBytes; -} - int theseBytesRead = 0; theseBytesRead += octalCodeBytes; -if (wantDebug) { - qDebug() << " --- calling readElementData() bytes available=" << (bufferSizeBytes - (bytesRead + octalCodeBytes)) << "---"; -} theseBytesRead += readElementData(bitstreamRootElement, bitstreamAt + octalCodeBytes, bufferSizeBytes - (bytesRead + octalCodeBytes), args); -if (wantDebug) { - qDebug() << " --- AFTER calling readElementData() ---"; - qDebug() << " theseBytesRead=" << theseBytesRead; -} // skip bitstream to new startPoint bitstreamAt += theseBytesRead; bytesRead += theseBytesRead; -if (wantDebug) { - qDebug() << " bytesRead=" << bytesRead; -} - if (args.wantImportProgress) { emit importProgress((100 * (bitstreamAt - bitstream)) / bufferSizeBytes); } @@ -1891,12 +1848,6 @@ bool Octree::readFromSVOFile(const char* fileName) { unsigned long headerLength = 0; // bytes in the header - bool wantDebug = true; - if (wantDebug) { - qDebug() << "Octree::readFromSVOFile()"; - qDebug() << " fileLength=" << fileLength; - } - bool wantImportProgress = true; // before reading the file, check to see if this version of the Octree supports file versions @@ -1964,11 +1915,6 @@ bool Octree::readFromSVOFile(const char* fileName) { ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, SharedNodePointer(), wantImportProgress, gotVersion); - if (wantDebug) { - qDebug() << " --- after reading header, type and version ---"; - qDebug() << " dataLength=" << dataLength; - qDebug() << " --- calling readBitstreamToTree() ---"; - } readBitstreamToTree(dataAt, dataLength, args); delete[] entireFileDataSection; @@ -1985,8 +1931,6 @@ bool Octree::readFromSVOFile(const char* fileName) { file.read((char*)&chunkLength, sizeof(chunkLength)); // read the chunk size from the file - qDebug() << "read chunk size of:" << chunkLength; - remainingLength -= sizeof(chunkLength); if (chunkLength > remainingLength) { @@ -2011,9 +1955,6 @@ bool Octree::readFromSVOFile(const char* fileName) { ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, SharedNodePointer(), wantImportProgress, gotVersion); - if (wantDebug) { - qDebug() << " --- calling readBitstreamToTree() dataLength:" << dataLength << "---"; - } readBitstreamToTree(dataAt, dataLength, args); } @@ -2084,7 +2025,6 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) { if (hasBufferBreaks) { quint16 bufferSize = packetData.getFinalizedSize(); file.write((const char*)&bufferSize, sizeof(bufferSize)); - qDebug() << "wrote chunk size of:" << bufferSize << "---"; } file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize()); lastPacketWritten = true; @@ -2102,7 +2042,6 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) { if (hasBufferBreaks) { quint16 bufferSize = packetData.getFinalizedSize(); file.write((const char*)&bufferSize, sizeof(bufferSize)); - qDebug() << "wrote FINAL chunk size of:" << bufferSize << "---"; } file.write((const char*)packetData.getFinalizedData(), packetData.getFinalizedSize()); }