From fdc231424bfede5508deccc886198c21fdb5c96c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Oct 2014 09:50:06 -0700 Subject: [PATCH 01/29] Update entitySelectionTools to use camera position/orientation instead of avatar --- examples/libraries/entitySelectionTool.js | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 75ea95a74a..399be0e676 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -22,8 +22,8 @@ SelectionDisplay = (function () { var mode = "UNKNOWN"; var overlayNames = new Array(); - var lastAvatarPosition = MyAvatar.position; - var lastAvatarOrientation = MyAvatar.orientation; + var lastCameraPosition = Camera.getPosition(); + var lastCameraOrientation = Camera.getOrientation(); var lastPlaneIntersection; var currentSelection = { id: -1, isKnownID: false }; @@ -452,15 +452,15 @@ SelectionDisplay = (function () { currentSelection = entityID; entitySelected = true; - lastAvatarPosition = MyAvatar.position; - lastAvatarOrientation = MyAvatar.orientation; + lastCameraPosition = Camera.getPosition(); + lastCameraOrientation = Camera.getOrientation(); if (event !== false) { selectedEntityProperties = properties; selectedEntityPropertiesOriginalPosition = properties.position; selectedEntityPropertiesOriginalDimensions = properties.dimensions; pickRay = Camera.computePickRay(event.x, event.y); - lastPlaneIntersection = rayPlaneIntersection(pickRay, properties.position, Quat.getFront(lastAvatarOrientation)); + lastPlaneIntersection = rayPlaneIntersection(pickRay, properties.position, Quat.getFront(lastCameraOrientation)); var wantDebug = false; if (wantDebug) { @@ -838,7 +838,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -877,7 +877,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -914,7 +914,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -967,7 +967,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1017,7 +1017,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1066,7 +1066,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1115,7 +1115,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1164,7 +1164,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1213,7 +1213,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1280,7 +1280,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1347,7 +1347,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1414,7 +1414,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1481,7 +1481,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1548,7 +1548,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1615,7 +1615,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1682,7 +1682,7 @@ SelectionDisplay = (function () { // translate mode left/right based on view toward entity var newIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); @@ -1981,7 +1981,7 @@ SelectionDisplay = (function () { that.checkMove = function() { if (currentSelection.isKnownID && - (!Vec3.equal(MyAvatar.position, lastAvatarPosition) || !Quat.equal(MyAvatar.orientation, lastAvatarOrientation))){ + (!Vec3.equal(Camera.getPosition(), lastCameraPosition) || !Quat.equal(Camera.getOrientation(), lastCameraOrientation))){ that.select(currentSelection, false); } }; @@ -2277,7 +2277,7 @@ SelectionDisplay = (function () { if (somethingClicked) { pickRay = Camera.computePickRay(event.x, event.y); lastPlaneIntersection = rayPlaneIntersection(pickRay, selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastAvatarOrientation)); + Quat.getFront(lastCameraOrientation)); if (wantDebug) { print("mousePressEvent()...... " + overlayNames[result.overlayID]); Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); From 0326ec2aa9959b729d17977848df627d41036bc2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Oct 2014 10:44:26 -0700 Subject: [PATCH 02/29] Fix right/left stretch entity tool --- examples/libraries/entitySelectionTool.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 399be0e676..5e344c9c8d 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1120,16 +1120,16 @@ SelectionDisplay = (function () { var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; + var oldRIGHT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; var newRIGHT = oldRIGHT + vector.x; - var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: 0 , z: 0 }; + var changeInDimensions = { x: (oldRIGHT - newRIGHT), y: 0 , z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); if (newDimensions.x < MINIMUM_DIMENSION) { newDimensions.x = MINIMUM_DIMENSION; } - var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, y: 0, z: 0 }; + var changeInPosition = { x: (oldRIGHT - newRIGHT) * -0.5, y: 0, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); var wantDebug = false; if (wantDebug) { @@ -1169,18 +1169,18 @@ SelectionDisplay = (function () { var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; + var oldLEFT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; var newLEFT = oldLEFT + vector.x; - var changeInDimensions = { x: (oldLEFT - newLEFT), y: 0, z: 0 }; + var changeInDimensions = { x: (newLEFT - oldLEFT), y: 0, z: 0 }; var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); if (newDimensions.x < MINIMUM_DIMENSION) { newDimensions.x = MINIMUM_DIMENSION; } - var changeInPosition = { x: (oldLEFT - newLEFT) * -0.5, y: 0, z: 0 }; + var changeInPosition = { x: (newLEFT - oldLEFT) * 0.5, y: 0, z: 0 }; var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; + var wantDebug = true; if (wantDebug) { print("stretchLEFT... "); Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); From 5139914ba9690316aeb2eab67c3cc966a8f27487 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 16 Oct 2014 10:50:42 -0700 Subject: [PATCH 03/29] Fix entity tools focus not always using latest entity position --- examples/newEditEntities.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 756fbdb645..8e1ccab67e 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -648,7 +648,9 @@ Controller.keyReleaseEvent.connect(function (event) { handeMenuEvent("Delete"); } else if (event.text == "f") { if (entitySelected) { - entityCameraTool.focus(selectedEntityProperties); + // Get latest properties + var properties = Entities.getEntityProperties(selectedEntityID); + entityCameraTool.focus(properties); } } }); From f09133f413624c0ee192a3943ef460d764acb711 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 16 Oct 2014 17:23:31 -0700 Subject: [PATCH 04/29] Adding the Batch class to GPU --- interface/src/gpu/Batch.cpp | 65 +++++++++++++++++++++++++ interface/src/gpu/Batch.h | 94 +++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 interface/src/gpu/Batch.cpp create mode 100644 interface/src/gpu/Batch.h diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp new file mode 100644 index 0000000000..a364a678fc --- /dev/null +++ b/interface/src/gpu/Batch.cpp @@ -0,0 +1,65 @@ +// +// Batch.cpp +// interface/src/gpu +// +// Created by Sam Gateau on 10/14/2014. +// Copyright 2014 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 "Batch.h" + +#include + +using namespace gpu; + +Batch::Batch() : + _commands(), + _params(), + _resources(){ +} + +Batch::~Batch() { +} + +void Batch::clear() { + _commands.clear(); + _params.clear(); + _resources.clear(); +} + +void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { + _commands.push(COMMAND_DRAW); + _params.push(startVertex); + _params.push(nbVertices); + _params.push(primitiveType); +} + +void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) { + _commands.push(COMMAND_DRAW_INDEXED); + _params.push(startIndex); + _params.push(nbIndices); + _params.push(primitiveType); +} + +void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { + _commands.push(COMMAND_DRAW_INSTANCED); + _params.push(startInstance); + _params.push(startVertex); + _params.push(nbVertices); + _params.push(primitiveType); + _params.push(nbInstances); +} + +void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { + _commands.push(COMMAND_DRAW_INDEXED_INSTANCED); + _params.push(startInstance); + _params.push(startIndex); + _params.push(nbIndices); + _params.push(primitiveType); + _params.push(nbInstances); +} + + + diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h new file mode 100644 index 0000000000..43888e517b --- /dev/null +++ b/interface/src/gpu/Batch.h @@ -0,0 +1,94 @@ +// +// Batch.h +// interface/src/gpu +// +// Created by Sam Gateau on 10/14/2014. +// Copyright 2014 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_gpu_Batch_h +#define hifi_gpu_Batch_h + +#include +#include "InterfaceConfig.h" + +namespace gpu { + +class Buffer; +typedef int Stamp; + +// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience +namespace backend { + +}; + +enum Primitive { + PRIMITIVE_POINTS = 0, + PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP, + PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_QUADS, +}; + +class Batch { +public: + + Batch(); + Batch(const Batch& batch); + ~Batch(); + + void clear(); + + void draw( Primitive primitiveType, int nbVertices, int startVertex = 0); + void drawIndexed( Primitive primitiveType, int nbIndices, int startIndex = 0 ); + void drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); + void drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + + void glBindBuffer( GLenum +protected: + + enum Command { + COMMAND_DRAW = 0, + COMMAND_DRAW_INDEXED, + COMMAND_DRAW_INSTANCED, + COMMAND_DRAW_INDEXED_INSTANCED, + + COMMAND_SET_PIPE_STATE, + COMMAND_SET_VIEWPORT, + COMMAND_SET_FRAMEBUFFER, + COMMAND_SET_RESOURCE, + COMMAND_SET_VERTEX_STREAM, + COMMAND_SET_INDEX_STREAM, + + COMMAND_GL_SET_UNIFORM, + + }; + typedef std::vector Commands; + + class Param { + public: + union { + uint32 _uint; + char _chars[4]; + }; + Param( uint32 val ): _uint(val) {} + }; + typedef std::vector Params; + + class ResourceCache { + public: + Resource* _resource; + }; + typedef std::vector Resources; + + Commands _commands; + Params _params; + Resources _resources; +}; + +}; + +#endif From a8c3b18e7866902d53577f28b928f20f7625c4d6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 16 Oct 2014 17:29:40 -0700 Subject: [PATCH 05/29] Adding the Batch class to GPU and fixing the compilation issues --- interface/src/gpu/Batch.cpp | 66 ++++++++++++++++++------------------- interface/src/gpu/Batch.h | 6 +++- 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index a364a678fc..f21ddb3fbc 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -29,37 +29,37 @@ void Batch::clear() { _resources.clear(); } -void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { - _commands.push(COMMAND_DRAW); - _params.push(startVertex); - _params.push(nbVertices); - _params.push(primitiveType); -} - -void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) { - _commands.push(COMMAND_DRAW_INDEXED); - _params.push(startIndex); - _params.push(nbIndices); - _params.push(primitiveType); -} - -void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { - _commands.push(COMMAND_DRAW_INSTANCED); - _params.push(startInstance); - _params.push(startVertex); - _params.push(nbVertices); - _params.push(primitiveType); - _params.push(nbInstances); -} - -void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { - _commands.push(COMMAND_DRAW_INDEXED_INSTANCED); - _params.push(startInstance); - _params.push(startIndex); - _params.push(nbIndices); - _params.push(primitiveType); - _params.push(nbInstances); -} - - +void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { + _commands.push_back(COMMAND_DRAW); + _params.push_back(startVertex); + _params.push_back(nbVertices); + _params.push_back(primitiveType); +} + +void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) { + _commands.push_back(COMMAND_DRAW_INDEXED); + _params.push_back(startIndex); + _params.push_back(nbIndices); + _params.push_back(primitiveType); +} + +void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { + _commands.push_back(COMMAND_DRAW_INSTANCED); + _params.push_back(startInstance); + _params.push_back(startVertex); + _params.push_back(nbVertices); + _params.push_back(primitiveType); + _params.push_back(nbInstances); +} + +void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { + _commands.push_back(COMMAND_DRAW_INDEXED_INSTANCED); + _params.push_back(startInstance); + _params.push_back(startIndex); + _params.push_back(nbIndices); + _params.push_back(primitiveType); + _params.push_back(nbInstances); +} + + diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 43888e517b..51e2ce61b6 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -14,10 +14,15 @@ #include #include "InterfaceConfig.h" +#include + namespace gpu { class Buffer; +class Resource; typedef int Stamp; +typedef unsigned int uint32; +typedef int int32; // TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience namespace backend { @@ -47,7 +52,6 @@ public: void drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); void drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); - void glBindBuffer( GLenum protected: enum Command { From 0def490db7937d7b92b0b2d03e3ebd3a20a58a54 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 17 Oct 2014 18:17:44 -0700 Subject: [PATCH 06/29] startign to record all the gl commands in the Batch --- interface/src/gpu/Batch.cpp | 403 +++++++++++++++++++++++++++++++ interface/src/gpu/Batch.h | 195 +++++++++++++-- interface/src/renderer/Model.cpp | 102 ++++---- 3 files changed, 643 insertions(+), 57 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index f21ddb3fbc..43c6872072 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -12,6 +12,8 @@ #include +#define DO_IT_NOW(call, offset) int param = _params.size() - (offset); do##call(param); + using namespace gpu; Batch::Batch() : @@ -61,5 +63,406 @@ void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, i _params.push_back(nbInstances); } +// TODO: As long as we have gl calls explicitely issued from interface +// code, we need to be able to record and batch these calls. THe long +// term strategy is to get rid of any GL calls in favor of the HIFI GPU API + +void Batch::_glEnable(GLenum cap) { + _commands.push_back(COMMAND_glEnable); + _params.push_back(cap); + + DO_IT_NOW(_glEnable, 1); +} +void Batch::do_glEnable(int ¶mOffset) { + glEnable(_params[paramOffset++]._uint); +} + +void Batch::_glDisable(GLenum cap) { + _commands.push_back(COMMAND_glDisable); + _params.push_back(cap); + + DO_IT_NOW(_glDisable, 1); +} +void Batch::do_glDisable(int ¶mOffset) { + glDisable(_params[paramOffset++]._uint); +} + +void Batch::_glEnableClientState(GLenum array) { + _commands.push_back(COMMAND_glEnableClientState); + _params.push_back(array); + + DO_IT_NOW(_glEnableClientState, 1 ); +} +void Batch::do_glEnableClientState(int ¶mOffset) { + glEnableClientState(_params[paramOffset++]._uint); +} + +void Batch::_glDisableClientState(GLenum array) { + _commands.push_back(COMMAND_glDisableClientState); + _params.push_back(array); + + DO_IT_NOW(_glDisableClientState, 1); +} +void Batch::do_glDisableClientState(int ¶mOffset) { + glDisableClientState(_params[paramOffset++]._uint); +} + +void Batch::_glCullFace(GLenum mode) { + _commands.push_back(COMMAND_glCullFace); + _params.push_back(mode); + + DO_IT_NOW(_glCullFace, 1); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { + _commands.push_back(COMMAND_glAlphaFunc); + _params.push_back(ref); + _params.push_back(func); + + DO_IT_NOW(_glAlphaFunc, 1); +} +void Batch::do_glAlphaFunc(int ¶mOffset) { + glAlphaFunc(_params[paramOffset++]._uint, _params[paramOffset++]._float); +} + +void Batch::_glDepthFunc(GLenum func) { + _commands.push_back(COMMAND_glDepthFunc); + _params.push_back(func); + + DO_IT_NOW(_glDepthFunc, 1); +} +void Batch::do_glDepthFunc(int ¶mOffset) { + glDepthFunc(_params[paramOffset++]._uint); +} + +void Batch::_glDepthMask(GLboolean flag) { + _commands.push_back(COMMAND_glDepthMask); + _params.push_back(flag); + + DO_IT_NOW(_glDepthMask, 1); +} +void Batch::do_glDepthMask(int ¶mOffset) { + glDepthMask(_params[paramOffset++]._uint); +} + +void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { + _commands.push_back(COMMAND_glDepthRange); + _params.push_back(zFar); + _params.push_back(zNear); + + DO_IT_NOW(_glDepthRange, 2); +} +void Batch::do_glDepthRange(int ¶mOffset) { + glDepthRange(_params[paramOffset++]._double, _params[paramOffset++]._double); +} + +void Batch::_glBindBuffer(GLenum target, GLuint buffer) { + _commands.push_back(COMMAND_glBindBuffer); + _params.push_back(buffer); + _params.push_back(target); + + DO_IT_NOW(_glBindBuffer, 2); +} +void Batch::do_glBindBuffer(int ¶mOffset) { + glBindBuffer(_params[paramOffset++]._uint, _params[paramOffset++]._uint); +} + +void Batch::_glBindTexture(GLenum target, GLuint texture) { + _commands.push_back(COMMAND_glBindTexture); + _params.push_back(texture); + _params.push_back(target); + + DO_IT_NOW(_glBindTexture, 2); +} +void Batch::do_glBindTexture(int ¶mOffset) { + glBindTexture(_params[paramOffset++]._uint, _params[paramOffset++]._uint); +} + +void Batch::_glActiveTexture(GLenum texture) { + _commands.push_back(COMMAND_glActiveTexture); + _params.push_back(texture); + + DO_IT_NOW(_glActiveTexture, 1); +} +void Batch::do_glActiveTexture(int ¶mOffset) { + glActiveTexture(_params[paramOffset++]._uint); +} + +void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { + _commands.push_back(COMMAND_glDrawBuffers); + _params.push_back(bufs); + _params.push_back(n); + + DO_IT_NOW(_glDrawBuffers, 2); +} +void Batch::do_glDrawBuffers(int ¶mOffset) { + glDrawBuffers(_params[paramOffset++]._uint, (const GLenum*) _params[paramOffset++]._constPointer); +} + +void Batch::_glUseProgram(GLuint program) { + _commands.push_back(COMMAND_glUseProgram); + _params.push_back(program); + + DO_IT_NOW(_glUseProgram, 1); +} +void Batch::do_glUseProgram(int ¶mOffset) { + glUseProgram(_params[paramOffset++]._uint); +} + +void Batch::_glUniform1f(GLint location, GLfloat v0) { + _commands.push_back(COMMAND_glUniform1f); + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform1f, 1); +} +void Batch::do_glUniform1f(int ¶mOffset) { + glUniform1f(_params[paramOffset++]._float); +} + +void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + _commands.push_back(COMMAND_glUniformMatrix4fv); + _params.push_back(value); + _params.push_back(transpose); + _params.push_back(count); + _params.push_back(location); + + DO_IT_NOW(_glUniformMatrix4fv, 4); +} +void Batch::do_glUniformMatrix4fv(int ¶mOffset) { + glUniformMatrix4fv(_params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._constPointer); +} + +void Batch::_glMatrixMode(GLenum mode) { + _commands.push_back(COMMAND_glMatrixMode); + _params.push_back(mode); + + DO_IT_NOW(_glMatrixMode, 1); +} +void Batch::do_glMatrixMode(int ¶mOffset) { + glMatrixMode(_params[paramOffset++]._uint); +} + +void Batch::_glPushMatrix() { + _commands.push_back(COMMAND_glPushMatrix); + + DO_IT_NOW(_glPushMatrix, 0); +} +void Batch::do_glPushMatrix(int ¶mOffset) { + glPushMatrix(); +} + +void Batch::_glPopMatrix() { + _commands.push_back(COMMAND_glPopMatrix); + + DO_IT_NOW(_glPopMatrix, 0); +} +void Batch::do_glPopMatrix(int ¶mOffset) { + glPopMatrix(); +} + +void Batch::_glMultMatrixf(const GLfloat *m) { + _commands.push_back(COMMAND_glMultMatrixf); + _params.push_back(m); + + DO_IT_NOW(_glMultMatrixf, 1); +} +void Batch::do_glMultMatrixf(int ¶mOffset) { + glMultMatrixf((const GLfloat*) _params[paramOffset++]._constPointer); +} + +void Batch::_glLoadMatrixf(const GLfloat *m) { + _commands.push_back(COMMAND_glLoadMatrixf); + _params.push_back(m); + + DO_IT_NOW(_glLoadMatrixf, 1); +} +void Batch::do_glLoadMatrixf(int ¶mOffset) { + glLoadMatrixf((const GLfloat*)_params[paramOffset++]._constPointer); +} + +void Batch::_glLoadIdentity(void) { + _commands.push_back(COMMAND_glLoadIdentity); + + DO_IT_NOW(_glLoadIdentity, 0); +} +void Batch::do_glLoadIdentity(int ¶mOffset) { + glLoadIdentity(); +} + +void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + _commands.push_back(COMMAND_glRotatef); + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + _params.push_back(angle); + + DO_IT_NOW(_glRotatef, 4); +} +void Batch::do_glRotatef(int ¶mOffset) { + glRotatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); +} + +void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) { + _commands.push_back(COMMAND_glScalef); + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + + DO_IT_NOW(_glScalef, 3); +} +void Batch::do_glScalef(int ¶mOffset) { + glScalef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); +} + +void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) { + _commands.push_back(COMMAND_glTranslatef); + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + + DO_IT_NOW(_glTranslatef, 3); +} +void Batch::do_glTranslatef(int ¶mOffset) { + glTranslatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); +} + +void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { + _commands.push_back(COMMAND_glDrawArrays); + _params.push_back(count); + _params.push_back(first); + _params.push_back(mode); + + DO_IT_NOW(_glDrawArrays, 3); +} +void Batch::do_glDrawArrays(int ¶mOffset) { + glDrawArrays(_params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._int); +} + +void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { + _commands.push_back(COMMAND_glDrawRangeElements); + _params.push_back(indices); + _params.push_back(type); + _params.push_back(count); + _params.push_back(end); + _params.push_back(start); + _params.push_back(mode); + + DO_IT_NOW(_glDrawRangeElements, 6); +} +void Batch::do_glDrawRangeElements(int ¶mOffset) { + glDrawRangeElements(_params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._constPointer); +} + +void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + _commands.push_back(COMMAND_glColorPointer); + _params.push_back(pointer); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); + + DO_IT_NOW(_glColorPointer, 4); +} +void Batch::do_glColorPointer(int ¶mOffset) { + glColorPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._constPointer); +} + +void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { + _commands.push_back(COMMAND_glNormalPointer); + _params.push_back(pointer); + _params.push_back(stride); + _params.push_back(type); + + DO_IT_NOW(_glNormalPointer, 4); +} +void Batch::do_glNormalPointer(int ¶mOffset) { + glNormalPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._constPointer); +} + +void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + _commands.push_back(COMMAND_glTexCoordPointer); + _params.push_back(pointer); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + _commands.push_back(COMMAND_glVertexPointer); + _params.push_back(pointer); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + + +void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { + _commands.push_back(COMMAND_glVertexPointer); + _params.push_back(pointer); + _params.push_back(stride); + _params.push_back(normalized); + _params.push_back(type); + _params.push_back(size); + _params.push_back(index); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glEnableVertexArrayAttrib(GLint location) { + _commands.push_back(COMMAND_glEnableVertexArrayAttrib); + _params.push_back(location); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glDisableVertexArrayAttrib(GLint location) { + _commands.push_back(COMMAND_glDisableVertexArrayAttrib); + _params.push_back(location); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + _commands.push_back(COMMAND_glColor4f); + _params.push_back(alpha); + _params.push_back(blue); + _params.push_back(green); + _params.push_back(red); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { + _commands.push_back(COMMAND_glMaterialf); + _params.push_back(param); + _params.push_back(pname); + _params.push_back(face); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { + _commands.push_back(COMMAND_glMaterialfv); + _params.push_back(params); + _params.push_back(pname); + _params.push_back(face); +} +void Batch::do_glCullFace(int ¶mOffset) { + glCullFace(_params[paramOffset++]._uint); +} diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 51e2ce61b6..a03c4ac1b7 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -47,10 +47,64 @@ public: void clear(); - void draw( Primitive primitiveType, int nbVertices, int startVertex = 0); - void drawIndexed( Primitive primitiveType, int nbIndices, int startIndex = 0 ); - void drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); - void drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + void draw( Primitive primitiveType, int nbVertices, int startVertex = 0); + void drawIndexed( Primitive primitiveType, int nbIndices, int startIndex = 0 ); + void drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); + void drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + + // TODO: As long as we have gl calls explicitely issued from interface + // code, we need to be able to record and batch these calls. THe long + // term strategy is to get rid of any GL calls in favor of the HIFI GPU API + void _glEnable(GLenum cap); + void _glDisable(GLenum cap); + + void _glEnableClientState(GLenum array); + void _glDisableClientState(GLenum array); + + void _glCullFace(GLenum mode); + void _glAlphaFunc(GLenum func, GLclampf ref); + + void _glDepthFunc(GLenum func); + void _glDepthMask(GLboolean flag); + void _glDepthRange(GLclampd zNear, GLclampd zFar); + + void _glBindBuffer(GLenum target, GLuint buffer); + + void _glBindTexture(GLenum target, GLuint texture); + void _glActiveTexture(GLenum texture); + + void _glDrawBuffers(GLsizei n, const GLenum* bufs); + + void _glUseProgram(GLuint program); + void _glUniform1f(GLint location, GLfloat v0); + void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); + + void _glMatrixMode(GLenum mode); + void _glPushMatrix(); + void _glPopMatrix(); + void _glMultMatrixf(const GLfloat *m); + void _glLoadMatrixf(const GLfloat *m); + void _glLoadIdentity(void); + void _glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); + void _glScalef(GLfloat x, GLfloat y, GLfloat z); + void _glTranslatef(GLfloat x, GLfloat y, GLfloat z); + + void _glDrawArrays(GLenum mode, GLint first, GLsizei count); + void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); + + void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); + void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer); + void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); + void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); + + void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); + void _glEnableVertexArrayAttrib(GLint location); + void _glDisableVertexArrayAttrib(GLint location); + + void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + + void _glMaterialf(GLenum face, GLenum pname, GLfloat param); + void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); protected: @@ -67,18 +121,77 @@ protected: COMMAND_SET_VERTEX_STREAM, COMMAND_SET_INDEX_STREAM, - COMMAND_GL_SET_UNIFORM, - + // TODO: As long as we have gl calls explicitely issued from interface + // code, we need to be able to record and batch these calls. THe long + // term strategy is to get rid of any GL calls in favor of the HIFI GPU API + COMMAND_glEnable, + COMMAND_glDisable, + + COMMAND_glEnableClientState, + COMMAND_glDisableClientState, + + COMMAND_glCullFace, + COMMAND_glAlphaFunc, + + COMMAND_glDepthFunc, + COMMAND_glDepthMask, + COMMAND_glDepthRange, + + COMMAND_glBindBuffer, + + COMMAND_glBindTexture, + COMMAND_glActiveTexture, + + COMMAND_glDrawBuffers, + + COMMAND_glUseProgram, + COMMAND_glUniform1f, + COMMAND_glUniformMatrix4fv, + + COMMAND_glMatrixMode, + COMMAND_glPushMatrix, + COMMAND_glPopMatrix, + COMMAND_glMultMatrixf, + COMMAND_glLoadMatrixf, + COMMAND_glLoadIdentity, + COMMAND_glRotatef, + COMMAND_glScalef, + COMMAND_glTranslatef, + + COMMAND_glDrawArrays, + COMMAND_glDrawRangeElements, + + COMMAND_glColorPointer, + COMMAND_glNormalPointer, + COMMAND_glTexCoordPointer, + COMMAND_glVertexPointer, + + COMMAND_glVertexAttribPointer, + COMMAND_glEnableVertexArrayAttrib, + COMMAND_glDisableVertexArrayAttrib, + + COMMAND_glColor4f, + + COMMAND_glMaterialf, + COMMAND_glMaterialfv, }; typedef std::vector Commands; - - class Param { - public: - union { - uint32 _uint; - char _chars[4]; - }; - Param( uint32 val ): _uint(val) {} + + class Param { + public: + union { + int32 _int; + uint32 _uint; + float _float; + char _chars[4]; + const void* _constPointer; + double _double; + }; + Param(int32 val) : _int(val) {} + Param(uint32 val) : _uint(val) {} + Param(float val) : _float(val) {} + Param(const void* val) : _constPointer(val) {} + Param(double val) : _double(val) {} }; typedef std::vector Params; @@ -91,6 +204,60 @@ protected: Commands _commands; Params _params; Resources _resources; + + // TODO: As long as we have gl calls explicitely issued from interface + // code, we need to be able to record and batch these calls. THe long + // term strategy is to get rid of any GL calls in favor of the HIFI GPU API + void do_glEnable(int ¶mOffset); + void do_glDisable(int ¶mOffset); + + void do_glEnableClientState(int ¶mOffset); + void do_glDisableClientState(int ¶mOffset); + + void do_glCullFace(int ¶mOffset); + void do_glAlphaFunc(int ¶mOffset); + + void do_glDepthFunc(int ¶mOffset); + void do_glDepthMask(int ¶mOffset); + void do_glDepthRange(int ¶mOffset); + + void do_glBindBuffer(int ¶mOffset); + + void do_glBindTexture(int ¶mOffset); + void do_glActiveTexture(int ¶mOffset); + + void do_glDrawBuffers(int ¶mOffset); + + void do_glUseProgram(int ¶mOffset); + void do_glUniform1f(int ¶mOffset); + void do_glUniformMatrix4fv(int ¶mOffset); + + void do_glMatrixMode(int ¶mOffset); + void do_glPushMatrix(int ¶mOffset); + void do_glPopMatrix(int ¶mOffset); + void do_glMultMatrixf(int ¶mOffset); + void do_glLoadMatrixf(int ¶mOffset); + void do_glLoadIdentity(int ¶mOffset); + void do_glRotatef(int ¶mOffset); + void do_glScalef(int ¶mOffset); + void do_glTranslatef(int ¶mOffset); + + void do_glDrawArrays(int ¶mOffset); + void do_glDrawRangeElements(int ¶mOffset); + + void do_glColorPointer(int ¶mOffset); + void do_glNormalPointer(int ¶mOffset); + void do_glTexCoordPointer(int ¶mOffset); + void do_glVertexPointer(int ¶mOffset); + + void do_glVertexAttribPointer(int ¶mOffset); + void do_glEnableVertexArrayAttrib(int ¶mOffset); + void do_glDisableVertexArrayAttrib(int ¶mOffset); + + void do_glColor4f(int ¶mOffset); + + void do_glMaterialf(int ¶mOffset); + void do_glMaterialfv(int ¶mOffset); }; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3800e78008..6032ae4d69 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -26,6 +26,9 @@ #include "Application.h" #include "Model.h" +#include "gpu/Batch.h" +#define GLBATCH( call ) batch._##call + using namespace std; static int modelPointerTypeId = qRegisterMetaType >(); @@ -1616,6 +1619,10 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); + // Try to use the Batch + gpu::Batch batch; + + // i is the "index" from the original networkMeshes QVector... foreach (int i, list) { @@ -1631,7 +1638,8 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); - const_cast(networkMesh.indexBuffer).bind(); + //const_cast(networkMesh.indexBuffer).bind(); + GLBATCH(glBindBuffer)( GL_INDEX_ARRAY, const_cast(networkMesh.indexBuffer).bufferId() ); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1668,12 +1676,16 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, const_cast(networkMesh.vertexBuffer).bind(); - glPushMatrix(); - Application::getInstance()->loadTranslatedViewMatrix(_translation); + GLBATCH(glPushMatrix)(); + //Application::getInstance()->loadTranslatedViewMatrix(_translation); + GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); + glm::vec3 viewMatTranslation = Application::getInstance()->getViewMatrixTranslation(); + GLBATCH(glTranslatef)(_translation.x + viewMatTranslation.x, _translation.y + viewMatTranslation.y, + _translation.z + viewMatTranslation.z); const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { - glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, + GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) + mesh.texCoords.size() * sizeof(glm::vec2) + @@ -1684,7 +1696,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, skinProgram->enableAttributeArray(skinLocations->clusterIndices); skinProgram->enableAttributeArray(skinLocations->clusterWeights); } else { - glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); + GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); } if (mesh.blendshapes.isEmpty()) { @@ -1692,9 +1704,9 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); activeProgram->enableAttributeArray(activeLocations->tangent); } - glColorPointer(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + + GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + mesh.tangents.size() * sizeof(glm::vec3))); - glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + + GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); } else { @@ -1702,20 +1714,20 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); activeProgram->enableAttributeArray(activeLocations->tangent); } - glColorPointer(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); - glTexCoordPointer(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); + GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); + GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); _blendedVertexBuffers[i].bind(); } - glVertexPointer(3, GL_FLOAT, 0, 0); - glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); + GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); + GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); if (!mesh.colors.isEmpty()) { - glEnableClientState(GL_COLOR_ARRAY); + GLBATCH(glEnableClientState)(GL_COLOR_ARRAY); } else { - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); } if (!mesh.texCoords.isEmpty()) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY); } qint64 offset = 0; @@ -1728,7 +1740,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } // apply material properties if (mode == SHADOW_RENDER_MODE) { - glBindTexture(GL_TEXTURE_2D, 0); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); } else { if (dontReduceMaterialSwitches || lastMaterialID != part.materialID) { @@ -1741,36 +1753,36 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); if (!(translucent && alphaThreshold == 0.0f)) { - glAlphaFunc(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); + GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); } glm::vec4 specular = glm::vec4(part.specularColor, 1.0f); - glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); - glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); - glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular); - glMaterialf(GL_FRONT, GL_SHININESS, part.shininess); + GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); + GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); + GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); + GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, part.shininess); Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); } - glBindTexture(GL_TEXTURE_2D, !diffuseMap ? + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); if (!mesh.tangents.isEmpty()) { - glActiveTexture(GL_TEXTURE1); + GLBATCH(glActiveTexture)(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); - glBindTexture(GL_TEXTURE_2D, !normalMap ? + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); - glActiveTexture(GL_TEXTURE0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); } if (specularTextureUnit) { - glActiveTexture(specularTextureUnit); + GLBATCH(glActiveTexture)(specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); - glBindTexture(GL_TEXTURE_2D, !specularMap ? + GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); - glActiveTexture(GL_TEXTURE0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); } if (args) { args->_materialSwitches++; @@ -1783,12 +1795,12 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, meshPartsRendered++; if (part.quadIndices.size() > 0) { - glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); + GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.quadIndices.size() * sizeof(int); } if (part.triangleIndices.size() > 0) { - glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), + GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.triangleIndices.size() * sizeof(int); } @@ -1802,35 +1814,39 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } if (!mesh.colors.isEmpty()) { - glDisableClientState(GL_COLOR_ARRAY); + GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); } if (!mesh.texCoords.isEmpty()) { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); } if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); + GLBATCH(glActiveTexture)(GL_TEXTURE1); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); - activeProgram->disableAttributeArray(activeLocations->tangent); + // activeProgram->disableAttributeArray(activeLocations->tangent); + GLBATCH(glDisableVertexArrayAttrib)(activeLocations->tangent); } if (specularTextureUnit) { - glActiveTexture(specularTextureUnit); - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); + GLBATCH(glActiveTexture)(specularTextureUnit); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + GLBATCH(glActiveTexture)(GL_TEXTURE0); } if (state.clusterMatrices.size() > 1) { - skinProgram->disableAttributeArray(skinLocations->clusterIndices); - skinProgram->disableAttributeArray(skinLocations->clusterWeights); + // skinProgram->disableAttributeArray(skinLocations->clusterIndices); + GLBATCH(glDisableVertexArrayAttrib)(skinLocations->clusterIndices); + // skinProgram->disableAttributeArray(skinLocations->clusterWeights); + GLBATCH(glDisableVertexArrayAttrib)(skinLocations->clusterWeights); } - glPopMatrix(); + GLBATCH(glPopMatrix)(); } - activeProgram->release(); - + //activeProgram->release(); + GLBATCH(glUseProgram)(0); + return meshPartsRendered; } From 3cd42b76715d25687bae2c30441a613e2b7f2538 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 18 Oct 2014 19:46:15 +0200 Subject: [PATCH 07/29] Allows Windows users to put SDL2 folder in %HIFI_LIB_DIR% folder (see BUILD.md for info about %HIFI_LIB_DIR% environment variable) --- cmake/modules/FindSDL2.cmake | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index f24af555a2..b9d1e9ee01 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -102,6 +102,8 @@ #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("sdl2") FIND_PATH(SDL2_INCLUDE_DIR SDL.h HINTS @@ -118,6 +120,7 @@ FIND_PATH(SDL2_INCLUDE_DIR SDL.h /opt/local # DarwinPorts /opt/csw # Blastwave /opt + Include HINTS ${SDL2_SEARCH_DIRS} ) # Lookup the 64 bit libs on x64 @@ -133,6 +136,7 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt + Include HINTS ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -147,6 +151,7 @@ ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt + Include HINTS ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -170,6 +175,7 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt + Include HINTS ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -185,6 +191,7 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt + Include HINTS ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") From e586b6e29b3004766f708f8eae8899261ada0416 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 20 Oct 2014 12:27:49 -0700 Subject: [PATCH 08/29] Remove nodes with no opaque elements. --- libraries/metavoxels/src/MetavoxelMessages.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libraries/metavoxels/src/MetavoxelMessages.cpp b/libraries/metavoxels/src/MetavoxelMessages.cpp index 17379a930f..299ffbbb80 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.cpp +++ b/libraries/metavoxels/src/MetavoxelMessages.cpp @@ -734,6 +734,22 @@ int VoxelMaterialSpannerEditVisitor::visit(MetavoxelInfo& info) { } } } + + // if there are no visible colors, we can clear everything + bool foundOpaque = false; + for (const QRgb* src = colorContents.constData(), *end = src + colorContents.size(); src != end; src++) { + if (qAlpha(*src) != 0) { + foundOpaque = true; + break; + } + } + if (!foundOpaque) { + info.outputValues[0] = AttributeValue(_outputs.at(0)); + info.outputValues[1] = AttributeValue(_outputs.at(1)); + info.outputValues[2] = AttributeValue(_outputs.at(2)); + return STOP_RECURSION; + } + VoxelColorDataPointer newColorPointer(new VoxelColorData(colorContents, VOXEL_BLOCK_SAMPLES)); info.outputValues[0] = AttributeValue(info.inputValues.at(0).getAttribute(), encodeInline(newColorPointer)); From 90a1f141ba0581dd236fd02cae8ffeaf913252b2 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 20 Oct 2014 22:28:02 +0200 Subject: [PATCH 09/29] removed duplicate hints entries --- cmake/modules/FindSDL2.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index b9d1e9ee01..d04cc5b48c 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -120,7 +120,7 @@ FIND_PATH(SDL2_INCLUDE_DIR SDL.h /opt/local # DarwinPorts /opt/csw # Blastwave /opt - Include HINTS ${SDL2_SEARCH_DIRS} + ${SDL2_SEARCH_DIRS} ) # Lookup the 64 bit libs on x64 @@ -136,7 +136,7 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt - Include HINTS ${SDL2_SEARCH_DIRS} + ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -151,7 +151,7 @@ ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt - Include HINTS ${SDL2_SEARCH_DIRS} + ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -175,7 +175,7 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt - Include HINTS ${SDL2_SEARCH_DIRS} + ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -191,7 +191,7 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt - Include HINTS ${SDL2_SEARCH_DIRS} + ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") From d64b43693db7b31b3aa7856e318d9deb5937345f Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 20 Oct 2014 15:33:46 -0700 Subject: [PATCH 10/29] Networking fix. --- assignment-client/src/metavoxels/MetavoxelServer.cpp | 4 ++-- libraries/metavoxels/src/MetavoxelClientManager.cpp | 8 ++++---- libraries/metavoxels/src/MetavoxelMessages.h | 1 + libraries/networking/src/PacketHeaders.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index a74b5bee90..dd35a23630 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -237,7 +237,7 @@ void MetavoxelSession::update() { // go back to the beginning with the current packet and note that there's a delta pending _sequencer.getOutputStream().getUnderlying().device()->seek(start); - MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID }; + MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID, _lod }; out << QVariant::fromValue(msg); _sequencer.endPacket(); @@ -290,7 +290,7 @@ void MetavoxelSession::sendPacketGroup(int alreadySent) { for (int i = 0; i < additionalPackets; i++) { Bitstream& out = _sequencer.startPacket(); if (_reliableDeltaChannel) { - MetavoxelDeltaPendingMessage msg = { _reliableDeltaID }; + MetavoxelDeltaPendingMessage msg = { _reliableDeltaID, _reliableDeltaLOD }; out << QVariant::fromValue(msg); } else { out << QVariant(); diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index 57f7b53cc3..2e0146af3b 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -255,12 +255,12 @@ void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) { } } else if (userType == MetavoxelDeltaPendingMessage::Type) { // check the id to make sure this is not a delta we've already processed - int id = message.value().id; - if (id > _reliableDeltaID) { - _reliableDeltaID = id; + MetavoxelDeltaPendingMessage pending = message.value(); + if (pending.id > _reliableDeltaID) { + _reliableDeltaID = pending.id; _reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX); _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream()); - _reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD(); + _reliableDeltaLOD = pending.lod; PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); _remoteDataLOD = receiveRecord->getLOD(); _remoteData = receiveRecord->getData(); diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index 9a7e254571..b9a44a0e6b 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -68,6 +68,7 @@ class MetavoxelDeltaPendingMessage { public: STREAM int id; + STREAM MetavoxelLOD lod; }; DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage) diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 283765c265..7f81a4c59e 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -81,7 +81,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAudioStreamStats: return 1; case PacketTypeMetavoxelData: - return 7; + return 8; case PacketTypeVoxelData: return VERSION_VOXELS_HAS_FILE_BREAKS; default: From 45fb31cd08b80c434bdbf8bc2c27ad5efd9caed7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 20 Oct 2014 18:43:41 -0700 Subject: [PATCH 11/29] Basic network simulation for metavoxels. --- interface/src/Menu.cpp | 10 +++ interface/src/Menu.h | 4 ++ interface/src/MetavoxelSystem.cpp | 105 ++++++++++++++++++++++++++-- interface/src/MetavoxelSystem.h | 16 +++++ libraries/metavoxels/src/Endpoint.h | 2 +- 5 files changed, 132 insertions(+), 5 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 3a213cb64f..11ab5769cb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -45,6 +45,7 @@ #include "ui/AttachmentsDialog.h" #include "ui/InfoView.h" #include "ui/MetavoxelEditor.h" +#include "ui/MetavoxelNetworkSimulator.h" #include "ui/ModelsBrowser.h" #include "ui/LoginDialog.h" #include "ui/NodeBounds.h" @@ -431,6 +432,8 @@ Menu::Menu() : QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels"); addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false, Application::getInstance()->getMetavoxels(), SLOT(refreshVoxelData())); + addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0, this, + SLOT(showMetavoxelNetworkSimulator())); QMenu* handOptionsMenu = developerMenu->addMenu("Hands"); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, false); @@ -1378,6 +1381,13 @@ void Menu::showMetavoxelEditor() { _MetavoxelEditor->raise(); } +void Menu::showMetavoxelNetworkSimulator() { + if (!_metavoxelNetworkSimulator) { + _metavoxelNetworkSimulator = new MetavoxelNetworkSimulator(); + } + _metavoxelNetworkSimulator->raise(); +} + void Menu::showScriptEditor() { if(!_ScriptEditor || !_ScriptEditor->isVisible()) { _ScriptEditor = new ScriptEditorWindow(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a1936050ff..80f7f1e006 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -78,6 +78,7 @@ class AttachmentsDialog; class BandwidthDialog; class LodToolsDialog; class MetavoxelEditor; +class MetavoxelNetworkSimulator; class ChatWindow; class OctreeStatsDialog; class MenuItemProperties; @@ -218,6 +219,7 @@ private slots: void cycleFrustumRenderMode(); void runTests(); void showMetavoxelEditor(); + void showMetavoxelNetworkSimulator(); void showScriptEditor(); void showChat(); void toggleConsole(); @@ -274,6 +276,7 @@ private: FrustumDrawMode _frustumDrawMode; ViewFrustumOffset _viewFrustumOffset; QPointer _MetavoxelEditor; + QPointer _metavoxelNetworkSimulator; QPointer _ScriptEditor; QPointer _chatWindow; QDialog* _jsConsole; @@ -430,6 +433,7 @@ namespace MenuOption { const QString MuteEnvironment = "Mute Environment"; const QString MyLocations = "My Locations..."; const QString NameLocation = "Name this location"; + const QString NetworkSimulator = "Network Simulator..."; const QString NewVoxelCullingMode = "New Voxel Culling Mode"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; const QString OctreeStats = "Voxel and Entity Statistics"; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index e9cfde60f9..97385a8671 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -39,6 +39,13 @@ REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType(); +MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, int minimumDelay, int maximumDelay) : + dropRate(dropRate), + repeatRate(repeatRate), + minimumDelay(minimumDelay), + maximumDelay(maximumDelay) { +} + void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); @@ -61,6 +68,16 @@ MetavoxelLOD MetavoxelSystem::getLOD() { return _lod; } +void MetavoxelSystem::setNetworkSimulation(const NetworkSimulation& simulation) { + QWriteLocker locker(&_networkSimulationLock); + _networkSimulation = simulation; +} + +MetavoxelSystem::NetworkSimulation MetavoxelSystem::getNetworkSimulation() { + QReadLocker locker(&_networkSimulationLock); + return _networkSimulation; +} + class SimulateVisitor : public MetavoxelVisitor { public: @@ -692,10 +709,53 @@ MetavoxelData MetavoxelSystemClient::getAugmentedData() { return _augmentedData; } +class ReceiveDelayer : public QObject { +public: + + ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet); + +protected: + + virtual void timerEvent(QTimerEvent* event); + +private: + + SharedNodePointer _node; + QByteArray _packet; +}; + +ReceiveDelayer::ReceiveDelayer(const SharedNodePointer& node, const QByteArray& packet) : + _node(node), + _packet(packet) { +} + +void ReceiveDelayer::timerEvent(QTimerEvent* event) { + QMutexLocker locker(&_node->getMutex()); + MetavoxelClient* client = static_cast(_node->getLinkedData()); + if (client) { + QMetaObject::invokeMethod(&client->getSequencer(), "receivedDatagram", Q_ARG(const QByteArray&, _packet)); + } + deleteLater(); +} + int MetavoxelSystemClient::parseData(const QByteArray& packet) { // process through sequencer - QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); - Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::METAVOXELS).updateValue(packet.size()); + MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); + if (randFloat() < simulation.dropRate) { + return packet.size(); + } + int count = (randFloat() < simulation.repeatRate) ? 2 : 1; + for (int i = 0; i < count; i++) { + int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); + if (delay > 0) { + ReceiveDelayer* delayer = new ReceiveDelayer(_node, packet); + delayer->startTimer(delay); + + } else { + QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); + } + Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::METAVOXELS).updateValue(packet.size()); + } return packet.size(); } @@ -774,9 +834,46 @@ void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) { QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD)); } +class SendDelayer : public QObject { +public: + + SendDelayer(const SharedNodePointer& node, const QByteArray& data); + + virtual void timerEvent(QTimerEvent* event); + +private: + + SharedNodePointer _node; + QByteArray _data; +}; + +SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) : + _node(node), + _data(data) { +} + +void SendDelayer::timerEvent(QTimerEvent* event) { + NodeList::getInstance()->writeDatagram(_data, _node); + deleteLater(); +} + void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { - NodeList::getInstance()->writeDatagram(data, _node); - Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size()); + MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); + if (randFloat() < simulation.dropRate) { + return; + } + int count = (randFloat() < simulation.repeatRate) ? 2 : 1; + for (int i = 0; i < count; i++) { + int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); + if (delay > 0) { + SendDelayer* delayer = new SendDelayer(_node, data); + delayer->startTimer(delay); + + } else { + NodeList::getInstance()->writeDatagram(data, _node); + } + Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size()); + } } BufferData::~BufferData() { diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index ac6a75c68b..af6f4c6c7a 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -31,12 +31,25 @@ class MetavoxelSystem : public MetavoxelClientManager { public: + class NetworkSimulation { + public: + float dropRate; + float repeatRate; + int minimumDelay; + int maximumDelay; + + NetworkSimulation(float dropRate = 0.0f, float repeatRate = 0.0f, int minimumDelay = 0, int maximumDelay = 0); + }; + virtual void init(); virtual MetavoxelLOD getLOD(); const Frustum& getFrustum() const { return _frustum; } + void setNetworkSimulation(const NetworkSimulation& simulation); + NetworkSimulation getNetworkSimulation(); + const AttributePointer& getPointBufferAttribute() { return _pointBufferAttribute; } const AttributePointer& getHeightfieldBufferAttribute() { return _heightfieldBufferAttribute; } const AttributePointer& getVoxelBufferAttribute() { return _voxelBufferAttribute; } @@ -93,6 +106,9 @@ private: MetavoxelLOD _lod; QReadWriteLock _lodLock; Frustum _frustum; + + NetworkSimulation _networkSimulation; + QReadWriteLock _networkSimulationLock; }; /// Generic abstract base class for objects that handle a signal. diff --git a/libraries/metavoxels/src/Endpoint.h b/libraries/metavoxels/src/Endpoint.h index d6999196d8..7b0adb4cef 100644 --- a/libraries/metavoxels/src/Endpoint.h +++ b/libraries/metavoxels/src/Endpoint.h @@ -32,7 +32,7 @@ public: PacketRecord* baselineReceiveRecord = NULL); virtual ~Endpoint(); - const DatagramSequencer& getSequencer() const { return _sequencer; } + DatagramSequencer& getSequencer() { return _sequencer; } virtual void update(); From 4e605f5f6751e65642d2090ecd46dee7339d321c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 21 Oct 2014 00:20:08 -0700 Subject: [PATCH 12/29] First headMove "no-barf" version with lean/nod to walk, turn --- examples/headMove.js | 293 ++++++++++++++++-------------- interface/src/avatar/MyAvatar.cpp | 2 + interface/src/avatar/MyAvatar.h | 3 + 3 files changed, 165 insertions(+), 133 deletions(-) diff --git a/examples/headMove.js b/examples/headMove.js index 086ef80abc..3e856b6fa5 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -5,174 +5,201 @@ // Created by Philip Rosedale on September 8, 2014 // Copyright 2014 High Fidelity, Inc. // -// Press the spacebar and move/turn your head to move around. +// Press the spacebar and then use your head to move and turn. Pull back to see your body. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // var debug = false; +var willMove = false; + +var warpActive = false; +var warpPosition = { x: 0, y: 0, z: 0 }; + +// Overlays to show target location + +var WARP_SPHERE_SIZE = 0.15; +var warpSphere = Overlays.addOverlay("sphere", { + position: { x: 0, y: 0, z: 0 }, + size: WARP_SPHERE_SIZE, + color: { red: 200, green: 0, blue: 0 }, + alpha: 0.5, + solid: true, + visible: false, +}); + +var WARP_LINE_HEIGHT = 5; +var warpLine = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z:0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 255, blue: 255}, + alpha: 1, + lineWidth: 5, + visible: false, +}); var movingWithHead = false; var headStartPosition, headStartDeltaPitch, headStartFinalPitch, headStartRoll, headStartYaw; +var timeSinceLastTurn = 0.0; +var timeSinceLastStep = 0.0; +var isTurning = false; +var deltaYaw = 0.0; +var turnAmount = 0.0; +var keyDownTime = 0.0; +var watchAvatar = false; +var oldMode; -var HEAD_MOVE_DEAD_ZONE = 0.05; -var HEAD_STRAFE_DEAD_ZONE = 0.03; -var HEAD_ROTATE_DEAD_ZONE = 10.0; -var HEAD_YAW_RATE = 1.5; -var HEAD_PITCH_RATE = 1.0; -var WALL_BOUNCE = 10000.0; -var FIXED_WALK_VELOCITY = 1.5; - -// Modify these values to tweak the strength of the motion. -// A larger *FACTOR increases the speed. -// A lower SHORT_TIMESCALE makes the motor achieve full speed faster. -var HEAD_VELOCITY_FWD_FACTOR = 10.0; -var HEAD_VELOCITY_LEFT_FACTOR = 0.0; -var HEAD_VELOCITY_UP_FACTOR = 20.0; -var SHORT_TIMESCALE = 0.01; -var VERY_LARGE_TIMESCALE = 1000000.0; - -var xAxis = {x:1.0, y:0.0, z:0.0 }; -var yAxis = {x:0.0, y:1.0, z:0.0 }; -var zAxis = {x:0.0, y:0.0, z:1.0 }; - -// If these values are set to something -var maxVelocity = 1.25; -var noFly = true; -var fixedWalkVelocity = true; - -//var roomLimits = { xMin: 618, xMax: 635.5, zMin: 528, zMax: 552.5 }; -var roomLimits = { xMin: -1.0, xMax: -1.0, zMin: -1.0, zMax: -1.0 }; - -function isInRoom(position) { - var BUFFER = 2.0; - if (roomLimits.xMin < 0) { - return false; - } - if ((position.x > (roomLimits.xMin - BUFFER)) && - (position.x < (roomLimits.xMax + BUFFER)) && - (position.z > (roomLimits.zMin - BUFFER)) && - (position.z < (roomLimits.zMax + BUFFER))) - { - return true; - } else { - return false; - } +function saveCameraState() { + oldMode = Camera.getMode(); + Camera.setMode("independent"); } -function moveWithHead(deltaTime) { - var position = MyAvatar.position; - var motorTimescale = VERY_LARGE_TIMESCALE; +function restoreCameraState() { + //Camera.stopLooking(); + Camera.setMode(oldMode); +} + +function activateWarp() { + if (warpActive) return; + warpActive = true; + + updateWarp(); +} + +var WARP_PITCH_DEAD_ZONE = 4.0; +var WARP_SENSITIVITY = 0.35; +var TRIGGER_PULLBACK_DISTANCE = 0.04; +var WATCH_AVATAR_DISTANCE = 1.5; +var MAX_WARP_YAW = 40.0; +var MAX_PULLBACK_YAW = 5.0; + +var sound = new Sound("http://public.highfidelity.io/sounds/Footsteps/FootstepW2Right-12db.wav"); +function playSound() { + var options = new AudioInjectionOptions(); + var position = MyAvatar.position; + options.position = position; + options.volume = 0.5; + Audio.playSound(sound, options); +} + +function updateWarp() { + if (!warpActive) return; + + var look = Quat.getFront(Camera.getOrientation()); + var deltaPosition = Vec3.subtract(MyAvatar.getTrackedHeadPosition(), headStartPosition); + var deltaPitch = Math.abs(MyAvatar.getHeadFinalPitch() - headStartFinalPitch); + deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw; + + willMove = (!watchAvatar && (Math.abs(deltaYaw) < MAX_WARP_YAW) && (deltaPitch > WARP_PITCH_DEAD_ZONE)); + + if (willMove) { + var distance = Math.pow((deltaPitch - WARP_PITCH_DEAD_ZONE) * WARP_SENSITIVITY, 2.0); + var warpDirection = Vec3.normalize({ x: look.x, y: 0, z: look.z }); + warpPosition = Vec3.multiply(warpDirection, distance); + warpPosition = Vec3.sum(MyAvatar.position, warpPosition); + } + + if (!watchAvatar && (Math.abs(deltaYaw) < MAX_PULLBACK_YAW) && (deltaPosition.z > TRIGGER_PULLBACK_DISTANCE)) { + saveCameraState(); + var height = MyAvatar.getEyePosition().y - MyAvatar.position.y; + var cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -height, z: -height * WATCH_AVATAR_DISTANCE })); + Camera.setPosition(cameraPosition); + watchAvatar = true; + } + + // Adjust overlays to match warp position + Overlays.editOverlay(warpSphere, { + position: warpPosition, + visible: willMove, + }); + Overlays.editOverlay(warpLine, { + position: Vec3.sum(warpPosition, { x: 0, y: -WARP_LINE_HEIGHT / 2.0, z: 0 }), + end: Vec3.sum(warpPosition, { x: 0, y: WARP_LINE_HEIGHT / 2.0, z: 0 }), + visible: willMove, + }); +} + +function finishWarp() { + if (!warpActive) return; + warpActive = false; + Overlays.editOverlay(warpSphere, { + visible: false, + }); + Overlays.editOverlay(warpLine, { + visible: false, + }); + if (willMove) { + MyAvatar.position = warpPosition; + playSound(); + } else if (!watchAvatar) { + isTurning = true; + turnAmount = deltaYaw; + timeSinceLastTurn = TURN_INTERVAL; + playSound(); + } +} + +var EPSILON_YAW = 180.0; +var TURN_INTERVAL = 0.175; + +function update(deltaTime) { + if (movingWithHead) { - var deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw; - var deltaPitch = MyAvatar.getHeadDeltaPitch() - headStartDeltaPitch; - var deltaRoll = MyAvatar.getHeadFinalRoll() - headStartRoll; - var velocity = MyAvatar.getVelocity(); - var position = MyAvatar.position; - var neckPosition = MyAvatar.getNeckPosition(); - var bodyLocalCurrentHeadVector = Vec3.subtract(neckPosition, position); - bodyLocalCurrentHeadVector = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), bodyLocalCurrentHeadVector); - var headDelta = Vec3.subtract(bodyLocalCurrentHeadVector, headStartPosition); - headDelta.y = 0.0; // Don't respond to any of the vertical component of head motion - headDelta = Vec3.multiplyQbyV(MyAvatar.orientation, headDelta); - headDelta = Vec3.multiplyQbyV(Quat.inverse(Camera.getOrientation()), headDelta); - - var length = Vec3.length(headDelta); + keyDownTime += deltaTime; + updateWarp(); + } - if (length > 1.0) { - // Needs fixed! Right now sometimes reported neck position jumps to a bad value - headDelta.x = headDelta.y = headDelta.z = 0.0; - length = 0.0; - return; - } - - // Thrust based on leaning forward and side-to-side - var targetVelocity = {x:0.0, y:0.0, z:0.0}; - if (length > HEAD_MOVE_DEAD_ZONE) { - //headDelta = Vec3.normalize(headDelta); - //targetVelocity = Vec3.multiply(headDelta, FIXED_WALK_VELOCITY); - targetVelocity = Vec3.multiply(headDelta, HEAD_VELOCITY_FWD_FACTOR); - } - /* - if (Math.abs(headDelta.z) > HEAD_MOVE_DEAD_ZONE) { - if (fixedWalkVelocity) { - targetVelocity = Vec3.multiply(zAxis, headDelta.z > 0 ? FIXED_WALK_VELOCITY : -FIXED_WALK_VELOCITY); + if (isTurning) { + timeSinceLastTurn += deltaTime; + if (timeSinceLastTurn > TURN_INTERVAL) { + if (Math.abs(turnAmount) <= EPSILON_YAW) { + var thisTurn = turnAmount; + isTurning = false; } else { - targetVelocity = Vec3.multiply(zAxis, headDelta.z * HEAD_VELOCITY_FWD_FACTOR); + var thisTurn = turnAmount / 2.0; + turnAmount = turnAmount / 2.0; } - } - if (Math.abs(headDelta.x) > HEAD_STRAFE_DEAD_ZONE) { - var deltaVelocity = Vec3.multiply(xAxis, headDelta.x * HEAD_VELOCITY_LEFT_FACTOR); - targetVelocity = Vec3.sum(targetVelocity, deltaVelocity); - } - */ - if (Math.abs(deltaYaw) > HEAD_ROTATE_DEAD_ZONE) { - var orientation = Quat.multiply(Quat.angleAxis((deltaYaw + deltaRoll) * HEAD_YAW_RATE * deltaTime, yAxis), MyAvatar.orientation); + var orientation = MyAvatar.orientation; + orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, thisTurn, 0), orientation) ; MyAvatar.orientation = orientation; - } - - // Thrust Up/Down based on head pitch - if (!noFly) { - var deltaVelocity = Vec3.multiply(yAxis, headDelta.y * HEAD_VELOCITY_UP_FACTOR); - targetVelocity = Vec3.sum(targetVelocity, deltaVelocity); - } - // For head trackers, adjust pitch by head pitch - MyAvatar.headPitch += deltaPitch * HEAD_PITCH_RATE * deltaTime; - - // apply the motor - MyAvatar.motorVelocity = targetVelocity; - motorTimescale = SHORT_TIMESCALE; - } - - // Check against movement box limits - if (isInRoom(position)) { - var thrust = { x: 0, y: 0, z: 0 }; - // use thrust to constrain the avatar to the space - if (position.x < roomLimits.xMin) { - thrust.x += (roomLimits.xMin - position.x) * WALL_BOUNCE * deltaTime; - } else if (position.x > roomLimits.xMax) { - thrust.x += (roomLimits.xMax - position.x) * WALL_BOUNCE * deltaTime; - } - if (position.z < roomLimits.zMin) { - thrust.z += (roomLimits.zMin - position.z) * WALL_BOUNCE * deltaTime; - } else if (position.z > roomLimits.zMax) { - thrust.z += (roomLimits.zMax - position.z) * WALL_BOUNCE * deltaTime; - } - MyAvatar.addThrust(thrust); - if (movingWithHead && Vec3.length(thrust) > 0.0) { - // reduce the timescale of the motor so that it won't defeat the thrust code - Vec3.print("adebug room containment thrust = ", thrust); - motorTimescale = 1000000.0; + timeSinceLastTurn = 0.0; } } - MyAvatar.motorTimescale = motorTimescale; } Controller.keyPressEvent.connect(function(event) { if (event.text == "SPACE" && !movingWithHead) { + keyDownTime = 0.0; movingWithHead = true; - headStartPosition = Vec3.subtract(MyAvatar.getNeckPosition(), MyAvatar.position); - headStartPosition = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), headStartPosition); + headStartPosition = MyAvatar.getTrackedHeadPosition(); headStartDeltaPitch = MyAvatar.getHeadDeltaPitch(); headStartFinalPitch = MyAvatar.getHeadFinalPitch(); headStartRoll = MyAvatar.getHeadFinalRoll(); headStartYaw = MyAvatar.getHeadFinalYaw(); - // start with disabled motor -- it will be updated shortly - MyAvatar.motorTimescale = VERY_LARGE_TIMESCALE; - MyAvatar.motorVelocity = {x:0.0, y:0.0, z:0.0}; - MyAvatar.motorReferenceFrame = "camera"; // alternatives are: "avatar" and "world" + deltaYaw = 0.0; + activateWarp(); } }); +var TIME_FOR_TURNAROUND = 0.15; +var TURN_AROUND = 180.0; + Controller.keyReleaseEvent.connect(function(event) { if (event.text == "SPACE") { movingWithHead = false; - // disable motor by giving it an obnoxiously large timescale - MyAvatar.motorTimescale = VERY_LARGE_TIMESCALE; - MyAvatar.motorVelocity = {x:0.0, y:0.0, z:0.0}; + isTurning = false; + if (keyDownTime < TIME_FOR_TURNAROUND) { + MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, TURN_AROUND, 0), MyAvatar.orientation); + playSound(); + } + finishWarp(); + if (watchAvatar) { + restoreCameraState(); + watchAvatar = false; + } } }); -Script.update.connect(moveWithHead); +Script.update.connect(update); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bf6f176d22..4751abfd84 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -296,6 +296,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { } else if (OculusManager::isConnected()) { estimatedPosition = OculusManager::getRelativePosition(); estimatedPosition.x *= -1.0f; + _trackedHeadPosition = estimatedPosition; const float OCULUS_LEAN_SCALE = 0.05f; estimatedPosition /= OCULUS_LEAN_SCALE; @@ -303,6 +304,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker(); if (tracker) { estimatedPosition = tracker->getHeadTranslation(); + _trackedHeadPosition = estimatedPosition; estimatedRotation = glm::degrees(safeEulerAngles(tracker->getHeadRotation())); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 98fc5ff74d..9cb9246da7 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -113,6 +113,7 @@ public: static void sendKillAvatar(); + Q_INVOKABLE glm::vec3 getTrackedHeadPosition() const { return _trackedHeadPosition; } Q_INVOKABLE glm::vec3 getHeadPosition() const { return getHead()->getPosition(); } Q_INVOKABLE float getHeadFinalYaw() const { return getHead()->getFinalYaw(); } Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); } @@ -237,6 +238,8 @@ private: RecorderPointer _recorder; + glm::vec3 _trackedHeadPosition; + // private methods void updateOrientation(float deltaTime); glm::vec3 applyKeyboardMotor(float deltaTime, const glm::vec3& velocity, bool walkingOnFloor); From 8b8b7f1189b2d45b894b952f7d1f6640b471fd26 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 21 Oct 2014 13:39:24 +0200 Subject: [PATCH 13/29] Moved the new hints to HINTS, thanks for the hint @birarda --- cmake/modules/FindSDL2.cmake | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake index d04cc5b48c..6ef9ffa52a 100644 --- a/cmake/modules/FindSDL2.cmake +++ b/cmake/modules/FindSDL2.cmake @@ -107,6 +107,7 @@ hifi_library_search_hints("sdl2") FIND_PATH(SDL2_INCLUDE_DIR SDL.h HINTS + ${SDL2_SEARCH_DIRS} $ENV{SDL2} PATH_SUFFIXES include/SDL2 include SDL2 i686-w64-mingw32/include/SDL2 @@ -120,13 +121,13 @@ FIND_PATH(SDL2_INCLUDE_DIR SDL.h /opt/local # DarwinPorts /opt/csw # Blastwave /opt - ${SDL2_SEARCH_DIRS} ) # Lookup the 64 bit libs on x64 IF(CMAKE_SIZEOF_VOID_P EQUAL 8) FIND_LIBRARY(SDL2_LIBRARY_TEMP SDL2 HINTS + ${SDL2_SEARCH_DIRS} $ENV{SDL2} PATH_SUFFIXES lib64 lib lib/x64 @@ -136,12 +137,12 @@ IF(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt - ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) FIND_LIBRARY(SDL2_LIBRARY_TEMP SDL2 HINTS + ${SDL2_SEARCH_DIRS} $ENV{SDL2} PATH_SUFFIXES lib lib/x86 @@ -151,7 +152,6 @@ ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) /opt/local /opt/csw /opt - ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -166,6 +166,7 @@ IF(NOT SDL2_BUILDING_LIBRARY) FIND_LIBRARY(SDL2MAIN_LIBRARY NAMES SDL2main HINTS + ${SDL2_SEARCH_DIRS} $ENV{SDL2} PATH_SUFFIXES lib64 lib lib/x64 @@ -175,13 +176,13 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt - ${SDL2_SEARCH_DIRS} ) # On 32bit build find the 32bit libs ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8) FIND_LIBRARY(SDL2MAIN_LIBRARY NAMES SDL2main HINTS + ${SDL2_SEARCH_DIRS} $ENV{SDL2} PATH_SUFFIXES lib lib/x86 @@ -191,7 +192,6 @@ IF(NOT SDL2_BUILDING_LIBRARY) /opt/local /opt/csw /opt - ${SDL2_SEARCH_DIRS} ) ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8) ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") From 99adb413e3b9a13626bc11fa937212137a33b60d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Oct 2014 08:20:15 -0700 Subject: [PATCH 14/29] add 3D text overlay support --- interface/src/ui/overlays/Base3DOverlay.h | 1 + interface/src/ui/overlays/Overlay.h | 1 + interface/src/ui/overlays/Overlay2D.h | 2 + interface/src/ui/overlays/Overlays.cpp | 7 +- interface/src/ui/overlays/Text3DOverlay.cpp | 197 ++++++++++++++++++++ interface/src/ui/overlays/Text3DOverlay.h | 72 +++++++ 6 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 interface/src/ui/overlays/Text3DOverlay.cpp create mode 100644 interface/src/ui/overlays/Text3DOverlay.h diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index e293bae5a9..fa750e4fe7 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -26,6 +26,7 @@ public: ~Base3DOverlay(); // getters + virtual bool is3D() const { return true; } const glm::vec3& getPosition() const { return _position; } const glm::vec3& getCenter() const { return _position; } // TODO: consider implementing registration points in this class float getLineWidth() const { return _lineWidth; } diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index dfa9b11d74..d4d0c40135 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -40,6 +40,7 @@ public: virtual void render() = 0; // getters + virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } bool getVisible() const { return _visible; } xColor getColor(); diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 34028de89a..283e7b7b23 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -29,6 +29,8 @@ class Overlay2D : public Overlay { public: Overlay2D(); ~Overlay2D(); + + virtual bool is3D() const { return false; } // getters int getX() const { return _bounds.x(); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 922c6a0408..46b7d5afdc 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -23,6 +23,7 @@ #include "Rectangle3DOverlay.h" #include "Sphere3DOverlay.h" #include "TextOverlay.h" +#include "Text3DOverlay.h" Overlays::Overlays() : _nextOverlayID(1) { } @@ -131,6 +132,9 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = new ImageOverlay(); } else if (type == "text") { thisOverlay = new TextOverlay(); + } else if (type == "text3d") { + thisOverlay = new Text3DOverlay(); +qDebug() << "created Text3DOverlay:" << thisOverlay; } else if (type == "cube") { thisOverlay = new Cube3DOverlay(); } else if (type == "sphere") { @@ -167,8 +171,7 @@ unsigned int Overlays::addOverlay(Overlay* overlay) { QWriteLocker lock(&_lock); unsigned int thisID = _nextOverlayID; _nextOverlayID++; - bool is3D = typeid(*overlay) != typeid(ImageOverlay) && typeid(*overlay) != typeid(TextOverlay); - if (is3D) { + if (overlay->is3D()) { _overlays3D[thisID] = overlay; } else { _overlays2D[thisID] = overlay; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp new file mode 100644 index 0000000000..de72ed2692 --- /dev/null +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -0,0 +1,197 @@ +// +// Text3DOverlay.cpp +// interface/src/ui/overlays +// +// Copyright 2014 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 this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include + +#include "Application.h" +#include "Text3DOverlay.h" +#include "ui/TextRenderer.h" + +const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; +const float DEFAULT_MARGIN = 0.1f; + +Text3DOverlay::Text3DOverlay() : + _backgroundColor(DEFAULT_BACKGROUND_COLOR), + _lineHeight(0.1f), + _leftMargin(DEFAULT_MARGIN), + _topMargin(DEFAULT_MARGIN), + _rightMargin(DEFAULT_MARGIN), + _bottomMargin(DEFAULT_MARGIN), + _isFacingAvatar(false) +{ +} + +Text3DOverlay::~Text3DOverlay() { +} + +xColor Text3DOverlay::getBackgroundColor() { + if (_colorPulse == 0.0f) { + return _backgroundColor; + } + + float pulseLevel = updatePulse(); + xColor result = _backgroundColor; + if (_colorPulse < 0.0f) { + result.red *= (1.0f - pulseLevel); + result.green *= (1.0f - pulseLevel); + result.blue *= (1.0f - pulseLevel); + } else { + result.red *= pulseLevel; + result.green *= pulseLevel; + result.blue *= pulseLevel; + } + return result; +} + + +void Text3DOverlay::render() { + if (!_visible) { + return; // do nothing if we're not visible + } + + glPushMatrix(); { + glTranslatef(_position.x, _position.y, _position.z); + glm::quat rotation; + if (_isFacingAvatar) { + // rotate about vertical to face the camera + rotation = Application::getInstance()->getCamera()->getRotation(); + rotation *= glm::angleAxis(glm::pi(), glm::vec3(0.0f, 1.0f, 0.0f)); + } else { + rotation = getRotation(); + } + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + + const float MAX_COLOR = 255.0f; + xColor backgroundColor = getBackgroundColor(); + float alpha = getAlpha(); + glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, alpha); + + glm::vec2 dimensions = getDimensions(); + glm::vec2 halfDimensions = dimensions * 0.5f; + + const float SLIGHTLY_BEHIND = -0.005f; + + glBegin(GL_QUADS); + glVertex3f(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); + glVertex3f(halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); + glVertex3f(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); + glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); + glEnd(); + + //TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false, + // EffectType effect = NO_EFFECT, int effectThickness = 1); + + const int FIXED_FONT_POINT_SIZE = 40; + const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation + + TextRenderer* textRenderer = TextRenderer::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); + float LINE_SCALE_RATIO = 1.2f; + float maxHeight = (float)textRenderer->calculateHeight("Xy") * LINE_SCALE_RATIO; + + float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; + + glTranslatef(-(halfDimensions.x - _leftMargin), halfDimensions.y - _topMargin, 0.0f); + + glm::vec2 clipMinimum(0.0f, 0.0f); + glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, + (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); + + glScalef(scaleFactor, -scaleFactor, 1.0); + int x = 0; + int y = 0; + + bool wantClipping = true; + + if (wantClipping) { + enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); + enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); + enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); + enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); + } + + glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR); + QStringList lines = _text.split("\n"); + int lineOffset = maxHeight; + foreach(QString thisLine, lines) { + textRenderer->draw(x, y + lineOffset, qPrintable(thisLine)); + lineOffset += maxHeight; + } + + if (wantClipping) { + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); + } + + } glPopMatrix(); + +} + +void Text3DOverlay::enableClipPlane(GLenum plane, float x, float y, float z, float w) { + GLdouble coefficients[] = { x, y, z, w }; + glClipPlane(plane, coefficients); + glEnable(plane); +} + +void Text3DOverlay::setProperties(const QScriptValue& properties) { + Planar3DOverlay::setProperties(properties); + + QScriptValue text = properties.property("text"); + if (text.isValid()) { + setText(text.toVariant().toString()); + } + + QScriptValue backgroundColor = properties.property("backgroundColor"); + if (backgroundColor.isValid()) { + QScriptValue red = backgroundColor.property("red"); + QScriptValue green = backgroundColor.property("green"); + QScriptValue blue = backgroundColor.property("blue"); + if (red.isValid() && green.isValid() && blue.isValid()) { + _backgroundColor.red = red.toVariant().toInt(); + _backgroundColor.green = green.toVariant().toInt(); + _backgroundColor.blue = blue.toVariant().toInt(); + } + } + + if (properties.property("lineHeight").isValid()) { + setLineHeight(properties.property("lineHeight").toVariant().toFloat()); + } + + if (properties.property("leftMargin").isValid()) { + setLeftMargin(properties.property("leftMargin").toVariant().toFloat()); + } + + if (properties.property("topMargin").isValid()) { + setTopMargin(properties.property("topMargin").toVariant().toFloat()); + } + + if (properties.property("rightMargin").isValid()) { + setRightMargin(properties.property("rightMargin").toVariant().toFloat()); + } + + if (properties.property("bottomMargin").isValid()) { + setBottomMargin(properties.property("bottomMargin").toVariant().toFloat()); + } + + + QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar"); + if (isFacingAvatarValue.isValid()) { + _isFacingAvatar = isFacingAvatarValue.toVariant().toBool(); + } + +} + + diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h new file mode 100644 index 0000000000..35ca352891 --- /dev/null +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -0,0 +1,72 @@ +// +// Text3DOverlay.h +// interface/src/ui/overlays +// +// Copyright 2014 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_Text3DOverlay_h +#define hifi_Text3DOverlay_h + +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +//#include "Overlay.h" +//#include "Overlay3D.h" +#include "Planar3DOverlay.h" + +class Text3DOverlay : public Planar3DOverlay { + Q_OBJECT + +public: + Text3DOverlay(); + ~Text3DOverlay(); + virtual void render(); + + // getters + const QString& getText() const { return _text; } + float getLineHeight() const { return _lineHeight; } + float getLeftMargin() const { return _leftMargin; } + float getTopMargin() const { return _topMargin; } + float getRightMargin() const { return _rightMargin; } + float getBottomMargin() const { return _bottomMargin; } + xColor getBackgroundColor(); + + // setters + void setText(const QString& text) { _text = text; } + void setLineHeight(float value) { _lineHeight = value; } + void setLeftMargin(float margin) { _leftMargin = margin; } + void setTopMargin(float margin) { _topMargin = margin; } + void setRightMargin(float margin) { _rightMargin = margin; } + void setBottomMargin(float margin) { _bottomMargin = margin; } + + virtual void setProperties(const QScriptValue& properties); + +private: + void enableClipPlane(GLenum plane, float x, float y, float z, float w); + + QString _text; + xColor _backgroundColor; + float _lineHeight; + float _leftMargin; + float _topMargin; + float _rightMargin; + float _bottomMargin; + bool _isFacingAvatar; +}; + + +#endif // hifi_Text3DOverlay_h From 956d7c73b222604d68b69b734a3f2566b4f8564c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Oct 2014 08:21:01 -0700 Subject: [PATCH 15/29] removed debug --- interface/src/ui/overlays/Overlays.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 46b7d5afdc..b079acb0a8 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -134,7 +134,6 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = new TextOverlay(); } else if (type == "text3d") { thisOverlay = new Text3DOverlay(); -qDebug() << "created Text3DOverlay:" << thisOverlay; } else if (type == "cube") { thisOverlay = new Cube3DOverlay(); } else if (type == "sphere") { From 1b9565e575ea68ae53d9a32ef4b7db38e9aab2d5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Oct 2014 08:25:04 -0700 Subject: [PATCH 16/29] cleanup --- interface/src/ui/overlays/Text3DOverlay.cpp | 27 +++++++-------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index de72ed2692..569179b86c 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -109,32 +109,23 @@ void Text3DOverlay::render() { (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); glScalef(scaleFactor, -scaleFactor, 1.0); - int x = 0; - int y = 0; - - bool wantClipping = true; - - if (wantClipping) { - enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); - enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); - enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); - enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); - } + enableClipPlane(GL_CLIP_PLANE0, -1.0f, 0.0f, 0.0f, clipMinimum.x + clipDimensions.x); + enableClipPlane(GL_CLIP_PLANE1, 1.0f, 0.0f, 0.0f, -clipMinimum.x); + enableClipPlane(GL_CLIP_PLANE2, 0.0f, -1.0f, 0.0f, clipMinimum.y + clipDimensions.y); + enableClipPlane(GL_CLIP_PLANE3, 0.0f, 1.0f, 0.0f, -clipMinimum.y); glColor3f(_color.red / MAX_COLOR, _color.green / MAX_COLOR, _color.blue / MAX_COLOR); QStringList lines = _text.split("\n"); int lineOffset = maxHeight; foreach(QString thisLine, lines) { - textRenderer->draw(x, y + lineOffset, qPrintable(thisLine)); + textRenderer->draw(0, lineOffset, qPrintable(thisLine)); lineOffset += maxHeight; } - if (wantClipping) { - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); - } + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); } glPopMatrix(); From 00dbe486d9339de11c00a51425081dfea97bae69 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 21 Oct 2014 10:50:53 -0700 Subject: [PATCH 17/29] FIrst working version of the GLBatching system introduced in the MOdelrendering path --- interface/src/gpu/Batch.cpp | 843 ++++++++++++++++++------------- interface/src/gpu/Batch.h | 164 ++++-- interface/src/renderer/Model.cpp | 66 ++- 3 files changed, 659 insertions(+), 414 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 43c6872072..9458dc8a3f 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -12,14 +12,21 @@ #include -#define DO_IT_NOW(call, offset) int param = _params.size() - (offset); do##call(param); +#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); + +//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); do##call(__param); +//#define DO_IT_NOW(call, offset) uint32 __param = _commandOffsets.back(); CommandCall call = _commandCalls.back(); (this->*(call))(__param); +//#define DO_IT_NOW(call, offset) runLastCommand(); +//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); runCommand(_commands.size() -1);// do##call(__param); +#define DO_IT_NOW(call, offset) using namespace gpu; Batch::Batch() : _commands(), _params(), - _resources(){ + _resources(), + _data(){ } Batch::~Batch() { @@ -29,24 +36,99 @@ void Batch::clear() { _commands.clear(); _params.clear(); _resources.clear(); + _data.clear(); +} + +uint32 Batch::cacheResource(Resource* res) { + uint32 offset = _resources.size(); + _resources.push_back(ResourceCache(res)); + + return offset; +} + +uint32 Batch::cacheResource(const void* pointer) { + uint32 offset = _resources.size(); + _resources.push_back(ResourceCache(pointer)); + + return offset; +} + +uint32 Batch::cacheData(uint32 size, const void* data) { + uint32 offset = _data.size(); + uint32 nbBytes = size; + _data.resize(offset + nbBytes); + memcpy(_data.data() + offset, data, size); + + return offset; +} + +#define CASE_COMMAND(call) case COMMAND_##call: { do_##call(offset); } break; + +void Batch::runCommand(Command com, uint32 offset) { + switch (com) { + CASE_COMMAND(draw); + CASE_COMMAND(drawIndexed); + CASE_COMMAND(drawInstanced); + CASE_COMMAND(drawIndexedInstanced); + CASE_COMMAND(glEnable); + CASE_COMMAND(glDisable); + CASE_COMMAND(glEnableClientState); + CASE_COMMAND(glDisableClientState); + CASE_COMMAND(glCullFace); + CASE_COMMAND(glAlphaFunc); + CASE_COMMAND(glDepthFunc); + CASE_COMMAND(glDepthMask); + CASE_COMMAND(glDepthRange); + CASE_COMMAND(glBindBuffer); + CASE_COMMAND(glBindTexture); + CASE_COMMAND(glActiveTexture); + CASE_COMMAND(glDrawBuffers); + CASE_COMMAND(glUseProgram); + CASE_COMMAND(glUniform1f); + CASE_COMMAND(glUniformMatrix4fv); + CASE_COMMAND(glMatrixMode); + CASE_COMMAND(glPushMatrix); + CASE_COMMAND(glPopMatrix); + CASE_COMMAND(glMultMatrixf); + CASE_COMMAND(glLoadMatrixf); + CASE_COMMAND(glLoadIdentity); + CASE_COMMAND(glRotatef); + CASE_COMMAND(glScalef); + CASE_COMMAND(glTranslatef); + CASE_COMMAND(glDrawArrays); + CASE_COMMAND(glDrawRangeElements); + CASE_COMMAND(glColorPointer); + CASE_COMMAND(glNormalPointer); + CASE_COMMAND(glTexCoordPointer); + CASE_COMMAND(glVertexPointer); + CASE_COMMAND(glVertexAttribPointer); + CASE_COMMAND(glEnableVertexAttribArray); + CASE_COMMAND(glDisableVertexAttribArray); + CASE_COMMAND(glColor4f); + CASE_COMMAND(glMaterialf); + CASE_COMMAND(glMaterialfv); + } } void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { - _commands.push_back(COMMAND_DRAW); + ADD_COMMAND(draw); + _params.push_back(startVertex); _params.push_back(nbVertices); _params.push_back(primitiveType); } void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) { - _commands.push_back(COMMAND_DRAW_INDEXED); + ADD_COMMAND(drawIndexed); + _params.push_back(startIndex); _params.push_back(nbIndices); _params.push_back(primitiveType); } void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { - _commands.push_back(COMMAND_DRAW_INSTANCED); + ADD_COMMAND(drawInstanced); + _params.push_back(startInstance); _params.push_back(startVertex); _params.push_back(nbVertices); @@ -55,7 +137,8 @@ void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVe } void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { - _commands.push_back(COMMAND_DRAW_INDEXED_INSTANCED); + ADD_COMMAND(drawIndexedInstanced); + _params.push_back(startInstance); _params.push_back(startIndex); _params.push_back(nbIndices); @@ -67,402 +150,474 @@ void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, i // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API -void Batch::_glEnable(GLenum cap) { - _commands.push_back(COMMAND_glEnable); - _params.push_back(cap); - - DO_IT_NOW(_glEnable, 1); -} -void Batch::do_glEnable(int ¶mOffset) { - glEnable(_params[paramOffset++]._uint); -} - -void Batch::_glDisable(GLenum cap) { - _commands.push_back(COMMAND_glDisable); - _params.push_back(cap); - - DO_IT_NOW(_glDisable, 1); -} -void Batch::do_glDisable(int ¶mOffset) { - glDisable(_params[paramOffset++]._uint); -} - -void Batch::_glEnableClientState(GLenum array) { - _commands.push_back(COMMAND_glEnableClientState); - _params.push_back(array); - - DO_IT_NOW(_glEnableClientState, 1 ); -} -void Batch::do_glEnableClientState(int ¶mOffset) { - glEnableClientState(_params[paramOffset++]._uint); -} +void Batch::_glEnable(GLenum cap) { + ADD_COMMAND(glEnable); -void Batch::_glDisableClientState(GLenum array) { - _commands.push_back(COMMAND_glDisableClientState); - _params.push_back(array); - - DO_IT_NOW(_glDisableClientState, 1); + _params.push_back(cap); + + DO_IT_NOW(_glEnable, 1); } -void Batch::do_glDisableClientState(int ¶mOffset) { +void Batch::do_glEnable(uint32& paramOffset) { + glEnable(_params[paramOffset++]._uint); +} + +void Batch::_glDisable(GLenum cap) { + ADD_COMMAND(glDisable); + + _params.push_back(cap); + + DO_IT_NOW(_glDisable, 1); +} +void Batch::do_glDisable(uint32& paramOffset) { + glDisable(_params[paramOffset++]._uint); +} + +void Batch::_glEnableClientState(GLenum array) { + ADD_COMMAND(glEnableClientState); + + _params.push_back(array); + + DO_IT_NOW(_glEnableClientState, 1 ); +} +void Batch::do_glEnableClientState(uint32& paramOffset) { + glEnableClientState(_params[paramOffset++]._uint); +} + +void Batch::_glDisableClientState(GLenum array) { + ADD_COMMAND(glDisableClientState); + + _params.push_back(array); + + DO_IT_NOW(_glDisableClientState, 1); +} +void Batch::do_glDisableClientState(uint32& paramOffset) { glDisableClientState(_params[paramOffset++]._uint); } -void Batch::_glCullFace(GLenum mode) { - _commands.push_back(COMMAND_glCullFace); - _params.push_back(mode); - - DO_IT_NOW(_glCullFace, 1); +void Batch::_glCullFace(GLenum mode) { + ADD_COMMAND(glCullFace); + + _params.push_back(mode); + + DO_IT_NOW(_glCullFace, 1); } -void Batch::do_glCullFace(int ¶mOffset) { +void Batch::do_glCullFace(uint32& paramOffset) { glCullFace(_params[paramOffset++]._uint); } -void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { - _commands.push_back(COMMAND_glAlphaFunc); - _params.push_back(ref); - _params.push_back(func); - - DO_IT_NOW(_glAlphaFunc, 1); -} -void Batch::do_glAlphaFunc(int ¶mOffset) { - glAlphaFunc(_params[paramOffset++]._uint, _params[paramOffset++]._float); -} +void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { + ADD_COMMAND(glAlphaFunc); -void Batch::_glDepthFunc(GLenum func) { - _commands.push_back(COMMAND_glDepthFunc); - _params.push_back(func); - - DO_IT_NOW(_glDepthFunc, 1); -} -void Batch::do_glDepthFunc(int ¶mOffset) { + _params.push_back(ref); + _params.push_back(func); + + DO_IT_NOW(_glAlphaFunc, 2); +} +void Batch::do_glAlphaFunc(uint32& paramOffset) { + glAlphaFunc(_params[paramOffset++]._uint, _params[paramOffset++]._float); +} + +void Batch::_glDepthFunc(GLenum func) { + ADD_COMMAND(glDepthFunc); + + _params.push_back(func); + + DO_IT_NOW(_glDepthFunc, 1); +} +void Batch::do_glDepthFunc(uint32& paramOffset) { glDepthFunc(_params[paramOffset++]._uint); -} - -void Batch::_glDepthMask(GLboolean flag) { - _commands.push_back(COMMAND_glDepthMask); - _params.push_back(flag); - - DO_IT_NOW(_glDepthMask, 1); -} -void Batch::do_glDepthMask(int ¶mOffset) { +} + +void Batch::_glDepthMask(GLboolean flag) { + ADD_COMMAND(glDepthMask); + + _params.push_back(flag); + + DO_IT_NOW(_glDepthMask, 1); +} +void Batch::do_glDepthMask(uint32& paramOffset) { glDepthMask(_params[paramOffset++]._uint); -} - -void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { - _commands.push_back(COMMAND_glDepthRange); - _params.push_back(zFar); - _params.push_back(zNear); - - DO_IT_NOW(_glDepthRange, 2); -} -void Batch::do_glDepthRange(int ¶mOffset) { +} + +void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { + ADD_COMMAND(glDepthRange); + + _params.push_back(zFar); + _params.push_back(zNear); + + DO_IT_NOW(_glDepthRange, 2); +} +void Batch::do_glDepthRange(uint32& paramOffset) { glDepthRange(_params[paramOffset++]._double, _params[paramOffset++]._double); } -void Batch::_glBindBuffer(GLenum target, GLuint buffer) { - _commands.push_back(COMMAND_glBindBuffer); - _params.push_back(buffer); - _params.push_back(target); - - DO_IT_NOW(_glBindBuffer, 2); -} -void Batch::do_glBindBuffer(int ¶mOffset) { +void Batch::_glBindBuffer(GLenum target, GLuint buffer) { + ADD_COMMAND(glBindBuffer); + + _params.push_back(buffer); + _params.push_back(target); + + DO_IT_NOW(_glBindBuffer, 2); +} +void Batch::do_glBindBuffer(uint32& paramOffset) { glBindBuffer(_params[paramOffset++]._uint, _params[paramOffset++]._uint); } -void Batch::_glBindTexture(GLenum target, GLuint texture) { - _commands.push_back(COMMAND_glBindTexture); - _params.push_back(texture); - _params.push_back(target); - - DO_IT_NOW(_glBindTexture, 2); -} -void Batch::do_glBindTexture(int ¶mOffset) { +void Batch::_glBindTexture(GLenum target, GLuint texture) { + ADD_COMMAND(glBindTexture); + + _params.push_back(texture); + _params.push_back(target); + + DO_IT_NOW(_glBindTexture, 2); +} +void Batch::do_glBindTexture(uint32& paramOffset) { glBindTexture(_params[paramOffset++]._uint, _params[paramOffset++]._uint); } -void Batch::_glActiveTexture(GLenum texture) { - _commands.push_back(COMMAND_glActiveTexture); - _params.push_back(texture); - - DO_IT_NOW(_glActiveTexture, 1); -} -void Batch::do_glActiveTexture(int ¶mOffset) { +void Batch::_glActiveTexture(GLenum texture) { + ADD_COMMAND(glActiveTexture); + + _params.push_back(texture); + + DO_IT_NOW(_glActiveTexture, 1); +} +void Batch::do_glActiveTexture(uint32& paramOffset) { glActiveTexture(_params[paramOffset++]._uint); } -void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { - _commands.push_back(COMMAND_glDrawBuffers); - _params.push_back(bufs); - _params.push_back(n); - - DO_IT_NOW(_glDrawBuffers, 2); -} -void Batch::do_glDrawBuffers(int ¶mOffset) { - glDrawBuffers(_params[paramOffset++]._uint, (const GLenum*) _params[paramOffset++]._constPointer); +void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { + ADD_COMMAND(glDrawBuffers); + + _params.push_back(cacheData(n * sizeof(GLenum), bufs)); + _params.push_back(n); + + DO_IT_NOW(_glDrawBuffers, 2); +} +void Batch::do_glDrawBuffers(uint32& paramOffset) { + glDrawBuffers(_params[paramOffset++]._uint, (const GLenum*) editData(_params[paramOffset++]._uint)); } -void Batch::_glUseProgram(GLuint program) { - _commands.push_back(COMMAND_glUseProgram); - _params.push_back(program); - - DO_IT_NOW(_glUseProgram, 1); -} -void Batch::do_glUseProgram(int ¶mOffset) { +void Batch::_glUseProgram(GLuint program) { + ADD_COMMAND(glUseProgram); + + _params.push_back(program); + + DO_IT_NOW(_glUseProgram, 1); +} +void Batch::do_glUseProgram(uint32& paramOffset) { glUseProgram(_params[paramOffset++]._uint); } - -void Batch::_glUniform1f(GLint location, GLfloat v0) { - _commands.push_back(COMMAND_glUniform1f); - _params.push_back(v0); - _params.push_back(location); - - DO_IT_NOW(_glUniform1f, 1); -} -void Batch::do_glUniform1f(int ¶mOffset) { - glUniform1f(_params[paramOffset++]._float); + +void Batch::_glUniform1f(GLint location, GLfloat v0) { + ADD_COMMAND(glUniform1f); + + _params.push_back(v0); + _params.push_back(location); + + DO_IT_NOW(_glUniform1f, 1); +} +void Batch::do_glUniform1f(uint32& paramOffset) { + glUniform1f(_params[paramOffset++]._int, _params[paramOffset++]._float); } -void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - _commands.push_back(COMMAND_glUniformMatrix4fv); - _params.push_back(value); - _params.push_back(transpose); - _params.push_back(count); - _params.push_back(location); - - DO_IT_NOW(_glUniformMatrix4fv, 4); -} -void Batch::do_glUniformMatrix4fv(int ¶mOffset) { - glUniformMatrix4fv(_params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._constPointer); +void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { + ADD_COMMAND(glUniformMatrix4fv); + + const int MATRIX4_SIZE = 16 * sizeof(float); + _params.push_back(cacheData(count * MATRIX4_SIZE, value)); + _params.push_back(transpose); + _params.push_back(count); + _params.push_back(location); + + DO_IT_NOW(_glUniformMatrix4fv, 4); +} +void Batch::do_glUniformMatrix4fv(uint32& paramOffset) { + glUniformMatrix4fv(_params[paramOffset++]._int, _params[paramOffset++]._uint, + _params[paramOffset++]._uint, (const GLfloat*) editData(_params[paramOffset++]._uint)); } -void Batch::_glMatrixMode(GLenum mode) { - _commands.push_back(COMMAND_glMatrixMode); - _params.push_back(mode); - - DO_IT_NOW(_glMatrixMode, 1); -} -void Batch::do_glMatrixMode(int ¶mOffset) { +void Batch::_glMatrixMode(GLenum mode) { + ADD_COMMAND(glMatrixMode); + + _params.push_back(mode); + + DO_IT_NOW(_glMatrixMode, 1); +} +void Batch::do_glMatrixMode(uint32& paramOffset) { glMatrixMode(_params[paramOffset++]._uint); } -void Batch::_glPushMatrix() { - _commands.push_back(COMMAND_glPushMatrix); - - DO_IT_NOW(_glPushMatrix, 0); -} -void Batch::do_glPushMatrix(int ¶mOffset) { +void Batch::_glPushMatrix() { + ADD_COMMAND(glPushMatrix); + + DO_IT_NOW(_glPushMatrix, 0); +} +void Batch::do_glPushMatrix(uint32& paramOffset) { glPushMatrix(); } -void Batch::_glPopMatrix() { - _commands.push_back(COMMAND_glPopMatrix); +void Batch::_glPopMatrix() { + ADD_COMMAND(glPopMatrix); DO_IT_NOW(_glPopMatrix, 0); -} -void Batch::do_glPopMatrix(int ¶mOffset) { +} +void Batch::do_glPopMatrix(uint32& paramOffset) { glPopMatrix(); } -void Batch::_glMultMatrixf(const GLfloat *m) { - _commands.push_back(COMMAND_glMultMatrixf); - _params.push_back(m); - +void Batch::_glMultMatrixf(const GLfloat *m) { + ADD_COMMAND(glMultMatrixf); + + const int MATRIX4_SIZE = 16 * sizeof(float); + _params.push_back(cacheData(MATRIX4_SIZE, m)); + DO_IT_NOW(_glMultMatrixf, 1); -} -void Batch::do_glMultMatrixf(int ¶mOffset) { - glMultMatrixf((const GLfloat*) _params[paramOffset++]._constPointer); +} +void Batch::do_glMultMatrixf(uint32& paramOffset) { + glMultMatrixf((const GLfloat*) editData(_params[paramOffset++]._uint)); } -void Batch::_glLoadMatrixf(const GLfloat *m) { - _commands.push_back(COMMAND_glLoadMatrixf); - _params.push_back(m); +void Batch::_glLoadMatrixf(const GLfloat *m) { + ADD_COMMAND(glLoadMatrixf); - DO_IT_NOW(_glLoadMatrixf, 1); -} -void Batch::do_glLoadMatrixf(int ¶mOffset) { - glLoadMatrixf((const GLfloat*)_params[paramOffset++]._constPointer); -} - -void Batch::_glLoadIdentity(void) { - _commands.push_back(COMMAND_glLoadIdentity); - - DO_IT_NOW(_glLoadIdentity, 0); -} -void Batch::do_glLoadIdentity(int ¶mOffset) { + const int MATRIX4_SIZE = 16 * sizeof(float); + _params.push_back(cacheData(MATRIX4_SIZE, m)); + + DO_IT_NOW(_glLoadMatrixf, 1); +} +void Batch::do_glLoadMatrixf(uint32& paramOffset) { + glLoadMatrixf((const GLfloat*)editData(_params[paramOffset++]._uint)); +} + +void Batch::_glLoadIdentity(void) { + ADD_COMMAND(glLoadIdentity); + + DO_IT_NOW(_glLoadIdentity, 0); +} +void Batch::do_glLoadIdentity(uint32& paramOffset) { glLoadIdentity(); -} - -void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - _commands.push_back(COMMAND_glRotatef); - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - _params.push_back(angle); - - DO_IT_NOW(_glRotatef, 4); -} -void Batch::do_glRotatef(int ¶mOffset) { +} + +void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + ADD_COMMAND(glRotatef); + + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + _params.push_back(angle); + + DO_IT_NOW(_glRotatef, 4); +} +void Batch::do_glRotatef(uint32& paramOffset) { glRotatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) { - _commands.push_back(COMMAND_glScalef); - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - - DO_IT_NOW(_glScalef, 3); -} -void Batch::do_glScalef(int ¶mOffset) { +} + +void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) { + ADD_COMMAND(glScalef); + + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + + DO_IT_NOW(_glScalef, 3); +} +void Batch::do_glScalef(uint32& paramOffset) { glScalef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) { - _commands.push_back(COMMAND_glTranslatef); - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - - DO_IT_NOW(_glTranslatef, 3); -} -void Batch::do_glTranslatef(int ¶mOffset) { +} + +void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) { + ADD_COMMAND(glTranslatef); + + _params.push_back(z); + _params.push_back(y); + _params.push_back(x); + + DO_IT_NOW(_glTranslatef, 3); +} +void Batch::do_glTranslatef(uint32& paramOffset) { glTranslatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { - _commands.push_back(COMMAND_glDrawArrays); - _params.push_back(count); - _params.push_back(first); - _params.push_back(mode); - - DO_IT_NOW(_glDrawArrays, 3); -} -void Batch::do_glDrawArrays(int ¶mOffset) { +} + +void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { + ADD_COMMAND(glDrawArrays); + + _params.push_back(count); + _params.push_back(first); + _params.push_back(mode); + + DO_IT_NOW(_glDrawArrays, 3); +} +void Batch::do_glDrawArrays(uint32& paramOffset) { glDrawArrays(_params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._int); -} - -void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { - _commands.push_back(COMMAND_glDrawRangeElements); - _params.push_back(indices); - _params.push_back(type); - _params.push_back(count); - _params.push_back(end); - _params.push_back(start); - _params.push_back(mode); - - DO_IT_NOW(_glDrawRangeElements, 6); -} -void Batch::do_glDrawRangeElements(int ¶mOffset) { - glDrawRangeElements(_params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._constPointer); -} - -void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - _commands.push_back(COMMAND_glColorPointer); - _params.push_back(pointer); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glColorPointer, 4); -} -void Batch::do_glColorPointer(int ¶mOffset) { - glColorPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._constPointer); -} - -void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { - _commands.push_back(COMMAND_glNormalPointer); - _params.push_back(pointer); - _params.push_back(stride); - _params.push_back(type); - - DO_IT_NOW(_glNormalPointer, 4); -} -void Batch::do_glNormalPointer(int ¶mOffset) { - glNormalPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._constPointer); -} - -void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - _commands.push_back(COMMAND_glTexCoordPointer); - _params.push_back(pointer); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); -} - -void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - _commands.push_back(COMMAND_glVertexPointer); - _params.push_back(pointer); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); +} + +void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { + ADD_COMMAND(glDrawRangeElements); + + _params.push_back(cacheResource(indices)); + _params.push_back(type); + _params.push_back(count); + _params.push_back(end); + _params.push_back(start); + _params.push_back(mode); + + //do_glDrawRangeElements(_commandOffsets.back()); + // runCommand(_commands.size() - 1); + DO_IT_NOW(_glDrawRangeElements, 6); +} +void Batch::do_glDrawRangeElements(uint32& paramOffset) { + glDrawRangeElements(_params[paramOffset++]._uint, _params[paramOffset++]._uint, + _params[paramOffset++]._uint, _params[paramOffset++]._int, + _params[paramOffset++]._uint, editResource(_params[paramOffset++]._uint)->_pointer); +} + +void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + ADD_COMMAND(glColorPointer); + + _params.push_back(cacheResource(pointer)); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); + + DO_IT_NOW(_glColorPointer, 4); +} +void Batch::do_glColorPointer(uint32& paramOffset) { + glColorPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, + _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); +} + +void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { + ADD_COMMAND(glNormalPointer); + + _params.push_back(cacheResource(pointer)); + _params.push_back(stride); + _params.push_back(type); + + DO_IT_NOW(_glNormalPointer, 3); +} +void Batch::do_glNormalPointer(uint32& paramOffset) { + glNormalPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, + editResource(_params[paramOffset++]._uint)->_pointer); +} + +void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + ADD_COMMAND(glTexCoordPointer); + + _params.push_back(cacheResource(pointer)); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); + + DO_IT_NOW(_glTexCoordPointer, 4); +} +void Batch::do_glTexCoordPointer(uint32& paramOffset) { + glTexCoordPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, + _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); +} + +void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { + ADD_COMMAND(glVertexPointer); + + _params.push_back(cacheResource(pointer)); + _params.push_back(stride); + _params.push_back(type); + _params.push_back(size); + + DO_IT_NOW(_glVertexPointer, 4); +} +void Batch::do_glVertexPointer(uint32& paramOffset) { + glVertexPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, + _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); } -void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { - _commands.push_back(COMMAND_glVertexPointer); - _params.push_back(pointer); - _params.push_back(stride); - _params.push_back(normalized); - _params.push_back(type); - _params.push_back(size); - _params.push_back(index); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); -} +void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { + ADD_COMMAND(glVertexAttribPointer); -void Batch::_glEnableVertexArrayAttrib(GLint location) { - _commands.push_back(COMMAND_glEnableVertexArrayAttrib); - _params.push_back(location); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); -} + _params.push_back(cacheResource(pointer)); + _params.push_back(stride); + _params.push_back(normalized); + _params.push_back(type); + _params.push_back(size); + _params.push_back(index); -void Batch::_glDisableVertexArrayAttrib(GLint location) { - _commands.push_back(COMMAND_glDisableVertexArrayAttrib); - _params.push_back(location); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); + DO_IT_NOW(_glVertexAttribPointer, 6); } - -void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - _commands.push_back(COMMAND_glColor4f); - _params.push_back(alpha); - _params.push_back(blue); - _params.push_back(green); - _params.push_back(red); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); -} - -void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { - _commands.push_back(COMMAND_glMaterialf); - _params.push_back(param); - _params.push_back(pname); - _params.push_back(face); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); -} - -void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { - _commands.push_back(COMMAND_glMaterialfv); - _params.push_back(params); - _params.push_back(pname); - _params.push_back(face); -} -void Batch::do_glCullFace(int ¶mOffset) { - glCullFace(_params[paramOffset++]._uint); +void Batch::do_glVertexAttribPointer(uint32& paramOffset) { + glVertexAttribPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, + _params[paramOffset++]._uint, _params[paramOffset++]._uint, + _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); } + +void Batch::_glEnableVertexAttribArray(GLint location) { + ADD_COMMAND(glEnableVertexAttribArray); + + _params.push_back(location); + + DO_IT_NOW(_glEnableVertexAttribArray, 1); +} +void Batch::do_glEnableVertexAttribArray(uint32& paramOffset) { + glEnableVertexAttribArray(_params[paramOffset++]._uint); +} + +void Batch::_glDisableVertexAttribArray(GLint location) { + ADD_COMMAND(glDisableVertexAttribArray); + + _params.push_back(location); + + DO_IT_NOW(_glDisableVertexAttribArray, 1); +} +void Batch::do_glDisableVertexAttribArray(uint32& paramOffset) { + glDisableVertexAttribArray(_params[paramOffset++]._uint); +} + +void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + ADD_COMMAND(glColor4f); + + _params.push_back(alpha); + _params.push_back(blue); + _params.push_back(green); + _params.push_back(red); + + DO_IT_NOW(_glColor4f, 4); +} +void Batch::do_glColor4f(uint32& paramOffset) { + glColor4f(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); +} + +void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { + ADD_COMMAND(glMaterialf); + + _params.push_back(param); + _params.push_back(pname); + _params.push_back(face); + + DO_IT_NOW(_glMaterialf, 3); +} +void Batch::do_glMaterialf(uint32& paramOffset) { + glMaterialf(_params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._float); +} + +void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { + ADD_COMMAND(glMaterialfv); + + _params.push_back(cacheData(4 * sizeof(float), params)); + _params.push_back(pname); + _params.push_back(face); + + DO_IT_NOW(_glMaterialfv, 3); +} +void Batch::do_glMaterialfv(uint32& paramOffset) { + glMaterialfv(_params[paramOffset++]._uint, _params[paramOffset++]._uint, (const GLfloat*) editData(_params[paramOffset++]._uint)); +} + + + +void backend::renderBatch(Batch& batch) { + for (int i = 0; i < batch._commands.size(); i++) { + batch.runCommand(i); + } +} \ No newline at end of file diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index a03c4ac1b7..815a7f61f2 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -18,6 +18,13 @@ namespace gpu { +class Batch; +// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience +namespace backend { + + void renderBatch(Batch& batch); +}; + class Buffer; class Resource; typedef int Stamp; @@ -98,21 +105,22 @@ public: void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); - void _glEnableVertexArrayAttrib(GLint location); - void _glDisableVertexArrayAttrib(GLint location); + void _glEnableVertexAttribArray(GLint location); + void _glDisableVertexAttribArray(GLint location); void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); void _glMaterialf(GLenum face, GLenum pname, GLfloat param); void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); + protected: enum Command { - COMMAND_DRAW = 0, - COMMAND_DRAW_INDEXED, - COMMAND_DRAW_INSTANCED, - COMMAND_DRAW_INDEXED_INSTANCED, + COMMAND_draw = 0, + COMMAND_drawIndexed, + COMMAND_drawInstanced, + COMMAND_drawIndexedInstanced, COMMAND_SET_PIPE_STATE, COMMAND_SET_VIEWPORT, @@ -167,8 +175,8 @@ protected: COMMAND_glVertexPointer, COMMAND_glVertexAttribPointer, - COMMAND_glEnableVertexArrayAttrib, - COMMAND_glDisableVertexArrayAttrib, + COMMAND_glEnableVertexAttribArray, + COMMAND_glDisableVertexAttribArray, COMMAND_glColor4f, @@ -176,6 +184,10 @@ protected: COMMAND_glMaterialfv, }; typedef std::vector Commands; + typedef void (Batch::*CommandCall)(uint32&); + typedef std::vector CommandCalls; + typedef std::vector CommandOffsets; + class Param { public: @@ -184,80 +196,136 @@ protected: uint32 _uint; float _float; char _chars[4]; - const void* _constPointer; double _double; }; Param(int32 val) : _int(val) {} Param(uint32 val) : _uint(val) {} Param(float val) : _float(val) {} - Param(const void* val) : _constPointer(val) {} Param(double val) : _double(val) {} }; typedef std::vector Params; class ResourceCache { public: - Resource* _resource; + union { + Resource* _resource; + const void* _pointer; + }; + ResourceCache(Resource* res) : _resource(res) {} + ResourceCache(const void* pointer) : _pointer(pointer) {} }; typedef std::vector Resources; + typedef unsigned char Byte; + typedef std::vector Bytes; + Commands _commands; + CommandCalls _commandCalls; + CommandOffsets _commandOffsets; Params _params; Resources _resources; + Bytes _data; + + + uint32 cacheResource(Resource* res); + uint32 cacheResource(const void* pointer); + ResourceCache* editResource(uint32 offset) { + if (offset >= _resources.size()) + return 0; + return (_resources.data() + offset); + } + + uint32 cacheData(uint32 size, const void* data); + Byte* editData(uint32 offset) { + if (offset >= _data.size()) + return 0; + return (_data.data() + offset); + } + + void runCommand(uint32 index) { + uint32 offset = _commandOffsets[index]; + CommandCall call = _commandCalls[index]; + (this->*(call))(offset); + uint32 nextOFfset = offset; + + GLenum error = glGetError(); + if (error) { + error++; + } + } + + void runLastCommand() { + uint32 index = _commands.size() - 1; + uint32 offset = _commandOffsets[index]; + /* CommandCall call = _commandCalls[index]; + (this->*(call))(offset); + uint32 nextOFfset = offset; + */ + runCommand(_commands[index], offset); + } + + void runCommand(Command com, uint32 offset); + + void do_draw(uint32& paramOffset) {} + void do_drawIndexed(uint32& paramOffset) {} + void do_drawInstanced(uint32& paramOffset) {} + void do_drawIndexedInstanced(uint32& paramOffset) {} // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - void do_glEnable(int ¶mOffset); - void do_glDisable(int ¶mOffset); + void do_glEnable(uint32& paramOffset); + void do_glDisable(uint32& paramOffset); - void do_glEnableClientState(int ¶mOffset); - void do_glDisableClientState(int ¶mOffset); + void do_glEnableClientState(uint32& paramOffset); + void do_glDisableClientState(uint32& paramOffset); - void do_glCullFace(int ¶mOffset); - void do_glAlphaFunc(int ¶mOffset); + void do_glCullFace(uint32& paramOffset); + void do_glAlphaFunc(uint32& paramOffset); - void do_glDepthFunc(int ¶mOffset); - void do_glDepthMask(int ¶mOffset); - void do_glDepthRange(int ¶mOffset); + void do_glDepthFunc(uint32& paramOffset); + void do_glDepthMask(uint32& paramOffset); + void do_glDepthRange(uint32& paramOffset); - void do_glBindBuffer(int ¶mOffset); + void do_glBindBuffer(uint32& paramOffset); - void do_glBindTexture(int ¶mOffset); - void do_glActiveTexture(int ¶mOffset); + void do_glBindTexture(uint32& paramOffset); + void do_glActiveTexture(uint32& paramOffset); - void do_glDrawBuffers(int ¶mOffset); + void do_glDrawBuffers(uint32& paramOffset); - void do_glUseProgram(int ¶mOffset); - void do_glUniform1f(int ¶mOffset); - void do_glUniformMatrix4fv(int ¶mOffset); + void do_glUseProgram(uint32& paramOffset); + void do_glUniform1f(uint32& paramOffset); + void do_glUniformMatrix4fv(uint32& paramOffset); - void do_glMatrixMode(int ¶mOffset); - void do_glPushMatrix(int ¶mOffset); - void do_glPopMatrix(int ¶mOffset); - void do_glMultMatrixf(int ¶mOffset); - void do_glLoadMatrixf(int ¶mOffset); - void do_glLoadIdentity(int ¶mOffset); - void do_glRotatef(int ¶mOffset); - void do_glScalef(int ¶mOffset); - void do_glTranslatef(int ¶mOffset); + void do_glMatrixMode(uint32& paramOffset); + void do_glPushMatrix(uint32& paramOffset); + void do_glPopMatrix(uint32& paramOffset); + void do_glMultMatrixf(uint32& paramOffset); + void do_glLoadMatrixf(uint32& paramOffset); + void do_glLoadIdentity(uint32& paramOffset); + void do_glRotatef(uint32& paramOffset); + void do_glScalef(uint32& paramOffset); + void do_glTranslatef(uint32& paramOffset); - void do_glDrawArrays(int ¶mOffset); - void do_glDrawRangeElements(int ¶mOffset); + void do_glDrawArrays(uint32& paramOffset); + void do_glDrawRangeElements(uint32& paramOffset); - void do_glColorPointer(int ¶mOffset); - void do_glNormalPointer(int ¶mOffset); - void do_glTexCoordPointer(int ¶mOffset); - void do_glVertexPointer(int ¶mOffset); + void do_glColorPointer(uint32& paramOffset); + void do_glNormalPointer(uint32& paramOffset); + void do_glTexCoordPointer(uint32& paramOffset); + void do_glVertexPointer(uint32& paramOffset); - void do_glVertexAttribPointer(int ¶mOffset); - void do_glEnableVertexArrayAttrib(int ¶mOffset); - void do_glDisableVertexArrayAttrib(int ¶mOffset); + void do_glVertexAttribPointer(uint32& paramOffset); + void do_glEnableVertexAttribArray(uint32& paramOffset); + void do_glDisableVertexAttribArray(uint32& paramOffset); - void do_glColor4f(int ¶mOffset); + void do_glColor4f(uint32& paramOffset); - void do_glMaterialf(int ¶mOffset); - void do_glMaterialfv(int ¶mOffset); + void do_glMaterialf(uint32& paramOffset); + void do_glMaterialfv(uint32& paramOffset); + + friend void backend::renderBatch(Batch& batch); }; }; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6032ae4d69..765acdf797 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1609,18 +1609,28 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, ProgramObject* activeProgram = program; Locations* activeLocations = locations; - - if (isSkinned) { + + // Try to use the Batch + gpu::Batch batch; + + /*if (isSkinned) { skinProgram->bind(); activeProgram = skinProgram; activeLocations = skinLocations; } else { program->bind(); + }*/ + if (isSkinned) { + activeProgram = skinProgram; + activeLocations = skinLocations; } - activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); - - // Try to use the Batch - gpu::Batch batch; + if (!activeProgram->isLinked()) { + activeProgram->link(); + } + GLBATCH(glUseProgram)(activeProgram->programId()); + // activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); + GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); + // i is the "index" from the original networkMeshes QVector... @@ -1639,7 +1649,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, const FBXMesh& mesh = geometry.meshes.at(i); //const_cast(networkMesh.indexBuffer).bind(); - GLBATCH(glBindBuffer)( GL_INDEX_ARRAY, const_cast(networkMesh.indexBuffer).bufferId() ); + GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1674,8 +1684,9 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } } - const_cast(networkMesh.vertexBuffer).bind(); - + //const_cast(networkMesh.vertexBuffer).bind(); + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); + GLBATCH(glPushMatrix)(); //Application::getInstance()->loadTranslatedViewMatrix(_translation); GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); @@ -1690,19 +1701,25 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) + mesh.texCoords.size() * sizeof(glm::vec2) + (mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0); - skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); - skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, - offset + vertexCount * sizeof(glm::vec4), 4); - skinProgram->enableAttributeArray(skinLocations->clusterIndices); - skinProgram->enableAttributeArray(skinLocations->clusterWeights); + //skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); + GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, (const void*) offset); + //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, + // offset + vertexCount * sizeof(glm::vec4), 4); + GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); + //skinProgram->enableAttributeArray(skinLocations->clusterIndices); + GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); + //skinProgram->enableAttributeArray(skinLocations->clusterWeights); + GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); } else { GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); } if (mesh.blendshapes.isEmpty()) { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); - activeProgram->enableAttributeArray(activeLocations->tangent); + //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); + GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3))); + //activeProgram->enableAttributeArray(activeLocations->tangent); + GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); } GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + mesh.tangents.size() * sizeof(glm::vec3))); @@ -1711,12 +1728,15 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, } else { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); - activeProgram->enableAttributeArray(activeLocations->tangent); + //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); + GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0); + //activeProgram->enableAttributeArray(activeLocations->tangent); + GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); } GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - _blendedVertexBuffers[i].bind(); + // _blendedVertexBuffers[i].bind(); + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); } GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); @@ -1738,6 +1758,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); continue; } + // apply material properties if (mode == SHADOW_RENDER_MODE) { GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); @@ -1826,7 +1847,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, GLBATCH(glActiveTexture)(GL_TEXTURE0); // activeProgram->disableAttributeArray(activeLocations->tangent); - GLBATCH(glDisableVertexArrayAttrib)(activeLocations->tangent); + GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent); } if (specularTextureUnit) { @@ -1837,9 +1858,9 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, if (state.clusterMatrices.size() > 1) { // skinProgram->disableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glDisableVertexArrayAttrib)(skinLocations->clusterIndices); + GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices); // skinProgram->disableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glDisableVertexArrayAttrib)(skinLocations->clusterWeights); + GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights); } GLBATCH(glPopMatrix)(); @@ -1847,6 +1868,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, //activeProgram->release(); GLBATCH(glUseProgram)(0); + ::gpu::backend::renderBatch(batch); return meshPartsRendered; } From 2a5b2d86869939e4a4c7117dc75c8c851931a8cc Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 21 Oct 2014 11:40:16 -0700 Subject: [PATCH 18/29] Improved version of headMove with timed target reveal --- examples/headMove.js | 64 ++++++++++------------------ libraries/script-engine/src/Vec3.cpp | 4 ++ libraries/script-engine/src/Vec3.h | 1 + 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/examples/headMove.js b/examples/headMove.js index 3e856b6fa5..236130e23d 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -41,11 +41,7 @@ var warpLine = Overlays.addOverlay("line3d", { var movingWithHead = false; var headStartPosition, headStartDeltaPitch, headStartFinalPitch, headStartRoll, headStartYaw; -var timeSinceLastTurn = 0.0; -var timeSinceLastStep = 0.0; -var isTurning = false; var deltaYaw = 0.0; -var turnAmount = 0.0; var keyDownTime = 0.0; var watchAvatar = false; var oldMode; @@ -56,7 +52,6 @@ function saveCameraState() { } function restoreCameraState() { - //Camera.stopLooking(); Camera.setMode(oldMode); } @@ -67,8 +62,6 @@ function activateWarp() { updateWarp(); } -var WARP_PITCH_DEAD_ZONE = 4.0; -var WARP_SENSITIVITY = 0.35; var TRIGGER_PULLBACK_DISTANCE = 0.04; var WATCH_AVATAR_DISTANCE = 1.5; var MAX_WARP_YAW = 40.0; @@ -83,26 +76,32 @@ function playSound() { Audio.playSound(sound, options); } +var WARP_SMOOTHING = 0.90; +var WARP_START_TIME = 0.50; +var WARP_START_DISTANCE = 1.0; +var WARP_SENSITIVITY = 0.15; + function updateWarp() { if (!warpActive) return; var look = Quat.getFront(Camera.getOrientation()); var deltaPosition = Vec3.subtract(MyAvatar.getTrackedHeadPosition(), headStartPosition); - var deltaPitch = Math.abs(MyAvatar.getHeadFinalPitch() - headStartFinalPitch); + var deltaPitch = MyAvatar.getHeadFinalPitch() - headStartFinalPitch; deltaYaw = MyAvatar.getHeadFinalYaw() - headStartYaw; - willMove = (!watchAvatar && (Math.abs(deltaYaw) < MAX_WARP_YAW) && (deltaPitch > WARP_PITCH_DEAD_ZONE)); + willMove = (!watchAvatar && (Math.abs(deltaYaw) < MAX_WARP_YAW) && (keyDownTime > WARP_START_TIME)); if (willMove) { - var distance = Math.pow((deltaPitch - WARP_PITCH_DEAD_ZONE) * WARP_SENSITIVITY, 2.0); + //var distance = Math.pow((deltaPitch - WARP_PITCH_DEAD_ZONE) * WARP_SENSITIVITY, 2.0); + var distance = Math.exp(deltaPitch * WARP_SENSITIVITY) * WARP_START_DISTANCE; var warpDirection = Vec3.normalize({ x: look.x, y: 0, z: look.z }); - warpPosition = Vec3.multiply(warpDirection, distance); - warpPosition = Vec3.sum(MyAvatar.position, warpPosition); + warpPosition = Vec3.mix(Vec3.sum(MyAvatar.position, Vec3.multiply(warpDirection, distance)), warpPosition, WARP_SMOOTHING); } + var height = MyAvatar.getEyePosition().y - MyAvatar.position.y; + if (!watchAvatar && (Math.abs(deltaYaw) < MAX_PULLBACK_YAW) && (deltaPosition.z > TRIGGER_PULLBACK_DISTANCE)) { saveCameraState(); - var height = MyAvatar.getEyePosition().y - MyAvatar.position.y; var cameraPosition = Vec3.subtract(MyAvatar.position, Vec3.multiplyQbyV(Camera.getOrientation(), { x: 0, y: -height, z: -height * WATCH_AVATAR_DISTANCE })); Camera.setPosition(cameraPosition); watchAvatar = true; @@ -132,40 +131,15 @@ function finishWarp() { if (willMove) { MyAvatar.position = warpPosition; playSound(); - } else if (!watchAvatar) { - isTurning = true; - turnAmount = deltaYaw; - timeSinceLastTurn = TURN_INTERVAL; - playSound(); } } -var EPSILON_YAW = 180.0; -var TURN_INTERVAL = 0.175; - function update(deltaTime) { if (movingWithHead) { keyDownTime += deltaTime; updateWarp(); } - - if (isTurning) { - timeSinceLastTurn += deltaTime; - if (timeSinceLastTurn > TURN_INTERVAL) { - if (Math.abs(turnAmount) <= EPSILON_YAW) { - var thisTurn = turnAmount; - isTurning = false; - } else { - var thisTurn = turnAmount / 2.0; - turnAmount = turnAmount / 2.0; - } - var orientation = MyAvatar.orientation; - orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, thisTurn, 0), orientation) ; - MyAvatar.orientation = orientation; - timeSinceLastTurn = 0.0; - } - } } Controller.keyPressEvent.connect(function(event) { @@ -178,19 +152,25 @@ Controller.keyPressEvent.connect(function(event) { headStartRoll = MyAvatar.getHeadFinalRoll(); headStartYaw = MyAvatar.getHeadFinalYaw(); deltaYaw = 0.0; + warpPosition = MyAvatar.position; activateWarp(); } }); -var TIME_FOR_TURNAROUND = 0.15; +var TIME_FOR_TURN_AROUND = 0.50; +var TIME_FOR_TURN = 0.25; var TURN_AROUND = 180.0; Controller.keyReleaseEvent.connect(function(event) { if (event.text == "SPACE") { movingWithHead = false; - isTurning = false; - if (keyDownTime < TIME_FOR_TURNAROUND) { - MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, TURN_AROUND, 0), MyAvatar.orientation); + if (keyDownTime < TIME_FOR_TURN_AROUND) { + if (keyDownTime < TIME_FOR_TURN) { + var currentYaw = MyAvatar.getHeadFinalYaw(); + MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, currentYaw, 0), MyAvatar.orientation); + } else { + MyAvatar.orientation = Quat.multiply(Quat.fromPitchYawRollDegrees(0, TURN_AROUND, 0), MyAvatar.orientation); + } playSound(); } finishWarp(); diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index f88df3b7c0..bab63bbd4e 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -58,6 +58,10 @@ glm::vec3 Vec3::normalize(const glm::vec3& v) { return glm::normalize(v); } +glm::vec3 Vec3::mix(const glm::vec3& v1, const glm::vec3& v2, float m) { + return glm::mix(v1, v2, m); +} + void Vec3::print(const QString& lable, const glm::vec3& v) { qDebug() << qPrintable(lable) << v.x << "," << v.y << "," << v.z; } diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index 693fd604f7..3f7d5476a2 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -36,6 +36,7 @@ public slots: float distance(const glm::vec3& v1, const glm::vec3& v2); float orientedAngle(const glm::vec3& v1, const glm::vec3& v2, const glm::vec3& v3); glm::vec3 normalize(const glm::vec3& v); + glm::vec3 mix(const glm::vec3& v1, const glm::vec3& v2, float m); void print(const QString& lable, const glm::vec3& v); bool equal(const glm::vec3& v1, const glm::vec3& v2); }; From 02c6b5a8bfc09d9f81025d8a9dcadce11cc1f3ed Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 Oct 2014 12:16:55 -0700 Subject: [PATCH 19/29] Fix for send delay, delay ordering. --- interface/src/MetavoxelSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 97385a8671..e0794725cb 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -849,7 +849,7 @@ private: SendDelayer::SendDelayer(const SharedNodePointer& node, const QByteArray& data) : _node(node), - _data(data) { + _data(data.constData(), data.size()) { } void SendDelayer::timerEvent(QTimerEvent* event) { From 228de963ab6e387b74fc1dc7409504ef3f283354 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 21 Oct 2014 12:28:44 -0700 Subject: [PATCH 20/29] CR feedback --- interface/src/ui/overlays/Text3DOverlay.cpp | 6 ------ interface/src/ui/overlays/Text3DOverlay.h | 11 ----------- 2 files changed, 17 deletions(-) diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index 569179b86c..feb36943c3 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -11,9 +11,6 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include - #include "Application.h" #include "Text3DOverlay.h" #include "ui/TextRenderer.h" @@ -90,9 +87,6 @@ void Text3DOverlay::render() { glVertex3f(-halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); glEnd(); - //TextRenderer(const char* family, int pointSize = -1, int weight = -1, bool italic = false, - // EffectType effect = NO_EFFECT, int effectThickness = 1); - const int FIXED_FONT_POINT_SIZE = 40; const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 40.0f; // this is a ratio determined through experimentation diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index 35ca352891..855890e493 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -14,18 +14,7 @@ // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" -#include -#include -#include -#include -#include #include -#include - -#include - -//#include "Overlay.h" -//#include "Overlay3D.h" #include "Planar3DOverlay.h" class Text3DOverlay : public Planar3DOverlay { From d5c7c605537e30be54486797ed74d022afafb33c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 21 Oct 2014 12:13:12 -0700 Subject: [PATCH 21/29] Update entity edit tools Move editing functions into "tool" objects which contain onBegin, onMove, and onEnd functions. Add multi-selection Add local and world editing modes Fix XZ tool --- examples/libraries/entityCameraTool.js | 5 +- examples/libraries/entitySelectionTool.js | 2779 ++++++++++----------- examples/newEditEntities.js | 13 + 3 files changed, 1267 insertions(+), 1530 deletions(-) diff --git a/examples/libraries/entityCameraTool.js b/examples/libraries/entityCameraTool.js index 8e267e9544..63121d88a9 100644 --- a/examples/libraries/entityCameraTool.js +++ b/examples/libraries/entityCameraTool.js @@ -97,11 +97,12 @@ EntityCameraTool = function() { that.focus = function(entityProperties) { var dim = entityProperties.dimensions; + dim = SelectionManager.worldDimensions; var size = Math.max(dim.x, Math.max(dim.y, dim.z)); that.targetZoomDistance = Math.max(size * FOCUS_ZOOM_SCALE, FOCUS_MIN_ZOOM); - that.setFocalPoint(entityProperties.position); + that.setFocalPoint(SelectionManager.worldPosition);//entityProperties.position); that.updateCamera(); } @@ -184,7 +185,7 @@ EntityCameraTool = function() { // Scale based on current zoom level dZoom *= that.targetZoomDistance * ZOOM_SCALING; - that.targetZoomDistance = Math.max(Math.min(that.targetZoomDistance + dZoom, MAX_ZOOM_DISTANCE), MIN_ZOOM_DISTANCE); + that.targetZoomDistance = Math.max(that.targetZoomDistance + dZoom, MIN_ZOOM_DISTANCE); that.updateCamera(); } diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 5e344c9c8d..b70c2187c2 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -13,6 +13,124 @@ Script.include("libraries/globals.js"); +SPACE_LOCAL = "local"; +SPACE_WORLD = "world"; + +SelectionManager = (function() { + var that = {}; + + + that.savedProperties = {}; + + that.eventListener = null; + that.selections = []; + + that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); + that.localPosition = { x: 0, y: 0, z: 0 }; + that.localDimensions = { x: 0, y: 0, z: 0 }; + + that.worldRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); + that.worldPosition = { x: 0, y: 0, z: 0 }; + that.worldDimensions = { x: 0, y: 0, z: 0 }; + that.centerPosition = { x: 0, y: 0, z: 0 }; + + that.saveProperties = function() { + that.savedProperties = {}; + for (var i = 0; i < that.selections.length; i++) { + var entityID = that.selections[i]; + that.savedProperties[entityID.id] = Entities.getEntityProperties(entityID); + } + }; + + that.setEventListener = function(func) { + that.eventListener = func; + }; + + that.addEntity = function(entityID) { + print("Adding: " + entityID.id); + var idx = that.selections.indexOf(entityID); + if (idx == -1) { + that.selections.push(entityID); + } + + that._update(); + }; + + that.removeEntity = function(entityID) { + var idx = that.selections.indexOf(entityID); + if (idx >= 0) { + that.selections.splice(idx, 1); + } + + that._update(); + }; + + that.clearSelections = function() { + that.selections = []; + + that._update(); + }; + + that._update = function() { + if (that.selections.length == 0) { + that.localDimensions = null; + that.localPosition = null; + that.worldDimensions = null; + that.worldPosition = null; + } else if (that.selections.length == 1) { + var properties = Entities.getEntityProperties(that.selections[0]); + that.localDimensions = properties.dimensions; + that.localPosition = properties.position; + that.localRotation = properties.rotation; + + that.worldDimensions = properties.boundingBox.dimensions; + that.worldPosition = properties.boundingBox.center; + } else { + // For 1+ selections we can only modify selections in world space + SelectionDisplay.setSpaceMode(SPACE_WORLD); + + that.localRotation = null; + that.localDimensions = null; + that.localPosition = null; + + var properties = Entities.getEntityProperties(that.selections[0]); + + var brn = properties.boundingBox.brn; + var tfl = properties.boundingBox.tfl; + + for (var i = 1; i < that.selections.length; i++) { + properties = Entities.getEntityProperties(that.selections[i]); + var bb = properties.boundingBox; + brn.x = Math.min(bb.brn.x, brn.x); + brn.y = Math.min(bb.brn.y, brn.y); + brn.z = Math.min(bb.brn.z, brn.z); + tfl.x = Math.max(bb.tfl.x, tfl.x); + tfl.y = Math.max(bb.tfl.y, tfl.y); + tfl.z = Math.max(bb.tfl.z, tfl.z); + } + + that.localDimensions = null; + that.localPosition = null; + that.worldDimensions = { + x: tfl.x - brn.x, + y: tfl.y - brn.y, + z: tfl.z - brn.z + }; + that.worldPosition = { + x: brn.x + (that.worldDimensions.x / 2), + y: brn.y + (that.worldDimensions.y / 2), + z: brn.z + (that.worldDimensions.z / 2), + }; + } + + if (that.eventListener) { + that.eventListener(); + } + }; + + return that; +})(); + SelectionDisplay = (function () { var that = {}; @@ -20,6 +138,7 @@ SelectionDisplay = (function () { var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.015; + var spaceMode = SPACE_LOCAL; var mode = "UNKNOWN"; var overlayNames = new Array(); var lastCameraPosition = Camera.getPosition(); @@ -112,7 +231,6 @@ SelectionDisplay = (function () { lineWidth: grabberLineWidth, }; - var highlightBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, @@ -146,6 +264,15 @@ SelectionDisplay = (function () { scale: 0.1, isFacingAvatar: true }); + + // var normalLine = Overlays.addOverlay("line3d", { + // visible: true, + // lineWidth: 2.0, + // start: { x: 0, y: 0, z: 0 }, + // end: { x: 0, y: 0, z: 0 }, + // color: { red: 255, green: 255, blue: 0 }, + // ignoreRayIntersection: true, + // }); var grabberLBN = Overlays.addOverlay("cube", grabberPropertiesCorner); var grabberRBN = Overlays.addOverlay("cube", grabberPropertiesCorner); @@ -176,7 +303,7 @@ SelectionDisplay = (function () { var grabberEdgeFR = Overlays.addOverlay("cube", grabberPropertiesEdge); var grabberEdgeFL = Overlays.addOverlay("cube", grabberPropertiesEdge); - var cornerEdgeFaceGrabbers = [ + var stretchHandles = [ grabberLBN, grabberRBN, grabberLBF, @@ -205,6 +332,7 @@ SelectionDisplay = (function () { grabberEdgeFL, ]; + var baseOverlayAngles = { x: 0, y: 0, z: 0 }; var baseOverlayRotation = Quat.fromVec3Degrees(baseOverlayAngles); var baseOfEntityProjectionOverlay = Overlays.addOverlay("rectangle3d", { @@ -225,6 +353,34 @@ SelectionDisplay = (function () { var rollOverlayAngles = { x: 0, y: 180, z: 0 }; var rollOverlayRotation = Quat.fromVec3Degrees(rollOverlayAngles); + var xRailOverlay = Overlays.addOverlay("line3d", { + visible: false, + lineWidth: 1.0, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 255, green: 0, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + visible: false, + }); + var yRailOverlay = Overlays.addOverlay("line3d", { + visible: false, + lineWidth: 1.0, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 255, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + visible: false, + }); + var zRailOverlay = Overlays.addOverlay("line3d", { + visible: false, + lineWidth: 1.0, + start: { x: 0, y: 0, z: 0 }, + end: { x: 0, y: 0, z: 0 }, + color: { red: 0, green: 0, blue: 255 }, + ignoreRayIntersection: true, // always ignore this + visible: false, + }); + var rotateZeroOverlay = Overlays.addOverlay("line3d", { visible: false, lineWidth: 2.0, @@ -340,6 +496,24 @@ SelectionDisplay = (function () { isFacingAvatar: false }); + var allOverlays = [ + highlightBox, + selectionBox, + grabberMoveUp, + yawHandle, + pitchHandle, + rollHandle, + rotateOverlayTarget, + rotateOverlayInner, + rotateOverlayOuter, + rotateOverlayCurrent, + rotateZeroOverlay, + rotateCurrentOverlay, + xRailOverlay, + yRailOverlay, + zRailOverlay, + ].concat(stretchHandles); + overlayNames[highlightBox] = "highlightBox"; overlayNames[selectionBox] = "selectionBox"; overlayNames[baseOfEntityProjectionOverlay] = "baseOfEntityProjectionOverlay"; @@ -384,60 +558,33 @@ SelectionDisplay = (function () { overlayNames[rotateZeroOverlay] = "rotateZeroOverlay"; overlayNames[rotateCurrentOverlay] = "rotateCurrentOverlay"; + + var activeTool = null; + var grabberTools = {}; + function addGrabberTool(overlay, tool) { + grabberTools[overlay] = { + mode: tool.mode, + onBegin: tool.onBegin, + onMove: tool.onMove, + onEnd: tool.onEnd, + } + } + that.cleanup = function () { - Overlays.deleteOverlay(highlightBox); - Overlays.deleteOverlay(selectionBox); - Overlays.deleteOverlay(grabberMoveUp); - Overlays.deleteOverlay(baseOfEntityProjectionOverlay); - Overlays.deleteOverlay(grabberLBN); - Overlays.deleteOverlay(grabberLBF); - Overlays.deleteOverlay(grabberRBN); - Overlays.deleteOverlay(grabberRBF); - Overlays.deleteOverlay(grabberLTN); - Overlays.deleteOverlay(grabberLTF); - Overlays.deleteOverlay(grabberRTN); - Overlays.deleteOverlay(grabberRTF); - - Overlays.deleteOverlay(grabberTOP); - Overlays.deleteOverlay(grabberBOTTOM); - Overlays.deleteOverlay(grabberLEFT); - Overlays.deleteOverlay(grabberRIGHT); - Overlays.deleteOverlay(grabberNEAR); - Overlays.deleteOverlay(grabberFAR); - - Overlays.deleteOverlay(grabberEdgeTR); - Overlays.deleteOverlay(grabberEdgeTL); - Overlays.deleteOverlay(grabberEdgeTF); - Overlays.deleteOverlay(grabberEdgeTN); - Overlays.deleteOverlay(grabberEdgeBR); - Overlays.deleteOverlay(grabberEdgeBL); - Overlays.deleteOverlay(grabberEdgeBF); - Overlays.deleteOverlay(grabberEdgeBN); - Overlays.deleteOverlay(grabberEdgeNR); - Overlays.deleteOverlay(grabberEdgeNL); - Overlays.deleteOverlay(grabberEdgeFR); - Overlays.deleteOverlay(grabberEdgeFL); - - Overlays.deleteOverlay(yawHandle); - Overlays.deleteOverlay(pitchHandle); - Overlays.deleteOverlay(rollHandle); - - Overlays.deleteOverlay(rotateOverlayTarget); - Overlays.deleteOverlay(rotateOverlayInner); - Overlays.deleteOverlay(rotateOverlayOuter); - Overlays.deleteOverlay(rotateOverlayCurrent); - - Overlays.deleteOverlay(rotateZeroOverlay); - Overlays.deleteOverlay(rotateCurrentOverlay); - - + for (var i = 0; i < allOverlays.length; i++) { + Overlays.deleteOverlay(allOverlays[i]); + } }; that.highlightSelectable = function(entityID) { var properties = Entities.getEntityProperties(entityID); - Overlays.editOverlay(highlightBox, { visible: true, position: properties.boundingBox.center, - dimensions: properties.boundingBox.dimensions }); + Overlays.editOverlay(highlightBox, { + visible: true, + position: properties.boundingBox.center, + dimensions: properties.dimensions, + rotation: properties.rotation + }); }; that.unhighlightSelectable = function(entityID) { @@ -446,9 +593,9 @@ SelectionDisplay = (function () { that.select = function(entityID, event) { var properties = Entities.getEntityProperties(entityID); - if (currentSelection.isKnownID == true) { - that.unselect(currentSelection); - } + // if (currentSelection.isKnownID == true) { + // that.unselect(currentSelection); + // } currentSelection = entityID; entitySelected = true; @@ -493,26 +640,29 @@ SelectionDisplay = (function () { var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF; - objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z }; - - top = properties.boundingBox.tfl.y; - far = properties.boundingBox.tfl.z; - left = properties.boundingBox.tfl.x; + // objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z }; - bottom = properties.boundingBox.brn.y; - right = properties.boundingBox.brn.x; - near = properties.boundingBox.brn.z; + var dimensions; + if (spaceMode == SPACE_LOCAL) { + objectCenter = SelectionManager.localPosition; + dimensions = SelectionManager.localDimensions; + } else { + objectCenter = SelectionManager.worldPosition; + dimensions = SelectionManager.worldDimensions; + } + objectCenter = SelectionManager.worldPosition; + dimensions = SelectionManager.worldDimensions; - boundsCenter = { x: properties.boundingBox.center.x, y: properties.boundingBox.center.y, z: properties.boundingBox.center.z }; + top = objectCenter.y + (dimensions.y / 2); + far = objectCenter.z + (dimensions.z / 2); + left = objectCenter.x + (dimensions.x / 2); - BLN = { x: left, y: bottom, z: near }; - BRN = { x: right, y: bottom, z: near }; - BLF = { x: left, y: bottom, z: far }; - BRF = { x: right, y: bottom, z: far }; - TLN = { x: left, y: top, z: near }; - TRN = { x: right, y: top, z: near }; - TLF = { x: left, y: top, z: far }; - TRF = { x: right, y: top, z: far }; + bottom = objectCenter.y - (dimensions.y / 2); + near = objectCenter.z - (dimensions.z / 2); + right = objectCenter.x - (dimensions.x / 2); + + // boundsCenter = { x: properties.boundingBox.center.x, y: properties.boundingBox.center.y, z: properties.boundingBox.center.z }; + boundsCenter = objectCenter; var yawCorner; var pitchCorner; @@ -531,9 +681,10 @@ SelectionDisplay = (function () { ------------------------------*/ - if (MyAvatar.position.x > objectCenter.x) { + var cameraPosition = Camera.getPosition(); + if (cameraPosition.x > objectCenter.x) { // must be BRF or BRN - if (MyAvatar.position.z < objectCenter.z) { + if (cameraPosition.z < objectCenter.z) { yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 90, z: 0 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 90, z: 0 }); @@ -598,7 +749,7 @@ SelectionDisplay = (function () { } else { // must be BLF or BLN - if (MyAvatar.position.z < objectCenter.z) { + if (cameraPosition.z < objectCenter.z) { yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 180, z: 0 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 90, y: 0, z: 90 }); @@ -663,7 +814,7 @@ SelectionDisplay = (function () { var translateHandlesVisible = true; var stretchHandlesVisible = true; var selectionBoxVisible = true; - if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_XZ") { + if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_X in case they Z") { rotateHandlesVisible = false; translateHandlesVisible = false; stretchHandlesVisible = false; @@ -679,41 +830,20 @@ SelectionDisplay = (function () { Overlays.editOverlay(highlightBox, { visible: false }); - Overlays.editOverlay(selectionBox, { visible: selectionBoxVisible, position: properties.boundingBox.center, - dimensions: properties.boundingBox.dimensions }); - - + var dimensions, rotation, position; + if (spaceMode == SPACE_LOCAL) { + rotation = SelectionManager.localRotation; + dimensions = SelectionManager.localDimensions; + position = SelectionManager.localPosition; + } else { + rotation = SelectionManager.worldRotation; + dimensions = SelectionManager.worldDimensions; + position = SelectionManager.worldPosition; + } + Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: boundsCenter.x, y: top + grabberMoveUpOffset, z: boundsCenter.z } }); - Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: near } }); - Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: near } }); - Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: far } }); - Overlays.editOverlay(grabberRBF, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: far } }); - Overlays.editOverlay(grabberLTN, { visible: stretchHandlesVisible, position: { x: left, y: top, z: near } }); - Overlays.editOverlay(grabberRTN, { visible: stretchHandlesVisible, position: { x: right, y: top, z: near } }); - Overlays.editOverlay(grabberLTF, { visible: stretchHandlesVisible, position: { x: left, y: top, z: far } }); - Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, position: { x: right, y: top, z: far } }); - - - Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: boundsCenter.z } }); - Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: boundsCenter.z } }); - Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: boundsCenter.z } }); - Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: boundsCenter.z } }); - Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: near } }); - Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: boundsCenter.y, z: far } }); - - Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, position: { x: right, y: top, z: boundsCenter.z } }); - Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, position: { x: left, y: top, z: boundsCenter.z } }); - Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: far } }); - Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: top, z: near } }); - Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, position: { x: right, y: bottom, z: boundsCenter.z } }); - Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, position: { x: left, y: bottom, z: boundsCenter.z } }); - Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: far } }); - Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, position: { x: boundsCenter.x, y: bottom, z: near } }); - Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: near } }); - Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: near } }); - Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, position: { x: right, y: boundsCenter.y, z: far } }); - Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, position: { x: left, y: boundsCenter.y, z: far } }); + that.updateHandles(entityID); Overlays.editOverlay(baseOfEntityProjectionOverlay, @@ -770,6 +900,22 @@ SelectionDisplay = (function () { Entities.editEntity(entityID, { localRenderAlpha: 0.1 }); }; + that.setSpaceMode = function(newSpaceMode) { + if (spaceMode != newSpaceMode) { + spaceMode = newSpaceMode; + that.updateHandles(); + } + }; + + that.toggleSpaceMode = function() { + if (spaceMode == SPACE_WORLD && SelectionManager.selections.length > 1) { + print("Local space editing is not available with multiple selections"); + return; + } + spaceMode = spaceMode == SPACE_LOCAL ? SPACE_WORLD : SPACE_LOCAL; + that.updateHandles(); + }; + that.unselectAll = function () { if (currentSelection.isKnownID == true) { that.unselect(currentSelection); @@ -778,50 +924,170 @@ SelectionDisplay = (function () { entitySelected = false; }; + that.updateHandles = function(entityID) { + if (!entitySelected) { + that.setOverlaysVisible(false); + return; + } + + var properties = Entities.getEntityProperties(entityID); + + var rotation, dimensions, position; + + if (spaceMode == SPACE_LOCAL) { + rotation = properties.rotation; + dimensions = SelectionManager.localDimensions; + position = SelectionManager.localPosition; + } else { + rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); + dimensions = SelectionManager.worldDimensions; + position = SelectionManager.worldPosition; + } + + var halfDimensions = Vec3.multiply(0.5, dimensions); + + left = -halfDimensions.x; + right = halfDimensions.x; + top = halfDimensions.y; + bottom = -halfDimensions.y; + var front = far = halfDimensions.z; + near = -halfDimensions.z; + + var LBN = { x: left, y: bottom, z: near }; + var RBN = { x: right, y: bottom, z: near }; + var LBF = { x: left, y: bottom, z: far }; + var RBF = { x: right, y: bottom, z: far }; + var LTN = { x: left, y: top, z: near }; + var RTN = { x: right, y: top, z: near }; + var LTF = { x: left, y: top, z: far }; + var RTF = { x: right, y: top, z: far }; + + var TOP = { x: 0, y: top, z: 0 }; + var BOTTOM = { x: 0, y: bottom, z: 0 }; + var LEFT = { x: left, y: 0, z: 0 }; + var RIGHT = { x: right, y: 0, z: 0 }; + var NEAR = { x: 0, y: 0, z: near }; + var FAR = { x: 0, y: 0, z: far }; + + var EdgeTR = { x: right, y: top, z: 0 }; + var EdgeTL = { x: left, y: top, z: 0 }; + var EdgeTF = { x: 0, y: top, z: front }; + var EdgeTN = { x: 0, y: top, z: near }; + var EdgeBR = { x: right, y: bottom, z: 0 }; + var EdgeBL = { x: left, y: bottom, z: 0 }; + var EdgeBF = { x: 0, y: bottom, z: front }; + var EdgeBN = { x: 0, y: bottom, z: near }; + var EdgeNR = { x: right, y: 0, z: near }; + var EdgeNL = { x: left, y: 0, z: near }; + var EdgeFR = { x: right, y: 0, z: front }; + var EdgeFL = { x: left, y: 0, z: front }; + + LBN = Vec3.multiplyQbyV(rotation, LBN); + RBN = Vec3.multiplyQbyV(rotation, RBN); + LBF = Vec3.multiplyQbyV(rotation, LBF); + RBF = Vec3.multiplyQbyV(rotation, RBF); + LTN = Vec3.multiplyQbyV(rotation, LTN); + RTN = Vec3.multiplyQbyV(rotation, RTN); + LTF = Vec3.multiplyQbyV(rotation, LTF); + RTF = Vec3.multiplyQbyV(rotation, RTF); + + TOP = Vec3.multiplyQbyV(rotation, TOP); + BOTTOM = Vec3.multiplyQbyV(rotation, BOTTOM); + LEFT = Vec3.multiplyQbyV(rotation, LEFT); + RIGHT = Vec3.multiplyQbyV(rotation, RIGHT); + NEAR = Vec3.multiplyQbyV(rotation, NEAR); + FAR = Vec3.multiplyQbyV(rotation, FAR); + + EdgeTR = Vec3.multiplyQbyV(rotation, EdgeTR); + EdgeTL = Vec3.multiplyQbyV(rotation, EdgeTL); + EdgeTF = Vec3.multiplyQbyV(rotation, EdgeTF); + EdgeTN = Vec3.multiplyQbyV(rotation, EdgeTN); + EdgeBR = Vec3.multiplyQbyV(rotation, EdgeBR); + EdgeBL = Vec3.multiplyQbyV(rotation, EdgeBL); + EdgeBF = Vec3.multiplyQbyV(rotation, EdgeBF); + EdgeBN = Vec3.multiplyQbyV(rotation, EdgeBN); + EdgeNR = Vec3.multiplyQbyV(rotation, EdgeNR); + EdgeNL = Vec3.multiplyQbyV(rotation, EdgeNL); + EdgeFR = Vec3.multiplyQbyV(rotation, EdgeFR); + EdgeFL = Vec3.multiplyQbyV(rotation, EdgeFL); + + LBN = Vec3.sum(position, LBN); + RBN = Vec3.sum(position, RBN); + LBF = Vec3.sum(position, LBF); + RBF = Vec3.sum(position, RBF); + LTN = Vec3.sum(position, LTN); + RTN = Vec3.sum(position, RTN); + LTF = Vec3.sum(position, LTF); + RTF = Vec3.sum(position, RTF); + + TOP = Vec3.sum(position, TOP); + BOTTOM = Vec3.sum(position, BOTTOM); + LEFT = Vec3.sum(position, LEFT); + RIGHT = Vec3.sum(position, RIGHT); + NEAR = Vec3.sum(position, NEAR); + FAR = Vec3.sum(position, FAR); + + EdgeTR = Vec3.sum(position, EdgeTR); + EdgeTL = Vec3.sum(position, EdgeTL); + EdgeTF = Vec3.sum(position, EdgeTF); + EdgeTN = Vec3.sum(position, EdgeTN); + EdgeBR = Vec3.sum(position, EdgeBR); + EdgeBL = Vec3.sum(position, EdgeBL); + EdgeBF = Vec3.sum(position, EdgeBF); + EdgeBN = Vec3.sum(position, EdgeBN); + EdgeNR = Vec3.sum(position, EdgeNR); + EdgeNL = Vec3.sum(position, EdgeNL); + EdgeFR = Vec3.sum(position, EdgeFR); + EdgeFL = Vec3.sum(position, EdgeFL); + + var stretchHandlesVisible = spaceMode == SPACE_LOCAL; + Overlays.editOverlay(grabberLBN, { visible: stretchHandlesVisible, rotation: rotation, position: LBN }); + Overlays.editOverlay(grabberRBN, { visible: stretchHandlesVisible, rotation: rotation, position: RBN }); + Overlays.editOverlay(grabberLBF, { visible: stretchHandlesVisible, rotation: rotation, position: LBF }); + Overlays.editOverlay(grabberRBF, { visible: stretchHandlesVisible, rotation: rotation, position: RBF }); + Overlays.editOverlay(grabberLTN, { visible: stretchHandlesVisible, rotation: rotation, position: LTN }); + Overlays.editOverlay(grabberRTN, { visible: stretchHandlesVisible, rotation: rotation, position: RTN }); + Overlays.editOverlay(grabberLTF, { visible: stretchHandlesVisible, rotation: rotation, position: LTF }); + Overlays.editOverlay(grabberRTF, { visible: stretchHandlesVisible, rotation: rotation, position: RTF }); + + Overlays.editOverlay(grabberTOP, { visible: stretchHandlesVisible, rotation: rotation, position: TOP }); + Overlays.editOverlay(grabberBOTTOM, { visible: stretchHandlesVisible, rotation: rotation, position: BOTTOM }); + Overlays.editOverlay(grabberLEFT, { visible: stretchHandlesVisible, rotation: rotation, position: LEFT }); + Overlays.editOverlay(grabberRIGHT, { visible: stretchHandlesVisible, rotation: rotation, position: RIGHT }); + Overlays.editOverlay(grabberNEAR, { visible: stretchHandlesVisible, rotation: rotation, position: NEAR }); + Overlays.editOverlay(grabberFAR, { visible: stretchHandlesVisible, rotation: rotation, position: FAR }); + + Overlays.editOverlay(selectionBox, { + position: position, + dimensions: dimensions, + rotation: rotation, + visible: true, + }); + + Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTR }); + Overlays.editOverlay(grabberEdgeTL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTL }); + Overlays.editOverlay(grabberEdgeTF, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTF }); + Overlays.editOverlay(grabberEdgeTN, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTN }); + Overlays.editOverlay(grabberEdgeBR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBR }); + Overlays.editOverlay(grabberEdgeBL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBL }); + Overlays.editOverlay(grabberEdgeBF, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBF }); + Overlays.editOverlay(grabberEdgeBN, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeBN }); + Overlays.editOverlay(grabberEdgeNR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeNR }); + Overlays.editOverlay(grabberEdgeNL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeNL }); + Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFR }); + Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFL }); + + }; + + that.setOverlaysVisible = function(isVisible) { + var length = allOverlays.length; + for (var i = 0; i < length; i++) { + Overlays.editOverlay(allOverlays[i], { visible: isVisible }); + } + }; + that.unselect = function (entityID) { - Overlays.editOverlay(selectionBox, { visible: false }); - Overlays.editOverlay(baseOfEntityProjectionOverlay, { visible: false }); - Overlays.editOverlay(grabberMoveUp, { visible: false }); - Overlays.editOverlay(grabberLBN, { visible: false }); - Overlays.editOverlay(grabberLBF, { visible: false }); - Overlays.editOverlay(grabberRBN, { visible: false }); - Overlays.editOverlay(grabberRBF, { visible: false }); - Overlays.editOverlay(grabberLTN, { visible: false }); - Overlays.editOverlay(grabberLTF, { visible: false }); - Overlays.editOverlay(grabberRTN, { visible: false }); - Overlays.editOverlay(grabberRTF, { visible: false }); - - Overlays.editOverlay(grabberTOP, { visible: false }); - Overlays.editOverlay(grabberBOTTOM, { visible: false }); - Overlays.editOverlay(grabberLEFT, { visible: false }); - Overlays.editOverlay(grabberRIGHT, { visible: false }); - Overlays.editOverlay(grabberNEAR, { visible: false }); - Overlays.editOverlay(grabberFAR, { visible: false }); - - Overlays.editOverlay(grabberEdgeTR, { visible: false }); - Overlays.editOverlay(grabberEdgeTL, { visible: false }); - Overlays.editOverlay(grabberEdgeTF, { visible: false }); - Overlays.editOverlay(grabberEdgeTN, { visible: false }); - Overlays.editOverlay(grabberEdgeBR, { visible: false }); - Overlays.editOverlay(grabberEdgeBL, { visible: false }); - Overlays.editOverlay(grabberEdgeBF, { visible: false }); - Overlays.editOverlay(grabberEdgeBN, { visible: false }); - Overlays.editOverlay(grabberEdgeNR, { visible: false }); - Overlays.editOverlay(grabberEdgeNL, { visible: false }); - Overlays.editOverlay(grabberEdgeFR, { visible: false }); - Overlays.editOverlay(grabberEdgeFL, { visible: false }); - - Overlays.editOverlay(yawHandle, { visible: false }); - Overlays.editOverlay(pitchHandle, { visible: false }); - Overlays.editOverlay(rollHandle, { visible: false }); - - Overlays.editOverlay(rotateOverlayTarget, { visible: false }); - Overlays.editOverlay(rotateOverlayInner, { visible: false }); - Overlays.editOverlay(rotateOverlayOuter, { visible: false }); - Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); - - Overlays.editOverlay(rotateZeroOverlay, { visible: false }); - Overlays.editOverlay(rotateCurrentOverlay, { visible: false }); + that.setOverlaysVisible(false); Entities.editEntity(entityID, { localRenderAlpha: 1.0 }); @@ -829,1160 +1095,711 @@ SelectionDisplay = (function () { entitySelected = false; }; - that.translateXZ = function(event) { - if (!entitySelected || mode !== "TRANSLATE_XZ") { - return; // not allowed + var lastXZPick = null; + var translateXZTool = { + mode: 'TRANSLATE_XZ', + onBegin: function(event) { + SelectionManager.saveProperties(); + var position = SelectionManager.worldPosition; + var dimensions = SelectionManager.worldDimensions; + var bottom = position.y - (dimensions.y / 2) + + var pickRay = Camera.computePickRay(event.x, event.y); + lastXZPick = rayPlaneIntersection(pickRay, position, { x: 0, y: 1, z: 0 }); + }, + onEnd: function(event, reason) { + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }, + onMove: function(event) { + if (!entitySelected || mode !== "TRANSLATE_XZ") { + return; // not allowed + } + + pickRay = Camera.computePickRay(event.x, event.y); + + // translate mode left/right based on view toward entity + var newIntersection = rayPlaneIntersection(pickRay, + selectedEntityPropertiesOriginalPosition, + Quat.getFront(lastCameraOrientation)); + + var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); + + var pickRay = Camera.computePickRay(event.x, event.y); + var pick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, { x: 0, y: 1, z: 0 }); + vector = Vec3.subtract(pick, lastXZPick); + lastXZPick = pick; + + var wantDebug = false; + + for (var i = 0; i < SelectionManager.selections.length; i++) { + var properties = Entities.getEntityProperties(SelectionManager.selections[i]); + var original = properties.position; + properties.position = Vec3.sum(properties.position, vector); + Entities.editEntity(SelectionManager.selections[i], properties); + + if (wantDebug) { + print("translateXZ... "); + Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); + Vec3.print(" newIntersection:", newIntersection); + Vec3.print(" vector:", vector); + Vec3.print(" originalPosition:", original); + Vec3.print(" newPosition:", properties.position); + Vec3.print(" newPosition:", newPosition); + } + } + + tooltip.updateText(selectedEntityProperties); + that.select(currentSelection, false); // TODO: this should be more than highlighted + SelectionManager._update(); } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - // this allows us to use the old editModels "shifted" logic which makes the - // up/down behavior of the mouse move "in"/"out" of the screen. - var i = Vec3.dot(vector, Quat.getRight(orientation)); - var j = Vec3.dot(vector, Quat.getUp(orientation)); - vector = Vec3.sum(Vec3.multiply(Quat.getRight(orientation), i), - Vec3.multiply(Quat.getFront(orientation), j)); - - newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, vector); - - var wantDebug = false; - if (wantDebug) { - print("translateXZ... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" recentPosition:", selectedEntityProperties.position); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted }; - that.translateUpDown = function(event) { - if (!entitySelected || mode !== "TRANSLATE_UP_DOWN") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - // we only care about the Y axis - vector.x = 0; - vector.z = 0; - - newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, vector); - - var wantDebug = false; - if (wantDebug) { - print("translateUpDown... "); - print(" event.y:" + event.y); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" recentPosition:", selectedEntityProperties.position); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchNEAR = function(event) { - if (!entitySelected || mode !== "STRETCH_NEAR") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldNEAR = selectedEntityPropertiesOriginalPosition.z - halfDimensions.z; - var newNEAR = oldNEAR + vector.z; - - // if near is changing, then... - // dimensions changes by: (oldNEAR - newNEAR) - var changeInDimensions = { x: 0, y: 0, z: (oldNEAR - newNEAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: 0, y: 0, z: (oldNEAR - newNEAR) * -0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchNEAR... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldNEAR:" + oldNEAR); - print(" newNEAR:" + newNEAR); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchFAR = function(event) { - if (!entitySelected || mode !== "STRETCH_FAR") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldFAR = selectedEntityPropertiesOriginalPosition.z + halfDimensions.z; - var newFAR = oldFAR + vector.z; - var changeInDimensions = { x: 0, y: 0, z: (newFAR - oldFAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: 0, y: 0, z: (newFAR - oldFAR) * 0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchFAR... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldFAR:" + oldFAR); - print(" newFAR:" + newFAR); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchTOP = function(event) { - if (!entitySelected || mode !== "STRETCH_TOP") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldTOP = selectedEntityPropertiesOriginalPosition.y + halfDimensions.y; - var newTOP = oldTOP + vector.y; - var changeInDimensions = { x: 0, y: (newTOP - oldTOP), z: 0 }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: 0, y: (newTOP - oldTOP) * 0.5, z: 0 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchTOP... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldTOP:" + oldTOP); - print(" newTOP:" + newTOP); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchBOTTOM = function(event) { - if (!entitySelected || mode !== "STRETCH_BOTTOM") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldBOTTOM = selectedEntityPropertiesOriginalPosition.y - halfDimensions.y; - var newBOTTOM = oldBOTTOM + vector.y; - var changeInDimensions = { x: 0, y: (oldBOTTOM - newBOTTOM), z: 0 }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: 0, y: (oldBOTTOM - newBOTTOM) * -0.5, z: 0 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchBOTTOM... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldBOTTOM:" + oldBOTTOM); - print(" newBOTTOM:" + newBOTTOM); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchRIGHT = function(event) { - if (!entitySelected || mode !== "STRETCH_RIGHT") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; - var newRIGHT = oldRIGHT + vector.x; - var changeInDimensions = { x: (oldRIGHT - newRIGHT), y: 0 , z: 0 }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (oldRIGHT - newRIGHT) * -0.5, y: 0, z: 0 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchRIGHT... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldRIGHT:" + oldRIGHT); - print(" newRIGHT:" + newRIGHT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchLEFT = function(event) { - if (!entitySelected || mode !== "STRETCH_LEFT") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; - var newLEFT = oldLEFT + vector.x; - var changeInDimensions = { x: (newLEFT - oldLEFT), y: 0, z: 0 }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newLEFT - oldLEFT) * 0.5, y: 0, z: 0 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = true; - if (wantDebug) { - print("stretchLEFT... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldLEFT:" + oldLEFT); - print(" newLEFT:" + newLEFT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchRBN = function(event) { - if (!entitySelected || mode !== "STRETCH_RBN") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; - var newRIGHT = oldRIGHT + vector.x; - - var oldBOTTOM = selectedEntityPropertiesOriginalPosition.y - halfDimensions.y; - var newBOTTOM = oldBOTTOM - vector.y; - - var oldNEAR = selectedEntityPropertiesOriginalPosition.z - halfDimensions.z; - var newNEAR = oldNEAR - vector.z; - - - var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newBOTTOM - oldBOTTOM) , z: (newNEAR - oldNEAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, - y: (newBOTTOM - oldBOTTOM) * -0.5, - z: (newNEAR - oldNEAR) * -0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchRBN... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldRIGHT:" + oldRIGHT); - print(" newRIGHT:" + newRIGHT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchLBN = function(event) { - if (!entitySelected || mode !== "STRETCH_LBN") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; - var newLEFT = oldLEFT - vector.x; - - var oldBOTTOM = selectedEntityPropertiesOriginalPosition.y - halfDimensions.y; - var newBOTTOM = oldBOTTOM - vector.y; - - var oldNEAR = selectedEntityPropertiesOriginalPosition.z - halfDimensions.z; - var newNEAR = oldNEAR - vector.z; - - - var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newBOTTOM - oldBOTTOM) , z: (newNEAR - oldNEAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, - y: (newBOTTOM - oldBOTTOM) * -0.5, - z: (newNEAR - oldNEAR) * -0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchLBN... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldLEFT:" + oldLEFT); - print(" newLEFT:" + newLEFT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchRTN = function(event) { - if (!entitySelected || mode !== "STRETCH_RTN") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; - var newRIGHT = oldRIGHT + vector.x; - - var oldTOP = selectedEntityPropertiesOriginalPosition.y + halfDimensions.y; - var newTOP = oldTOP + vector.y; - - var oldNEAR = selectedEntityPropertiesOriginalPosition.z - halfDimensions.z; - var newNEAR = oldNEAR - vector.z; - - - var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newTOP - oldTOP) , z: (newNEAR - oldNEAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, - y: (newTOP - oldTOP) * 0.5, - z: (newNEAR - oldNEAR) * -0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchRTN... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldRIGHT:" + oldRIGHT); - print(" newRIGHT:" + newRIGHT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchLTN = function(event) { - if (!entitySelected || mode !== "STRETCH_LTN") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; - var newLEFT = oldLEFT - vector.x; - - var oldTOP = selectedEntityPropertiesOriginalPosition.y + halfDimensions.y; - var newTOP = oldTOP + vector.y; - - var oldNEAR = selectedEntityPropertiesOriginalPosition.z - halfDimensions.z; - var newNEAR = oldNEAR - vector.z; - - - var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newTOP - oldTOP) , z: (newNEAR - oldNEAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, - y: (newTOP - oldTOP) * 0.5, - z: (newNEAR - oldNEAR) * -0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchLTN... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldLEFT:" + oldLEFT); - print(" newLEFT:" + newLEFT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchRBF = function(event) { - if (!entitySelected || mode !== "STRETCH_RBF") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; - var newRIGHT = oldRIGHT + vector.x; - - var oldBOTTOM = selectedEntityPropertiesOriginalPosition.y - halfDimensions.y; - var newBOTTOM = oldBOTTOM - vector.y; - - var oldFAR = selectedEntityPropertiesOriginalPosition.z + halfDimensions.z; - var newFAR = oldFAR + vector.z; - - - var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newBOTTOM - oldBOTTOM) , z: (newFAR - oldFAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, - y: (newBOTTOM - oldBOTTOM) * -0.5, - z: (newFAR - oldFAR) * 0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchRBF... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldRIGHT:" + oldRIGHT); - print(" newRIGHT:" + newRIGHT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchLBF = function(event) { - if (!entitySelected || mode !== "STRETCH_LBF") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; - var newLEFT = oldLEFT - vector.x; - - var oldBOTTOM = selectedEntityPropertiesOriginalPosition.y - halfDimensions.y; - var newBOTTOM = oldBOTTOM - vector.y; - - var oldFAR = selectedEntityPropertiesOriginalPosition.z + halfDimensions.z; - var newFAR = oldFAR + vector.z; - - - var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newBOTTOM - oldBOTTOM) , z: (newFAR - oldFAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, - y: (newBOTTOM - oldBOTTOM) * -0.5, - z: (newFAR - oldFAR) * 0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchLBF... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldLEFT:" + oldLEFT); - print(" newLEFT:" + newLEFT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchRTF = function(event) { - if (!entitySelected || mode !== "STRETCH_RTF") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldRIGHT = selectedEntityPropertiesOriginalPosition.x + halfDimensions.x; - var newRIGHT = oldRIGHT + vector.x; - - var oldTOP = selectedEntityPropertiesOriginalPosition.y + halfDimensions.y; - var newTOP = oldTOP + vector.y; - - var oldFAR = selectedEntityPropertiesOriginalPosition.z + halfDimensions.z; - var newFAR = oldFAR + vector.z; - - - var changeInDimensions = { x: (newRIGHT - oldRIGHT), y: (newTOP - oldTOP) , z: (newFAR - oldFAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newRIGHT - oldRIGHT) * 0.5, - y: (newTOP - oldTOP) * 0.5, - z: (newFAR - oldFAR) * 0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchRTF... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldRIGHT:" + oldRIGHT); - print(" newRIGHT:" + newRIGHT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.stretchLTF = function(event) { - if (!entitySelected || mode !== "STRETCH_LTF") { - return; // not allowed - } - pickRay = Camera.computePickRay(event.x, event.y); - - // translate mode left/right based on view toward entity - var newIntersection = rayPlaneIntersection(pickRay, - selectedEntityPropertiesOriginalPosition, - Quat.getFront(lastCameraOrientation)); - - var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); - - var halfDimensions = Vec3.multiply(selectedEntityPropertiesOriginalDimensions, 0.5); - var oldLEFT = selectedEntityPropertiesOriginalPosition.x - halfDimensions.x; - var newLEFT = oldLEFT - vector.x; - - var oldTOP = selectedEntityPropertiesOriginalPosition.y + halfDimensions.y; - var newTOP = oldTOP + vector.y; - - var oldFAR = selectedEntityPropertiesOriginalPosition.z + halfDimensions.z; - var newFAR = oldFAR + vector.z; - - - var changeInDimensions = { x: (newLEFT - oldLEFT), y: (newTOP - oldTOP) , z: (newFAR - oldFAR) }; - var newDimensions = Vec3.sum(selectedEntityPropertiesOriginalDimensions, changeInDimensions); - - if (newDimensions.x < MINIMUM_DIMENSION) { - newDimensions.x = MINIMUM_DIMENSION; - } - - if (newDimensions.y < MINIMUM_DIMENSION) { - newDimensions.y = MINIMUM_DIMENSION; - } - - if (newDimensions.z < MINIMUM_DIMENSION) { - newDimensions.z = MINIMUM_DIMENSION; - } - - var changeInPosition = { x: (newLEFT - oldLEFT) * -0.5, - y: (newTOP - oldTOP) * 0.5, - z: (newFAR - oldFAR) * 0.5 }; - var newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, changeInPosition); - var wantDebug = false; - if (wantDebug) { - print("stretchLTF... "); - Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); - Vec3.print(" newIntersection:", newIntersection); - Vec3.print(" vector:", vector); - print(" oldLEFT:" + oldLEFT); - print(" newLEFT:" + newLEFT); - Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); - Vec3.print(" changeInDimensions:", changeInDimensions); - Vec3.print(" newDimensions:", newDimensions); - - Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); - Vec3.print(" changeInPosition:", changeInPosition); - Vec3.print(" newPosition:", newPosition); - } - - selectedEntityProperties.position = newPosition; - selectedEntityProperties.dimensions = newDimensions; - Entities.editEntity(currentSelection, selectedEntityProperties); - tooltip.updateText(selectedEntityProperties); - that.select(currentSelection, false); // TODO: this should be more than highlighted - }; - - that.rotateYaw = function(event) { - if (!entitySelected || mode !== "ROTATE_YAW") { - return; // not allowed - } - - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - - if (debug) { - print("rotateYaw()..."); - print(" event.x,y:" + event.x + "," + event.y); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); - Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); - Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); - - var result = Overlays.findRayIntersection(pickRay); - - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } - - if (result.intersects) { - - + addGrabberTool(grabberMoveUp, { + mode: "TRANSLATE_UP_DOWN", + onBegin: function(event) { + SelectionManager.saveProperties(); + }, + onEnd: function(event, reason) { + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }, + onMove: function(event) { + if (!entitySelected || mode !== "TRANSLATE_UP_DOWN") { + return; // not allowed + } + pickRay = Camera.computePickRay(event.x, event.y); + + // translate mode left/right based on view toward entity + var newIntersection = rayPlaneIntersection(pickRay, + selectedEntityPropertiesOriginalPosition, + Quat.getFront(lastCameraOrientation)); + + var vector = Vec3.subtract(newIntersection, lastPlaneIntersection); + lastPlaneIntersection = newIntersection; + + // we only care about the Y axis + vector.x = 0; + vector.z = 0; + + // newPosition = Vec3.sum(selectedEntityPropertiesOriginalPosition, vector); + + var wantDebug = false; + if (wantDebug) { + print("translateUpDown... "); + print(" event.y:" + event.y); + Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); + Vec3.print(" newIntersection:", newIntersection); + Vec3.print(" vector:", vector); + Vec3.print(" originalPosition:", selectedEntityPropertiesOriginalPosition); + Vec3.print(" recentPosition:", selectedEntityProperties.position); + Vec3.print(" newPosition:", newPosition); + } + for (var i = 0; i < SelectionManager.selections.length; i++) { + var properties = Entities.getEntityProperties(SelectionManager.selections[i]); + var original = properties.position; + properties.position = Vec3.sum(properties.position, vector); + Entities.editEntity(SelectionManager.selections[i], properties); + } + + tooltip.updateText(selectedEntityProperties); + that.select(currentSelection, false); // TODO: this should be more than highlighted + SelectionManager._update(); + }, + }); + + var vec3Mult = function(v1, v2) { + return { x: v1.x * v2.x, y: v1.y * v2.y, z: v1.z * v2.z }; + } + var makeStretchTool = function(stretchMode, direction, pivot) { + var signs = { + x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0), + y: direction.y < 0 ? -1 : (direction.y > 0 ? 1 : 0), + z: direction.z < 0 ? -1 : (direction.z > 0 ? 1 : 0), + }; + + var mask = { + x: Math.abs(direction.x) > 0 ? 1 : 0, + y: Math.abs(direction.y) > 0 ? 1 : 0, + z: Math.abs(direction.z) > 0 ? 1 : 0, + }; + + var numDimensions = mask.x + mask.y + mask.z; + + var planeNormal = null; + var lastPick = null; + var initialPosition = null; + var initialDimensions = null; + var initialIntersection = null; + var initialProperties = null; + var rotation = null; + + var onBegin = function(event) { + print("STARTING: " + stretchMode); var properties = Entities.getEntityProperties(currentSelection); - var center = yawCenter; - var zero = yawZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - - var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } - - // for debugging - if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - print(" angleFromZero:" + angleFromZero); + initialProperties = properties; + rotation = spaceMode == SPACE_LOCAL ? properties.rotation : Quat.fromPitchYawRollDegrees(0, 0, 0); + + if (spaceMode == SPACE_LOCAL) { + initialPosition = SelectionManager.localPosition; + initialDimensions = SelectionManager.localDimensions; + } else { + initialPosition = SelectionManager.worldPosition; + initialDimensions = SelectionManager.worldDimensions; } - var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); - var newRotation = Quat.multiply(yawChange, originalRotation); - - Entities.editEntity(currentSelection, { rotation: newRotation }); - - // update the rotation display accordingly... - var startAtCurrent = 0; - var endAtCurrent = angleFromZero; - var startAtRemainder = angleFromZero; - var endAtRemainder = 360; - if (angleFromZero < 0) { - startAtCurrent = 360 + angleFromZero; - endAtCurrent = 360; - startAtRemainder = 0; - endAtRemainder = startAtCurrent; + if (numDimensions == 1 && mask.x) { + var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 }); + start = Vec3.sum(start, properties.position); + var end = Vec3.multiplyQbyV(rotation, { x: 10000, y: 0, z: 0 }); + end = Vec3.sum(end, properties.position); + Overlays.editOverlay(xRailOverlay, { + start: start, + end: end, + visible: true, + }); } - if (snapToInner) { - Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, - majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + if (numDimensions == 1 && mask.y) { + var start = Vec3.multiplyQbyV(rotation, { x: 0, y: -10000, z: 0 }); + start = Vec3.sum(start, properties.position); + var end = Vec3.multiplyQbyV(rotation, { x: 0, y: 10000, z: 0 }); + end = Vec3.sum(end, properties.position); + Overlays.editOverlay(yRailOverlay, { + start: start, + end: end, + visible: true, + }); + } + if (numDimensions == 1 && mask.z) { + var start = Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: -10000 }); + start = Vec3.sum(start, properties.position); + var end = Vec3.multiplyQbyV(rotation, { x: 0, y: 0, z: 10000 }); + end = Vec3.sum(end, properties.position); + Overlays.editOverlay(zRailOverlay, { + start: start, + end: end, + visible: true, + }); + } + if (numDimensions == 1) { + if (mask.x == 1) { + planeNormal = { x: 0, y: 1, z: 0 }; + } else if (mask.y == 1) { + planeNormal = { x: 1, y: 0, z: 0 }; + } else { + planeNormal = { x: 0, y: 1, z: 0 }; + } + } else if (numDimensions == 2) { + if (mask.x == 0) { + planeNormal = { x: 1, y: 0, z: 0 }; + } else if (mask.y == 0) { + planeNormal = { x: 0, y: 1, z: 0 }; + } else { + planeNormal = { x: 0, y: 0, z: z }; + } + } + planeNormal = Vec3.multiplyQbyV(rotation, planeNormal); + var pickRay = Camera.computePickRay(event.x, event.y); + lastPick = rayPlaneIntersection(pickRay, + initialPosition, + planeNormal); + + // Overlays.editOverlay(normalLine, { + // start: initialPosition, + // end: Vec3.sum(Vec3.multiply(100000, planeNormal), initialPosition), + // }); + + SelectionManager.saveProperties(); + }; + + var onEnd = function(event, reason) { + print("ENDING: " + stretchMode); + Overlays.editOverlay(xRailOverlay, { visible: false }); + Overlays.editOverlay(yRailOverlay, { visible: false }); + Overlays.editOverlay(zRailOverlay, { visible: false }); + + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }; + + var onMove = function(event) { + if (!entitySelected || mode !== stretchMode) { + return; // not allowed + } + var proportional = spaceMode == SPACE_WORLD || event.isShifted; + + var position, dimensions, rotation; + if (spaceMode == SPACE_LOCAL) { + position = SelectionManager.localPosition; + dimensions = SelectionManager.localDimensions; + rotation = SelectionManager.localRotation; } else { - Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, - majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + position = SelectionManager.worldPosition; + dimensions = SelectionManager.worldDimensions; + rotation = SelectionManager.worldRotation; + } + + var pickRay = Camera.computePickRay(event.x, event.y); + newPick = rayPlaneIntersection(pickRay, + initialPosition, + planeNormal); + var vector = Vec3.subtract(newPick, lastPick); + + vector = Vec3.multiplyQbyV(Quat.inverse(rotation), vector); + + vector = vec3Mult(mask, vector); + + var changeInDimensions = Vec3.multiply(-1, vec3Mult(signs, vector)); + var newDimensions; + if (proportional) { + var absX = Math.abs(changeInDimensions.x); + var absY = Math.abs(changeInDimensions.y); + var absZ = Math.abs(changeInDimensions.z); + print('abs: ' + absX + ', ' + absY + ', ' + absZ); + var pctChange = 0; + if (absX > absY && absX > absZ) { + pctChange = changeInDimensions.x / initialProperties.dimensions.x; + pctChange = changeInDimensions.x / initialDimensions.x; + } else if (absY > absZ) { + pctChange = changeInDimensions.y / initialProperties.dimensions.y; + pctChange = changeInDimensions.y / initialDimensions.y; + } else { + pctChange = changeInDimensions.z / initialProperties.dimensions.z; + pctChange = changeInDimensions.z / initialDimensions.z; + } + print('change: ' + pctChange); + pctChange += 1.0; + newDimensions = Vec3.multiply(pctChange, initialDimensions); + } else { + newDimensions = Vec3.sum(initialDimensions, changeInDimensions); } + newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION); + newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION); + newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION); + + var p = Vec3.multiply(0.5, pivot); + var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(p, changeInDimensions)); + var newPosition = Vec3.sum(initialPosition, changeInPosition); + + + selectedEntityProperties.position = newPosition; + selectedEntityProperties.dimensions = newDimensions; + for (var i = 0; i < SelectionManager.selections.length; i++) { + Entities.editEntity(SelectionManager.selections[i], selectedEntityProperties); + } + + var wantDebug = false; + if (wantDebug) { + print(stretchMode); + Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection); + Vec3.print(" newIntersection:", newIntersection); + Vec3.print(" vector:", vector); + Vec3.print(" oldPOS:", oldPOS); + Vec3.print(" newPOS:", newPOS); + Vec3.print(" oldDimensions:", selectedEntityPropertiesOriginalDimensions); + Vec3.print(" changeInDimensions:", changeInDimensions); + Vec3.print(" newDimensions:", newDimensions); + + Vec3.print(" oldPosition:", selectedEntityPropertiesOriginalPosition); + Vec3.print(" changeInPosition:", changeInPosition); + Vec3.print(" newPosition:", newPosition); + } + + tooltip.updateText(selectedEntityProperties); + SelectionManager._update(); + that.select(currentSelection, false); // TODO: this should be more than highlighted + + }; + + return { + mode: stretchMode, + onBegin: onBegin, + onMove: onMove, + onEnd: onEnd + }; + }; + + that.cancelTool = function() { + if (activeTool) { + activeTool.onEnd(null, 'cancel'); + activeTool = null; + SelectionManager._update(); } }; - that.rotatePitch = function(event) { - if (!entitySelected || mode !== "ROTATE_PITCH") { - return; // not allowed + function addStretchTool(overlay, mode, pivot, direction) { + if (!pivot) { + pivot = Vec3.multiply(-1, direction); + pivot.y = direction.y; } - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + var tool = makeStretchTool(mode, direction, pivot); - if (debug) { - print("rotatePitch()..."); - print(" event.x,y:" + event.x + "," + event.y); - } + addGrabberTool(overlay, tool); + } - var pickRay = Camera.computePickRay(event.x, event.y); - Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); - Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); - Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); - var result = Overlays.findRayIntersection(pickRay); + addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); + addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); + addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); + addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); + addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); + addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } + addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}); + addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}); + addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}); + addStretchTool(grabberRBF, "STRETCH_RBF", null, {x: -1, y: 0, z: -1}); + addStretchTool(grabberLTN, "STRETCH_LTN", null, {x: 1, y: 0, z: 1}); + addStretchTool(grabberRTN, "STRETCH_RTN", null, {x: -1, y: 0, z: 1}); + addStretchTool(grabberLTF, "STRETCH_LTF", null, {x: 1, y: 0, z: -1}); + addStretchTool(grabberRTF, "STRETCH_RTF", null, {x: -1, y: 0, z: -1}); - if (result.intersects) { - var properties = Entities.getEntityProperties(currentSelection); - var center = pitchCenter; - var zero = pitchZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {x: 1, y: 1, z: 0}); + addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}); + addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}); + addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}); + addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: 1, y: -1, z: 0}); + addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: -1, y: -1, z: 0}); + addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: -1, z: 1}); + addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: -1, z: -1}); + addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}); + addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}); + addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}); + addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}); - var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; + var initialPosition = SelectionManager.worldPosition; + addGrabberTool(yawHandle, { + mode: "ROTATE_YAW", + onBegin: function(event) { + SelectionManager.saveProperties(); + initialPosition = SelectionManager.worldPosition; + }, + onEnd: function(event, reason) { + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }, + onMove: function(event) { + if (!entitySelected || mode !== "ROTATE_YAW") { + return; // not allowed } - // for debugging + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - print(" angleFromZero:" + angleFromZero); + print("rotateYaw()..."); + print(" event.x,y:" + event.x + "," + event.y); } - var pitchChange = Quat.fromVec3Degrees({ x: angleFromZero, y: 0, z: 0 }); - var newRotation = Quat.multiply(pitchChange, originalRotation); - - Entities.editEntity(currentSelection, { rotation: newRotation }); - - // update the rotation display accordingly... - var startAtCurrent = 0; - var endAtCurrent = angleFromZero; - var startAtRemainder = angleFromZero; - var endAtRemainder = 360; - if (angleFromZero < 0) { - startAtCurrent = 360 + angleFromZero; - endAtCurrent = 360; - startAtRemainder = 0; - endAtRemainder = startAtCurrent; - } - if (snapToInner) { - Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, - majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); - } else { - Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, - majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); - } - } - }; - - that.rotateRoll = function(event) { - if (!entitySelected || mode !== "ROTATE_ROLL") { - return; // not allowed - } - var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); - - if (debug) { - print("rotateRoll()..."); - print(" event.x,y:" + event.x + "," + event.y); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); - Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); - Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); - Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); - var result = Overlays.findRayIntersection(pickRay); - - if (debug) { - print(" findRayIntersection() .... result.intersects:" + result.intersects); - } - - if (result.intersects) { - var properties = Entities.getEntityProperties(currentSelection); - var center = rollCenter; - var zero = rollZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - - var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } - - // for debugging - if (debug) { - Vec3.print(" result.intersection:",result.intersection); - Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); - print(" angleFromZero:" + angleFromZero); - } - - var rollChange = Quat.fromVec3Degrees({ x: 0, y: 0, z: angleFromZero }); - var newRotation = Quat.multiply(rollChange, originalRotation); + var pickRay = Camera.computePickRay(event.x, event.y); + Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); + Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); + Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); + Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); - Entities.editEntity(currentSelection, { rotation: newRotation }); + var result = Overlays.findRayIntersection(pickRay); - // update the rotation display accordingly... - var startAtCurrent = 0; - var endAtCurrent = angleFromZero; - var startAtRemainder = angleFromZero; - var endAtRemainder = 360; - if (angleFromZero < 0) { - startAtCurrent = 360 + angleFromZero; - endAtCurrent = 360; - startAtRemainder = 0; - endAtRemainder = startAtCurrent; + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); } - if (snapToInner) { - Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, - majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); - } else { - Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, - majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + + if (result.intersects) { + var properties = Entities.getEntityProperties(currentSelection); + var center = yawCenter; + var zero = yawZero; + var centerToZero = Vec3.subtract(center, zero); + var centerToIntersect = Vec3.subtract(center, result.intersection); + var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + + var distanceFromCenter = Vec3.distance(center, result.intersection); + var snapToInner = false; + if (distanceFromCenter < innerRadius) { + angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; + snapToInner = true; + } + + // for debugging + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } + + var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var properties = Entities.getEntityProperties(entityID); + var initialProperties = SelectionManager.savedProperties[entityID.id]; + var dPos = Vec3.subtract(initialProperties.position, initialPosition); + dPos = Vec3.multiplyQbyV(yawChange, dPos); + + Entities.editEntity(entityID, { + position: Vec3.sum(initialPosition, dPos), + rotation: Quat.multiply(yawChange, initialProperties.rotation), + }); + } + + // update the rotation display accordingly... + var startAtCurrent = 0; + var endAtCurrent = angleFromZero; + var startAtRemainder = angleFromZero; + var endAtRemainder = 360; + if (angleFromZero < 0) { + startAtCurrent = 360 + angleFromZero; + endAtCurrent = 360; + startAtRemainder = 0; + endAtRemainder = startAtCurrent; + } + if (snapToInner) { + Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + } else { + Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + } + } } - }; + }); + + addGrabberTool(pitchHandle, { + mode: "ROTATE_PITCH", + onBegin: function(event) { + SelectionManager.saveProperties(); + initialPosition = SelectionManager.worldPosition; + }, + onEnd: function(event, reason) { + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }, + onMove: function(event) { + if (!entitySelected || mode !== "ROTATE_PITCH") { + return; // not allowed + } + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + + if (debug) { + print("rotatePitch()..."); + print(" event.x,y:" + event.x + "," + event.y); + } + + var pickRay = Camera.computePickRay(event.x, event.y); + Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); + Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); + Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); + Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); + var result = Overlays.findRayIntersection(pickRay); + + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); + } + + if (result.intersects) { + var properties = Entities.getEntityProperties(currentSelection); + var center = pitchCenter; + var zero = pitchZero; + var centerToZero = Vec3.subtract(center, zero); + var centerToIntersect = Vec3.subtract(center, result.intersection); + var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + + var distanceFromCenter = Vec3.distance(center, result.intersection); + var snapToInner = false; + if (distanceFromCenter < innerRadius) { + angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; + snapToInner = true; + } + + // for debugging + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } + + var pitchChange = Quat.fromVec3Degrees({ x: angleFromZero, y: 0, z: 0 }); + + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var properties = Entities.getEntityProperties(entityID); + var initialProperties = SelectionManager.savedProperties[entityID.id]; + var dPos = Vec3.subtract(initialProperties.position, initialPosition); + dPos = Vec3.multiplyQbyV(pitchChange, dPos); + + Entities.editEntity(entityID, { + position: Vec3.sum(initialPosition, dPos), + rotation: Quat.multiply(pitchChange, initialProperties.rotation), + }); + } + + // update the rotation display accordingly... + var startAtCurrent = 0; + var endAtCurrent = angleFromZero; + var startAtRemainder = angleFromZero; + var endAtRemainder = 360; + if (angleFromZero < 0) { + startAtCurrent = 360 + angleFromZero; + endAtCurrent = 360; + startAtRemainder = 0; + endAtRemainder = startAtCurrent; + } + if (snapToInner) { + Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + } else { + Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + } + } + } + }); + + addGrabberTool(rollHandle, { + mode: "ROTATE_ROLL", + onBegin: function(event) { + SelectionManager.saveProperties(); + initialPosition = SelectionManager.worldPosition; + }, + onEnd: function(event, reason) { + if (reason == 'cancel') { + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID.id]; + Entities.editEntity(entityID, initialProperties); + } + } + }, + onMove: function(event) { + if (!entitySelected || mode !== "ROTATE_ROLL") { + return; // not allowed + } + var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems"); + + if (debug) { + print("rotateRoll()..."); + print(" event.x,y:" + event.x + "," + event.y); + } + + var pickRay = Camera.computePickRay(event.x, event.y); + Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false}); + Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false }); + Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false }); + Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true }); + Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true }); + var result = Overlays.findRayIntersection(pickRay); + + if (debug) { + print(" findRayIntersection() .... result.intersects:" + result.intersects); + } + + if (result.intersects) { + var properties = Entities.getEntityProperties(currentSelection); + var center = rollCenter; + var zero = rollZero; + var centerToZero = Vec3.subtract(center, zero); + var centerToIntersect = Vec3.subtract(center, result.intersection); + var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + + var distanceFromCenter = Vec3.distance(center, result.intersection); + var snapToInner = false; + if (distanceFromCenter < innerRadius) { + angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; + snapToInner = true; + } + + // for debugging + if (debug) { + Vec3.print(" result.intersection:",result.intersection); + Overlays.editOverlay(rotateCurrentOverlay, { visible: true, start: center, end: result.intersection }); + print(" angleFromZero:" + angleFromZero); + } + + var rollChange = Quat.fromVec3Degrees({ x: 0, y: 0, z: angleFromZero }); + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var properties = Entities.getEntityProperties(entityID); + var initialProperties = SelectionManager.savedProperties[entityID.id]; + var dPos = Vec3.subtract(initialProperties.position, initialPosition); + dPos = Vec3.multiplyQbyV(rollChange, dPos); + + Entities.editEntity(entityID, { + position: Vec3.sum(initialPosition, dPos), + rotation: Quat.multiply(rollChange, initialProperties.rotation), + }); + } + + // update the rotation display accordingly... + var startAtCurrent = 0; + var endAtCurrent = angleFromZero; + var startAtRemainder = angleFromZero; + var endAtRemainder = 360; + if (angleFromZero < 0) { + startAtCurrent = 360 + angleFromZero; + endAtCurrent = 360; + startAtRemainder = 0; + endAtRemainder = startAtCurrent; + } + if (snapToInner) { + Overlays.editOverlay(rotateOverlayOuter, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + } else { + Overlays.editOverlay(rotateOverlayInner, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + } + } + } + }); that.checkMove = function() { if (currentSelection.isKnownID && (!Vec3.equal(Camera.getPosition(), lastCameraPosition) || !Quat.equal(Camera.getOrientation(), lastCameraOrientation))){ - that.select(currentSelection, false); + that.select(currentSelection, false, false); } }; @@ -2011,119 +1828,66 @@ SelectionDisplay = (function () { Vec3.print(" result.intersection:", result.intersection); } - switch(result.overlayID) { - case grabberMoveUp: - mode = "TRANSLATE_UP_DOWN"; - somethingClicked = true; + var tool = grabberTools[result.overlayID]; + if (tool) { + print("FOUND TOOL! " + tool.mode); + activeTool = tool; + mode = tool.mode; + somethingClicked = true; + if (activeTool && activeTool.onBegin) { + activeTool.onBegin(event); + } + } else { + switch(result.overlayID) { + case grabberMoveUp: + mode = "TRANSLATE_UP_DOWN"; + somethingClicked = true; - // in translate mode, we hide our stretch handles... - Overlays.editOverlay(grabberLBN, { visible: false }); - Overlays.editOverlay(grabberLBF, { visible: false }); - Overlays.editOverlay(grabberRBN, { visible: false }); - Overlays.editOverlay(grabberRBF, { visible: false }); - Overlays.editOverlay(grabberLTN, { visible: false }); - Overlays.editOverlay(grabberLTF, { visible: false }); - Overlays.editOverlay(grabberRTN, { visible: false }); - Overlays.editOverlay(grabberRTF, { visible: false }); + // in translate mode, we hide our stretch handles... + for (var i = 0; i < stretchHandles.length; i++) { + Overlays.editOverlay(stretchHandles[i], { visible: false }); + } + break; - Overlays.editOverlay(grabberTOP, { visible: false }); - Overlays.editOverlay(grabberBOTTOM, { visible: false }); - Overlays.editOverlay(grabberLEFT, { visible: false }); - Overlays.editOverlay(grabberRIGHT, { visible: false }); - Overlays.editOverlay(grabberNEAR, { visible: false }); - Overlays.editOverlay(grabberFAR, { visible: false }); - Overlays.editOverlay(grabberEdgeTR, { visible: false }); - Overlays.editOverlay(grabberEdgeTL, { visible: false }); - Overlays.editOverlay(grabberEdgeTF, { visible: false }); - Overlays.editOverlay(grabberEdgeTN, { visible: false }); - Overlays.editOverlay(grabberEdgeBR, { visible: false }); - Overlays.editOverlay(grabberEdgeBL, { visible: false }); - Overlays.editOverlay(grabberEdgeBF, { visible: false }); - Overlays.editOverlay(grabberEdgeBN, { visible: false }); - Overlays.editOverlay(grabberEdgeNR, { visible: false }); - Overlays.editOverlay(grabberEdgeNL, { visible: false }); - Overlays.editOverlay(grabberEdgeFR, { visible: false }); - Overlays.editOverlay(grabberEdgeFL, { visible: false }); - break; + case grabberNEAR: + case grabberEdgeTN: // TODO: maybe this should be TOP+NEAR stretching? + case grabberEdgeBN: // TODO: maybe this should be BOTTOM+FAR stretching? + mode = "STRETCH_NEAR"; + somethingClicked = true; + break; - case grabberRBN: - mode = "STRETCH_RBN"; - somethingClicked = true; - break; + case grabberFAR: + case grabberEdgeTF: // TODO: maybe this should be TOP+FAR stretching? + case grabberEdgeBF: // TODO: maybe this should be BOTTOM+FAR stretching? + mode = "STRETCH_FAR"; + somethingClicked = true; + break; + case grabberTOP: + mode = "STRETCH_TOP"; + somethingClicked = true; + break; + case grabberBOTTOM: + mode = "STRETCH_BOTTOM"; + somethingClicked = true; + break; + case grabberRIGHT: + case grabberEdgeTR: // TODO: maybe this should be TOP+RIGHT stretching? + case grabberEdgeBR: // TODO: maybe this should be BOTTOM+RIGHT stretching? + mode = "STRETCH_RIGHT"; + somethingClicked = true; + break; + case grabberLEFT: + case grabberEdgeTL: // TODO: maybe this should be TOP+LEFT stretching? + case grabberEdgeBL: // TODO: maybe this should be BOTTOM+LEFT stretching? + mode = "STRETCH_LEFT"; + somethingClicked = true; + break; - case grabberLBN: - mode = "STRETCH_LBN"; - somethingClicked = true; - break; - - case grabberRTN: - mode = "STRETCH_RTN"; - somethingClicked = true; - break; - - case grabberLTN: - mode = "STRETCH_LTN"; - somethingClicked = true; - break; - - case grabberRBF: - mode = "STRETCH_RBF"; - somethingClicked = true; - break; - - case grabberLBF: - mode = "STRETCH_LBF"; - somethingClicked = true; - break; - - case grabberRTF: - mode = "STRETCH_RTF"; - somethingClicked = true; - break; - - case grabberLTF: - mode = "STRETCH_LTF"; - somethingClicked = true; - break; - - case grabberNEAR: - case grabberEdgeTN: // TODO: maybe this should be TOP+NEAR stretching? - case grabberEdgeBN: // TODO: maybe this should be BOTTOM+FAR stretching? - mode = "STRETCH_NEAR"; - somethingClicked = true; - break; - - case grabberFAR: - case grabberEdgeTF: // TODO: maybe this should be TOP+FAR stretching? - case grabberEdgeBF: // TODO: maybe this should be BOTTOM+FAR stretching? - mode = "STRETCH_FAR"; - somethingClicked = true; - break; - case grabberTOP: - mode = "STRETCH_TOP"; - somethingClicked = true; - break; - case grabberBOTTOM: - mode = "STRETCH_BOTTOM"; - somethingClicked = true; - break; - case grabberRIGHT: - case grabberEdgeTR: // TODO: maybe this should be TOP+RIGHT stretching? - case grabberEdgeBR: // TODO: maybe this should be BOTTOM+RIGHT stretching? - mode = "STRETCH_RIGHT"; - somethingClicked = true; - break; - case grabberLEFT: - case grabberEdgeTL: // TODO: maybe this should be TOP+LEFT stretching? - case grabberEdgeBL: // TODO: maybe this should be BOTTOM+LEFT stretching? - mode = "STRETCH_LEFT"; - somethingClicked = true; - break; - - default: - mode = "UNKNOWN"; - break; + default: + mode = "UNKNOWN"; + break; + } } } @@ -2164,6 +1928,16 @@ SelectionDisplay = (function () { originalRoll = roll; if (result.intersects) { + var tool = grabberTools[result.overlayID]; + if (tool) { + print("FOUND TOOL! " + tool.mode); + activeTool = tool; + mode = tool.mode; + somethingClicked = true; + if (activeTool && activeTool.onBegin) { + activeTool.onBegin(event); + } + } switch(result.overlayID) { case yawHandle: mode = "ROTATE_YAW"; @@ -2176,6 +1950,7 @@ SelectionDisplay = (function () { case pitchHandle: mode = "ROTATE_PITCH"; + initialPosition = SelectionManager.worldPosition; somethingClicked = true; overlayOrientation = pitchHandleRotation; overlayCenter = pitchCenter; @@ -2263,7 +2038,9 @@ SelectionDisplay = (function () { if (result.intersects) { switch(result.overlayID) { case selectionBox: - mode = "TRANSLATE_XZ"; + activeTool = translateXZTool; + mode = translateXZTool.mode; + activeTool.onBegin(event); somethingClicked = true; break; default: @@ -2296,169 +2073,111 @@ SelectionDisplay = (function () { }; that.mouseMoveEvent = function(event) { - //print("mouseMoveEvent()... mode:" + mode); - switch (mode) { - case "ROTATE_YAW": - that.rotateYaw(event); - break; - case "ROTATE_PITCH": - that.rotatePitch(event); - break; - case "ROTATE_ROLL": - that.rotateRoll(event); - break; - case "TRANSLATE_UP_DOWN": - that.translateUpDown(event); - break; - case "TRANSLATE_XZ": - that.translateXZ(event); - break; - case "STRETCH_RBN": - that.stretchRBN(event); - break; - case "STRETCH_LBN": - that.stretchLBN(event); - break; - case "STRETCH_RTN": - that.stretchRTN(event); - break; - case "STRETCH_LTN": - that.stretchLTN(event); - break; + if (activeTool) { + activeTool.onMove(event); + SelectionManager._update(); + return true; + } - case "STRETCH_RBF": - that.stretchRBF(event); - break; - case "STRETCH_LBF": - that.stretchLBF(event); - break; - case "STRETCH_RTF": - that.stretchRTF(event); - break; - case "STRETCH_LTF": - that.stretchLTF(event); - break; + // if no tool is active, then just look for handles to highlight... + var pickRay = Camera.computePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(pickRay); + var pickedColor; + var pickedAlpha; + var highlightNeeded = false; - case "STRETCH_NEAR": - that.stretchNEAR(event); - break; - case "STRETCH_FAR": - that.stretchFAR(event); - break; - case "STRETCH_TOP": - that.stretchTOP(event); - break; - case "STRETCH_BOTTOM": - that.stretchBOTTOM(event); - break; - case "STRETCH_RIGHT": - that.stretchRIGHT(event); - break; - case "STRETCH_LEFT": - that.stretchLEFT(event); - break; - default: - // if not in any specific mode, then just look for handles to highlight... - var pickRay = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(pickRay); - var pickedColor; - var pickedAlpha; - var highlightNeeded = false; - - if (result.intersects) { - switch(result.overlayID) { - case yawHandle: - case pitchHandle: - case rollHandle: - pickedColor = rotateHandleColor; - pickedAlpha = rotateHandleAlpha; - highlightNeeded = true; - break; - - case grabberMoveUp: - pickedColor = rotateHandleColor; - pickedAlpha = rotateHandleAlpha; - highlightNeeded = true; - break; - - case grabberLBN: - case grabberLBF: - case grabberRBN: - case grabberRBF: - case grabberLTN: - case grabberLTF: - case grabberRTN: - case grabberRTF: - pickedColor = grabberColorCorner; - pickedAlpha = grabberAlpha; - highlightNeeded = true; - break; - - case grabberTOP: - case grabberBOTTOM: - case grabberLEFT: - case grabberRIGHT: - case grabberNEAR: - case grabberFAR: - pickedColor = grabberColorFace; - pickedAlpha = grabberAlpha; - highlightNeeded = true; - break; - - case grabberEdgeTR: - case grabberEdgeTL: - case grabberEdgeTF: - case grabberEdgeTN: - case grabberEdgeBR: - case grabberEdgeBL: - case grabberEdgeBF: - case grabberEdgeBN: - case grabberEdgeNR: - case grabberEdgeNL: - case grabberEdgeFR: - case grabberEdgeFL: - pickedColor = grabberColorEdge; - pickedAlpha = grabberAlpha; - highlightNeeded = true; - break; - - default: - if (previousHandle) { - Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); - previousHandle = false; - } - break; - } + if (result.intersects) { + switch(result.overlayID) { + case yawHandle: + case pitchHandle: + case rollHandle: + pickedColor = rotateHandleColor; + pickedAlpha = rotateHandleAlpha; + highlightNeeded = true; + break; - if (highlightNeeded) { - if (previousHandle) { - Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); - previousHandle = false; - } - Overlays.editOverlay(result.overlayID, { color: highlightedHandleColor, alpha: highlightedHandleAlpha }); - previousHandle = result.overlayID; - previousHandleColor = pickedColor; - previousHandleAlpha = pickedAlpha; - } - - } else { + case grabberMoveUp: + pickedColor = rotateHandleColor; + pickedAlpha = rotateHandleAlpha; + highlightNeeded = true; + break; + + case grabberLBN: + case grabberLBF: + case grabberRBN: + case grabberRBF: + case grabberLTN: + case grabberLTF: + case grabberRTN: + case grabberRTF: + pickedColor = grabberColorCorner; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + case grabberTOP: + case grabberBOTTOM: + case grabberLEFT: + case grabberRIGHT: + case grabberNEAR: + case grabberFAR: + pickedColor = grabberColorFace; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + case grabberEdgeTR: + case grabberEdgeTL: + case grabberEdgeTF: + case grabberEdgeTN: + case grabberEdgeBR: + case grabberEdgeBL: + case grabberEdgeBF: + case grabberEdgeBN: + case grabberEdgeNR: + case grabberEdgeNL: + case grabberEdgeFR: + case grabberEdgeFL: + pickedColor = grabberColorEdge; + pickedAlpha = grabberAlpha; + highlightNeeded = true; + break; + + default: if (previousHandle) { Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); previousHandle = false; } + break; + } + + if (highlightNeeded) { + if (previousHandle) { + Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); + previousHandle = false; } - - return false; + Overlays.editOverlay(result.overlayID, { color: highlightedHandleColor, alpha: highlightedHandleAlpha }); + previousHandle = result.overlayID; + previousHandleColor = pickedColor; + previousHandleAlpha = pickedAlpha; + } + + } else { + if (previousHandle) { + Overlays.editOverlay(previousHandle, { color: previousHandleColor, alpha: previousHandleAlpha }); + previousHandle = false; + } } - return true; + + return false; }; that.updateHandleSizes = function() { if (selectedEntityProperties) { var diff = Vec3.subtract(selectedEntityProperties.position, Camera.getPosition()); var grabberSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO; - for (var i = 0; i < cornerEdgeFaceGrabbers.length; i++) { - Overlays.editOverlay(cornerEdgeFaceGrabbers[i], { + for (var i = 0; i < stretchHandles.length; i++) { + Overlays.editOverlay(stretchHandles[i], { size: grabberSize, }); } @@ -2481,6 +2200,10 @@ SelectionDisplay = (function () { that.mouseReleaseEvent = function(event) { var showHandles = false; + if (activeTool && activeTool.onEnd) { + activeTool.onEnd(event); + } + activeTool = null; // hide our rotation overlays..., and show our handles if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL") { Overlays.editOverlay(rotateOverlayTarget, { visible: false }); diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 8e1ccab67e..9b46cdaf3f 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -21,6 +21,7 @@ Script.include("libraries/progressDialog.js"); Script.include("libraries/entitySelectionTool.js"); var selectionDisplay = SelectionDisplay; +var selectionManager = SelectionManager; Script.include("libraries/ModelImporter.js"); var modelImporter = new ModelImporter(); @@ -34,6 +35,8 @@ var entityPropertyDialogBox = EntityPropertyDialogBox; Script.include("libraries/entityCameraTool.js"); var entityCameraTool = new EntityCameraTool(); +selectionManager.setEventListener(selectionDisplay.updateHandles()); + var windowDimensions = Controller.getViewportDimensions(); var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; var toolHeight = 50; @@ -440,6 +443,11 @@ function mousePressEvent(event) { orientation = MyAvatar.orientation; intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation)); + if (!event.isShifted) { + selectionManager.clearSelections(); + } + selectionManager.addEntity(foundEntity); + print("Model selected selectedEntityID:" + selectedEntityID.id); } @@ -641,11 +649,16 @@ Menu.menuItemEvent.connect(handeMenuEvent); Controller.keyReleaseEvent.connect(function (event) { // since sometimes our menu shortcut keys don't work, trap our menu items here also and fire the appropriate menu items + print(event.text); if (event.text == "`") { handeMenuEvent("Edit Properties..."); } if (event.text == "BACKSPACE") { handeMenuEvent("Delete"); + } else if (event.text == "TAB") { + selectionDisplay.toggleSpaceMode(); + } else if (event.text == "ESC") { + selectionDisplay.cancelTool(); } else if (event.text == "f") { if (entitySelected) { // Get latest properties From bd4738d2c2251b540913bdccda6918eb4717d67b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 Oct 2014 15:48:53 -0700 Subject: [PATCH 22/29] Reliable delta fix. --- .../src/metavoxels/MetavoxelServer.cpp | 13 +-- .../src/metavoxels/MetavoxelServer.h | 1 + libraries/metavoxels/src/Endpoint.cpp | 3 +- libraries/metavoxels/src/Endpoint.h | 10 ++- .../metavoxels/src/MetavoxelClientManager.cpp | 81 +++++++++++++++++-- .../metavoxels/src/MetavoxelClientManager.h | 12 +++ libraries/metavoxels/src/MetavoxelMessages.h | 3 +- tests/metavoxels/src/MetavoxelTests.cpp | 32 ++++---- 8 files changed, 120 insertions(+), 35 deletions(-) diff --git a/assignment-client/src/metavoxels/MetavoxelServer.cpp b/assignment-client/src/metavoxels/MetavoxelServer.cpp index dd35a23630..3cf01bdc9f 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.cpp +++ b/assignment-client/src/metavoxels/MetavoxelServer.cpp @@ -237,8 +237,9 @@ void MetavoxelSession::update() { // go back to the beginning with the current packet and note that there's a delta pending _sequencer.getOutputStream().getUnderlying().device()->seek(start); - MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID, _lod }; - out << QVariant::fromValue(msg); + MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID, sendRecord->getPacketNumber(), + _sequencer.getIncomingPacketNumber() }; + out << (_reliableDeltaMessage = QVariant::fromValue(msg)); _sequencer.endPacket(); } else { @@ -254,8 +255,9 @@ void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) { } PacketRecord* MetavoxelSession::maybeCreateSendRecord() const { - return _reliableDeltaChannel ? new PacketRecord(_reliableDeltaLOD, _reliableDeltaData) : - new PacketRecord(_lod, _sender->getData()); + return _reliableDeltaChannel ? new PacketRecord(_sequencer.getOutgoingPacketNumber(), + _reliableDeltaLOD, _reliableDeltaData) : new PacketRecord(_sequencer.getOutgoingPacketNumber(), + _lod, _sender->getData()); } void MetavoxelSession::handleMessage(const QVariant& message) { @@ -290,8 +292,7 @@ void MetavoxelSession::sendPacketGroup(int alreadySent) { for (int i = 0; i < additionalPackets; i++) { Bitstream& out = _sequencer.startPacket(); if (_reliableDeltaChannel) { - MetavoxelDeltaPendingMessage msg = { _reliableDeltaID, _reliableDeltaLOD }; - out << QVariant::fromValue(msg); + out << _reliableDeltaMessage; } else { out << QVariant(); } diff --git a/assignment-client/src/metavoxels/MetavoxelServer.h b/assignment-client/src/metavoxels/MetavoxelServer.h index 70c49fad64..840041e0f0 100644 --- a/assignment-client/src/metavoxels/MetavoxelServer.h +++ b/assignment-client/src/metavoxels/MetavoxelServer.h @@ -134,6 +134,7 @@ private: MetavoxelLOD _reliableDeltaLOD; Bitstream::WriteMappings _reliableDeltaWriteMappings; int _reliableDeltaID; + QVariant _reliableDeltaMessage; }; /// Handles persistence in a separate thread. diff --git a/libraries/metavoxels/src/Endpoint.cpp b/libraries/metavoxels/src/Endpoint.cpp index 65e088c75e..5a4e74ce08 100644 --- a/libraries/metavoxels/src/Endpoint.cpp +++ b/libraries/metavoxels/src/Endpoint.cpp @@ -107,7 +107,8 @@ PacketRecord* Endpoint::maybeCreateReceiveRecord() const { return NULL; } -PacketRecord::PacketRecord(const MetavoxelLOD& lod, const MetavoxelData& data) : +PacketRecord::PacketRecord(int packetNumber, const MetavoxelLOD& lod, const MetavoxelData& data) : + _packetNumber(packetNumber), _lod(lod), _data(data) { } diff --git a/libraries/metavoxels/src/Endpoint.h b/libraries/metavoxels/src/Endpoint.h index 7b0adb4cef..816a1fe2a9 100644 --- a/libraries/metavoxels/src/Endpoint.h +++ b/libraries/metavoxels/src/Endpoint.h @@ -45,10 +45,10 @@ protected slots: virtual void handleMessage(const QVariant& message, Bitstream& in); void recordSend(); - void recordReceive(); + virtual void recordReceive(); - void clearSendRecordsBefore(int index); - void clearReceiveRecordsBefore(int index); + virtual void clearSendRecordsBefore(int index); + virtual void clearReceiveRecordsBefore(int index); protected: @@ -71,14 +71,16 @@ protected: class PacketRecord { public: - PacketRecord(const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData()); + PacketRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData()); virtual ~PacketRecord(); + int getPacketNumber() const { return _packetNumber; } const MetavoxelLOD& getLOD() const { return _lod; } const MetavoxelData& getData() const { return _data; } private: + int _packetNumber; MetavoxelLOD _lod; MetavoxelData _data; }; diff --git a/libraries/metavoxels/src/MetavoxelClientManager.cpp b/libraries/metavoxels/src/MetavoxelClientManager.cpp index 2e0146af3b..09164d72c4 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.cpp +++ b/libraries/metavoxels/src/MetavoxelClientManager.cpp @@ -216,12 +216,71 @@ void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit, bool reliable) } } +PacketRecord* MetavoxelClient::getAcknowledgedSendRecord(int packetNumber) const { + PacketRecord* lastAcknowledged = getLastAcknowledgedSendRecord(); + if (lastAcknowledged->getPacketNumber() == packetNumber) { + return lastAcknowledged; + } + foreach (PacketRecord* record, _clearedSendRecords) { + if (record->getPacketNumber() == packetNumber) { + return record; + } + } + return NULL; +} + +PacketRecord* MetavoxelClient::getAcknowledgedReceiveRecord(int packetNumber) const { + PacketRecord* lastAcknowledged = getLastAcknowledgedReceiveRecord(); + if (lastAcknowledged->getPacketNumber() == packetNumber) { + return lastAcknowledged; + } + foreach (PacketRecord* record, _clearedReceiveRecords) { + if (record->getPacketNumber() == packetNumber) { + return record; + } + } + return NULL; +} + void MetavoxelClient::dataChanged(const MetavoxelData& oldData) { // make thread-safe copy QWriteLocker locker(&_dataCopyLock); _dataCopy = _data; } +void MetavoxelClient::recordReceive() { + Endpoint::recordReceive(); + + // clear the cleared lists + foreach (PacketRecord* record, _clearedSendRecords) { + delete record; + } + _clearedSendRecords.clear(); + + foreach (PacketRecord* record, _clearedReceiveRecords) { + delete record; + } + _clearedReceiveRecords.clear(); +} + +void MetavoxelClient::clearSendRecordsBefore(int index) { + // move to cleared list + QList::iterator end = _sendRecords.begin() + index + 1; + for (QList::const_iterator it = _sendRecords.begin(); it != end; it++) { + _clearedSendRecords.append(*it); + } + _sendRecords.erase(_sendRecords.begin(), end); +} + +void MetavoxelClient::clearReceiveRecordsBefore(int index) { + // move to cleared list + QList::iterator end = _receiveRecords.begin() + index + 1; + for (QList::const_iterator it = _receiveRecords.begin(); it != end; it++) { + _clearedReceiveRecords.append(*it); + } + _receiveRecords.erase(_receiveRecords.begin(), end); +} + void MetavoxelClient::writeUpdateMessage(Bitstream& out) { ClientStateMessage state = { _updater->getLOD() }; out << QVariant::fromValue(state); @@ -232,7 +291,9 @@ void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) { if (userType == MetavoxelDeltaMessage::Type) { PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); if (_reliableDeltaChannel) { - _remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _remoteDataLOD = _reliableDeltaLOD); + MetavoxelData reference = _remoteData; + MetavoxelLOD referenceLOD = _remoteDataLOD; + _remoteData.readDelta(reference, referenceLOD, in, _remoteDataLOD = _reliableDeltaLOD); _sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings()); in.clearPersistentMappings(); _reliableDeltaChannel = NULL; @@ -260,8 +321,17 @@ void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) { _reliableDeltaID = pending.id; _reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX); _reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream()); - _reliableDeltaLOD = pending.lod; - PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord(); + PacketRecord* sendRecord = getAcknowledgedSendRecord(pending.receivedPacketNumber); + if (!sendRecord) { + qWarning() << "Missing send record for delta" << pending.receivedPacketNumber; + return; + } + _reliableDeltaLOD = sendRecord->getLOD(); + PacketRecord* receiveRecord = getAcknowledgedReceiveRecord(pending.sentPacketNumber); + if (!receiveRecord) { + qWarning() << "Missing receive record for delta" << pending.sentPacketNumber; + return; + } _remoteDataLOD = receiveRecord->getLOD(); _remoteData = receiveRecord->getData(); } @@ -271,10 +341,11 @@ void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) { } PacketRecord* MetavoxelClient::maybeCreateSendRecord() const { - return new PacketRecord(_reliableDeltaChannel ? _reliableDeltaLOD : _updater->getLOD()); + return new PacketRecord(_sequencer.getOutgoingPacketNumber(), + _reliableDeltaChannel ? _reliableDeltaLOD : _updater->getLOD()); } PacketRecord* MetavoxelClient::maybeCreateReceiveRecord() const { - return new PacketRecord(_remoteDataLOD, _remoteData); + return new PacketRecord(_sequencer.getIncomingPacketNumber(), _remoteDataLOD, _remoteData); } diff --git a/libraries/metavoxels/src/MetavoxelClientManager.h b/libraries/metavoxels/src/MetavoxelClientManager.h index 7ddee2d68d..0a32f2986d 100644 --- a/libraries/metavoxels/src/MetavoxelClientManager.h +++ b/libraries/metavoxels/src/MetavoxelClientManager.h @@ -116,8 +116,16 @@ public: protected: + PacketRecord* getAcknowledgedSendRecord(int packetNumber) const; + PacketRecord* getAcknowledgedReceiveRecord(int packetNumber) const; + virtual void dataChanged(const MetavoxelData& oldData); + virtual void recordReceive(); + + virtual void clearSendRecordsBefore(int index); + virtual void clearReceiveRecordsBefore(int index); + virtual void writeUpdateMessage(Bitstream& out); virtual void handleMessage(const QVariant& message, Bitstream& in); @@ -132,9 +140,13 @@ protected: ReliableChannel* _reliableDeltaChannel; MetavoxelLOD _reliableDeltaLOD; int _reliableDeltaID; + QVariant _reliableDeltaMessage; MetavoxelData _dataCopy; QReadWriteLock _dataCopyLock; + + QList _clearedSendRecords; + QList _clearedReceiveRecords; }; #endif // hifi_MetavoxelClientManager_h diff --git a/libraries/metavoxels/src/MetavoxelMessages.h b/libraries/metavoxels/src/MetavoxelMessages.h index b9a44a0e6b..06f2fc9b8d 100644 --- a/libraries/metavoxels/src/MetavoxelMessages.h +++ b/libraries/metavoxels/src/MetavoxelMessages.h @@ -68,7 +68,8 @@ class MetavoxelDeltaPendingMessage { public: STREAM int id; - STREAM MetavoxelLOD lod; + STREAM int sentPacketNumber; + STREAM int receivedPacketNumber; }; DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage) diff --git a/tests/metavoxels/src/MetavoxelTests.cpp b/tests/metavoxels/src/MetavoxelTests.cpp index 0a6a5de96d..92f8d0568c 100644 --- a/tests/metavoxels/src/MetavoxelTests.cpp +++ b/tests/metavoxels/src/MetavoxelTests.cpp @@ -603,31 +603,27 @@ int RandomVisitor::visit(MetavoxelInfo& info) { class TestSendRecord : public PacketRecord { public: - TestSendRecord(const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), - const SharedObjectPointer& localState = SharedObjectPointer(), int packetNumber = 0); + TestSendRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), + const SharedObjectPointer& localState = SharedObjectPointer()); const SharedObjectPointer& getLocalState() const { return _localState; } - int getPacketNumber() const { return _packetNumber; } private: SharedObjectPointer _localState; - int _packetNumber; - }; -TestSendRecord::TestSendRecord(const MetavoxelLOD& lod, const MetavoxelData& data, - const SharedObjectPointer& localState, int packetNumber) : - PacketRecord(lod, data), - _localState(localState), - _packetNumber(packetNumber) { +TestSendRecord::TestSendRecord(int packetNumber, const MetavoxelLOD& lod, const MetavoxelData& data, + const SharedObjectPointer& localState) : + PacketRecord(packetNumber, lod, data), + _localState(localState) { } class TestReceiveRecord : public PacketRecord { public: - TestReceiveRecord(const MetavoxelLOD& lod = MetavoxelLOD(), const MetavoxelData& data = MetavoxelData(), - const SharedObjectPointer& remoteState = SharedObjectPointer()); + TestReceiveRecord(int packetNumber = 0, const MetavoxelLOD& lod = MetavoxelLOD(), + const MetavoxelData& data = MetavoxelData(), const SharedObjectPointer& remoteState = SharedObjectPointer()); const SharedObjectPointer& getRemoteState() const { return _remoteState; } @@ -636,9 +632,9 @@ private: SharedObjectPointer _remoteState; }; -TestReceiveRecord::TestReceiveRecord(const MetavoxelLOD& lod, +TestReceiveRecord::TestReceiveRecord(int packetNumber, const MetavoxelLOD& lod, const MetavoxelData& data, const SharedObjectPointer& remoteState) : - PacketRecord(lod, data), + PacketRecord(packetNumber, lod, data), _remoteState(remoteState) { } @@ -1110,14 +1106,14 @@ void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) { PacketRecord* TestEndpoint::maybeCreateSendRecord() const { if (_reliableDeltaChannel) { - return new TestSendRecord(_reliableDeltaLOD, _reliableDeltaData, _localState, _sequencer.getOutgoingPacketNumber()); + return new TestSendRecord(_sequencer.getOutgoingPacketNumber(), _reliableDeltaLOD, _reliableDeltaData, _localState); } - return new TestSendRecord(_lod, (_mode == METAVOXEL_CLIENT_MODE) ? MetavoxelData() : _data, - _localState, _sequencer.getOutgoingPacketNumber()); + return new TestSendRecord(_sequencer.getOutgoingPacketNumber(), _lod, + (_mode == METAVOXEL_CLIENT_MODE) ? MetavoxelData() : _data, _localState); } PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const { - return new TestReceiveRecord(_remoteDataLOD, _remoteData, _remoteState); + return new TestReceiveRecord(_sequencer.getIncomingPacketNumber(), _remoteDataLOD, _remoteData, _remoteState); } void TestEndpoint::handleHighPriorityMessage(const QVariant& message) { From 0f58b42795a6831ed9e218eca573024eaa5b72c0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 Oct 2014 16:27:26 -0700 Subject: [PATCH 23/29] Forgot these guys. --- .../src/ui/MetavoxelNetworkSimulator.cpp | 72 +++++++++++++++++++ interface/src/ui/MetavoxelNetworkSimulator.h | 40 +++++++++++ 2 files changed, 112 insertions(+) create mode 100644 interface/src/ui/MetavoxelNetworkSimulator.cpp create mode 100644 interface/src/ui/MetavoxelNetworkSimulator.h diff --git a/interface/src/ui/MetavoxelNetworkSimulator.cpp b/interface/src/ui/MetavoxelNetworkSimulator.cpp new file mode 100644 index 0000000000..4b48efd0ce --- /dev/null +++ b/interface/src/ui/MetavoxelNetworkSimulator.cpp @@ -0,0 +1,72 @@ +// +// MetavoxelNetworkSimulator.cpp +// interface/src/ui +// +// Created by Andrzej Kapolka on 10/20/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include +#include + +#include "Application.h" +#include "MetavoxelNetworkSimulator.h" + +MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() : + QWidget(Application::getInstance()->getGLWidget(), Qt::Dialog) { + + setWindowTitle("Metavoxel Network Simulator"); + setAttribute(Qt::WA_DeleteOnClose); + + QVBoxLayout* topLayout = new QVBoxLayout(); + setLayout(topLayout); + + QFormLayout* form = new QFormLayout(); + topLayout->addLayout(form); + + MetavoxelSystem::NetworkSimulation simulation = Application::getInstance()->getMetavoxels()->getNetworkSimulation(); + + form->addRow("Drop Rate:", _dropRate = new QDoubleSpinBox()); + _dropRate->setSuffix("%"); + _dropRate->setValue(simulation.dropRate * 100.0); + connect(_dropRate, static_cast(&QDoubleSpinBox::valueChanged), this, + &MetavoxelNetworkSimulator::updateMetavoxelSystem); + + form->addRow("Repeat Rate:", _repeatRate = new QDoubleSpinBox()); + _repeatRate->setSuffix("%"); + _repeatRate->setValue(simulation.repeatRate * 100.0); + connect(_repeatRate, static_cast(&QDoubleSpinBox::valueChanged), this, + &MetavoxelNetworkSimulator::updateMetavoxelSystem); + + form->addRow("Minimum Delay:", _minimumDelay = new QSpinBox()); + _minimumDelay->setMaximum(1000); + _minimumDelay->setSuffix("ms"); + _minimumDelay->setValue(simulation.minimumDelay); + connect(_minimumDelay, static_cast(&QSpinBox::valueChanged), this, + &MetavoxelNetworkSimulator::updateMetavoxelSystem); + + form->addRow("Maximum Delay:", _maximumDelay = new QSpinBox()); + _maximumDelay->setMaximum(1000); + _maximumDelay->setSuffix("ms"); + _maximumDelay->setValue(simulation.maximumDelay); + connect(_maximumDelay, static_cast(&QSpinBox::valueChanged), this, + &MetavoxelNetworkSimulator::updateMetavoxelSystem); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this); + topLayout->addWidget(buttons); + connect(buttons, &QDialogButtonBox::accepted, this, &QWidget::close); + + show(); +} + +void MetavoxelNetworkSimulator::updateMetavoxelSystem() { + Application::getInstance()->getMetavoxels()->setNetworkSimulation(MetavoxelSystem::NetworkSimulation( + _dropRate->value() / 100.0, _repeatRate->value() / 100.0, qMin(_minimumDelay->value(), _maximumDelay->value()), + qMax(_minimumDelay->value(), _maximumDelay->value()))); +} diff --git a/interface/src/ui/MetavoxelNetworkSimulator.h b/interface/src/ui/MetavoxelNetworkSimulator.h new file mode 100644 index 0000000000..fcf4a53c04 --- /dev/null +++ b/interface/src/ui/MetavoxelNetworkSimulator.h @@ -0,0 +1,40 @@ +// +// MetavoxelNetworkSimulator.h +// interface/src/ui +// +// Created by Andrzej Kapolka on 10/20/14. +// Copyright 2014 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_MetavoxelNetworkSimulator_h +#define hifi_MetavoxelNetworkSimulator_h + +#include + +class QDoubleSpinBox; +class QSpinBox; + +/// Allows tweaking network simulation (packet drop percentage, etc.) settings for metavoxels. +class MetavoxelNetworkSimulator : public QWidget { + Q_OBJECT + +public: + + MetavoxelNetworkSimulator(); + +private slots: + + void updateMetavoxelSystem(); + +private: + + QDoubleSpinBox* _dropRate; + QDoubleSpinBox* _repeatRate; + QSpinBox* _minimumDelay; + QSpinBox* _maximumDelay; +}; + +#endif // hifi_MetavoxelNetworkSimulator_h From 311d1332f10451171b934e860a035454337f689a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 Oct 2014 17:29:28 -0700 Subject: [PATCH 24/29] Include a simple bandwidth limit option. --- interface/src/MetavoxelSystem.cpp | 40 ++++++++++++++++++- interface/src/MetavoxelSystem.h | 29 +++++++++++++- .../src/ui/MetavoxelNetworkSimulator.cpp | 17 +++++++- interface/src/ui/MetavoxelNetworkSimulator.h | 1 + 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index e0794725cb..9cf621f2bd 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -39,11 +39,13 @@ REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType(); -MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, int minimumDelay, int maximumDelay) : +MetavoxelSystem::NetworkSimulation::NetworkSimulation(float dropRate, float repeatRate, + int minimumDelay, int maximumDelay, int bandwidthLimit) : dropRate(dropRate), repeatRate(repeatRate), minimumDelay(minimumDelay), - maximumDelay(maximumDelay) { + maximumDelay(maximumDelay), + bandwidthLimit(bandwidthLimit) { } void MetavoxelSystem::init() { @@ -695,6 +697,28 @@ void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor, bool render) { } } +Throttle::Throttle() : + _limit(INT_MAX), + _total(0) { +} + +bool Throttle::shouldThrottle(int bytes) { + // clear expired buckets + qint64 now = QDateTime::currentMSecsSinceEpoch(); + while (!_buckets.isEmpty() && _buckets.first().first >= now) { + _total -= _buckets.takeFirst().second; + } + + // if possible, add the new bucket + if (_total + bytes > _limit) { + return true; + } + const int BUCKET_DURATION = 1000; + _buckets.append(Bucket(now + BUCKET_DURATION, bytes)); + _total += bytes; + return false; +} + MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : MetavoxelClient(node, updater) { } @@ -746,6 +770,12 @@ int MetavoxelSystemClient::parseData(const QByteArray& packet) { } int count = (randFloat() < simulation.repeatRate) ? 2 : 1; for (int i = 0; i < count; i++) { + if (simulation.bandwidthLimit > 0) { + _receiveThrottle.setLimit(simulation.bandwidthLimit); + if (_receiveThrottle.shouldThrottle(packet.size())) { + continue; + } + } int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); if (delay > 0) { ReceiveDelayer* delayer = new ReceiveDelayer(_node, packet); @@ -864,6 +894,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { } int count = (randFloat() < simulation.repeatRate) ? 2 : 1; for (int i = 0; i < count; i++) { + if (simulation.bandwidthLimit > 0) { + _sendThrottle.setLimit(simulation.bandwidthLimit); + if (_sendThrottle.shouldThrottle(data.size())) { + continue; + } + } int delay = randIntInRange(simulation.minimumDelay, simulation.maximumDelay); if (delay > 0) { SendDelayer* delayer = new SendDelayer(_node, data); diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index af6f4c6c7a..14a24eea59 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -37,8 +37,10 @@ public: float repeatRate; int minimumDelay; int maximumDelay; + int bandwidthLimit; - NetworkSimulation(float dropRate = 0.0f, float repeatRate = 0.0f, int minimumDelay = 0, int maximumDelay = 0); + NetworkSimulation(float dropRate = 0.0f, float repeatRate = 0.0f, int minimumDelay = 0, + int maximumDelay = 0, int bandwidthLimit = 0); }; virtual void init(); @@ -132,6 +134,28 @@ typedef QVector BufferPointVector; Q_DECLARE_METATYPE(BufferPointVector) +/// Simple throttle for limiting bandwidth on a per-second basis. +class Throttle { +public: + + Throttle(); + + /// Sets the per-second limit. + void setLimit(int limit) { _limit = limit; } + + /// Determines whether the message with the given size should be throttled (discarded). If not, registers the message + /// as having been processed (i.e., contributing to later throttling). + bool shouldThrottle(int bytes); + +private: + + int _limit; + int _total; + + typedef QPair Bucket; + QList _buckets; +}; + /// A client session associated with a single server. class MetavoxelSystemClient : public MetavoxelClient { Q_OBJECT @@ -161,6 +185,9 @@ private: MetavoxelData _augmentedData; MetavoxelData _renderedAugmentedData; QReadWriteLock _augmentedDataLock; + + Throttle _sendThrottle; + Throttle _receiveThrottle; }; /// Base class for cached static buffers. diff --git a/interface/src/ui/MetavoxelNetworkSimulator.cpp b/interface/src/ui/MetavoxelNetworkSimulator.cpp index 4b48efd0ce..aabee97636 100644 --- a/interface/src/ui/MetavoxelNetworkSimulator.cpp +++ b/interface/src/ui/MetavoxelNetworkSimulator.cpp @@ -18,6 +18,8 @@ #include "Application.h" #include "MetavoxelNetworkSimulator.h" +const int BYTES_PER_KILOBYTE = 1024; + MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() : QWidget(Application::getInstance()->getGLWidget(), Qt::Dialog) { @@ -58,6 +60,13 @@ MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() : connect(_maximumDelay, static_cast(&QSpinBox::valueChanged), this, &MetavoxelNetworkSimulator::updateMetavoxelSystem); + form->addRow("Bandwidth Limit:", _bandwidthLimit = new QSpinBox()); + _bandwidthLimit->setMaximum(1024 * 1024); + _bandwidthLimit->setSuffix("KB/s"); + _bandwidthLimit->setValue(simulation.bandwidthLimit / BYTES_PER_KILOBYTE); + connect(_bandwidthLimit, static_cast(&QSpinBox::valueChanged), this, + &MetavoxelNetworkSimulator::updateMetavoxelSystem); + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this); topLayout->addWidget(buttons); connect(buttons, &QDialogButtonBox::accepted, this, &QWidget::close); @@ -66,7 +75,13 @@ MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() : } void MetavoxelNetworkSimulator::updateMetavoxelSystem() { + int bandwidthLimit = _bandwidthLimit->value() * BYTES_PER_KILOBYTE; + if (bandwidthLimit > 0) { + // make sure the limit is enough to let at least one packet through + const int MINIMUM_BANDWIDTH_LIMIT = 2048; + bandwidthLimit = qMax(bandwidthLimit, MINIMUM_BANDWIDTH_LIMIT); + } Application::getInstance()->getMetavoxels()->setNetworkSimulation(MetavoxelSystem::NetworkSimulation( _dropRate->value() / 100.0, _repeatRate->value() / 100.0, qMin(_minimumDelay->value(), _maximumDelay->value()), - qMax(_minimumDelay->value(), _maximumDelay->value()))); + qMax(_minimumDelay->value(), _maximumDelay->value()), bandwidthLimit)); } diff --git a/interface/src/ui/MetavoxelNetworkSimulator.h b/interface/src/ui/MetavoxelNetworkSimulator.h index fcf4a53c04..18d0857ae4 100644 --- a/interface/src/ui/MetavoxelNetworkSimulator.h +++ b/interface/src/ui/MetavoxelNetworkSimulator.h @@ -35,6 +35,7 @@ private: QDoubleSpinBox* _repeatRate; QSpinBox* _minimumDelay; QSpinBox* _maximumDelay; + QSpinBox* _bandwidthLimit; }; #endif // hifi_MetavoxelNetworkSimulator_h From 4840c44d7ca47cfc263ae859d25b54efbce81561 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 21 Oct 2014 17:41:41 -0700 Subject: [PATCH 25/29] Time calculation fix. --- interface/src/MetavoxelSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 9cf621f2bd..8166c3938c 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -705,7 +705,7 @@ Throttle::Throttle() : bool Throttle::shouldThrottle(int bytes) { // clear expired buckets qint64 now = QDateTime::currentMSecsSinceEpoch(); - while (!_buckets.isEmpty() && _buckets.first().first >= now) { + while (!_buckets.isEmpty() && now >= _buckets.first().first) { _total -= _buckets.takeFirst().second; } From 821284edfd29b5b2aaaca75c6b50b6840d455739 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 21 Oct 2014 17:46:41 -0700 Subject: [PATCH 26/29] Introduce the gpu::Batch for the full Model::render call --- interface/src/gpu/Batch.cpp | 7 +- interface/src/gpu/Batch.h | 19 +--- interface/src/renderer/Model.cpp | 164 +++++++++++++++++++------------ interface/src/renderer/Model.h | 6 +- 4 files changed, 111 insertions(+), 85 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 9458dc8a3f..ddc5a9f24f 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -14,16 +14,15 @@ #define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); -//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); do##call(__param); -//#define DO_IT_NOW(call, offset) uint32 __param = _commandOffsets.back(); CommandCall call = _commandCalls.back(); (this->*(call))(__param); //#define DO_IT_NOW(call, offset) runLastCommand(); -//#define DO_IT_NOW(call, offset) uint32 __param = _params.size() - (offset); runCommand(_commands.size() -1);// do##call(__param); #define DO_IT_NOW(call, offset) using namespace gpu; Batch::Batch() : _commands(), + _commandCalls(), + _commandOffsets(), _params(), _resources(), _data(){ @@ -34,6 +33,8 @@ Batch::~Batch() { void Batch::clear() { _commands.clear(); + _commandCalls.clear(); + _commandOffsets.clear(); _params.clear(); _resources.clear(); _data.clear(); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 815a7f61f2..567740511e 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -31,11 +31,6 @@ typedef int Stamp; typedef unsigned int uint32; typedef int int32; -// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience -namespace backend { - -}; - enum Primitive { PRIMITIVE_POINTS = 0, PRIMITIVE_LINES, @@ -226,7 +221,6 @@ protected: Resources _resources; Bytes _data; - uint32 cacheResource(Resource* res); uint32 cacheResource(const void* pointer); ResourceCache* editResource(uint32 offset) { @@ -246,22 +240,11 @@ protected: uint32 offset = _commandOffsets[index]; CommandCall call = _commandCalls[index]; (this->*(call))(offset); - uint32 nextOFfset = offset; - - GLenum error = glGetError(); - if (error) { - error++; - } } void runLastCommand() { uint32 index = _commands.size() - 1; - uint32 offset = _commandOffsets[index]; - /* CommandCall call = _commandCalls[index]; - (this->*(call))(offset); - uint32 nextOFfset = offset; - */ - runCommand(_commands[index], offset); + runCommand(index); } void runCommand(Command com, uint32 offset); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 765acdf797..739f5d75b1 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -28,6 +28,7 @@ #include "gpu/Batch.h" #define GLBATCH( call ) batch._##call +//#define GLBATCH( call ) call using namespace std; @@ -433,97 +434,135 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { segregateMeshGroups(); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glDisable(GL_COLOR_MATERIAL); + // Let's introduce a gpu::Batch to capture all the calls to the graphics api + gpu::Batch batch; + + GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY); + GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY); + + GLBATCH(glDisable)(GL_COLOR_MATERIAL); if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { - glDisable(GL_CULL_FACE); + GLBATCH(glDisable)(GL_CULL_FACE); } else { - glEnable(GL_CULL_FACE); + GLBATCH(glEnable)(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { - glCullFace(GL_FRONT); + GLBATCH(glCullFace)(GL_FRONT); } } // render opaque meshes with alpha testing - - glDisable(GL_BLEND); - glEnable(GL_ALPHA_TEST); + + GLBATCH(glDisable)(GL_BLEND); + GLBATCH(glEnable)(GL_ALPHA_TEST); if (mode == SHADOW_RENDER_MODE) { - glAlphaFunc(GL_EQUAL, 0.0f); + GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); } - - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + + + /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); - + */ + { + GLenum buffers[3]; + int bufferCount = 0; + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + } + if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + } + if (mode == DEFAULT_RENDER_MODE) { + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + } + GLBATCH(glDrawBuffers)(bufferCount, buffers); + } + const float DEFAULT_ALPHA_THRESHOLD = 0.5f; + //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + // render translucent meshes afterwards - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); + { + GLenum buffers[2]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; + GLBATCH(glDrawBuffers)(bufferCount, buffers); + } + int translucentMeshPartsRendered = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - - glDisable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - glDepthMask(false); - glDepthFunc(GL_LEQUAL); - - Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + + GLBATCH(glDisable)(GL_ALPHA_TEST); + GLBATCH(glEnable)(GL_BLEND); + GLBATCH(glDepthMask)(false); + GLBATCH(glDepthFunc)(GL_LEQUAL); + //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); + { + GLenum buffers[1]; + int bufferCount = 0; + buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; + GLBATCH(glDrawBuffers)(bufferCount, buffers); + } + if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); } - - glDepthMask(true); - glDepthFunc(GL_LESS); - glDisable(GL_CULL_FACE); + + GLBATCH(glDepthMask)(true); + GLBATCH(glDepthFunc)(GL_LESS); + GLBATCH(glDisable)(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { - glCullFace(GL_BACK); + GLBATCH(glCullFace)(GL_BACK); } - + // deactivate vertex arrays after drawing - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); + GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); + GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); // bind with 0 to switch back to normal operation - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - + GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); + GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); + GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + + // Render! + ::gpu::backend::renderBatch(batch); + batch.clear(); + // restore all the default material settings Application::getInstance()->setupWorldLight(); @@ -1509,7 +1548,7 @@ void Model::segregateMeshGroups() { _meshGroupsKnown = true; } -int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, +int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); @@ -1611,7 +1650,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, Locations* activeLocations = locations; // Try to use the Batch - gpu::Batch batch; + //gpu::Batch batch; /*if (isSkinned) { skinProgram->bind(); @@ -1868,7 +1907,6 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, //activeProgram->release(); GLBATCH(glUseProgram)(0); - ::gpu::backend::renderBatch(batch); return meshPartsRendered; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 86fa0c2b7a..b6c9987807 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -36,6 +36,10 @@ class ViewFrustum; typedef QSharedPointer AnimationHandlePointer; typedef QWeakPointer WeakAnimationHandlePointer; +namespace gpu { + class Batch; +} + /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { Q_OBJECT @@ -252,7 +256,7 @@ private: void applyNextGeometry(); void deleteGeometry(); - int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); QVector createJointStates(const FBXGeometry& geometry); void initJointTransforms(); From 86819b934439209cd9b662c8e35f67d7e061ac74 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 21 Oct 2014 18:03:53 -0700 Subject: [PATCH 27/29] fix endline on Batch.cpp --- interface/src/gpu/Batch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index ddc5a9f24f..945ccd4feb 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -621,4 +621,4 @@ void backend::renderBatch(Batch& batch) { for (int i = 0; i < batch._commands.size(); i++) { batch.runCommand(i); } -} \ No newline at end of file +} From 057c17fd2fa0641a1422fb5315f2b2f44647e3a8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 21 Oct 2014 18:14:26 -0700 Subject: [PATCH 28/29] fix suseless spaces around parameters in functions --- interface/src/gpu/Batch.cpp | 8 ++++---- interface/src/gpu/Batch.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp index 945ccd4feb..8a094d1024 100644 --- a/interface/src/gpu/Batch.cpp +++ b/interface/src/gpu/Batch.cpp @@ -111,7 +111,7 @@ void Batch::runCommand(Command com, uint32 offset) { } } -void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { +void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) { ADD_COMMAND(draw); _params.push_back(startVertex); @@ -119,7 +119,7 @@ void Batch::draw( Primitive primitiveType, int nbVertices, int startVertex) { _params.push_back(primitiveType); } -void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) { +void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) { ADD_COMMAND(drawIndexed); _params.push_back(startIndex); @@ -127,7 +127,7 @@ void Batch::drawIndexed( Primitive primitiveType, int nbIndices, int startIndex) _params.push_back(primitiveType); } -void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { +void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { ADD_COMMAND(drawInstanced); _params.push_back(startInstance); @@ -137,7 +137,7 @@ void Batch::drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVe _params.push_back(nbInstances); } -void Batch::drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { +void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { ADD_COMMAND(drawIndexedInstanced); _params.push_back(startInstance); diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h index 567740511e..60c9c2d645 100644 --- a/interface/src/gpu/Batch.h +++ b/interface/src/gpu/Batch.h @@ -49,10 +49,10 @@ public: void clear(); - void draw( Primitive primitiveType, int nbVertices, int startVertex = 0); - void drawIndexed( Primitive primitiveType, int nbIndices, int startIndex = 0 ); - void drawInstanced( uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); - void drawIndexedInstanced( uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); + void draw(Primitive primitiveType, int nbVertices, int startVertex = 0); + void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0); + void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); + void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long From f76d060de3dd99dc6da584274b8387f872cf1ebc Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 21 Oct 2014 20:22:44 -0700 Subject: [PATCH 29/29] Revert "Record graphics API commands in a "gpu::Batch" to separate traversal from rendering" --- interface/src/gpu/Batch.cpp | 624 ------------------------------- interface/src/gpu/Batch.h | 316 ---------------- interface/src/renderer/Model.cpp | 316 ++++++---------- interface/src/renderer/Model.h | 6 +- 4 files changed, 121 insertions(+), 1141 deletions(-) delete mode 100644 interface/src/gpu/Batch.cpp delete mode 100644 interface/src/gpu/Batch.h diff --git a/interface/src/gpu/Batch.cpp b/interface/src/gpu/Batch.cpp deleted file mode 100644 index 8a094d1024..0000000000 --- a/interface/src/gpu/Batch.cpp +++ /dev/null @@ -1,624 +0,0 @@ -// -// Batch.cpp -// interface/src/gpu -// -// Created by Sam Gateau on 10/14/2014. -// Copyright 2014 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 "Batch.h" - -#include - -#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size()); - -//#define DO_IT_NOW(call, offset) runLastCommand(); -#define DO_IT_NOW(call, offset) - -using namespace gpu; - -Batch::Batch() : - _commands(), - _commandCalls(), - _commandOffsets(), - _params(), - _resources(), - _data(){ -} - -Batch::~Batch() { -} - -void Batch::clear() { - _commands.clear(); - _commandCalls.clear(); - _commandOffsets.clear(); - _params.clear(); - _resources.clear(); - _data.clear(); -} - -uint32 Batch::cacheResource(Resource* res) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(res)); - - return offset; -} - -uint32 Batch::cacheResource(const void* pointer) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(pointer)); - - return offset; -} - -uint32 Batch::cacheData(uint32 size, const void* data) { - uint32 offset = _data.size(); - uint32 nbBytes = size; - _data.resize(offset + nbBytes); - memcpy(_data.data() + offset, data, size); - - return offset; -} - -#define CASE_COMMAND(call) case COMMAND_##call: { do_##call(offset); } break; - -void Batch::runCommand(Command com, uint32 offset) { - switch (com) { - CASE_COMMAND(draw); - CASE_COMMAND(drawIndexed); - CASE_COMMAND(drawInstanced); - CASE_COMMAND(drawIndexedInstanced); - CASE_COMMAND(glEnable); - CASE_COMMAND(glDisable); - CASE_COMMAND(glEnableClientState); - CASE_COMMAND(glDisableClientState); - CASE_COMMAND(glCullFace); - CASE_COMMAND(glAlphaFunc); - CASE_COMMAND(glDepthFunc); - CASE_COMMAND(glDepthMask); - CASE_COMMAND(glDepthRange); - CASE_COMMAND(glBindBuffer); - CASE_COMMAND(glBindTexture); - CASE_COMMAND(glActiveTexture); - CASE_COMMAND(glDrawBuffers); - CASE_COMMAND(glUseProgram); - CASE_COMMAND(glUniform1f); - CASE_COMMAND(glUniformMatrix4fv); - CASE_COMMAND(glMatrixMode); - CASE_COMMAND(glPushMatrix); - CASE_COMMAND(glPopMatrix); - CASE_COMMAND(glMultMatrixf); - CASE_COMMAND(glLoadMatrixf); - CASE_COMMAND(glLoadIdentity); - CASE_COMMAND(glRotatef); - CASE_COMMAND(glScalef); - CASE_COMMAND(glTranslatef); - CASE_COMMAND(glDrawArrays); - CASE_COMMAND(glDrawRangeElements); - CASE_COMMAND(glColorPointer); - CASE_COMMAND(glNormalPointer); - CASE_COMMAND(glTexCoordPointer); - CASE_COMMAND(glVertexPointer); - CASE_COMMAND(glVertexAttribPointer); - CASE_COMMAND(glEnableVertexAttribArray); - CASE_COMMAND(glDisableVertexAttribArray); - CASE_COMMAND(glColor4f); - CASE_COMMAND(glMaterialf); - CASE_COMMAND(glMaterialfv); - } -} - -void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) { - ADD_COMMAND(draw); - - _params.push_back(startVertex); - _params.push_back(nbVertices); - _params.push_back(primitiveType); -} - -void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) { - ADD_COMMAND(drawIndexed); - - _params.push_back(startIndex); - _params.push_back(nbIndices); - _params.push_back(primitiveType); -} - -void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) { - ADD_COMMAND(drawInstanced); - - _params.push_back(startInstance); - _params.push_back(startVertex); - _params.push_back(nbVertices); - _params.push_back(primitiveType); - _params.push_back(nbInstances); -} - -void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) { - ADD_COMMAND(drawIndexedInstanced); - - _params.push_back(startInstance); - _params.push_back(startIndex); - _params.push_back(nbIndices); - _params.push_back(primitiveType); - _params.push_back(nbInstances); -} - -// TODO: As long as we have gl calls explicitely issued from interface -// code, we need to be able to record and batch these calls. THe long -// term strategy is to get rid of any GL calls in favor of the HIFI GPU API - -void Batch::_glEnable(GLenum cap) { - ADD_COMMAND(glEnable); - - _params.push_back(cap); - - DO_IT_NOW(_glEnable, 1); -} -void Batch::do_glEnable(uint32& paramOffset) { - glEnable(_params[paramOffset++]._uint); -} - -void Batch::_glDisable(GLenum cap) { - ADD_COMMAND(glDisable); - - _params.push_back(cap); - - DO_IT_NOW(_glDisable, 1); -} -void Batch::do_glDisable(uint32& paramOffset) { - glDisable(_params[paramOffset++]._uint); -} - -void Batch::_glEnableClientState(GLenum array) { - ADD_COMMAND(glEnableClientState); - - _params.push_back(array); - - DO_IT_NOW(_glEnableClientState, 1 ); -} -void Batch::do_glEnableClientState(uint32& paramOffset) { - glEnableClientState(_params[paramOffset++]._uint); -} - -void Batch::_glDisableClientState(GLenum array) { - ADD_COMMAND(glDisableClientState); - - _params.push_back(array); - - DO_IT_NOW(_glDisableClientState, 1); -} -void Batch::do_glDisableClientState(uint32& paramOffset) { - glDisableClientState(_params[paramOffset++]._uint); -} - -void Batch::_glCullFace(GLenum mode) { - ADD_COMMAND(glCullFace); - - _params.push_back(mode); - - DO_IT_NOW(_glCullFace, 1); -} -void Batch::do_glCullFace(uint32& paramOffset) { - glCullFace(_params[paramOffset++]._uint); -} - -void Batch::_glAlphaFunc(GLenum func, GLclampf ref) { - ADD_COMMAND(glAlphaFunc); - - _params.push_back(ref); - _params.push_back(func); - - DO_IT_NOW(_glAlphaFunc, 2); -} -void Batch::do_glAlphaFunc(uint32& paramOffset) { - glAlphaFunc(_params[paramOffset++]._uint, _params[paramOffset++]._float); -} - -void Batch::_glDepthFunc(GLenum func) { - ADD_COMMAND(glDepthFunc); - - _params.push_back(func); - - DO_IT_NOW(_glDepthFunc, 1); -} -void Batch::do_glDepthFunc(uint32& paramOffset) { - glDepthFunc(_params[paramOffset++]._uint); -} - -void Batch::_glDepthMask(GLboolean flag) { - ADD_COMMAND(glDepthMask); - - _params.push_back(flag); - - DO_IT_NOW(_glDepthMask, 1); -} -void Batch::do_glDepthMask(uint32& paramOffset) { - glDepthMask(_params[paramOffset++]._uint); -} - -void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { - ADD_COMMAND(glDepthRange); - - _params.push_back(zFar); - _params.push_back(zNear); - - DO_IT_NOW(_glDepthRange, 2); -} -void Batch::do_glDepthRange(uint32& paramOffset) { - glDepthRange(_params[paramOffset++]._double, _params[paramOffset++]._double); -} - -void Batch::_glBindBuffer(GLenum target, GLuint buffer) { - ADD_COMMAND(glBindBuffer); - - _params.push_back(buffer); - _params.push_back(target); - - DO_IT_NOW(_glBindBuffer, 2); -} -void Batch::do_glBindBuffer(uint32& paramOffset) { - glBindBuffer(_params[paramOffset++]._uint, _params[paramOffset++]._uint); -} - -void Batch::_glBindTexture(GLenum target, GLuint texture) { - ADD_COMMAND(glBindTexture); - - _params.push_back(texture); - _params.push_back(target); - - DO_IT_NOW(_glBindTexture, 2); -} -void Batch::do_glBindTexture(uint32& paramOffset) { - glBindTexture(_params[paramOffset++]._uint, _params[paramOffset++]._uint); -} - -void Batch::_glActiveTexture(GLenum texture) { - ADD_COMMAND(glActiveTexture); - - _params.push_back(texture); - - DO_IT_NOW(_glActiveTexture, 1); -} -void Batch::do_glActiveTexture(uint32& paramOffset) { - glActiveTexture(_params[paramOffset++]._uint); -} - -void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) { - ADD_COMMAND(glDrawBuffers); - - _params.push_back(cacheData(n * sizeof(GLenum), bufs)); - _params.push_back(n); - - DO_IT_NOW(_glDrawBuffers, 2); -} -void Batch::do_glDrawBuffers(uint32& paramOffset) { - glDrawBuffers(_params[paramOffset++]._uint, (const GLenum*) editData(_params[paramOffset++]._uint)); -} - -void Batch::_glUseProgram(GLuint program) { - ADD_COMMAND(glUseProgram); - - _params.push_back(program); - - DO_IT_NOW(_glUseProgram, 1); -} -void Batch::do_glUseProgram(uint32& paramOffset) { - glUseProgram(_params[paramOffset++]._uint); -} - -void Batch::_glUniform1f(GLint location, GLfloat v0) { - ADD_COMMAND(glUniform1f); - - _params.push_back(v0); - _params.push_back(location); - - DO_IT_NOW(_glUniform1f, 1); -} -void Batch::do_glUniform1f(uint32& paramOffset) { - glUniform1f(_params[paramOffset++]._int, _params[paramOffset++]._float); -} - -void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - ADD_COMMAND(glUniformMatrix4fv); - - const int MATRIX4_SIZE = 16 * sizeof(float); - _params.push_back(cacheData(count * MATRIX4_SIZE, value)); - _params.push_back(transpose); - _params.push_back(count); - _params.push_back(location); - - DO_IT_NOW(_glUniformMatrix4fv, 4); -} -void Batch::do_glUniformMatrix4fv(uint32& paramOffset) { - glUniformMatrix4fv(_params[paramOffset++]._int, _params[paramOffset++]._uint, - _params[paramOffset++]._uint, (const GLfloat*) editData(_params[paramOffset++]._uint)); -} - -void Batch::_glMatrixMode(GLenum mode) { - ADD_COMMAND(glMatrixMode); - - _params.push_back(mode); - - DO_IT_NOW(_glMatrixMode, 1); -} -void Batch::do_glMatrixMode(uint32& paramOffset) { - glMatrixMode(_params[paramOffset++]._uint); -} - -void Batch::_glPushMatrix() { - ADD_COMMAND(glPushMatrix); - - DO_IT_NOW(_glPushMatrix, 0); -} -void Batch::do_glPushMatrix(uint32& paramOffset) { - glPushMatrix(); -} - -void Batch::_glPopMatrix() { - ADD_COMMAND(glPopMatrix); - - DO_IT_NOW(_glPopMatrix, 0); -} -void Batch::do_glPopMatrix(uint32& paramOffset) { - glPopMatrix(); -} - -void Batch::_glMultMatrixf(const GLfloat *m) { - ADD_COMMAND(glMultMatrixf); - - const int MATRIX4_SIZE = 16 * sizeof(float); - _params.push_back(cacheData(MATRIX4_SIZE, m)); - - DO_IT_NOW(_glMultMatrixf, 1); -} -void Batch::do_glMultMatrixf(uint32& paramOffset) { - glMultMatrixf((const GLfloat*) editData(_params[paramOffset++]._uint)); -} - -void Batch::_glLoadMatrixf(const GLfloat *m) { - ADD_COMMAND(glLoadMatrixf); - - const int MATRIX4_SIZE = 16 * sizeof(float); - _params.push_back(cacheData(MATRIX4_SIZE, m)); - - DO_IT_NOW(_glLoadMatrixf, 1); -} -void Batch::do_glLoadMatrixf(uint32& paramOffset) { - glLoadMatrixf((const GLfloat*)editData(_params[paramOffset++]._uint)); -} - -void Batch::_glLoadIdentity(void) { - ADD_COMMAND(glLoadIdentity); - - DO_IT_NOW(_glLoadIdentity, 0); -} -void Batch::do_glLoadIdentity(uint32& paramOffset) { - glLoadIdentity(); -} - -void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glRotatef); - - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - _params.push_back(angle); - - DO_IT_NOW(_glRotatef, 4); -} -void Batch::do_glRotatef(uint32& paramOffset) { - glRotatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glScalef); - - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - - DO_IT_NOW(_glScalef, 3); -} -void Batch::do_glScalef(uint32& paramOffset) { - glScalef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) { - ADD_COMMAND(glTranslatef); - - _params.push_back(z); - _params.push_back(y); - _params.push_back(x); - - DO_IT_NOW(_glTranslatef, 3); -} -void Batch::do_glTranslatef(uint32& paramOffset) { - glTranslatef(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { - ADD_COMMAND(glDrawArrays); - - _params.push_back(count); - _params.push_back(first); - _params.push_back(mode); - - DO_IT_NOW(_glDrawArrays, 3); -} -void Batch::do_glDrawArrays(uint32& paramOffset) { - glDrawArrays(_params[paramOffset++]._uint, _params[paramOffset++]._int, _params[paramOffset++]._int); -} - -void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { - ADD_COMMAND(glDrawRangeElements); - - _params.push_back(cacheResource(indices)); - _params.push_back(type); - _params.push_back(count); - _params.push_back(end); - _params.push_back(start); - _params.push_back(mode); - - //do_glDrawRangeElements(_commandOffsets.back()); - // runCommand(_commands.size() - 1); - DO_IT_NOW(_glDrawRangeElements, 6); -} -void Batch::do_glDrawRangeElements(uint32& paramOffset) { - glDrawRangeElements(_params[paramOffset++]._uint, _params[paramOffset++]._uint, - _params[paramOffset++]._uint, _params[paramOffset++]._int, - _params[paramOffset++]._uint, editResource(_params[paramOffset++]._uint)->_pointer); -} - -void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glColorPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glColorPointer, 4); -} -void Batch::do_glColorPointer(uint32& paramOffset) { - glColorPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, - _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); -} - -void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glNormalPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - - DO_IT_NOW(_glNormalPointer, 3); -} -void Batch::do_glNormalPointer(uint32& paramOffset) { - glNormalPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, - editResource(_params[paramOffset++]._uint)->_pointer); -} - -void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glTexCoordPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glTexCoordPointer, 4); -} -void Batch::do_glTexCoordPointer(uint32& paramOffset) { - glTexCoordPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, - _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); -} - -void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND(glVertexPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glVertexPointer, 4); -} -void Batch::do_glVertexPointer(uint32& paramOffset) { - glVertexPointer(_params[paramOffset++]._int, _params[paramOffset++]._uint, - _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); -} - - -void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { - ADD_COMMAND(glVertexAttribPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(normalized); - _params.push_back(type); - _params.push_back(size); - _params.push_back(index); - - DO_IT_NOW(_glVertexAttribPointer, 6); -} -void Batch::do_glVertexAttribPointer(uint32& paramOffset) { - glVertexAttribPointer(_params[paramOffset++]._uint, _params[paramOffset++]._int, - _params[paramOffset++]._uint, _params[paramOffset++]._uint, - _params[paramOffset++]._int, editResource(_params[paramOffset++]._uint)->_pointer); -} - - - -void Batch::_glEnableVertexAttribArray(GLint location) { - ADD_COMMAND(glEnableVertexAttribArray); - - _params.push_back(location); - - DO_IT_NOW(_glEnableVertexAttribArray, 1); -} -void Batch::do_glEnableVertexAttribArray(uint32& paramOffset) { - glEnableVertexAttribArray(_params[paramOffset++]._uint); -} - -void Batch::_glDisableVertexAttribArray(GLint location) { - ADD_COMMAND(glDisableVertexAttribArray); - - _params.push_back(location); - - DO_IT_NOW(_glDisableVertexAttribArray, 1); -} -void Batch::do_glDisableVertexAttribArray(uint32& paramOffset) { - glDisableVertexAttribArray(_params[paramOffset++]._uint); -} - -void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - ADD_COMMAND(glColor4f); - - _params.push_back(alpha); - _params.push_back(blue); - _params.push_back(green); - _params.push_back(red); - - DO_IT_NOW(_glColor4f, 4); -} -void Batch::do_glColor4f(uint32& paramOffset) { - glColor4f(_params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float, _params[paramOffset++]._float); -} - -void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) { - ADD_COMMAND(glMaterialf); - - _params.push_back(param); - _params.push_back(pname); - _params.push_back(face); - - DO_IT_NOW(_glMaterialf, 3); -} -void Batch::do_glMaterialf(uint32& paramOffset) { - glMaterialf(_params[paramOffset++]._uint, _params[paramOffset++]._uint, _params[paramOffset++]._float); -} - -void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { - ADD_COMMAND(glMaterialfv); - - _params.push_back(cacheData(4 * sizeof(float), params)); - _params.push_back(pname); - _params.push_back(face); - - DO_IT_NOW(_glMaterialfv, 3); -} -void Batch::do_glMaterialfv(uint32& paramOffset) { - glMaterialfv(_params[paramOffset++]._uint, _params[paramOffset++]._uint, (const GLfloat*) editData(_params[paramOffset++]._uint)); -} - - - -void backend::renderBatch(Batch& batch) { - for (int i = 0; i < batch._commands.size(); i++) { - batch.runCommand(i); - } -} diff --git a/interface/src/gpu/Batch.h b/interface/src/gpu/Batch.h deleted file mode 100644 index 60c9c2d645..0000000000 --- a/interface/src/gpu/Batch.h +++ /dev/null @@ -1,316 +0,0 @@ -// -// Batch.h -// interface/src/gpu -// -// Created by Sam Gateau on 10/14/2014. -// Copyright 2014 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_gpu_Batch_h -#define hifi_gpu_Batch_h - -#include -#include "InterfaceConfig.h" - -#include - -namespace gpu { - -class Batch; -// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience -namespace backend { - - void renderBatch(Batch& batch); -}; - -class Buffer; -class Resource; -typedef int Stamp; -typedef unsigned int uint32; -typedef int int32; - -enum Primitive { - PRIMITIVE_POINTS = 0, - PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP, - PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_QUADS, -}; - -class Batch { -public: - - Batch(); - Batch(const Batch& batch); - ~Batch(); - - void clear(); - - void draw(Primitive primitiveType, int nbVertices, int startVertex = 0); - void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0); - void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0); - void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0); - - // TODO: As long as we have gl calls explicitely issued from interface - // code, we need to be able to record and batch these calls. THe long - // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - void _glEnable(GLenum cap); - void _glDisable(GLenum cap); - - void _glEnableClientState(GLenum array); - void _glDisableClientState(GLenum array); - - void _glCullFace(GLenum mode); - void _glAlphaFunc(GLenum func, GLclampf ref); - - void _glDepthFunc(GLenum func); - void _glDepthMask(GLboolean flag); - void _glDepthRange(GLclampd zNear, GLclampd zFar); - - void _glBindBuffer(GLenum target, GLuint buffer); - - void _glBindTexture(GLenum target, GLuint texture); - void _glActiveTexture(GLenum texture); - - void _glDrawBuffers(GLsizei n, const GLenum* bufs); - - void _glUseProgram(GLuint program); - void _glUniform1f(GLint location, GLfloat v0); - void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); - - void _glMatrixMode(GLenum mode); - void _glPushMatrix(); - void _glPopMatrix(); - void _glMultMatrixf(const GLfloat *m); - void _glLoadMatrixf(const GLfloat *m); - void _glLoadIdentity(void); - void _glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); - void _glScalef(GLfloat x, GLfloat y, GLfloat z); - void _glTranslatef(GLfloat x, GLfloat y, GLfloat z); - - void _glDrawArrays(GLenum mode, GLint first, GLsizei count); - void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); - - void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer); - void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - - void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); - void _glEnableVertexAttribArray(GLint location); - void _glDisableVertexAttribArray(GLint location); - - void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); - - void _glMaterialf(GLenum face, GLenum pname, GLfloat param); - void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); - - -protected: - - enum Command { - COMMAND_draw = 0, - COMMAND_drawIndexed, - COMMAND_drawInstanced, - COMMAND_drawIndexedInstanced, - - COMMAND_SET_PIPE_STATE, - COMMAND_SET_VIEWPORT, - COMMAND_SET_FRAMEBUFFER, - COMMAND_SET_RESOURCE, - COMMAND_SET_VERTEX_STREAM, - COMMAND_SET_INDEX_STREAM, - - // TODO: As long as we have gl calls explicitely issued from interface - // code, we need to be able to record and batch these calls. THe long - // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - COMMAND_glEnable, - COMMAND_glDisable, - - COMMAND_glEnableClientState, - COMMAND_glDisableClientState, - - COMMAND_glCullFace, - COMMAND_glAlphaFunc, - - COMMAND_glDepthFunc, - COMMAND_glDepthMask, - COMMAND_glDepthRange, - - COMMAND_glBindBuffer, - - COMMAND_glBindTexture, - COMMAND_glActiveTexture, - - COMMAND_glDrawBuffers, - - COMMAND_glUseProgram, - COMMAND_glUniform1f, - COMMAND_glUniformMatrix4fv, - - COMMAND_glMatrixMode, - COMMAND_glPushMatrix, - COMMAND_glPopMatrix, - COMMAND_glMultMatrixf, - COMMAND_glLoadMatrixf, - COMMAND_glLoadIdentity, - COMMAND_glRotatef, - COMMAND_glScalef, - COMMAND_glTranslatef, - - COMMAND_glDrawArrays, - COMMAND_glDrawRangeElements, - - COMMAND_glColorPointer, - COMMAND_glNormalPointer, - COMMAND_glTexCoordPointer, - COMMAND_glVertexPointer, - - COMMAND_glVertexAttribPointer, - COMMAND_glEnableVertexAttribArray, - COMMAND_glDisableVertexAttribArray, - - COMMAND_glColor4f, - - COMMAND_glMaterialf, - COMMAND_glMaterialfv, - }; - typedef std::vector Commands; - typedef void (Batch::*CommandCall)(uint32&); - typedef std::vector CommandCalls; - typedef std::vector CommandOffsets; - - - class Param { - public: - union { - int32 _int; - uint32 _uint; - float _float; - char _chars[4]; - double _double; - }; - Param(int32 val) : _int(val) {} - Param(uint32 val) : _uint(val) {} - Param(float val) : _float(val) {} - Param(double val) : _double(val) {} - }; - typedef std::vector Params; - - class ResourceCache { - public: - union { - Resource* _resource; - const void* _pointer; - }; - ResourceCache(Resource* res) : _resource(res) {} - ResourceCache(const void* pointer) : _pointer(pointer) {} - }; - typedef std::vector Resources; - - typedef unsigned char Byte; - typedef std::vector Bytes; - - Commands _commands; - CommandCalls _commandCalls; - CommandOffsets _commandOffsets; - Params _params; - Resources _resources; - Bytes _data; - - uint32 cacheResource(Resource* res); - uint32 cacheResource(const void* pointer); - ResourceCache* editResource(uint32 offset) { - if (offset >= _resources.size()) - return 0; - return (_resources.data() + offset); - } - - uint32 cacheData(uint32 size, const void* data); - Byte* editData(uint32 offset) { - if (offset >= _data.size()) - return 0; - return (_data.data() + offset); - } - - void runCommand(uint32 index) { - uint32 offset = _commandOffsets[index]; - CommandCall call = _commandCalls[index]; - (this->*(call))(offset); - } - - void runLastCommand() { - uint32 index = _commands.size() - 1; - runCommand(index); - } - - void runCommand(Command com, uint32 offset); - - void do_draw(uint32& paramOffset) {} - void do_drawIndexed(uint32& paramOffset) {} - void do_drawInstanced(uint32& paramOffset) {} - void do_drawIndexedInstanced(uint32& paramOffset) {} - - // TODO: As long as we have gl calls explicitely issued from interface - // code, we need to be able to record and batch these calls. THe long - // term strategy is to get rid of any GL calls in favor of the HIFI GPU API - void do_glEnable(uint32& paramOffset); - void do_glDisable(uint32& paramOffset); - - void do_glEnableClientState(uint32& paramOffset); - void do_glDisableClientState(uint32& paramOffset); - - void do_glCullFace(uint32& paramOffset); - void do_glAlphaFunc(uint32& paramOffset); - - void do_glDepthFunc(uint32& paramOffset); - void do_glDepthMask(uint32& paramOffset); - void do_glDepthRange(uint32& paramOffset); - - void do_glBindBuffer(uint32& paramOffset); - - void do_glBindTexture(uint32& paramOffset); - void do_glActiveTexture(uint32& paramOffset); - - void do_glDrawBuffers(uint32& paramOffset); - - void do_glUseProgram(uint32& paramOffset); - void do_glUniform1f(uint32& paramOffset); - void do_glUniformMatrix4fv(uint32& paramOffset); - - void do_glMatrixMode(uint32& paramOffset); - void do_glPushMatrix(uint32& paramOffset); - void do_glPopMatrix(uint32& paramOffset); - void do_glMultMatrixf(uint32& paramOffset); - void do_glLoadMatrixf(uint32& paramOffset); - void do_glLoadIdentity(uint32& paramOffset); - void do_glRotatef(uint32& paramOffset); - void do_glScalef(uint32& paramOffset); - void do_glTranslatef(uint32& paramOffset); - - void do_glDrawArrays(uint32& paramOffset); - void do_glDrawRangeElements(uint32& paramOffset); - - void do_glColorPointer(uint32& paramOffset); - void do_glNormalPointer(uint32& paramOffset); - void do_glTexCoordPointer(uint32& paramOffset); - void do_glVertexPointer(uint32& paramOffset); - - void do_glVertexAttribPointer(uint32& paramOffset); - void do_glEnableVertexAttribArray(uint32& paramOffset); - void do_glDisableVertexAttribArray(uint32& paramOffset); - - void do_glColor4f(uint32& paramOffset); - - void do_glMaterialf(uint32& paramOffset); - void do_glMaterialfv(uint32& paramOffset); - - friend void backend::renderBatch(Batch& batch); -}; - -}; - -#endif diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 739f5d75b1..3800e78008 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -26,10 +26,6 @@ #include "Application.h" #include "Model.h" -#include "gpu/Batch.h" -#define GLBATCH( call ) batch._##call -//#define GLBATCH( call ) call - using namespace std; static int modelPointerTypeId = qRegisterMetaType >(); @@ -434,135 +430,97 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { segregateMeshGroups(); } - // Let's introduce a gpu::Batch to capture all the calls to the graphics api - gpu::Batch batch; - - GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY); - - GLBATCH(glDisable)(GL_COLOR_MATERIAL); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glDisable(GL_COLOR_MATERIAL); if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { - GLBATCH(glDisable)(GL_CULL_FACE); + glDisable(GL_CULL_FACE); } else { - GLBATCH(glEnable)(GL_CULL_FACE); + glEnable(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_FRONT); + glCullFace(GL_FRONT); } } // render opaque meshes with alpha testing - - GLBATCH(glDisable)(GL_BLEND); - GLBATCH(glEnable)(GL_ALPHA_TEST); + + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); + glAlphaFunc(GL_EQUAL, 0.0f); } - - - /*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( + + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers( mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, mode == DEFAULT_RENDER_MODE); - */ - { - GLenum buffers[3]; - int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - } - if (mode == DEFAULT_RENDER_MODE) { - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - } - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - + const float DEFAULT_ALPHA_THRESHOLD = 0.5f; - //renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args); int opaqueMeshPartsRendered = 0; - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); - opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); - + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args); + opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args); + // render translucent meshes afterwards - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); - { - GLenum buffers[2]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true); int translucentMeshPartsRendered = 0; const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); - - GLBATCH(glDisable)(GL_ALPHA_TEST); - GLBATCH(glEnable)(GL_BLEND); - GLBATCH(glDepthMask)(false); - GLBATCH(glDepthFunc)(GL_LEQUAL); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args); + + glDisable(GL_ALPHA_TEST); + glEnable(GL_BLEND); + glDepthMask(false); + glDepthFunc(GL_LEQUAL); + + Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); - //Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true); - { - GLenum buffers[1]; - int bufferCount = 0; - buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; - GLBATCH(glDrawBuffers)(bufferCount, buffers); - } - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); - translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args); + translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args); } - - GLBATCH(glDepthMask)(true); - GLBATCH(glDepthFunc)(GL_LESS); - GLBATCH(glDisable)(GL_CULL_FACE); + + glDepthMask(true); + glDepthFunc(GL_LESS); + glDisable(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glCullFace)(GL_BACK); + glCullFace(GL_BACK); } - + // deactivate vertex arrays after drawing - GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY); - GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY); - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); // bind with 0 to switch back to normal operation - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - - // Render! - ::gpu::backend::renderBatch(batch); - batch.clear(); - + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + // restore all the default material settings Application::getInstance()->setupWorldLight(); @@ -1548,7 +1506,7 @@ void Model::segregateMeshGroups() { _meshGroupsKnown = true; } -int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, +int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) { bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts); @@ -1648,30 +1606,16 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl ProgramObject* activeProgram = program; Locations* activeLocations = locations; - - // Try to use the Batch - //gpu::Batch batch; - - /*if (isSkinned) { + + if (isSkinned) { skinProgram->bind(); activeProgram = skinProgram; activeLocations = skinLocations; } else { program->bind(); - }*/ - if (isSkinned) { - activeProgram = skinProgram; - activeLocations = skinLocations; } - if (!activeProgram->isLinked()) { - activeProgram->link(); - } - GLBATCH(glUseProgram)(activeProgram->programId()); - // activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); - GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); - - - + activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold); + // i is the "index" from the original networkMeshes QVector... foreach (int i, list) { @@ -1687,8 +1631,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); - //const_cast(networkMesh.indexBuffer).bind(); - GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast(networkMesh.indexBuffer).bufferId()); + const_cast(networkMesh.indexBuffer).bind(); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1723,70 +1666,56 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } } - //const_cast(networkMesh.vertexBuffer).bind(); - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast(networkMesh.vertexBuffer).bufferId()); - - GLBATCH(glPushMatrix)(); - //Application::getInstance()->loadTranslatedViewMatrix(_translation); - GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix()); - glm::vec3 viewMatTranslation = Application::getInstance()->getViewMatrixTranslation(); - GLBATCH(glTranslatef)(_translation.x + viewMatTranslation.x, _translation.y + viewMatTranslation.y, - _translation.z + viewMatTranslation.z); + const_cast(networkMesh.vertexBuffer).bind(); + + glPushMatrix(); + Application::getInstance()->loadTranslatedViewMatrix(_translation); const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, + glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) + mesh.texCoords.size() * sizeof(glm::vec2) + (mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0); - //skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); - GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, (const void*) offset); - //skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, - // offset + vertexCount * sizeof(glm::vec4), 4); - GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4))); - //skinProgram->enableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices); - //skinProgram->enableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights); + skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4); + skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT, + offset + vertexCount * sizeof(glm::vec4), 4); + skinProgram->enableAttributeArray(skinLocations->clusterIndices); + skinProgram->enableAttributeArray(skinLocations->clusterWeights); } else { - GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]); + glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); } if (mesh.blendshapes.isEmpty()) { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); - GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3))); - //activeProgram->enableAttributeArray(activeLocations->tangent); - GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); + activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); + activeProgram->enableAttributeArray(activeLocations->tangent); } - GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + + glColorPointer(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + mesh.tangents.size() * sizeof(glm::vec3))); - GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + + glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) + (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); } else { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - //activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); - GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0); - //activeProgram->enableAttributeArray(activeLocations->tangent); - GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent); + activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3); + activeProgram->enableAttributeArray(activeLocations->tangent); } - GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); - GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); - // _blendedVertexBuffers[i].bind(); - GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId()); + glColorPointer(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3))); + glTexCoordPointer(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); + _blendedVertexBuffers[i].bind(); } - GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0); - GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); + glVertexPointer(3, GL_FLOAT, 0, 0); + glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3))); if (!mesh.colors.isEmpty()) { - GLBATCH(glEnableClientState)(GL_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); } else { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } if (!mesh.texCoords.isEmpty()) { - GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); } qint64 offset = 0; @@ -1797,10 +1726,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int); continue; } - // apply material properties if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); } else { if (dontReduceMaterialSwitches || lastMaterialID != part.materialID) { @@ -1813,36 +1741,36 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); if (!(translucent && alphaThreshold == 0.0f)) { - GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); + glAlphaFunc(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); } glm::vec4 specular = glm::vec4(part.specularColor, 1.0f); - GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); - GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); - GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular); - GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, part.shininess); + glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); + glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular); + glMaterialf(GL_FRONT, GL_SHININESS, part.shininess); Texture* diffuseMap = networkPart.diffuseTexture.data(); if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); } - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ? + glBindTexture(GL_TEXTURE_2D, !diffuseMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); if (!mesh.tangents.isEmpty()) { - GLBATCH(glActiveTexture)(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE1); Texture* normalMap = networkPart.normalTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ? + glBindTexture(GL_TEXTURE_2D, !normalMap ? Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); - GLBATCH(glActiveTexture)(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); } if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); + glActiveTexture(specularTextureUnit); Texture* specularMap = networkPart.specularTexture.data(); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ? + glBindTexture(GL_TEXTURE_2D, !specularMap ? Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID()); - GLBATCH(glActiveTexture)(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); } if (args) { args->_materialSwitches++; @@ -1855,12 +1783,12 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl meshPartsRendered++; if (part.quadIndices.size() > 0) { - GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); + glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.quadIndices.size() * sizeof(int); } if (part.triangleIndices.size() > 0) { - GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), + glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.triangleIndices.size() * sizeof(int); } @@ -1874,39 +1802,35 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } if (!mesh.colors.isEmpty()) { - GLBATCH(glDisableClientState)(GL_COLOR_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); } if (!mesh.texCoords.isEmpty()) { - GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { - GLBATCH(glActiveTexture)(GL_TEXTURE1); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); - // activeProgram->disableAttributeArray(activeLocations->tangent); - GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent); + activeProgram->disableAttributeArray(activeLocations->tangent); } if (specularTextureUnit) { - GLBATCH(glActiveTexture)(specularTextureUnit); - GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); - GLBATCH(glActiveTexture)(GL_TEXTURE0); + glActiveTexture(specularTextureUnit); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); } if (state.clusterMatrices.size() > 1) { - // skinProgram->disableAttributeArray(skinLocations->clusterIndices); - GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices); - // skinProgram->disableAttributeArray(skinLocations->clusterWeights); - GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights); + skinProgram->disableAttributeArray(skinLocations->clusterIndices); + skinProgram->disableAttributeArray(skinLocations->clusterWeights); } - GLBATCH(glPopMatrix)(); + glPopMatrix(); } - //activeProgram->release(); - GLBATCH(glUseProgram)(0); - + activeProgram->release(); + return meshPartsRendered; } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b6c9987807..86fa0c2b7a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -36,10 +36,6 @@ class ViewFrustum; typedef QSharedPointer AnimationHandlePointer; typedef QWeakPointer WeakAnimationHandlePointer; -namespace gpu { - class Batch; -} - /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { Q_OBJECT @@ -256,7 +252,7 @@ private: void applyNextGeometry(); void deleteGeometry(); - int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); + int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL); QVector createJointStates(const FBXGeometry& geometry); void initJointTransforms();