diff options
author | Mitchell Stokes <mogurijin@gmail.com> | 2012-12-19 00:56:25 +0400 |
---|---|---|
committer | Mitchell Stokes <mogurijin@gmail.com> | 2012-12-19 00:56:25 +0400 |
commit | ef0473994b6b21aa49bbfab26a483d90d0fef004 (patch) | |
tree | 18d9dd7d2fbe6eddaf58f66b6b301c694cb43a50 /source/gameengine/Rasterizer | |
parent | 6b2af22d37dc1a039104f2ca0b3b4b56aca7d41c (diff) |
BGE: Some as of yet unmerged work I did in the Swiss branch. These changes include:
* Cleaning up the conversion code to avoid a per-face material conversion. Materials are now stored in buckets and only converted if a new material is found. This replaces some of Campbell's earlier work on the subject. His work wasn't as thorough, but it was much safer for a release.
* Shaders are only compiled for LibLoaded materials once. Before they could be compiled twice, which could really slow things down.
* Refactoring the rasterizer code to use a strategy design pattern to handle different geometry rendering methods such as immediate mode, vertex arrays and vertex buffer objects. VBOs are added, but they will be disabled in a following commit since they are still slower than vertex arrays with display lists. However, VBOs are still useful for mobile, so it's good to keep them around.
* Better multi-uv support. The BGE should now be able to handle more than two UV layers, which should help it better match the viewport.
Diffstat (limited to 'source/gameengine/Rasterizer')
22 files changed, 1281 insertions, 760 deletions
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index f24e3397801..2b5b0aeac2a 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -232,6 +232,24 @@ void RAS_BucketManager::Renderbuckets( RenderSolidBuckets(cameratrans, rasty, rendertools); RenderAlphaBuckets(cameratrans, rasty, rendertools); + /* All meshes should be up to date now */ + /* Don't do this while processing buckets because some meshes are split between buckets */ + BucketList::iterator bit; + list<RAS_MeshSlot>::iterator mit; + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + RAS_MaterialBucket* bucket = *bit; + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + mit->m_mesh->SetMeshModified(false); + } + } + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + RAS_MaterialBucket* bucket = *bit; + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + mit->m_mesh->SetMeshModified(false); + } + } + + rendertools->SetClientObject(rasty, NULL); } diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 9fffc8bebc9..b267879611e 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -184,7 +184,7 @@ public: /* * PreCalculate texture gen */ - virtual void OnConstruction(int layer) {} + virtual void OnConstruction() {} #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index e6948025999..5a720857d50 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -52,6 +52,7 @@ using namespace std; class RAS_ICanvas; class RAS_IPolyMaterial; +class RAS_MeshSlot; typedef vector<unsigned short> KX_IndexArray; typedef vector<RAS_TexVert> KX_VertexArray; @@ -129,7 +130,7 @@ public: RAS_TEXCO_GEN, //< GPU will generate texture coordinates RAS_TEXCO_ORCO, //< Vertex coordinates (object space) RAS_TEXCO_GLOB, //< Vertex coordinates (world space) - RAS_TEXCO_UV1, //< UV coordinates + RAS_TEXCO_UV, //< UV coordinates RAS_TEXCO_OBJECT, //< Use another object's position as coordinates RAS_TEXCO_LAVECTOR, //< Light vector as coordinates RAS_TEXCO_VIEW, //< View vector as coordinates @@ -137,7 +138,6 @@ public: RAS_TEXCO_WINDOW, //< Window coordinates RAS_TEXCO_NORM, //< Normal coordinates RAS_TEXTANGENT, //< - RAS_TEXCO_UV2, //< RAS_TEXCO_VCOL, //< Vertex Color RAS_TEXCO_DISABLE //< Disable this texture unit (cached) }; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 9fb47117f1d..54fe19a291f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -605,7 +605,8 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa if (ms.m_pDeformer) { - ms.m_pDeformer->Apply(m_material); + if (ms.m_pDeformer->Apply(m_material)); + ms.m_mesh->SetMeshModified(true); // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) } @@ -648,10 +649,6 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa else rasty->IndexPrimitives(ms); - if (rasty->QueryLists()) - if (ms.m_DisplayList) - ms.m_mesh->SetMeshModified(false); - rendertools->PopMatrix(); } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 2ccb9453b3d..49b74895302 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -324,15 +324,14 @@ void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[RAS_TexVert::MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, bool flat, int origindex) { - RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex); + RAS_TexVert texvert(xyz, uvs, tangent, rgba, normal, flat, origindex); RAS_MeshMaterial *mmat; RAS_DisplayArray *darray; RAS_MeshSlot *slot; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 281eae8734a..d77d0483024 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -116,8 +116,7 @@ public: virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts); virtual void AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[RAS_TexVert::MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgbacolor, const MT_Vector3& normal, diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index 189c4f78f77..11cb4b1d9f9 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -46,12 +46,17 @@ set(SRC RAS_GLExtensionManager.cpp RAS_ListRasterizer.cpp RAS_OpenGLRasterizer.cpp - RAS_VAOpenGLRasterizer.cpp + RAS_StorageIM.cpp + RAS_StorageVA.cpp + RAS_StorageVBO.cpp RAS_GLExtensionManager.h + RAS_IStorage.h RAS_ListRasterizer.h RAS_OpenGLRasterizer.h - RAS_VAOpenGLRasterizer.h + RAS_StorageIM.h + RAS_StorageVA.h + RAS_StorageVBO.h ) add_definitions(-DGLEW_STATIC) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h new file mode 100644 index 00000000000..f5c16bc8cd8 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_IStorage.h @@ -0,0 +1,62 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_STORAGE +#define __KX_STORAGE + +#include "RAS_MaterialBucket.h" + +enum RAS_STORAGE_TYPE { + RAS_AUTO_STORAGE, + RAS_IMMEDIATE, + RAS_VA, + RAS_VBO +}; + +class RAS_IStorage +{ + +public: + virtual ~RAS_IStorage() {}; + + virtual bool Init()=0; + virtual void Exit()=0; + + virtual void IndexPrimitives(RAS_MeshSlot& ms)=0; + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0; + + virtual void SetDrawingMode(int drawingmode)=0; + + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_IStorage"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_STORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index d74aa134779..3a60643e9e7 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -106,9 +106,8 @@ bool RAS_ListSlot::End() -RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock) -: RAS_VAOpenGLRasterizer(canvas, lock), - mUseVertexArrays(useVertexArrays), +RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock, int storage) +: RAS_OpenGLRasterizer(canvas, storage), mATI(false) { if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc.")) @@ -238,11 +237,8 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) return; } } - // derived mesh cannot use vertex array - if (mUseVertexArrays && !ms.m_pDerivedMesh) - RAS_VAOpenGLRasterizer::IndexPrimitives(ms); - else - RAS_OpenGLRasterizer::IndexPrimitives(ms); + + RAS_OpenGLRasterizer::IndexPrimitives(ms); if (ms.m_bDisplayList) { localSlot->EndList(); @@ -267,13 +263,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) } } - // workaround: note how we do not use vertex arrays for making display - // lists, since glVertexAttribPointerARB doesn't seem to work correct - // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh) - RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); - else - RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); + RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); if (ms.m_bDisplayList) { localSlot->EndList(); @@ -283,29 +273,17 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) bool RAS_ListRasterizer::Init(void) { - if (mUseVertexArrays) { - return RAS_VAOpenGLRasterizer::Init(); - } else { - return RAS_OpenGLRasterizer::Init(); - } + return RAS_OpenGLRasterizer::Init(); } void RAS_ListRasterizer::SetDrawingMode(int drawingmode) { - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::SetDrawingMode(drawingmode); - } else { - RAS_OpenGLRasterizer::SetDrawingMode(drawingmode); - } + RAS_OpenGLRasterizer::SetDrawingMode(drawingmode); } void RAS_ListRasterizer::Exit() { - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::Exit(); - } else { - RAS_OpenGLRasterizer::Exit(); - } + RAS_OpenGLRasterizer::Exit(); } // eof diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index a8eb2d5ffdf..0eddde7c203 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -7,7 +7,7 @@ #define __RAS_LISTRASTERIZER_H__ #include "RAS_MaterialBucket.h" -#include "RAS_VAOpenGLRasterizer.h" +#include "RAS_OpenGLRasterizer.h" #include <vector> #include <map> @@ -49,7 +49,7 @@ typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_ArrayLists; typedef std::vector<RAS_ListSlot*> RAS_ListSlots; // indexed by material slot number typedef std::map<DerivedMesh*, RAS_ListSlots*> RAS_DerivedMeshLists; -class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer +class RAS_ListRasterizer : public RAS_OpenGLRasterizer { bool mUseVertexArrays; bool mATI; @@ -61,7 +61,7 @@ class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer public: void RemoveListSlot(RAS_ListSlot* list); - RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); + RAS_ListRasterizer(RAS_ICanvas* canvas, bool lock=false, int storage=RAS_AUTO_STORAGE); virtual ~RAS_ListRasterizer(); virtual void IndexPrimitives(class RAS_MeshSlot& ms); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 22a700c7d2b..1328a5521b4 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -43,6 +43,10 @@ #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text +#include "RAS_StorageIM.h" +#include "RAS_StorageVA.h" +#include "RAS_StorageVBO.h" + #include "GPU_draw.h" #include "GPU_material.h" #include "GPU_extensions.h" @@ -74,7 +78,7 @@ static GLuint right_eye_vinterlace_mask[32]; */ static GLuint hinterlace_mask[33]; -RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) +RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) :RAS_IRasterizer(canvas), m_2DCanvas(canvas), m_fogenabled(false), @@ -93,7 +97,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_attrib_num(0), //m_last_alphablend(GPU_BLEND_SOLID), m_last_frontface(true), - m_materialCachingInfo(0) + m_materialCachingInfo(0), + m_storage_type(storage) { m_viewmatrix.setIdentity(); m_viewinvmatrix.setIdentity(); @@ -107,6 +112,24 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) hinterlace_mask[32] = 0; m_prevafvalue = GPU_get_anisotropic(); + + if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE && GLEW_ARB_vertex_buffer_object*/) + { + m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_VBO; + } + else if (m_storage_type == RAS_VA || m_storage_type == RAS_AUTO_STORAGE && GLEW_VERSION_1_1) + { + m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_VA; + } + else + { + m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m_attrib_num, m_attrib); + m_storage_type = RAS_IMMEDIATE; + } } @@ -115,10 +138,16 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { // Restore the previous AF value GPU_set_anisotropic(m_prevafvalue); + if (m_failsafe_storage && m_failsafe_storage != m_storage) + delete m_failsafe_storage; + + if (m_storage) + delete m_storage; } bool RAS_OpenGLRasterizer::Init() { + bool storage_init; GPU_state_init(); @@ -146,7 +175,9 @@ bool RAS_OpenGLRasterizer::Init() glShadeModel(GL_SMOOTH); - return true; + storage_init = m_storage->Init(); + + return true && storage_init; } @@ -267,6 +298,8 @@ bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) void RAS_OpenGLRasterizer::Exit() { + m_storage->Exit(); + glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClearDepth(1.0); @@ -289,7 +322,7 @@ void RAS_OpenGLRasterizer::Exit() bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; - m_drawingmode = drawingmode; + SetDrawingMode(drawingmode); // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -328,6 +361,8 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) if (m_drawingmode == KX_WIREFRAME) glDisable(GL_CULL_FACE); + + m_storage->SetDrawingMode(drawingmode); } int RAS_OpenGLRasterizer::GetDrawingMode() @@ -666,7 +701,7 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, glattrib = -1; if (GLEW_ARB_vertex_program) for (unit=0; unit<m_attrib_num; unit++) - if (m_attrib[unit] == RAS_TEXCO_UV1) + if (m_attrib[unit] == RAS_TEXCO_UV) glattrib = unit; rendertools->RenderText(polymat->GetDrawingMode(), polymat, @@ -708,257 +743,20 @@ void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit) m_attrib[unit] = coords; } -void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) -{ - int unit; - - if (GLEW_ARB_multitexture) { - for (unit=0; unit<m_texco_num; unit++) { - if (tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) { - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); - continue; - } - switch (m_texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ()); - break; - case RAS_TEXCO_UV1: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1()); - break; - case RAS_TEXCO_NORM: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal()); - break; - case RAS_TEXTANGENT: - glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent()); - break; - case RAS_TEXCO_UV2: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); - break; - default: - break; - } - } - } - - if (GLEW_ARB_vertex_program) { - for (unit=0; unit<m_attrib_num; unit++) { - switch (m_attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glVertexAttrib3fvARB(unit, tv.getXYZ()); - break; - case RAS_TEXCO_UV1: - glVertexAttrib2fvARB(unit, tv.getUV1()); - break; - case RAS_TEXCO_NORM: - glVertexAttrib3fvARB(unit, tv.getNormal()); - break; - case RAS_TEXTANGENT: - glVertexAttrib4fvARB(unit, tv.getTangent()); - break; - case RAS_TEXCO_UV2: - glVertexAttrib2fvARB(unit, tv.getUV2()); - break; - case RAS_TEXCO_VCOL: - glVertexAttrib4ubvARB(unit, tv.getRGBA()); - break; - default: - break; - } - } - } - -} - void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { - IndexPrimitivesInternal(ms, false); + if (ms.m_pDerivedMesh) + m_failsafe_storage->IndexPrimitives(ms); + else + m_storage->IndexPrimitives(ms); } void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) { - IndexPrimitivesInternal(ms, true); -} - -static bool current_wireframe; -static RAS_MaterialBucket *current_bucket; -static RAS_IPolyMaterial *current_polymat; -static RAS_MeshSlot *current_ms; -static RAS_MeshObject *current_mesh; -static int current_blmat_nr; -static GPUVertexAttribs current_gpu_attribs; -static Image *current_image; -static int CheckMaterialDM(int matnr, void *attribs) -{ - // only draw the current material - if (matnr != current_blmat_nr) - return 0; - GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; - if (gattribs) - memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); - return 1; -} - -/* -static int CheckTexfaceDM(void *mcol, int index) -{ - - // index is the original face index, retrieve the polygon - RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? - current_mesh->GetPolygon(index) : NULL; - if (polygon && polygon->GetMaterial() == current_bucket) { - // must handle color. - if (current_wireframe) - return 2; - if (current_ms->m_bObjectColor) { - MT_Vector4& rgba = current_ms->m_RGBAcolor; - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - // don't use mcol - return 2; - } - if (!mcol) { - // we have to set the color from the material - unsigned char rgba[4]; - current_polymat->GetMaterialRGBAColor(rgba); - glColor4ubv((const GLubyte *)rgba); - return 2; - } - return 1; - } - return 0; -} -*/ - -static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr) -{ - - // index is the original face index, retrieve the polygon - if (matnr == current_blmat_nr && - (tface == NULL || tface->tpage == current_image)) { - // must handle color. - if (current_wireframe) - return DM_DRAW_OPTION_NO_MCOL; - if (current_ms->m_bObjectColor) { - MT_Vector4& rgba = current_ms->m_RGBAcolor; - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - // don't use mcol - return DM_DRAW_OPTION_NO_MCOL; - } - if (!has_mcol) { - // we have to set the color from the material - unsigned char rgba[4]; - current_polymat->GetMaterialRGBAColor(rgba); - glColor4ubv((const GLubyte *)rgba); - return DM_DRAW_OPTION_NO_MCOL; - } - return DM_DRAW_OPTION_NORMAL; - } - return DM_DRAW_OPTION_SKIP; -} - -void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) -{ - bool obcolor = ms.m_bObjectColor; - bool wireframe = m_drawingmode <= KX_WIREFRAME; - MT_Vector4& rgba = ms.m_RGBAcolor; - RAS_MeshSlot::iterator it; - - if (ms.m_pDerivedMesh) { - // mesh data is in derived mesh, - current_bucket = ms.m_bucket; - current_polymat = current_bucket->GetPolyMaterial(); - current_ms = &ms; - current_mesh = ms.m_mesh; - current_wireframe = wireframe; - // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ - - // handle two-side - if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL) - this->SetCullFace(true); - else - this->SetCullFace(false); - - if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { - // GetMaterialIndex return the original mface material index, - // increment by 1 to match what derived mesh is doing - current_blmat_nr = current_polymat->GetMaterialIndex()+1; - // For GLSL we need to retrieve the GPU material attribute - Material* blmat = current_polymat->GetBlenderMaterial(); - Scene* blscene = current_polymat->GetBlenderScene(); - if (!wireframe && blscene && blmat) - GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); - else - memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); - // DM draw can mess up blending mode, restore at the end - int current_blend_mode = GPU_get_material_alpha_blend(); - ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); - GPU_set_material_alpha_blend(current_blend_mode); - } - else { - //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); - current_blmat_nr = current_polymat->GetMaterialIndex(); - current_image = current_polymat->GetBlenderImage(); - ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL); - } - return; - } - // iterate over display arrays, each containing an index + vertex array - for (ms.begin(it); !ms.end(it); ms.next(it)) { - RAS_TexVert *vertex; - size_t i, j, numvert; - - numvert = it.array->m_type; - - if (it.array->m_type == RAS_DisplayArray::LINE) { - // line drawing - glBegin(GL_LINES); - - for (i=0; i<it.totindex; i+=2) - { - vertex = &it.vertex[it.index[i]]; - glVertex3fv(vertex->getXYZ()); - - vertex = &it.vertex[it.index[i+1]]; - glVertex3fv(vertex->getXYZ()); - } - - glEnd(); - } - else { - // triangle and quad drawing - if (it.array->m_type == RAS_DisplayArray::TRIANGLE) - glBegin(GL_TRIANGLES); - else - glBegin(GL_QUADS); - - for (i=0; i<it.totindex; i+=numvert) - { - if (obcolor) - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - - for (j=0; j<numvert; j++) { - vertex = &it.vertex[it.index[i+j]]; - - if (!wireframe) { - if (!obcolor) - glColor4ubv((const GLubyte *)(vertex->getRGBA())); - - glNormal3fv(vertex->getNormal()); - - if (multi) - TexCoord(*vertex); - else - glTexCoord2fv(vertex->getUV1()); - } - - glVertex3fv(vertex->getXYZ()); - } - } - - glEnd(); - } - } + if (ms.m_pDerivedMesh) + m_failsafe_storage->IndexPrimitivesMulti(ms); + else + m_storage->IndexPrimitivesMulti(ms); } void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 88bb0be531b..c156ee53ed3 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -41,6 +41,7 @@ using namespace std; #include "RAS_IRasterizer.h" +#include "RAS_IStorage.h" #include "RAS_MaterialBucket.h" #include "RAS_ICanvas.h" @@ -83,7 +84,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_ambr; float m_ambg; float m_ambb; - double m_time; MT_Matrix4x4 m_viewmatrix; MT_Matrix4x4 m_viewinvmatrix; @@ -115,9 +115,15 @@ protected: /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; + /** Making use of a Strategy desing pattern for storage behavior. + Examples of concrete strategies: Vertex Arrays, VBOs, Immediate Mode*/ + int m_storage_type; + RAS_IStorage* m_storage; + RAS_IStorage* m_failsafe_storage; //So derived mesh can use immediate mode + public: double GetTime(); - RAS_OpenGLRasterizer(RAS_ICanvas* canv); + RAS_OpenGLRasterizer(RAS_ICanvas* canv, int storage=RAS_AUTO_STORAGE); virtual ~RAS_OpenGLRasterizer(); /*enum DrawType @@ -166,8 +172,6 @@ public: class RAS_IPolyMaterial* polymat, class RAS_IRenderTools* rendertools); - void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); - virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat); virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); virtual void SetViewMatrix( diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp new file mode 100644 index 00000000000..7b38b3b42f3 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp @@ -0,0 +1,310 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "RAS_StorageIM.h" + +#include "GL/glew.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "DNA_meshdata_types.h" + +extern "C"{ + #include "BLI_utildefines.h" + #include "BKE_DerivedMesh.h" +} + +RAS_StorageIM::RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib) : + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib) +{ +} +RAS_StorageIM::~RAS_StorageIM() +{ +} + +bool RAS_StorageIM::Init() +{ + return true; +} +void RAS_StorageIM::Exit() +{ +} + +void RAS_StorageIM::IndexPrimitives(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, false); +} + +void RAS_StorageIM::IndexPrimitivesMulti(class RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, true); +} + +void RAS_StorageIM::TexCoord(const RAS_TexVert &tv) +{ + int unit; + + if (GLEW_ARB_multitexture) { + for (unit = 0; unit < *m_texco_num; unit++) { + switch(m_texco[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, tv.getUV(unit)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, tv.getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, tv.getTangent()); + break; + default: + break; + } + } + } + + if (GLEW_ARB_vertex_program) { + int uv = 0; + for (unit = 0; unit < *m_attrib_num; unit++) { + switch(m_attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttrib3fvARB(unit, tv.getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttrib2fvARB(unit, tv.getUV(uv++)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttrib3fvARB(unit, tv.getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttrib4fvARB(unit, tv.getTangent()); + break; + case RAS_IRasterizer::RAS_TEXCO_VCOL: + glVertexAttrib4ubvARB(unit, tv.getRGBA()); + break; + default: + break; + } + } + } + +} + +void RAS_StorageIM::SetCullFace(bool enable) +{ + if (enable) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); +} + +static bool current_wireframe; +static RAS_MaterialBucket *current_bucket; +static RAS_IPolyMaterial *current_polymat; +static RAS_MeshSlot *current_ms; +static RAS_MeshObject *current_mesh; +static int current_blmat_nr; +static GPUVertexAttribs current_gpu_attribs; +static Image *current_image; +static int CheckMaterialDM(int matnr, void *attribs) +{ + // only draw the current material + if (matnr != current_blmat_nr) + return 0; + GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; + if (gattribs) + memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); + return 1; +} + +/* +static int CheckTexfaceDM(void *mcol, int index) +{ + + // index is the original face index, retrieve the polygon + RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? + current_mesh->GetPolygon(index) : NULL; + if (polygon && polygon->GetMaterial() == current_bucket) { + // must handle color. + if (current_wireframe) + return 2; + if (current_ms->m_bObjectColor) { + MT_Vector4& rgba = current_ms->m_RGBAcolor; + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + // don't use mcol + return 2; + } + if (!mcol) { + // we have to set the color from the material + unsigned char rgba[4]; + current_polymat->GetMaterialRGBAColor(rgba); + glColor4ubv((const GLubyte *)rgba); + return 2; + } + return 1; + } + return 0; +} +*/ + +static DMDrawOption CheckTexDM(MTFace *tface, int has_mcol, int matnr) +{ + + // index is the original face index, retrieve the polygon + if (matnr == current_blmat_nr && + (tface == NULL || tface->tpage == current_image)) { + // must handle color. + if (current_wireframe) + return DM_DRAW_OPTION_NO_MCOL; + if (current_ms->m_bObjectColor) { + MT_Vector4& rgba = current_ms->m_RGBAcolor; + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + // don't use mcol + return DM_DRAW_OPTION_NO_MCOL; + } + if (!has_mcol) { + // we have to set the color from the material + unsigned char rgba[4]; + current_polymat->GetMaterialRGBAColor(rgba); + glColor4ubv((const GLubyte *)rgba); + return DM_DRAW_OPTION_NO_MCOL; + } + return DM_DRAW_OPTION_NORMAL; + } + return DM_DRAW_OPTION_SKIP; +} + +void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) +{ + bool obcolor = ms.m_bObjectColor; + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME; + MT_Vector4& rgba = ms.m_RGBAcolor; + RAS_MeshSlot::iterator it; + + if (ms.m_pDerivedMesh) { + // mesh data is in derived mesh, + current_bucket = ms.m_bucket; + current_polymat = current_bucket->GetPolyMaterial(); + current_ms = &ms; + current_mesh = ms.m_mesh; + current_wireframe = wireframe; + // MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */ + + // handle two-side + if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL) + this->SetCullFace(true); + else + this->SetCullFace(false); + + if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { + // GetMaterialIndex return the original mface material index, + // increment by 1 to match what derived mesh is doing + current_blmat_nr = current_polymat->GetMaterialIndex()+1; + // For GLSL we need to retrieve the GPU material attribute + Material* blmat = current_polymat->GetBlenderMaterial(); + Scene* blscene = current_polymat->GetBlenderScene(); + if (!wireframe && blscene && blmat) + GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); + else + memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); + // DM draw can mess up blending mode, restore at the end + int current_blend_mode = GPU_get_material_alpha_blend(); + ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); + GPU_set_material_alpha_blend(current_blend_mode); + } else { + //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); + current_blmat_nr = current_polymat->GetMaterialIndex(); + current_image = current_polymat->GetBlenderImage(); + ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL); + } + return; + } + // iterate over display arrays, each containing an index + vertex array + for (ms.begin(it); !ms.end(it); ms.next(it)) { + RAS_TexVert *vertex; + size_t i, j, numvert; + + numvert = it.array->m_type; + + if (it.array->m_type == RAS_DisplayArray::LINE) { + // line drawing + glBegin(GL_LINES); + + for (i = 0; i < it.totindex; i += 2) + { + vertex = &it.vertex[it.index[i]]; + glVertex3fv(vertex->getXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); + } + + glEnd(); + } + else { + // triangle and quad drawing + if (it.array->m_type == RAS_DisplayArray::TRIANGLE) + glBegin(GL_TRIANGLES); + else + glBegin(GL_QUADS); + + for (i = 0; i < it.totindex; i += numvert) + { + if (obcolor) + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + + for (j = 0; j < numvert; j++) { + vertex = &it.vertex[it.index[i+j]]; + + if (!wireframe) { + if (!obcolor) + glColor4ubv((const GLubyte *)(vertex->getRGBA())); + + glNormal3fv(vertex->getNormal()); + + if (multi) + TexCoord(*vertex); + else + glTexCoord2fv(vertex->getUV(0)); + } + + glVertex3fv(vertex->getXYZ()); + } + } + + glEnd(); + } + } +} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h new file mode 100644 index 00000000000..de4ff30d394 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.h @@ -0,0 +1,68 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_IMMEDIATEMODESTORAGE +#define __KX_IMMEDIATEMODESTORAGE + +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" + +class RAS_StorageIM : public RAS_IStorage +{ +public: + RAS_StorageIM(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageIM(); + + virtual bool Init(); + virtual void Exit(); + + virtual void IndexPrimitives(RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); + + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + int* m_texco_num; + int* m_attrib_num; + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + void TexCoord(const RAS_TexVert &tv); + void SetCullFace(bool enable); + + void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); + + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageIM"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_IMMEDIATEMODESTORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp new file mode 100644 index 00000000000..e0d580eff11 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp @@ -0,0 +1,320 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "RAS_StorageVA.h" + +#include "GL/glew.h" + +RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib) : + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib), + m_last_texco_num(0), + m_last_attrib_num(0) +{ +} + +RAS_StorageVA::~RAS_StorageVA() +{ +} + +bool RAS_StorageVA::Init() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + return true; +} + +void RAS_StorageVA::Exit() +{ +} + +void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot& ms) +{ + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME; + RAS_MeshSlot::iterator it; + GLenum drawmode; + + if (!wireframe) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + // use glDrawElements to draw each vertexarray + for (ms.begin(it); !ms.end(it); ms.next(it)) { + if (it.totindex == 0) + continue; + + // drawing mode + if (it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if (it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; + + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; + + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + } + } + else + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + if (!wireframe) { + glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV(0)); + if (glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); + } + + // here the actual drawing takes places + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + if (!wireframe) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } +} + +void RAS_StorageVA::IndexPrimitivesMulti(class RAS_MeshSlot& ms) +{ + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME, use_color_array; + RAS_MeshSlot::iterator it; + GLenum drawmode; + + if (!wireframe) + EnableTextures(true); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + // use glDrawElements to draw each vertexarray + for (ms.begin(it); !ms.end(it); ms.next(it)) { + if (it.totindex == 0) + continue; + + // drawing mode + if (it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if (it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; + + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; + + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + use_color_array = false; + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + use_color_array = true; + } + } + else + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + + if (!wireframe) { + TexCoordPtr(it.vertex); + if (use_color_array) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); + } + + // here the actual drawing takes places + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + if (!wireframe) { + glDisableClientState(GL_COLOR_ARRAY); + EnableTextures(false); + } +} + +void RAS_StorageVA::TexCoordPtr(const RAS_TexVert *tv) +{ + /* note: this function must closely match EnableTextures to enable/disable + * the right arrays, otherwise coordinate and attribute pointers from other + * materials can still be used and cause crashes */ + int unit; + + if (GLEW_ARB_multitexture) + { + for (unit = 0; unit < *m_texco_num; unit++) + { + glClientActiveTextureARB(GL_TEXTURE0_ARB+unit); + switch (m_texco[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV(unit)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent()); + break; + default: + break; + } + } + + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + + if (GLEW_ARB_vertex_program) { + int uv = 0; + for (unit = 0; unit < *m_attrib_num; unit++) { + switch (m_attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV(uv++)); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); + break; + case RAS_IRasterizer::RAS_TEXCO_VCOL: + glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA()); + break; + default: + break; + } + } + } +} + +void RAS_StorageVA::EnableTextures(bool enable) +{ + RAS_IRasterizer::TexCoGen *texco, *attrib; + int unit, texco_num, attrib_num; + + /* we cache last texcoords and attribs to ensure we disable the ones that + * were actually last set */ + if (enable) { + texco = m_texco; + texco_num = *m_texco_num; + attrib = m_attrib; + attrib_num = *m_attrib_num; + + memcpy(m_last_texco, m_texco, sizeof(RAS_IRasterizer::TexCoGen)*(*m_texco_num)); + m_last_texco_num = *m_texco_num; + memcpy(m_last_attrib, m_attrib, sizeof(RAS_IRasterizer::TexCoGen)*(*m_attrib_num)); + m_last_attrib_num = *m_attrib_num; + } + else { + texco = m_last_texco; + texco_num = m_last_texco_num; + attrib = m_last_attrib; + attrib_num = m_last_attrib_num; + } + + if (GLEW_ARB_multitexture) { + for (unit = 0; unit < texco_num; unit++) { + glClientActiveTextureARB(GL_TEXTURE0_ARB + unit); + + switch (texco[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + case RAS_IRasterizer::RAS_TEXCO_UV: + case RAS_IRasterizer::RAS_TEXCO_NORM: + case RAS_IRasterizer::RAS_TEXTANGENT: + if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + default: + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + } + } + + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + else { + if (texco_num) { + if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + + if (GLEW_ARB_vertex_program) { + for (unit = 0; unit < attrib_num; unit++) { + switch (attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + case RAS_IRasterizer::RAS_TEXCO_UV: + case RAS_IRasterizer::RAS_TEXCO_NORM: + case RAS_IRasterizer::RAS_TEXTANGENT: + case RAS_IRasterizer::RAS_TEXCO_VCOL: + if (enable) glEnableVertexAttribArrayARB(unit); + else glDisableVertexAttribArrayARB(unit); + break; + default: + glDisableVertexAttribArrayARB(unit); + break; + } + } + } + + if (!enable) { + m_last_texco_num = 0; + m_last_attrib_num = 0; + } +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h index 6b159db05ed..da7766ec5ca 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.h @@ -25,46 +25,53 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file RAS_VAOpenGLRasterizer.h - * \ingroup bgerastogl - */ +#ifndef __KX_VERTEXARRAYSTORAGE +#define __KX_VERTEXARRAYSTORAGE -#ifndef __RAS_VAOPENGLRASTERIZER_H__ -#define __RAS_VAOPENGLRASTERIZER_H__ +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" #include "RAS_OpenGLRasterizer.h" -class RAS_VAOpenGLRasterizer : public RAS_OpenGLRasterizer +class RAS_StorageVA : public RAS_IStorage { - void TexCoordPtr(const RAS_TexVert *tv); - /* bool m_Lock; */ /* UNUSED */ - - TexCoGen m_last_texco[RAS_MAX_TEXCO]; - TexCoGen m_last_attrib[RAS_MAX_ATTRIB]; - int m_last_texco_num; - int m_last_attrib_num; public: - RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock=false); - virtual ~RAS_VAOpenGLRasterizer(); + RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageVA(); virtual bool Init(); virtual void Exit(); - virtual void SetDrawingMode(int drawingmode); - - virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitives(RAS_MeshSlot& ms); virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); -private: + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + + int* m_texco_num; + int* m_attrib_num; + + int m_last_texco_num; + int m_last_attrib_num; + + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + RAS_IRasterizer::TexCoGen m_last_texco[RAS_MAX_TEXCO]; + RAS_IRasterizer::TexCoGen m_last_attrib[RAS_MAX_ATTRIB]; + virtual void EnableTextures(bool enable); - //virtual bool QueryArrays() {return true;} - //virtual bool QueryLists() {return m_Lock;} + virtual void TexCoordPtr(const RAS_TexVert *tv); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_VAOpenGLRasterizer") +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); } + void operator delete( void *mem ) { MEM_freeN(mem); } #endif }; -#endif /* __RAS_VAOPENGLRASTERIZER_H__ */ +#endif //__KX_VERTEXARRAYSTORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp new file mode 100644 index 00000000000..d40aa98295b --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp @@ -0,0 +1,259 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "RAS_StorageVBO.h" +#include "RAS_MeshObject.h" + +#include "GL/glew.h" + +VBO::VBO(RAS_DisplayArray *data, unsigned int indices) +{ + this->data = data; + this->size = data->m_vertex.size(); + this->indices = indices; + this->stride = 32*sizeof(GLfloat); // ATI cards really like 32byte aligned VBOs, so we add a little padding + + // Determine drawmode + if (data->m_type == data->QUAD) + this->mode = GL_QUADS; + else if (data->m_type == data->TRIANGLE) + this->mode = GL_TRIANGLES; + else + this->mode = GL_LINE; + + // Generate Buffers + glGenBuffersARB(1, &this->ibo); + glGenBuffersARB(1, &this->vbo_id); + + // Fill the buffers with initial data + UpdateIndices(); + UpdateData(); + + // Establish offsets + this->vertex_offset = 0; + this->normal_offset = (void*)(3*sizeof(GLfloat)); + this->tangent_offset = (void*)(6*sizeof(GLfloat)); + this->color_offset = (void*)(10*sizeof(GLfloat)); + this->uv_offset = (void*)(11*sizeof(GLfloat)); +} + +VBO::~VBO() +{ + glDeleteBuffersARB(1, &this->ibo); + glDeleteBuffersARB(1, &this->vbo_id); +} + +void VBO::UpdateData() +{ + unsigned int i, j, k; + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); + glBufferData(GL_ARRAY_BUFFER, this->stride*this->size, NULL, GL_STATIC_DRAW); + + // Map the buffer + GLfloat *vbo_map = (GLfloat*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + + // Gather data + for (i = 0, j = 0; i < data->m_vertex.size(); i++, j += this->stride/sizeof(GLfloat)) + { + memcpy(&vbo_map[j], data->m_vertex[i].getXYZ(), sizeof(float)*3); + memcpy(&vbo_map[j+3], data->m_vertex[i].getNormal(), sizeof(float)*3); + memcpy(&vbo_map[j+6], data->m_vertex[i].getTangent(), sizeof(float)*4); + memcpy(&vbo_map[j+10], data->m_vertex[i].getRGBA(), sizeof(char)*4); + + for (k = 0; k < RAS_TexVert::MAX_UNIT; k++) + memcpy(&vbo_map[j+11+(k*2)], data->m_vertex[i].getUV(k), sizeof(float)*2); + } + + glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); +} + +void VBO::UpdateIndices() +{ + int space = data->m_index.size() * sizeof(GLushort); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); + + // Upload Data to VBO + glBufferData(GL_ELEMENT_ARRAY_BUFFER, space, &data->m_index[0], GL_STATIC_DRAW); +} + +void VBO::Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, bool multi) +{ + int unit; + + // Bind buffers + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, this->ibo); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vbo_id); + + // Vertexes + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, this->stride, this->vertex_offset); + + // Normals + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, this->stride, this->normal_offset); + + // Colors + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, this->stride, this->color_offset); + + if (multi) + { + for (unit = 0; unit < texco_num; ++unit) + { + glClientActiveTexture(GL_TEXTURE0_ARB + unit); + switch (texco[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(3, GL_FLOAT, this->stride, this->vertex_offset); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, this->stride, (void*)((intptr_t)this->uv_offset+(sizeof(GLfloat)*2*unit))); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(3, GL_FLOAT, this->stride, this->normal_offset); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, this->stride, this->tangent_offset); + break; + default: + break; + } + } + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + else //TexFace + { + glClientActiveTextureARB(GL_TEXTURE0_ARB); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, this->stride, this->uv_offset); + } + + if (GLEW_ARB_vertex_program) + { + int uv = 0; + for (unit = 0; unit < attrib_num; ++unit) + { + switch (attrib[unit]) { + case RAS_IRasterizer::RAS_TEXCO_ORCO: + case RAS_IRasterizer::RAS_TEXCO_GLOB: + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, this->stride, this->vertex_offset); + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXCO_UV: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, this->stride, (void*)((intptr_t)this->uv_offset+uv)); + uv += sizeof(GLfloat)*2; + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXCO_NORM: + glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, stride, this->normal_offset); + glEnableVertexAttribArrayARB(unit); + break; + case RAS_IRasterizer::RAS_TEXTANGENT: + glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, this->stride, this->tangent_offset); + glEnableVertexAttribArrayARB(unit); + break; + default: + break; + } + } + } + + glDrawElements(this->mode, this->indices, GL_UNSIGNED_SHORT, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (GLEW_ARB_vertex_program) + { + for (int i = 0; i < attrib_num; ++i) + glDisableVertexAttribArrayARB(i); + } + + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + +RAS_StorageVBO::RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib): + m_texco_num(texco_num), + m_texco(texco), + m_attrib_num(attrib_num), + m_attrib(attrib) +{ +} + +RAS_StorageVBO::~RAS_StorageVBO() +{ +} + +bool RAS_StorageVBO::Init() +{ + return true; +} + +void RAS_StorageVBO::Exit() +{ + m_vbo_lookup.clear(); +} + +void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, false); +} + +void RAS_StorageVBO::IndexPrimitivesMulti(RAS_MeshSlot& ms) +{ + IndexPrimitivesInternal(ms, true); +} + +void RAS_StorageVBO::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) +{ + RAS_MeshSlot::iterator it; + VBO *vbo; + + for (ms.begin(it); !ms.end(it); ms.next(it)) + { + vbo = m_vbo_lookup[it.array]; + + if (vbo == 0) + m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex); + + // Update the vbo + if (ms.m_mesh->MeshModified()) + { + vbo->UpdateData(); + } + + vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, multi); + } +} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h new file mode 100644 index 00000000000..d8d8192e482 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h @@ -0,0 +1,100 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __KX_VERTEXBUFFEROBJECTSTORAGE +#define __KX_VERTEXBUFFEROBJECTSTORAGE + +#include <map> +#include "GL/glew.h" + +#include "RAS_IStorage.h" +#include "RAS_IRasterizer.h" + +#include "RAS_OpenGLRasterizer.h" + +class VBO +{ +public: + VBO(RAS_DisplayArray *data, unsigned int indices); + ~VBO(); + + void Draw(int texco_num, RAS_IRasterizer::TexCoGen* texco, int attrib_num, RAS_IRasterizer::TexCoGen* attrib, bool multi); + + void UpdateData(); + void UpdateIndices(); +private: + RAS_DisplayArray* data; + GLuint size; + GLuint stride; + GLuint indices; + GLenum mode; + GLuint ibo; + GLuint vbo_id; + + void* vertex_offset; + void* normal_offset; + void* color_offset; + void* tangent_offset; + void* uv_offset; +}; + +class RAS_StorageVBO : public RAS_IStorage +{ + +public: + RAS_StorageVBO(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib); + virtual ~RAS_StorageVBO(); + + virtual bool Init(); + virtual void Exit(); + + virtual void IndexPrimitives(RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(RAS_MeshSlot& ms); + + virtual void SetDrawingMode(int drawingmode){m_drawingmode=drawingmode;}; + +protected: + int m_drawingmode; + + int* m_texco_num; + int* m_attrib_num; + + RAS_IRasterizer::TexCoGen* m_texco; + RAS_IRasterizer::TexCoGen* m_attrib; + + std::map<RAS_DisplayArray*, class VBO*> m_vbo_lookup; + + virtual void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_StorageVA"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //__KX_VERTEXBUFFEROBJECTSTORAGE diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp deleted file mode 100644 index 076acb0d153..00000000000 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp - * \ingroup bgerastogl - */ - -#include "RAS_VAOpenGLRasterizer.h" -#include <stdlib.h> - -#include "GL/glew.h" -#include "GPU_extensions.h" - -#include "STR_String.h" -#include "RAS_TexVert.h" -#include "MT_CmMatrix4x4.h" -#include "RAS_IRenderTools.h" // rendering text - -RAS_VAOpenGLRasterizer::RAS_VAOpenGLRasterizer(RAS_ICanvas* canvas, bool lock) -: RAS_OpenGLRasterizer(canvas), - /* m_Lock(lock && GLEW_EXT_compiled_vertex_array), */ /* UNUSED */ - m_last_texco_num(0), - m_last_attrib_num(0) -{ -} - -RAS_VAOpenGLRasterizer::~RAS_VAOpenGLRasterizer() -{ -} - -bool RAS_VAOpenGLRasterizer::Init(void) -{ - - bool result = RAS_OpenGLRasterizer::Init(); - - if (result) - { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - return result; -} - -void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode) -{ - m_drawingmode = drawingmode; - - switch (m_drawingmode) - { - case KX_BOUNDINGBOX: - case KX_WIREFRAME: - //glDisableClientState(GL_COLOR_ARRAY); - //glDisable(GL_CULL_FACE); - break; - case KX_SOLID: - //glDisableClientState(GL_COLOR_ARRAY); - break; - case KX_TEXTURED: - case KX_SHADED: - case KX_SHADOW: - //glEnableClientState(GL_COLOR_ARRAY); - default: - break; - } -} - -void RAS_VAOpenGLRasterizer::Exit() -{ - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - RAS_OpenGLRasterizer::Exit(); -} - -void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) -{ - static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; - RAS_MeshSlot::iterator it; - GLenum drawmode; - - if (ms.m_pDerivedMesh) { - // cannot be handled here, pass to RAS_OpenGLRasterizer - RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false); - return; - } - - if (!wireframe) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - // use glDrawElements to draw each vertexarray - for (ms.begin(it); !ms.end(it); ms.next(it)) { - if (it.totindex == 0) - continue; - - // drawing mode - if (it.array->m_type == RAS_DisplayArray::TRIANGLE) - drawmode = GL_TRIANGLES; - else if (it.array->m_type == RAS_DisplayArray::QUAD) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - // colors - if (drawmode != GL_LINES && !wireframe) { - if (ms.m_bObjectColor) { - const MT_Vector4& rgba = ms.m_RGBAcolor; - - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - } - else { - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - glEnableClientState(GL_COLOR_ARRAY); - } - } - else - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - - glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); - glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); - if (!wireframe) { - glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1()); - if (glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); - } - - // here the actual drawing takes places - glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); - } - - if (!wireframe) { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } -} - -void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) -{ - static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; - RAS_MeshSlot::iterator it; - GLenum drawmode; - - if (ms.m_pDerivedMesh) { - // cannot be handled here, pass to RAS_OpenGLRasterizer - RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true); - return; - } - - if (!wireframe) - EnableTextures(true); - - // use glDrawElements to draw each vertexarray - for (ms.begin(it); !ms.end(it); ms.next(it)) { - if (it.totindex == 0) - continue; - - // drawing mode - if (it.array->m_type == RAS_DisplayArray::TRIANGLE) - drawmode = GL_TRIANGLES; - else if (it.array->m_type == RAS_DisplayArray::QUAD) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - // colors - if (drawmode != GL_LINES && !wireframe) { - if (ms.m_bObjectColor) { - const MT_Vector4& rgba = ms.m_RGBAcolor; - - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - } - else { - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - glEnableClientState(GL_COLOR_ARRAY); - } - } - else - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - - glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); - glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); - if (!wireframe) { - TexCoordPtr(it.vertex); - if (glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); - } - - // here the actual drawing takes places - glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); - } - - if (!wireframe) { - glDisableClientState(GL_COLOR_ARRAY); - EnableTextures(false); - } -} - -void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) -{ - /* note: this function must closely match EnableTextures to enable/disable - * the right arrays, otherwise coordinate and attribute pointers from other - * materials can still be used and cause crashes */ - int unit; - - if (GLEW_ARB_multitexture) - { - for (unit=0; unit<m_texco_num; unit++) - { - glClientActiveTextureARB(GL_TEXTURE0_ARB+unit); - if (tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2()); - continue; - } - switch (m_texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); - break; - case RAS_TEXCO_UV1: - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1()); - break; - case RAS_TEXCO_NORM: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getNormal()); - break; - case RAS_TEXTANGENT: - glTexCoordPointer(4, GL_FLOAT, sizeof(RAS_TexVert),tv->getTangent()); - break; - case RAS_TEXCO_UV2: - glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV2()); - break; - default: - break; - } - } - - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - - if (GLEW_ARB_vertex_program) { - for (unit=0; unit<m_attrib_num; unit++) { - switch (m_attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); - break; - case RAS_TEXCO_UV1: - glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); - break; - case RAS_TEXCO_NORM: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getNormal()); - break; - case RAS_TEXTANGENT: - glVertexAttribPointerARB(unit, 4, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getTangent()); - break; - case RAS_TEXCO_UV2: - glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV2()); - break; - case RAS_TEXCO_VCOL: - glVertexAttribPointerARB(unit, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(RAS_TexVert), tv->getRGBA()); - break; - default: - break; - } - } - } -} - -void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) -{ - TexCoGen *texco, *attrib; - int unit, texco_num, attrib_num; - - /* we cache last texcoords and attribs to ensure we disable the ones that - * were actually last set */ - if (enable) { - texco = m_texco; - texco_num = m_texco_num; - attrib = m_attrib; - attrib_num = m_attrib_num; - - memcpy(m_last_texco, m_texco, sizeof(TexCoGen)*m_texco_num); - m_last_texco_num = m_texco_num; - memcpy(m_last_attrib, m_attrib, sizeof(TexCoGen)*m_attrib_num); - m_last_attrib_num = m_attrib_num; - } - else { - texco = m_last_texco; - texco_num = m_last_texco_num; - attrib = m_last_attrib; - attrib_num = m_last_attrib_num; - } - - if (GLEW_ARB_multitexture) { - for (unit=0; unit<texco_num; unit++) { - glClientActiveTextureARB(GL_TEXTURE0_ARB+unit); - - switch (texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - case RAS_TEXCO_UV1: - case RAS_TEXCO_NORM: - case RAS_TEXTANGENT: - case RAS_TEXCO_UV2: - if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); - else glDisableClientState(GL_TEXTURE_COORD_ARRAY); - break; - default: - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - break; - } - } - - glClientActiveTextureARB(GL_TEXTURE0_ARB); - } - else { - if (texco_num) { - if (enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY); - else glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } - - if (GLEW_ARB_vertex_program) { - for (unit=0; unit<attrib_num; unit++) { - switch (attrib[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - case RAS_TEXCO_UV1: - case RAS_TEXCO_NORM: - case RAS_TEXTANGENT: - case RAS_TEXCO_UV2: - case RAS_TEXCO_VCOL: - if (enable) glEnableVertexAttribArrayARB(unit); - else glDisableVertexAttribArrayARB(unit); - break; - default: - glDisableVertexAttribArrayARB(unit); - break; - } - } - } - - if (!enable) { - m_last_texco_num = 0; - m_last_attrib_num = 0; - } -} - diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 945644ff3e6..0a90054275b 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -34,8 +34,7 @@ #include "MT_Matrix4x4.h" RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, @@ -43,8 +42,6 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const unsigned int origindex) { xyz.getValue(m_localxyz); - uv.getValue(m_uv1); - uv2.getValue(m_uv2); SetRGBA(rgba); SetNormal(normal); tangent.getValue(m_tangent); @@ -52,6 +49,11 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, m_origindex = origindex; m_unit = 2; m_softBodyIndex = -1; + + for (int i = 0; i < MAX_UNIT; ++i) + { + uvs[i].getValue(m_uvs[i]); + } } const MT_Point3& RAS_TexVert::xyz() @@ -80,26 +82,15 @@ void RAS_TexVert::SetXYZ(const float xyz[3]) m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2]; } -void RAS_TexVert::SetUV1(const MT_Point2& uv) -{ - uv.getValue(m_uv1); -} - -void RAS_TexVert::SetUV1(const float uv[3]) +void RAS_TexVert::SetUV(int index, const MT_Point2& uv) { - m_uv1[0] = uv[0]; - m_uv1[1] = uv[1]; + uv.getValue(m_uvs[index]); } -void RAS_TexVert::SetUV2(const MT_Point2& uv) +void RAS_TexVert::SetUV(int index, const float uv[2]) { - uv.getValue(m_uv2); -} - -void RAS_TexVert::SetUV2(const float uv[3]) -{ - m_uv2[0] = uv[0]; - m_uv2[1] = uv[1]; + m_uvs[index][0] = uv[0]; + m_uvs[index][1] = uv[1]; } void RAS_TexVert::SetRGBA(const unsigned int rgba) @@ -132,14 +123,17 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent) // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { + bool uv_match = true; + for (int i=0; i<MAX_UNIT; i++) + uv_match = uv_match && MT_fuzzyEqual(MT_Vector2(m_uvs[i]), MT_Vector2(other->m_uvs[i])); + return ( /* m_flag == other->m_flag && */ /* at the moment the face only stores the smooth/flat setting so don't bother comparing it */ m_rgba == other->m_rgba && MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && - MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && - MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) /* && + uv_match /* && MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))*/); /* don't bother comparing m_localxyz since we know there from the same vert */ } @@ -162,12 +156,7 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } -void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat) -{ - SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); -} - -void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat) +void RAS_TexVert::TransformUV(int index, const MT_Matrix4x4& mat) { - SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue()); + SetUV(index, (mat * MT_Vector4(m_uvs[index][0], m_uvs[index][1], 0.0, 1.0)).getValue()); } diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 98ea4dd60aa..a91d2c7f848 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -48,23 +48,21 @@ class RAS_TexVert { float m_localxyz[3]; // 3*4 = 12 - float m_uv1[2]; // 2*4 = 8 - float m_uv2[2]; // 2*4 = 8 + float m_uvs[8][2]; // 8*2*4=64 //8 = MAX_UNIT unsigned int m_rgba; // 4 - float m_tangent[4]; // 4*4 = 16 - float m_normal[3]; // 3*4 = 12 + float m_tangent[4]; // 4*4 = 16 + float m_normal[3]; // 3*4 = 12 short m_flag; // 2 short m_softBodyIndex; //2 unsigned int m_unit; // 4 unsigned int m_origindex; // 4 //--------- - // 56+6+8+2=72 - // 32 bytes total size, fits nice = 56 = not fit nice. + // 120 + // 32 bytes total size, fits nice = 120 = not fit nice. public: enum { FLAT = 1, - SECOND_UV = 2, MAX_UNIT = 8 }; @@ -74,8 +72,7 @@ public: RAS_TexVert()// :m_xyz(0,0,0),m_uv(0,0),m_rgba(0) {} RAS_TexVert(const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, + const MT_Point2 uvs[MAX_UNIT], const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, @@ -83,12 +80,8 @@ public: const unsigned int origindex); ~RAS_TexVert() {}; - const float* getUV1 () const { - return m_uv1; - }; - - const float* getUV2 () const { - return m_uv2; + const float* getUV (int unit) const { + return m_uvs[unit]; }; const float* getXYZ() const { @@ -123,10 +116,8 @@ public: void SetXYZ(const MT_Point3& xyz); void SetXYZ(const float xyz[3]); - void SetUV1(const MT_Point2& uv); - void SetUV2(const MT_Point2& uv); - void SetUV1(const float uv[2]); - void SetUV2(const float uv[2]); + void SetUV(int index, const MT_Point2& uv); + void SetUV(int index, const float uv[2]); void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); @@ -139,8 +130,7 @@ public: void Transform(const class MT_Matrix4x4& mat, const class MT_Matrix4x4& nmat); - void TransformUV1(const MT_Matrix4x4& mat); - void TransformUV2(const MT_Matrix4x4& mat); + void TransformUV(int index, const MT_Matrix4x4& mat); // compare two vertices, to test if they can be shared, used for // splitting up based on uv's, colors, etc diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp index d335a38171f..3203fcf9d6b 100644 --- a/source/gameengine/Rasterizer/RAS_texmatrix.cpp +++ b/source/gameengine/Rasterizer/RAS_texmatrix.cpp @@ -52,9 +52,9 @@ void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Ve MT_Scalar d = -p[0].xyz().dot(normal); - MT_Matrix3x3 mat3( p[0].getUV1()[0],p[0].getUV1()[1], 1, - p[1].getUV1()[0],p[1].getUV1()[1], 1, - p[2].getUV1()[0],p[2].getUV1()[1], 1); + MT_Matrix3x3 mat3( p[0].getUV(0)[0],p[0].getUV(0)[1], 1, + p[1].getUV(0)[0],p[1].getUV(0)[1], 1, + p[2].getUV(0)[0],p[2].getUV(0)[1], 1); MT_Matrix3x3 mat3inv = mat3.inverse(); |