#include "SceneCache.h"
namespace
{
const float ANGLE_TO_RADIAN = 3.1415926f / 180.f;
const GLfloat BLACK_COLOR[] = {0.0f, 0.0f, 0.0f, 1.0f};
const GLfloat GREEN_COLOR[] = {0.0f, 1.0f, 0.0f, 1.0f};
const GLfloat WHITE_COLOR[] = {1.0f, 1.0f, 1.0f, 1.0f};
const GLfloat WIREFRAME_COLOR[] = {0.5f, 0.5f, 0.5f, 1.0f};
const int TRIANGLE_VERTEX_COUNT = 3;
const int VERTEX_STRIDE = 4;
const int NORMAL_STRIDE = 3;
const int UV_STRIDE = 2;
const GLfloat DEFAULT_LIGHT_POSITION[] = {0.0f, 0.0f, 0.0f, 1.0f};
const GLfloat DEFAULT_DIRECTION_LIGHT_POSITION[] = {0.0f, 0.0f, 1.0f, 0.0f};
const GLfloat DEFAULT_SPOT_LIGHT_DIRECTION[] = {0.0f, 0.0f, -1.0f};
const GLfloat DEFAULT_LIGHT_COLOR[] = {1.0f, 1.0f, 1.0f, 1.0f};
const GLfloat DEFAULT_LIGHT_SPOT_CUTOFF = 180.0f;
const char * pPropertyName,
const char * pFactorPropertyName,
GLuint & pTextureName)
{
{
if (lFactor != 1)
{
lResult[0] *= lFactor;
lResult[1] *= lFactor;
lResult[2] *= lFactor;
}
}
{
if (lTextureCount)
{
{
}
}
}
return lResult;
}
}
VBOMesh::VBOMesh() : mHasNormal(false), mHasUV(false), mAllByControlPoint(true)
{
for (int lVBOIndex = 0; lVBOIndex < VBO_COUNT; ++lVBOIndex)
{
mVBONames[lVBOIndex] = 0;
}
}
VBOMesh::~VBOMesh()
{
glDeleteBuffers(VBO_COUNT, mVBONames);
for(int i=0; i < mSubMeshes.GetCount(); i++)
{
delete mSubMeshes[i];
}
mSubMeshes.Clear();
}
bool VBOMesh::Initialize(
const FbxMesh *pMesh)
{
return false;
{
{
FBX_ASSERT(lMaterialIndice->
GetCount() == lPolygonCount);
if (lMaterialIndice->
GetCount() == lPolygonCount)
{
for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
{
const int lMaterialIndex = lMaterialIndice->
GetAt(lPolygonIndex);
if (mSubMeshes.GetCount() < lMaterialIndex + 1)
{
mSubMeshes.Resize(lMaterialIndex + 1);
}
if (mSubMeshes[lMaterialIndex] ==
NULL)
{
mSubMeshes[lMaterialIndex] = new SubMesh;
}
mSubMeshes[lMaterialIndex]->TriangleCount += 1;
}
for (int i = 0; i < mSubMeshes.GetCount(); i++)
{
if (mSubMeshes[i] ==
NULL)
mSubMeshes[i] = new SubMesh;
}
const int lMaterialCount = mSubMeshes.GetCount();
int lOffset = 0;
for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
{
mSubMeshes[lIndex]->IndexOffset = lOffset;
lOffset += mSubMeshes[lIndex]->TriangleCount * 3;
mSubMeshes[lIndex]->TriangleCount = 0;
}
FBX_ASSERT(lOffset == lPolygonCount * 3);
}
}
}
if (mSubMeshes.GetCount() == 0)
{
mSubMeshes.Resize(1);
mSubMeshes[0] = new SubMesh();
}
if (mHasNormal)
{
{
mHasNormal = false;
}
{
mAllByControlPoint = false;
}
}
if (mHasUV)
{
{
mHasUV = false;
}
{
mAllByControlPoint = false;
}
}
if (!mAllByControlPoint)
{
lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
}
float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE];
unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT];
if (mHasNormal)
{
lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE];
}
const char * lUVName =
NULL;
{
lUVs = new float[lPolygonVertexCount * UV_STRIDE];
lUVName = lUVNames[0];
}
if (mAllByControlPoint)
{
if (mHasNormal)
{
}
if (mHasUV)
{
}
for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
{
lCurrentVertex = lControlPoints[lIndex];
lVertices[lIndex * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
lVertices[lIndex * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
lVertices[lIndex * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
lVertices[lIndex * VERTEX_STRIDE + 3] = 1;
if (mHasNormal)
{
int lNormalIndex = lIndex;
{
}
lCurrentNormal = lNormalElement->
GetDirectArray().GetAt(lNormalIndex);
lNormals[lIndex * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
lNormals[lIndex * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
lNormals[lIndex * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
}
if (mHasUV)
{
int lUVIndex = lIndex;
{
}
lUVs[lIndex * UV_STRIDE] = static_cast<float>(lCurrentUV[0]);
lUVs[lIndex * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]);
}
}
}
int lVertexCount = 0;
for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
{
int lMaterialIndex = 0;
{
lMaterialIndex = lMaterialIndice->
GetAt(lPolygonIndex);
}
const int lIndexOffset = mSubMeshes[lMaterialIndex]->IndexOffset +
mSubMeshes[lMaterialIndex]->TriangleCount * 3;
for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
{
const int lControlPointIndex = pMesh->
GetPolygonVertex(lPolygonIndex, lVerticeIndex);
if (mAllByControlPoint)
{
lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
}
else
{
lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);
lCurrentVertex = lControlPoints[lControlPointIndex];
lVertices[lVertexCount * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
lVertices[lVertexCount * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
lVertices[lVertexCount * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
lVertices[lVertexCount * VERTEX_STRIDE + 3] = 1;
if (mHasNormal)
{
lNormals[lVertexCount * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
lNormals[lVertexCount * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
lNormals[lVertexCount * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
}
if (mHasUV)
{
bool lUnmappedUV;
pMesh->
GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
lUVs[lVertexCount * UV_STRIDE] = static_cast<float>(lCurrentUV[0]);
lUVs[lVertexCount * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]);
}
}
++lVertexCount;
}
mSubMeshes[lMaterialIndex]->TriangleCount += 1;
}
glGenBuffers(VBO_COUNT, mVBONames);
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]);
glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * VERTEX_STRIDE * sizeof(float), lVertices, GL_STATIC_DRAW);
delete [] lVertices;
if (mHasNormal)
{
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[NORMAL_VBO]);
glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * NORMAL_STRIDE * sizeof(float), lNormals, GL_STATIC_DRAW);
delete [] lNormals;
}
if (mHasUV)
{
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[UV_VBO]);
glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * UV_STRIDE * sizeof(float), lUVs, GL_STATIC_DRAW);
delete [] lUVs;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBONames[INDEX_VBO]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, lPolygonCount * TRIANGLE_VERTEX_COUNT * sizeof(unsigned int), lIndices, GL_STATIC_DRAW);
delete [] lIndices;
return true;
}
void VBOMesh::UpdateVertexPosition(
const FbxMesh * pMesh,
const FbxVector4 * pVertices)
const {
float * lVertices =
NULL;
int lVertexCount = 0;
if (mAllByControlPoint)
{
lVertices = new float[lVertexCount * VERTEX_STRIDE];
for (int lIndex = 0; lIndex < lVertexCount; ++lIndex)
{
lVertices[lIndex * VERTEX_STRIDE] = static_cast<float>(pVertices[lIndex][0]);
lVertices[lIndex * VERTEX_STRIDE + 1] = static_cast<float>(pVertices[lIndex][1]);
lVertices[lIndex * VERTEX_STRIDE + 2] = static_cast<float>(pVertices[lIndex][2]);
lVertices[lIndex * VERTEX_STRIDE + 3] = 1;
}
}
else
{
lVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
lVertices = new float[lVertexCount * VERTEX_STRIDE];
lVertexCount = 0;
for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
{
for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
{
const int lControlPointIndex = pMesh->
GetPolygonVertex(lPolygonIndex, lVerticeIndex);
lVertices[lVertexCount * VERTEX_STRIDE] = static_cast<float>(pVertices[lControlPointIndex][0]);
lVertices[lVertexCount * VERTEX_STRIDE + 1] = static_cast<float>(pVertices[lControlPointIndex][1]);
lVertices[lVertexCount * VERTEX_STRIDE + 2] = static_cast<float>(pVertices[lControlPointIndex][2]);
lVertices[lVertexCount * VERTEX_STRIDE + 3] = 1;
++lVertexCount;
}
}
}
if (lVertices)
{
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]);
glBufferData(GL_ARRAY_BUFFER, lVertexCount * VERTEX_STRIDE * sizeof(float), lVertices, GL_STATIC_DRAW);
delete [] lVertices;
}
}
void VBOMesh::Draw(int pMaterialIndex, ShadingMode pShadingMode) const
{
#if _MSC_VER >= 1900 && defined(_WIN64)
#pragma warning( push )
#pragma warning( disable : 4312)
#endif
GLsizei lOffset = mSubMeshes[pMaterialIndex]->IndexOffset * sizeof(unsigned int);
if ( pShadingMode == SHADING_MODE_SHADED)
{
const GLsizei lElementCount = mSubMeshes[pMaterialIndex]->TriangleCount * 3;
glDrawElements(GL_TRIANGLES, lElementCount, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(lOffset));
}
else
{
for (int lIndex = 0; lIndex < mSubMeshes[pMaterialIndex]->TriangleCount; ++lIndex)
{
glDrawElements(GL_LINE_LOOP, TRIANGLE_VERTEX_COUNT, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(lOffset));
lOffset += sizeof(unsigned int) * TRIANGLE_VERTEX_COUNT;
}
}
#if _MSC_VER >= 1900 && defined(_WIN64)
#pragma warning( pop )
#endif
}
void VBOMesh::BeginDraw(ShadingMode pShadingMode) const
{
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glPushAttrib(GL_ENABLE_BIT);
glPushAttrib(GL_CURRENT_BIT);
glPushAttrib(GL_LIGHTING_BIT);
glPushAttrib(GL_TEXTURE_BIT);
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]);
glVertexPointer(VERTEX_STRIDE, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if (mHasNormal && pShadingMode == SHADING_MODE_SHADED)
{
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[NORMAL_VBO]);
glNormalPointer(GL_FLOAT, 0, 0);
glEnableClientState(GL_NORMAL_ARRAY);
}
if (mHasUV && pShadingMode == SHADING_MODE_SHADED)
{
glBindBuffer(GL_ARRAY_BUFFER, mVBONames[UV_VBO]);
glTexCoordPointer(UV_STRIDE, GL_FLOAT, 0, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBONames[INDEX_VBO]);
if (pShadingMode == SHADING_MODE_SHADED)
{
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_NORMALIZE);
}
else
{
glColor4fv(WIREFRAME_COLOR);
}
}
void VBOMesh::EndDraw() const
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glPopAttrib();
glPopAttrib();
glPopAttrib();
glPopAttrib();
glPopClientAttrib();
}
MaterialCache::MaterialCache() : mShinness(0)
{
}
MaterialCache::~MaterialCache()
{
}
{
const FbxDouble3 lEmissive = GetMaterialProperty(pMaterial,
mEmissive.mColor[0] = static_cast<GLfloat>(lEmissive[0]);
mEmissive.mColor[1] = static_cast<GLfloat>(lEmissive[1]);
mEmissive.mColor[2] = static_cast<GLfloat>(lEmissive[2]);
const FbxDouble3 lAmbient = GetMaterialProperty(pMaterial,
mAmbient.mColor[0] = static_cast<GLfloat>(lAmbient[0]);
mAmbient.mColor[1] = static_cast<GLfloat>(lAmbient[1]);
mAmbient.mColor[2] = static_cast<GLfloat>(lAmbient[2]);
const FbxDouble3 lDiffuse = GetMaterialProperty(pMaterial,
mDiffuse.mColor[0] = static_cast<GLfloat>(lDiffuse[0]);
mDiffuse.mColor[1] = static_cast<GLfloat>(lDiffuse[1]);
mDiffuse.mColor[2] = static_cast<GLfloat>(lDiffuse[2]);
const FbxDouble3 lSpecular = GetMaterialProperty(pMaterial,
mSpecular.mColor[0] = static_cast<GLfloat>(lSpecular[0]);
mSpecular.mColor[1] = static_cast<GLfloat>(lSpecular[1]);
mSpecular.mColor[2] = static_cast<GLfloat>(lSpecular[2]);
{
mShinness = static_cast<GLfloat>(lShininess);
}
return true;
}
void MaterialCache::SetCurrentMaterial() const
{
glMaterialfv(GL_FRONT, GL_EMISSION, mEmissive.mColor);
glMaterialfv(GL_FRONT, GL_AMBIENT, mAmbient.mColor);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mDiffuse.mColor);
glMaterialfv(GL_FRONT, GL_SPECULAR, mSpecular.mColor);
glMaterialf(GL_FRONT, GL_SHININESS, mShinness);
glBindTexture(GL_TEXTURE_2D, mDiffuse.mTextureName);
}
void MaterialCache::SetDefaultMaterial()
{
glMaterialfv(GL_FRONT, GL_EMISSION, BLACK_COLOR);
glMaterialfv(GL_FRONT, GL_AMBIENT, BLACK_COLOR);
glMaterialfv(GL_FRONT, GL_DIFFUSE, GREEN_COLOR);
glMaterialfv(GL_FRONT, GL_SPECULAR, BLACK_COLOR);
glMaterialf(GL_FRONT, GL_SHININESS, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
int LightCache::sLightCount = 0;
{
mLightIndex = GL_LIGHT0 + sLightCount++;
}
LightCache::~LightCache()
{
glDisable(mLightIndex);
--sLightCount;
}
{
mColorRed.mValue = static_cast<float>(lLightColor[0]);
mColorGreen.mValue = static_cast<float>(lLightColor[1]);
mColorBlue.mValue = static_cast<float>(lLightColor[2]);
if (pAnimLayer)
{
}
{
mConeAngle.mValue =
static_cast<GLfloat
>(lConeAngleProperty.
Get());
if (pAnimLayer)
mConeAngle.mAnimCurve = lConeAngleProperty.
GetCurve(pAnimLayer);
}
return true;
}
void LightCache::SetLight(
const FbxTime & pTime)
const {
const GLfloat lLightColor[4] = {mColorRed.Get(pTime), mColorGreen.Get(pTime), mColorBlue.Get(pTime), 1.0f};
const GLfloat lConeAngle = mConeAngle.Get(pTime);
glColor3fv(lLightColor);
glPushAttrib(GL_ENABLE_BIT);
glPushAttrib(GL_POLYGON_BIT);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
{
glPushMatrix();
glScalef(1.0f, 1.0f, -1.0f);
const double lRadians = ANGLE_TO_RADIAN * lConeAngle;
const double lHeight = 15.0;
const double lBase = lHeight * tan(lRadians / 2);
GLUquadricObj * lQuadObj = gluNewQuadric();
gluCylinder(lQuadObj, 0.0, lBase, lHeight, 18, 1);
gluDeleteQuadric(lQuadObj);
glPopMatrix();
}
else
{
GLUquadricObj * lQuadObj = gluNewQuadric();
gluSphere(lQuadObj, 1.0, 10, 10);
gluDeleteQuadric(lQuadObj);
}
glPopAttrib();
glPopAttrib();
{
glLightfv(mLightIndex, GL_POSITION, DEFAULT_DIRECTION_LIGHT_POSITION);
}
else
{
glLightfv(mLightIndex, GL_POSITION, DEFAULT_LIGHT_POSITION);
}
glLightfv(mLightIndex, GL_DIFFUSE, lLightColor);
glLightfv(mLightIndex, GL_SPECULAR, lLightColor);
{
glLightfv(mLightIndex, GL_SPOT_DIRECTION, DEFAULT_SPOT_LIGHT_DIRECTION);
if (lConeAngle != 0.0f)
{
glLightf(mLightIndex, GL_SPOT_CUTOFF, lConeAngle/2);
}
}
glEnable(mLightIndex);
}
void LightCache::IntializeEnvironment(
const FbxColor & pAmbientLight)
{
glLightfv(GL_LIGHT0, GL_POSITION, DEFAULT_DIRECTION_LIGHT_POSITION);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DEFAULT_LIGHT_COLOR);
glLightfv(GL_LIGHT0, GL_SPECULAR, DEFAULT_LIGHT_COLOR);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, DEFAULT_LIGHT_SPOT_CUTOFF);
glEnable(GL_LIGHT0);
GLfloat lAmbientLight[] = {static_cast<GLfloat>(pAmbientLight[0]), static_cast<GLfloat>(pAmbientLight[1]),
static_cast<GLfloat>(pAmbientLight[2]), 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lAmbientLight);
}