#include "Geometry.h" #include "Triangle3.h" #include "glInterface.h" #include "RenderState.h" #ifdef _CRT_SET #define _CRTDBG_MAP_ALLOC #include #include // redefine new operator #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif using namespace std; namespace CHCDemoEngine { Geometry::Geometry(Vector3 *vertices, Vector3 *normals, Texcoord2 *texcoords, int numVertices, bool delData, Vector3 *tangents): mVertices(vertices), mNormals(normals), mTexCoords(texcoords), mTangents(tangents), mNumVertices(numVertices), mVboId(-1), mVboId2(-1), mIndices(NULL) { mHasTexture = (mTexCoords != NULL); mHasTangents = (mTangents != NULL); /* mIndices = new unsigned int[mNumVertices]; for (int i = 0; i < mNumVertices; ++ i) { mIndices[i] = i; }*/ // prepare vbos Prepare(); if (delData) { DEL_ARRAY_PTR(mVertices); DEL_ARRAY_PTR(mIndices); DEL_ARRAY_PTR(mNormals); DEL_ARRAY_PTR(mTexCoords); DEL_ARRAY_PTR(mTangents); } } Geometry::~Geometry() { DEL_ARRAY_PTR(mVertices); DEL_ARRAY_PTR(mNormals); DEL_ARRAY_PTR(mTexCoords); DEL_ARRAY_PTR(mTangents); DEL_ARRAY_PTR(mIndices); // delete vbos glDeleteBuffersARB(1, &mVboId); glDeleteBuffersARB(1, &mVboId2); } void Geometry::Prepare() { CalcBoundingBox(); int dataSize = mNumVertices * 6; if (mTexCoords) dataSize += mNumVertices * 2; if (mTangents) dataSize += mNumVertices * 3; float *data = new float[dataSize]; for (int i = 0; i < mNumVertices; ++ i) { ((Vector3 *)data)[i] = mVertices[i]; ((Vector3 *)data)[i + mNumVertices] = mNormals[i]; } float *currentPData = data + mNumVertices * 6; if (mTangents) { for (int i = 0; i < mNumVertices; ++ i) { Vector3 tangent = Normalize(mTangents[i]); Vector3 normal = Normalize(mNormals[i]); float dotProd = DotProd(tangent, normal); //tangent -= normal * dotProd; tangent = Normalize(tangent); //mTangents[i] = tangent; mTangents[i] = tangent * 0.5f + Vector3(0.5f); } for (int i = 0; i < mNumVertices; ++ i) { ((Vector3 *)data)[mNumVertices * 2 + i] = mTangents[i]; } currentPData += mNumVertices * 3; } if (mTexCoords) { for (int i = 0; i < mNumVertices; ++ i) { ((Texcoord2 *)currentPData)[i] = mTexCoords[i]; } } glGenBuffersARB(1, &mVboId); glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId); int currentPVbo = 0; glVertexPointer(3, GL_FLOAT, 0, (char *)NULL); currentPVbo += mNumVertices * sizeof(Vector3); glNormalPointer(GL_FLOAT, 0, (char *)NULL + currentPVbo); currentPVbo += mNumVertices * 2 * sizeof(Vector3); if (mTangents) { // hack: use color pointer to store tangents glColorPointer(3, GL_FLOAT, 0, (char *)NULL + currentPVbo); currentPVbo += mNumVertices * sizeof(Vector3); } if (mTexCoords) { glTexCoordPointer(2, GL_FLOAT, 0, (char *)NULL + currentPVbo); } glBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize * sizeof(float), data, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); /////////// //-- the index array if (mIndices) { glGenBuffersARB(1, &mVboId2); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mVboId2); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mNumVertices * sizeof(unsigned int), mIndices, GL_STATIC_DRAW_ARB); int bufferSize; glGetBufferParameterivARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &bufferSize); //cout << "Index Array in VBO: " << bufferSize << " bytes\n" << "id: " << mVboId2 << endl; glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } // data handled by graphics driver from now on delete [] data; } void Geometry::Render(RenderState *state) { if (mHasTangents) { glEnableClientState(GL_COLOR_ARRAY); } if (state->GetCurrentVboId() != mVboId) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId); int currentPointer; glNormalPointer(GL_FLOAT, 0, (char *)NULL + mNumVertices * sizeof(Vector3)); if (mHasTangents) { glColorPointer(3, GL_FLOAT, 0, (char *)NULL + mNumVertices * 2 * sizeof(Vector3)); currentPointer = mNumVertices * 3 * sizeof(Vector3); } else { currentPointer = mNumVertices * 2 * sizeof(Vector3); } if (mHasTexture) { glTexCoordPointer(2, GL_FLOAT, 0, (char *)NULL + currentPointer); } glVertexPointer(3, GL_FLOAT, 0, (char *)NULL); //glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mVboId2); /// update state state->SetCurrentVboId(mVboId); } glDrawArrays(GL_TRIANGLES, 0, mNumVertices); //glDrawElements(GL_TRIANGLES, mNumVertices, GL_UNSIGNED_INT, 0); if (mHasTangents) glDisableClientState(GL_COLOR_ARRAY); } void Geometry::CalcBoundingBox() { mBoundingBox.Initialize(); for (int i = 0; i < mNumVertices; ++ i) { mBoundingBox.Include(mVertices[i]); } } const AxisAlignedBox3& Geometry::GetBoundingBox() const { return mBoundingBox; } Vector3 *Geometry::GetVertices(int &numVertices) const { numVertices = mNumVertices; return mVertices; } Vector3 *Geometry::GetNormals(int &numNormals) const { numNormals = mNumVertices; return mNormals; } Vector3 *Geometry::GetTangents(int &numTangents) const { numTangents = mHasTangents ? mNumVertices : 0;; return mTangents; } Texcoord2 *Geometry::GetTexCoords(int &numTexCoords) const { numTexCoords = mHasTangents ? mNumVertices : 0;; return mTexCoords; } }