mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-17 23:16:18 +02:00
Adding the AABox transform features (from Extents) adn introducing a simple MeshPartPayload to render simple geometry
This commit is contained in:
parent
81eedb8585
commit
5805cc8f2b
6 changed files with 347 additions and 151 deletions
|
@ -25,7 +25,7 @@ namespace render {
|
|||
// Return opaque for lack of a better idea
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
}
|
||||
|
||||
|
||||
template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) {
|
||||
if (payload) {
|
||||
return payload->getBound();
|
||||
|
@ -39,64 +39,38 @@ namespace render {
|
|||
|
||||
using namespace render;
|
||||
|
||||
MeshPartPayload::MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex,
|
||||
glm::vec3 position, glm::quat orientation, bool isCollisionGeometry) :
|
||||
model(model),
|
||||
_drawMesh(drawMesh),
|
||||
meshIndex(meshIndex),
|
||||
partIndex(partIndex),
|
||||
_shapeID(shapeIndex),
|
||||
_modelPosition(position),
|
||||
_modelOrientation(orientation),
|
||||
_isCollisionGeometry(isCollisionGeometry) {
|
||||
initCache();
|
||||
MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform) {
|
||||
|
||||
updateMeshPart(mesh, partIndex);
|
||||
updateMaterial(material);
|
||||
updateTransform(transform);
|
||||
}
|
||||
|
||||
void MeshPartPayload::initCache() {
|
||||
void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) {
|
||||
_drawMesh = drawMesh;
|
||||
if (_drawMesh) {
|
||||
auto vertexFormat = _drawMesh->getVertexFormat();
|
||||
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
|
||||
_isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX);
|
||||
|
||||
if (!_isCollisionGeometry) {
|
||||
const FBXGeometry& geometry = model->_geometry->getFBXGeometry();
|
||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||
_isBlendShaped = !mesh.blendshapes.isEmpty();
|
||||
} else {
|
||||
_isBlendShaped = false;
|
||||
}
|
||||
|
||||
_drawPart = _drawMesh->getPartBuffer().get<model::Mesh::Part>(partIndex);
|
||||
|
||||
_localBound = _drawMesh->evalPartBound(partIndex);
|
||||
}
|
||||
|
||||
auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID);
|
||||
if (networkMaterial) {
|
||||
_drawMaterial = networkMaterial->_material;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateDrawMaterial(model::MaterialPointer material) {
|
||||
_drawMaterial = material;
|
||||
void MeshPartPayload::updateTransform(const Transform& transform) {
|
||||
_drawTransform = transform;
|
||||
_worldBound = _localBound;
|
||||
_worldBound.transform(_drawTransform);
|
||||
}
|
||||
|
||||
void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) {
|
||||
_modelPosition = position;
|
||||
_modelOrientation = orientation;
|
||||
void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) {
|
||||
_drawMaterial = drawMaterial;
|
||||
}
|
||||
|
||||
render::ItemKey MeshPartPayload::getKey() const {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape();
|
||||
|
||||
if (!model->isVisible()) {
|
||||
builder.withInvisible();
|
||||
}
|
||||
|
||||
if (_isBlendShaped || _isSkinned) {
|
||||
builder.withDeformed();
|
||||
}
|
||||
|
||||
if (_drawMaterial) {
|
||||
auto matKey = _drawMaterial->getKey();
|
||||
if (matKey.isTransparent() || matKey.isTransparentMap()) {
|
||||
|
@ -108,21 +82,7 @@ render::ItemKey MeshPartPayload::getKey() const {
|
|||
}
|
||||
|
||||
render::Item::Bound MeshPartPayload::getBound() const {
|
||||
// NOTE: we can't cache this bounds because we need to handle the case of a moving
|
||||
// entity or mesh part.
|
||||
if (_isCollisionGeometry) {
|
||||
if (_drawMesh && _drawBound.isNull()) {
|
||||
_drawBound = _drawMesh->evalPartBound(partIndex);
|
||||
}
|
||||
// If we not skinned use the bounds of the subMesh for all it's parts
|
||||
const FBXMesh& mesh = model->_collisionGeometry->getFBXGeometry().meshes.at(meshIndex);
|
||||
auto otherBound = model->calculateScaledOffsetExtents(mesh.meshExtents, _modelPosition, _modelOrientation);
|
||||
|
||||
return model->getPartBounds(0, 0, _modelPosition, _modelOrientation);
|
||||
|
||||
} else {
|
||||
return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation);
|
||||
}
|
||||
return _worldBound;
|
||||
}
|
||||
|
||||
void MeshPartPayload::drawCall(gpu::Batch& batch) const {
|
||||
|
@ -130,22 +90,12 @@ void MeshPartPayload::drawCall(gpu::Batch& batch) const {
|
|||
}
|
||||
|
||||
void MeshPartPayload::bindMesh(gpu::Batch& batch) const {
|
||||
if (!_isBlendShaped) {
|
||||
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
|
||||
|
||||
batch.setInputFormat((_drawMesh->getVertexFormat()));
|
||||
|
||||
batch.setInputStream(0, _drawMesh->getVertexStream());
|
||||
} else {
|
||||
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
|
||||
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
|
||||
|
||||
batch.setInputFormat((_drawMesh->getVertexFormat()));
|
||||
batch.setInputFormat((_drawMesh->getVertexFormat()));
|
||||
|
||||
batch.setInputStream(0, _drawMesh->getVertexStream());
|
||||
|
||||
batch.setInputBuffer(0, model->_blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3));
|
||||
batch.setInputBuffer(1, model->_blendedVertexBuffers[meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
|
||||
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
|
||||
}
|
||||
|
||||
// TODO: Get rid of that extra call
|
||||
if (!_hasColorAttrib) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
@ -236,40 +186,215 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio
|
|||
}
|
||||
|
||||
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const {
|
||||
if (!_isCollisionGeometry) {
|
||||
// Still relying on the raw data from the model
|
||||
const Model::MeshState& state = model->_meshStates.at(meshIndex);
|
||||
|
||||
Transform transform;
|
||||
if (state.clusterBuffer) {
|
||||
if (model->_cauterizeBones) {
|
||||
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer);
|
||||
} else {
|
||||
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
|
||||
}
|
||||
} else {
|
||||
if (model->_cauterizeBones) {
|
||||
transform = Transform(state.cauterizedClusterMatrices[0]);
|
||||
} else {
|
||||
transform = Transform(state.clusterMatrices[0]);
|
||||
}
|
||||
}
|
||||
transform.preTranslate(_modelPosition);
|
||||
batch.setModelTransform(transform);
|
||||
} else {
|
||||
Transform transform;
|
||||
transform.setTranslation(_modelPosition);
|
||||
transform.setRotation(_modelOrientation);
|
||||
transform.postScale(model->getScale());
|
||||
transform.postTranslate(model->getOffset());
|
||||
batch.setModelTransform(transform);
|
||||
}
|
||||
batch.setModelTransform(_drawTransform);
|
||||
}
|
||||
|
||||
|
||||
void MeshPartPayload::render(RenderArgs* args) const {
|
||||
PerformanceTimer perfTimer("MeshPartPayload::render");
|
||||
if (!model->_readyWhenAdded || !model->_isVisible) {
|
||||
|
||||
|
||||
gpu::Batch& batch = *(args->_batch);
|
||||
auto mode = args->_renderMode;
|
||||
|
||||
auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME
|
||||
|
||||
model::MaterialKey drawMaterialKey;
|
||||
if (_drawMaterial) {
|
||||
drawMaterialKey = _drawMaterial->getKey();
|
||||
}
|
||||
bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap();
|
||||
|
||||
bool hasTangents = drawMaterialKey.isNormalMap();
|
||||
bool hasSpecular = drawMaterialKey.isGlossMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||
bool isSkinned = false;
|
||||
bool wireframe = false;
|
||||
if (wireframe) {
|
||||
translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false;
|
||||
}
|
||||
|
||||
ModelRender::Locations* locations = nullptr;
|
||||
ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe,
|
||||
args, locations);
|
||||
|
||||
|
||||
// Bind the model transform and the skinCLusterMatrices if needed
|
||||
bindTransform(batch, locations);
|
||||
|
||||
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
||||
bindMesh(batch);
|
||||
|
||||
// apply material properties
|
||||
bindMaterial(batch, locations);
|
||||
|
||||
|
||||
// TODO: We should be able to do that just in the renderTransparentJob
|
||||
if (translucentMesh && locations->lightBufferUnit >= 0) {
|
||||
PerformanceTimer perfTimer("DLE->setupTransparent()");
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
|
||||
}
|
||||
if (args) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
// Draw!
|
||||
{
|
||||
PerformanceTimer perfTimer("batch.drawIndexed()");
|
||||
drawCall(batch);
|
||||
}
|
||||
|
||||
if (args) {
|
||||
const int INDICES_PER_TRIANGLE = 3;
|
||||
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace render {
|
||||
template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) {
|
||||
if (payload) {
|
||||
return payload->getKey();
|
||||
}
|
||||
// Return opaque for lack of a better idea
|
||||
return ItemKey::Builder::opaqueShape();
|
||||
}
|
||||
|
||||
template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) {
|
||||
if (payload) {
|
||||
return payload->getBound();
|
||||
}
|
||||
return render::Item::Bound();
|
||||
}
|
||||
template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) {
|
||||
return payload->render(args);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace render;
|
||||
|
||||
ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex,
|
||||
glm::vec3 position, glm::quat orientation) :
|
||||
_model(model),
|
||||
_meshIndex(_meshIndex),
|
||||
_shapeID(shapeIndex),
|
||||
_modelPosition(position),
|
||||
_modelOrientation(orientation) {
|
||||
auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh;
|
||||
updateMeshPart(modelMesh, partIndex);
|
||||
|
||||
initCache();
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::initCache() {
|
||||
if (_drawMesh) {
|
||||
auto vertexFormat = _drawMesh->getVertexFormat();
|
||||
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
|
||||
_isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX);
|
||||
|
||||
|
||||
const FBXGeometry& geometry = _model->_geometry->getFBXGeometry();
|
||||
const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
|
||||
_isBlendShaped = !mesh.blendshapes.isEmpty();
|
||||
}
|
||||
|
||||
auto networkMaterial = _model->_geometry->getShapeMaterial(_shapeID);
|
||||
if (networkMaterial) {
|
||||
_drawMaterial = networkMaterial->_material;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ModelMeshPartPayload::notifyLocationChanged() {
|
||||
_model->_needsUpdateClusterMatrices = true;
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) {
|
||||
_modelPosition = position;
|
||||
_modelOrientation = orientation;
|
||||
}
|
||||
|
||||
render::ItemKey ModelMeshPartPayload::getKey() const {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape();
|
||||
|
||||
if (!_model->isVisible()) {
|
||||
builder.withInvisible();
|
||||
}
|
||||
|
||||
if (_isBlendShaped || _isSkinned) {
|
||||
builder.withDeformed();
|
||||
}
|
||||
|
||||
if (_drawMaterial) {
|
||||
auto matKey = _drawMaterial->getKey();
|
||||
if (matKey.isTransparent() || matKey.isTransparentMap()) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
render::Item::Bound ModelMeshPartPayload::getBound() const {
|
||||
// NOTE: we can't cache this bounds because we need to handle the case of a moving
|
||||
// entity or mesh part.
|
||||
return _model->getPartBounds(_meshIndex, _partIndex, _modelPosition, _modelOrientation);
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
|
||||
if (!_isBlendShaped) {
|
||||
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
|
||||
|
||||
batch.setInputFormat((_drawMesh->getVertexFormat()));
|
||||
|
||||
batch.setInputStream(0, _drawMesh->getVertexStream());
|
||||
} else {
|
||||
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
|
||||
|
||||
batch.setInputFormat((_drawMesh->getVertexFormat()));
|
||||
|
||||
batch.setInputBuffer(0, _model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3));
|
||||
batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
|
||||
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
|
||||
}
|
||||
|
||||
// TODO: Get rid of that extra call
|
||||
if (!_hasColorAttrib) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const {
|
||||
// Still relying on the raw data from the model
|
||||
const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
|
||||
|
||||
Transform transform;
|
||||
if (state.clusterBuffer) {
|
||||
if (_model->_cauterizeBones) {
|
||||
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer);
|
||||
} else {
|
||||
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
|
||||
}
|
||||
} else {
|
||||
if (_model->_cauterizeBones) {
|
||||
transform = Transform(state.cauterizedClusterMatrices[0]);
|
||||
} else {
|
||||
transform = Transform(state.clusterMatrices[0]);
|
||||
}
|
||||
}
|
||||
// transform.preTranslate(_modelPosition);
|
||||
transform.preTranslate(_drawTransform.getTranslation());
|
||||
batch.setModelTransform(transform);
|
||||
}
|
||||
|
||||
|
||||
void ModelMeshPartPayload::render(RenderArgs* args) const {
|
||||
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
|
||||
if (!_model->_readyWhenAdded || !_model->_isVisible) {
|
||||
return; // bail asap
|
||||
}
|
||||
|
||||
|
@ -278,25 +403,25 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
|||
|
||||
auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME
|
||||
|
||||
const FBXGeometry& geometry = model->_geometry->getFBXGeometry();
|
||||
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = model->_geometry->getMeshes();
|
||||
const FBXGeometry& geometry = _model->_geometry->getFBXGeometry();
|
||||
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = _model->_geometry->getMeshes();
|
||||
|
||||
// guard against partially loaded meshes
|
||||
if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)model->_meshStates.size() ) {
|
||||
if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Back to model to update the cluster matrices right now
|
||||
model->updateClusterMatrices(_modelPosition, _modelOrientation);
|
||||
_model->updateClusterMatrices(_modelPosition, _modelOrientation);
|
||||
|
||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||
const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
|
||||
|
||||
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
|
||||
// to false to rebuild out mesh groups.
|
||||
if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) {
|
||||
model->_meshGroupsKnown = false; // regenerate these lists next time around.
|
||||
model->_readyWhenAdded = false; // in case any of our users are using scenes
|
||||
model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
|
||||
if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) {
|
||||
_model->_meshGroupsKnown = false; // regenerate these lists next time around.
|
||||
_model->_readyWhenAdded = false; // in case any of our users are using scenes
|
||||
_model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
|
||||
return; // FIXME!
|
||||
}
|
||||
|
||||
|
@ -317,12 +442,12 @@ void MeshPartPayload::render(RenderArgs* args) const {
|
|||
bool hasSpecular = drawMaterialKey.isGlossMap();
|
||||
bool hasLightmap = drawMaterialKey.isLightmapMap();
|
||||
bool isSkinned = _isSkinned;
|
||||
bool wireframe = model->isWireframe();
|
||||
bool wireframe = _model->isWireframe();
|
||||
|
||||
// render the part bounding box
|
||||
#ifdef DEBUG_BOUNDING_PARTS
|
||||
{
|
||||
AABox partBounds = getPartBounds(meshIndex, partIndex);
|
||||
AABox partBounds = getPartBounds(_meshIndex, partIndex);
|
||||
bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE;
|
||||
|
||||
glm::vec4 cubeColor;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// MeshPartPayload.h
|
||||
// ModelMeshPartPayload.h
|
||||
// interface/src/renderer
|
||||
//
|
||||
// Created by Sam Gateau on 10/3/15.
|
||||
|
@ -24,47 +24,42 @@ class Model;
|
|||
|
||||
class MeshPartPayload {
|
||||
public:
|
||||
MeshPartPayload(Model* model, model::MeshPointer drawMesh, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation, bool isCollisionGeometry = false);
|
||||
|
||||
MeshPartPayload() {}
|
||||
MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform);
|
||||
|
||||
typedef render::Payload<MeshPartPayload> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
Model* model;
|
||||
int meshIndex;
|
||||
int partIndex;
|
||||
int _shapeID;
|
||||
glm::vec3 _modelPosition;
|
||||
glm::quat _modelOrientation;
|
||||
virtual void updateMeshPart(model::MeshPointer drawMesh, int partIndex);
|
||||
|
||||
virtual void notifyLocationChanged() {}
|
||||
virtual void updateTransform(const Transform& transform);
|
||||
|
||||
// can replace the material used to draw that item
|
||||
void updateDrawMaterial(model::MaterialPointer material);
|
||||
|
||||
void updateModelLocation(glm::vec3 position, glm::quat orientation);
|
||||
virtual void updateMaterial(model::MaterialPointer drawMaterial);
|
||||
|
||||
// Render Item interface
|
||||
render::ItemKey getKey() const;
|
||||
render::Item::Bound getBound() const;
|
||||
void render(RenderArgs* args) const;
|
||||
|
||||
// MeshPartPayload functions to perform render
|
||||
virtual render::ItemKey getKey() const;
|
||||
virtual render::Item::Bound getBound() const;
|
||||
virtual void render(RenderArgs* args) const;
|
||||
|
||||
// ModelMeshPartPayload functions to perform render
|
||||
void drawCall(gpu::Batch& batch) const;
|
||||
void bindMesh(gpu::Batch& batch) const;
|
||||
void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const;
|
||||
void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const;
|
||||
|
||||
|
||||
void initCache();
|
||||
virtual void bindMesh(gpu::Batch& batch) const;
|
||||
virtual void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const;
|
||||
virtual void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const;
|
||||
|
||||
// Payload resource cached values
|
||||
model::MeshPointer _drawMesh;
|
||||
int _partIndex = 0;
|
||||
model::Mesh::Part _drawPart;
|
||||
|
||||
model::MaterialPointer _drawMaterial;
|
||||
mutable model::Box _drawBound;
|
||||
|
||||
model::Box _localBound;
|
||||
Transform _drawTransform;
|
||||
mutable model::Box _worldBound;
|
||||
|
||||
bool _hasColorAttrib = false;
|
||||
bool _isSkinned = false;
|
||||
bool _isBlendShaped = false;
|
||||
bool _isCollisionGeometry = false;
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
@ -73,4 +68,35 @@ namespace render {
|
|||
template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args);
|
||||
}
|
||||
|
||||
|
||||
class ModelMeshPartPayload : public MeshPartPayload {
|
||||
public:
|
||||
ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, glm::vec3 position, glm::quat orientation);
|
||||
|
||||
typedef render::Payload<ModelMeshPartPayload> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
virtual void notifyLocationChanged();
|
||||
virtual void updateModelLocation(glm::vec3 position, glm::quat orientation);
|
||||
|
||||
// Render Item interface
|
||||
render::ItemKey getKey() const;
|
||||
render::Item::Bound getBound() const;
|
||||
void render(RenderArgs* args) const;
|
||||
|
||||
// ModelMeshPartPayload functions to perform render
|
||||
void bindMesh(gpu::Batch& batch) const;
|
||||
void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const;
|
||||
|
||||
|
||||
void initCache();
|
||||
Model* _model;
|
||||
int _meshIndex;
|
||||
int _shapeID;
|
||||
glm::vec3 _modelPosition;
|
||||
glm::quat _modelOrientation;
|
||||
bool _isSkinned = false;
|
||||
bool _isBlendShaped = false;
|
||||
};
|
||||
|
||||
#endif // hifi_MeshPartPayload_h
|
||||
|
|
|
@ -110,11 +110,15 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
void Model::enqueueLocationChange() {
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_translation);
|
||||
transform.setRotation(_rotation);
|
||||
|
||||
render::PendingChanges pendingChanges;
|
||||
foreach (auto itemID, _renderItems.keys()) {
|
||||
pendingChanges.updateItem<MeshPartPayload>(itemID, [=](MeshPartPayload& data) {
|
||||
data.updateModelLocation(_translation, _rotation);
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
data.updateTransform(transform);
|
||||
data.notifyLocationChanged();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -495,11 +499,12 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChan
|
|||
|
||||
foreach (auto renderItem, _renderItemsSet) {
|
||||
auto item = scene->allocateID();
|
||||
auto renderData = MeshPartPayload::Pointer(renderItem);
|
||||
// auto renderData = MeshPartPayload::Pointer(renderItem);
|
||||
auto renderData = renderItem;
|
||||
auto renderPayload = std::make_shared<MeshPartPayload::Payload>(renderData);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
data.notifyLocationChanged();
|
||||
});
|
||||
_renderItems.insert(item, renderPayload);
|
||||
somethingAdded = true;
|
||||
|
@ -528,7 +533,7 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene,
|
|||
renderPayload->addStatusGetters(statusGetters);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
data.notifyLocationChanged();
|
||||
});
|
||||
_renderItems.insert(item, renderPayload);
|
||||
somethingAdded = true;
|
||||
|
@ -1155,6 +1160,10 @@ void Model::segregateMeshGroups() {
|
|||
|
||||
_renderItemsSet.clear();
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_translation);
|
||||
transform.setRotation(_rotation);
|
||||
|
||||
// Run through all of the meshes, and place them into their segregated, but unsorted buckets
|
||||
int shapeID = 0;
|
||||
for (int i = 0; i < (int)networkMeshes.size(); i++) {
|
||||
|
@ -1164,11 +1173,13 @@ void Model::segregateMeshGroups() {
|
|||
// Create the render payloads
|
||||
int totalParts = mesh.parts.size();
|
||||
for (int partIndex = 0; partIndex < totalParts; partIndex++) {
|
||||
auto renderItem = std::make_shared<MeshPartPayload>(this, networkMesh._mesh, i, partIndex, shapeID, _translation, _rotation, showingCollisionHull);
|
||||
if (showingCollisionHull) {
|
||||
renderItem->updateDrawMaterial(ModelRender::getCollisionHullMaterial());
|
||||
_renderItemsSet << std::make_shared<MeshPartPayload>(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform);
|
||||
|
||||
} else {
|
||||
_renderItemsSet << std::make_shared<ModelMeshPartPayload>(this, i, partIndex, shapeID, _translation, _rotation);
|
||||
}
|
||||
_renderItemsSet << renderItem;
|
||||
|
||||
shapeID++;
|
||||
}
|
||||
}
|
||||
|
@ -1181,6 +1192,10 @@ bool Model::initWhenReady(render::ScenePointer scene) {
|
|||
|
||||
render::PendingChanges pendingChanges;
|
||||
|
||||
Transform transform;
|
||||
transform.setTranslation(_translation);
|
||||
transform.setRotation(_rotation);
|
||||
|
||||
foreach (auto renderItem, _renderItemsSet) {
|
||||
auto item = scene->allocateID();
|
||||
auto renderData = MeshPartPayload::Pointer(renderItem);
|
||||
|
@ -1188,8 +1203,8 @@ bool Model::initWhenReady(render::ScenePointer scene) {
|
|||
_renderItems.insert(item, renderPayload);
|
||||
pendingChanges.resetItem(item, renderPayload);
|
||||
pendingChanges.updateItem<MeshPartPayload>(item, [&](MeshPartPayload& data) {
|
||||
data.updateModelLocation(_translation, _rotation);
|
||||
data.model->_needsUpdateClusterMatrices = true;
|
||||
data.updateTransform(transform);
|
||||
data.notifyLocationChanged();
|
||||
});
|
||||
}
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
|
|
|
@ -366,7 +366,7 @@ private:
|
|||
bool _needsUpdateClusterMatrices = true;
|
||||
bool _showCollisionHull = false;
|
||||
|
||||
friend class MeshPartPayload;
|
||||
friend class ModelMeshPartPayload;
|
||||
protected:
|
||||
RigPointer _rig;
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "AABox.h"
|
||||
|
||||
#include "AACube.h"
|
||||
#include "Transform.h"
|
||||
#include "Extents.h"
|
||||
#include "GeometryUtil.h"
|
||||
#include "NumericalConstants.h"
|
||||
|
@ -486,3 +487,18 @@ AABox& AABox::operator += (const AABox& box) {
|
|||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void AABox::scale(const glm::vec3& scale) {
|
||||
_corner *= scale;
|
||||
_scale *= scale;
|
||||
}
|
||||
|
||||
void AABox::rotate(const glm::quat& rotation) {
|
||||
|
||||
}
|
||||
|
||||
void AABox::transform(const Transform& transform) {
|
||||
scale(transform.getScale());
|
||||
rotate(transform.getRotation());
|
||||
translate(transform.getTranslation());
|
||||
}
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
class AACube;
|
||||
class Extents;
|
||||
class Transform;
|
||||
|
||||
class AABox {
|
||||
|
||||
|
@ -40,7 +41,6 @@ public:
|
|||
void setBox(const glm::vec3& corner, float scale);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
void scale(float scale);
|
||||
const glm::vec3& getCorner() const { return _corner; }
|
||||
const glm::vec3& getScale() const { return _scale; }
|
||||
const glm::vec3& getDimensions() const { return _scale; }
|
||||
|
@ -80,6 +80,20 @@ public:
|
|||
AABox& operator += (const glm::vec3& point);
|
||||
AABox& operator += (const AABox& box);
|
||||
|
||||
// Translate the AABox just moving the corner
|
||||
void translate(const glm::vec3& translation) { _corner += translation; }
|
||||
|
||||
// Rotate the AABox around its frame origin
|
||||
// meaning rotating the corners of the AABox around the point {0,0,0} and reevaluating the min max
|
||||
void rotate(const glm::quat& rotation);
|
||||
|
||||
/// Scale the AABox
|
||||
void scale(float scale);
|
||||
void scale(const glm::vec3& scale);
|
||||
|
||||
// Transform the extents with transform
|
||||
void transform(const Transform& transform);
|
||||
|
||||
bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits<float>::infinity()); }
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue