From 3727607c820b3686b21d44a9ba07a53ac2a7e846 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Sun, 21 Feb 2016 18:50:20 +0100 Subject: [PATCH] UPBGE: Fix wire material. Previously all wire material was using triangles and not quad as BF BGE. The perfect behavior should be to respect edges and not only faces. Now we use only lines not quad or triangles and these lines are real edge of valid faces. To find a edge we test if two vertices are en edge in the poly which contains the face, if yes we call RAS_MeshObject::AddLine(bucket, v1, v2). And in AddPolygon the vertex offset are don't added if the material is wire : RAS_IPolyMayerial::IsWire(). Now in RAS_DisplayArray we have a new variable m_type depending of an enum which contains LINES, TRIANGLES. The function GetOpenGLPrimitiveType convert this value to an opengl primitive type. RAS_IRasterizer::SetLines became useless for regular meshes (because they use GL_LINES directly) but it's still resquierd for DerivedMesh. The call to this function was removed in KX_BlenderMaterial and added in RAS_OpenGLRasterizer::DrawDerivedMesh. --- build_files/cmake/macros.cmake | 2 +- source/blenderplayer/CMakeLists.txt | 4 +- .../Converter/BL_BlenderDataConversion.cpp | 26 +++++++++++ .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 34 +++++++------- source/gameengine/Ketsji/KX_BlenderMaterial.h | 1 + source/gameengine/Rasterizer/CMakeLists.txt | 1 + .../Rasterizer/RAS_DisplayArray.cpp | 46 +++++++++++++++++++ .../gameengine/Rasterizer/RAS_DisplayArray.h | 7 +++ .../Rasterizer/RAS_IPolygonMaterial.h | 1 + .../Rasterizer/RAS_MaterialBucket.cpp | 5 ++ .../Rasterizer/RAS_MaterialBucket.h | 1 + .../gameengine/Rasterizer/RAS_MeshObject.cpp | 16 ++++++- source/gameengine/Rasterizer/RAS_MeshObject.h | 1 + source/gameengine/Rasterizer/RAS_MeshSlot.cpp | 12 ++++- .../RAS_OpenGLRasterizer.cpp | 8 ++++ .../RAS_OpenGLRasterizer/RAS_StorageVA.cpp | 4 +- .../RAS_OpenGLRasterizer/RAS_StorageVBO.cpp | 2 +- 17 files changed, 146 insertions(+), 25 deletions(-) create mode 100644 source/gameengine/Rasterizer/RAS_DisplayArray.cpp diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index df0c3651c772..a10cead7dea1 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -609,8 +609,8 @@ function(SETUP_BLENDER_SORTED_LIBS) ge_logic_ketsji extern_recastnavigation ge_logic - ge_rasterizer ge_oglrasterizer + ge_rasterizer ge_logic_expressions ge_scenegraph ge_logic_network diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 4b828408e459..e1af0710c3e0 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -125,8 +125,8 @@ endif() ge_phys_bullet ge_phys_dummy ge_logic - ge_rasterizer - ge_oglrasterizer + ge_oglrasterizer + ge_rasterizer ge_logic_expressions ge_scenegraph bf_ikplugin diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 2759ff2bf7a6..b8c7d17c5cd5 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -819,6 +819,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, MFace *mface = dm->getTessFaceArray(dm); MTFace *tface = static_cast(dm->getTessFaceDataArray(dm, CD_MTFACE)); MCol *mcol = static_cast(dm->getTessFaceDataArray(dm, CD_MCOL)); + MPoly *mpolyarray = (MPoly *)dm->getPolyArray(dm); + MLoop *mlooparray = (MLoop *)dm->getLoopArray(dm); + MEdge *medgearray = (MEdge *)dm->getEdgeArray(dm); + int *mfaceTompoly = (int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); float (*tangent)[4] = NULL; int totface = dm->getNumTessFaces(dm); const char *tfaceName = ""; @@ -976,6 +980,28 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, indices[3] = meshobj->AddVertex(bucket, 3, pt[3], uvs[3], tan[3], rgb[3], no[3], flat, mface->v4); } + if (bucket->IsWire() && visible) { + // The fourth value can be uninitialized. + unsigned int mfaceindices[4] = {mface->v1, mface->v2, mface->v3, mface->v4}; + MPoly *mpoly = mpolyarray + mfaceTompoly[f]; + unsigned int lpstart = mpoly->loopstart; + unsigned int totlp = mpoly->totloop; + // Iterate on all edges (=loops) of the MPoly which contains the current MFace. + for (unsigned int i = lpstart; i < lpstart + totlp; ++i) { + MLoop *mloop = mlooparray + i; + // Get the edge. + MEdge *medge = medgearray + mloop->e; + // Iterate on all MFace vertices index. + for (unsigned short j = (nverts - 1), k = 0; k < nverts; j = k++) { + // If 2 vertices are the same as an edge, we add a line in the mesh. + if (ELEM(medge->v1, mfaceindices[j], mfaceindices[k]) && + ELEM(medge->v2, mfaceindices[j], mfaceindices[k])) { + meshobj->AddLine(bucket, indices[j], indices[k]); + break; + } + } + } + } meshobj->AddPolygon(bucket, nverts, indices, visible, collider, twoside); } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 61c916ef7372..db51aa533a1a 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -356,17 +356,16 @@ void KX_BlenderMaterial::ActivateShaders(RAS_IRasterizer *rasty) { SetShaderData(rasty); - if (m_material->ras_mode & TWOSIDED) + if (IsWire()) { rasty->SetCullFace(false); - else - rasty->SetCullFace(true); - - if (m_material->ras_mode & WIRE) { + } + else if (m_material->ras_mode & TWOSIDED) { rasty->SetCullFace(false); - rasty->SetLines(true); } - else - rasty->SetLines(false); + else { + rasty->SetCullFace(true); + } + ActivateGLMaterials(rasty); ActivateTexGen(rasty); } @@ -375,17 +374,15 @@ void KX_BlenderMaterial::ActivateBlenderShaders(RAS_IRasterizer *rasty) { SetBlenderShaderData(rasty); - if (m_material->ras_mode & TWOSIDED) + if (IsWire()) { rasty->SetCullFace(false); - else - rasty->SetCullFace(true); - - if (m_material->ras_mode & WIRE) { + } + else if (m_material->ras_mode & TWOSIDED) { rasty->SetCullFace(false); - rasty->SetLines(true); } - else - rasty->SetLines(false); + else { + rasty->SetCullFace(true); + } ActivateGLMaterials(rasty); m_blenderShader->SetAttribs(rasty); @@ -438,6 +435,11 @@ void KX_BlenderMaterial::Desactivate(RAS_IRasterizer *rasty) rasty->SetAttribNum(0); } +bool KX_BlenderMaterial::IsWire() const +{ + return m_material->ras_mode & WIRE; +} + bool KX_BlenderMaterial::IsAlphaShadow() const { return m_material->alphablend != GEMAT_SOLID; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 9fc20feaffd3..7c7e4c4fac99 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -56,6 +56,7 @@ class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial void ActivateBlenderShaders(RAS_IRasterizer *rasty); + virtual bool IsWire() const; virtual bool IsAlphaShadow() const; virtual bool UseInstancing() const; Material *GetBlenderMaterial() const; diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index d8c2585b326b..3c5eef770417 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -49,6 +49,7 @@ set(INC_SYS set(SRC RAS_2DFilterManager.cpp RAS_BucketManager.cpp + RAS_DisplayArray.cpp RAS_DisplayArrayBucket.cpp RAS_FramingManager.cpp RAS_IPolygonMaterial.cpp diff --git a/source/gameengine/Rasterizer/RAS_DisplayArray.cpp b/source/gameengine/Rasterizer/RAS_DisplayArray.cpp new file mode 100644 index 000000000000..b2735983d790 --- /dev/null +++ b/source/gameengine/Rasterizer/RAS_DisplayArray.cpp @@ -0,0 +1,46 @@ +/* + * ***** 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: all of this file. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file RAS_DisplayArray.cpp + * \ingroup bgerast + */ + +#include "RAS_DisplayArray.h" + +#include "glew-mx.h" + +int RAS_DisplayArray::GetOpenGLPrimitiveType() const +{ + switch (m_type) { + case LINES: + { + return GL_LINES; + } + case TRIANGLES: + { + return GL_TRIANGLES; + } + } + return 0; +} diff --git a/source/gameengine/Rasterizer/RAS_DisplayArray.h b/source/gameengine/Rasterizer/RAS_DisplayArray.h index 0373d9abf5f7..ba69044f0270 100644 --- a/source/gameengine/Rasterizer/RAS_DisplayArray.h +++ b/source/gameengine/Rasterizer/RAS_DisplayArray.h @@ -43,8 +43,15 @@ class RAS_DisplayArray std::vector m_vertex; std::vector m_index; + enum { + TRIANGLES, + LINES, + } m_type; + enum {BUCKET_MAX_INDEX = 65535}; enum {BUCKET_MAX_VERTEX = 65535}; + + int GetOpenGLPrimitiveType() const; }; #endif // __RAS_DISPLAY_ARRAY_H__ diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 7b8a824aeaec..3c8ebb1f9f3f 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -136,6 +136,7 @@ class RAS_IPolyMaterial virtual MTexPoly *GetMTexPoly() const = 0; virtual unsigned int *GetMCol() const = 0; virtual Scene *GetBlenderScene() const = 0; + virtual bool IsWire() const = 0; virtual bool IsAlphaShadow() const = 0; virtual bool UseInstancing() const = 0; virtual void ReleaseMaterial() = 0; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 0fb0b1be29ca..c748a4afdfff 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -72,6 +72,11 @@ bool RAS_MaterialBucket::IsZSort() const return (m_material->IsZSort()); } +bool RAS_MaterialBucket::IsWire() const +{ + return (m_material->IsWire()); +} + bool RAS_MaterialBucket::UseInstancing() const { return (m_material->UseInstancing()); diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 91aae9f11758..75147ef54e60 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -52,6 +52,7 @@ class RAS_MaterialBucket RAS_IPolyMaterial *GetPolyMaterial() const; bool IsAlpha() const; bool IsZSort() const; + bool IsWire() const; bool UseInstancing() const; // Rendering diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index d95e5fb12afd..ff9931412038 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -297,6 +297,20 @@ void RAS_MeshObject::AddMaterial(RAS_MaterialBucket *bucket, unsigned int index) } } +void RAS_MeshObject::AddLine(RAS_MaterialBucket *bucket, unsigned int v1, unsigned int v2) +{ + // find a mesh material + RAS_MeshMaterial *mmat = GetMeshMaterial(bucket->GetPolyMaterial()); + // add it to the bucket, this also adds new display arrays + RAS_MeshSlot *slot = mmat->m_baseslot; + + // create a new polygon + RAS_DisplayArray *darray = slot->GetDisplayArray(); + darray->m_type = RAS_DisplayArray::LINES; + slot->AddPolygonVertex(v1); + slot->AddPolygonVertex(v2); +} + RAS_Polygon *RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts, unsigned int indices[4], bool visible, bool collider, bool twoside) { @@ -314,7 +328,7 @@ RAS_Polygon *RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts poly->SetCollider(collider); poly->SetTwoside(twoside); - if (visible) { + if (visible && !bucket->IsWire()) { // Add the first triangle. slot->AddPolygonVertex(indices[0]); slot->AddPolygonVertex(indices[1]); diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index de69b9744b13..130d70da8f35 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -131,6 +131,7 @@ class RAS_MeshObject // mesh construction void AddMaterial(RAS_MaterialBucket *bucket, unsigned int index); + void AddLine(RAS_MaterialBucket *bucket, unsigned int v1, unsigned int v2); virtual RAS_Polygon *AddPolygon(RAS_MaterialBucket *bucket, int numverts, unsigned int indices[4], bool visible, bool collider, bool twoside); virtual unsigned int AddVertex(RAS_MaterialBucket *bucket, int i, diff --git a/source/gameengine/Rasterizer/RAS_MeshSlot.cpp b/source/gameengine/Rasterizer/RAS_MeshSlot.cpp index 55f2e8862ae6..ef9e7a75dee2 100644 --- a/source/gameengine/Rasterizer/RAS_MeshSlot.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshSlot.cpp @@ -104,8 +104,16 @@ RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) void RAS_MeshSlot::init(RAS_MaterialBucket *bucket) { m_bucket = bucket; - m_displayArrayBucket = new RAS_DisplayArrayBucket(bucket, (new RAS_DisplayArray()), m_mesh); - m_displayArray = m_displayArrayBucket->GetDisplayArray(); + + m_displayArray = new RAS_DisplayArray(); + if (bucket->IsWire()) { + m_displayArray->m_type = RAS_DisplayArray::LINES; + } + else { + m_displayArray->m_type = RAS_DisplayArray::TRIANGLES; + } + + m_displayArrayBucket = new RAS_DisplayArrayBucket(bucket, m_displayArray, m_mesh); } RAS_DisplayArray *RAS_MeshSlot::GetDisplayArray() diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 21c370372360..8ce858e16b2b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -870,6 +870,10 @@ void RAS_OpenGLRasterizer::DrawDerivedMesh(RAS_MeshSlot *ms) else this->SetCullFace(false); + if (current_bucket->IsWire()) { + SetLines(true); + } + if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { // GetMaterialIndex return the original mface material index, // increment by 1 to match what derived mesh is doing @@ -891,6 +895,10 @@ void RAS_OpenGLRasterizer::DrawDerivedMesh(RAS_MeshSlot *ms) current_image = current_polymat->GetBlenderImage(); ms->m_pDerivedMesh->drawFacesTex(ms->m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV); } + + if (current_bucket->IsWire()) { + SetLines(false); + } } void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp index 6924bc44815b..2d2a79a4deb7 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp @@ -197,7 +197,7 @@ void RAS_StorageVA::IndexPrimitives(RAS_MeshSlot *ms) glColor4f(0.0f, 0.0f, 0.0f, 1.0f); // here the actual drawing takes places - glDrawElements(GL_TRIANGLES, array->m_index.size(), GL_UNSIGNED_INT, indexarray); + glDrawElements(array->GetOpenGLPrimitiveType(), array->m_index.size(), GL_UNSIGNED_INT, indexarray); if (displayList) { displayList->End(m_drawingmode, RAS_DisplayList::DRAW_LIST); @@ -210,7 +210,7 @@ void RAS_StorageVA::IndexPrimitivesInstancing(RAS_DisplayArrayBucket *arrayBucke unsigned int *indexarray = array->m_index.data(); // here the actual drawing takes places - glDrawElementsInstanced(GL_TRIANGLES, array->m_index.size(), GL_UNSIGNED_INT, indexarray, arrayBucket->GetNumActiveMeshSlots()); + glDrawElementsInstanced(array->GetOpenGLPrimitiveType(), array->m_index.size(), GL_UNSIGNED_INT, indexarray, arrayBucket->GetNumActiveMeshSlots()); } RAS_DisplayList *RAS_StorageVA::GetDisplayList(RAS_DisplayArrayBucket *arrayBucket) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp index d90fc548dd6d..b9208d9f0ef6 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp @@ -39,7 +39,7 @@ VBO::VBO(RAS_DisplayArray *data, unsigned int indices) m_indices = indices; m_stride = sizeof(RAS_TexVert); - m_mode = GL_TRIANGLES; + m_mode = m_data->GetOpenGLPrimitiveType(); // Generate Buffers glGenBuffersARB(1, &m_ibo);