Merge pull request #4789 from Atlante45/display_zones

Display zones
This commit is contained in:
samcake 2015-05-07 11:20:46 -07:00
commit 12c26f9c3c
15 changed files with 339 additions and 185 deletions

View file

@ -35,6 +35,7 @@ ZoneOverlayManager = function(isEntityFunc, entityAddedFunc, entityRemovedFunc,
this.setVisible = function(isVisible) {
if (visible != isVisible) {
visible = isVisible;
Entities.setDrawZoneBoundaries(visible);
for (var id in entityOverlays) {
Overlays.editOverlay(entityOverlays[id].solid, { visible: visible });
Overlays.editOverlay(entityOverlays[id].outline, { visible: visible });

View file

@ -3254,6 +3254,11 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
renderMode = RenderArgs::MIRROR_RENDER_MODE;
}
_entities.render(renderMode, renderSide, renderDebugFlags);
if (!Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) {
// Restaure polygon mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
// render JS/scriptable overlays

View file

@ -685,7 +685,7 @@ void ApplicationOverlay::renderControllerPointers() {
}
//If the cursor is out of the screen then don't render it
if (mouseX < 0 || mouseX >= canvasSize.x || mouseY < 0 || mouseY >= canvasSize.y) {
if (mouseX < 0 || mouseX >= (int)canvasSize.x || mouseY < 0 || mouseY >= (int)canvasSize.y) {
_reticleActive[index] = false;
continue;
}
@ -998,7 +998,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() {
if (nodeList && !nodeList->getDomainHandler().isConnected()) {
auto geometryCache = DependencyManager::get<GeometryCache>();
auto canvasSize = qApp->getCanvasSize();
if (canvasSize.x != _previousBorderWidth || canvasSize.y != _previousBorderHeight) {
if ((int)canvasSize.x != _previousBorderWidth || (int)canvasSize.y != _previousBorderHeight) {
glm::vec4 color(CONNECTION_STATUS_BORDER_COLOR[0],
CONNECTION_STATUS_BORDER_COLOR[1],
CONNECTION_STATUS_BORDER_COLOR[2], 1.0f);

View file

@ -87,11 +87,10 @@ void Overlays::renderHUD() {
QReadLocker lock(&_lock);
auto lodManager = DependencyManager::get<LODManager>();
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
RenderArgs args(NULL, Application::getInstance()->getViewFrustum(),
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
foreach(Overlay* thisOverlay, _overlaysHUD) {
if (thisOverlay->is3D()) {
@ -125,11 +124,10 @@ void Overlays::renderWorld(bool drawFront,
float myAvatarScale = 1.0f;
auto lodManager = DependencyManager::get<LODManager>();
RenderArgs args = { NULL, Application::getInstance()->getDisplayViewFrustum(),
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
renderMode, renderSide, renderDebugFlags,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
RenderArgs args(NULL, Application::getInstance()->getDisplayViewFrustum(),
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
renderMode, renderSide, renderDebugFlags);
foreach(Overlay* thisOverlay, _overlaysWorld) {

View file

@ -392,8 +392,8 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
ViewFrustum* frustum = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ?
_viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum();
RenderArgs args = { this, frustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide,
renderDebugFlags, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
RenderArgs args(this, frustum, getSizeScale(), getBoundaryLevelAdjust(),
renderMode, renderSide, renderDebugFlags);
_tree->lockForRead();
@ -677,8 +677,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
if (entityItem->isVisible()) {
// NOTE: Zone Entities are a special case we handle here... Zones don't render
// like other entity types. So we will skip the normal rendering tests
// NOTE: Zone Entities are a special case we handle here...
if (entityItem->getType() == EntityTypes::Zone) {
if (entityItem->contains(_viewState->getAvatarPosition())) {
float entityVolumeEstimate = entityItem->getVolumeEstimate();
@ -699,42 +698,42 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
}
}
}
} else {
// render entityItem
AABox entityBox = entityItem->getAABox();
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter());
}
bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE;
if (!outOfView) {
bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance);
// render entityItem
AABox entityBox = entityItem->getAABox();
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter());
bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE;
if (!outOfView) {
bool bigEnoughToRender = _viewState->shouldRenderMesh(entityBox.getLargestDimension(), distance);
if (bigEnoughToRender) {
renderProxies(entityItem, args);
Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
}
} else {
args->_itemsTooSmall++;
if (bigEnoughToRender) {
renderProxies(entityItem, args);
Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
}
} else {
args->_itemsOutOfView++;
args->_itemsTooSmall++;
}
} else {
args->_itemsOutOfView++;
}
}
}
}
float EntityTreeRenderer::getSizeScale() const {
float EntityTreeRenderer::getSizeScale() const {
return _viewState->getSizeScale();
}

View file

@ -11,8 +11,10 @@
#include "RenderableZoneEntityItem.h"
#include <DeferredLightingEffect.h>
#include <DependencyManager.h>
#include <GeometryCache.h>
#include <PerfStat.h>
EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
return new RenderableZoneEntityItem(entityID, properties);
@ -27,10 +29,12 @@ void RenderableZoneEntityItem::changeProperties(Lambda setNewProperties) {
setNewProperties();
if (oldShapeURL != getCompoundShapeURL()) {
if (!_model) {
_model = getModel();
_needsInitialSimulation = true;
if (_model) {
delete _model;
}
_model = getModel();
_needsInitialSimulation = true;
_model->setURL(getCompoundShapeURL(), QUrl(), true, true);
}
if (oldPosition != getPosition() ||
@ -61,6 +65,7 @@ int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
Model* RenderableZoneEntityItem::getModel() {
Model* model = new Model();
model->setIsWireframe(true);
model->init();
return model;
}
@ -74,9 +79,66 @@ void RenderableZoneEntityItem::initialSimulation() {
_needsInitialSimulation = false;
}
void RenderableZoneEntityItem::updateGeometry() {
if (_model && !_model->isActive() && hasCompoundShapeURL()) {
// Since we have a delayload, we need to update the geometry if it has been downloaded
_model->setURL(getCompoundShapeURL(), QUrl(), true);
}
if (_model && _model->isActive() && _needsInitialSimulation) {
initialSimulation();
}
}
void RenderableZoneEntityItem::render(RenderArgs* args) {
if (_drawZoneBoundaries) {
// TODO: Draw the zone boundaries...
switch (getShapeType()) {
case SHAPE_TYPE_COMPOUND: {
updateGeometry();
if (_model && _model->isActive()) {
PerformanceTimer perfTimer("zone->renderCompound");
glPushMatrix();
_model->renderInScene(getLocalRenderAlpha(), args);
glPopMatrix();
}
break;
}
case SHAPE_TYPE_BOX:
case SHAPE_TYPE_SPHERE: {
PerformanceTimer perfTimer("zone->renderPrimitive");
glm::vec3 position = getPosition();
glm::vec3 center = getCenter();
glm::vec3 dimensions = getDimensions();
glm::quat rotation = getRotation();
glm::vec4 DEFAULT_COLOR(1.0f, 1.0f, 1.0f, getLocalRenderAlpha());
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);
glPushMatrix(); {
glm::vec3 positionToCenter = center - position;
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
glScalef(dimensions.x, dimensions.y, dimensions.z);
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
if (getShapeType() == SHAPE_TYPE_SPHERE) {
const int SLICES = 15;
const int STACKS = 15;
deferredLightingEffect->renderWireSphere(0.5f, SLICES, STACKS, DEFAULT_COLOR);
} else {
deferredLightingEffect->renderWireCube(1.0f, DEFAULT_COLOR);
}
} glPopMatrix();
} glPopMatrix();
break;
}
default:
// Not handled
break;
}
}
}
@ -84,16 +146,9 @@ bool RenderableZoneEntityItem::contains(const glm::vec3& point) const {
if (getShapeType() != SHAPE_TYPE_COMPOUND) {
return EntityItem::contains(point);
}
if (_model && !_model->isActive() && hasCompoundShapeURL()) {
// Since we have a delayload, we need to update the geometry if it has been downloaded
_model->setURL(getCompoundShapeURL(), QUrl(), true);
}
const_cast<RenderableZoneEntityItem*>(this)->updateGeometry();
if (_model && _model->isActive() && EntityItem::contains(point)) {
if (_needsInitialSimulation) {
const_cast<RenderableZoneEntityItem*>(this)->initialSimulation();
}
return _model->convexHullContains(point);
}

View file

@ -38,6 +38,7 @@ public:
private:
Model* getModel();
void initialSimulation();
void updateGeometry();
template<typename Lambda>
void changeProperties(Lambda functor);

View file

@ -263,17 +263,15 @@ void ZoneEntityItem::debugDump() const {
ShapeType ZoneEntityItem::getShapeType() const {
// Zones are not allowed to have a SHAPE_TYPE_NONE... they are always at least a SHAPE_TYPE_BOX
if (_shapeType == SHAPE_TYPE_COMPOUND) {
return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_BOX;
return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : DEFAULT_SHAPE_TYPE;
} else {
return _shapeType == SHAPE_TYPE_NONE ? SHAPE_TYPE_BOX : _shapeType;
return _shapeType == SHAPE_TYPE_NONE ? DEFAULT_SHAPE_TYPE : _shapeType;
}
}
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
_compoundShapeURL = url;
if (!_compoundShapeURL.isEmpty()) {
updateShapeType(SHAPE_TYPE_COMPOUND);
} else if (_shapeType == SHAPE_TYPE_COMPOUND) {
if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) {
_shapeType = DEFAULT_SHAPE_TYPE;
}
}

View file

@ -44,11 +44,6 @@ public:
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
// NOTE: Apparently if you begin to return a shape type, then the physics system will prevent an avatar
// from penetrating the walls of the entity. This fact will likely be important to Clement as he works
// on better defining the shape/volume of a zone.
//virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
xColor getKeyLightColor() const { xColor color = { _keyLightColor[RED_INDEX], _keyLightColor[GREEN_INDEX], _keyLightColor[BLUE_INDEX] }; return color; }
void setKeyLightColor(const xColor& value) {
_keyLightColor[RED_INDEX] = value.red;
@ -146,7 +141,7 @@ protected:
uint16_t _stageDay;
float _stageHour;
ShapeType _shapeType = SHAPE_TYPE_NONE;
ShapeType _shapeType = DEFAULT_SHAPE_TYPE;
QString _compoundShapeURL;
BackgroundMode _backgroundMode = BACKGROUND_MODE_INHERIT;

View file

@ -31,36 +31,51 @@ typedef GLBackend::GLState::Command1<State::DepthTest> CommandDepthTest;
typedef GLBackend::GLState::Command3<State::StencilActivation, State::StencilTest, State::StencilTest> CommandStencil;
typedef GLBackend::GLState::Command1<State::BlendFunction> CommandBlend;
// The state commands to reset to default,
// WARNING depending on the order of the State::Field enum
const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = {
CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, State::DEFAULT.fillMode)),
CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, State::DEFAULT.cullMode)),
CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, State::DEFAULT.frontFaceClockwise)),
CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, State::DEFAULT.depthClipEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, State::DEFAULT.scissorEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, State::DEFAULT.multisampleEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, State::DEFAULT.antialisedLineEnable)),
const GLBackend::GLState::Commands makeResetStateCommands();
const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = makeResetStateCommands();
// Depth bias has 2 fields in State but really one call in GLBackend
CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))),
CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))),
CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, State::DEFAULT.depthTest)),
// Depth bias has 3 fields in State but really one call in GLBackend
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)),
CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, State::DEFAULT.alphaToCoverageEnable)),
CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, State::DEFAULT.sampleMask)),
CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, State::DEFAULT.blendFunction)),
CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, State::DEFAULT.colorWriteMask))
};
const GLBackend::GLState::Commands makeResetStateCommands() {
// Since State::DEFAULT is a static defined in another .cpp the initialisation order is random
// and we have a 50/50 chance that State::DEFAULT is not yet initialized.
// Since State::DEFAULT = State::Data() it is much easier to not use the actual State::DEFAULT
// but another State::Data object with a default initialization.
State::Data DEFAULT = State::Data();
CommandPointer depthBiasCommand = CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(DEFAULT.depthBias, DEFAULT.depthBiasSlopeScale)));
CommandPointer stencilCommand = CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, DEFAULT.stencilActivation, DEFAULT.stencilTestFront, DEFAULT.stencilTestBack));
// The state commands to reset to default,
// WARNING depending on the order of the State::Field enum
return {
CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, DEFAULT.fillMode)),
CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, DEFAULT.cullMode)),
CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, DEFAULT.frontFaceClockwise)),
CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, DEFAULT.depthClipEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, DEFAULT.scissorEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, DEFAULT.multisampleEnable)),
CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, DEFAULT.antialisedLineEnable)),
// Depth bias has 2 fields in State but really one call in GLBackend
CommandPointer(depthBiasCommand),
CommandPointer(depthBiasCommand),
CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, DEFAULT.depthTest)),
// Depth bias has 3 fields in State but really one call in GLBackend
CommandPointer(stencilCommand),
CommandPointer(stencilCommand),
CommandPointer(stencilCommand),
CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, DEFAULT.alphaToCoverageEnable)),
CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, DEFAULT.sampleMask)),
CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, DEFAULT.blendFunction)),
CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, DEFAULT.colorWriteMask))
};
}
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode))));

