This commit is contained in:
Sam Gateau 2015-05-07 11:35:58 -07:00
commit 54c47fe3f9
32 changed files with 927 additions and 231 deletions

View file

@ -0,0 +1,60 @@
//
// zoneSkyboxExample.js
// examples
//
// Created by Brad Hefta-Gaub on 4/16/15.
// Copyright 2015 High Fidelity, Inc.
//
// This is an example script that demonstrates creating a zone using the atmosphere features
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var count = 0;
var stopAfter = 600;
var zoneEntityA = Entities.addEntity({
type: "Zone",
position: { x: 1000, y: 1000, z: 1000},
dimensions: { x: 2000, y: 2000, z: 2000 },
keyLightColor: { red: 255, green: 0, blue: 0 },
stageSunModelEnabled: false,
shapeType: "sphere",
backgroundMode: "skybox",
atmosphere: {
center: { x: 1000, y: 0, z: 1000},
innerRadius: 1000.0,
outerRadius: 1025.0,
rayleighScattering: 0.0025,
mieScattering: 0.0010,
scatteringWavelengths: { x: 0.650, y: 0.570, z: 0.475 },
hasStars: false
},
skybox: {
color: { red: 255, green: 0, blue: 255 },
url: ""
},
stageLatitude: 37.777,
stageLongitude: 122.407,
stageAltitude: 0.03,
stageDay: 60,
stageHour: 0,
stageSunModelEnabled: true
});
var props = Entities.getEntityProperties(zoneEntityA);
print(JSON.stringify(props));
// register the call back so it fires before each data send
Script.update.connect(function(deltaTime) {
// stop it...
if (count >= stopAfter) {
print("calling Script.stop()");
Script.stop();
}
count++;
});

View file

