mirror of
https://github.com/JulianGro/overte.git
synced 2025-05-16 22:40:51 +02:00
518 lines
21 KiB
C++
518 lines
21 KiB
C++
//
|
|
// 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 <glm/gtx/quaternion.hpp>
|
|
|
|
#include <FBXReader.h>
|
|
|
|
#include "InterfaceConfig.h"
|
|
|
|
#include <ModelEntityItem.h>
|
|
#include <BoxEntityItem.h>
|
|
|
|
|
|
#include "Menu.h"
|
|
#include "EntityTreeRenderer.h"
|
|
|
|
|
|
|
|
EntityTreeRenderer::EntityTreeRenderer() :
|
|
OctreeRenderer() {
|
|
}
|
|
|
|
EntityTreeRenderer::~EntityTreeRenderer() {
|
|
clearModelsCache();
|
|
}
|
|
|
|
void EntityTreeRenderer::clear() {
|
|
OctreeRenderer::clear();
|
|
clearModelsCache();
|
|
}
|
|
|
|
void EntityTreeRenderer::clearModelsCache() {
|
|
qDebug() << "EntityTreeRenderer::clearModelsCache()...";
|
|
|
|
// delete the models in _knownEntityItemModels
|
|
foreach(Model* model, _knownEntityItemModels) {
|
|
delete model;
|
|
}
|
|
_knownEntityItemModels.clear();
|
|
|
|
foreach(Model* model, _unknownEntityItemModels) {
|
|
delete model;
|
|
}
|
|
_unknownEntityItemModels.clear();
|
|
}
|
|
|
|
void EntityTreeRenderer::init() {
|
|
//REGISTER_ENTITY_TYPE_RENDERER(Model, this->renderEntityTypeModel);
|
|
//REGISTER_ENTITY_TYPE_RENDERER(Box, this->renderEntityTypeBox);
|
|
|
|
OctreeRenderer::init();
|
|
static_cast<EntityTree*>(_tree)->setFBXService(this);
|
|
}
|
|
|
|
void EntityTreeRenderer::setTree(Octree* newTree) {
|
|
OctreeRenderer::setTree(newTree);
|
|
static_cast<EntityTree*>(_tree)->setFBXService(this);
|
|
}
|
|
|
|
void EntityTreeRenderer::update() {
|
|
if (_tree) {
|
|
EntityTree* tree = static_cast<EntityTree*>(_tree);
|
|
tree->update();
|
|
}
|
|
}
|
|
|
|
void EntityTreeRenderer::render(RenderMode renderMode) {
|
|
//qDebug() << "EntityTreeRenderer::render() ************";
|
|
OctreeRenderer::render(renderMode);
|
|
//qDebug() << "-------------------- EntityTreeRenderer::render() ------------";
|
|
//static_cast<EntityTree*>(_tree)->debugDumpMap();
|
|
//qDebug() << "******* DONE ******* EntityTreeRenderer::render() ************";
|
|
}
|
|
|
|
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(const EntityItem* entityItem) {
|
|
const FBXGeometry* result = NULL;
|
|
|
|
if (entityItem->getType() == EntityTypes::Model) {
|
|
const ModelEntityItem* modelEntityItem = static_cast<const ModelEntityItem*>(entityItem);
|
|
|
|
Model* model = getModel(modelEntityItem);
|
|
if (model) {
|
|
result = &model->getGeometry()->getFBXGeometry();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityItem) {
|
|
const Model* result = NULL;
|
|
if (entityItem->getType() == EntityTypes::Model) {
|
|
const ModelEntityItem* modelEntityItem = static_cast<const ModelEntityItem*>(entityItem);
|
|
|
|
result = getModel(modelEntityItem);
|
|
}
|
|
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) {
|
|
args->_elementsTouched++;
|
|
// actually render it here...
|
|
// we need to iterate the actual entityItems of the element
|
|
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
|
|
|
QList<EntityItem*>& entityItems = entityTreeElement->getEntities();
|
|
|
|
|
|
uint16_t numberOfEntities = entityItems.size();
|
|
|
|
//qDebug() << "EntityTreeRenderer::renderElement() element=" << element << "numberOfEntities=" << numberOfEntities;
|
|
|
|
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
|
|
bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy);
|
|
bool displayElementChildProxies = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementChildProxies);
|
|
|
|
|
|
if (!isShadowMode && displayElementProxy && numberOfEntities > 0) {
|
|
glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter() * (float)TREE_SCALE;
|
|
float elementSize = entityTreeElement->getScale() * (float)TREE_SCALE;
|
|
glColor3f(1.0f, 0.0f, 0.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x, elementCenter.y, elementCenter.z);
|
|
glutWireCube(elementSize);
|
|
glPopMatrix();
|
|
|
|
if (displayElementChildProxies) {
|
|
// draw the children
|
|
float halfSize = elementSize / 2.0f;
|
|
float quarterSize = elementSize / 4.0f;
|
|
glColor3f(1.0f, 1.0f, 0.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(1.0f, 0.0f, 1.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z - quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(0.0f, 1.0f, 0.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(0.0f, 0.0f, 1.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(1.0f, 1.0f, 1.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(0.0f, 0.5f, 0.5f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x - quarterSize, elementCenter.y + quarterSize, elementCenter.z + quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(0.5f, 0.0f, 0.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y - quarterSize, elementCenter.z + quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
|
|
glColor3f(0.0f, 0.5f, 0.0f);
|
|
glPushMatrix();
|
|
glTranslatef(elementCenter.x + quarterSize, elementCenter.y + quarterSize, elementCenter.z - quarterSize);
|
|
glutWireCube(halfSize);
|
|
glPopMatrix();
|
|
}
|
|
|
|
}
|
|
|
|
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
|
EntityItem* entityItem = entityItems[i];
|
|
|
|
bool wantDebug = false;
|
|
|
|
if (wantDebug) {
|
|
bool isBestFit = entityTreeElement->bestFitEntityBounds(entityItem);
|
|
qDebug() << "EntityTreeRenderer::renderElement() "
|
|
<< "entityTreeElement=" << entityTreeElement
|
|
<< "entityItems[" << i << "]=" << entityItem
|
|
<< "ID=" << entityItem->getEntityItemID()
|
|
<< "isBestFit=" << isBestFit;
|
|
}
|
|
|
|
// render entityItem aspoints
|
|
AACube entityCube = entityItem->getAACube();
|
|
entityCube.scale(TREE_SCALE);
|
|
|
|
// TODO: some entity types (like lights) might want to be rendered even
|
|
// when they are outside of the view frustum...
|
|
if (args->_viewFrustum->cubeInFrustum(entityCube) != ViewFrustum::OUTSIDE) {
|
|
|
|
Glower* glower = NULL;
|
|
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);
|
|
}
|
|
|
|
if (glower) {
|
|
delete glower;
|
|
}
|
|
|
|
} else {
|
|
args->_itemsOutOfView++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EntityTreeRenderer::renderEntityTypeModel(EntityItem* entity, RenderArgs* args) {
|
|
assert(entity->getType() == EntityTypes::Model);
|
|
|
|
ModelEntityItem* entityItem = static_cast<ModelEntityItem*>(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<glm::quat> 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<BoxEntityItem*>(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();
|
|
}
|
|
|
|
int EntityTreeRenderer::getBoundaryLevelAdjust() const {
|
|
return Menu::getInstance()->getBoundaryLevelAdjust();
|
|
}
|
|
|
|
|
|
void EntityTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
|
static_cast<EntityTree*>(_tree)->processEraseMessage(dataByteArray, sourceNode);
|
|
}
|
|
|
|
|
|
|
|
|
|
|