mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #3690 from ZappoMan/rayPickSubMeshes
Ray pick sub meshes
This commit is contained in:
commit
5b3897f1cf
41 changed files with 432 additions and 147 deletions
87
examples/testModelOverlaySubMeshes.js
Normal file
87
examples/testModelOverlaySubMeshes.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
var position = Vec3.sum(MyAvatar.position, { x: 0, y: -1, z: 0});
|
||||
|
||||
var scalingFactor = 0.01;
|
||||
|
||||
var sphereNaturalExtentsMin = { x: -1230, y: -1223, z: -1210 };
|
||||
var sphereNaturalExtentsMax = { x: 1230, y: 1229, z: 1223 };
|
||||
var panelsNaturalExtentsMin = { x: -1181, y: -326, z: 56 };
|
||||
var panelsNaturalExtentsMax = { x: 1181, y: 576, z: 1183 };
|
||||
|
||||
var sphereNaturalDimensions = Vec3.subtract(sphereNaturalExtentsMax, sphereNaturalExtentsMin);
|
||||
var panelsNaturalDimensions = Vec3.subtract(panelsNaturalExtentsMax, panelsNaturalExtentsMin);
|
||||
Vec3.print("sphereNaturalDimensions:", sphereNaturalDimensions);
|
||||
Vec3.print("panelsNaturalDimensions:", panelsNaturalDimensions);
|
||||
|
||||
var sphereNaturalCenter = Vec3.sum(sphereNaturalExtentsMin, Vec3.multiply(sphereNaturalDimensions, 0.5));
|
||||
var panelsNaturalCenter = Vec3.sum(panelsNaturalExtentsMin, Vec3.multiply(panelsNaturalDimensions, 0.5));
|
||||
Vec3.print("sphereNaturalCenter:", sphereNaturalCenter);
|
||||
Vec3.print("panelsNaturalCenter:", panelsNaturalCenter);
|
||||
|
||||
var sphereDimensions = Vec3.multiply(sphereNaturalDimensions, scalingFactor);
|
||||
var panelsDimensions = Vec3.multiply(panelsNaturalDimensions, scalingFactor);
|
||||
Vec3.print("sphereDimensions:", sphereDimensions);
|
||||
Vec3.print("panelsDimensions:", panelsDimensions);
|
||||
|
||||
var sphereCenter = Vec3.multiply(sphereNaturalCenter, scalingFactor);
|
||||
var panelsCenter = Vec3.multiply(panelsNaturalCenter, scalingFactor);
|
||||
Vec3.print("sphereCenter:", sphereCenter);
|
||||
Vec3.print("panelsCenter:", panelsCenter);
|
||||
|
||||
var centerShift = Vec3.subtract(panelsCenter, sphereCenter);
|
||||
Vec3.print("centerShift:", centerShift);
|
||||
|
||||
var spherePosition = position;
|
||||
Vec3.print("spherePosition:", spherePosition);
|
||||
var panelsPosition = Vec3.sum(spherePosition, centerShift);
|
||||
Vec3.print("panelsPosition:", panelsPosition);
|
||||
|
||||
|
||||
var screensOverlay = Overlays.addOverlay("model", {
|
||||
position: panelsPosition,
|
||||
dimensions: panelsDimensions,
|
||||
url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_IsolatedPanelsFreezeTransforms.fbx"
|
||||
});
|
||||
|
||||
|
||||
var structureOverlay = Overlays.addOverlay("model", {
|
||||
position: spherePosition,
|
||||
dimensions: sphereDimensions,
|
||||
url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_OrbShellOnly.fbx",
|
||||
ignoreRayIntersection: true, // we don't want to ray pick against any of this
|
||||
});
|
||||
|
||||
var statusText = Overlays.addOverlay("text", {
|
||||
x: 200,
|
||||
y: 100,
|
||||
width: 200,
|
||||
height: 20,
|
||||
backgroundColor: { red: 0, green: 0, blue: 0},
|
||||
alpha: 1.0,
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
topMargin: 4,
|
||||
leftMargin: 4,
|
||||
text: "",
|
||||
});
|
||||
|
||||
|
||||
Controller.mouseMoveEvent.connect(function(event){
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var result = Overlays.findRayIntersection(pickRay);
|
||||
|
||||
if (result.intersects) {
|
||||
if (result.overlayID == screensOverlay) {
|
||||
Overlays.editOverlay(statusText, { text: "You are pointing at: " + result.extraInfo });
|
||||
} else {
|
||||
Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." });
|
||||
}
|
||||
} else {
|
||||
Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Script.scriptEnding.connect(function(){
|
||||
Overlays.deleteOverlay(screensOverlay);
|
||||
Overlays.deleteOverlay(structureOverlay);
|
||||
Overlays.deleteOverlay(statusText);
|
||||
});
|
|
@ -2787,7 +2787,7 @@ void Application::updateShadowMap() {
|
|||
|
||||
{
|
||||
PerformanceTimer perfTimer("entities");
|
||||
_entities.render(OctreeRenderer::SHADOW_RENDER_MODE);
|
||||
_entities.render(RenderArgs::SHADOW_RENDER_MODE);
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <BoxEntityItem.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RenderArgs.h>
|
||||
|
||||
|
||||
#include "Menu.h"
|
||||
|
@ -67,7 +68,7 @@ void EntityTreeRenderer::update() {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::render(RenderMode renderMode) {
|
||||
void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode) {
|
||||
OctreeRenderer::render(renderMode);
|
||||
deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) {
|
||||
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
|
||||
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
|
||||
bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds);
|
||||
if (!isShadowMode && displayModelBounds) {
|
||||
PerformanceTimer perfTimer("renderProxies");
|
||||
|
@ -239,7 +240,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
|
|||
|
||||
uint16_t numberOfEntities = entityItems.size();
|
||||
|
||||
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
|
||||
bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE;
|
||||
bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy);
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <OctreePacketData.h>
|
||||
#include <OctreeRenderer.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
|
@ -48,7 +49,7 @@ public:
|
|||
void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE);
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||
|
||||
virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem);
|
||||
virtual const Model* getModelForEntityItem(const EntityItem* entityItem);
|
||||
|
|
|
@ -112,7 +112,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
// TODO: should we allow entityItems to have alpha on their models?
|
||||
Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE
|
||||
Model::RenderMode modelRenderMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE
|
||||
? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
|
||||
|
||||
if (_model->isActive()) {
|
||||
|
|
|
@ -36,6 +36,7 @@ using namespace std;
|
|||
static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
|
||||
static int weakNetworkGeometryPointerTypeId = qRegisterMetaType<QWeakPointer<NetworkGeometry> >();
|
||||
static int vec3VectorTypeId = qRegisterMetaType<QVector<glm::vec3> >();
|
||||
float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f;
|
||||
|
||||
Model::Model(QObject* parent) :
|
||||
QObject(parent),
|
||||
|
@ -124,35 +125,64 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
void Model::initProgram(ProgramObject& program, Model::Locations& locations, int specularTextureUnit) {
|
||||
program.bind();
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite
|
||||
glBindAttribLocation(program.programId(), 4, "tangent");
|
||||
glLinkProgram(program.programId());
|
||||
#endif
|
||||
|
||||
locations.tangent = program.attributeLocation("tangent");
|
||||
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
|
||||
program.setUniformValue("diffuseMap", 0);
|
||||
program.setUniformValue("normalMap", 1);
|
||||
program.setUniformValue("specularMap", specularTextureUnit);
|
||||
program.release();
|
||||
}
|
||||
|
||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) {
|
||||
initProgram(program, locations, specularTextureUnit);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite
|
||||
glBindAttribLocation(program.programId(), 5, "clusterIndices");
|
||||
glBindAttribLocation(program.programId(), 6, "clusterWeights");
|
||||
glLinkProgram(program.programId());
|
||||
#endif
|
||||
|
||||
program.bind();
|
||||
locations.clusterMatrices = program.uniformLocation("clusterMatrices");
|
||||
|
||||
locations.clusterIndices = program.attributeLocation("clusterIndices");
|
||||
locations.clusterWeights = program.attributeLocation("clusterWeights");
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
// HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite
|
||||
|
||||
glBindAttribLocation(program.programId(), 4, "tangent");
|
||||
|
||||
glLinkProgram(program.programId());
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
locations.tangent = program.attributeLocation("tangent");
|
||||
|
||||
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
|
||||
|
||||
program.setUniformValue("diffuseMap", 0);
|
||||
|
||||
program.setUniformValue("normalMap", 1);
|
||||
|
||||
program.setUniformValue("specularMap", specularTextureUnit);
|
||||
|
||||
program.release();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) {
|
||||
|
||||
initProgram(program, locations, specularTextureUnit);
|
||||
|
||||
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
// HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite
|
||||
|
||||
glBindAttribLocation(program.programId(), 5, "clusterIndices");
|
||||
|
||||
glBindAttribLocation(program.programId(), 6, "clusterWeights");
|
||||
|
||||
glLinkProgram(program.programId());
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
program.bind();
|
||||
|
||||
locations.clusterMatrices = program.uniformLocation("clusterMatrices");
|
||||
|
||||
|
||||
|
||||
locations.clusterIndices = program.attributeLocation("clusterIndices");
|
||||
|
||||
locations.clusterWeights = program.attributeLocation("clusterWeights");
|
||||
|
||||
program.release();
|
||||
}
|
||||
|
||||
|
@ -410,6 +440,80 @@ void Model::setJointStates(QVector<JointState> states) {
|
|||
_boundingRadius = radius;
|
||||
}
|
||||
|
||||
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const {
|
||||
|
||||
bool intersectedSomething = false;
|
||||
|
||||
// if we aren't active, we can't ray pick yet...
|
||||
if (!isActive()) {
|
||||
return intersectedSomething;
|
||||
}
|
||||
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = _translation;
|
||||
glm::mat4 rotation = glm::mat4_cast(_rotation);
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::mat4 modelToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
|
||||
|
||||
Extents modelExtents = getMeshExtents(); // NOTE: unrotated
|
||||
|
||||
glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
|
||||
glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference
|
||||
AABox overlayFrameBox(corner, dimensions);
|
||||
|
||||
glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the model frame
|
||||
// and testing intersection there.
|
||||
if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) {
|
||||
|
||||
float bestDistance = std::numeric_limits<float>::max();
|
||||
float distanceToSubMesh;
|
||||
BoxFace subMeshFace;
|
||||
BoxFace bestSubMeshFace;
|
||||
int subMeshIndex = 0;
|
||||
int bestSubMeshIndex = -1;
|
||||
|
||||
// If we hit the models box, then consider the submeshes...
|
||||
foreach(const AABox& subMeshBox, _calculatedMeshBoxes) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
|
||||
if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) {
|
||||
if (distanceToSubMesh < bestDistance) {
|
||||
bestSubMeshIndex = subMeshIndex;
|
||||
bestDistance = distanceToSubMesh;
|
||||
bestSubMeshFace = subMeshFace;
|
||||
intersectedSomething = true;
|
||||
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
|
||||
}
|
||||
}
|
||||
subMeshIndex++;
|
||||
}
|
||||
|
||||
return intersectedSomething;
|
||||
}
|
||||
|
||||
return intersectedSomething;
|
||||
}
|
||||
|
||||
void Model::recalcuateMeshBoxes() {
|
||||
if (!_calculatedMeshBoxesValid) {
|
||||
PerformanceTimer perfTimer("calculatedMeshBoxes");
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
int numberOfMeshes = geometry.meshes.size();
|
||||
_calculatedMeshBoxes.resize(numberOfMeshes);
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||
}
|
||||
_calculatedMeshBoxesValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
// render the attachments
|
||||
|
@ -425,16 +529,7 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
// against. We cache the results of these calculations so long as the model hasn't been
|
||||
// simulated and the mesh hasn't changed.
|
||||
if (args && !_calculatedMeshBoxesValid) {
|
||||
PerformanceTimer perfTimer("calculatedMeshBoxes");
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
int numberOfMeshes = geometry.meshes.size();
|
||||
_calculatedMeshBoxes.resize(numberOfMeshes);
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||
}
|
||||
_calculatedMeshBoxesValid = true;
|
||||
recalcuateMeshBoxes();
|
||||
}
|
||||
|
||||
// set up dilated textures on first render after load/simulate
|
||||
|
@ -874,7 +969,15 @@ void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions) {
|
|||
}
|
||||
|
||||
void Model::setScaleToFit(bool scaleToFit, float largestDimension) {
|
||||
// NOTE: if the model is not active, then it means we don't actually know the true/natural dimensions of the
|
||||
// mesh, and so we can't do the needed calculations for scaling to fit to a single largest dimension. In this
|
||||
// case we will record that we do want to do this, but we will stick our desired single dimension into the
|
||||
// first element of the vec3 for the non-fixed aspect ration dimensions
|
||||
if (!isActive()) {
|
||||
_scaleToFit = scaleToFit;
|
||||
if (scaleToFit) {
|
||||
_scaleToFitDimensions = glm::vec3(largestDimension, FAKE_DIMENSION_PLACEHOLDER, FAKE_DIMENSION_PLACEHOLDER);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -896,6 +999,15 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension) {
|
|||
}
|
||||
|
||||
void Model::scaleToFit() {
|
||||
// If our _scaleToFitDimensions.y/z are FAKE_DIMENSION_PLACEHOLDER then it means our
|
||||
// user asked to scale us in a fixed aspect ratio to a single largest dimension, but
|
||||
// we didn't yet have an active mesh. We can only enter this scaleToFit() in this state
|
||||
// if we now do have an active mesh, so we take this opportunity to actually determine
|
||||
// the correct scale.
|
||||
if (_scaleToFit && _scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER
|
||||
&& _scaleToFitDimensions.z == FAKE_DIMENSION_PLACEHOLDER) {
|
||||
setScaleToFit(_scaleToFit, _scaleToFitDimensions.x);
|
||||
}
|
||||
Extents modelMeshExtents = getUnscaledMeshExtents();
|
||||
|
||||
// size is our "target size in world space"
|
||||
|
|
|
@ -189,13 +189,18 @@ public:
|
|||
|
||||
Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url)
|
||||
{ _geometry->setTextureWithNameToURL(name, url); }
|
||||
|
||||
|
||||
bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const;
|
||||
|
||||
protected:
|
||||
QSharedPointer<NetworkGeometry> _geometry;
|
||||
|
||||
glm::vec3 _scale;
|
||||
glm::vec3 _offset;
|
||||
|
||||
static float FAKE_DIMENSION_PLACEHOLDER;
|
||||
|
||||
bool _scaleToFit; /// If you set scaleToFit, we will calculate scale based on MeshExtents
|
||||
glm::vec3 _scaleToFitDimensions; /// this is the dimensions that scale to fit will use
|
||||
bool _scaledToFit; /// have we scaled to fit
|
||||
|
@ -341,6 +346,8 @@ private:
|
|||
QVector<AABox> _calculatedMeshBoxes;
|
||||
bool _calculatedMeshBoxesValid;
|
||||
|
||||
void recalcuateMeshBoxes();
|
||||
|
||||
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
|
||||
|
||||
bool _meshGroupsKnown;
|
||||
|
|
|
@ -48,6 +48,11 @@ public:
|
|||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const {
|
||||
return findRayIntersection(origin, direction, distance, face);
|
||||
}
|
||||
|
||||
protected:
|
||||
void drawDashedLine(const glm::vec3& start, const glm::vec3& end);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ BillboardOverlay::BillboardOverlay() :
|
|||
_isLoaded = false;
|
||||
}
|
||||
|
||||
void BillboardOverlay::render() {
|
||||
void BillboardOverlay::render(RenderArgs* args) {
|
||||
if (!_visible || !_isLoaded) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class BillboardOverlay : public Base3DOverlay {
|
|||
public:
|
||||
BillboardOverlay();
|
||||
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
|
|
|
@ -36,7 +36,7 @@ Circle3DOverlay::Circle3DOverlay() :
|
|||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
}
|
||||
|
||||
void Circle3DOverlay::render() {
|
||||
void Circle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class Circle3DOverlay : public Planar3DOverlay {
|
|||
public:
|
||||
Circle3DOverlay();
|
||||
~Circle3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
float getStartAt() const { return _startAt; }
|
||||
|
|
|
@ -25,7 +25,7 @@ Cube3DOverlay::Cube3DOverlay() {
|
|||
Cube3DOverlay::~Cube3DOverlay() {
|
||||
}
|
||||
|
||||
void Cube3DOverlay::render() {
|
||||
void Cube3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class Cube3DOverlay : public Volume3DOverlay {
|
|||
public:
|
||||
Cube3DOverlay();
|
||||
~Cube3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ void ImageOverlay::replyFinished() {
|
|||
_isLoaded = true;
|
||||
}
|
||||
|
||||
void ImageOverlay::render() {
|
||||
void ImageOverlay::render(RenderArgs* args) {
|
||||
if (!_visible || !_isLoaded) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class ImageOverlay : public Overlay2D {
|
|||
public:
|
||||
ImageOverlay();
|
||||
~ImageOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
const QRect& getClipFromSource() const { return _fromImage; }
|
||||
|
|
|
@ -21,7 +21,7 @@ Line3DOverlay::Line3DOverlay() {
|
|||
Line3DOverlay::~Line3DOverlay() {
|
||||
}
|
||||
|
||||
void Line3DOverlay::render() {
|
||||
void Line3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class Line3DOverlay : public Base3DOverlay {
|
|||
public:
|
||||
Line3DOverlay();
|
||||
~Line3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
const glm::vec3& getEnd() const { return _end; }
|
||||
|
|
|
@ -25,7 +25,7 @@ void LocalModelsOverlay::update(float deltatime) {
|
|||
_entityTreeRenderer->update();
|
||||
}
|
||||
|
||||
void LocalModelsOverlay::render() {
|
||||
void LocalModelsOverlay::render(RenderArgs* args) {
|
||||
if (_visible) {
|
||||
|
||||
float glowLevel = getGlowLevel();
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
~LocalModelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
private:
|
||||
EntityTreeRenderer* _entityTreeRenderer;
|
||||
|
|
|
@ -51,7 +51,7 @@ void LocalVoxelsOverlay::update(float deltatime) {
|
|||
_tree->unlock();
|
||||
}
|
||||
|
||||
void LocalVoxelsOverlay::render() {
|
||||
void LocalVoxelsOverlay::render(RenderArgs* args) {
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
float size = glm::length(dimensions);
|
||||
if (_visible && size > 0 && _voxelSystem && _voxelSystem->isInitialized()) {
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
~LocalVoxelsOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ void ModelOverlay::update(float deltatime) {
|
|||
if (_updateModel) {
|
||||
_updateModel = false;
|
||||
|
||||
_model.setScaleToFit(true, _scale);
|
||||
_model.setSnapModelToCenter(true);
|
||||
_model.setRotation(_rotation);
|
||||
_model.setTranslation(_position);
|
||||
|
@ -37,7 +36,7 @@ void ModelOverlay::update(float deltatime) {
|
|||
_isLoaded = _model.isActive();
|
||||
}
|
||||
|
||||
void ModelOverlay::render() {
|
||||
void ModelOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return;
|
||||
}
|
||||
|
@ -49,7 +48,7 @@ void ModelOverlay::render() {
|
|||
if (glowLevel > 0.0f) {
|
||||
glower = new Glower(glowLevel);
|
||||
}
|
||||
_model.render(getAlpha());
|
||||
_model.render(getAlpha(), Model::DEFAULT_RENDER_MODE, args);
|
||||
if (glower) {
|
||||
delete glower;
|
||||
}
|
||||
|
@ -70,6 +69,7 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
QScriptValue scaleValue = properties.property("scale");
|
||||
if (scaleValue.isValid()) {
|
||||
_scale = scaleValue.toVariant().toFloat();
|
||||
_model.setScaleToFit(true, _scale);
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
|
@ -124,33 +124,15 @@ void ModelOverlay::setProperties(const QScriptValue &properties) {
|
|||
|
||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face) const {
|
||||
|
||||
// if our model isn't active, we can't ray pick yet...
|
||||
if (!_model.isActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::vec3 position = getPosition();
|
||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||
glm::mat4 translation = glm::translate(position);
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
Extents modelExtents = _model.getMeshExtents(); // NOTE: unrotated
|
||||
|
||||
glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
|
||||
glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference
|
||||
AABox overlayFrameBox(corner, dimensions);
|
||||
|
||||
glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||
// and testing intersection there.
|
||||
if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
QString subMeshNameTemp;
|
||||
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, subMeshNameTemp);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const {
|
||||
|
||||
return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,9 +22,11 @@ public:
|
|||
ModelOverlay();
|
||||
|
||||
virtual void update(float deltatime);
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, QString& extraInfo) const;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <QString>
|
||||
|
||||
#include <SharedUtil.h> // for xColor
|
||||
#include <RenderArgs.h>
|
||||
|
||||
const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
const float DEFAULT_ALPHA = 0.7f;
|
||||
|
@ -37,7 +38,7 @@ public:
|
|||
~Overlay();
|
||||
void init(QGLWidget* parent);
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render() = 0;
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
// getters
|
||||
virtual bool is3D() const = 0;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <limits>
|
||||
#include <Application.h>
|
||||
#include <Menu.h>
|
||||
|
||||
#include "BillboardOverlay.h"
|
||||
#include "Circle3DOverlay.h"
|
||||
|
@ -78,8 +79,13 @@ void Overlays::update(float deltatime) {
|
|||
|
||||
void Overlays::render2D() {
|
||||
QReadLocker lock(&_lock);
|
||||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlays2D) {
|
||||
thisOverlay->render();
|
||||
thisOverlay->render(&args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +101,11 @@ void Overlays::render3D() {
|
|||
float angle = 0.0f;
|
||||
glm::vec3 axis(0.0f, 1.0f, 0.0f);
|
||||
float myAvatarScale = 1.0f;
|
||||
|
||||
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
|
||||
Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
|
||||
RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
foreach(Overlay* thisOverlay, _overlays3D) {
|
||||
glPushMatrix();
|
||||
|
@ -118,7 +129,7 @@ void Overlays::render3D() {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
thisOverlay->render();
|
||||
thisOverlay->render(&args);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +250,8 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray)
|
|||
if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) {
|
||||
float thisDistance;
|
||||
BoxFace thisFace;
|
||||
if (thisOverlay->findRayIntersection(ray.origin, ray.direction, thisDistance, thisFace)) {
|
||||
QString thisExtraInfo;
|
||||
if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) {
|
||||
if (thisDistance < bestDistance) {
|
||||
bestDistance = thisDistance;
|
||||
result.intersects = true;
|
||||
|
@ -247,6 +259,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray)
|
|||
result.face = thisFace;
|
||||
result.overlayID = thisID;
|
||||
result.intersection = ray.origin + (ray.direction * thisDistance);
|
||||
result.extraInfo = thisExtraInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +272,8 @@ RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() :
|
|||
overlayID(-1),
|
||||
distance(0),
|
||||
face(),
|
||||
intersection()
|
||||
intersection(),
|
||||
extraInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -298,6 +312,7 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine,
|
|||
obj.setProperty("face", faceName);
|
||||
QScriptValue intersection = vec3toScriptValue(engine, value.intersection);
|
||||
obj.setProperty("intersection", intersection);
|
||||
obj.setProperty("extraInfo", value.extraInfo);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -326,6 +341,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R
|
|||
if (intersection.isValid()) {
|
||||
vec3FromScriptValue(intersection, value.intersection);
|
||||
}
|
||||
value.extraInfo = object.property("extraInfo").toVariant().toString();
|
||||
}
|
||||
|
||||
bool Overlays::isLoaded(unsigned int id) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#ifndef hifi_Overlays_h
|
||||
#define hifi_Overlays_h
|
||||
|
||||
#include <QString>
|
||||
#include <QScriptValue>
|
||||
|
||||
#include "Overlay.h"
|
||||
|
@ -23,6 +24,7 @@ public:
|
|||
float distance;
|
||||
BoxFace face;
|
||||
glm::vec3 intersection;
|
||||
QString extraInfo;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(RayToOverlayIntersectionResult);
|
||||
|
|
|
@ -23,7 +23,7 @@ Rectangle3DOverlay::Rectangle3DOverlay() {
|
|||
Rectangle3DOverlay::~Rectangle3DOverlay() {
|
||||
}
|
||||
|
||||
void Rectangle3DOverlay::render() {
|
||||
void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class Rectangle3DOverlay : public Planar3DOverlay {
|
|||
public:
|
||||
Rectangle3DOverlay();
|
||||
~Rectangle3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ Sphere3DOverlay::Sphere3DOverlay() {
|
|||
Sphere3DOverlay::~Sphere3DOverlay() {
|
||||
}
|
||||
|
||||
void Sphere3DOverlay::render() {
|
||||
void Sphere3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class Sphere3DOverlay : public Volume3DOverlay {
|
|||
public:
|
||||
Sphere3DOverlay();
|
||||
~Sphere3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ xColor Text3DOverlay::getBackgroundColor() {
|
|||
}
|
||||
|
||||
|
||||
void Text3DOverlay::render() {
|
||||
void Text3DOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <RenderArgs.h>
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Text3DOverlay : public Planar3DOverlay {
|
||||
|
@ -23,7 +25,7 @@ class Text3DOverlay : public Planar3DOverlay {
|
|||
public:
|
||||
Text3DOverlay();
|
||||
~Text3DOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
const QString& getText() const { return _text; }
|
||||
|
|
|
@ -48,7 +48,7 @@ xColor TextOverlay::getBackgroundColor() {
|
|||
}
|
||||
|
||||
|
||||
void TextOverlay::render() {
|
||||
void TextOverlay::render(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class TextOverlay : public Overlay2D {
|
|||
public:
|
||||
TextOverlay();
|
||||
~TextOverlay();
|
||||
virtual void render();
|
||||
virtual void render(RenderArgs* args);
|
||||
|
||||
// getters
|
||||
const QString& getText() const { return _text; }
|
||||
|
|
|
@ -70,6 +70,14 @@ Extents FBXGeometry::getUnscaledMeshExtents() const {
|
|||
return scaledExtents;
|
||||
}
|
||||
|
||||
QString FBXGeometry::getModelNameOfMesh(int meshIndex) const {
|
||||
if (meshIndicesToModelNames.contains(meshIndex)) {
|
||||
return meshIndicesToModelNames.value(meshIndex);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
|
||||
static int fbxAnimationFrameMetaTypeId = qRegisterMetaType<FBXAnimationFrame>();
|
||||
|
@ -512,6 +520,17 @@ QString processID(const QString& id) {
|
|||
return id.mid(id.lastIndexOf(':') + 1);
|
||||
}
|
||||
|
||||
QString getName(const QVariantList& properties) {
|
||||
QString name;
|
||||
if (properties.size() == 3) {
|
||||
name = properties.at(1).toString();
|
||||
name = processID(name.left(name.indexOf(QChar('\0'))));
|
||||
} else {
|
||||
name = processID(properties.at(0).toString());
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
QString getID(const QVariantList& properties, int index = 0) {
|
||||
return processID(properties.at(index).toString());
|
||||
}
|
||||
|
@ -869,7 +888,7 @@ ExtractedMesh extractMesh(const FBXNode& object) {
|
|||
beginIndex = endIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return data.extracted;
|
||||
}
|
||||
|
||||
|
@ -1008,6 +1027,10 @@ bool checkMaterialsHaveTextures(const QHash<QString, Material>& materials,
|
|||
|
||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
||||
QHash<QString, ExtractedMesh> meshes;
|
||||
QHash<QString, QString> modelIDsToNames;
|
||||
QHash<QString, int> meshIDsToMeshIndices;
|
||||
QHash<QString, QString> ooChildToParent;
|
||||
|
||||
QVector<ExtractedBlendshape> blendshapes;
|
||||
QMultiHash<QString, QString> parentMap;
|
||||
QMultiHash<QString, QString> childMap;
|
||||
|
@ -1078,6 +1101,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
FBXGeometry geometry;
|
||||
float unitScaleFactor = 1.0f;
|
||||
foreach (const FBXNode& child, node.children) {
|
||||
|
||||
if (child.name == "FBXHeaderExtension") {
|
||||
foreach (const FBXNode& object, child.children) {
|
||||
if (object.name == "SceneInfo") {
|
||||
|
@ -1115,20 +1139,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
if (object.name == "Geometry") {
|
||||
if (object.properties.at(2) == "Mesh") {
|
||||
meshes.insert(getID(object.properties), extractMesh(object));
|
||||
|
||||
} else { // object.properties.at(2) == "Shape"
|
||||
ExtractedBlendshape extracted = { getID(object.properties), extractBlendshape(object) };
|
||||
blendshapes.append(extracted);
|
||||
}
|
||||
} else if (object.name == "Model") {
|
||||
QString name;
|
||||
if (object.properties.size() == 3) {
|
||||
name = object.properties.at(1).toString();
|
||||
name = processID(name.left(name.indexOf(QChar('\0'))));
|
||||
QString name = getName(object.properties);
|
||||
QString id = getID(object.properties);
|
||||
modelIDsToNames.insert(id, name);
|
||||
|
||||
} else {
|
||||
name = getID(object.properties);
|
||||
}
|
||||
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") {
|
||||
jointEyeLeftID = getID(object.properties);
|
||||
|
||||
|
@ -1392,6 +1411,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
} else if (child.name == "Connections") {
|
||||
foreach (const FBXNode& connection, child.children) {
|
||||
if (connection.name == "C" || connection.name == "Connect") {
|
||||
if (connection.properties.at(0) == "OO") {
|
||||
QString childID = getID(connection.properties, 1);
|
||||
QString parentID = getID(connection.properties, 2);
|
||||
ooChildToParent.insert(childID, parentID);
|
||||
}
|
||||
if (connection.properties.at(0) == "OP") {
|
||||
QByteArray type = connection.properties.at(3).toByteArray().toLower();
|
||||
if (type.contains("diffuse")) {
|
||||
|
@ -1882,6 +1906,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
||||
|
||||
geometry.meshes.append(extracted.mesh);
|
||||
int meshIndex = geometry.meshes.size() - 1;
|
||||
meshIDsToMeshIndices.insert(it.key(), meshIndex);
|
||||
|
||||
}
|
||||
|
||||
// now that all joints have been scanned, compute a collision shape for each joint
|
||||
|
@ -1981,6 +2008,22 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
geometry.sittingPoints.append(sittingPoint);
|
||||
}
|
||||
|
||||
// attempt to map any meshes to a named model
|
||||
for (QHash<QString, int>::const_iterator m = meshIDsToMeshIndices.constBegin();
|
||||
m != meshIDsToMeshIndices.constEnd(); m++) {
|
||||
|
||||
const QString& meshID = m.key();
|
||||
int meshIndex = m.value();
|
||||
|
||||
if (ooChildToParent.contains(meshID)) {
|
||||
const QString& modelID = ooChildToParent.value(meshID);
|
||||
if (modelIDsToNames.contains(modelID)) {
|
||||
const QString& modelName = modelIDsToNames.value(modelID);
|
||||
geometry.meshIndicesToModelNames.insert(meshIndex, modelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
|
|
|
@ -224,6 +224,12 @@ public:
|
|||
|
||||
/// Returns the unscaled extents of the model's mesh
|
||||
Extents getUnscaledMeshExtents() const;
|
||||
|
||||
|
||||
QHash<int, QString> meshIndicesToModelNames;
|
||||
|
||||
/// given a meshIndex this will return the name of the model that mesh belongs to if known
|
||||
QString getModelNameOfMesh(int meshIndex) const;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(FBXGeometry)
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ }
|
||||
|
||||
virtual void init();
|
||||
virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE) { /* swallow these */ }
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE) { /* swallow these */ }
|
||||
|
||||
void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; }
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <SharedUtil.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RenderArgs.h>
|
||||
#include "OctreeRenderer.h"
|
||||
|
||||
OctreeRenderer::OctreeRenderer() :
|
||||
|
@ -161,7 +162,7 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void OctreeRenderer::render(RenderMode renderMode) {
|
||||
void OctreeRenderer::render(RenderArgs::RenderMode renderMode) {
|
||||
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
if (_tree) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QObject>
|
||||
|
||||
#include <PacketHeaders.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "Octree.h"
|
||||
|
@ -25,7 +26,6 @@
|
|||
#include "ViewFrustum.h"
|
||||
|
||||
class OctreeRenderer;
|
||||
class RenderArgs;
|
||||
|
||||
|
||||
// Generic client side Octree renderer class.
|
||||
|
@ -51,10 +51,8 @@ public:
|
|||
/// initialize and GPU/rendering related resources
|
||||
virtual void init();
|
||||
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE };
|
||||
|
||||
/// render the content of the octree
|
||||
virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE);
|
||||
virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE);
|
||||
|
||||
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||
|
@ -104,31 +102,4 @@ protected:
|
|||
int _opaqueMeshPartsRendered;
|
||||
};
|
||||
|
||||
class RenderArgs {
|
||||
public:
|
||||
OctreeRenderer* _renderer;
|
||||
ViewFrustum* _viewFrustum;
|
||||
float _sizeScale;
|
||||
int _boundaryLevelAdjust;
|
||||
OctreeRenderer::RenderMode _renderMode;
|
||||
|
||||
int _elementsTouched;
|
||||
int _itemsRendered;
|
||||
int _itemsOutOfView;
|
||||
int _itemsTooSmall;
|
||||
|
||||
int _meshesConsidered;
|
||||
int _meshesRendered;
|
||||
int _meshesOutOfView;
|
||||
int _meshesTooSmall;
|
||||
|
||||
int _materialSwitches;
|
||||
int _trianglesRendered;
|
||||
int _quadsRendered;
|
||||
|
||||
int _translucentMeshPartsRendered;
|
||||
int _opaqueMeshPartsRendered;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_OctreeRenderer_h
|
||||
|
|
46
libraries/shared/src/RenderArgs.h
Normal file
46
libraries/shared/src/RenderArgs.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// RenderArgs.h
|
||||
// libraries/shared
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 10/29/14.
|
||||
// Copyright 2013-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_RenderArgs_h
|
||||
#define hifi_RenderArgs_h
|
||||
|
||||
class ViewFrustum;
|
||||
class OctreeRenderer;
|
||||
|
||||
class RenderArgs {
|
||||
public:
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE };
|
||||
|
||||
OctreeRenderer* _renderer;
|
||||
ViewFrustum* _viewFrustum;
|
||||
float _sizeScale;
|
||||
int _boundaryLevelAdjust;
|
||||
RenderMode _renderMode;
|
||||
|
||||
int _elementsTouched;
|
||||
int _itemsRendered;
|
||||
int _itemsOutOfView;
|
||||
int _itemsTooSmall;
|
||||
|
||||
int _meshesConsidered;
|
||||
int _meshesRendered;
|
||||
int _meshesOutOfView;
|
||||
int _meshesTooSmall;
|
||||
|
||||
int _materialSwitches;
|
||||
int _trianglesRendered;
|
||||
int _quadsRendered;
|
||||
|
||||
int _translucentMeshPartsRendered;
|
||||
int _opaqueMeshPartsRendered;
|
||||
};
|
||||
|
||||
#endif // hifi_RenderArgs_h
|
Loading…
Reference in a new issue