@ -0,0 +1,140 @@
//
// planky.js
// examples
//
// Created by Thijs Wenker on 5/2/14.
// Copyright 2015 High Fidelity, Inc.
//
// Pull blocks off the bottom and put them on the top using the grab.js script.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
const NUM_LAYERS = 16;
const BASE_DIMENSION = { x: 7, y: 2, z: 7 };
const BLOCKS_PER_LAYER = 3;
const BLOCK_SIZE = {x: 0.2, y: 0.1, z: 0.8};
const BLOCK_SPACING = BLOCK_SIZE.x / 3;
const GRAVITY = {x: 0, y: -2.8, z: 0};
const DENSITY = 2000;
const DAMPING_FACTOR = 0.98;
const ANGULAR_DAMPING_FACTOR = 0.8;
const SPAWN_DISTANCE = 3;
const BLOCK_YAW_OFFSET = 45;
const BUTTON_DIMENSIONS = {width: 49, height: 49};
var windowWidth = Window.innerWidth;
var size;
var pieces = [];
var ground = false;
var layerRotated = false;
function grabLowestJointY() {
var jointNames = MyAvatar.getJointNames();
var floorY = MyAvatar.position.y;
for (var jointName in jointNames) {
if (MyAvatar.getJointPosition(jointNames[jointName]).y < floorY) {
floorY = MyAvatar.getJointPosition(jointNames[jointName]).y;
}
}
return floorY;
}
function getButtonPosX() {
return windowWidth - ((BUTTON_DIMENSIONS.width / 2) + BUTTON_DIMENSIONS.width);
}
var button = Overlays.addOverlay('image', {
x: getButtonPosX(),
y: 10,
width: BUTTON_DIMENSIONS.width,
height: BUTTON_DIMENSIONS.height,
imageURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/planky_button.svg',
alpha: 1
});
function resetBlocks() {
pieces.forEach(function(piece) {
Entities.deleteEntity(piece);
});
pieces = [];
var avatarRot = Quat.fromPitchYawRollDegrees(0.0, MyAvatar.bodyYaw, 0.0);
basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(SPAWN_DISTANCE, Quat.getFront(avatarRot)));
basePosition.y = grabLowestJointY() - (BASE_DIMENSION.y / 2);
if (!ground) {
ground = Entities.addEntity({
type: 'Model',
modelURL: HIFI_PUBLIC_BUCKET + 'eric/models/woodFloor.fbx',
dimensions: BASE_DIMENSION,
position: basePosition,
rotation: avatarRot,
shapeType: 'box'
});
} else {
Entities.editEntity(ground, {position: basePosition, rotation: avatarRot});
}
var offsetRot = Quat.multiply(avatarRot, Quat.fromPitchYawRollDegrees(0.0, BLOCK_YAW_OFFSET, 0.0));
basePosition.y += (BASE_DIMENSION.y / 2);
for (var layerIndex = 0; layerIndex < NUM_LAYERS; layerIndex++) {
var layerRotated = layerIndex % 2 === 0;
var offset = -(BLOCK_SPACING);
var layerRotation = Quat.fromPitchYawRollDegrees(0, layerRotated ? 0 : 90, 0.0);
for (var blockIndex = 0; blockIndex < BLOCKS_PER_LAYER; blockIndex++) {
var blockPositionXZ = BLOCK_SIZE.x * blockIndex - (BLOCK_SIZE.x * 3 / 2 - BLOCK_SIZE.x / 2);
var localTransform = Vec3.multiplyQbyV(offsetRot, {
x: (layerRotated ? blockPositionXZ + offset: 0),
y: (BLOCK_SIZE.y / 2) + (BLOCK_SIZE.y * layerIndex),
z: (layerRotated ? 0 : blockPositionXZ + offset)
});
pieces.push(Entities.addEntity({
type: 'Model',
modelURL: HIFI_PUBLIC_BUCKET + 'marketplace/hificontent/Games/blocks/block.fbx',
shapeType: 'box',
name: 'JengaBlock' + ((layerIndex * BLOCKS_PER_LAYER) + blockIndex),
dimensions: BLOCK_SIZE,
position: {
x: basePosition.x + localTransform.x,
y: basePosition.y + localTransform.y,
z: basePosition.z + localTransform.z
},
rotation: Quat.multiply(layerRotation, offsetRot),
collisionsWillMove: true,
damping: DAMPING_FACTOR,
angularDamping: ANGULAR_DAMPING_FACTOR,
gravity: GRAVITY,
density: DENSITY
}));
offset += BLOCK_SPACING;
}
}
}
function mousePressEvent(event) {
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
if (clickedOverlay === button) {
resetBlocks();
}
}
Controller.mousePressEvent.connect(mousePressEvent);
function cleanup() {
Overlays.deleteOverlay(button);
if (ground) {
Entities.deleteEntity(ground);
}
pieces.forEach(function(piece) {
Entities.deleteEntity(piece);
});
pieces = [];
}
function onUpdate() {
}
Script.update.connect(onUpdate)
Script.scriptEnding.connect(cleanup);

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

@ -3260,6 +3260,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

