More work on voxeltars; basic skinning works.

This commit is contained in:
Andrzej Kapolka 2013-06-02 19:55:51 -07:00
parent 35ae08def0
commit 8d757e148f
8 changed files with 168 additions and 73 deletions

View file

@ -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));

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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 ];

View file

@ -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);

View file

@ -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