Basic attachment rendering.

This commit is contained in:
Andrzej Kapolka 2014-05-05 15:46:09 -07:00
parent 65e34f9697
commit f37460e39a
5 changed files with 76 additions and 22 deletions

View file

@ -126,6 +126,7 @@ void Avatar::simulate(float deltaTime) {
_skeletonModel.simulate(deltaTime);
}
_skeletonModel.simulate(deltaTime, _hasNewJointRotations);
simulateAttachments(deltaTime, _hasNewJointRotations);
_hasNewJointRotations = false;
glm::vec3 headPosition = _position;
@ -338,6 +339,7 @@ void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
return;
}
_skeletonModel.render(1.0f, modelRenderMode);
renderAttachments(modelRenderMode);
getHand()->render(false);
}
getHead()->render(1.0f, modelRenderMode);
@ -347,6 +349,32 @@ bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode render
return true;
}
void Avatar::simulateAttachments(float deltaTime, bool fullUpdate) {
if (!fullUpdate) {
return; // only simulate if we have new data
}
for (int i = 0; i < _attachmentModels.size(); i++) {
const AttachmentData& attachment = _attachmentData.at(i);
Model* model = _attachmentModels.at(i);
int jointIndex = getJointIndex(attachment.jointName);
glm::vec3 jointPosition;
glm::quat jointRotation;
if (_skeletonModel.getJointPosition(jointIndex, jointPosition) &&
_skeletonModel.getJointRotation(jointIndex, jointRotation)) {
model->setTranslation(jointPosition + jointRotation * attachment.translation * _skeletonModel.getScale());
model->setRotation(jointRotation * attachment.rotation);
model->setScale(_skeletonModel.getScale() * attachment.scale);
model->simulate(deltaTime);
}
}
}
void Avatar::renderAttachments(Model::RenderMode renderMode) {
foreach (Model* model, _attachmentModels) {
model->render(1.0f, renderMode);
}
}
void Avatar::updateJointMappings() {
// no-op; joint mappings come from skeleton model
}
@ -667,6 +695,25 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
}
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
AvatarData::setAttachmentData(attachmentData);
// make sure we have as many models as attachments
while (_attachmentModels.size() < attachmentData.size()) {
Model* model = new Model(this);
model->init();
_attachmentModels.append(model);
}
while (_attachmentModels.size() > attachmentData.size()) {
delete _attachmentModels.takeLast();
}
// update the urls
for (int i = 0; i < attachmentData.size(); i++) {
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
}
}
void Avatar::setDisplayName(const QString& displayName) {
AvatarData::setDisplayName(displayName);
_displayNameBoundingRect = textRenderer(DISPLAYNAME)->metrics().tightBoundingRect(displayName);

View file

@ -131,6 +131,7 @@ public:
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
virtual void setDisplayName(const QString& displayName);
virtual void setBillboard(const QByteArray& billboard);
@ -160,6 +161,7 @@ signals:
protected:
SkeletonModel _skeletonModel;
QVector<Model*> _attachmentModels;
float _bodyYawDelta;
glm::vec3 _velocity;
float _leanScale;
@ -188,6 +190,9 @@ protected:
virtual void renderBody(RenderMode renderMode, float glowLevel = 0.0f);
virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const;
void simulateAttachments(float deltaTime, bool fullUpdate = true);
void renderAttachments(Model::RenderMode renderMode);
virtual void updateJointMappings();
private:

View file

@ -244,6 +244,7 @@ void MyAvatar::simulate(float deltaTime) {
getHand()->simulate(deltaTime, true);
_skeletonModel.simulate(deltaTime);
simulateAttachments(deltaTime);
// copy out the skeleton joints from the model
_jointData.resize(_skeletonModel.getJointStateCount());
@ -657,7 +658,8 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ?
Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE;
_skeletonModel.render(1.0f, modelRenderMode);
renderAttachments(modelRenderMode);
// Render head so long as the camera isn't inside it
if (shouldRenderHead(Application::getInstance()->getCamera()->getPosition(), renderMode)) {
getHead()->render(1.0f, modelRenderMode);

View file

@ -509,6 +509,24 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo
}
}
bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
}
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
return true;
}
bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) const {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
}
rotation = _jointStates[jointIndex].combinedRotation *
(fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation :
_geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation);
return true;
}
void Model::clearShapes() {
for (int i = 0; i < _jointShapes.size(); ++i) {
delete _jointShapes[i];
@ -957,24 +975,6 @@ void Model::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint
// nothing by default
}
bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
}
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
return true;
}
bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) const {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
}
rotation = _jointStates[jointIndex].combinedRotation *
(fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation :
_geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation);
return true;
}
bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation,
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment) {
if (jointIndex == -1 || _jointStates.isEmpty()) {

View file

@ -180,6 +180,9 @@ public:
/// Returns the extended length from the right hand to its first free ancestor.
float getRightArmLength() const;
bool getJointPosition(int jointIndex, glm::vec3& position) const;
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
void clearShapes();
void rebuildShapes();
void updateShapePositions();
@ -269,9 +272,6 @@ protected:
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
bool getJointPosition(int jointIndex, glm::vec3& position) const;
bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const;
bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(),
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f));