@ -1173,8 +1173,10 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren
Camera *camera = Application::getInstance()->getCamera();
const glm::vec3 cameraPos = camera->getPosition();
// HACK: comment this block which possibly change the near and break the rendering 5/6/2015
// Only tweak the frustum near far if it's not shadow
if (renderMode != RenderArgs::SHADOW_RENDER_MODE) {
/* if (renderMode != RenderArgs::SHADOW_RENDER_MODE) {
// Set near clip distance according to skeleton model dimensions if first person and there is no separate head model.
if (shouldRenderHead(cameraPos, renderMode) || !getHead()->getFaceModel().getURL().isEmpty()) {
renderFrustum->setNearClip(DEFAULT_NEAR_CLIP);
@ -1184,7 +1186,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren
+ camera->getOrientation() * glm::vec3(0.0f, 0.0f, -clipDistance) - cameraPos);
renderFrustum->setNearClip(clipDistance);
}
}
}*/
// Render the body's voxels and head
RenderArgs::RenderMode modelRenderMode = renderMode;

View file

@ -190,8 +190,8 @@ void ApplicationOverlay::renderOverlay() {
Overlays& overlays = qApp->getOverlays();
_textureFov = glm::radians(_hmdUIAngularSize);
auto deviceSize = Application::getInstance()->getDeviceSize();
_textureAspectRatio = (float)deviceSize.width() / (float)deviceSize.height();
glm::vec2 deviceSize = qApp->getCanvasSize();
_textureAspectRatio = (float)deviceSize.x / (float)deviceSize.y;
//Handle fading and deactivation/activation of UI
@ -209,7 +209,7 @@ void ApplicationOverlay::renderOverlay() {
const float NEAR_CLIP = -10000;
const float FAR_CLIP = 10000;
glLoadIdentity();
glOrtho(0, deviceSize.width(), deviceSize.height(), 0, NEAR_CLIP, FAR_CLIP);
glOrtho(0, deviceSize.x, deviceSize.y, 0, NEAR_CLIP, FAR_CLIP);
glMatrixMode(GL_MODELVIEW);
@ -270,11 +270,11 @@ void ApplicationOverlay::displayOverlayTexture() {
glEnable(GL_BLEND);
}
static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(1.0f, 1.0f, 1.0f, _alpha));
});
@ -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();
@ -445,7 +445,22 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
data.setSunBrightness(sunBrightness);
_viewState->overrideEnvironmentData(data);
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
} else {
_viewState->endOverrideEnvironmentData();
if (_bestZone->getBackgroundMode() == BACKGROUND_MODE_SKYBOX) {
auto stage = scene->getSkyStage();
stage->getSkybox()->setColor(_bestZone->getSkyboxProperties().getColorVec3());
if (_bestZone->getSkyboxProperties().getURL().isEmpty()) {
stage->getSkybox()->clearCubemap();
} else {
stage->getSkybox()->clearCubemap(); // NOTE: this should be changed to do something to set the cubemap
}
stage->setBackgroundMode(model::SunSkyStage::SKY_BOX);
}
}
} else {
if (_hasPreviousZone) {
scene->setKeyLightColor(_previousKeyLightColor);
@ -460,6 +475,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode,
_hasPreviousZone = false;
}
_viewState->endOverrideEnvironmentData();
scene->getSkyStage()->setBackgroundMode(model::SunSkyStage::SKY_DOME);
}
// we must call endScene while we still have the tree locked so that no one deletes a model
@ -661,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();
@ -683,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

@ -26,13 +26,13 @@ AtmospherePropertyGroup::AtmospherePropertyGroup() {
}
void AtmospherePropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, Center, center);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, InnerRadius, innerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, OuterRadius, outerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, MieScattering, mieScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, RayleighScattering, rayleighScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, ScatteringWavelengths, scatteringWavelengths);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, HasStars, hasStars);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, atmosphere, Center, center);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, InnerRadius, innerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, OuterRadius, outerRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, MieScattering, mieScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, RayleighScattering, rayleighScattering);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(Atmosphere, atmosphere, ScatteringWavelengths, scatteringWavelengths);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Atmosphere, atmosphere, HasStars, hasStars);
}
void AtmospherePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {

View file

@ -28,6 +28,7 @@
#include "ZoneEntityItem.h"
AtmospherePropertyGroup EntityItemProperties::_staticAtmosphere;
SkyboxPropertyGroup EntityItemProperties::_staticSkybox;
EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1);
@ -237,7 +238,7 @@ void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) {
}
}
const char* backgroundModeNames[] = {"inherit", "atmosphere", "texture" };
const char* backgroundModeNames[] = {"inherit", "atmosphere", "skybox" };
QHash<QString, BackgroundMode> stringToBackgroundModeLookup;
@ -248,7 +249,7 @@ void addBackgroundMode(BackgroundMode type) {
void buildStringToBackgroundModeLookup() {
addBackgroundMode(BACKGROUND_MODE_INHERIT);
addBackgroundMode(BACKGROUND_MODE_ATMOSPHERE);
addBackgroundMode(BACKGROUND_MODE_TEXTURE);
addBackgroundMode(BACKGROUND_MODE_SKYBOX);
}
QString EntityItemProperties::getBackgroundModeAsString() const {
@ -337,6 +338,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_MODE, backgroundMode);
changedProperties += _atmosphere.getChangedProperties();
changedProperties += _skybox.getChangedProperties();
return changedProperties;
}
@ -455,6 +457,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
}
_atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
_skybox.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
return properties;
}
@ -526,6 +529,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(stageHour, setStageHour);
COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(backgroundMode, BackgroundMode);
_atmosphere.copyFromScriptValue(object, _defaultSettings);
_skybox.copyFromScriptValue(object, _defaultSettings);
_lastEdited = usecTimestampNow();
}
@ -735,6 +739,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
_staticAtmosphere.setProperties(properties);
_staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
_staticSkybox.setProperties(properties);
_staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
}
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID());
@ -986,6 +993,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
properties.getAtmosphere().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
}
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID);
@ -1090,6 +1098,7 @@ void EntityItemProperties::markAllChanged() {
_backgroundModeChanged = true;
_atmosphere.markAllChanged();
_skybox.markAllChanged();
}

