mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 01:03:57 +02:00
More work on voxeltars; basic skinning works.
This commit is contained in:
parent
35ae08def0
commit
8d757e148f
8 changed files with 168 additions and 73 deletions
|
@ -172,8 +172,6 @@ Avatar::~Avatar() {
|
|||
|
||||
void Avatar::init() {
|
||||
_voxels.init();
|
||||
|
||||
_voxels.createVoxel(0.0f, 0.0f, 0.0f, 1.0f, 255, 0, 255);
|
||||
}
|
||||
|
||||
void Avatar::reset() {
|
||||
|
@ -953,8 +951,11 @@ void Avatar::updateBodyBalls(float deltaTime) {
|
|||
}
|
||||
*/
|
||||
|
||||
//update position by velocity...
|
||||
// update position by velocity...
|
||||
_bodyBall[b].position += _bodyBall[b].velocity * deltaTime;
|
||||
|
||||
// update rotation
|
||||
_bodyBall[b].rotation = _skeleton.joint[b].rotation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1016,14 +1017,7 @@ void Avatar::renderBody(bool lookingInMirror) {
|
|||
const float RENDER_TRANSLUCENT_BEYOND = 0.5f;
|
||||
|
||||
// Render the body's voxels
|
||||
glPushMatrix();
|
||||
const glm::vec3& voxelPosition = _joint[AVATAR_JOINT_PELVIS].springyPosition;
|
||||
glTranslatef(voxelPosition.x, voxelPosition.y, voxelPosition.z);
|
||||
glm::quat rotation = getOrientation();
|
||||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||
_voxels.render(false);
|
||||
glPopMatrix();
|
||||
|
||||
// Render the body as balls and cones
|
||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||
|
@ -1130,6 +1124,11 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const {
|
||||
position = _bodyBall[jointID].position;
|
||||
rotation = _bodyBall[jointID].rotation;
|
||||
}
|
||||
|
||||
void Avatar::writeAvatarDataToFile() {
|
||||
Application::getInstance()->setSetting("avatarPos", _position);
|
||||
Application::getInstance()->setSetting("avatarRotation", glm::vec3(_bodyYaw, _bodyPitch, _bodyRoll));
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
void setOrientation (const glm::quat& orientation);
|
||||
|
||||
//getters
|
||||
|
||||
const Skeleton& getSkeleton () const { return _skeleton;}
|
||||
float getHeadYawRate () const { return _head.yawRate;}
|
||||
float getBodyYaw () const { return _bodyYaw;}
|
||||
bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();}
|
||||
|
@ -97,6 +97,9 @@ public:
|
|||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||
glm::vec3 getThrust() { return _thrust; };
|
||||
|
||||
// Get the position/rotation of a single body ball
|
||||
void getBodyBallTransform(AvatarJointID jointID, glm::vec3& position, glm::quat& rotation) const;
|
||||
|
||||
//read/write avatar data
|
||||
void writeAvatarDataToFile();
|
||||
void readAvatarDataFromFile();
|
||||
|
@ -108,7 +111,8 @@ private:
|
|||
|
||||
struct AvatarBall
|
||||
{
|
||||
glm::vec3 position;
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
glm::vec3 velocity;
|
||||
float jointTightness;
|
||||
float radius;
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "AvatarVoxelSystem.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
const float AVATAR_TREE_SCALE = 1.0f;
|
||||
const int MAX_VOXELS_PER_AVATAR = 2000;
|
||||
const int BONE_INDEX_ELEMENTS_PER_VERTEX = 4;
|
||||
const int BONE_INDEX_ELEMENTS_PER_VOXEL = BONE_INDEX_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL;
|
||||
const int BONE_WEIGHT_ELEMENTS_PER_VERTEX = 4;
|
||||
const int BONE_WEIGHT_ELEMENTS_PER_VOXEL = BONE_WEIGHT_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL;
|
||||
const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXEL;
|
||||
|
||||
AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) :
|
||||
VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR),
|
||||
|
@ -38,21 +38,31 @@ void AvatarVoxelSystem::init() {
|
|||
VoxelSystem::init();
|
||||
|
||||
// prep the data structures for incoming voxel data
|
||||
_writeBoneIndicesArray = new GLubyte[BONE_INDEX_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_readBoneIndicesArray = new GLubyte[BONE_INDEX_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_writeBoneIndicesArray = new GLubyte[BONE_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_readBoneIndicesArray = new GLubyte[BONE_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
|
||||
_writeBoneWeightsArray = new GLfloat[BONE_WEIGHT_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_readBoneWeightsArray = new GLfloat[BONE_WEIGHT_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_writeBoneWeightsArray = new GLfloat[BONE_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
_readBoneWeightsArray = new GLfloat[BONE_ELEMENTS_PER_VOXEL * _maxVoxels];
|
||||
|
||||
// VBO for the boneIndicesArray
|
||||
glGenBuffers(1, &_vboBoneIndicesID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID);
|
||||
glBufferData(GL_ARRAY_BUFFER, BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
// VBO for the boneWeightsArray
|
||||
glGenBuffers(1, &_vboBoneWeightsID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
|
||||
glBufferData(GL_ARRAY_BUFFER, BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
for (int i = 0; i < 150; i++) {
|
||||
int power = pow(2, randIntInRange(6, 8));
|
||||
float size = 1.0f / power;
|
||||
_tree->createVoxel(
|
||||
randIntInRange(0, power - 1) * size,
|
||||
randIntInRange(0, power - 1) * size,
|
||||
randIntInRange(0, power - 1) * size, size, 255, 0, 255, true);
|
||||
}
|
||||
setupNewVoxelsForDrawing();
|
||||
|
||||
// load our skin program if this is the first avatar system to initialize
|
||||
if (_skinProgram != 0) {
|
||||
|
@ -75,14 +85,15 @@ void AvatarVoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::v
|
|||
float voxelScale, const nodeColor& color) {
|
||||
VoxelSystem::updateNodeInArrays(nodeIndex, startVertex, voxelScale, color);
|
||||
|
||||
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_INDEX_ELEMENTS_PER_VOXEL);
|
||||
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
|
||||
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (nodeIndex * BONE_ELEMENTS_PER_VOXEL);
|
||||
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (nodeIndex * BONE_ELEMENTS_PER_VOXEL);
|
||||
for (int i = 0; i < VERTICES_PER_VOXEL; i++) {
|
||||
GLubyte boneIndices[] = { 0, 0, 0, 0};
|
||||
glm::vec4 boneWeights = glm::vec4(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
for (int j = 0; j < BONE_INDEX_ELEMENTS_PER_VERTEX; j++) {
|
||||
*(writeBoneIndicesAt + i * BONE_INDEX_ELEMENTS_PER_VERTEX + j) = boneIndices[j];
|
||||
*(writeBoneWeightsAt + i * BONE_WEIGHT_ELEMENTS_PER_VERTEX + j) = boneWeights[j];
|
||||
BoneIndices boneIndices;
|
||||
glm::vec4 boneWeights;
|
||||
computeBoneIndicesAndWeights(computeVoxelVertex(startVertex, voxelScale, i), boneIndices, boneWeights);
|
||||
for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) {
|
||||
*(writeBoneIndicesAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneIndices[j];
|
||||
*(writeBoneWeightsAt + i * BONE_ELEMENTS_PER_VERTEX + j) = boneWeights[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,16 +102,16 @@ void AvatarVoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segment
|
|||
VoxelSystem::copyWrittenDataSegmentToReadArrays(segmentStart, segmentEnd);
|
||||
|
||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||
GLintptr segmentStartAt = segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLsizeiptr segmentSizeBytes = segmentLength * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLubyte* readBoneIndicesAt = _readBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL);
|
||||
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL);
|
||||
GLintptr segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLsizeiptr segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLubyte* readBoneIndicesAt = _readBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
GLubyte* writeBoneIndicesAt = _writeBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
memcpy(readBoneIndicesAt, writeBoneIndicesAt, segmentSizeBytes);
|
||||
|
||||
segmentStartAt = segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
segmentSizeBytes = segmentLength * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
GLfloat* readBoneWeightsAt = _readBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
|
||||
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
|
||||
segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
GLfloat* readBoneWeightsAt = _readBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
GLfloat* writeBoneWeightsAt = _writeBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
memcpy(readBoneWeightsAt, writeBoneWeightsAt, segmentSizeBytes);
|
||||
}
|
||||
|
||||
|
@ -108,38 +119,94 @@ void AvatarVoxelSystem::updateVBOSegment(glBufferIndex segmentStart, glBufferInd
|
|||
VoxelSystem::updateVBOSegment(segmentStart, segmentEnd);
|
||||
|
||||
int segmentLength = (segmentEnd - segmentStart) + 1;
|
||||
GLintptr segmentStartAt = segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLsizeiptr segmentSizeBytes = segmentLength * BONE_INDEX_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLubyte* readBoneIndicesFrom = _readBoneIndicesArray + (segmentStart * BONE_INDEX_ELEMENTS_PER_VOXEL);
|
||||
GLintptr segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLsizeiptr segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLubyte);
|
||||
GLubyte* readBoneIndicesFrom = _readBoneIndicesArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneIndicesFrom);
|
||||
|
||||
segmentStartAt = segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
segmentSizeBytes = segmentLength * BONE_WEIGHT_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
GLfloat* readBoneWeightsFrom = _readBoneWeightsArray + (segmentStart * BONE_WEIGHT_ELEMENTS_PER_VOXEL);
|
||||
segmentStartAt = segmentStart * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
segmentSizeBytes = segmentLength * BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat);
|
||||
GLfloat* readBoneWeightsFrom = _readBoneWeightsArray + (segmentStart * BONE_ELEMENTS_PER_VOXEL);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readBoneWeightsFrom);
|
||||
}
|
||||
|
||||
void AvatarVoxelSystem::bindProgram(bool texture) {
|
||||
void AvatarVoxelSystem::applyScaleAndBindProgram(bool texture) {
|
||||
_skinProgram->bind();
|
||||
|
||||
QMatrix4x4 boneMatrices[1];
|
||||
// the base matrix includes centering and scale
|
||||
QMatrix4x4 baseMatrix;
|
||||
baseMatrix.scale(_treeScale);
|
||||
baseMatrix.translate(-0.5f, -0.5f, -0.5f);
|
||||
|
||||
_skinProgram->setUniformValueArray(_boneMatricesLocation, boneMatrices, sizeof(boneMatrices) / sizeof(boneMatrices[0]));
|
||||
// bone matrices include joint transforms
|
||||
QMatrix4x4 boneMatrices[NUM_AVATAR_JOINTS];
|
||||
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
|
||||
glm::vec3 position;
|
||||
glm::quat orientation;
|
||||
_avatar->getBodyBallTransform((AvatarJointID)i, position, orientation);
|
||||
boneMatrices[i].translate(position.x, position.y, position.z);
|
||||
boneMatrices[i].rotate(QQuaternion(orientation.w, orientation.x, orientation.y, orientation.z));
|
||||
const glm::vec3& defaultPosition = _avatar->getSkeleton().joint[i].absoluteDefaultPosePosition;
|
||||
boneMatrices[i].translate(-defaultPosition.x, -defaultPosition.y, -defaultPosition.z);
|
||||
boneMatrices[i] *= baseMatrix;
|
||||
}
|
||||
_skinProgram->setUniformValueArray(_boneMatricesLocation, boneMatrices, NUM_AVATAR_JOINTS);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneIndicesID);
|
||||
_skinProgram->setAttributeBuffer(_boneIndicesLocation, GL_UNSIGNED_BYTE, 0, BONE_INDEX_ELEMENTS_PER_VERTEX);
|
||||
glVertexAttribPointer(_boneIndicesLocation, BONE_ELEMENTS_PER_VERTEX, GL_UNSIGNED_BYTE, false, 0, 0);
|
||||
_skinProgram->enableAttributeArray(_boneIndicesLocation);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
|
||||
_skinProgram->setAttributeBuffer(_boneWeightsLocation, GL_FLOAT, 0, BONE_WEIGHT_ELEMENTS_PER_VERTEX);
|
||||
_skinProgram->setAttributeBuffer(_boneWeightsLocation, GL_FLOAT, 0, BONE_ELEMENTS_PER_VERTEX);
|
||||
_skinProgram->enableAttributeArray(_boneWeightsLocation);
|
||||
}
|
||||
|
||||
void AvatarVoxelSystem::releaseProgram(bool texture) {
|
||||
void AvatarVoxelSystem::removeScaleAndReleaseProgram(bool texture) {
|
||||
_skinProgram->release();
|
||||
_skinProgram->disableAttributeArray(_boneIndicesLocation);
|
||||
_skinProgram->disableAttributeArray(_boneWeightsLocation);
|
||||
}
|
||||
|
||||
class IndexDistance {
|
||||
public:
|
||||
IndexDistance(GLubyte index = 0, float distance = FLT_MAX) : index(index), distance(distance) { }
|
||||
|
||||
GLubyte index;
|
||||
float distance;
|
||||
};
|
||||
|
||||
void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, BoneIndices& indices, glm::vec4& weights) const {
|
||||
// transform into joint space
|
||||
glm::vec3 jointVertex = (vertex - glm::vec3(0.5f, 0.5f, 0.5f)) * AVATAR_TREE_SCALE;
|
||||
|
||||
// find the nearest four joints (TODO: use a better data structure for the pose positions to speed this up)
|
||||
IndexDistance nearest[BONE_ELEMENTS_PER_VERTEX];
|
||||
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
|
||||
float distance = glm::distance(jointVertex, _avatar->getSkeleton().joint[i].absoluteDefaultPosePosition);
|
||||
for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) {
|
||||
if (distance < nearest[j].distance) {
|
||||
// move the rest of the indices down
|
||||
for (int k = BONE_ELEMENTS_PER_VERTEX - 1; k > j; k--) {
|
||||
nearest[k] = nearest[k - 1];
|
||||
}
|
||||
nearest[j] = IndexDistance(i, distance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compute the weights based on inverse distance
|
||||
float totalWeight = 0.0f;
|
||||
for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) {
|
||||
indices[i] = nearest[i].index;
|
||||
weights[i] = (i == 0) ? 1.0f : 0.0f; // 1.0f / glm::max(nearest[i].distance, EPSILON);
|
||||
totalWeight += weights[i];
|
||||
}
|
||||
|
||||
// normalize the weights
|
||||
for (int i = 0; i < BONE_ELEMENTS_PER_VERTEX; i++) {
|
||||
weights[i] /= totalWeight;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
|
||||
#include "VoxelSystem.h"
|
||||
|
||||
const int BONE_ELEMENTS_PER_VERTEX = 4;
|
||||
typedef GLubyte BoneIndices[BONE_ELEMENTS_PER_VERTEX];
|
||||
|
||||
class Avatar;
|
||||
|
||||
class AvatarVoxelSystem : public VoxelSystem {
|
||||
|
@ -28,11 +31,13 @@ protected:
|
|||
float voxelScale, const nodeColor& color);
|
||||
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void bindProgram(bool texture);
|
||||
virtual void releaseProgram(bool texture);
|
||||
virtual void applyScaleAndBindProgram(bool texture);
|
||||
virtual void removeScaleAndReleaseProgram(bool texture);
|
||||
|
||||
private:
|
||||
|
||||
void computeBoneIndicesAndWeights(const glm::vec3& vertex, BoneIndices& indices, glm::vec4& weights) const;
|
||||
|
||||
Avatar* _avatar;
|
||||
|
||||
GLubyte* _readBoneIndicesArray;
|
||||
|
|
|
@ -18,7 +18,7 @@ void Skeleton::initialize() {
|
|||
joint[b].parent = AVATAR_JOINT_NULL;
|
||||
joint[b].position = glm::vec3(0.0, 0.0, 0.0);
|
||||
joint[b].defaultPosePosition = glm::vec3(0.0, 0.0, 0.0);
|
||||
joint[b].rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
joint[b].rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
joint[b].length = 0.0;
|
||||
}
|
||||
|
||||
|
@ -77,9 +77,18 @@ void Skeleton::initialize() {
|
|||
joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( -0.01, -0.22, 0.08 );
|
||||
joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
|
||||
|
||||
// calculate bone length
|
||||
// calculate bone length, absolute positions
|
||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||
joint[b].length = glm::length(joint[b].defaultPosePosition);
|
||||
|
||||
if (joint[b].parent == AVATAR_JOINT_NULL) {
|
||||
joint[b].absoluteDefaultPosePosition = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
} else {
|
||||
joint[b].absoluteDefaultPosePosition = joint[ joint[b].parent ].absoluteDefaultPosePosition;
|
||||
}
|
||||
|
||||
glm::vec3 rotatedJointVector = joint[b].defaultPosePosition;
|
||||
joint[b].absoluteDefaultPosePosition += rotatedJointVector;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,11 +58,12 @@ public:
|
|||
|
||||
struct AvatarJoint
|
||||
{
|
||||
AvatarJointID parent; // which joint is this joint connected to?
|
||||
glm::vec3 position; // the position at the "end" of the joint - in global space
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::quat rotation; // the parent-relative rotation (orientation) of the joint as a quaternion
|
||||
float length; // the length of vector connecting the joint and its parent
|
||||
AvatarJointID parent; // which joint is this joint connected to?
|
||||
glm::vec3 position; // the position at the "end" of the joint - in global space
|
||||
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose"
|
||||
glm::vec3 absoluteDefaultPosePosition; // the absolute position when the avatar is in the "T-pose"
|
||||
glm::quat rotation; // the parent-relative rotation (orientation) of the joint as a quaternion
|
||||
float length; // the length of vector connecting the joint and its parent
|
||||
};
|
||||
|
||||
AvatarJoint joint[ NUM_AVATAR_JOINTS ];
|
||||
|
|
|
@ -415,6 +415,11 @@ void VoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& s
|
|||
}
|
||||
}
|
||||
|
||||
glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const {
|
||||
const float* identityVertex = identityVertices + index * 3;
|
||||
return startVertex + glm::vec3(identityVertex[0], identityVertex[1], identityVertex[2]) * voxelScale;
|
||||
}
|
||||
|
||||
ProgramObject* VoxelSystem::_perlinModulateProgram = 0;
|
||||
GLuint VoxelSystem::_permutationNormalTextureID = 0;
|
||||
|
||||
|
@ -609,8 +614,8 @@ void VoxelSystem::render(bool texture) {
|
|||
// get the lock so that the update thread won't change anything
|
||||
pthread_mutex_lock(&_bufferWriteLock);
|
||||
|
||||
glPushMatrix();
|
||||
updateVBOs();
|
||||
|
||||
// tell OpenGL where to find vertex and color information
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
@ -625,7 +630,7 @@ void VoxelSystem::render(bool texture) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
|
||||
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
|
||||
|
||||
bindProgram(texture);
|
||||
applyScaleAndBindProgram(texture);
|
||||
|
||||
// for performance, disable blending and enable backface culling
|
||||
glDisable(GL_BLEND);
|
||||
|
@ -633,14 +638,13 @@ void VoxelSystem::render(bool texture) {
|
|||
|
||||
// draw the number of voxels we have
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
|
||||
glScalef(_treeScale, _treeScale, _treeScale);
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, VERTICES_PER_VOXEL * _voxelsInReadArrays - 1,
|
||||
36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
releaseProgram(texture);
|
||||
removeScaleAndReleaseProgram(texture);
|
||||
|
||||
// deactivate vertex and color arrays after drawing
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -650,21 +654,24 @@ void VoxelSystem::render(bool texture) {
|
|||
// bind with 0 to switch back to normal operation
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
|
||||
pthread_mutex_unlock(&_bufferWriteLock);
|
||||
}
|
||||
|
||||
void VoxelSystem::bindProgram(bool texture) {
|
||||
void VoxelSystem::applyScaleAndBindProgram(bool texture) {
|
||||
glPushMatrix();
|
||||
glScalef(_treeScale, _treeScale, _treeScale);
|
||||
|
||||
if (texture) {
|
||||
_perlinModulateProgram->bind();
|
||||
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelSystem::releaseProgram(bool texture) {
|
||||
void VoxelSystem::removeScaleAndReleaseProgram(bool texture) {
|
||||
// scale back down to 1 so heads aren't massive
|
||||
glPopMatrix();
|
||||
|
||||
if (texture) {
|
||||
_perlinModulateProgram->release();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
|
|
@ -81,14 +81,20 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
int _maxVoxels;
|
||||
float _treeScale;
|
||||
int _maxVoxels;
|
||||
VoxelTree* _tree;
|
||||
|
||||
glm::vec3 computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const;
|
||||
|
||||
void setupNewVoxelsForDrawing();
|
||||
|
||||
virtual void updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||
float voxelScale, const nodeColor& color);
|
||||
virtual void copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
|
||||
virtual void bindProgram(bool texture);
|
||||
virtual void releaseProgram(bool texture);
|
||||
virtual void applyScaleAndBindProgram(bool texture);
|
||||
virtual void removeScaleAndReleaseProgram(bool texture);
|
||||
|
||||
private:
|
||||
// disallow copying of VoxelSystem objects
|
||||
|
@ -123,8 +129,6 @@ private:
|
|||
static float _maxDistance;
|
||||
static float _minDistance;
|
||||
|
||||
float _treeScale;
|
||||
VoxelTree* _tree;
|
||||
GLfloat* _readVerticesArray;
|
||||
GLubyte* _readColorsArray;
|
||||
GLfloat* _writeVerticesArray;
|
||||
|
@ -157,7 +161,6 @@ private:
|
|||
int newTreeToArrays(VoxelNode *currentNode);
|
||||
void cleanupRemovedVoxels();
|
||||
|
||||
void setupNewVoxelsForDrawing();
|
||||
void copyWrittenDataToReadArrays(bool fullVBOs);
|
||||
|
||||
void updateFullVBOs(); // all voxels in the VBO
|
||||
|
|
Loading…
Reference in a new issue