mirror of
https://github.com/lubosz/overte.git
synced 2025-04-27 20:15:29 +02:00
Voxel attachments.
This commit is contained in:
parent
240f65b7c5
commit
bae4a17605
7 changed files with 170 additions and 31 deletions
interface
resources/shaders
src/renderer
|
@ -17,8 +17,8 @@ varying vec4 normal;
|
|||
void main(void) {
|
||||
// compute the base color based on OpenGL lighting model
|
||||
vec4 normalizedNormal = normalize(normal);
|
||||
vec4 base = gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalizedNormal, gl_LightSource[0].position));
|
||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||
gl_FrontLightProduct[0].diffuse * max(0.0, dot(normalizedNormal, gl_LightSource[0].position)));
|
||||
|
||||
// compute the specular component (sans exponent)
|
||||
float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), normalizedNormal));
|
||||
|
|
|
@ -16,7 +16,10 @@ void main(void) {
|
|||
// transform and store the normal for interpolation
|
||||
normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||
|
||||
// pass along the texture coordinate
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
// use standard pipeline transform
|
||||
|
|
|
@ -31,7 +31,10 @@ void main(void) {
|
|||
position = gl_ModelViewProjectionMatrix * position;
|
||||
normal = normalize(gl_ModelViewMatrix * normal);
|
||||
|
||||
// pass along the texture coordinate
|
||||
// pass along the vertex color
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
// and the texture coordinates
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
|
||||
gl_Position = position;
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <OctalCode.h>
|
||||
|
||||
#include <VoxelTree.h>
|
||||
|
||||
#include "FBXReader.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
@ -1192,3 +1196,102 @@ FBXGeometry readFBX(const QByteArray& model, const QByteArray& mapping) {
|
|||
return extractFBXGeometry(parseFBX(&modelBuffer), parseMapping(&mappingBuffer));
|
||||
}
|
||||
|
||||
bool addMeshVoxelsOperation(VoxelNode* node, void* extraData) {
|
||||
if (!node->isLeaf()) {
|
||||
return true;
|
||||
}
|
||||
FBXMesh& mesh = *static_cast<FBXMesh*>(extraData);
|
||||
FBXMeshPart& part = mesh.parts[0];
|
||||
|
||||
const int FACE_COUNT = 6;
|
||||
const int VERTICES_PER_FACE = 4;
|
||||
const int VERTEX_COUNT = FACE_COUNT * VERTICES_PER_FACE;
|
||||
const float EIGHT_BIT_MAXIMUM = 255.0f;
|
||||
glm::vec3 color = glm::vec3(node->getColor()[0], node->getColor()[1], node->getColor()[2]) / EIGHT_BIT_MAXIMUM;
|
||||
for (int i = 0; i < VERTEX_COUNT; i++) {
|
||||
part.quadIndices.append(part.quadIndices.size());
|
||||
mesh.colors.append(color);
|
||||
}
|
||||
glm::vec3 corner = node->getCorner();
|
||||
float scale = node->getScale();
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(-1.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(0.0f, -1.0f, 0.0f));
|
||||
}
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(0.0f, 0.0f, -1.0f));
|
||||
}
|
||||
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x + scale, corner.y + scale, corner.z + scale));
|
||||
mesh.vertices.append(glm::vec3(corner.x, corner.y + scale, corner.z + scale));
|
||||
for (int i = 0; i < VERTICES_PER_FACE; i++) {
|
||||
mesh.normals.append(glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FBXGeometry readSVO(const QByteArray& model) {
|
||||
FBXGeometry geometry;
|
||||
|
||||
// we have one joint
|
||||
FBXJoint joint = { -1 };
|
||||
geometry.joints.append(joint);
|
||||
|
||||
// and one mesh with one cluster and one part
|
||||
FBXMesh mesh;
|
||||
mesh.isEye = false;
|
||||
mesh.springiness = 0.0f;
|
||||
|
||||
FBXCluster cluster = { 0 };
|
||||
mesh.clusters.append(cluster);
|
||||
|
||||
FBXMeshPart part;
|
||||
part.diffuseColor = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
part.shininess = 96.0f;
|
||||
mesh.parts.append(part);
|
||||
|
||||
VoxelTree tree;
|
||||
ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS);
|
||||
tree.readBitstreamToTree((unsigned char*)model.data(), model.size(), args);
|
||||
tree.recurseTreeWithOperation(addMeshVoxelsOperation, &mesh);
|
||||
|
||||
geometry.meshes.append(mesh);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
|
||||
QVector<glm::vec3> vertices;
|
||||
QVector<glm::vec3> normals;
|
||||
QVector<glm::vec3> colors;
|
||||
QVector<glm::vec2> texCoords;
|
||||
QVector<glm::vec4> clusterIndices;
|
||||
QVector<glm::vec4> clusterWeights;
|
||||
|
@ -137,4 +138,7 @@ public:
|
|||
/// \exception QString if an error occurs in parsing
|
||||
FBXGeometry readFBX(const QByteArray& model, const QByteArray& mapping);
|
||||
|
||||
/// Reads SVO geometry from the supplied model data.
|
||||
FBXGeometry readSVO(const QByteArray& model);
|
||||
|
||||
#endif /* defined(__interface__FBXReader__) */
|
||||
|
|
|
@ -348,7 +348,7 @@ void NetworkGeometry::maybeReadModelWithMapping() {
|
|||
}
|
||||
|
||||
try {
|
||||
_geometry = readFBX(model, mapping);
|
||||
_geometry = url.path().toLower().endsWith(".svo") ? readSVO(model) : readFBX(model, mapping);
|
||||
|
||||
} catch (const QString& error) {
|
||||
qDebug() << "Error reading " << url << ": " << error << "\n";
|
||||
|
@ -395,35 +395,43 @@ void NetworkGeometry::maybeReadModelWithMapping() {
|
|||
|
||||
// if we don't need to do any blending or springing, then the positions/normals can be static
|
||||
if (mesh.blendshapes.isEmpty() && mesh.springiness == 0.0f) {
|
||||
glBufferData(GL_ARRAY_BUFFER, (mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3) +
|
||||
mesh.texCoords.size() * sizeof(glm::vec2) + (mesh.clusterIndices.size() +
|
||||
mesh.clusterWeights.size()) * sizeof(glm::vec4), NULL, GL_STATIC_DRAW);
|
||||
int normalsOffset = mesh.vertices.size() * sizeof(glm::vec3);
|
||||
int colorsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
|
||||
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
|
||||
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
|
||||
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
|
||||
glBufferData(GL_ARRAY_BUFFER, clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4),
|
||||
NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh.vertices.size() * sizeof(glm::vec3), mesh.vertices.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(glm::vec3),
|
||||
mesh.normals.size() * sizeof(glm::vec3), mesh.normals.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, (mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3),
|
||||
mesh.texCoords.size() * sizeof(glm::vec2), mesh.texCoords.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, (mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3) +
|
||||
mesh.texCoords.size() * sizeof(glm::vec2), mesh.clusterIndices.size() * sizeof(glm::vec4),
|
||||
glBufferSubData(GL_ARRAY_BUFFER, normalsOffset, mesh.normals.size() * sizeof(glm::vec3), mesh.normals.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, colorsOffset, mesh.colors.size() * sizeof(glm::vec3), mesh.colors.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2),
|
||||
mesh.texCoords.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, clusterIndicesOffset, mesh.clusterIndices.size() * sizeof(glm::vec4),
|
||||
mesh.clusterIndices.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, (mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3) +
|
||||
mesh.texCoords.size() * sizeof(glm::vec2) + mesh.clusterIndices.size() * sizeof(glm::vec4),
|
||||
mesh.clusterWeights.size() * sizeof(glm::vec4), mesh.clusterWeights.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, clusterWeightsOffset, mesh.clusterWeights.size() * sizeof(glm::vec4),
|
||||
mesh.clusterWeights.constData());
|
||||
|
||||
// if there's no springiness, then the cluster indices/weights can be static
|
||||
} else if (mesh.springiness == 0.0f) {
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh.texCoords.size() * sizeof(glm::vec2) + (mesh.clusterIndices.size() +
|
||||
mesh.clusterWeights.size()) * sizeof(glm::vec4), NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh.texCoords.size() * sizeof(glm::vec2), mesh.texCoords.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, mesh.texCoords.size() * sizeof(glm::vec2),
|
||||
mesh.clusterIndices.size() * sizeof(glm::vec4), mesh.clusterIndices.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, mesh.texCoords.size() * sizeof(glm::vec2) +
|
||||
mesh.clusterIndices.size() * sizeof(glm::vec4), mesh.clusterWeights.size() * sizeof(glm::vec4),
|
||||
int texCoordsOffset = mesh.colors.size() * sizeof(glm::vec3);
|
||||
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
|
||||
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
|
||||
glBufferData(GL_ARRAY_BUFFER, clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4),
|
||||
NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh.colors.size() * sizeof(glm::vec3), mesh.colors.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2), mesh.texCoords.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, clusterIndicesOffset, mesh.clusterIndices.size() * sizeof(glm::vec4),
|
||||
mesh.clusterIndices.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, clusterWeightsOffset, mesh.clusterWeights.size() * sizeof(glm::vec4),
|
||||
mesh.clusterWeights.constData());
|
||||
|
||||
} else {
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh.texCoords.size() * sizeof(glm::vec2), NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh.texCoords.size() * sizeof(glm::vec2), mesh.texCoords.constData());
|
||||
int texCoordsOffset = mesh.colors.size() * sizeof(glm::vec3);
|
||||
glBufferData(GL_ARRAY_BUFFER, texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2), NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh.colors.size() * sizeof(glm::vec3), mesh.colors.constData());
|
||||
glBufferSubData(GL_ARRAY_BUFFER, texCoordsOffset, mesh.texCoords.size() * sizeof(glm::vec2),
|
||||
mesh.texCoords.constData());
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
|
|
@ -234,7 +234,6 @@ bool Model::render(float alpha) {
|
|||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
|
||||
|
@ -253,8 +252,8 @@ bool Model::render(float alpha) {
|
|||
_skinProgram.bind();
|
||||
glUniformMatrix4fvARB(_clusterMatricesLocation, state.clusterMatrices.size(), false,
|
||||
(const float*)state.clusterMatrices.constData());
|
||||
int offset = vertexCount * sizeof(glm::vec2) + (mesh.blendshapes.isEmpty() ?
|
||||
vertexCount * 2 * sizeof(glm::vec3) : 0);
|
||||
int offset = mesh.colors.size() * sizeof(glm::vec3) + mesh.texCoords.size() * sizeof(glm::vec2) +
|
||||
(mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0);
|
||||
_skinProgram.setAttributeBuffer(_clusterIndicesLocation, GL_FLOAT, offset, 4);
|
||||
_skinProgram.setAttributeBuffer(_clusterWeightsLocation, GL_FLOAT,
|
||||
offset + vertexCount * sizeof(glm::vec4), 4);
|
||||
|
@ -271,10 +270,13 @@ bool Model::render(float alpha) {
|
|||
}
|
||||
|
||||
if (mesh.blendshapes.isEmpty() && mesh.springiness == 0.0f) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3)));
|
||||
glColorPointer(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3)));
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
|
||||
mesh.colors.size() * sizeof(glm::vec3)));
|
||||
|
||||
} else {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, 0);
|
||||
glColorPointer(3, GL_FLOAT, 0, 0);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(mesh.colors.size() * sizeof(glm::vec3)));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _blendedVertexBufferIDs.at(i));
|
||||
|
||||
if (!state.worldSpaceVertices.isEmpty()) {
|
||||
|
@ -313,6 +315,15 @@ bool Model::render(float alpha) {
|
|||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
|
||||
|
||||
if (!mesh.colors.isEmpty()) {
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
} else {
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
if (!mesh.texCoords.isEmpty()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
qint64 offset = 0;
|
||||
for (int j = 0; j < networkMesh.parts.size(); j++) {
|
||||
const NetworkMeshPart& networkPart = networkMesh.parts.at(j);
|
||||
|
@ -343,6 +354,13 @@ bool Model::render(float alpha) {
|
|||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
}
|
||||
|
||||
if (!mesh.colors.isEmpty()) {
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
if (!mesh.texCoords.isEmpty()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
_skinProgram.disableAttributeArray(_clusterIndicesLocation);
|
||||
|
|
Loading…
Reference in a new issue