diff options
Diffstat (limited to 'source/gameengine/Converter/BL_BlenderDataConversion.cpp')
-rw-r--r-- | source/gameengine/Converter/BL_BlenderDataConversion.cpp | 897 |
1 files changed, 654 insertions, 243 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index eb695e624e4..e568cf1fdf8 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -30,8 +30,8 @@ * \ingroup bgeconv */ -#ifdef _MSC_VER -# pragma warning (disable:4786) +#if defined(WIN32) && !defined(FREE_WINDOWS) +#pragma warning (disable : 4786) #endif #include <math.h> @@ -423,55 +423,62 @@ 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 +487,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 +558,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 +588,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 +596,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 ) { @@ -651,7 +683,7 @@ static bool ConvertMaterial( if (!material->cubemap[i]->cube[0]) BL_Texture::SplitEnvMap(material->cubemap[i]); - material->texname[i] = material->cubemap[i]->ima->id.name; + material->texname[i]= material->cubemap[i]->ima->id.name; material->mapping[i].mapping |= USEENV; } } @@ -701,7 +733,7 @@ static bool ConvertMaterial( material->mapping[i].projplane[2] = mttmp->projz; /// -------------------------------- - switch (mttmp->blendtype) { + switch( mttmp->blendtype ) { case MTEX_BLEND: material->blend_mode[i] = BLEND_MIX; break; @@ -725,7 +757,7 @@ static bool ConvertMaterial( // above one tex the switches here // are not used - switch (valid_index) { + switch(valid_index) { case 0: material->IdMode = DEFAULT_BLENDER; break; @@ -798,14 +830,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 +855,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 +882,405 @@ 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, bool libloading) +{ + RAS_MeshObject *meshobj; + int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object. + + if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL) + return meshobj; + // Get DerivedMesh data + DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); + DM_ensure_tessface(dm); + + MVert *mvert = dm->getVertArray(dm); + int totvert = dm->getNumVerts(dm); + + MFace *mface = dm->getTessFaceArray(dm); + MTFace *tface = static_cast<MTFace*>(dm->getTessFaceDataArray(dm, CD_MTFACE)); + MCol *mcol = static_cast<MCol*>(dm->getTessFaceDataArray(dm, CD_MCOL)); + float (*tangent)[4] = NULL; + int totface = dm->getNumTessFaces(dm); + const char *tfaceName = ""; + + if (tface) { + DM_add_tangent_layer(dm); + tangent = (float(*)[4])dm->getTessFaceDataArray(dm, CD_TANGENT); + } + + meshobj = new RAS_MeshObject(mesh); + + // Extract avaiable layers + MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; + for (int lay=0; lay<MAX_MTFACE; lay++) { + layers[lay].face = 0; + layers[lay].name = ""; + } + + int validLayers = 0; + for (int i=0; i<dm->faceData.totlayer; i++) + { + if (dm->faceData.layers[i].type == CD_MTFACE) + { + assert(validLayers <= 8); + + layers[validLayers].face = (MTFace*)(dm->faceData.layers[i].data); + layers[validLayers].name = dm->faceData.layers[i].name; + if (tface == layers[validLayers].face) + tfaceName = layers[validLayers].name; + validLayers++; + } + } + + meshobj->SetName(mesh->id.name + 2); + meshobj->m_sharedvertex_map.resize(totvert); + + Material* ma = 0; + bool collider = true; + MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; + unsigned int rgb[4] = {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 */ + 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]; + + 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); + no[0] = n0; + no[1] = n1; + no[2] = n2; + + if (mface->v4) { + normal_short_to_float_v3(n3, mvert[mface->v4].no); + no[3] = n3; + } + } + else { + float fno[3]; + + if (mface->v4) + normal_quad_v3(fno,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co); + else + normal_tri_v3(fno,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co); + + no[0] = no[1] = no[2] = no[3] = MT_Vector3(fno); + } + + if (tangent) { + tan[0] = tangent[f*4 + 0]; + tan[1] = tangent[f*4 + 1]; + tan[2] = tangent[f*4 + 2]; + + if (mface->v4) + tan[3] = tangent[f*4 + 3]; + } + + if (blenderobj) + ma = give_current_material(blenderobj, mface->mat_nr+1); + else + ma = mesh->mat ? mesh->mat[mface->mat_nr]:NULL; + + /* ckeck for texface since texface _only_ is used as a fallback */ + if (ma == NULL && tface == NULL) { + ma= &defmaterial; + } + + { + bool visible = true; + bool twoside = false; + + RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter); + + // set render flags + if (ma) + { + visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); + twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); + collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); + } + else{ + visible = true; + twoside = false; + collider = true; + } + + /* mark face as flat, so vertices are split */ + bool flat = (mface->flag & ME_SMOOTH) == 0; + +#ifdef GLES + // Force 3 verts on GLES + int nverts = 3; +#else + int nverts = (mface->v4)? 4: 3; +#endif + RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); + + poly->SetVisible(visible); + poly->SetCollider(collider); + poly->SetTwoside(twoside); + //poly->SetEdgeCode(mface->edcode); + + 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); + +#ifndef GLES + if (nverts==4) + meshobj->AddVertex(poly,3,pt[3],uvs[3],tan[3],rgb[3],no[3],flat,mface->v4); + + +#else + if(mface->v4) + { + // GLES doesn't support QUADs so we are spliiting a quad |_| to two triangles |/| + + poly = meshobj->AddPolygon(bucket, 3); + + poly->SetVisible(visible); + poly->SetCollider(collider); + poly->SetTwoside(twoside); + + meshobj->AddVertex(poly,0,pt[2],uvs[2],tan[2],rgb[2],no[2],flat,mface->v3); + meshobj->AddVertex(poly,1,pt[3],uvs[3],tan[3],rgb[3],no[3],flat,mface->v4); + meshobj->AddVertex(poly,2,pt[0],uvs[0],tan[0],rgb[0],no[0],flat,mface->v1); + + } +#endif + + } + + if (tface) + tface++; + if (mcol) + mcol+=4; + + for (int lay=0; lay<MAX_MTFACE; lay++) + { + MTF_localLayer &layer = layers[lay]; + if (layer.face == 0) break; + + layer.face++; + } + } + // keep meshobj->m_sharedvertex_map for reinstance phys mesh. + // 2.49a and before it did: meshobj->m_sharedvertex_map.clear(); + // but this didnt save much ram. - Campbell + meshobj->EndConversion(); + + // pre calculate texture generation + // 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); + + converter->RegisterGameMesh(meshobj, mesh); + return meshobj; +} + /* 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_old(Mesh* mesh, Object* blenderobj, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; int lightlayer = blenderobj ? blenderobj->lay:(1<<20)-1; // all layers if no object. @@ -910,7 +1310,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 = ""; @@ -945,19 +1344,18 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, { 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); + MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; unsigned int rgb0,rgb1,rgb2,rgb3 = 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]; /* 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 +1363,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 +1380,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); @@ -1008,43 +1406,32 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, 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]; + unsigned int rgb[4]; /* first is the BL_Material */ - if (!bl_mat) { + 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); - } + + /* XXX fix me. Temp work around*/ + if(!ma) + ma= &defmaterial; + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, + converter->GetGLSLMaterials()); - /* 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); + short type = (bl_mat) ? ((ma->mode & MA_VERTEXCOLP || bl_mat->glslmat) ? 0 : 1) : 0; + GetRGB(type,mface,mcol,ma,rgb); - uv0 = uv_1[0]; uv1 = uv_1[1]; - uv2 = uv_1[2]; uv3 = uv_1[3]; + rgb0 = rgb[0]; rgb1 = rgb[1]; + rgb2 = rgb[2]; rgb3 = rgb[3]; - uv20 = uv_2[0]; uv21 = uv_2[1]; - uv22 = uv_2[2]; uv23 = uv_2[3]; + GetUVs(bl_mat, layers, mface, tface, uvs); /* 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)); - //} - + kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL), lightlayer); polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat); } else { @@ -1095,12 +1482,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, /* set UV properties */ if (tface) { - uv0.setValue(tface->uv[0]); - uv1.setValue(tface->uv[1]); - uv2.setValue(tface->uv[2]); + uvs[0][0].setValue(tface->uv[0]); + uvs[1][0].setValue(tface->uv[1]); + uvs[2][0].setValue(tface->uv[2]); if (mface->v4) - uv3.setValue(tface->uv[3]); + uvs[3][0].setValue(tface->uv[3]); tile = tface->tile; } @@ -1210,8 +1597,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, polymat = bucket->GetPolyMaterial(); // keep the material pointers, they will be reused for next face } - + +#ifdef GLES + // Force 3 verts on GLES + int nverts = 3; +#else int nverts = (mface->v4)? 4: 3; +#endif RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); poly->SetVisible(visible); @@ -1219,12 +1611,32 @@ 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],rgb0,no[0],flat,mface->v1); + meshobj->AddVertex(poly,1,pt[1],uvs[1],tan[1],rgb1,no[1],flat,mface->v2); + meshobj->AddVertex(poly,2,pt[2],uvs[2],tan[2],rgb2,no[2],flat,mface->v3); + +#ifndef GLES 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],rgb3,no[3],flat,mface->v4); +#else + if(mface->v4) + { + // GLES doesn't support QUADs so we are spliiting a quad |_| to two triangles |/| + + poly = meshobj->AddPolygon(bucket, 3); + + poly->SetVisible(visible); + poly->SetCollider(collider); + poly->SetTwoside(twoside); + + meshobj->AddVertex(poly,0,pt[2],uvs[2],tan[2],rgb2,no[2],flat,mface->v3); + meshobj->AddVertex(poly,1,pt[3],uvs[3],tan[3],rgb3,no[3],flat,mface->v4); + meshobj->AddVertex(poly,2,pt[0],uvs[0],tan[0],rgb0,no[0],flat,mface->v1); + + } +#endif + } if (tface) @@ -1248,7 +1660,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, // pre calculate texture generation for (list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial(); mit != meshobj->GetLastMaterial(); ++ mit) { - mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer); + mit->m_bucket->GetPolyMaterial()->OnConstruction(); } if (layers) @@ -1381,30 +1793,32 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size) } if (me->totvert) { - loc[0] = (min[0] + max[0]) / 2.0f; - loc[1] = (min[1] + max[1]) / 2.0f; - loc[2] = (min[2] + max[2]) / 2.0f; + loc[0]= (min[0]+max[0])/2.0f; + loc[1]= (min[1]+max[1])/2.0f; + loc[2]= (min[2]+max[2])/2.0f; - size[0] = (max[0] - min[0]) / 2.0f; - size[1] = (max[1] - min[1]) / 2.0f; - size[2] = (max[2] - min[2]) / 2.0f; + size[0]= (max[0]-min[0])/2.0f; + size[1]= (max[1]-min[1])/2.0f; + size[2]= (max[2]-min[2])/2.0f; } else { - loc[0] = loc[1] = loc[2] = 0.0f; - size[0] = size[1] = size[2] = 0.0f; + loc[0]= loc[1]= loc[2]= 0.0f; + size[0]= size[1]= size[2]= 0.0f; } - bb->vec[0][0] = bb->vec[1][0] = bb->vec[2][0] = bb->vec[3][0] = loc[0]-size[0]; - bb->vec[4][0] = bb->vec[5][0] = bb->vec[6][0] = bb->vec[7][0] = loc[0]+size[0]; + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0]; - bb->vec[0][1] = bb->vec[1][1] = bb->vec[4][1] = bb->vec[5][1] = loc[1]-size[1]; - bb->vec[2][1] = bb->vec[3][1] = bb->vec[6][1] = bb->vec[7][1] = loc[1]+size[1]; + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1]; - bb->vec[0][2] = bb->vec[3][2] = bb->vec[4][2] = bb->vec[7][2] = loc[2]-size[2]; - bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = loc[2]+size[2]; + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2]; return sqrt(radius); } + + static void my_tex_space_mesh(Mesh *me) @@ -1427,12 +1841,12 @@ static void my_tex_space_mesh(Mesh *me) minmax_v3v3_v3(min, max, fp); } if (kb->totelem) { - loc[0] = (min[0]+max[0])/2.0f; loc[1] = (min[1]+max[1])/2.0f; loc[2] = (min[2]+max[2])/2.0f; - size[0] = (max[0]-min[0])/2.0f; size[1] = (max[1]-min[1])/2.0f; size[2] = (max[2]-min[2])/2.0f; + loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f; + size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f; } else { - loc[0] = loc[1] = loc[2] = 0.0; - size[0] = size[1] = size[2] = 0.0; + loc[0]= loc[1]= loc[2]= 0.0; + size[0]= size[1]= size[2]= 0.0; } } @@ -1440,19 +1854,19 @@ static void my_tex_space_mesh(Mesh *me) copy_v3_v3(me->loc, loc); copy_v3_v3(me->size, size); - me->rot[0] = me->rot[1] = me->rot[2] = 0.0f; + me->rot[0]= me->rot[1]= me->rot[2]= 0.0f; if (me->size[0] == 0.0f) me->size[0] = 1.0f; - else if (me->size[0] > 0.0f && me->size[0]< 0.00001f) me->size[0] = 0.00001f; - else if (me->size[0] < 0.0f && me->size[0]> -0.00001f) me->size[0] = -0.00001f; + else if (me->size[0] > 0.0f && me->size[0]< 0.00001f) me->size[0]= 0.00001f; + else if (me->size[0] < 0.0f && me->size[0]> -0.00001f) me->size[0]= -0.00001f; - if (me->size[1] == 0.0f) me->size[1] = 1.0f; - else if (me->size[1] > 0.0f && me->size[1]< 0.00001f) me->size[1] = 0.00001f; - else if (me->size[1] < 0.0f && me->size[1]> -0.00001f) me->size[1] = -0.00001f; + if (me->size[1] == 0.0f) me->size[1]= 1.0f; + else if (me->size[1] > 0.0f && me->size[1]< 0.00001f) me->size[1]= 0.00001f; + else if (me->size[1] < 0.0f && me->size[1]> -0.00001f) me->size[1]= -0.00001f; - if (me->size[2] == 0.0f) me->size[2] = 1.0f; - else if (me->size[2] > 0.0f && me->size[2]< 0.00001f) me->size[2] = 0.00001f; - else if (me->size[2] < 0.0f && me->size[2]> -0.00001f) me->size[2] = -0.00001f; + if (me->size[2] == 0.0f) me->size[2]= 1.0f; + else if (me->size[2] > 0.0f && me->size[2]< 0.00001f) me->size[2]= 0.00001f; + else if (me->size[2] < 0.0f && me->size[2]> -0.00001f) me->size[2]= -0.00001f; } } @@ -1469,13 +1883,13 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa float min_r[3], max_r[3]; INIT_MINMAX(min_r, max_r); dm->getMinMax(dm, min_r, max_r); - size[0] = 0.5f * fabsf(max_r[0] - min_r[0]); - size[1] = 0.5f * fabsf(max_r[1] - min_r[1]); - size[2] = 0.5f * fabsf(max_r[2] - min_r[2]); + size[0]= 0.5f*fabsf(max_r[0] - min_r[0]); + size[1]= 0.5f*fabsf(max_r[1] - min_r[1]); + size[2]= 0.5f*fabsf(max_r[2] - min_r[2]); - center[0] = 0.5f * (max_r[0] + min_r[0]); - center[1] = 0.5f * (max_r[1] + min_r[1]); - center[2] = 0.5f * (max_r[2] + min_r[2]); + center[0]= 0.5f*(max_r[0] + min_r[0]); + center[1]= 0.5f*(max_r[1] + min_r[1]); + center[2]= 0.5f*(max_r[2] + min_r[2]); return; } else { @@ -1489,11 +1903,11 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa break; case OB_CURVE: case OB_SURF: - center[0] = center[1] = center[2] = 0.0; + center[0]= center[1]= center[2]= 0.0; size[0] = size[1]=size[2]=0.0; break; case OB_FONT: - center[0] = center[1] = center[2] = 0.0; + center[0]= center[1]= center[2]= 0.0; size[0] = size[1]=size[2]=1.0; break; case OB_MBALL: @@ -1503,15 +1917,15 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa if (bb==NULL) { - center[0] = center[1] = center[2] = 0.0; - size[0] = size[1] = size[2] = 1.0; + center[0]= center[1]= center[2]= 0.0; + size[0] = size[1]=size[2]=1.0; } else { size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]); size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]); size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]); - + center[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]); center[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]); center[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]); @@ -1579,20 +1993,12 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //bool bRigidBody = (userigidbody == 0); // object has physics representation? - if (!(blenderobject->gameflag & OB_COLLISION)) { - // Respond to all collisions so that Near sensors work on No Collision - // objects. - gameobj->SetUserCollisionGroup(0xff); - gameobj->SetUserCollisionMask(0xff); + if (!(blenderobject->gameflag & OB_COLLISION)) return; - } - - gameobj->SetUserCollisionGroup(blenderobject->col_group); - gameobj->SetUserCollisionMask(blenderobject->col_mask); // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; - while (parent && parent->parent) { + while(parent && parent->parent) { parent= parent->parent; } @@ -1921,12 +2327,14 @@ 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(); - switch (ob->type) { + switch(ob->type) + { case OB_LAMP: { KX_LightObject* gamelight = gamelight_from_blamp(ob, static_cast<Lamp*>(ob->data), ob->lay, kxscene, rendertools, converter); @@ -1958,7 +2366,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); @@ -2321,7 +2729,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, RAS_IRenderTools* rendertools, RAS_ICanvas* canvas, KX_BlenderSceneConverter* converter, - bool alwaysUseExpandFraming + bool alwaysUseExpandFraming, + bool libloading ) { @@ -2431,7 +2840,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, base->object, kxscene, rendertools, - converter); + converter, + libloading); bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0; bool addobj=true; @@ -2490,7 +2900,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 |