View file

@ -30,6 +30,7 @@
#include <ShapeInfo.h>
#include "AtmospherePropertyGroup.h"
#include "SkyboxPropertyGroup.h"
#include "EntityItemID.h"
#include "EntityItemPropertiesMacros.h"
#include "EntityTypes.h"
@ -138,8 +139,9 @@ public:
DEFINE_PROPERTY(PROP_STAGE_DAY, StageDay, stageDay, quint16);
DEFINE_PROPERTY(PROP_STAGE_HOUR, StageHour, stageHour, float);
DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString);
DEFINE_PROPERTY_GROUP(Atmosphere, atmosphere, AtmospherePropertyGroup);
DEFINE_PROPERTY_REF_ENUM(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode);
DEFINE_PROPERTY_GROUP(Atmosphere, atmosphere, AtmospherePropertyGroup);
DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup);
static QString getBackgroundModeString(BackgroundMode mode);

View file

@ -116,6 +116,17 @@
bytesRead += sizeof(rgbColor); \
}
#define READ_ENTITY_PROPERTY_XCOLOR(P,M) \
if (propertyFlags.getHasProperty(P)) { \
if (overwriteLocalData) { \
M.red = dataAt[RED_INDEX]; \
M.green = dataAt[GREEN_INDEX]; \
M.blue = dataAt[BLUE_INDEX]; \
} \
dataAt += sizeof(rgbColor); \
bytesRead += sizeof(rgbColor); \
}
#define READ_ENTITY_PROPERTY_TO_PROPERTIES(P,T,O) \
if (propertyFlags.getHasProperty(P)) { \
T fromBuffer; \
@ -206,27 +217,40 @@
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(G,P,p) \
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_VEC3(G,g,P,p) \
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
QScriptValue groupProperties = properties.property(#G); \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue V = vec3toScriptValue(engine, _##p); \
groupProperties.setProperty(#p, V); \
properties.setProperty(#G, groupProperties); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,P,p) \
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(G,g,P,p) \
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
QScriptValue groupProperties = properties.property(#G); \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
groupProperties.setProperty(#p, _##p); \
properties.setProperty(#G, groupProperties); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_COLOR(G,g,P,p) \
if (!skipDefaults || defaultEntityProperties.get##G().get##P() != _##p) { \
QScriptValue groupProperties = properties.property(#g); \
if (!groupProperties.isValid()) { \
groupProperties = engine->newObject(); \
} \
QScriptValue colorValue = xColorToScriptValue(engine, _##p); \
groupProperties.setProperty(#p, colorValue); \
properties.setProperty(#g, groupProperties); \
}
#define COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(P) \
if (!skipDefaults || defaultEntityProperties._##P != _##P) { \
QScriptValue P = vec3toScriptValue(engine, _##P); \
@ -328,6 +352,20 @@
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_STRING(G, P, S)\
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue P = G.property(#P); \
if (P.isValid()) { \
QString newValue = P.toVariant().toString().trimmed();\
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_UUID(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
@ -428,6 +466,31 @@
} \
}
#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_COLOR(G, P, S) \
{ \
QScriptValue G = object.property(#G); \
if (G.isValid()) { \
QScriptValue P = G.property(#P); \
if (P.isValid()) { \
QScriptValue r = P.property("red"); \
QScriptValue g = P.property("green"); \
QScriptValue b = P.property("blue"); \
if (r.isValid() && g.isValid() && b.isValid()) {\
xColor newColor; \
newColor.red = r.toVariant().toInt(); \
newColor.green = g.toVariant().toInt(); \
newColor.blue = b.toVariant().toInt(); \
if (_defaultSettings || \
(newColor.red != _color.red || \
newColor.green != _color.green || \
newColor.blue != _color.blue)) { \
S(newColor); \
} \
} \
} \
} \
}
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \

View file

@ -144,6 +144,8 @@ enum EntityPropertyList {
PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_LOCAL_GRAVITY,
PROP_ATMOSPHERE_HAS_STARS = PROP_PARTICLE_RADIUS,
PROP_BACKGROUND_MODE = PROP_MODEL_URL,
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
};
@ -158,7 +160,7 @@ extern EntityPropertyList PROP_LAST_ITEM;
enum BackgroundMode {
BACKGROUND_MODE_INHERIT,
BACKGROUND_MODE_ATMOSPHERE,
BACKGROUND_MODE_TEXTURE,
BACKGROUND_MODE_SKYBOX,
};

View file

@ -0,0 +1,130 @@
//
// SkyboxPropertyGroup.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 <OctreePacketData.h>
#include "SkyboxPropertyGroup.h"
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
SkyboxPropertyGroup::SkyboxPropertyGroup() {
_color.red = _color.green = _color.blue = 0;
_url = QString();
}
void SkyboxPropertyGroup::copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_COLOR(Skybox, skybox, Color, color);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(Skybox, skybox, URL, url);
}
void SkyboxPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_COLOR(skybox, color, setColor);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_STRING(skybox, url, setURL);
}
void SkyboxPropertyGroup::debugDump() const {
qDebug() << " SkyboxPropertyGroup: ---------------------------------------------";
qDebug() << " Color:" << getColor() << " has changed:" << colorChanged();
qDebug() << " URL:" << getURL() << " has changed:" << urlChanged();
}
bool SkyboxPropertyGroup::appentToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, appendColor, getColor());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, appendValue, getURL());
return true;
}
bool SkyboxPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {
int bytesRead = 0;
bool overwriteLocalData = true;
READ_ENTITY_PROPERTY_XCOLOR(PROP_SKYBOX_COLOR, _color);
READ_ENTITY_PROPERTY_STRING(PROP_SKYBOX_URL, setURL);
processedBytes += bytesRead;
return true;
}
void SkyboxPropertyGroup::markAllChanged() {
_colorChanged = true;
_urlChanged = true;
}
EntityPropertyFlags SkyboxPropertyGroup::getChangedProperties() const {
EntityPropertyFlags changedProperties;
CHECK_PROPERTY_CHANGE(PROP_SKYBOX_COLOR, color);
CHECK_PROPERTY_CHANGE(PROP_SKYBOX_URL, url);
return changedProperties;
}
void SkyboxPropertyGroup::getProperties(EntityItemProperties& properties) const {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Skybox, Color, getColor);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Skybox, URL, getURL);
}
bool SkyboxPropertyGroup::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Skybox, Color, color, setColor);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Skybox, URL, url, setURL);
return somethingChanged;
}
EntityPropertyFlags SkyboxPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties;
requestedProperties += PROP_SKYBOX_COLOR;
requestedProperties += PROP_SKYBOX_URL;
return requestedProperties;
}
void SkyboxPropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_COLOR, appendColor, getColor());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_URL, appendValue, getURL());
}
int SkyboxPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY_XCOLOR(PROP_SKYBOX_COLOR, _color);
READ_ENTITY_PROPERTY_STRING(PROP_SKYBOX_URL, setURL);
return bytesRead;
}

View file

@ -0,0 +1,85 @@
//
// SkyboxPropertyGroup.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_SkyboxPropertyGroup_h
#define hifi_SkyboxPropertyGroup_h
#include <QtScript/QScriptEngine>
#include "PropertyGroup.h"
#include "EntityItemPropertiesMacros.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
#include <stdint.h>
#include <glm/glm.hpp>
class SkyboxPropertyGroup : public PropertyGroup {
public:
SkyboxPropertyGroup();
virtual ~SkyboxPropertyGroup() {}
// EntityItemProperty related helpers
virtual void copyToScriptValue(QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const;
virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings);
virtual void debugDump() const;
virtual bool appentToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes);
virtual void markAllChanged();
virtual EntityPropertyFlags getChangedProperties() const;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties);
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
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);
glm::vec3 getColorVec3() const {
const quint8 MAX_COLOR = 255;
glm::vec3 color = { (float)_color.red / (float)MAX_COLOR,
(float)_color.green / (float)MAX_COLOR,
(float)_color.blue / (float)MAX_COLOR };
return color;
}
DEFINE_PROPERTY_REF(PROP_SKYBOX_COLOR, Color, color, xColor);
DEFINE_PROPERTY_REF(PROP_SKYBOX_URL, URL, url, QString);
};
#endif // hifi_SkyboxPropertyGroup_h