View file

@ -20,6 +20,8 @@ State::State() {
State::~State() {
}
// WARNING: GLBackend::GLState::_resetStateCommands heavily relies on the fact that State::DEFAULT = State::Data()
// Please make sure to go check makeResetStateCommands() before modifying this value
const State::Data State::DEFAULT = State::Data();
State::Signature State::evalSignature(const Data& state) {

View file

@ -167,8 +167,8 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
void OctreeRenderer::render(RenderArgs::RenderMode renderMode,
RenderArgs::RenderSide renderSide,
RenderArgs::DebugFlags renderDebugFlags) {
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, renderSide,
renderDebugFlags, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
RenderArgs args(this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(),
renderMode, renderSide, renderDebugFlags);
if (_tree) {
_tree->lockForRead();
_tree->recurseTreeWithOperation(renderOperation, &args);

View file

@ -84,6 +84,7 @@ Model::Model(QObject* parent) :
_calculatedMeshBoxesValid(false),
_calculatedMeshTrianglesValid(false),
_meshGroupsKnown(false),
_isWireframe(false),
_renderCollisionHull(false) {
// we may have been created in the network thread, but we live in the main thread
@ -100,8 +101,8 @@ Model::RenderPipelineLib Model::_renderPipelineLib;
const GLint MATERIAL_GPU_SLOT = 3;
void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::ShaderPointer& vertexShader,
gpu::ShaderPointer& pixelShader ) {
gpu::ShaderPointer& vertexShader,
gpu::ShaderPointer& pixelShader ) {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
@ -119,7 +120,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
// Backface on shadow
if (key.isShadow()) {
state->setCullMode(gpu::State::CULL_FRONT);
@ -140,7 +141,20 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
// Good to go add the brand new pipeline
auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations)));
if (!key.isWireFrame()) {
RenderKey wireframeKey(key.getRaw() | RenderKey::IS_WIREFRAME);
gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues()));
wireframeState->setFillMode(gpu::State::FILL_LINE);
// create a new RenderPipeline with the same shader side and the mirrorState
auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState));
insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations)));
}
// If not a shadow pass, create the mirror version from the same state, just change the FrontFace
if (!key.isShadow()) {
@ -152,6 +166,17 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
// create a new RenderPipeline with the same shader side and the mirrorState
auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState));
insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations)));
if (!key.isWireFrame()) {
RenderKey wireframeKey(key.getRaw() | RenderKey::IS_MIRROR | RenderKey::IS_WIREFRAME);
gpu::StatePointer wireframeState = gpu::StatePointer(new gpu::State(state->getValues()));;
wireframeState->setFillMode(gpu::State::FILL_LINE);
// create a new RenderPipeline with the same shader side and the mirrorState
auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState));
insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations)));
}
}
}
@ -808,19 +833,19 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
//renderMeshes(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, forceRenderMeshes);
int opaqueMeshPartsRendered = 0;
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, false, args, true);
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, false, args, true);
// render translucent meshes afterwards
//DependencyManager::get<TextureCache>()->setPrimaryDrawBuffers(false, true, true);
@ -834,14 +859,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
int translucentMeshPartsRendered = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, false, args, true);
{
GLenum buffers[1];
@ -855,14 +880,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, false, args, true);
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, false, args, true);
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
}
@ -1110,7 +1135,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
// if so instructed, keep the current geometry until the new one is loaded
_nextBaseGeometry = _nextGeometry = DependencyManager::get<GeometryCache>()->getGeometry(url, fallback, delayLoad);
_nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS;
if (!retainCurrent || !isActive() || _nextGeometry->isLoaded()) {
if (!retainCurrent || !isActive() || (_nextGeometry && _nextGeometry->isLoaded())) {
applyNextGeometry();
}
}
@ -1873,19 +1898,21 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
int opaqueMeshPartsRendered = 0;
// now, for each model in the scene, render the mesh portions
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, false, args);
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, true, args);
// render translucent meshes afterwards
{
@ -1898,14 +1925,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
int translucentParts = 0;
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, false, args);
{
@ -1921,14 +1948,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryTransparentFramebuffer());
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, false, args);
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, false, args);
// batch.setFramebuffer(DependencyManager::get<TextureCache>()->getPrimaryOpaqueFramebuffer());
}
@ -2017,7 +2044,7 @@ bool Model::renderInScene(float alpha, RenderArgs* args) {
updateGeometry();
simulate(0.0, true);
}
renderSetup(args);
_modelsInScene.push_back(this);
return true;
@ -2057,8 +2084,8 @@ void Model::segregateMeshGroups() {
if (wantDebug) {
qCDebug(renderutils) << "materialID:" << materialID << "parts:" << mesh.parts.size();
}
RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned);
RenderKey key(translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe());
// reuse or create the bucket corresponding to that key and insert the mesh as unsorted
_renderBuckets[key.getRaw()]._unsortedMeshes.insertMulti(materialID, i);
@ -2067,20 +2094,20 @@ void Model::segregateMeshGroups() {
for(auto& b : _renderBuckets) {
foreach(auto i, b.second._unsortedMeshes) {
b.second._meshes.append(i);
b.second._unsortedMeshes.clear();
}
b.second._unsortedMeshes.clear();
}
_meshGroupsKnown = true;
}
}
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) {
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) {
PROFILE_RANGE(__FUNCTION__);
// depending on which parameters we were called with, pick the correct mesh group to render
QVector<int>* whichList = NULL;
RenderKey key(translucent, hasLightmap, hasTangents, hasSpecular, isSkinned);
RenderKey key(translucent, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
auto bucket = _renderBuckets.find(key.getRaw());
if (bucket != _renderBuckets.end()) {
@ -2091,10 +2118,10 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
}
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args,
Locations*& locations) {
RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
auto pipeline = _renderPipelineLib.find(key.getRaw());
if (pipeline == _renderPipelineLib.end()) {
qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw();
@ -2119,7 +2146,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
}
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args) {
PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0;
@ -2128,12 +2155,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
Locations* locations = nullptr;
foreach(Model* model, _modelsInScene) {
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
if (whichList) {
QVector<int>& list = *whichList;
if (list.size() > 0) {
if (pickProgramsNeeded) {
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations);
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe, args, locations);
pickProgramsNeeded = false;
}
@ -2147,14 +2174,14 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
}
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args,
bool forceRenderSomeMeshes) {
PROFILE_RANGE(__FUNCTION__);
int meshPartsRendered = 0;
//Pick the mesh list with the requested render flags
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe);
if (!whichList) {
return 0;
}
@ -2166,9 +2193,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
}
Locations* locations = nullptr;
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned,
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe,
args, locations);
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold,
args, locations, forceRenderSomeMeshes);
return meshPartsRendered;

