www.pudn.com > tomohide_fur.03.13.02.zip > FurMesh.cpp
//----------------------------------------------------------------------------- // File: FurMesh.cpp // // Copyright (C) 2001-2002 Tomohide Kano. All rights reserved. //----------------------------------------------------------------------------- #include#include #include "extensions.h" #include "FurMesh.h" struct FURVERTEX { D3DXVECTOR3 pos; D3DXVECTOR2 tex1; D3DXVECTOR2 tex2; D3DXVECTOR2 scale; D3DXVECTOR2 radius; D3DXVECTOR3 ds; D3DXVECTOR3 dt; D3DXVECTOR3 normal; }; const GLuint OFFSET_POS = 0 * sizeof(float); const GLuint OFFSET_TEX1 = 3 * sizeof(float); const GLuint OFFSET_TEX2 = 5 * sizeof(float); const GLuint OFFSET_SCALE = 7 * sizeof(float); const GLuint OFFSET_RADIUS = 9 * sizeof(float); const GLuint OFFSET_DS = 11 * sizeof(float); const GLuint OFFSET_DT = 14 * sizeof(float); const GLuint OFFSET_NORMAL = 17 * sizeof(float); const GLuint STRIDE = sizeof(FURVERTEX); // 80 bytes // partial derivatives of bivariate function const float DELTA = 0.01; inline D3DXVECTOR3 deriv_u(FurMesh::FUNC f, float u, float v) { return (f(u+DELTA, v) - f(u-DELTA, v)) / (2*DELTA); } inline D3DXVECTOR3 deriv_v(FurMesh::FUNC f, float u, float v) { return (f(u, v+DELTA) - f(u, v-DELTA)) / (2*DELTA); } inline D3DXVECTOR3 deriv_uu(FurMesh::FUNC f, float u, float v) { return (deriv_u(f, u+DELTA, v) - deriv_u(f, u-DELTA, v)) / (2*DELTA); } inline D3DXVECTOR3 deriv_vv(FurMesh::FUNC f, float u, float v) { return (deriv_v(f, u, v+DELTA) - deriv_v(f, u, v-DELTA)) / (2*DELTA); } inline D3DXVECTOR3 deriv_uv(FurMesh::FUNC f, float u, float v) { return (deriv_u(f, u, v+DELTA) - deriv_u(f, u, v-DELTA)) / (2*DELTA); } //----------------------------------------------------------------------------- // FurMesh //----------------------------------------------------------------------------- FurMesh::FurMesh() { m_Name = ""; m_NumVertex = 0; m_NumIndex = 0; m_VertexBuffer = 0; m_IndexBuffer = 0; } //----------------------------------------------------------------------------- // ~FurMesh //----------------------------------------------------------------------------- FurMesh::~FurMesh() { glFreeObjectBufferATI(m_VertexBuffer); glFreeObjectBufferATI(m_IndexBuffer); } //----------------------------------------------------------------------------- // Init //----------------------------------------------------------------------------- bool FurMesh::Init(const PARAM ¶m) { m_Name = param.name; int num_u = param.num_u; int num_v = param.num_v; FUNC func = param.func; float scale_s = param.fur_scale_s; float scale_t = param.fur_scale_t; m_NumVertex = (num_u + 1) * (num_v + 1); m_NumIndex = num_u * num_v * 6; // vertex buffer { int i, j; FURVERTEX *pVertices = new FURVERTEX[m_NumVertex]; FURVERTEX *p = pVertices; for (j = 0; j <= num_v; j++) for (i = 0; i <= num_u; i++) { float u = float(i) / num_u; float v = float(j) / num_v; // vertex position p->pos = func(u, v); // texture coord for normal map p->tex1 = D3DXVECTOR2(u, v); // texture coord for fur texture p->tex2 = D3DXVECTOR2(scale_s * u, scale_t * v); // partial derivatives with respect to (u, v) D3DXVECTOR3& Pu = deriv_u(func, u, v); D3DXVECTOR3& Pv = deriv_v(func, u, v); D3DXVECTOR3& Puu = deriv_uu(func, u, v); // D3DXVECTOR3& Puv = deriv_uv(func, u, v); D3DXVECTOR3& Pvv = deriv_vv(func, u, v); // basis vectors of local texture space D3DXVec3Normalize(&p->ds, &Pu); D3DXVec3Normalize(&p->dt, &Pv); D3DXVec3Normalize(&p->normal, D3DXVec3Cross(&p->normal, &Pu, &Pv)); // scale factor p->scale.x = scale_s / D3DXVec3Length(&Pu); p->scale.y = scale_t / D3DXVec3Length(&Pv); // radii of curvature { // first and second fundamental forms // http://mathworld.wolfram.com/FundamentalForms.html float E = D3DXVec3LengthSq(&Pu); // float F = D3DXVec3Dot(&Pu, &Pv); float G = D3DXVec3LengthSq(&Pv); float e = D3DXVec3Dot(&p->normal, &Puu); // float f = D3DXVec3Dot(&p->normal, &Puv); float g = D3DXVec3Dot(&p->normal, &Pvv); // normal curvatures in the directions of u and v // http://mathworld.wolfram.com/NormalCurvature.html float curvature_u = -e / E; float curvature_v = -g / G; // radii of curvature corresponding to the normal curvatures // http://mathworld.wolfram.com/RadiusofCurvature.html if (curvature_u < 0.001) curvature_u = 0.001; p->radius.x = 1.0 / curvature_u; if (curvature_v < 0.001) curvature_v = 0.001; p->radius.y = 1.0 / curvature_v; // to be accurate, principal curvatures should be taken into account... // http://mathworld.wolfram.com/PrincipalCurvatures.html } p++; } m_VertexBuffer = glNewObjectBufferATI(m_NumVertex * sizeof(FURVERTEX), pVertices, GL_STATIC_ATI); delete [] pVertices; } // index buffer (triangle list) { int i, j, k; GLuint *pIndices = new GLuint[m_NumIndex]; GLuint *p = pIndices; for (j = 0; j < num_v; j++) { k = j * (num_u + 1); for (i = 0; i < num_u; i++, k++) { *p++ = k; *p++ = k + 1; *p++ = k + (num_u + 1); *p++ = k + (num_u + 1) + 1; *p++ = k + (num_u + 1); *p++ = k + 1; } } m_IndexBuffer = glNewObjectBufferATI(m_NumIndex * sizeof(GLuint), pIndices, GL_STATIC_ATI); delete [] pIndices; } if (glGetError()) return false; return true; } //----------------------------------------------------------------------------- // Draw //----------------------------------------------------------------------------- void FurMesh::Draw() const { // element array glEnableClientState(GL_ELEMENT_ARRAY_ATI); glArrayObjectATI(GL_ELEMENT_ARRAY_ATI, 1, GL_UNSIGNED_INT, 0, m_IndexBuffer, 0); // vertex position glEnableClientState(GL_VERTEX_ARRAY); glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_POS); // texture coord for normal map glClientActiveTextureARB(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_TEX1); // texture coord for fur texture glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_TEX2); // scale factor glClientActiveTextureARB(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_SCALE); // radius of curvature glClientActiveTextureARB(GL_TEXTURE3_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_RADIUS); // tangent vector along s glClientActiveTextureARB(GL_TEXTURE4_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_DS); // tangent vector along t glClientActiveTextureARB(GL_TEXTURE5_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_DT); // normal vector glEnableClientState(GL_NORMAL_ARRAY); glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, STRIDE, m_VertexBuffer, OFFSET_NORMAL); // draw triangle list glDrawElementArrayATI(GL_TRIANGLES, m_NumIndex); // disable arrays glDisableClientState(GL_ELEMENT_ARRAY_ATI); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE1_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE2_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE3_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE4_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE5_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE0_ARB); }