View file

@ -71,13 +71,13 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte
EnvironmentData ZoneEntityItem::getEnvironmentData() const {
EnvironmentData result;
result.setAtmosphereCenter(_atmospherePropeties.getCenter());
result.setAtmosphereInnerRadius(_atmospherePropeties.getInnerRadius());
result.setAtmosphereOuterRadius(_atmospherePropeties.getOuterRadius());
result.setRayleighScattering(_atmospherePropeties.getRayleighScattering());
result.setMieScattering(_atmospherePropeties.getMieScattering());
result.setScatteringWavelengths(_atmospherePropeties.getScatteringWavelengths());
result.setHasStars(_atmospherePropeties.getHasStars());
result.setAtmosphereCenter(_atmosphereProperties.getCenter());
result.setAtmosphereInnerRadius(_atmosphereProperties.getInnerRadius());
result.setAtmosphereOuterRadius(_atmosphereProperties.getOuterRadius());
result.setRayleighScattering(_atmosphereProperties.getRayleighScattering());
result.setMieScattering(_atmosphereProperties.getMieScattering());
result.setScatteringWavelengths(_atmosphereProperties.getScatteringWavelengths());
result.setHasStars(_atmosphereProperties.getHasStars());
// NOTE: The sunLocation and SunBrightness will be overwritten in the EntityTreeRenderer to use the
// keyLight details from the scene interface
@ -105,7 +105,8 @@ EntityItemProperties ZoneEntityItem::getProperties() const {
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundMode, getBackgroundMode);
_atmospherePropeties.getProperties(properties);
_atmosphereProperties.getProperties(properties);
_skyboxProperties.getProperties(properties);
return properties;
}
@ -128,9 +129,10 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundMode, setBackgroundMode);
bool somethingChangedInAtmosphere = _atmospherePropeties.setProperties(properties);
bool somethingChangedInAtmosphere = _atmosphereProperties.setProperties(properties);
bool somethingChangedInSkybox = _skyboxProperties.setProperties(properties);
somethingChanged = somethingChanged || somethingChangedInAtmosphere;
somethingChanged = somethingChanged || somethingChangedInAtmosphere || somethingChangedInSkybox;
if (somethingChanged) {
bool wantDebug = false;
@ -165,8 +167,17 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
READ_ENTITY_PROPERTY_SETTER(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
bytesRead += _atmospherePropeties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
int bytesFromAtmosphere = _atmosphereProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
bytesRead += bytesFromAtmosphere;
dataAt += bytesFromAtmosphere;
int bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData);
bytesRead += bytesFromSkybox;
dataAt += bytesFromSkybox;
return bytesRead;
}
@ -189,7 +200,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_SHAPE_TYPE;
requestedProperties += PROP_COMPOUND_SHAPE_URL;
requestedProperties += PROP_BACKGROUND_MODE;
requestedProperties += _atmospherePropeties.getEntityProperties(params);
requestedProperties += _atmosphereProperties.getEntityProperties(params);
requestedProperties += _skyboxProperties.getEntityProperties(params);
return requestedProperties;
}
@ -218,7 +230,10 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, appendValue, (uint32_t)getBackgroundMode()); // could this be a uint16??
_atmospherePropeties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
_atmosphereProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
}
@ -241,23 +256,22 @@ void ZoneEntityItem::debugDump() const {
qCDebug(entities) << " _stageHour:" << _stageHour;
qCDebug(entities) << " _backgroundMode:" << EntityItemProperties::getBackgroundModeString(_backgroundMode);
_atmospherePropeties.debugDump();
_atmosphereProperties.debugDump();
_skyboxProperties.debugDump();
}
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;
@ -110,6 +105,8 @@ public:
BackgroundMode getBackgroundMode() const { return _backgroundMode; }
EnvironmentData getEnvironmentData() const;
const AtmospherePropertyGroup& getAtmosphereProperties() const { return _atmosphereProperties; }
const SkyboxPropertyGroup& getSkyboxProperties() const { return _skyboxProperties; }
virtual bool supportsDetailedRayIntersection() const { return true; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
@ -144,11 +141,12 @@ protected:
uint16_t _stageDay;
float _stageHour;
ShapeType _shapeType = SHAPE_TYPE_NONE;
ShapeType _shapeType = DEFAULT_SHAPE_TYPE;
QString _compoundShapeURL;
BackgroundMode _backgroundMode = BACKGROUND_MODE_INHERIT;
AtmospherePropertyGroup _atmospherePropeties;
AtmospherePropertyGroup _atmosphereProperties;
SkyboxPropertyGroup _skyboxProperties;
static bool _drawZoneBoundaries;
static bool _zonesArePickable;

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

@ -41,10 +41,13 @@ void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
_cubemap = cubemap;
}
void Skybox::clearCubemap() {
_cubemap.reset();
}
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
static gpu::PipelinePointer thePipeline;
static gpu::BufferPointer theBuffer;
static gpu::Stream::FormatPointer theFormat;

