mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 19:04:32 +02:00
Support for multiple mesh "parts" (with different materials), fix for
untextured meshes.
This commit is contained in:
parent
0a5ba79bbe
commit
ba25087b3e
8 changed files with 191 additions and 106 deletions
|
@ -236,10 +236,11 @@ bool BlendFace::render(float alpha) {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
_blendedVertexBufferIDs.append(id);
|
||||
|
||||
QVector<QSharedPointer<Texture> > dilated;
|
||||
dilated.resize(mesh.parts.size());
|
||||
_dilatedTextures.append(dilated);
|
||||
}
|
||||
|
||||
// make sure we have the right number of dilated texture pointers
|
||||
_dilatedTextures.resize(geometry.meshes.size());
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -255,23 +256,6 @@ bool BlendFace::render(float alpha) {
|
|||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
int vertexCount = mesh.vertices.size();
|
||||
|
||||
// apply eye rotation if appropriate
|
||||
Texture* texture = networkMesh.diffuseTexture.data();
|
||||
if (mesh.isEye) {
|
||||
if (texture != NULL) {
|
||||
texture = (_dilatedTextures[i] = static_cast<DilatableNetworkTexture*>(texture)->getDilatedTexture(
|
||||
_owningHead->getPupilDilation())).data();
|
||||
}
|
||||
}
|
||||
|
||||
// apply material properties
|
||||
glm::vec4 diffuse = glm::vec4(mesh.diffuseColor, alpha);
|
||||
glm::vec4 specular = glm::vec4(mesh.specularColor, alpha);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, mesh.shininess);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, networkMesh.vertexBufferID);
|
||||
|
||||
const MeshState& state = _meshStates.at(i);
|
||||
|
@ -297,8 +281,6 @@ bool BlendFace::render(float alpha) {
|
|||
_program.bind();
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture == NULL ? 0 : texture->getID());
|
||||
|
||||
if (mesh.blendshapes.isEmpty() && mesh.springiness == 0.0f) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3)));
|
||||
|
||||
|
@ -343,10 +325,36 @@ bool BlendFace::render(float alpha) {
|
|||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
|
||||
|
||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, mesh.quadIndices.size(), GL_UNSIGNED_INT, 0);
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, mesh.triangleIndices.size(),
|
||||
GL_UNSIGNED_INT, (void*)(mesh.quadIndices.size() * sizeof(int)));
|
||||
qint64 offset = 0;
|
||||
for (int j = 0; j < networkMesh.parts.size(); j++) {
|
||||
const NetworkMeshPart& networkPart = networkMesh.parts.at(j);
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
|
||||
// apply material properties
|
||||
glm::vec4 diffuse = glm::vec4(part.diffuseColor, alpha);
|
||||
glm::vec4 specular = glm::vec4(part.specularColor, alpha);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, part.shininess);
|
||||
|
||||
Texture* texture = networkPart.diffuseTexture.data();
|
||||
if (mesh.isEye) {
|
||||
if (texture != NULL) {
|
||||
texture = (_dilatedTextures[i][j] = static_cast<DilatableNetworkTexture*>(texture)->getDilatedTexture(
|
||||
_owningHead->getPupilDilation())).data();
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, texture == NULL ? Application::getInstance()->getTextureCache()->getWhiteTextureID() :
|
||||
texture->getID());
|
||||
|
||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
||||
GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
}
|
||||
|
||||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
_skinProgram.disableAttributeArray(_clusterIndicesLocation);
|
||||
|
|
|
@ -76,7 +76,7 @@ private:
|
|||
|
||||
QVector<MeshState> _meshStates;
|
||||
QVector<GLuint> _blendedVertexBufferIDs;
|
||||
QVector<QSharedPointer<Texture> > _dilatedTextures;
|
||||
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
||||
bool _resetStates;
|
||||
|
||||
QVector<glm::vec3> _blendedVertices;
|
||||
|
|
|
@ -426,6 +426,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
QVector<int> normalIndices;
|
||||
QVector<glm::vec2> texCoords;
|
||||
QVector<int> texCoordIndices;
|
||||
QVector<int> materials;
|
||||
foreach (const FBXNode& data, object.children) {
|
||||
if (data.name == "Vertices") {
|
||||
mesh.vertices = createVec3Vector(data.properties.at(0).value<QVector<double> >());
|
||||
|
@ -459,6 +460,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
texCoordIndices = subdata.properties.at(0).value<QVector<int> >();
|
||||
}
|
||||
}
|
||||
} else if (data.name == "LayerElementMaterial") {
|
||||
foreach (const FBXNode& subdata, data.children) {
|
||||
if (subdata.name == "Materials") {
|
||||
materials = subdata.properties.at(0).value<QVector<int> >();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,25 +501,30 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
}
|
||||
|
||||
// convert the polygons to quads and triangles
|
||||
int polygonIndex = 0;
|
||||
for (const int* beginIndex = polygonIndices.constData(), *end = beginIndex + polygonIndices.size();
|
||||
beginIndex != end; ) {
|
||||
beginIndex != end; polygonIndex++) {
|
||||
const int* endIndex = beginIndex;
|
||||
while (*endIndex++ >= 0);
|
||||
|
||||
int materialIndex = (polygonIndex < materials.size()) ? materials.at(polygonIndex) : 0;
|
||||
mesh.parts.resize(max(mesh.parts.size(), materialIndex + 1));
|
||||
FBXMeshPart& part = mesh.parts[materialIndex];
|
||||
|
||||
if (endIndex - beginIndex == 4) {
|
||||
mesh.quadIndices.append(*beginIndex++);
|
||||
mesh.quadIndices.append(*beginIndex++);
|
||||
mesh.quadIndices.append(*beginIndex++);
|
||||
mesh.quadIndices.append(-*beginIndex++ - 1);
|
||||
part.quadIndices.append(*beginIndex++);
|
||||
part.quadIndices.append(*beginIndex++);
|
||||
part.quadIndices.append(*beginIndex++);
|
||||
part.quadIndices.append(-*beginIndex++ - 1);
|
||||
|
||||
} else {
|
||||
for (const int* nextIndex = beginIndex + 1;; ) {
|
||||
mesh.triangleIndices.append(*beginIndex);
|
||||
mesh.triangleIndices.append(*nextIndex++);
|
||||
part.triangleIndices.append(*beginIndex);
|
||||
part.triangleIndices.append(*nextIndex++);
|
||||
if (*nextIndex >= 0) {
|
||||
mesh.triangleIndices.append(*nextIndex);
|
||||
part.triangleIndices.append(*nextIndex);
|
||||
} else {
|
||||
mesh.triangleIndices.append(-*nextIndex - 1);
|
||||
part.triangleIndices.append(-*nextIndex - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -754,21 +766,23 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
glm::mat4 modelTransform = getGlobalTransform(parentMap, models, modelID);
|
||||
|
||||
// look for textures, material properties
|
||||
int partIndex = 0;
|
||||
foreach (qint64 childID, childMap.values(modelID)) {
|
||||
if (!materials.contains(childID)) {
|
||||
if (!materials.contains(childID) || partIndex >= mesh.parts.size()) {
|
||||
continue;
|
||||
}
|
||||
Material material = materials.value(childID);
|
||||
mesh.diffuseColor = material.diffuse;
|
||||
mesh.specularColor = material.specular;
|
||||
mesh.shininess = material.shininess;
|
||||
FBXMeshPart& part = mesh.parts[partIndex++];
|
||||
part.diffuseColor = material.diffuse;
|
||||
part.specularColor = material.specular;
|
||||
part.shininess = material.shininess;
|
||||
qint64 diffuseTextureID = diffuseTextures.value(childID);
|
||||
if (diffuseTextureID != 0) {
|
||||
mesh.diffuseFilename = textureFilenames.value(diffuseTextureID);
|
||||
part.diffuseFilename = textureFilenames.value(diffuseTextureID);
|
||||
}
|
||||
qint64 bumpTextureID = bumpTextures.value(childID);
|
||||
if (bumpTextureID != 0) {
|
||||
mesh.normalFilename = textureFilenames.value(bumpTextureID);
|
||||
part.normalFilename = textureFilenames.value(bumpTextureID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -832,34 +846,36 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
QSet<QPair<int, int> > edges;
|
||||
|
||||
mesh.vertexConnections.resize(mesh.vertices.size());
|
||||
for (int i = 0; i < mesh.quadIndices.size(); i += 4) {
|
||||
int index0 = mesh.quadIndices.at(i);
|
||||
int index1 = mesh.quadIndices.at(i + 1);
|
||||
int index2 = mesh.quadIndices.at(i + 2);
|
||||
int index3 = mesh.quadIndices.at(i + 3);
|
||||
|
||||
edges.insert(QPair<int, int>(qMin(index0, index1), qMax(index0, index1)));
|
||||
edges.insert(QPair<int, int>(qMin(index1, index2), qMax(index1, index2)));
|
||||
edges.insert(QPair<int, int>(qMin(index2, index3), qMax(index2, index3)));
|
||||
edges.insert(QPair<int, int>(qMin(index3, index0), qMax(index3, index0)));
|
||||
|
||||
mesh.vertexConnections[index0].append(QPair<int, int>(index3, index1));
|
||||
mesh.vertexConnections[index1].append(QPair<int, int>(index0, index2));
|
||||
mesh.vertexConnections[index2].append(QPair<int, int>(index1, index3));
|
||||
mesh.vertexConnections[index3].append(QPair<int, int>(index2, index0));
|
||||
}
|
||||
for (int i = 0; i < mesh.triangleIndices.size(); i += 3) {
|
||||
int index0 = mesh.triangleIndices.at(i);
|
||||
int index1 = mesh.triangleIndices.at(i + 1);
|
||||
int index2 = mesh.triangleIndices.at(i + 2);
|
||||
|
||||
edges.insert(QPair<int, int>(qMin(index0, index1), qMax(index0, index1)));
|
||||
edges.insert(QPair<int, int>(qMin(index1, index2), qMax(index1, index2)));
|
||||
edges.insert(QPair<int, int>(qMin(index2, index0), qMax(index2, index0)));
|
||||
|
||||
mesh.vertexConnections[index0].append(QPair<int, int>(index2, index1));
|
||||
mesh.vertexConnections[index1].append(QPair<int, int>(index0, index2));
|
||||
mesh.vertexConnections[index2].append(QPair<int, int>(index1, index0));
|
||||
foreach (const FBXMeshPart& part, mesh.parts) {
|
||||
for (int i = 0; i < part.quadIndices.size(); i += 4) {
|
||||
int index0 = part.quadIndices.at(i);
|
||||
int index1 = part.quadIndices.at(i + 1);
|
||||
int index2 = part.quadIndices.at(i + 2);
|
||||
int index3 = part.quadIndices.at(i + 3);
|
||||
|
||||
edges.insert(QPair<int, int>(qMin(index0, index1), qMax(index0, index1)));
|
||||
edges.insert(QPair<int, int>(qMin(index1, index2), qMax(index1, index2)));
|
||||
edges.insert(QPair<int, int>(qMin(index2, index3), qMax(index2, index3)));
|
||||
edges.insert(QPair<int, int>(qMin(index3, index0), qMax(index3, index0)));
|
||||
|
||||
mesh.vertexConnections[index0].append(QPair<int, int>(index3, index1));
|
||||
mesh.vertexConnections[index1].append(QPair<int, int>(index0, index2));
|
||||
mesh.vertexConnections[index2].append(QPair<int, int>(index1, index3));
|
||||
mesh.vertexConnections[index3].append(QPair<int, int>(index2, index0));
|
||||
}
|
||||
for (int i = 0; i < part.triangleIndices.size(); i += 3) {
|
||||
int index0 = part.triangleIndices.at(i);
|
||||
int index1 = part.triangleIndices.at(i + 1);
|
||||
int index2 = part.triangleIndices.at(i + 2);
|
||||
|
||||
edges.insert(QPair<int, int>(qMin(index0, index1), qMax(index0, index1)));
|
||||
edges.insert(QPair<int, int>(qMin(index1, index2), qMax(index1, index2)));
|
||||
edges.insert(QPair<int, int>(qMin(index2, index0), qMax(index2, index0)));
|
||||
|
||||
mesh.vertexConnections[index0].append(QPair<int, int>(index2, index1));
|
||||
mesh.vertexConnections[index1].append(QPair<int, int>(index0, index2));
|
||||
mesh.vertexConnections[index2].append(QPair<int, int>(index1, index0));
|
||||
}
|
||||
}
|
||||
|
||||
for (QSet<QPair<int, int> >::const_iterator edge = edges.constBegin(); edge != edges.constEnd(); edge++) {
|
||||
|
|
|
@ -56,12 +56,27 @@ public:
|
|||
glm::mat4 inverseBindMatrix;
|
||||
};
|
||||
|
||||
/// A single mesh (with optional blendshapes) extracted from an FBX document.
|
||||
class FBXMesh {
|
||||
/// A single part of a mesh (with the same material).
|
||||
class FBXMeshPart {
|
||||
public:
|
||||
|
||||
QVector<int> quadIndices;
|
||||
QVector<int> triangleIndices;
|
||||
|
||||
glm::vec3 diffuseColor;
|
||||
glm::vec3 specularColor;
|
||||
float shininess;
|
||||
|
||||
QByteArray diffuseFilename;
|
||||
QByteArray normalFilename;
|
||||
};
|
||||
|
||||
/// A single mesh (with optional blendshapes) extracted from an FBX document.
|
||||
class FBXMesh {
|
||||
public:
|
||||
|
||||
QVector<FBXMeshPart> parts;
|
||||
|
||||
QVector<glm::vec3> vertices;
|
||||
QVector<glm::vec3> normals;
|
||||
QVector<glm::vec2> texCoords;
|
||||
|
@ -72,13 +87,6 @@ public:
|
|||
|
||||
bool isEye;
|
||||
|
||||
glm::vec3 diffuseColor;
|
||||
glm::vec3 specularColor;
|
||||
float shininess;
|
||||
|
||||
QByteArray diffuseFilename;
|
||||
QByteArray normalFilename;
|
||||
|
||||
QVector<FBXBlendshape> blendshapes;
|
||||
|
||||
float springiness;
|
||||
|
|
|
@ -290,19 +290,26 @@ NetworkGeometry::~NetworkGeometry() {
|
|||
|
||||
glm::vec4 NetworkGeometry::computeAverageColor() const {
|
||||
glm::vec4 totalColor;
|
||||
int totalVertices = 0;
|
||||
int totalTriangles = 0;
|
||||
for (int i = 0; i < _meshes.size(); i++) {
|
||||
if (_geometry.meshes.at(i).isEye) {
|
||||
const FBXMesh& mesh = _geometry.meshes.at(i);
|
||||
if (mesh.isEye) {
|
||||
continue; // skip eyes
|
||||
}
|
||||
glm::vec4 color = glm::vec4(_geometry.meshes.at(i).diffuseColor, 1.0f);
|
||||
if (_meshes.at(i).diffuseTexture) {
|
||||
color *= _meshes.at(i).diffuseTexture->getAverageColor();
|
||||
const NetworkMesh& networkMesh = _meshes.at(i);
|
||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
const NetworkMeshPart& networkPart = networkMesh.parts.at(j);
|
||||
glm::vec4 color = glm::vec4(part.diffuseColor, 1.0f);
|
||||
if (networkPart.diffuseTexture) {
|
||||
color *= networkPart.diffuseTexture->getAverageColor();
|
||||
}
|
||||
int triangles = part.quadIndices.size() * 2 + part.triangleIndices.size();
|
||||
totalColor += color * triangles;
|
||||
totalTriangles += triangles;
|
||||
}
|
||||
totalColor += color * _geometry.meshes.at(i).vertices.size();
|
||||
totalVertices += _geometry.meshes.at(i).vertices.size();
|
||||
}
|
||||
return (totalVertices == 0) ? glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) : totalColor / totalVertices;
|
||||
return (totalTriangles == 0) ? glm::vec4(1.0f, 1.0f, 1.0f, 1.0f) : totalColor / totalTriangles;
|
||||
}
|
||||
|
||||
void NetworkGeometry::handleModelReplyError() {
|
||||
|
@ -351,13 +358,36 @@ void NetworkGeometry::maybeReadModelWithMapping() {
|
|||
foreach (const FBXMesh& mesh, _geometry.meshes) {
|
||||
NetworkMesh networkMesh;
|
||||
|
||||
int totalIndices = 0;
|
||||
foreach (const FBXMeshPart& part, mesh.parts) {
|
||||
NetworkMeshPart networkPart;
|
||||
QString basePath = url.path();
|
||||
basePath = basePath.left(basePath.lastIndexOf('/') + 1);
|
||||
if (!part.diffuseFilename.isEmpty()) {
|
||||
url.setPath(basePath + part.diffuseFilename);
|
||||
networkPart.diffuseTexture = Application::getInstance()->getTextureCache()->getTexture(url, mesh.isEye);
|
||||
}
|
||||
if (!part.normalFilename.isEmpty()) {
|
||||
url.setPath(basePath + part.normalFilename);
|
||||
networkPart.normalTexture = Application::getInstance()->getTextureCache()->getTexture(url);
|
||||
}
|
||||
networkMesh.parts.append(networkPart);
|
||||
|
||||
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
|
||||
}
|
||||
|
||||
glGenBuffers(1, &networkMesh.indexBufferID);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, networkMesh.indexBufferID);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (mesh.quadIndices.size() + mesh.triangleIndices.size()) * sizeof(int),
|
||||
NULL, GL_STATIC_DRAW);
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh.quadIndices.size() * sizeof(int), mesh.quadIndices.constData());
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, mesh.quadIndices.size() * sizeof(int),
|
||||
mesh.triangleIndices.size() * sizeof(int), mesh.triangleIndices.constData());
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, totalIndices * sizeof(int), NULL, GL_STATIC_DRAW);
|
||||
int offset = 0;
|
||||
foreach (const FBXMeshPart& part, mesh.parts) {
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.quadIndices.size() * sizeof(int),
|
||||
part.quadIndices.constData());
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, part.triangleIndices.size() * sizeof(int),
|
||||
part.triangleIndices.constData());
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glGenBuffers(1, &networkMesh.vertexBufferID);
|
||||
|
@ -398,16 +428,6 @@ void NetworkGeometry::maybeReadModelWithMapping() {
|
|||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
QString basePath = url.path();
|
||||
basePath = basePath.left(basePath.lastIndexOf('/') + 1);
|
||||
if (!mesh.diffuseFilename.isEmpty()) {
|
||||
url.setPath(basePath + mesh.diffuseFilename);
|
||||
networkMesh.diffuseTexture = Application::getInstance()->getTextureCache()->getTexture(url, mesh.isEye);
|
||||
}
|
||||
if (!mesh.normalFilename.isEmpty()) {
|
||||
url.setPath(basePath + mesh.normalFilename);
|
||||
networkMesh.normalTexture = Application::getInstance()->getTextureCache()->getTexture(url);
|
||||
}
|
||||
_meshes.append(networkMesh);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,14 @@ private:
|
|||
QVector<NetworkMesh> _meshes;
|
||||
};
|
||||
|
||||
/// The state associated with a single mesh part.
|
||||
class NetworkMeshPart {
|
||||
public:
|
||||
|
||||
QSharedPointer<NetworkTexture> diffuseTexture;
|
||||
QSharedPointer<NetworkTexture> normalTexture;
|
||||
};
|
||||
|
||||
/// The state associated with a single mesh.
|
||||
class NetworkMesh {
|
||||
public:
|
||||
|
@ -87,8 +95,7 @@ public:
|
|||
GLuint indexBufferID;
|
||||
GLuint vertexBufferID;
|
||||
|
||||
QSharedPointer<NetworkTexture> diffuseTexture;
|
||||
QSharedPointer<NetworkTexture> normalTexture;
|
||||
QVector<NetworkMeshPart> parts;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__GeometryCache__) */
|
||||
|
|
|
@ -17,14 +17,22 @@
|
|||
#include "Application.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
TextureCache::TextureCache() : _permutationNormalTextureID(0),
|
||||
_primaryFramebufferObject(NULL), _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL) {
|
||||
TextureCache::TextureCache() :
|
||||
_permutationNormalTextureID(0),
|
||||
_whiteTextureID(0),
|
||||
_primaryFramebufferObject(NULL),
|
||||
_secondaryFramebufferObject(NULL),
|
||||
_tertiaryFramebufferObject(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() {
|
||||
if (_permutationNormalTextureID != 0) {
|
||||
glDeleteTextures(1, &_permutationNormalTextureID);
|
||||
}
|
||||
if (_whiteTextureID != 0) {
|
||||
glDeleteTextures(1, &_whiteTextureID);
|
||||
}
|
||||
foreach (GLuint id, _fileTextureIDs) {
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
@ -66,6 +74,20 @@ GLuint TextureCache::getPermutationNormalTextureID() {
|
|||
return _permutationNormalTextureID;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getWhiteTextureID() {
|
||||
if (_whiteTextureID == 0) {
|
||||
glGenTextures(1, &_whiteTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _whiteTextureID);
|
||||
|
||||
const char OPAQUE_WHITE[] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, OPAQUE_WHITE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
return _whiteTextureID;
|
||||
}
|
||||
|
||||
GLuint TextureCache::getFileTextureID(const QString& filename) {
|
||||
GLuint id = _fileTextureIDs.value(filename);
|
||||
if (id == 0) {
|
||||
|
|
|
@ -37,6 +37,9 @@ public:
|
|||
/// the second, a set of random unit vectors to be used as noise gradients.
|
||||
GLuint getPermutationNormalTextureID();
|
||||
|
||||
/// Returns the ID of an opaque white texture (useful for a default).
|
||||
GLuint getWhiteTextureID();
|
||||
|
||||
/// Returns the ID of a texture containing the contents of the specified file, loading it if necessary.
|
||||
GLuint getFileTextureID(const QString& filename);
|
||||
|
||||
|
@ -65,7 +68,8 @@ private:
|
|||
QOpenGLFramebufferObject* createFramebufferObject();
|
||||
|
||||
GLuint _permutationNormalTextureID;
|
||||
|
||||
GLuint _whiteTextureID;
|
||||
|
||||
QHash<QString, GLuint> _fileTextureIDs;
|
||||
|
||||
QHash<QUrl, QWeakPointer<NetworkTexture> > _networkTextures;
|
||||
|
|
Loading…
Reference in a new issue