/* * ***** 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, int *attrib_layer) : m_drawingmode(RAS_IRasterizer::KX_TEXTURED), m_texco_num(texco_num), m_attrib_num(attrib_num), m_texco(texco), m_attrib(attrib), m_attrib_layer(attrib_layer) { } 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) { 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(m_attrib_layer[unit])); 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(); } } }