View file

@ -32,6 +32,7 @@ public:
void setCubemap(const gpu::TexturePointer& cubemap);
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
void clearCubemap();
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);

View file

@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) {
return 1;
case PacketTypeEntityAddOrEdit:
case PacketTypeEntityData:
return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE;
return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX;
case PacketTypeEntityErase:
return 2;
case PacketTypeAudioStreamStats:

View file

@ -141,5 +141,6 @@ const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18;
const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20;
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21;
#endif // hifi_PacketHeaders_h

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

@ -30,7 +30,8 @@
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
const float DEFAULT_NEAR_CLIP = 0.08f;
//const float DEFAULT_NEAR_CLIP = 0.08f;
const float DEFAULT_NEAR_CLIP = 0.25f;
const float DEFAULT_FAR_CLIP = (float)TREE_SCALE;
class ViewFrustum {

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

@ -294,7 +294,7 @@ GLuint TextureCache::getShadowDepthTextureID() {
/// Returns a texture version of an image file
gpu::TexturePointer TextureCache::getImageTexture(const QString & path) {
QImage image(path);
QImage image = QImage(path).mirrored(false, true);
gpu::Element formatGPU = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB);
gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, gpu::RGB);
if (image.hasAlphaChannel()) {

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;

View file

@ -23,11 +23,19 @@
const int BYTES_PER_COLOR = 3;
const int BYTES_PER_FLAGS = 1;
typedef unsigned char rgbColor[BYTES_PER_COLOR];
typedef unsigned char colorPart;
typedef unsigned char nodeColor[BYTES_PER_COLOR + BYTES_PER_FLAGS];
typedef unsigned char rgbColor[BYTES_PER_COLOR];
inline QDebug& operator<<(QDebug& dbg, const rgbColor& c) {
dbg.nospace() << "{type='rgbColor'"
", red=" << c[0] <<
", green=" << c[1] <<
", blue=" << c[2] <<
"}";
return dbg;
}
struct xColor {
unsigned char red;
unsigned char green;