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 | |
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')
45 files changed, 1856 insertions, 1289 deletions
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b3aabf1265a..2edbf14eb6c 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -636,7 +636,8 @@ typedef struct GameData { short physicsEngine; short exitkey, pad; short ticrate, maxlogicstep, physubstep, maxphystep; - short obstacleSimulation, pad1; + short obstacleSimulation; + short raster_storage; float levelHeight; float deactivationtime, lineardeactthreshold, angulardeactthreshold, pad2; } GameData; @@ -663,6 +664,12 @@ typedef struct GameData { #define OBSTSIMULATION_TOI_rays 1 #define OBSTSIMULATION_TOI_cells 2 +/* Raster storage */ +#define RAS_STORE_AUTO 0 +#define RAS_STORE_IMMEDIATE 1 +#define RAS_STORE_VA 2 +#define RAS_STORE_VBO 3 + /* GameData.flag */ #define GAME_RESTRICT_ANIM_UPDATES (1 << 0) #define GAME_ENABLE_ALL_FRAMES (1 << 1) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index fad4a2035fd..03f566b5bca 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2444,6 +2444,13 @@ static void rna_def_scene_game_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem storage_items[] ={ + {RAS_STORE_AUTO, "AUTO", 0, "Auto Select", "Chooses the best supported mode"}, + {RAS_STORE_IMMEDIATE, "IMMEDIATE", 0, "Immediate Mode", "Slowest performance, requires OpenGL (any version)"}, + {RAS_STORE_VA, "VERTEX_ARRAY", 0, "Vertex Arrays", "Moderate performance, requires at least OpenGL 1.1"}, + {RAS_STORE_VBO, "VERTEX_BUFFER_OBJECT", 0, "Vertex Buffer Objects", "Best performance, requires at least OpenGL 1.4"}, + {0, NULL, 0, NULL, NULL}}; + srna = RNA_def_struct(brna, "SceneGameData", NULL); RNA_def_struct_sdna(srna, "GameData"); RNA_def_struct_nested(brna, srna, "Scene"); @@ -2479,6 +2486,12 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine"); RNA_def_property_update(prop, NC_SCENE, NULL); + prop= RNA_def_property(srna, "raster_storage", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "raster_storage"); + RNA_def_property_enum_items(prop, storage_items); + RNA_def_property_ui_text(prop, "Storage", "Sets the storage mode used by the rasterizer"); + RNA_def_property_update(prop, NC_SCENE, NULL); + /* Do we need it here ? (since we already have it in World */ prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "freqplay"); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 6807f531f0a..9f788b29ac6 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -58,7 +58,6 @@ #include "RAS_GLExtensionManager.h" #include "RAS_OpenGLRasterizer.h" -#include "RAS_VAOpenGLRasterizer.h" #include "RAS_ListRasterizer.h" #include "NG_LoopBackNetworkDeviceInterface.h" @@ -287,16 +286,12 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; - if (displaylists) { - if (GLEW_VERSION_1_1 && !novertexarrays) - rasterizer = new RAS_ListRasterizer(canvas, true, true); - else - rasterizer = new RAS_ListRasterizer(canvas); - } - else if (GLEW_VERSION_1_1 && !novertexarrays) - rasterizer = new RAS_VAOpenGLRasterizer(canvas, false); + //Don't use displaylists with VBOs + //If auto starts using VBOs, make sure to check for that here + if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO) + rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage); else - rasterizer = new RAS_OpenGLRasterizer(canvas); + rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage); // create the inputdevices KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice(); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index ab0630bf398..15fc5ba76c7 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -423,55 +423,61 @@ static void SetDefaultLightMode(Scene* scene) // -- -static void GetRGB( - const bool use_mcol, - MFace *mface, - MCol *mmcol, - Material *mat, - unsigned int &c0, - unsigned int &c1, - unsigned int &c2, - unsigned int &c3) +static void GetRGB(short type, + MFace* mface, + MCol* mmcol, + Material *mat, + unsigned int c[4]) { unsigned int color = 0xFFFFFFFFL; - if (use_mcol) { - // vertex colors - - if (mmcol) { - c0 = KX_Mcol2uint_new(mmcol[0]); - c1 = KX_Mcol2uint_new(mmcol[1]); - c2 = KX_Mcol2uint_new(mmcol[2]); + switch (type) { + case 0: // vertex colors + { + if (mmcol) { + c[0] = KX_Mcol2uint_new(mmcol[0]); + c[1] = KX_Mcol2uint_new(mmcol[1]); + c[2] = KX_Mcol2uint_new(mmcol[2]); + if (mface->v4) + c[3] = KX_Mcol2uint_new(mmcol[3]); + } + else { // backup white + c[0] = KX_rgbaint2uint_new(color); + c[1] = KX_rgbaint2uint_new(color); + c[2] = KX_rgbaint2uint_new(color); + if (mface->v4) + c[3] = KX_rgbaint2uint_new( color ); + } + } break; + + + case 1: // material rgba + { + if (mat) { + union { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); + col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); + col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); + col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); + color = col_converter.integer; + } + c[0] = KX_rgbaint2uint_new(color); + c[1] = KX_rgbaint2uint_new(color); + c[2] = KX_rgbaint2uint_new(color); if (mface->v4) - c3 = KX_Mcol2uint_new(mmcol[3]); - } - else { // backup white - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); + c[3] = KX_rgbaint2uint_new(color); + } break; + + default: // white + { + c[0] = KX_rgbaint2uint_new(color); + c[1] = KX_rgbaint2uint_new(color); + c[2] = KX_rgbaint2uint_new(color); if (mface->v4) - c3 = KX_rgbaint2uint_new( color ); - } - } - else { - // material rgba - if (mat) { - union { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); - col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); - col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); - col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); - color = col_converter.integer; - } - // backup white is fallback - - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new(color); + c[3] = KX_rgbaint2uint_new(color); + } break; } } @@ -480,42 +486,67 @@ typedef struct MTF_localLayer { const char *name; } MTF_localLayer; -static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4]) +static void GetUVs(BL_Material *material, MTF_localLayer *layers, MFace *mface, MTFace *tface, MT_Point2 uvs[4][MAXTEX]) { - uv[0].setValue(tface->uv[0]); - uv[1].setValue(tface->uv[1]); - uv[2].setValue(tface->uv[2]); - if (mface->v4) { - uv[3].setValue(tface->uv[3]); + int unit = 0; + if (tface) + { + + uvs[0][0].setValue(tface->uv[0]); + uvs[1][0].setValue(tface->uv[1]); + uvs[2][0].setValue(tface->uv[2]); + + if (mface->v4) + uvs[3][0].setValue(tface->uv[3]); } -} + else + { + uvs[0][0] = uvs[1][0] = uvs[2][0] = uvs[3][0] = MT_Point2(0.f, 0.f); + } + + for (int vind = 0; vind<MAXTEX; vind++) + { + BL_Mapping &map = material->mapping[vind]; -static void GetUV( - MFace *mface, - MTFace *tface, - MTF_localLayer *layers, - const int layer_uv[2], - MT_Point2 uv[4], - MT_Point2 uv2[4]) -{ - bool validface = (tface != NULL); + if (!(map.mapping & USEUV)) continue; - uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + //If no UVSet is specified, try grabbing one from the UV/Image editor + if (map.uvCoName.IsEmpty() && tface) + { + uvs[0][unit].setValue(tface->uv[0]); + uvs[1][unit].setValue(tface->uv[1]); + uvs[2][unit].setValue(tface->uv[2]); - /* No material, what to do? let's see what is in the UV and set the material accordingly - * light and visible is always on */ - if (layer_uv[0] != -1) { - tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv); - if (layer_uv[1] != -1) { - tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2); + if (mface->v4) + uvs[3][unit].setValue(tface->uv[3]); + + ++unit; + continue; + } + + + for (int lay=0; lay<MAX_MTFACE; lay++) + { + MTF_localLayer& layer = layers[lay]; + if (layer.face == 0) break; + + if (map.uvCoName.IsEmpty() || strcmp(map.uvCoName.ReadPtr(), layer.name)==0) + { + MT_Point2 uvSet[4]; + + uvs[0][unit].setValue(layer.face->uv[0]); + uvs[1][unit].setValue(layer.face->uv[1]); + uvs[2][unit].setValue(layer.face->uv[2]); + + if (mface->v4) + uvs[3][unit].setValue(layer.face->uv[3]); + else + uvs[3][unit].setValue(0.0f, 0.0f); + + ++unit; + break; + } } - } - else if (validface) { - tface_to_uv_bge(mface, tface, uv); - } - else { - // nothing at all - uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); } } @@ -526,25 +557,29 @@ static bool ConvertMaterial( MTFace* tface, const char *tfaceName, MFace* mface, - MCol* mmcol, /* only for text, use first mcol, weak */ - MTF_localLayer *layers, - int layer_uv[2], - const bool glslmat) + MCol* mmcol, + bool glslmat) { material->Initialize(); - int numchan = -1, texalpha = 0; + int texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); + short type = 0; + if ( validmat ) + type = 1; // material color + material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; material->materialindex = mface->mat_nr; - /* default value for being unset */ - layer_uv[0] = layer_uv[1] = -1; - // -------------------------------- if (validmat) { + + // use vertex colors by explicitly setting + if (mat->mode &MA_VERTEXCOLP || glslmat) + type = 0; + // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; @@ -552,7 +587,6 @@ static bool ConvertMaterial( // cast shadows? material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0; MTex *mttmp = 0; - numchan = getNumTexChannels(mat); int valid_index = 0; /* In Multitexture use the face texture if and only if @@ -561,12 +595,9 @@ static bool ConvertMaterial( bool facetex = false; if (validface && mat->mode &MA_FACETEXTURE) facetex = true; - - numchan = numchan>MAXTEX?MAXTEX:numchan; - if (facetex && numchan == 0) numchan = 1; // foreach MTex - for (int i=0; i<numchan; i++) { + for (int i=0; i<MAXTEX; i++) { // use face tex if (i==0 && facetex ) { @@ -798,14 +829,11 @@ static bool ConvertMaterial( material->ras_mode |= USE_LIGHT; } - const char *uvName = "", *uv2Name = ""; - /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ if ( validface ) { material->tile = tface->tile; - uvName = tfaceName; - } + } else { // nothing at all material->alphablend = GEMAT_SOLID; @@ -826,45 +854,19 @@ static bool ConvertMaterial( material->ras_mode |= (mat && (mat->game.alpha_blend & GEMAT_ALPHA_SORT))? ZSORT: 0; } - // get uv sets - if (validmat) { - bool isFirstSet = true; - - // only two sets implemented, but any of the eight - // sets can make up the two layers - for (int vind = 0; vind<material->num_enabled; vind++) { - BL_Mapping &map = material->mapping[vind]; + // XXX The RGB values here were meant to be temporary storage for the conversion process, + // but fonts now make use of them too, so we leave them in for now. + unsigned int rgb[4]; + GetRGB(type,mface,mmcol,mat,rgb); - if (map.uvCoName.IsEmpty()) { - isFirstSet = false; - } - else { - for (int lay=0; lay<MAX_MTFACE; lay++) { - MTF_localLayer& layer = layers[lay]; - if (layer.face == 0) break; - - if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) { - if (isFirstSet) { - layer_uv[0] = lay; - isFirstSet = false; - uvName = layer.name; - } - else if (strcmp(layer.name, uvName) != 0) { - layer_uv[1] = lay; - map.mapping |= USECUSTOMUV; - uv2Name = layer.name; - } - } - } - } - } - } - - if (validmat && mmcol) { /* color is only for text */ - material->m_mcol = *(unsigned int *)mmcol; + // swap the material color, so MCol on bitmap font works + if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT)) + { + rgb[0] = KX_rgbaint2uint_new(rgb[0]); + rgb[1] = KX_rgbaint2uint_new(rgb[1]); + rgb[2] = KX_rgbaint2uint_new(rgb[2]); + rgb[3] = KX_rgbaint2uint_new(rgb[3]); } - material->SetUVLayerName(uvName); - material->SetUVLayerName2(uv2Name); if (validmat) material->matname =(mat->id.name); @@ -879,8 +881,189 @@ static bool ConvertMaterial( return true; } +RAS_MaterialBucket* material_from_mesh(Material *ma, MFace *mface, MTFace *tface, MCol *mcol, MTF_localLayer *layers, int lightlayer, unsigned int *rgb, MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT], const char *tfaceName, KX_Scene* scene, KX_BlenderSceneConverter *converter) +{ + RAS_IPolyMaterial* polymat = converter->FindCachedPolyMaterial(ma); + BL_Material* bl_mat = converter->FindCachedBlenderMaterial(ma); + KX_BlenderMaterial* kx_blmat = NULL; + KX_PolygonMaterial* kx_polymat = NULL; + + if (converter->GetMaterials()) { + /* do Blender Multitexture and Blender GLSL materials */ + + /* first is the BL_Material */ + if (!bl_mat) + { + bl_mat = new BL_Material(); + + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, + converter->GetGLSLMaterials()); + + converter->CacheBlenderMaterial(ma, bl_mat); + } + + + short type = (ma) ? ((ma->mode & MA_VERTEXCOLP || bl_mat->glslmat) ? 0 : 1) : 0; + GetRGB(type,mface,mcol,ma,rgb); + + GetUVs(bl_mat, layers, mface, tface, uvs); + + /* then the KX_BlenderMaterial */ + if (polymat == NULL) + { + kx_blmat = new KX_BlenderMaterial(); + + kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer); + polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat); + converter->CachePolyMaterial(ma, polymat); + } + } + else { + /* do Texture Face materials */ + Image* bima = (tface)? (Image*)tface->tpage: NULL; + STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; + + char alpha_blend=0; + short tile=0; + int tilexrep=4,tileyrep = 4; + + /* set material properties - old TexFace */ + if (ma) { + alpha_blend = ma->game.alpha_blend; + /* Commented out for now. If we ever get rid of + * "Texture Face/Singletexture" we can then think about it */ + + /* Texture Face mode ignores texture but requires "Face Textures to be True "*/ + #if 0 + if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) { + bima = NULL; + imastr = ""; + alpha_blend = GEMAT_SOLID; + } + else { + alpha_blend = ma->game.alpha_blend; + } + #endif + } + /* check for tface tex to fallback on */ + else { + if (bima) { + /* see if depth of the image is 32 */ + if (BKE_image_has_alpha(bima)) + alpha_blend = GEMAT_ALPHA; + else + alpha_blend = GEMAT_SOLID; + } + else { + alpha_blend = GEMAT_SOLID; + } + } + + if (bima) { + tilexrep = bima->xrep; + tileyrep = bima->yrep; + } + + /* set UV properties */ + if (tface) { + uvs[0][0].setValue(tface->uv[0]); + uvs[1][0].setValue(tface->uv[1]); + uvs[2][0].setValue(tface->uv[2]); + + if (mface->v4) + uvs[3][0].setValue(tface->uv[3]); + + tile = tface->tile; + } + else { + /* no texfaces */ + tile = 0; + } + + /* get vertex colors */ + if (mcol) { + /* we have vertex colors */ + rgb[0] = KX_Mcol2uint_new(mcol[0]); + rgb[1] = KX_Mcol2uint_new(mcol[1]); + rgb[2] = KX_Mcol2uint_new(mcol[2]); + + if (mface->v4) + rgb[3] = KX_Mcol2uint_new(mcol[3]); + } + else { + /* no vertex colors, take from material, otherwise white */ + unsigned int color = 0xFFFFFFFFL; + + if (ma) + { + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + + col_converter.cp[3] = (unsigned char) (ma->r*255.0); + col_converter.cp[2] = (unsigned char) (ma->g*255.0); + col_converter.cp[1] = (unsigned char) (ma->b*255.0); + col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); + + color = col_converter.integer; + } + + rgb[0] = KX_rgbaint2uint_new(color); + rgb[1] = KX_rgbaint2uint_new(color); + rgb[2] = KX_rgbaint2uint_new(color); + + if (mface->v4) + rgb[3] = KX_rgbaint2uint_new(color); + } + + // only zsort alpha + add + bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT); + bool zsort = (alpha_blend == GEMAT_ALPHA_SORT); + bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode; + + // don't need zort anymore, deal as if it it's alpha blend + if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA; + + if (polymat == NULL) + { + kx_polymat = new KX_PolygonMaterial(); + kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr, + tile, tilexrep, tileyrep, + alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol); + polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat); + + if (ma) { + polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; + polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512 + polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + } + else { + polymat->m_specular.setValue(0.0f,0.0f,0.0f); + polymat->m_shininess = 35.0; + } + + converter->CachePolyMaterial(ma, polymat); + } + } + + // see if a bucket was reused or a new one was created + // this way only one KX_BlenderMaterial object has to exist per bucket + bool bucketCreated; + RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); + if (bucketCreated) { + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); + if (converter->GetMaterials()) + converter->RegisterBlenderMaterial(bl_mat); + } + + return bucket; +} + /* blenderobj can be NULL, make sure its checked for */ -RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter) +RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter, bool libloading) { RAS_MeshObject *meshobj; int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object. @@ -910,7 +1093,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; - int layer_uv[2]; /* store uv1, uv2 layers */ for (int lay=0; lay<MAX_MTFACE; lay++) { layers[lay].face = 0; layers[lay].name = ""; @@ -933,31 +1115,23 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, meshobj->SetName(mesh->id.name + 2); meshobj->m_sharedvertex_map.resize(totvert); - RAS_IPolyMaterial* polymat = NULL; - STR_String imastr; - // These pointers will hold persistent material structure during the conversion - // to avoid countless allocation/deallocation of memory. - BL_Material* bl_mat = NULL; - KX_BlenderMaterial* kx_blmat = NULL; - KX_PolygonMaterial* kx_polymat = NULL; - for (int f=0;f<totface;f++,mface++) - { - Material* ma = 0; - bool collider = true; - MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); - MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); - unsigned int rgb0,rgb1,rgb2,rgb3 = 0; + Material* ma = 0; + bool collider = true; + MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; + unsigned int rgb[4] = {0}; - MT_Point3 pt0, pt1, pt2, pt3; - MT_Vector3 no0(0,0,0), no1(0,0,0), no2(0,0,0), no3(0,0,0); - MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0); + MT_Point3 pt[4]; + MT_Vector3 no[4]; + MT_Vector4 tan[4]; + for (int f=0;f<totface;f++,mface++) + { /* get coordinates, normals and tangents */ - pt0.setValue(mvert[mface->v1].co); - pt1.setValue(mvert[mface->v2].co); - pt2.setValue(mvert[mface->v3].co); - if (mface->v4) pt3.setValue(mvert[mface->v4].co); + pt[0].setValue(mvert[mface->v1].co); + pt[1].setValue(mvert[mface->v2].co); + pt[2].setValue(mvert[mface->v3].co); + if (mface->v4) pt[3].setValue(mvert[mface->v4].co); if (mface->flag & ME_SMOOTH) { float n0[3], n1[3], n2[3], n3[3]; @@ -965,13 +1139,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, normal_short_to_float_v3(n0, mvert[mface->v1].no); normal_short_to_float_v3(n1, mvert[mface->v2].no); normal_short_to_float_v3(n2, mvert[mface->v3].no); - no0 = n0; - no1 = n1; - no2 = n2; + no[0] = n0; + no[1] = n1; + no[2] = n2; if (mface->v4) { normal_short_to_float_v3(n3, mvert[mface->v4].no); - no3 = n3; + no[3] = n3; } } else { @@ -982,16 +1156,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, else normal_tri_v3(fno,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co); - no0 = no1 = no2 = no3 = MT_Vector3(fno); + no[0] = no[1] = no[2] = no[3] = MT_Vector3(fno); } if (tangent) { - tan0 = tangent[f*4 + 0]; - tan1 = tangent[f*4 + 1]; - tan2 = tangent[f*4 + 2]; + tan[0] = tangent[f*4 + 0]; + tan[1] = tangent[f*4 + 1]; + tan[2] = tangent[f*4 + 2]; if (mface->v4) - tan3 = tangent[f*4 + 3]; + tan[3] = tangent[f*4 + 3]; } if (blenderobj) ma = give_current_material(blenderobj, mface->mat_nr+1); @@ -1007,171 +1181,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, bool visible = true; bool twoside = false; - if (converter->GetMaterials()) { - const bool is_bl_mat_new = (bl_mat == NULL); - //const bool is_kx_blmat_new = (kx_blmat == NULL); - const bool glslmat = converter->GetGLSLMaterials(); - const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true; - /* do Blender Multitexture and Blender GLSL materials */ - MT_Point2 uv_1[4]; - MT_Point2 uv_2[4]; - - /* first is the BL_Material */ - if (!bl_mat) { - bl_mat = new BL_Material(); - } - - /* only */ - if (is_bl_mat_new || (bl_mat->material != ma)) { - ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, - layers, layer_uv, glslmat); - } - - /* vertex colors and uv's from the faces */ - GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3); - GetUV(mface, tface, layers, layer_uv, uv_1, uv_2); - - uv0 = uv_1[0]; uv1 = uv_1[1]; - uv2 = uv_1[2]; uv3 = uv_1[3]; - - uv20 = uv_2[0]; uv21 = uv_2[1]; - uv22 = uv_2[2]; uv23 = uv_2[3]; - - /* then the KX_BlenderMaterial */ - if (kx_blmat == NULL) - kx_blmat = new KX_BlenderMaterial(); - - //if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) { - kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL)); - //} - - polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat); - } - else { - /* do Texture Face materials */ - Image* bima = (tface)? (Image*)tface->tpage: NULL; - imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - - char alpha_blend=0; - short tile=0; - int tilexrep=4,tileyrep = 4; - - /* set material properties - old TexFace */ - if (ma) { - alpha_blend = ma->game.alpha_blend; - /* Commented out for now. If we ever get rid of - * "Texture Face/Singletexture" we can then think about it */ - - /* Texture Face mode ignores texture but requires "Face Textures to be True "*/ -#if 0 - if ((ma->mode &MA_FACETEXTURE)==0 && (ma->game.flag &GEMAT_TEXT)==0) { - bima = NULL; - imastr = ""; - alpha_blend = GEMAT_SOLID; - } - else { - alpha_blend = ma->game.alpha_blend; - } -#endif - } - /* check for tface tex to fallback on */ - else { - if (bima) { - /* see if depth of the image is 32 */ - if (BKE_image_has_alpha(bima)) - alpha_blend = GEMAT_ALPHA; - else - alpha_blend = GEMAT_SOLID; - } - else { - alpha_blend = GEMAT_SOLID; - } - } - - if (bima) { - tilexrep = bima->xrep; - tileyrep = bima->yrep; - } - - /* set UV properties */ - if (tface) { - uv0.setValue(tface->uv[0]); - uv1.setValue(tface->uv[1]); - uv2.setValue(tface->uv[2]); - - if (mface->v4) - uv3.setValue(tface->uv[3]); - - tile = tface->tile; - } - else { - /* no texfaces */ - tile = 0; - } - - /* get vertex colors */ - if (mcol) { - /* we have vertex colors */ - rgb0 = KX_Mcol2uint_new(mcol[0]); - rgb1 = KX_Mcol2uint_new(mcol[1]); - rgb2 = KX_Mcol2uint_new(mcol[2]); - - if (mface->v4) - rgb3 = KX_Mcol2uint_new(mcol[3]); - } - else { - /* no vertex colors, take from material, otherwise white */ - unsigned int color = 0xFFFFFFFFL; - - if (ma) - { - union - { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - - col_converter.cp[3] = (unsigned char) (ma->r * 255.0f); - col_converter.cp[2] = (unsigned char) (ma->g * 255.0f); - col_converter.cp[1] = (unsigned char) (ma->b * 255.0f); - col_converter.cp[0] = (unsigned char) (ma->alpha * 255.0f); - - color = col_converter.integer; - } - - rgb0 = KX_rgbaint2uint_new(color); - rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(color); - } - - // only zsort alpha + add - bool alpha = ELEM3(alpha_blend, GEMAT_ALPHA, GEMAT_ADD, GEMAT_ALPHA_SORT); - bool zsort = (alpha_blend == GEMAT_ALPHA_SORT); - bool light = (ma)?(ma->mode & MA_SHLESS)==0:default_light_mode; - - // don't need zort anymore, deal as if it it's alpha blend - if (alpha_blend == GEMAT_ALPHA_SORT) alpha_blend = GEMAT_ALPHA; - - if (kx_polymat == NULL) - kx_polymat = new KX_PolygonMaterial(); - kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr, - tile, tilexrep, tileyrep, - alpha_blend, alpha, zsort, light, lightlayer, tface, (unsigned int*)mcol); - polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat); - - if (ma) { - polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; - polymat->m_shininess = (float)ma->har/4.0f; // 0 < ma->har <= 512 - polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); - } - else { - polymat->m_specular.setValue(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.0; - } - } + RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter); // set render flags if (ma) @@ -1188,30 +1198,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, /* mark face as flat, so vertices are split */ bool flat = (mface->flag & ME_SMOOTH) == 0; - - // see if a bucket was reused or a new one was created - // this way only one KX_BlenderMaterial object has to exist per bucket - bool bucketCreated; - RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); - if (bucketCreated) { - // this is needed to free up memory afterwards - converter->RegisterPolyMaterial(polymat); - if (converter->GetMaterials()) { - converter->RegisterBlenderMaterial(bl_mat); - // the poly material has been stored in the bucket, next time we must create a new one - bl_mat = NULL; - kx_blmat = NULL; - } else { - // the poly material has been stored in the bucket, next time we must create a new one - kx_polymat = NULL; - } - } else { - // from now on, use the polygon material from the material bucket - polymat = bucket->GetPolyMaterial(); - // keep the material pointers, they will be reused for next face - } - + int nverts = (mface->v4)? 4: 3; + RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); poly->SetVisible(visible); @@ -1219,12 +1208,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, poly->SetTwoside(twoside); //poly->SetEdgeCode(mface->edcode); - meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1); - meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2); - meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3); + meshobj->AddVertex(poly,0,pt[0],uvs[0],tan[0],rgb[0],no[0],flat,mface->v1); + meshobj->AddVertex(poly,1,pt[1],uvs[1],tan[1],rgb[1],no[1],flat,mface->v2); + meshobj->AddVertex(poly,2,pt[2],uvs[2],tan[2],rgb[2],no[2],flat,mface->v3); if (nverts==4) - meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4); + meshobj->AddVertex(poly,3,pt[3],uvs[3],tan[3],rgb[3],no[3],flat,mface->v4); } if (tface) @@ -1246,22 +1235,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, meshobj->EndConversion(); // pre calculate texture generation - for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial(); - mit != meshobj->GetLastMaterial(); ++ mit) { - mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer); + // However, we want to delay this if we're libloading so we can make sure we have the right scene. + if (!libloading) { + for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial(); + mit != meshobj->GetLastMaterial(); ++ mit) { + mit->m_bucket->GetPolyMaterial()->OnConstruction(); + } } if (layers) delete []layers; dm->release(dm); - // cleanup material - if (bl_mat) - delete bl_mat; - if (kx_blmat) - delete kx_blmat; - if (kx_polymat) - delete kx_polymat; + converter->RegisterGameMesh(meshobj, mesh); return meshobj; } @@ -1921,7 +1907,8 @@ static KX_GameObject *gameobject_from_blenderobject( Object *ob, KX_Scene *kxscene, RAS_IRenderTools *rendertools, - KX_BlenderSceneConverter *converter) + KX_BlenderSceneConverter *converter, + bool libloading) { KX_GameObject *gameobj = NULL; Scene *blenderscene = kxscene->GetBlenderScene(); @@ -1958,7 +1945,7 @@ static KX_GameObject *gameobject_from_blenderobject( Mesh* mesh = static_cast<Mesh*>(ob->data); float center[3], extents[3]; float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents); - RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter); + RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,kxscene,converter, libloading); // needed for python scripting kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); @@ -2332,7 +2319,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, RAS_IRenderTools* rendertools, RAS_ICanvas* canvas, KX_BlenderSceneConverter* converter, - bool alwaysUseExpandFraming + bool alwaysUseExpandFraming, + bool libloading ) { @@ -2442,7 +2430,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, base->object, kxscene, rendertools, - converter); + converter, + libloading); bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0; bool addobj=true; @@ -2501,7 +2490,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, blenderobject, kxscene, rendertools, - converter); + converter, + libloading); // this code is copied from above except that // object from groups are never in active layer diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h index 2a7efaac898..f3a680929fb 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.h +++ b/source/gameengine/Converter/BL_BlenderDataConversion.h @@ -38,7 +38,7 @@ #include "KX_PhysicsEngineEnums.h" #include "SCA_IInputDevice.h" -class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter); +class RAS_MeshObject* BL_ConvertMesh(struct Mesh* mesh,struct Object* lightobj,class KX_Scene* scene, class KX_BlenderSceneConverter *converter, bool libloading); void BL_ConvertBlenderObjects(struct Main* maggie, class KX_Scene* kxscene, @@ -47,7 +47,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, class RAS_IRenderTools* rendertools, class RAS_ICanvas* canvas, class KX_BlenderSceneConverter* sceneconverter, - bool alwaysUseExpandFraming + bool alwaysUseExpandFraming, + bool libloading=false ); SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index d1684db0f5a..260ca9ede96 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -151,6 +151,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { + m_polymat_cache.erase((*itp).second->GetBlenderMaterial()); delete (*itp).second; itp++; } @@ -158,6 +159,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() // delete after RAS_IPolyMaterial vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { + m_mat_cache.erase((*itmat).second->material); delete (*itmat).second; itmat++; } @@ -286,7 +288,8 @@ struct BlenderDebugDraw : public btIDebugDraw void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, class RAS_IRenderTools* rendertools, - class RAS_ICanvas* canvas) + class RAS_ICanvas* canvas, + bool libloading) { //find out which physics engine Scene *blenderscene = destinationscene->GetBlenderScene(); @@ -355,7 +358,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, rendertools, canvas, this, - m_alwaysUseExpandFraming + m_alwaysUseExpandFraming, + libloading ); //These lookup are not needed during game @@ -406,6 +410,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) size = m_polymaterials.size(); for (i=0, polymit=m_polymaterials.begin(); i<size; ) { if ((*polymit).first == scene) { + m_polymat_cache.erase((*polymit).second->GetBlenderMaterial()); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); @@ -420,6 +425,7 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) size = m_materials.size(); for (i=0, matit=m_materials.begin(); i<size; ) { if ((*matit).first == scene) { + m_mat_cache.erase((*matit).second->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); @@ -470,6 +476,12 @@ bool KX_BlenderSceneConverter::GetGLSLMaterials() void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) { + // First make sure we don't register the material twice + vector<pair<KX_Scene*,BL_Material*> >::iterator it; + for (it = m_materials.begin(); it != m_materials.end(); ++it) + if (it->second == mat) + return; + m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat)); } @@ -540,19 +552,37 @@ RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( } else { return NULL; } -} - - - - - +} void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { + // First make sure we don't register the material twice + vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it; + for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) + if (it->second == polymat) + return; m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat)); } +void KX_BlenderSceneConverter::CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat) +{ + m_polymat_cache[mat] = polymat; +} + +RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(struct Material *mat) +{ + return m_polymat_cache[mat]; +} +void KX_BlenderSceneConverter::CacheBlenderMaterial(struct Material *mat, BL_Material *blmat) +{ + m_mat_cache[mat] = blmat; +} + +BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(struct Material *mat) +{ + return m_mat_cache[mat]; +} void KX_BlenderSceneConverter::RegisterInterpolatorList( BL_InterpolatorList *actList, @@ -1016,7 +1046,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) printf("MeshName: %s\n", mesh->name+2); - RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this); + RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); } } @@ -1038,7 +1068,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha printf("SceneName: %s\n", scene->name+2); /* merge into the base scene */ - KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene); + KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene @@ -1302,7 +1332,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } if (IS_TAGGED(bmat)) { - + m_polymat_cache.erase((*polymit).second->GetBlenderMaterial()); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); @@ -1320,6 +1350,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) for (i=0, matit=m_materials.begin(); i<size; ) { BL_Material *mat= (*matit).second; if (IS_TAGGED(mat->material)) { + m_mat_cache.erase((*matit).second->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); @@ -1469,7 +1500,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, } } - RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this); + RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this, false); kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */ return meshobj; diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index 34a1117a0eb..eddb377dbc7 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -39,6 +39,8 @@ #include "KX_ISceneConverter.h" #include "KX_IpoConvert.h" +#include <map> + using namespace std; class KX_WorldInfo; @@ -58,6 +60,11 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter vector<pair<KX_Scene*,RAS_IPolyMaterial*> > m_polymaterials; vector<pair<KX_Scene*,RAS_MeshObject*> > m_meshobjects; vector<pair<KX_Scene*,BL_Material *> > m_materials; + + // Cached material conversions + map<struct Material*, BL_Material*> m_mat_cache; + map<struct Material*, RAS_IPolyMaterial*> m_polymat_cache; + // Should also have a list of collision shapes. // For the time being this is held in KX_Scene::m_shapes @@ -93,7 +100,8 @@ public: virtual void ConvertScene( class KX_Scene* destinationscene, class RAS_IRenderTools* rendertools, - class RAS_ICanvas* canvas + class RAS_ICanvas* canvas, + bool libloading=false ); virtual void RemoveScene(class KX_Scene *scene); @@ -110,8 +118,12 @@ public: RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh/*, unsigned int onlayer*/); void RegisterPolyMaterial(RAS_IPolyMaterial *polymat); + void CachePolyMaterial(struct Material *mat, RAS_IPolyMaterial *polymat); + RAS_IPolyMaterial *FindCachedPolyMaterial(struct Material *mat); void RegisterBlenderMaterial(BL_Material *mat); + void CacheBlenderMaterial(struct Material *mat, BL_Material *blmat); + BL_Material *FindCachedBlenderMaterial(struct Material *mat); void RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act); BL_InterpolatorList *FindInterpolatorList(struct bAction *for_act); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 06399642edd..695bf0c4dc8 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -523,7 +523,8 @@ void BL_ConvertActuators(const char* maggiename, editobact->me, blenderobject, scene, - converter + converter, + false ); KX_SCA_ReplaceMeshActuator* tmpreplaceact = new KX_SCA_ReplaceMeshActuator( diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 92db1fe790e..1dcc68c8e75 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -76,7 +76,6 @@ extern "C" #include "SCA_IActuator.h" #include "RAS_MeshObject.h" #include "RAS_OpenGLRasterizer.h" -#include "RAS_VAOpenGLRasterizer.h" #include "RAS_ListRasterizer.h" #include "RAS_GLExtensionManager.h" #include "KX_PythonInit.h" @@ -582,16 +581,12 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_rendertools) goto initFailed; - if (useLists) { - if (GLEW_VERSION_1_1) - m_rasterizer = new RAS_ListRasterizer(m_canvas, true); - else - m_rasterizer = new RAS_ListRasterizer(m_canvas); - } - else if (GLEW_VERSION_1_1) - m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas); + //Don't use displaylists with VBOs + //If auto starts using VBOs, make sure to check for that here + if (useLists && gm->raster_storage != RAS_STORE_VBO) + m_rasterizer = new RAS_ListRasterizer(m_canvas, false, gm->raster_storage); else - m_rasterizer = new RAS_OpenGLRasterizer(m_canvas); + m_rasterizer = new RAS_OpenGLRasterizer(m_canvas, gm->raster_storage); /* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */ m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 23bfd7a111b..64e191fe960 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -95,21 +95,15 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) ras->SetTexCoordNum(0); ras->SetAttribNum(attrib_num); - for (i=0; i<attrib_num; i++) + for (i = 0; i < attrib_num; i++) ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); for (i = 0; i < attribs.totlayer; i++) { if (attribs.layer[i].glindex > attrib_num) continue; - if (attribs.layer[i].type == CD_MTFACE) { - if (!mat->uvName.IsEmpty() && strcmp(mat->uvName.ReadPtr(), attribs.layer[i].name) == 0) - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); - else if (!mat->uv2Name.IsEmpty() && strcmp(mat->uv2Name.ReadPtr(), attribs.layer[i].name) == 0) - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV2, attribs.layer[i].glindex); - else - ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV1, attribs.layer[i].glindex); - } + if (attribs.layer[i].type == CD_MTFACE) + ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_UV, attribs.layer[i].glindex); else if (attribs.layer[i].type == CD_TANGENT) ras->SetAttrib(RAS_IRasterizer::RAS_TEXTANGENT, attribs.layer[i].glindex); else if (attribs.layer[i].type == CD_ORCO) diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 0954aa0f7ab..461a8c51a52 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -20,15 +20,6 @@ MTex* getImageFromMaterial(Material *mat, int index) return m?m:0; } -int getNumTexChannels( Material *mat ) -{ - int count = -1; - if (!mat) return -1; - - for (count =0; (count < 10) && mat->mtex[count] != 0; count++) {} - return count; -} - BL_Material::BL_Material() { Initialize(); @@ -36,7 +27,10 @@ BL_Material::BL_Material() void BL_Material::Initialize() { - m_mcol = 0xFFFFFFFFL; + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 0; + rgb[3] = 0; IdMode = 0; ras_mode = 0; glslmat = 0; @@ -64,7 +58,7 @@ void BL_Material::Initialize() int i; - for (i=0; i<MAXTEX; i++) // :( + for (i = 0; i < MAXTEX; i++) // :( { mapping[i].mapping = 0; mapping[i].offsets[0] = 0.f; @@ -90,15 +84,6 @@ void BL_Material::Initialize() } } -void BL_Material::SetUVLayerName(const STR_String& name) -{ - uvName = name; -} -void BL_Material::SetUVLayerName2(const STR_String& name) -{ - uv2Name = name; -} - void BL_Material::SetSharedMaterial(bool v) { if ((v && num_users == -1) || num_users > 1 ) diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index ef180ed2126..0383c0891b6 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -87,13 +87,8 @@ public: MTFace tface; /* copy of the derived meshes tface */ Image* img[MAXTEX]; EnvMap* cubemap[MAXTEX]; - unsigned int m_mcol; /* for text color (only) */ - STR_String uvName; - STR_String uv2Name; - - void SetUVLayerName(const STR_String &name); - void SetUVLayerName2(const STR_String &name); + unsigned int rgb[4]; void SetSharedMaterial(bool v); bool IsShared(); @@ -180,7 +175,6 @@ enum BL_MappingProj // ------------------------------------ //extern void initBL_Material(BL_Material* mat); extern MTex* getImageFromMaterial(Material *mat, int index); -extern int getNumTexChannels( Material *mat ); // ------------------------------------ #endif diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 66423ed820e..98fff5c8b65 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -60,6 +60,7 @@ public: typedef std::map<char*, BL_TextureObject> BL_TextureMap; static BL_TextureMap g_textureManager; +static GLint g_max_units = -1; BL_Texture::BL_Texture() @@ -379,14 +380,17 @@ unsigned int BL_Texture::GetTextureType() const int BL_Texture::GetMaxUnits() { - GLint unit=0; - - if (GLEW_ARB_multitexture) { - glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit); - return (MAXTEX>=unit?unit:MAXTEX); + if (g_max_units < 0) { + GLint unit; + if (GLEW_ARB_multitexture) { + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit); + g_max_units = (MAXTEX>=unit)?unit:MAXTEX; + } else { + g_max_units = 0; + } } - return 0; + return g_max_units; } void BL_Texture::ActivateFirst() diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 20c36c2cc44..a55dd701826 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -60,7 +60,8 @@ KX_BlenderMaterial::KX_BlenderMaterial() void KX_BlenderMaterial::Initialize( KX_Scene *scene, BL_Material *data, - GameSettings *game) + GameSettings *game, + int lightlayer) { RAS_IPolyMaterial::Initialize( data->texname[0], @@ -84,6 +85,7 @@ void KX_BlenderMaterial::Initialize( mModified = 0; mConstructed = false; mPass = 0; + mLightLayer = lightlayer; // -------------------------------- // RAS_IPolyMaterial variables... m_flag |= RAS_BLENDERMAT; @@ -92,16 +94,11 @@ void KX_BlenderMaterial::Initialize( m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0; - // figure max - int enabled = mMaterial->num_enabled; - int max = BL_Texture::GetMaxUnits(); - mMaterial->num_enabled = enabled>=max?max:enabled; - // test the sum of the various modes for equality // so we can ether accept or reject this material // as being equal, this is rather important to // prevent material bleeding - for (int i=0; i<mMaterial->num_enabled; i++) { + for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]); } m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(USE_LIGHT)); @@ -124,7 +121,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const unsigned int* KX_BlenderMaterial::GetMCol(void) const { // fonts on polys - return &mMaterial->m_mcol; + return mMaterial->rgb; } void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const @@ -138,11 +135,6 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } -bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const -{ - return (mMaterial == bl_mat); -} - Material *KX_BlenderMaterial::GetBlenderMaterial() const { return mMaterial->material; @@ -163,7 +155,7 @@ void KX_BlenderMaterial::InitTextures() { // for each unique material... int i; - for (i=0; i<mMaterial->num_enabled; i++) { + for (i=0; i<BL_Texture::GetMaxUnits(); i++) { if ( mMaterial->mapping[i].mapping & USEENV ) { if (!GLEW_ARB_texture_cube_map) { spit("CubeMap textures not supported"); @@ -185,14 +177,14 @@ void KX_BlenderMaterial::InitTextures() } } -void KX_BlenderMaterial::OnConstruction(int layer) +void KX_BlenderMaterial::OnConstruction() { if (mConstructed) // when material are reused between objects return; if (mMaterial->glslmat) - SetBlenderGLSLShader(layer); + SetBlenderGLSLShader(); InitTextures(); @@ -239,7 +231,8 @@ void KX_BlenderMaterial::OnExit() } BL_Texture::ActivateFirst(); - for (int i=0; i<mMaterial->num_enabled; i++) { + for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { + if (!mTextures[i].Ok()) continue; BL_Texture::ActivateUnit(i); mTextures[i].DeleteTex(); mTextures[i].DisableUnit(); @@ -278,7 +271,7 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) mShader->ApplyShader(); // for each enabled unit - for (i=0; i<mMaterial->num_enabled; i++) { + for (i=0; i<BL_Texture::GetMaxUnits(); i++) { if (!mTextures[i].Ok()) continue; mTextures[i].ActivateTexture(); mTextures[0].SetMapping(mMaterial->mapping[i].mapping); @@ -354,7 +347,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) } int mode = 0,i=0; - for (i=0; (i<mMaterial->num_enabled && i<MAXTEX); i++) { + for (i=0; i<BL_Texture::GetMaxUnits(); i++) { if ( !mTextures[i].Ok() ) continue; mTextures[i].ActivateTexture(); @@ -647,16 +640,9 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const ras->SetTexCoordNum(mMaterial->num_enabled); - for (int i=0; i<mMaterial->num_enabled; i++) { + for (int i=0; i<BL_Texture::GetMaxUnits(); i++) { int mode = mMaterial->mapping[i].mapping; - if (mode &USECUSTOMUV) - { - if (!mMaterial->mapping[i].uvCoName.IsEmpty()) - ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i); - continue; - } - if ( mode &(USEREFL|USEOBJ)) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_GEN, i); else if (mode &USEORCO) @@ -664,7 +650,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const else if (mode &USENORM) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_NORM, i); else if (mode &USEUV) - ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV1, i); + ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV, i); else if (mode &USETANG) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXTANGENT, i); else @@ -790,10 +776,19 @@ void KX_BlenderMaterial::UpdateIPO( mMaterial->ref = (float)(ref); } -void KX_BlenderMaterial::SetBlenderGLSLShader(int layer) +void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) +{ + mScene= static_cast<KX_Scene *>(val); + if (mBlenderShader) + mBlenderShader->SetScene(mScene); + + OnConstruction(); +} + +void KX_BlenderMaterial::SetBlenderGLSLShader() { if (!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer); + mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, mLightLayer); if (!mBlenderShader->Ok()) { delete mBlenderShader; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 7bc9c7c3863..c34a49e1bde 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -39,7 +39,8 @@ public: void Initialize( class KX_Scene* scene, BL_Material* mat, - GameSettings* game + GameSettings* game, + int lightlayer ); virtual ~KX_BlenderMaterial(); @@ -76,8 +77,6 @@ public: TCachingInfo& cachingInfo )const; - /* mMaterial is private, but need this for conversion */ - bool IsMaterial(const BL_Material *bl_mat) const; Material* GetBlenderMaterial() const; MTFace* GetMTFace(void) const; unsigned int* GetMCol(void) const; @@ -97,14 +96,7 @@ public: MT_Scalar ref, MT_Scalar emit, MT_Scalar alpha ); - virtual void Replace_IScene(SCA_IScene *val) - { - mScene= static_cast<KX_Scene *>(val); - if (mBlenderShader) - { - mBlenderShader->SetScene(mScene); - } - }; + virtual void Replace_IScene(SCA_IScene *val); #ifdef WITH_PYTHON // -------------------------------- @@ -125,7 +117,7 @@ public: // -------------------------------- // pre calculate to avoid pops/lag at startup - virtual void OnConstruction(int layer); + virtual void OnConstruction(); static void EndFrame(); @@ -139,10 +131,11 @@ private: unsigned int mBlendFunc[2]; bool mModified; bool mConstructed; // if false, don't clean on exit + int mLightLayer; void InitTextures(); - void SetBlenderGLSLShader(int layer); + void SetBlenderGLSLShader(); void ActivatGLMaterials( RAS_IRasterizer* rasty )const; void ActivateTexGen( RAS_IRasterizer *ras ) const; diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index 18fb336dbe0..0dbfd7de2c6 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -57,7 +57,8 @@ public: virtual void ConvertScene( class KX_Scene* destinationscene, class RAS_IRenderTools* rendertools, - class RAS_ICanvas* canvas)=0; + class RAS_ICanvas* canvas, + bool libloading=false)=0; virtual void RemoveScene(class KX_Scene *scene)=0; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index a12e12ccef2..890b9d4c472 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1686,7 +1686,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes() } } -KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene) +KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene, bool libloading) { KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice, m_mousedevice, @@ -1697,7 +1697,8 @@ KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene) m_sceneconverter->ConvertScene(tmpscene, m_rendertools, - m_canvas); + m_canvas, + libloading); return tmpscene; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 972594bd90f..92ffaf47aa4 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -413,7 +413,7 @@ public: void GetOverrideFrameColor(float& r, float& g, float& b) const; KX_Scene* CreateScene(const STR_String& scenename); - KX_Scene* CreateScene(Scene *scene); + KX_Scene* CreateScene(Scene *scene, bool libloading=false); GlobalSettings* GetGlobalSettings(void); void SetGlobalSettings(GlobalSettings* gs); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index d83e98d4712..57695df2782 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -338,20 +338,20 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) for (i = it.startvertex; i < it.endvertex; i++) { RAS_TexVert *vert = &it.vertex[i]; if (uvindex_from != -1) { - if (uvindex_from == 0) vert->SetUV2(vert->getUV1()); - else vert->SetUV1(vert->getUV2()); + if (uvindex_from == 0) vert->SetUV(1, vert->getUV(0)); + else vert->SetUV(0, vert->getUV(1)); } switch (uvindex) { case 0: - vert->TransformUV1(transform); + vert->TransformUV(0, transform); break; case 1: - vert->TransformUV2(transform); + vert->TransformUV(1, transform); break; case -1: - vert->TransformUV1(transform); - vert->TransformUV2(transform); + vert->TransformUV(0, transform); + vert->TransformUV(1, transform); break; } } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index f157d9ed20a..5ce370ccdfe 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize( m_mcol = *mcol; } else { - m_mcol = 0; + memset(&m_mcol, 0, sizeof(m_mcol)); } m_material = ma; diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 2ce8f480c1c..89bfb4ff9fb 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial private: /** Blender texture face structure. */ mutable MTFace m_tface; - mutable unsigned int m_mcol; /* for text color (only) */ + mutable unsigned int m_mcol; Material* m_material; #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 2354359af18..ab73ba1902a 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -94,6 +94,7 @@ PyAttributeDef KX_VertexProxy::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("XYZ", KX_VertexProxy, pyattr_get_XYZ, pyattr_set_XYZ), KX_PYATTRIBUTE_RW_FUNCTION("UV", KX_VertexProxy, pyattr_get_UV, pyattr_set_UV), + KX_PYATTRIBUTE_RW_FUNCTION("uvs", KX_VertexProxy, pyattr_get_uvs, pyattr_set_uvs), KX_PYATTRIBUTE_RW_FUNCTION("color", KX_VertexProxy, pyattr_get_color, pyattr_set_color), KX_PYATTRIBUTE_RW_FUNCTION("normal", KX_VertexProxy, pyattr_get_normal, pyattr_set_normal), @@ -146,25 +147,25 @@ PyObject *KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *a PyObject *KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV1()[0]); + return PyFloat_FromDouble(self->m_vertex->getUV(0)[0]); } PyObject *KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV1()[1]); + return PyFloat_FromDouble(self->m_vertex->getUV(0)[1]); } PyObject *KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV2()[0]); + return PyFloat_FromDouble(self->m_vertex->getUV(1)[0]); } PyObject *KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); - return PyFloat_FromDouble(self->m_vertex->getUV2()[1]); + return PyFloat_FromDouble(self->m_vertex->getUV(1)[1]); } PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -176,7 +177,20 @@ PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF PyObject *KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); - return PyObjectFrom(MT_Point2(self->m_vertex->getUV1())); + return PyObjectFrom(MT_Point2(self->m_vertex->getUV(0))); +} + +PyObject *KX_VertexProxy::pyattr_get_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); + + PyObject* uvlist = PyList_New(RAS_TexVert::MAX_UNIT); + for (int i=0; i<RAS_TexVert::MAX_UNIT; ++i) + { + PyList_SET_ITEM(uvlist, i, PyObjectFrom(MT_Point2(self->m_vertex->getUV(i)))); + } + + return uvlist; } PyObject *KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -245,9 +259,9 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV1(); + MT_Point2 uv = self->m_vertex->getUV(0); uv[0] = val; - self->m_vertex->SetUV1(uv); + self->m_vertex->SetUV(0, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -260,9 +274,9 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV1(); + MT_Point2 uv = self->m_vertex->getUV(0); uv[1] = val; - self->m_vertex->SetUV1(uv); + self->m_vertex->SetUV(0, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -275,9 +289,9 @@ int KX_VertexProxy::pyattr_set_u2(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV2(); + MT_Point2 uv = self->m_vertex->getUV(1); uv[0] = val; - self->m_vertex->SetUV2(uv); + self->m_vertex->SetUV(1, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -290,9 +304,9 @@ int KX_VertexProxy::pyattr_set_v2(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); - MT_Point2 uv = self->m_vertex->getUV2(); + MT_Point2 uv = self->m_vertex->getUV(1); uv[1] = val; - self->m_vertex->SetUV2(uv); + self->m_vertex->SetUV(1, uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -390,7 +404,7 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF { MT_Point2 vec; if (PyVecTo(value, vec)) { - self->m_vertex->SetUV1(vec); + self->m_vertex->SetUV(0, vec); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -398,6 +412,32 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF return PY_SET_ATTR_FAIL; } +int KX_VertexProxy::pyattr_set_uvs(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_VertexProxy* self= static_cast<KX_VertexProxy*>(self_v); + if (PySequence_Check(value)) + { + MT_Point2 vec; + for (int i=0; i<PySequence_Size(value) && i<RAS_TexVert::MAX_UNIT; ++i) + { + if (PyVecTo(PySequence_GetItem(value, i), vec)) + { + self->m_vertex->SetUV(i, vec); + self->m_mesh->SetMeshModified(true); + } + else + { + PyErr_SetString(PyExc_AttributeError, STR_String().Format("list[%d] was not a vector", i).ReadPtr()); + return PY_SET_ATTR_FAIL; + } + } + + self->m_mesh->SetMeshModified(true); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + int KX_VertexProxy::pyattr_set_color(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_VertexProxy* self = static_cast<KX_VertexProxy*>(self_v); @@ -522,7 +562,7 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) PyObject *KX_VertexProxy::PyGetUV1() { - return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); + return PyObjectFrom(MT_Vector2(m_vertex->getUV(0))); } PyObject *KX_VertexProxy::PySetUV1(PyObject *value) @@ -531,31 +571,23 @@ PyObject *KX_VertexProxy::PySetUV1(PyObject *value) if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetUV1(vec); + m_vertex->SetUV(0, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } PyObject *KX_VertexProxy::PyGetUV2() { - return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); + return PyObjectFrom(MT_Vector2(m_vertex->getUV(1))); } PyObject *KX_VertexProxy::PySetUV2(PyObject *args) { MT_Point2 vec; - unsigned int unit= RAS_TexVert::SECOND_UV; - - PyObject *list = NULL; - if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) - return NULL; - - if (!PyVecTo(list, vec)) + if (!PyVecTo(args, vec)) return NULL; - m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); - m_vertex->SetUnit(unit); - m_vertex->SetUV2(vec); + m_vertex->SetUV(1, vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 4247d138a66..8070825ad11 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -74,6 +74,7 @@ public: static PyObject *pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_uvs(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_x(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_y(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_z(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -89,6 +90,7 @@ public: static int pyattr_set_UV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_color(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_normal(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_uvs(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); 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(); |