View file

@ -116,6 +116,9 @@ public:
Q_INVOKABLE void setCollisionModelURL(const QUrl& url);
const QUrl& getCollisionURL() const { return _collisionUrl; }
void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; }
bool isWireframe() const { return _isWireframe; }
/// Sets the distance parameter used for LOD computations.
void setLODDistance(float distance) { _lodDistance = distance; }
@ -350,6 +353,7 @@ private:
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
bool _meshGroupsKnown;
bool _isWireframe;
// debug rendering support
@ -366,23 +370,23 @@ private:
// helper functions used by render() or renderInScene()
void renderSetup(RenderArgs* args);
bool renderCore(float alpha, RenderArgs::RenderMode mode, RenderArgs* args);
int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL,
int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args = NULL,
bool forceRenderMeshes = false);
void setupBatchTransform(gpu::Batch& batch, RenderArgs* args);
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe);
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
RenderArgs* args, Locations* locations,
bool forceRenderSomeMeshes = false);
static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args,
Locations*& locations);
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold,
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args);
static AbstractViewStateInterface* _viewState;
@ -400,7 +404,8 @@ private:
IS_DEPTH_ONLY_FLAG,
IS_SHADOW_FLAG,
IS_MIRROR_FLAG, //THis means that the mesh is rendered mirrored, not the same as "Rear view mirror"
IS_WIREFRAME_FLAG,
NUM_FLAGS,
};
@ -415,7 +420,7 @@ private:
IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG),
IS_SHADOW = (1 << IS_SHADOW_FLAG),
IS_MIRROR = (1 << IS_MIRROR_FLAG),
IS_WIREFRAME = (1 << IS_WIREFRAME_FLAG),
};
typedef unsigned short Flags;
@ -433,6 +438,7 @@ private:
bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); }
bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing
bool isMirror() const { return isFlag(IS_MIRROR); }
bool isWireFrame() const { return isFlag(IS_WIREFRAME); }
Flags _flags = 0;
short _spare = 0;
@ -442,22 +448,24 @@ private:
RenderKey(
bool translucent, bool hasLightmap,
bool hasTangents, bool hasSpecular, bool isSkinned) :
bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) :
RenderKey( (translucent ? IS_TRANSLUCENT : 0)
| (hasLightmap ? HAS_LIGHTMAP : 0)
| (hasTangents ? HAS_TANGENTS : 0)
| (hasSpecular ? HAS_SPECULAR : 0)
| (isSkinned ? IS_SKINNED : 0)
| (isWireframe ? IS_WIREFRAME : 0)
) {}
RenderKey(RenderArgs::RenderMode mode,
bool translucent, float alphaThreshold, bool hasLightmap,
bool hasTangents, bool hasSpecular, bool isSkinned) :
bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) :
RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0)
| (hasLightmap && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly
| (hasTangents && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0)
| (hasSpecular && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0)
| (isSkinned ? IS_SKINNED : 0)
| (isWireframe ? IS_WIREFRAME : 0)
| ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0)
| ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_SHADOW : 0)
| ((mode == RenderArgs::MIRROR_RENDER_MODE) ? IS_MIRROR :0)

View file

@ -22,10 +22,60 @@ public:
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
enum DebugFlags {
RENDER_DEBUG_NONE=0,
RENDER_DEBUG_HULLS=1,
RENDER_DEBUG_SIMULATION_OWNERSHIP=2
RENDER_DEBUG_NONE = 0,
RENDER_DEBUG_HULLS = 1,
RENDER_DEBUG_SIMULATION_OWNERSHIP = 2,
};
RenderArgs(OctreeRenderer* renderer = nullptr,
ViewFrustum* viewFrustum = nullptr,
float sizeScale = 1.0f,
int boundaryLevelAdjust = 0,
RenderMode renderMode = DEFAULT_RENDER_MODE,
RenderSide renderSide = MONO,
DebugFlags debugFlags = RENDER_DEBUG_NONE,
int elementsTouched = 0,
int itemsRendered = 0,
int itemsOutOfView = 0,
int itemsTooSmall = 0,
int meshesConsidered = 0,
int meshesRendered = 0,
int meshesOutOfView = 0,
int meshesTooSmall = 0,
int materialSwitches = 0,
int trianglesRendered = 0,
int quadsRendered = 0,
int translucentMeshPartsRendered = 0,
int opaqueMeshPartsRendered = 0) :
_renderer(renderer),
_viewFrustum(viewFrustum),
_sizeScale(sizeScale),
_boundaryLevelAdjust(boundaryLevelAdjust),
_renderMode(renderMode),
_renderSide(renderSide),
_debugFlags(debugFlags),
_elementsTouched(elementsTouched),
_itemsRendered(itemsRendered),
_itemsOutOfView(itemsOutOfView),
_itemsTooSmall(itemsTooSmall),
_meshesConsidered(meshesConsidered),
_meshesRendered(meshesRendered),
_meshesOutOfView(meshesOutOfView),
_meshesTooSmall(meshesTooSmall),
_materialSwitches(materialSwitches),
_trianglesRendered(trianglesRendered),
_quadsRendered(quadsRendered),
_translucentMeshPartsRendered(translucentMeshPartsRendered),
_opaqueMeshPartsRendered(opaqueMeshPartsRendered) {
}
OctreeRenderer* _renderer;
ViewFrustum* _viewFrustum;