mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 02:16:26 +02:00
Merge pull request #5030 from ZappoMan/team-teaching-scene-api
TEAM TEACHING - rendering avatar models as payload parts
This commit is contained in:
commit
d4fddad176
13 changed files with 174 additions and 91 deletions
|
@ -292,6 +292,21 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
||||||
return displayNameRenderer;
|
return displayNameRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||||
|
auto avatarPayload = new render::Payload<AvatarData>(self);
|
||||||
|
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
||||||
|
_renderItemID = scene->allocateID();
|
||||||
|
pendingChanges.resetItem(_renderItemID, avatarPayloadPointer);
|
||||||
|
_skeletonModel.addToScene(scene, pendingChanges);
|
||||||
|
getHead()->getFaceModel().addToScene(scene, pendingChanges);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||||
|
pendingChanges.removeItem(_renderItemID);
|
||||||
|
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition, bool postLighting) {
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
_referential->update();
|
_referential->update();
|
||||||
|
@ -504,6 +519,20 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||||
|
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||||
|
// fix them up in the scene
|
||||||
|
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||||
|
render::PendingChanges pendingChanges;
|
||||||
|
if (_skeletonModel.needsFixupInScene()) {
|
||||||
|
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||||
|
_skeletonModel.addToScene(scene, pendingChanges);
|
||||||
|
}
|
||||||
|
if (getHead()->getFaceModel().needsFixupInScene()) {
|
||||||
|
getHead()->getFaceModel().removeFromScene(scene, pendingChanges);
|
||||||
|
getHead()->getFaceModel().addToScene(scene, pendingChanges);
|
||||||
|
}
|
||||||
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
|
||||||
{
|
{
|
||||||
Glower glower(renderArgs, glowLevel);
|
Glower glower(renderArgs, glowLevel);
|
||||||
|
|
||||||
|
@ -518,7 +547,8 @@ void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool
|
||||||
if (postLighting) {
|
if (postLighting) {
|
||||||
getHand()->render(renderArgs, false);
|
getHand()->render(renderArgs, false);
|
||||||
} else {
|
} else {
|
||||||
_skeletonModel.render(renderArgs, 1.0f);
|
// NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene
|
||||||
|
//_skeletonModel.render(renderArgs, 1.0f);
|
||||||
renderAttachments(renderArgs);
|
renderAttachments(renderArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,12 @@ public:
|
||||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition,
|
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition,
|
||||||
bool postLighting = false);
|
bool postLighting = false);
|
||||||
|
|
||||||
|
bool addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
|
render::PendingChanges& pendingChanges);
|
||||||
|
|
||||||
|
void removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
|
render::PendingChanges& pendingChanges);
|
||||||
|
|
||||||
//setters
|
//setters
|
||||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
||||||
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
||||||
|
|
|
@ -63,13 +63,8 @@ void AvatarManager::init() {
|
||||||
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
_avatarHash.insert(MY_AVATAR_KEY, _myAvatar);
|
||||||
|
|
||||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||||
auto avatarPayload = new render::Payload<AvatarData>(_myAvatar);
|
|
||||||
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
|
||||||
static_cast<Avatar*>(_myAvatar.get())->_renderItemID = scene->allocateID();
|
|
||||||
|
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
pendingChanges.resetItem(static_cast<Avatar*>(_myAvatar.get())->_renderItemID, avatarPayloadPointer);
|
_myAvatar->addToScene(_myAvatar, scene, pendingChanges);
|
||||||
|
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,18 +140,11 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() {
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
AvatarSharedPointer AvatarManager::addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) {
|
||||||
AvatarSharedPointer avatar = AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer);
|
std::shared_ptr<Avatar> avatar = std::dynamic_pointer_cast<Avatar>(AvatarHashMap::addAvatar(sessionUUID, mixerWeakPointer));
|
||||||
|
|
||||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||||
auto avatarPayload = new render::Payload<AvatarData>(avatar);
|
|
||||||
auto avatarPayloadPointer = Avatar::PayloadPointer(avatarPayload);
|
|
||||||
static_cast<Avatar*>(avatar.get())->_renderItemID = scene->allocateID();
|
|
||||||
|
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
pendingChanges.resetItem(static_cast<Avatar*>(avatar.get())->_renderItemID, avatarPayloadPointer);
|
avatar->addToScene(avatar, scene, pendingChanges);
|
||||||
|
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,17 +165,15 @@ void AvatarManager::removeAvatarMotionState(Avatar* avatar) {
|
||||||
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
void AvatarManager::removeAvatar(const QUuid& sessionUUID) {
|
||||||
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
|
AvatarHash::iterator avatarIterator = _avatarHash.find(sessionUUID);
|
||||||
if (avatarIterator != _avatarHash.end()) {
|
if (avatarIterator != _avatarHash.end()) {
|
||||||
Avatar* avatar = reinterpret_cast<Avatar*>(avatarIterator.value().get());
|
std::shared_ptr<Avatar> avatar = std::dynamic_pointer_cast<Avatar>(avatarIterator.value());
|
||||||
if (avatar != _myAvatar.get() && avatar->isInitialized()) {
|
if (avatar != _myAvatar && avatar->isInitialized()) {
|
||||||
removeAvatarMotionState(avatar);
|
removeAvatarMotionState(avatar.get());
|
||||||
|
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
_avatarHash.erase(avatarIterator);
|
_avatarHash.erase(avatarIterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
pendingChanges.removeItem(avatar->_renderItemID);
|
avatar->removeFromScene(avatar, scene, pendingChanges);
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,17 +40,6 @@ class Hand : public HandData {
|
||||||
public:
|
public:
|
||||||
Hand(Avatar* owningAvatar);
|
Hand(Avatar* owningAvatar);
|
||||||
|
|
||||||
struct HandBall
|
|
||||||
{
|
|
||||||
glm::vec3 position; // the actual dynamic position of the ball at any given time
|
|
||||||
glm::quat rotation; // the rotation of the ball
|
|
||||||
glm::vec3 velocity; // the velocity of the ball
|
|
||||||
float radius; // the radius of the ball
|
|
||||||
bool isCollidable; // whether or not the ball responds to collisions
|
|
||||||
bool isColliding; // ball is currently colliding
|
|
||||||
float touchForce; // a scalar determining the amount that the cursor (or hand) is penetrating the ball
|
|
||||||
};
|
|
||||||
|
|
||||||
void simulate(float deltaTime, bool isMine);
|
void simulate(float deltaTime, bool isMine);
|
||||||
void render(RenderArgs* renderArgs, bool isMine);
|
void render(RenderArgs* renderArgs, bool isMine);
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,8 @@ void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustu
|
||||||
renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition());
|
renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_faceModel.render(renderArgs, alpha);
|
// NOTE: we don't need to call this here because the model has been added as payload items
|
||||||
|
//_faceModel.render(renderArgs, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1171,10 +1171,25 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bool postLighting, float glowLevel) {
|
||||||
|
|
||||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
return; // wait until both models are loaded
|
return; // wait until both models are loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||||
|
// fix them up in the scene
|
||||||
|
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
|
||||||
|
render::PendingChanges pendingChanges;
|
||||||
|
if (_skeletonModel.needsFixupInScene()) {
|
||||||
|
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||||
|
_skeletonModel.addToScene(scene, pendingChanges);
|
||||||
|
}
|
||||||
|
if (getHead()->getFaceModel().needsFixupInScene()) {
|
||||||
|
getHead()->getFaceModel().removeFromScene(scene, pendingChanges);
|
||||||
|
getHead()->getFaceModel().addToScene(scene, pendingChanges);
|
||||||
|
}
|
||||||
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
|
||||||
Camera *camera = Application::getInstance()->getCamera();
|
Camera *camera = Application::getInstance()->getCamera();
|
||||||
const glm::vec3 cameraPos = camera->getPosition();
|
const glm::vec3 cameraPos = camera->getPosition();
|
||||||
|
|
||||||
|
@ -1195,7 +1210,9 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, bo
|
||||||
|
|
||||||
// Render the body's voxels and head
|
// Render the body's voxels and head
|
||||||
if (!postLighting) {
|
if (!postLighting) {
|
||||||
_skeletonModel.render(renderArgs, 1.0f);
|
|
||||||
|
// NOTE: we no longer call this here, because we've added all the model parts as renderable items in the scene
|
||||||
|
//_skeletonModel.render(renderArgs, 1.0f);
|
||||||
renderAttachments(renderArgs);
|
renderAttachments(renderArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,9 +255,12 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::updateJointState(int index) {
|
void SkeletonModel::updateJointState(int index) {
|
||||||
|
if (index > _jointStates.size()) {
|
||||||
|
return; // bail
|
||||||
|
}
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
const FBXJoint& joint = state.getFBXJoint();
|
const FBXJoint& joint = state.getFBXJoint();
|
||||||
if (joint.parentIndex != -1) {
|
if (joint.parentIndex != -1 && joint.parentIndex <= _jointStates.size()) {
|
||||||
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
if (index == geometry.leanJointIndex) {
|
if (index == geometry.leanJointIndex) {
|
||||||
|
|
|
@ -501,7 +501,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) {
|
||||||
_viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum();
|
_viewState->getShadowViewFrustum() : _viewState->getCurrentViewFrustum();
|
||||||
|
|
||||||
// Setup batch transform matrices
|
// Setup batch transform matrices
|
||||||
gpu::Batch batch;
|
gpu::Batch batch; // FIX ME - this is very suspicious!
|
||||||
glm::mat4 projMat;
|
glm::mat4 projMat;
|
||||||
Transform viewMat;
|
Transform viewMat;
|
||||||
frustum->evalProjectionMatrix(projMat);
|
frustum->evalProjectionMatrix(projMat);
|
||||||
|
@ -509,7 +509,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) {
|
||||||
batch.setProjectionTransform(projMat);
|
batch.setProjectionTransform(projMat);
|
||||||
batch.setViewTransform(viewMat);
|
batch.setViewTransform(viewMat);
|
||||||
|
|
||||||
renderArgs->_batch = &batch;
|
renderArgs->_batch = &batch; // FIX ME - this is very suspicious!
|
||||||
|
|
||||||
_tree->lockForRead();
|
_tree->lockForRead();
|
||||||
|
|
||||||
|
@ -525,6 +525,7 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) {
|
||||||
Model::endScene(renderArgs);
|
Model::endScene(renderArgs);
|
||||||
_tree->unlock();
|
_tree->unlock();
|
||||||
|
|
||||||
|
// FIX ME - this is very suspicious!
|
||||||
// glPushMatrix();
|
// glPushMatrix();
|
||||||
// renderArgs->_context->render(batch);
|
// renderArgs->_context->render(batch);
|
||||||
// glPopMatrix();
|
// glPopMatrix();
|
||||||
|
|
|
@ -406,6 +406,7 @@ void Model::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_meshGroupsKnown = false;
|
_meshGroupsKnown = false;
|
||||||
|
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::updateGeometry() {
|
bool Model::updateGeometry() {
|
||||||
|
@ -456,6 +457,7 @@ bool Model::updateGeometry() {
|
||||||
_dilatedTextures.clear();
|
_dilatedTextures.clear();
|
||||||
_geometry = geometry;
|
_geometry = geometry;
|
||||||
_meshGroupsKnown = false;
|
_meshGroupsKnown = false;
|
||||||
|
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||||
initJointStates(newJointStates);
|
initJointStates(newJointStates);
|
||||||
needToRebuild = true;
|
needToRebuild = true;
|
||||||
} else if (_jointStates.isEmpty()) {
|
} else if (_jointStates.isEmpty()) {
|
||||||
|
@ -704,10 +706,26 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
int i2 = part.quadIndices[vIndex++];
|
int i2 = part.quadIndices[vIndex++];
|
||||||
int i3 = part.quadIndices[vIndex++];
|
int i3 = part.quadIndices[vIndex++];
|
||||||
|
|
||||||
glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)));
|
glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f));
|
||||||
glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)));
|
glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f));
|
||||||
glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)));
|
glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f));
|
||||||
glm::vec3 v3 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f)));
|
glm::vec3 mv3 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f));
|
||||||
|
|
||||||
|
// track the mesh parts in model space
|
||||||
|
if (!atLeastOnePointInBounds) {
|
||||||
|
thisPartBounds.setBox(mv0, 0.0f);
|
||||||
|
atLeastOnePointInBounds = true;
|
||||||
|
} else {
|
||||||
|
thisPartBounds += mv0;
|
||||||
|
}
|
||||||
|
thisPartBounds += mv1;
|
||||||
|
thisPartBounds += mv2;
|
||||||
|
thisPartBounds += mv3;
|
||||||
|
|
||||||
|
glm::vec3 v0 = calculateScaledOffsetPoint(mv0);
|
||||||
|
glm::vec3 v1 = calculateScaledOffsetPoint(mv1);
|
||||||
|
glm::vec3 v2 = calculateScaledOffsetPoint(mv2);
|
||||||
|
glm::vec3 v3 = calculateScaledOffsetPoint(mv3);
|
||||||
|
|
||||||
// Sam's recommended triangle slices
|
// Sam's recommended triangle slices
|
||||||
Triangle tri1 = { v0, v1, v3 };
|
Triangle tri1 = { v0, v1, v3 };
|
||||||
|
@ -720,14 +738,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
thisMeshTriangles.push_back(tri1);
|
thisMeshTriangles.push_back(tri1);
|
||||||
thisMeshTriangles.push_back(tri2);
|
thisMeshTriangles.push_back(tri2);
|
||||||
|
|
||||||
if (!atLeastOnePointInBounds) {
|
|
||||||
thisPartBounds.setBox(v0, 0.0f);
|
|
||||||
atLeastOnePointInBounds = true;
|
|
||||||
}
|
|
||||||
thisPartBounds += v0;
|
|
||||||
thisPartBounds += v1;
|
|
||||||
thisPartBounds += v2;
|
|
||||||
thisPartBounds += v3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,21 +749,27 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
||||||
int i1 = part.triangleIndices[vIndex++];
|
int i1 = part.triangleIndices[vIndex++];
|
||||||
int i2 = part.triangleIndices[vIndex++];
|
int i2 = part.triangleIndices[vIndex++];
|
||||||
|
|
||||||
glm::vec3 v0 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)));
|
glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f));
|
||||||
glm::vec3 v1 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)));
|
glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f));
|
||||||
glm::vec3 v2 = calculateScaledOffsetPoint(glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)));
|
glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f));
|
||||||
|
|
||||||
|
// track the mesh parts in model space
|
||||||
|
if (!atLeastOnePointInBounds) {
|
||||||
|
thisPartBounds.setBox(mv0, 0.0f);
|
||||||
|
atLeastOnePointInBounds = true;
|
||||||
|
} else {
|
||||||
|
thisPartBounds += mv0;
|
||||||
|
}
|
||||||
|
thisPartBounds += mv1;
|
||||||
|
thisPartBounds += mv2;
|
||||||
|
|
||||||
|
glm::vec3 v0 = calculateScaledOffsetPoint(mv0);
|
||||||
|
glm::vec3 v1 = calculateScaledOffsetPoint(mv1);
|
||||||
|
glm::vec3 v2 = calculateScaledOffsetPoint(mv2);
|
||||||
|
|
||||||
Triangle tri = { v0, v1, v2 };
|
Triangle tri = { v0, v1, v2 };
|
||||||
|
|
||||||
thisMeshTriangles.push_back(tri);
|
thisMeshTriangles.push_back(tri);
|
||||||
|
|
||||||
if (!atLeastOnePointInBounds) {
|
|
||||||
thisPartBounds.setBox(v0, 0.0f);
|
|
||||||
atLeastOnePointInBounds = true;
|
|
||||||
}
|
|
||||||
thisPartBounds += v0;
|
|
||||||
thisPartBounds += v1;
|
|
||||||
thisPartBounds += v2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
|
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
|
||||||
|
@ -819,7 +835,6 @@ namespace render {
|
||||||
template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) {
|
template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) {
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_elementsTouched++;
|
args->_elementsTouched++;
|
||||||
//qDebug() << "would be TransparentMeshPart: " << payload->meshIndex << "," << payload->partIndex;
|
|
||||||
return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true);
|
return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -843,7 +858,9 @@ namespace render {
|
||||||
|
|
||||||
template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) {
|
template <> const Item::Bound payloadGetBound(const OpaqueMeshPart::Pointer& payload) {
|
||||||
if (payload) {
|
if (payload) {
|
||||||
return payload->model->getPartBounds(payload->meshIndex, payload->partIndex);
|
Item::Bound result = payload->model->getPartBounds(payload->meshIndex, payload->partIndex);
|
||||||
|
//qDebug() << "payloadGetBound(OpaqueMeshPart) " << result;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return render::Item::Bound();
|
return render::Item::Bound();
|
||||||
}
|
}
|
||||||
|
@ -857,6 +874,10 @@ namespace render {
|
||||||
|
|
||||||
|
|
||||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||||
|
if (!_meshGroupsKnown && isLoadedWithTextures()) {
|
||||||
|
segregateMeshGroups();
|
||||||
|
}
|
||||||
|
|
||||||
bool somethingAdded = false;
|
bool somethingAdded = false;
|
||||||
|
|
||||||
qDebug() << "Model::addToScene : " << this->getURL().toString();
|
qDebug() << "Model::addToScene : " << this->getURL().toString();
|
||||||
|
@ -883,6 +904,8 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChan
|
||||||
_renderItems << item;
|
_renderItems << item;
|
||||||
somethingAdded = true;
|
somethingAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_readyWhenAdded = readyToAddToScene();
|
||||||
|
|
||||||
return somethingAdded;
|
return somethingAdded;
|
||||||
}
|
}
|
||||||
|
@ -897,9 +920,8 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin
|
||||||
pendingChanges.removeItem(item);
|
pendingChanges.removeItem(item);
|
||||||
}
|
}
|
||||||
_renderItems.clear();
|
_renderItems.clear();
|
||||||
|
_readyWhenAdded = false;
|
||||||
qDebug() << "Model::removeFromScene : " << this->getURL().toString();
|
qDebug() << "Model::removeFromScene : " << this->getURL().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::render(RenderArgs* renderArgs, float alpha) {
|
bool Model::render(RenderArgs* renderArgs, float alpha) {
|
||||||
|
@ -1219,6 +1241,11 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
||||||
return translatedExtents;
|
return translatedExtents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the world space equivalent of some box in model space.
|
||||||
|
AABox Model::calculateScaledOffsetAABox(const AABox& box) const {
|
||||||
|
return AABox(calculateScaledOffsetExtents(Extents(box)));
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const {
|
glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const {
|
||||||
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
||||||
glm::vec3 offsetPoint = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(point, 1.0f));
|
glm::vec3 offsetPoint = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(point, 1.0f));
|
||||||
|
@ -1539,6 +1566,12 @@ void Model::snapToRegistrationPoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::simulate(float deltaTime, bool fullUpdate) {
|
void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||||
|
/*
|
||||||
|
qDebug() << "Model::simulate()";
|
||||||
|
qDebug() << " _translation:" << _translation;
|
||||||
|
qDebug() << " _rotation:" << _rotation;
|
||||||
|
*/
|
||||||
|
|
||||||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||||
|
|
||||||
|
@ -1929,6 +1962,7 @@ void Model::applyNextGeometry() {
|
||||||
_baseGeometry = _nextBaseGeometry;
|
_baseGeometry = _nextBaseGeometry;
|
||||||
_geometry = _nextGeometry;
|
_geometry = _nextGeometry;
|
||||||
_meshGroupsKnown = false;
|
_meshGroupsKnown = false;
|
||||||
|
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||||
_nextBaseGeometry.reset();
|
_nextBaseGeometry.reset();
|
||||||
_nextGeometry.reset();
|
_nextGeometry.reset();
|
||||||
}
|
}
|
||||||
|
@ -2216,23 +2250,15 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
recalculateMeshBoxes(true);
|
recalculateMeshBoxes(true);
|
||||||
}
|
}
|
||||||
if (_calculatedMeshPartBoxesValid && _calculatedMeshPartBoxes.contains(QPair<int,int>(meshIndex, partIndex))) {
|
if (_calculatedMeshPartBoxesValid && _calculatedMeshPartBoxes.contains(QPair<int,int>(meshIndex, partIndex))) {
|
||||||
return _calculatedMeshPartBoxes[QPair<int,int>(meshIndex, partIndex)];
|
return calculateScaledOffsetAABox(_calculatedMeshPartBoxes[QPair<int,int>(meshIndex, partIndex)]);
|
||||||
}
|
|
||||||
if (!_calculatedMeshBoxesValid) {
|
|
||||||
return _calculatedMeshBoxes[meshIndex];
|
|
||||||
}
|
}
|
||||||
return AABox();
|
return AABox();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
|
void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent) {
|
||||||
renderSetup(args);
|
if (!_readyWhenAdded) {
|
||||||
|
return; // bail asap
|
||||||
/*
|
|
||||||
if (translucent) {
|
|
||||||
renderCore(args, 1.0f);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
auto textureCache = DependencyManager::get<TextureCache>();
|
auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
|
||||||
gpu::Batch& batch = *(args->_batch);
|
gpu::Batch& batch = *(args->_batch);
|
||||||
|
@ -2243,13 +2269,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
_transforms.push_back(Transform());
|
_transforms.push_back(Transform());
|
||||||
}
|
}
|
||||||
|
|
||||||
// _transforms[0] = _viewState->getViewTransform();
|
// _transforms[0] = _viewState->getViewTransform();
|
||||||
// args->_viewFrustum->evalViewTransform(_transforms[0]);
|
// args->_viewFrustum->evalViewTransform(_transforms[0]);
|
||||||
|
|
||||||
// apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space)
|
// apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space)
|
||||||
// _transforms[0].setTranslation(_translation);
|
// _transforms[0].setTranslation(_translation);
|
||||||
|
|
||||||
// batch.setViewTransform(_transforms[0]);
|
// batch.setViewTransform(_transforms[0]);
|
||||||
|
|
||||||
|
|
||||||
// const float OPAQUE_ALPHA_THRESHOLD = 0.5f;
|
// const float OPAQUE_ALPHA_THRESHOLD = 0.5f;
|
||||||
|
@ -2259,10 +2285,15 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||||
|
|
||||||
|
// guard against partially loaded meshes
|
||||||
|
if (meshIndex >= networkMeshes.size() || meshIndex >= geometry.meshes.size() || meshIndex >= _meshStates.size() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const NetworkMesh& networkMesh = networkMeshes.at(meshIndex);
|
const NetworkMesh& networkMesh = networkMeshes.at(meshIndex);
|
||||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||||
const MeshState& state = _meshStates.at(meshIndex);
|
const MeshState& state = _meshStates.at(meshIndex);
|
||||||
|
|
||||||
bool translucentMesh = translucent; // networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size();
|
bool translucentMesh = translucent; // networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size();
|
||||||
bool hasTangents = !mesh.tangents.isEmpty();
|
bool hasTangents = !mesh.tangents.isEmpty();
|
||||||
bool hasSpecular = mesh.hasSpecularTexture();
|
bool hasSpecular = mesh.hasSpecularTexture();
|
||||||
|
@ -2287,6 +2318,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
|
|
||||||
if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) {
|
if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) {
|
||||||
_meshGroupsKnown = false; // regenerate these lists next time around.
|
_meshGroupsKnown = false; // regenerate these lists next time around.
|
||||||
|
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||||
return; // FIXME!
|
return; // FIXME!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2328,6 +2360,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
|
|
||||||
qint64 offset = 0;
|
qint64 offset = 0;
|
||||||
|
|
||||||
|
// guard against partially loaded meshes
|
||||||
|
if (partIndex >= networkMesh.parts.size() || partIndex >= mesh.parts.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const NetworkMeshPart& networkPart = networkMesh.parts.at(partIndex);
|
const NetworkMeshPart& networkPart = networkMesh.parts.at(partIndex);
|
||||||
const FBXMeshPart& part = mesh.parts.at(partIndex);
|
const FBXMeshPart& part = mesh.parts.at(partIndex);
|
||||||
model::MaterialPointer material = part._material;
|
model::MaterialPointer material = part._material;
|
||||||
|
@ -2352,8 +2389,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
|
|
||||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||||
if (mesh.isEye && diffuseMap) {
|
if (mesh.isEye && diffuseMap) {
|
||||||
diffuseMap = (_dilatedTextures[meshIndex][partIndex] =
|
// FIXME - guard against out of bounds here
|
||||||
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
if (meshIndex < _dilatedTextures.size()) {
|
||||||
|
if (partIndex < _dilatedTextures[meshIndex].size()) {
|
||||||
|
diffuseMap = (_dilatedTextures[meshIndex][partIndex] =
|
||||||
|
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static bool showDiffuse = true;
|
static bool showDiffuse = true;
|
||||||
if (showDiffuse && diffuseMap) {
|
if (showDiffuse && diffuseMap) {
|
||||||
|
@ -2623,6 +2665,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
|
|
||||||
if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {
|
if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {
|
||||||
_meshGroupsKnown = false; // regenerate these lists next time around.
|
_meshGroupsKnown = false; // regenerate these lists next time around.
|
||||||
|
_readyWhenAdded = false; // in case any of our users are using scenes
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ public:
|
||||||
static void endScene(RenderArgs* args);
|
static void endScene(RenderArgs* args);
|
||||||
|
|
||||||
// new Scene/Engine rendering support
|
// new Scene/Engine rendering support
|
||||||
|
bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); }
|
||||||
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); }
|
bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return isRenderable() && isActive() && isLoadedWithTextures(); }
|
||||||
bool addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
bool addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
|
@ -157,6 +158,9 @@ public:
|
||||||
/// Returns the scaled equivalent of some extents in model space.
|
/// Returns the scaled equivalent of some extents in model space.
|
||||||
Extents calculateScaledOffsetExtents(const Extents& extents) const;
|
Extents calculateScaledOffsetExtents(const Extents& extents) const;
|
||||||
|
|
||||||
|
/// Returns the world space equivalent of some box in model space.
|
||||||
|
AABox calculateScaledOffsetAABox(const AABox& box) const;
|
||||||
|
|
||||||
/// Returns the scaled equivalent of a point in model space.
|
/// Returns the scaled equivalent of a point in model space.
|
||||||
glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const;
|
glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const;
|
||||||
|
|
||||||
|
@ -542,6 +546,7 @@ private:
|
||||||
QSet<std::shared_ptr<TransparentMeshPart>> _transparentRenderItems;
|
QSet<std::shared_ptr<TransparentMeshPart>> _transparentRenderItems;
|
||||||
QSet<std::shared_ptr<OpaqueMeshPart>> _opaqueRenderItems;
|
QSet<std::shared_ptr<OpaqueMeshPart>> _opaqueRenderItems;
|
||||||
QSet<render::ItemID> _renderItems;
|
QSet<render::ItemID> _renderItems;
|
||||||
|
bool _readyWhenAdded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||||
|
|
|
@ -42,12 +42,6 @@ glm::vec3 AABox::calcCenter() const {
|
||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 AABox::calcTopFarLeft() const {
|
|
||||||
glm::vec3 topFarLeft(_corner);
|
|
||||||
topFarLeft += _scale;
|
|
||||||
return topFarLeft;
|
|
||||||
};
|
|
||||||
|
|
||||||
void AABox::scale(float scale) {
|
void AABox::scale(float scale) {
|
||||||
_corner = _corner * scale;
|
_corner = _corner * scale;
|
||||||
_scale = _scale * scale;
|
_scale = _scale * scale;
|
||||||
|
|
|
@ -47,7 +47,11 @@ public:
|
||||||
float getLargestDimension() const { return glm::max(_scale.x, glm::max(_scale.y, _scale.z)); }
|
float getLargestDimension() const { return glm::max(_scale.x, glm::max(_scale.y, _scale.z)); }
|
||||||
|
|
||||||
glm::vec3 calcCenter() const;
|
glm::vec3 calcCenter() const;
|
||||||
glm::vec3 calcTopFarLeft() const;
|
glm::vec3 calcTopFarLeft() const { return _corner + _scale; }
|
||||||
|
|
||||||
|
const glm::vec3& getMinimum() const { return _corner; }
|
||||||
|
glm::vec3 getMaximum() const { return _corner + _scale; }
|
||||||
|
|
||||||
glm::vec3 getVertex(BoxVertex vertex) const;
|
glm::vec3 getVertex(BoxVertex vertex) const;
|
||||||
|
|
||||||
const glm::vec3& getMinimumPoint() const { return _corner; }
|
const glm::vec3& getMinimumPoint() const { return _corner; }
|
||||||
|
|
|
@ -23,6 +23,10 @@ class AABox;
|
||||||
|
|
||||||
class Extents {
|
class Extents {
|
||||||
public:
|
public:
|
||||||
|
Extents(const glm::vec3& minimum, const glm::vec3& maximum) : minimum(minimum), maximum(maximum) { }
|
||||||
|
Extents() { reset(); }
|
||||||
|
Extents(const AABox& box) { reset(); add(box); }
|
||||||
|
|
||||||
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
|
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
@ -58,7 +62,7 @@ public:
|
||||||
|
|
||||||
/// \return new Extents which is original rotated around orign by rotation
|
/// \return new Extents which is original rotated around orign by rotation
|
||||||
Extents getRotated(const glm::quat& rotation) const {
|
Extents getRotated(const glm::quat& rotation) const {
|
||||||
Extents temp = { minimum, maximum };
|
Extents temp(minimum, maximum);
|
||||||
temp.rotate(rotation);
|
temp.rotate(rotation);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue