blender/source/gameengine/Converter/BL_BlenderDataConversion.cpp
Erwin Coumans 718e2bf74f improved game soft bodies, works for objects that are using 'set smooth'
use shape matching by default for game soft bodies
store soft body index for game vertices
2008-09-25 03:02:30 +00:00

2517 lines
72 KiB
C++

/**
* $Id$
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *****
* Convert blender data to ketsji
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef WIN32
#pragma warning (disable : 4786)
#endif
#include <math.h>
#include "BL_BlenderDataConversion.h"
#include "KX_BlenderGL.h"
#include "KX_BlenderScalarInterpolator.h"
#include "RAS_IPolygonMaterial.h"
#include "KX_PolygonMaterial.h"
// Expressions
#include "ListValue.h"
#include "IntValue.h"
// Collision & Fuzzics LTD
#include "PHY_Pro.h"
#include "KX_Scene.h"
#include "KX_GameObject.h"
#include "RAS_FramingManager.h"
#include "RAS_MeshObject.h"
#include "KX_ConvertActuators.h"
#include "KX_ConvertControllers.h"
#include "KX_ConvertSensors.h"
#include "SCA_LogicManager.h"
#include "SCA_EventManager.h"
#include "SCA_TimeEventManager.h"
#include "KX_Light.h"
#include "KX_Camera.h"
#include "KX_EmptyObject.h"
#include "MT_Point3.h"
#include "MT_Transform.h"
#include "MT_MinMax.h"
#include "SCA_IInputDevice.h"
#include "RAS_TexMatrix.h"
#include "RAS_ICanvas.h"
#include "RAS_MaterialBucket.h"
//#include "KX_BlenderPolyMaterial.h"
#include "RAS_Polygon.h"
#include "RAS_TexVert.h"
#include "RAS_BucketManager.h"
#include "RAS_IRenderTools.h"
#include "BL_Material.h"
#include "KX_BlenderMaterial.h"
#include "BL_Texture.h"
#include "DNA_action_types.h"
#include "BKE_main.h"
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BL_SkinMeshObject.h"
#include "BL_ShapeDeformer.h"
#include "BL_SkinDeformer.h"
#include "BL_MeshDeformer.h"
//#include "BL_ArmatureController.h"
#include "BlenderWorldInfo.h"
#include "KX_KetsjiEngine.h"
#include "KX_BlenderSceneConverter.h"
#include"SND_Scene.h"
#include "SND_SoundListener.h"
/* This little block needed for linking to Blender... */
#ifdef WIN32
#include "BLI_winstuff.h"
#endif
/* This list includes only data type definitions */
#include "DNA_object_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
#include "DNA_lamp_types.h"
#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "DNA_camera_types.h"
#include "DNA_property_types.h"
#include "DNA_text_types.h"
#include "DNA_sensor_types.h"
#include "DNA_controller_types.h"
#include "DNA_actuator_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_sound_types.h"
#include "DNA_key_types.h"
#include "DNA_armature_types.h"
#include "MEM_guardedalloc.h"
#include "BKE_utildefines.h"
#include "BKE_key.h"
#include "BKE_mesh.h"
#include "MT_Point3.h"
#include "BLI_arithb.h"
extern "C" {
#include "BKE_customdata.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
}
#include "BKE_material.h" /* give_current_material */
/* end of blender include block */
#include "KX_BlenderInputDevice.h"
#include "KX_ConvertProperties.h"
#include "KX_HashedPtr.h"
#include "KX_ScalarInterpolator.h"
#include "KX_IpoConvert.h"
#include "SYS_System.h"
#include "SG_Node.h"
#include "SG_BBox.h"
#include "SG_Tree.h"
// defines USE_ODE to choose physics engine
#include "KX_ConvertPhysicsObject.h"
// This file defines relationships between parents and children
// in the game engine.
#include "KX_SG_NodeRelationships.h"
#include "KX_SG_BoneParentNodeRelationship.h"
#include "BL_ArmatureObject.h"
#include "BL_DeformableGameObject.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "BSE_headerbuttons.h"
void update_for_newframe();
//void scene_update_for_newframe(struct Scene *sce, unsigned int lay);
//#include "BKE_ipo.h"
//void do_all_data_ipos(void);
#ifdef __cplusplus
}
#endif
static int default_face_mode = TF_DYNAMIC;
static unsigned int KX_rgbaint2uint_new(unsigned int icol)
{
union
{
unsigned int integer;
unsigned char cp[4];
} out_color, in_color;
in_color.integer = icol;
out_color.cp[0] = in_color.cp[3]; // red
out_color.cp[1] = in_color.cp[2]; // green
out_color.cp[2] = in_color.cp[1]; // blue
out_color.cp[3] = in_color.cp[0]; // alpha
return out_color.integer;
}
/* Now the real converting starts... */
static unsigned int KX_Mcol2uint_new(MCol col)
{
/* color has to be converted without endian sensitivity. So no shifting! */
union
{
MCol col;
unsigned int integer;
unsigned char cp[4];
} out_color, in_color;
in_color.col = col;
out_color.cp[0] = in_color.cp[3]; // red
out_color.cp[1] = in_color.cp[2]; // green
out_color.cp[2] = in_color.cp[1]; // blue
out_color.cp[3] = in_color.cp[0]; // alpha
return out_color.integer;
}
static void SetDefaultFaceType(Scene* scene)
{
default_face_mode = TF_DYNAMIC;
Scene *sce;
Base *base;
for(SETLOOPER(scene,base))
{
if (base->object->type == OB_LAMP)
{
default_face_mode = TF_DYNAMIC|TF_LIGHT;
return;
}
}
}
// --
static void GetRGB(short type,
MFace* mface,
MCol* mmcol,
Material *mat,
unsigned int &c0,
unsigned int &c1,
unsigned int &c2,
unsigned int &c3)
{
unsigned int color = 0xFFFFFFFFL;
switch(type)
{
case 0: // vertex colors
{
if(mmcol) {
c0 = KX_Mcol2uint_new(mmcol[0]);
c1 = KX_Mcol2uint_new(mmcol[1]);
c2 = KX_Mcol2uint_new(mmcol[2]);
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);
if (mface->v4)
c3 = 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.0);
col_converter.cp[2] = (unsigned char) (mat->g*255.0);
col_converter.cp[1] = (unsigned char) (mat->b*255.0);
col_converter.cp[0] = (unsigned char) (mat->alpha*255.0);
color = col_converter.integer;
}
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new(color);
} break;
default: // white
{
c0 = KX_rgbaint2uint_new(color);
c1 = KX_rgbaint2uint_new(color);
c2 = KX_rgbaint2uint_new(color);
if (mface->v4)
c3 = KX_rgbaint2uint_new(color);
} break;
}
}
typedef struct MTF_localLayer
{
MTFace *face;
const char *name;
}MTF_localLayer;
// ------------------------------------
BL_Material* ConvertMaterial(
Material *mat,
MTFace* tface,
const char *tfaceName,
MFace* mface,
MCol* mmcol,
int lightlayer,
Object* blenderobj,
MTF_localLayer *layers,
bool glslmat)
{
//this needs some type of manager
BL_Material *material = new BL_Material();
int numchan = -1, 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;
// --------------------------------
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;
MTex *mttmp = 0;
numchan = getNumTexChannels(mat);
int valid_index = 0;
// use the face texture if
// 1) it is set in the buttons
// 2) we have a face texture and a material but no valid texture in slot 1
bool facetex = false;
if(validface && mat->mode &MA_FACETEXTURE)
facetex = true;
if(validface && !mat->mtex[0])
facetex = true;
if(validface && mat->mtex[0]) {
MTex *tmp = mat->mtex[0];
if(!tmp->tex || tmp->tex && !tmp->tex->ima )
facetex = true;
}
numchan = numchan>MAXTEX?MAXTEX:numchan;
// foreach MTex
for(int i=0; i<numchan; i++) {
// use face tex
if(i==0 && facetex ) {
Image*tmp = (Image*)(tface->tpage);
if(tmp) {
material->img[i] = tmp;
material->texname[i] = material->img[i]->id.name;
material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0;
material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0;
material->flag[i] |= MIPMAP;
if(material->img[i]->flag & IMA_REFLECT)
material->mapping[i].mapping |= USEREFL;
else
{
mttmp = getImageFromMaterial( mat, i );
if(mttmp && mttmp->texco &TEXCO_UV)
{
STR_String uvName = mttmp->uvname;
if (!uvName.IsEmpty())
material->mapping[i].uvCoName = mttmp->uvname;
else
material->mapping[i].uvCoName = "";
}
material->mapping[i].mapping |= USEUV;
}
if(material->ras_mode & USE_LIGHT)
material->ras_mode &= ~USE_LIGHT;
if(tface->mode & TF_LIGHT)
material->ras_mode |= USE_LIGHT;
valid_index++;
}
else {
material->img[i] = 0;
material->texname[i] = "";
}
continue;
}
mttmp = getImageFromMaterial( mat, i );
if( mttmp ) {
if( mttmp->tex ) {
if( mttmp->tex->type == TEX_IMAGE ) {
material->mtexname[i] = mttmp->tex->id.name;
material->img[i] = mttmp->tex->ima;
if( material->img[i] ) {
material->texname[i] = material->img[i]->id.name;
material->flag[i] |= ( mttmp->tex->imaflag &TEX_MIPMAP )?MIPMAP:0;
// -----------------------
if( mttmp->tex->imaflag &TEX_USEALPHA ) {
material->flag[i] |= USEALPHA;
}
// -----------------------
else if( mttmp->tex->imaflag &TEX_CALCALPHA ) {
material->flag[i] |= CALCALPHA;
}
else if(mttmp->tex->flag &TEX_NEGALPHA) {
material->flag[i] |= USENEGALPHA;
}
material->color_blend[i] = mttmp->colfac;
material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0;
material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0;
if(!glslmat && (material->flag[i] & TEXALPHA))
texalpha = 1;
}
}
else if(mttmp->tex->type == TEX_ENVMAP) {
if( mttmp->tex->env->stype == ENV_LOAD ) {
material->mtexname[i] = mttmp->tex->id.name;
EnvMap *env = mttmp->tex->env;
env->ima = mttmp->tex->ima;
material->cubemap[i] = env;
if (material->cubemap[i])
{
if (!material->cubemap[i]->cube[0])
BL_Texture::SplitEnvMap(material->cubemap[i]);
material->texname[i]= material->cubemap[i]->ima->id.name;
material->mapping[i].mapping |= USEENV;
}
}
}
material->flag[i] |= (mat->ipo!=0)?HASIPO:0;
/// --------------------------------
// mapping methods
material->mapping[i].mapping |= ( mttmp->texco & TEXCO_REFL )?USEREFL:0;
if(mttmp->texco & TEXCO_OBJECT) {
material->mapping[i].mapping |= USEOBJ;
if(mttmp->object)
material->mapping[i].objconame = mttmp->object->id.name;
}
else if(mttmp->texco &TEXCO_REFL)
material->mapping[i].mapping |= USEREFL;
else if(mttmp->texco &(TEXCO_ORCO|TEXCO_GLOB))
material->mapping[i].mapping |= USEORCO;
else if(mttmp->texco &TEXCO_UV)
{
STR_String uvName = mttmp->uvname;
if (!uvName.IsEmpty())
material->mapping[i].uvCoName = mttmp->uvname;
else
material->mapping[i].uvCoName = "";
material->mapping[i].mapping |= USEUV;
}
else if(mttmp->texco &TEXCO_NORM)
material->mapping[i].mapping |= USENORM;
else if(mttmp->texco &TEXCO_TANGENT)
material->mapping[i].mapping |= USETANG;
else
material->mapping[i].mapping |= DISABLE;
material->mapping[i].scale[0] = mttmp->size[0];
material->mapping[i].scale[1] = mttmp->size[1];
material->mapping[i].scale[2] = mttmp->size[2];
material->mapping[i].offsets[0] = mttmp->ofs[0];
material->mapping[i].offsets[1] = mttmp->ofs[1];
material->mapping[i].offsets[2] = mttmp->ofs[2];
material->mapping[i].projplane[0] = mttmp->projx;
material->mapping[i].projplane[1] = mttmp->projy;
material->mapping[i].projplane[2] = mttmp->projz;
/// --------------------------------
switch( mttmp->blendtype ) {
case MTEX_BLEND:
material->blend_mode[i] = BLEND_MIX;
break;
case MTEX_MUL:
material->blend_mode[i] = BLEND_MUL;
break;
case MTEX_ADD:
material->blend_mode[i] = BLEND_ADD;
break;
case MTEX_SUB:
material->blend_mode[i] = BLEND_SUB;
break;
case MTEX_SCREEN:
material->blend_mode[i] = BLEND_SCR;
break;
}
valid_index++;
}
}
}
// above one tex the switches here
// are not used
switch(valid_index) {
case 0:
material->IdMode = DEFAULT_BLENDER;
break;
case 1:
material->IdMode = ONETEX;
break;
default:
material->IdMode = GREATERTHAN2;
break;
}
material->SetUsers(mat->id.us);
material->num_enabled = valid_index;
material->speccolor[0] = mat->specr;
material->speccolor[1] = mat->specg;
material->speccolor[2] = mat->specb;
material->hard = (float)mat->har/4.0f;
material->matcolor[0] = mat->r;
material->matcolor[1] = mat->g;
material->matcolor[2] = mat->b;
material->matcolor[3] = mat->alpha;
material->alpha = mat->alpha;
material->emit = mat->emit;
material->spec_f = mat->spec;
material->ref = mat->ref;
material->amb = mat->amb;
material->ras_mode |= (mat->mode & MA_WIRE)? WIRE: 0;
}
else {
int valid = 0;
// check for tface tex to fallback on
if( validface ){
// no light bugfix
if(tface->mode) material->ras_mode |= USE_LIGHT;
material->img[0] = (Image*)(tface->tpage);
// ------------------------
if(material->img[0]) {
material->texname[0] = material->img[0]->id.name;
material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0;
material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0;
material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0;
valid++;
}
}
material->SetUsers(-1);
material->num_enabled = valid;
material->IdMode = TEXFACE;
material->speccolor[0] = 1.f;
material->speccolor[1] = 1.f;
material->speccolor[2] = 1.f;
material->hard = 35.f;
material->matcolor[0] = 0.5f;
material->matcolor[1] = 0.5f;
material->matcolor[2] = 0.5f;
material->spec_f = 0.5f;
material->ref = 0.8f;
}
MT_Point2 uv[4];
MT_Point2 uv2[4];
const char *uvName = "", *uv2Name = "";
uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f);
uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f);
if( validface ) {
material->ras_mode |= !(
(mface->flag & ME_HIDE) ||
(tface->mode & TF_INVISIBLE)
)?POLY_VIS:0;
material->transp = tface->transp;
material->tile = tface->tile;
material->mode = tface->mode;
uv[0] = MT_Point2(tface->uv[0]);
uv[1] = MT_Point2(tface->uv[1]);
uv[2] = MT_Point2(tface->uv[2]);
if (mface->v4)
uv[3] = MT_Point2(tface->uv[3]);
uvName = tfaceName;
}
else {
// nothing at all
material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT));
material->mode = default_face_mode;
material->transp = TF_SOLID;
material->tile = 0;
}
// with ztransp enabled, enforce alpha blending mode
if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID))
material->transp = TF_ALPHA;
// always zsort alpha + add
if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) {
material->ras_mode |= ALPHA;
material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0;
}
// collider or not?
material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0;
// these flags are irrelevant at this point, remove so they
// don't hurt material bucketing
material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX);
// 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];
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)
{
MT_Point2 uvSet[4];
uvSet[0] = MT_Point2(layer.face->uv[0]);
uvSet[1] = MT_Point2(layer.face->uv[1]);
uvSet[2] = MT_Point2(layer.face->uv[2]);
if (mface->v4)
uvSet[3] = MT_Point2(layer.face->uv[3]);
else
uvSet[3] = MT_Point2(0.0f, 0.0f);
if (isFirstSet)
{
uv[0] = uvSet[0]; uv[1] = uvSet[1];
uv[2] = uvSet[2]; uv[3] = uvSet[3];
isFirstSet = false;
uvName = layer.name;
}
else if(strcmp(layer.name, uvName) != 0)
{
uv2[0] = uvSet[0]; uv2[1] = uvSet[1];
uv2[2] = uvSet[2]; uv2[3] = uvSet[3];
map.mapping |= USECUSTOMUV;
uv2Name = layer.name;
}
}
}
}
}
}
unsigned int rgb[4];
GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]);
// swap the material color, so MCol on TF_BMFONT works
if (validmat && type==1 && (tface && tface->mode & TF_BMFONT))
{
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->SetConversionRGB(rgb);
material->SetConversionUV(uvName, uv);
material->SetConversionUV2(uv2Name, uv2);
if(validmat)
material->matname =(mat->id.name);
material->tface = tface;
material->material = mat;
return material;
}
RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter)
{
RAS_MeshObject *meshobj;
bool skinMesh = false;
int lightlayer = blenderobj->lay;
// Get DerivedMesh data
DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj);
MVert *mvert = dm->getVertArray(dm);
int totvert = dm->getNumVerts(dm);
MFace *mface = dm->getFaceArray(dm);
MTFace *tface = static_cast<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE));
MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL));
float (*tangent)[3] = NULL;
int totface = dm->getNumFaces(dm);
const char *tfaceName = "";
if(tface) {
DM_add_tangent_layer(dm);
tangent = (float(*)[3])dm->getFaceDataArray(dm, CD_TANGENT);
}
// Determine if we need to make a skinned mesh
if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0))
{
meshobj = new BL_SkinMeshObject(mesh, lightlayer);
skinMesh = true;
}
else
meshobj = new RAS_MeshObject(mesh, lightlayer);
// 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);
meshobj->m_sharedvertex_map.resize(totvert);
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;
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);
/* get coordinates, normals and tangents */
pt0 = MT_Point3(mvert[mface->v1].co);
pt1 = MT_Point3(mvert[mface->v2].co);
pt2 = MT_Point3(mvert[mface->v3].co);
pt3 = (mface->v4)? MT_Point3(mvert[mface->v4].co): MT_Point3(0.0, 0.0, 0.0);
if(mface->flag & ME_SMOOTH) {
float n0[3], n1[3], n2[3], n3[3];
NormalShortToFloat(n0, mvert[mface->v1].no);
NormalShortToFloat(n1, mvert[mface->v2].no);
NormalShortToFloat(n2, mvert[mface->v3].no);
no0 = n0;
no1 = n1;
no2 = n2;
if(mface->v4) {
NormalShortToFloat(n3, mvert[mface->v4].no);
no3 = n3;
}
}
else {
float fno[3];
if(mface->v4)
CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
mvert[mface->v3].co, mvert[mface->v4].co, fno);
else
CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
mvert[mface->v3].co, fno);
no0 = no1 = no2 = no3 = MT_Vector3(fno);
}
if(tangent) {
tan0 = tangent[f*4 + 0];
tan1 = tangent[f*4 + 1];
tan2 = tangent[f*4 + 2];
if (mface->v4)
tan3 = tangent[f*4 + 3];
}
/* get material */
ma = give_current_material(blenderobj, mface->mat_nr+1);
{
bool visible = true;
RAS_IPolyMaterial* polymat = NULL;
BL_Material *bl_mat = NULL;
if(converter->GetMaterials()) {
/* do Blender Multitexture and Blender GLSL materials */
unsigned int rgb[4];
MT_Point2 uv[4];
/* first is the BL_Material */
bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol,
lightlayer, blenderobj, layers, converter->GetGLSLMaterials());
bl_mat->material_index = (int)mface->mat_nr;
visible = ((bl_mat->ras_mode & POLY_VIS)!=0);
collider = ((bl_mat->ras_mode & COLLIDER)!=0);
/* vertex colors and uv's were stored in bl_mat temporarily */
bl_mat->GetConversionRGB(rgb);
rgb0 = rgb[0]; rgb1 = rgb[1];
rgb2 = rgb[2]; rgb3 = rgb[3];
bl_mat->GetConversionUV(uv);
uv0 = uv[0]; uv1 = uv[1];
uv2 = uv[2]; uv3 = uv[3];
bl_mat->GetConversionUV2(uv);
uv20 = uv[0]; uv21 = uv[1];
uv22 = uv[2]; uv23 = uv[3];
/* then the KX_BlenderMaterial */
polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer);
}
else {
/* do Texture Face materials */
Image* bima = (tface)? (Image*)tface->tpage: NULL;
STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : "";
char transp=0;
short mode=0, tile=0;
int tilexrep=4,tileyrep = 4;
if (bima) {
tilexrep = bima->xrep;
tileyrep = bima->yrep;
}
/* get tface properties if available */
if(tface) {
/* TF_DYNAMIC means the polygon is a collision face */
collider = ((tface->mode & TF_DYNAMIC) != 0);
transp = tface->transp;
tile = tface->tile;
mode = tface->mode;
visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE));
uv0 = MT_Point2(tface->uv[0]);
uv1 = MT_Point2(tface->uv[1]);
uv2 = MT_Point2(tface->uv[2]);
if (mface->v4)
uv3 = MT_Point2(tface->uv[3]);
}
else {
/* no texfaces, set COLLSION true and everything else FALSE */
mode = default_face_mode;
transp = TF_SOLID;
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.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;
}
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 = (transp == TF_ALPHA || transp == TF_ADD);
bool zsort = (mode & TF_ALPHASORT)? alpha: 0;
polymat = new KX_PolygonMaterial(imastr, ma,
tile, tilexrep, tileyrep,
mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol);
if (ma) {
polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512
polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref);
}
else {
polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f);
polymat->m_shininess = 35.0;
}
}
/* 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);
}
} else {
// delete the material objects since they are no longer needed
// from now on, use the polygon material from the material bucket
delete polymat;
if(converter->GetMaterials()) {
delete bl_mat;
}
polymat = bucket->GetPolyMaterial();
}
int nverts = (mface->v4)? 4: 3;
RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts);
poly->SetVisible(visible);
poly->SetCollider(collider);
//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);
if (nverts==4)
meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4);
}
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++;
}
}
meshobj->m_sharedvertex_map.clear();
// pre calculate texture generation
for(list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
mit != meshobj->GetLastMaterial(); ++ mit) {
mit->m_bucket->GetPolyMaterial()->OnConstruction();
}
if (layers)
delete []layers;
dm->release(dm);
return meshobj;
}
static PHY_MaterialProps *CreateMaterialFromBlenderObject(struct Object* blenderobject,
KX_Scene *kxscene)
{
PHY_MaterialProps *materialProps = new PHY_MaterialProps;
MT_assert(materialProps && "Create physics material properties failed");
Material* blendermat = give_current_material(blenderobject, 0);
if (blendermat)
{
MT_assert(0.0f <= blendermat->reflect && blendermat->reflect <= 1.0f);
materialProps->m_restitution = blendermat->reflect;
materialProps->m_friction = blendermat->friction;
materialProps->m_fh_spring = blendermat->fh;
materialProps->m_fh_damping = blendermat->xyfrict;
materialProps->m_fh_distance = blendermat->fhdist;
materialProps->m_fh_normal = (blendermat->dynamode & MA_FH_NOR) != 0;
}
else {
//give some defaults
materialProps->m_restitution = 0.f;
materialProps->m_friction = 0.5;
materialProps->m_fh_spring = 0.f;
materialProps->m_fh_damping = 0.f;
materialProps->m_fh_distance = 0.f;
materialProps->m_fh_normal = false;
}
return materialProps;
}
static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blenderobject,
KX_Scene *kxscene)
{
PHY_ShapeProps *shapeProps = new PHY_ShapeProps;
MT_assert(shapeProps);
shapeProps->m_mass = blenderobject->mass;
// This needs to be fixed in blender. For now, we use:
// in Blender, inertia stands for the size value which is equivalent to
// the sphere radius
shapeProps->m_inertia = blenderobject->formfactor;
MT_assert(0.0f <= blenderobject->damping && blenderobject->damping <= 1.0f);
MT_assert(0.0f <= blenderobject->rdamping && blenderobject->rdamping <= 1.0f);
shapeProps->m_lin_drag = 1.0 - blenderobject->damping;
shapeProps->m_ang_drag = 1.0 - blenderobject->rdamping;
shapeProps->m_friction_scaling[0] = blenderobject->anisotropicFriction[0];
shapeProps->m_friction_scaling[1] = blenderobject->anisotropicFriction[1];
shapeProps->m_friction_scaling[2] = blenderobject->anisotropicFriction[2];
shapeProps->m_do_anisotropic = ((blenderobject->gameflag & OB_ANISOTROPIC_FRICTION) != 0);
shapeProps->m_do_fh = (blenderobject->gameflag & OB_DO_FH) != 0;
shapeProps->m_do_rot_fh = (blenderobject->gameflag & OB_ROT_FH) != 0;
return shapeProps;
}
//////////////////////////////////////////////////////////
static float my_boundbox_mesh(Mesh *me, float *loc, float *size)
{
MVert *mvert;
BoundBox *bb;
MT_Point3 min, max;
float mloc[3], msize[3];
int a;
if(me->bb==0) me->bb= (struct BoundBox *)MEM_callocN(sizeof(BoundBox), "boundbox");
bb= me->bb;
INIT_MINMAX(min, max);
if (!loc) loc= mloc;
if (!size) size= msize;
mvert= me->mvert;
for(a=0; a<me->totvert; a++, mvert++) {
DO_MINMAX(mvert->co, min, max);
}
if(me->totvert) {
loc[0]= (min[0]+max[0])/2.0;
loc[1]= (min[1]+max[1])/2.0;
loc[2]= (min[2]+max[2])/2.0;
size[0]= (max[0]-min[0])/2.0;
size[1]= (max[1]-min[1])/2.0;
size[2]= (max[2]-min[2])/2.0;
}
else {
loc[0]= loc[1]= loc[2]= 0.0;
size[0]= size[1]= size[2]= 0.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][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];
float radius = 0;
for (a=0, mvert = me->mvert; a < me->totvert; a++, mvert++)
{
float vert_radius = MT_Vector3(mvert->co).length2();
if (vert_radius > radius)
radius = vert_radius;
}
return sqrt(radius);
}
static void my_tex_space_mesh(Mesh *me)
{
KeyBlock *kb;
float *fp, loc[3], size[3], min[3], max[3];
int a;
my_boundbox_mesh(me, loc, size);
if(me->texflag & AUTOSPACE) {
if(me->key) {
kb= me->key->refkey;
if (kb) {
INIT_MINMAX(min, max);
fp= (float *)kb->data;
for(a=0; a<kb->totelem; a++, fp+=3) {
DO_MINMAX(fp, min, max);
}
if(kb->totelem) {
loc[0]= (min[0]+max[0])/2.0; loc[1]= (min[1]+max[1])/2.0; loc[2]= (min[2]+max[2])/2.0;
size[0]= (max[0]-min[0])/2.0; size[1]= (max[1]-min[1])/2.0; size[2]= (max[2]-min[2])/2.0;
}
else {
loc[0]= loc[1]= loc[2]= 0.0;
size[0]= size[1]= size[2]= 0.0;
}
}
}
VECCOPY(me->loc, loc);
VECCOPY(me->size, size);
me->rot[0]= me->rot[1]= me->rot[2]= 0.0;
if(me->size[0]==0.0) me->size[0]= 1.0;
else if(me->size[0]>0.0 && me->size[0]<0.00001) me->size[0]= 0.00001;
else if(me->size[0]<0.0 && me->size[0]> -0.00001) me->size[0]= -0.00001;
if(me->size[1]==0.0) me->size[1]= 1.0;
else if(me->size[1]>0.0 && me->size[1]<0.00001) me->size[1]= 0.00001;
else if(me->size[1]<0.0 && me->size[1]> -0.00001) me->size[1]= -0.00001;
if(me->size[2]==0.0) me->size[2]= 1.0;
else if(me->size[2]>0.0 && me->size[2]<0.00001) me->size[2]= 0.00001;
else if(me->size[2]<0.0 && me->size[2]> -0.00001) me->size[2]= -0.00001;
}
}
static void my_get_local_bounds(Object *ob, float *center, float *size)
{
BoundBox *bb= NULL;
/* uses boundbox, function used by Ketsji */
switch (ob->type)
{
case OB_MESH:
bb= ( (Mesh *)ob->data )->bb;
if(bb==0)
{
my_tex_space_mesh((struct Mesh *)ob->data);
bb= ( (Mesh *)ob->data )->bb;
}
break;
case OB_CURVE:
case OB_SURF:
case OB_FONT:
center[0]= center[1]= center[2]= 0.0;
size[0] = size[1]=size[2]=0.0;
break;
case OB_MBALL:
bb= ob->bb;
break;
}
if(bb==NULL)
{
center[0]= center[1]= center[2]= 0.0;
size[0] = size[1]=size[2]=1.0;
}
else
{
size[0]= 0.5*fabs(bb->vec[0][0] - bb->vec[4][0]);
size[1]= 0.5*fabs(bb->vec[0][1] - bb->vec[2][1]);
size[2]= 0.5*fabs(bb->vec[0][2] - bb->vec[1][2]);
center[0]= 0.5*(bb->vec[0][0] + bb->vec[4][0]);
center[1]= 0.5*(bb->vec[0][1] + bb->vec[2][1]);
center[2]= 0.5*(bb->vec[0][2] + bb->vec[1][2]);
}
}
//////////////////////////////////////////////////////
void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
struct Object* blenderobject,
RAS_MeshObject* meshobj,
KX_Scene* kxscene,
int activeLayerBitInfo,
e_PhysicsEngine physics_engine,
KX_BlenderSceneConverter *converter,
bool processCompoundChildren
)
{
//SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
//int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0);
//bool bRigidBody = (userigidbody == 0);
// object has physics representation?
if (!(blenderobject->gameflag & OB_COLLISION))
return;
// get Root Parent of blenderobject
struct Object* parent= blenderobject->parent;
while(parent && parent->parent) {
parent= parent->parent;
}
bool isCompoundChild = false;
if (parent && (parent->gameflag & OB_DYNAMIC)) {
if ((parent->gameflag & OB_CHILD) != 0)
{
isCompoundChild = true;
}
}
if (processCompoundChildren != isCompoundChild)
return;
PHY_ShapeProps* shapeprops =
CreateShapePropsFromBlenderObject(blenderobject,
kxscene);
PHY_MaterialProps* smmaterial =
CreateMaterialFromBlenderObject(blenderobject, kxscene);
KX_ObjectProperties objprop;
objprop.m_isCompoundChild = isCompoundChild;
objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0;
objprop.m_margin = blenderobject->margin;
// ACTOR is now a separate feature
objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0;
objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
///for game soft bodies
objprop.m_linearStiffness = blenderobject->linearStiffness;
objprop.m_angularStiffness = blenderobject->angularStiffness;
objprop.m_volumePreservation = blenderobject->volumePreservation;
objprop.m_gamesoftFlag = blenderobject->gamesoftFlag;
objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0;
objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag
//mmm, for now, taks this for the size of the dynamicobject
// Blender uses inertia for radius of dynamic object
objprop.m_radius = blenderobject->inertia;
objprop.m_in_active_layer = (blenderobject->lay & activeLayerBitInfo) != 0;
objprop.m_dynamic_parent=NULL;
objprop.m_isdeformable = ((blenderobject->gameflag2 & 2)) != 0;
objprop.m_boundclass = objprop.m_dyna?KX_BOUNDSPHERE:KX_BOUNDMESH;
KX_BoxBounds bb;
my_get_local_bounds(blenderobject,objprop.m_boundobject.box.m_center,bb.m_extends);
if (blenderobject->gameflag & OB_BOUNDS)
{
switch (blenderobject->boundtype)
{
case OB_BOUND_BOX:
objprop.m_boundclass = KX_BOUNDBOX;
//mmm, has to be divided by 2 to be proper extends
objprop.m_boundobject.box.m_extends[0]=2.f*bb.m_extends[0];
objprop.m_boundobject.box.m_extends[1]=2.f*bb.m_extends[1];
objprop.m_boundobject.box.m_extends[2]=2.f*bb.m_extends[2];
break;
case OB_BOUND_POLYT:
if (blenderobject->type == OB_MESH)
{
objprop.m_boundclass = KX_BOUNDPOLYTOPE;
break;
}
// Object is not a mesh... fall through OB_BOUND_POLYH to
// OB_BOUND_SPHERE
case OB_BOUND_POLYH:
if (blenderobject->type == OB_MESH)
{
objprop.m_boundclass = KX_BOUNDMESH;
break;
}
// Object is not a mesh... can't use polyheder.
// Fall through and become a sphere.
case OB_BOUND_SPHERE:
{
objprop.m_boundclass = KX_BOUNDSPHERE;
objprop.m_boundobject.c.m_radius = MT_max(bb.m_extends[0], MT_max(bb.m_extends[1], bb.m_extends[2]));
break;
}
case OB_BOUND_CYLINDER:
{
objprop.m_boundclass = KX_BOUNDCYLINDER;
objprop.m_boundobject.c.m_radius = MT_max(bb.m_extends[0], bb.m_extends[1]);
objprop.m_boundobject.c.m_height = 2.f*bb.m_extends[2];
break;
}
case OB_BOUND_CONE:
{
objprop.m_boundclass = KX_BOUNDCONE;
objprop.m_boundobject.c.m_radius = MT_max(bb.m_extends[0], bb.m_extends[1]);
objprop.m_boundobject.c.m_height = 2.f*bb.m_extends[2];
break;
}
}
}
if (parent && (parent->gameflag & OB_DYNAMIC)) {
KX_GameObject *parentgameobject = converter->FindGameObject(parent);
objprop.m_dynamic_parent = parentgameobject;
//cannot be dynamic:
objprop.m_dyna = false;
shapeprops->m_mass = 0.f;
}
objprop.m_concave = (blenderobject->boundtype & 4) != 0;
switch (physics_engine)
{
#ifdef USE_BULLET
case UseBullet:
KX_ConvertBulletObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop);
break;
#endif
#ifdef USE_SUMO_SOLID
case UseSumo:
KX_ConvertSumoObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop);
break;
#endif
#ifdef USE_ODE
case UseODE:
KX_ConvertODEEngineObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop);
break;
#endif //USE_ODE
case UseDynamo:
//KX_ConvertDynamoObject(gameobj,meshobj,kxscene,shapeprops, smmaterial, &objprop);
break;
case UseNone:
default:
break;
}
delete shapeprops;
delete smmaterial;
}
static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int layerflag, KX_Scene *kxscene, RAS_IRenderTools *rendertools, KX_BlenderSceneConverter *converter) {
RAS_LightObject lightobj;
KX_LightObject *gamelight;
lightobj.m_att1 = la->att1;
lightobj.m_att2 = (la->mode & LA_QUAD)?la->att2:0.0;
lightobj.m_red = la->r;
lightobj.m_green = la->g;
lightobj.m_blue = la->b;
lightobj.m_distance = la->dist;
lightobj.m_energy = la->energy;
lightobj.m_layer = layerflag;
lightobj.m_spotblend = la->spotblend;
lightobj.m_spotsize = la->spotsize;
lightobj.m_nodiffuse = (la->mode & LA_NO_DIFF) != 0;
lightobj.m_nospecular = (la->mode & LA_NO_SPEC) != 0;
if (la->mode & LA_NEG)
{
lightobj.m_red = -lightobj.m_red;
lightobj.m_green = -lightobj.m_green;
lightobj.m_blue = -lightobj.m_blue;
}
if (la->type==LA_SUN) {
lightobj.m_type = RAS_LightObject::LIGHT_SUN;
} else if (la->type==LA_SPOT) {
lightobj.m_type = RAS_LightObject::LIGHT_SPOT;
} else {
lightobj.m_type = RAS_LightObject::LIGHT_NORMAL;
}
gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools,
lightobj, converter->GetGLSLMaterials());
BL_ConvertLampIpos(la, gamelight, converter);
return gamelight;
}
static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) {
Camera* ca = static_cast<Camera*>(ob->data);
RAS_CameraData camdata(ca->lens, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob));
KX_Camera *gamecamera;
gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata);
gamecamera->SetName(ca->id.name + 2);
BL_ConvertCameraIpos(ca, gamecamera, converter);
return gamecamera;
}
static KX_GameObject *gameobject_from_blenderobject(
Object *ob,
KX_Scene *kxscene,
RAS_IRenderTools *rendertools,
KX_BlenderSceneConverter *converter,
Scene *blenderscene)
{
KX_GameObject *gameobj = NULL;
switch(ob->type)
{
case OB_LAMP:
{
KX_LightObject* gamelight= gamelight_from_blamp(ob, static_cast<Lamp*>(ob->data), ob->lay, kxscene, rendertools, converter);
gameobj = gamelight;
gamelight->AddRef();
kxscene->GetLightList()->Add(gamelight);
break;
}
case OB_CAMERA:
{
KX_Camera* gamecamera = gamecamera_from_bcamera(ob, kxscene, converter);
gameobj = gamecamera;
//don't add a reference: the camera list in kxscene->m_cameras is not released at the end
//gamecamera->AddRef();
kxscene->AddCamera(gamecamera);
break;
}
case OB_MESH:
{
Mesh* mesh = static_cast<Mesh*>(ob->data);
RAS_MeshObject* meshobj = converter->FindGameMesh(mesh, ob->lay);
float center[3], extents[3];
float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents);
if (!meshobj) {
meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter);
converter->RegisterGameMesh(meshobj, mesh);
}
// needed for python scripting
kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
gameobj = new BL_DeformableGameObject(ob,kxscene,KX_Scene::m_callbacks);
// set transformation
gameobj->AddMesh(meshobj);
// for all objects: check whether they want to
// respond to updates
bool ignoreActivityCulling =
((ob->gameflag2 & OB_NEVER_DO_ACTIVITY_CULLING)!=0);
gameobj->SetIgnoreActivityCulling(ignoreActivityCulling);
// two options exists for deform: shape keys and armature
// only support relative shape key
bool bHasShapeKey = mesh->key != NULL && mesh->key->type==KEY_RELATIVE;
bool bHasDvert = mesh->dvert != NULL && ob->defbase.first;
bool bHasArmature = (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && bHasDvert);
if (bHasShapeKey) {
// not that we can have shape keys without dvert!
BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
if (bHasArmature)
dcont->LoadShapeDrivers(ob->parent);
} else if (bHasArmature) {
BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
} else if (bHasDvert) {
// this case correspond to a mesh that can potentially deform but not with the
// object to which it is attached for the moment. A skin mesh was created in
// BL_ConvertMesh() so must create a deformer too!
BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
}
MT_Point3 min = MT_Point3(center) - MT_Vector3(extents);
MT_Point3 max = MT_Point3(center) + MT_Vector3(extents);
SG_BBox bbox = SG_BBox(min, max);
gameobj->GetSGNode()->SetBBox(bbox);
gameobj->GetSGNode()->SetRadius(radius);
break;
}
case OB_ARMATURE:
{
gameobj = new BL_ArmatureObject(
kxscene,
KX_Scene::m_callbacks,
ob // handle
);
/* Get the current pose from the armature object and apply it as the rest pose */
break;
}
case OB_EMPTY:
{
gameobj = new KX_EmptyObject(kxscene,KX_Scene::m_callbacks);
// set transformation
break;
}
}
if (gameobj)
{
gameobj->SetPhysicsEnvironment(kxscene->GetPhysicsEnvironment());
gameobj->SetLayer(ob->lay);
gameobj->SetBlenderObject(ob);
/* set the visibility state based on the objects render option in the outliner */
if(ob->restrictflag & OB_RESTRICT_RENDER) gameobj->SetVisible(0, 0);
}
return gameobj;
}
struct parentChildLink {
struct Object* m_blenderchild;
SG_Node* m_gamechildnode;
};
#include "DNA_constraint_types.h"
#include "BIF_editconstraint.h"
bPoseChannel *get_active_posechannel2 (Object *ob)
{
bArmature *arm= (bArmature*)ob->data;
bPoseChannel *pchan;
/* find active */
for(pchan= (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if(pchan->bone && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer))
return pchan;
}
return NULL;
}
ListBase *get_active_constraints2(Object *ob)
{
if (!ob)
return NULL;
if (ob->flag & OB_POSEMODE) {
bPoseChannel *pchan;
pchan = get_active_posechannel2(ob);
if (pchan)
return &pchan->constraints;
}
else
return &ob->constraints;
return NULL;
}
void RBJconstraints(Object *ob)//not used
{
ListBase *conlist;
bConstraint *curcon;
conlist = get_active_constraints2(ob);
if (conlist) {
for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
printf("%i\n",curcon->type);
}
}
}
#include "PHY_IPhysicsEnvironment.h"
#include "KX_IPhysicsController.h"
#include "PHY_DynamicTypes.h"
KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc){//not used
for (int j=0;j<sumolist->GetCount();j++)
{
KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j);
if (gameobje->GetName()==busc)
return gameobje->GetPhysicsController();
}
return 0;
}
KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){
for (int j=0;j<sumolist->GetCount();j++)
{
KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j);
if (gameobje->GetName()==busc)
return gameobje;
}
return 0;
}
// convert blender objects into ketsji gameobjects
void BL_ConvertBlenderObjects(struct Main* maggie,
const STR_String& scenename,
KX_Scene* kxscene,
KX_KetsjiEngine* ketsjiEngine,
e_PhysicsEngine physics_engine,
PyObject* pythondictionary,
SCA_IInputDevice* keydev,
RAS_IRenderTools* rendertools,
RAS_ICanvas* canvas,
KX_BlenderSceneConverter* converter,
bool alwaysUseExpandFraming
)
{
Scene *blenderscene = converter->GetBlenderSceneForName(scenename);
// for SETLOOPER
Scene *sce;
Base *base;
// Get the frame settings of the canvas.
// Get the aspect ratio of the canvas as designed by the user.
RAS_FrameSettings::RAS_FrameType frame_type;
int aspect_width;
int aspect_height;
vector<MT_Vector3> inivel,iniang;
set<Group*> grouplist; // list of groups to be converted
set<Object*> allblobj; // all objects converted
set<Object*> groupobj; // objects from groups (never in active layer)
if (alwaysUseExpandFraming) {
frame_type = RAS_FrameSettings::e_frame_extend;
aspect_width = canvas->GetWidth();
aspect_height = canvas->GetHeight();
} else {
if (blenderscene->framing.type == SCE_GAMEFRAMING_BARS) {
frame_type = RAS_FrameSettings::e_frame_bars;
} else if (blenderscene->framing.type == SCE_GAMEFRAMING_EXTEND) {
frame_type = RAS_FrameSettings::e_frame_extend;
} else {
frame_type = RAS_FrameSettings::e_frame_scale;
}
aspect_width = blenderscene->r.xsch;
aspect_height = blenderscene->r.ysch;
}
RAS_FrameSettings frame_settings(
frame_type,
blenderscene->framing.col[0],
blenderscene->framing.col[1],
blenderscene->framing.col[2],
aspect_width,
aspect_height
);
kxscene->SetFramingType(frame_settings);
kxscene->SetGravity(MT_Vector3(0,0,(blenderscene->world != NULL) ? -blenderscene->world->gravity : -9.8));
/* set activity culling parameters */
if (blenderscene->world) {
kxscene->SetActivityCulling( (blenderscene->world->mode & WO_ACTIVITY_CULLING) != 0);
kxscene->SetActivityCullingRadius(blenderscene->world->activityBoxRadius);
} else {
kxscene->SetActivityCulling(false);
}
int activeLayerBitInfo = blenderscene->lay;
// templist to find Root Parents (object with no parents)
CListValue* templist = new CListValue();
CListValue* sumolist = new CListValue();
vector<parentChildLink> vec_parent_child;
CListValue* objectlist = kxscene->GetObjectList();
CListValue* inactivelist = kxscene->GetInactiveList();
CListValue* parentlist = kxscene->GetRootParentList();
SCA_LogicManager* logicmgr = kxscene->GetLogicManager();
SCA_TimeEventManager* timemgr = kxscene->GetTimeEventManager();
CListValue* logicbrick_conversionlist = new CListValue();
//SG_TreeFactory tf;
// Convert actions to actionmap
bAction *curAct;
for (curAct = (bAction*)maggie->action.first; curAct; curAct=(bAction*)curAct->id.next)
{
logicmgr->RegisterActionName(curAct->id.name, curAct);
}
SetDefaultFaceType(blenderscene);
// Let's support scene set.
// Beware of name conflict in linked data, it will not crash but will create confusion
// in Python scripting and in certain actuators (replace mesh). Linked scene *should* have
// no conflicting name for Object, Object data and Action.
for (SETLOOPER(blenderscene, base))
{
Object* blenderobject = base->object;
allblobj.insert(blenderobject);
KX_GameObject* gameobj = gameobject_from_blenderobject(
base->object,
kxscene,
rendertools,
converter,
blenderscene);
bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
bool addobj=true;
if (converter->addInitFromFrame)
if (!isInActiveLayer)
addobj=false;
if (gameobj&&addobj)
{
MT_Point3 posPrev;
MT_Matrix3x3 angor;
if (converter->addInitFromFrame) blenderscene->r.cfra=blenderscene->r.sfra;
MT_Point3 pos = MT_Point3(
blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]
);
MT_Vector3 eulxyz = MT_Vector3(
blenderobject->rot[0],
blenderobject->rot[1],
blenderobject->rot[2]
);
MT_Vector3 scale = MT_Vector3(
blenderobject->size[0],
blenderobject->size[1],
blenderobject->size[2]
);
if (converter->addInitFromFrame){//rcruiz
float eulxyzPrev[3];
blenderscene->r.cfra=blenderscene->r.sfra-1;
update_for_newframe();
MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]
);
eulxyzPrev[0]=blenderobject->rot[0];
eulxyzPrev[1]=blenderobject->rot[1];
eulxyzPrev[2]=blenderobject->rot[2];
double fps = (double) blenderscene->r.frs_sec/
(double) blenderscene->r.frs_sec_base;
tmp.scale(fps, fps, fps);
inivel.push_back(tmp);
tmp=eulxyz-eulxyzPrev;
tmp.scale(fps, fps, fps);
iniang.push_back(tmp);
blenderscene->r.cfra=blenderscene->r.sfra;
update_for_newframe();
}
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
gameobj->NodeSetLocalScale(scale);
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
sumolist->Add(gameobj->AddRef());
BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
gameobj->SetName(blenderobject->id.name);
// templist to find Root Parents (object with no parents)
templist->Add(gameobj->AddRef());
// update children/parent hierarchy
if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
{
// blender has an additional 'parentinverse' offset in each object
SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
// define a normal parent relationship for this node.
KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
parentinversenode->SetParentRelation(parent_relation);
parentChildLink pclink;
pclink.m_blenderchild = blenderobject;
pclink.m_gamechildnode = parentinversenode;
vec_parent_child.push_back(pclink);
float* fl = (float*) blenderobject->parentinv;
MT_Transform parinvtrans(fl);
parentinversenode->SetLocalPosition(parinvtrans.getOrigin());
// problem here: the parent inverse transform combines scaling and rotation
// in the basis but the scenegraph needs separate rotation and scaling.
// This is not important for OpenGL (it uses 4x4 matrix) but it is important
// for the physic engine that needs a separate scaling
//parentinversenode->SetLocalOrientation(parinvtrans.getBasis());
// Extract the rotation and the scaling from the basis
MT_Matrix3x3 ori(parinvtrans.getBasis());
MT_Vector3 x(ori.getColumn(0));
MT_Vector3 y(ori.getColumn(1));
MT_Vector3 z(ori.getColumn(2));
MT_Vector3 scale(x.length(), y.length(), z.length());
if (!MT_fuzzyZero(scale[0]))
x /= scale[0];
if (!MT_fuzzyZero(scale[1]))
y /= scale[1];
if (!MT_fuzzyZero(scale[2]))
z /= scale[2];
ori.setColumn(0, x);
ori.setColumn(1, y);
ori.setColumn(2, z);
parentinversenode->SetLocalOrientation(ori);
parentinversenode->SetLocalScale(scale);
parentinversenode->AddChild(gameobj->GetSGNode());
}
// needed for python scripting
logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj);
// needed for group duplication
logicmgr->RegisterGameObj(blenderobject, gameobj);
for (int i = 0; i < gameobj->GetMeshCount(); i++)
logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject);
converter->RegisterGameObject(gameobj, blenderobject);
// this was put in rapidly, needs to be looked at more closely
// only draw/use objects in active 'blender' layers
logicbrick_conversionlist->Add(gameobj->AddRef());
if (converter->addInitFromFrame){
posPrev=gameobj->NodeGetWorldPosition();
angor=gameobj->NodeGetWorldOrientation();
}
if (isInActiveLayer)
{
objectlist->Add(gameobj->AddRef());
//tf.Add(gameobj->GetSGNode());
gameobj->NodeUpdateGS(0,true);
gameobj->AddMeshUser();
}
else
{
//we must store this object otherwise it will be deleted
//at the end of this function if it is not a root object
inactivelist->Add(gameobj->AddRef());
}
if (gameobj->IsDupliGroup())
grouplist.insert(blenderobject->dup_group);
if (converter->addInitFromFrame){
gameobj->NodeSetLocalPosition(posPrev);
gameobj->NodeSetLocalOrientation(angor);
}
}
/* Note about memory leak issues:
When a CValue derived class is created, m_refcount is initialized to 1
so the class must be released after being used to make sure that it won't
hang in memory. If the object needs to be stored for a long time,
use AddRef() so that this Release() does not free the object.
Make sure that for any AddRef() there is a Release()!!!!
Do the same for any object derived from CValue, CExpression and NG_NetworkMessage
*/
if (gameobj)
gameobj->Release();
}
if (!grouplist.empty())
{
// now convert the group referenced by dupli group object
// keep track of all groups already converted
set<Group*> allgrouplist = grouplist;
set<Group*> tempglist;
// recurse
while (!grouplist.empty())
{
set<Group*>::iterator git;
tempglist.clear();
tempglist.swap(grouplist);
for (git=tempglist.begin(); git!=tempglist.end(); git++)
{
Group* group = *git;
GroupObject* go;
for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next)
{
Object* blenderobject = go->ob;
if (converter->FindGameObject(blenderobject) == NULL)
{
allblobj.insert(blenderobject);
groupobj.insert(blenderobject);
KX_GameObject* gameobj = gameobject_from_blenderobject(
blenderobject,
kxscene,
rendertools,
converter,
blenderscene);
// this code is copied from above except that
// object from groups are never in active layer
bool isInActiveLayer = false;
bool addobj=true;
if (converter->addInitFromFrame)
if (!isInActiveLayer)
addobj=false;
if (gameobj&&addobj)
{
MT_Point3 posPrev;
MT_Matrix3x3 angor;
if (converter->addInitFromFrame)
blenderscene->r.cfra=blenderscene->r.sfra;
MT_Point3 pos = MT_Point3(
blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]
);
MT_Vector3 eulxyz = MT_Vector3(
blenderobject->rot[0],
blenderobject->rot[1],
blenderobject->rot[2]
);
MT_Vector3 scale = MT_Vector3(
blenderobject->size[0],
blenderobject->size[1],
blenderobject->size[2]
);
if (converter->addInitFromFrame){//rcruiz
float eulxyzPrev[3];
blenderscene->r.cfra=blenderscene->r.sfra-1;
update_for_newframe();
MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]
);
eulxyzPrev[0]=blenderobject->rot[0];
eulxyzPrev[1]=blenderobject->rot[1];
eulxyzPrev[2]=blenderobject->rot[2];
double fps = (double) blenderscene->r.frs_sec/
(double) blenderscene->r.frs_sec_base;
tmp.scale(fps, fps, fps);
inivel.push_back(tmp);
tmp=eulxyz-eulxyzPrev;
tmp.scale(fps, fps, fps);
iniang.push_back(tmp);
blenderscene->r.cfra=blenderscene->r.sfra;
update_for_newframe();
}
gameobj->NodeSetLocalPosition(pos);
gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
gameobj->NodeSetLocalScale(scale);
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
BL_ConvertMaterialIpos(blenderobject,gameobj, converter);
sumolist->Add(gameobj->AddRef());
BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
gameobj->SetName(blenderobject->id.name);
// templist to find Root Parents (object with no parents)
templist->Add(gameobj->AddRef());
// update children/parent hierarchy
if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame))
{
// blender has an additional 'parentinverse' offset in each object
SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks());
// define a normal parent relationship for this node.
KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New();
parentinversenode->SetParentRelation(parent_relation);
parentChildLink pclink;
pclink.m_blenderchild = blenderobject;
pclink.m_gamechildnode = parentinversenode;
vec_parent_child.push_back(pclink);
float* fl = (float*) blenderobject->parentinv;
MT_Transform parinvtrans(fl);
parentinversenode->SetLocalPosition(parinvtrans.getOrigin());
// Extract the rotation and the scaling from the basis
MT_Matrix3x3 ori(parinvtrans.getBasis());
MT_Vector3 x(ori.getColumn(0));
MT_Vector3 y(ori.getColumn(1));
MT_Vector3 z(ori.getColumn(2));
MT_Vector3 scale(x.length(), y.length(), z.length());
if (!MT_fuzzyZero(scale[0]))
x /= scale[0];
if (!MT_fuzzyZero(scale[1]))
y /= scale[1];
if (!MT_fuzzyZero(scale[2]))
z /= scale[2];
ori.setColumn(0, x);
ori.setColumn(1, y);
ori.setColumn(2, z);
parentinversenode->SetLocalOrientation(ori);
parentinversenode->SetLocalScale(scale);
parentinversenode->AddChild(gameobj->GetSGNode());
}
// needed for python scripting
logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj);
// needed for group duplication
logicmgr->RegisterGameObj(blenderobject, gameobj);
for (int i = 0; i < gameobj->GetMeshCount(); i++)
logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject);
converter->RegisterGameObject(gameobj, blenderobject);
// this was put in rapidly, needs to be looked at more closely
// only draw/use objects in active 'blender' layers
logicbrick_conversionlist->Add(gameobj->AddRef());
if (converter->addInitFromFrame){
posPrev=gameobj->NodeGetWorldPosition();
angor=gameobj->NodeGetWorldOrientation();
}
if (isInActiveLayer)
{
objectlist->Add(gameobj->AddRef());
//tf.Add(gameobj->GetSGNode());
gameobj->NodeUpdateGS(0,true);
gameobj->AddMeshUser();
}
else
{
//we must store this object otherwise it will be deleted
//at the end of this function if it is not a root object
inactivelist->Add(gameobj->AddRef());
}
if (gameobj->IsDupliGroup())
{
// check that the group is not already converted
if (allgrouplist.insert(blenderobject->dup_group).second)
grouplist.insert(blenderobject->dup_group);
}
if (converter->addInitFromFrame){
gameobj->NodeSetLocalPosition(posPrev);
gameobj->NodeSetLocalOrientation(angor);
}
}
if (gameobj)
gameobj->Release();
}
}
}
}
}
// non-camera objects not supported as camera currently
if (blenderscene->camera && blenderscene->camera->type == OB_CAMERA) {
KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera);
if(gamecamera)
kxscene->SetActiveCamera(gamecamera);
}
// Set up armatures
set<Object*>::iterator oit;
for(oit=allblobj.begin(); oit!=allblobj.end(); oit++)
{
Object* blenderobj = *oit;
if (blenderobj->type==OB_MESH) {
Mesh *me = (Mesh*)blenderobj->data;
if (me->dvert){
BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj);
if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){
KX_GameObject *par = converter->FindGameObject(blenderobj->parent);
if (par && obj->GetDeformer())
((BL_SkinDeformer*)obj->GetDeformer())->SetArmature((BL_ArmatureObject*) par);
}
}
}
}
// create hierarchy information
int i;
vector<parentChildLink>::iterator pcit;
for (pcit = vec_parent_child.begin();!(pcit==vec_parent_child.end());++pcit)
{
struct Object* blenderchild = pcit->m_blenderchild;
struct Object* blenderparent = blenderchild->parent;
KX_GameObject* parentobj = converter->FindGameObject(blenderparent);
KX_GameObject* childobj = converter->FindGameObject(blenderchild);
assert(childobj);
if (!parentobj || objectlist->SearchValue(childobj) != objectlist->SearchValue(parentobj))
{
// special case: the parent and child object are not in the same layer.
// This weird situation is used in Apricot for test purposes.
// Resolve it by not converting the child
childobj->GetSGNode()->DisconnectFromParent();
delete pcit->m_gamechildnode;
// Now destroy the child object but also all its descendent that may already be linked
// Remove the child reference in the local list!
// Note: there may be descendents already if the children of the child were processed
// by this loop before the child. In that case, we must remove the children also
CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj);
childrenlist->Add(childobj->AddRef());
for ( i=0;i<childrenlist->GetCount();i++)
{
KX_GameObject* obj = static_cast<KX_GameObject*>(childrenlist->GetValue(i));
if (templist->RemoveValue(obj))
obj->Release();
if (sumolist->RemoveValue(obj))
obj->Release();
if (logicbrick_conversionlist->RemoveValue(obj))
obj->Release();
}
childrenlist->Release();
// now destroy recursively
kxscene->RemoveObject(childobj);
continue;
}
switch (blenderchild->partype)
{
case PARVERT1:
{
// creat a new vertex parent relationship for this node.
KX_VertexParentRelation * vertex_parent_relation = KX_VertexParentRelation::New();
pcit->m_gamechildnode->SetParentRelation(vertex_parent_relation);
break;
}
case PARSLOW:
{
// creat a new slow parent relationship for this node.
KX_SlowParentRelation * slow_parent_relation = KX_SlowParentRelation::New(blenderchild->sf);
pcit->m_gamechildnode->SetParentRelation(slow_parent_relation);
break;
}
case PARBONE:
{
// parent this to a bone
Bone *parent_bone = get_named_bone(get_armature(blenderchild->parent), blenderchild->parsubstr);
if(parent_bone) {
KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone);
pcit->m_gamechildnode->SetParentRelation(bone_parent_relation);
}
break;
}
case PARSKEL: // skinned - ignore
break;
case PAROBJECT:
case PARCURVE:
case PARKEY:
case PARVERT3:
default:
// unhandled
break;
}
parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode);
}
vec_parent_child.clear();
// find 'root' parents (object that has not parents in SceneGraph)
for (i=0;i<templist->GetCount();++i)
{
KX_GameObject* gameobj = (KX_GameObject*) templist->GetValue(i);
if (gameobj->GetSGNode()->GetSGParent() == 0)
{
parentlist->Add(gameobj->AddRef());
gameobj->NodeUpdateGS(0,true);
}
}
bool processCompoundChildren = false;
// create physics information
for (i=0;i<sumolist->GetCount();i++)
{
KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
struct Object* blenderobject = converter->FindBlenderObject(gameobj);
int nummeshes = gameobj->GetMeshCount();
RAS_MeshObject* meshobj = 0;
if (nummeshes > 0)
{
meshobj = gameobj->GetMesh(0);
}
int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0;
BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren);
}
processCompoundChildren = true;
// create physics information
for (i=0;i<sumolist->GetCount();i++)
{
KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
struct Object* blenderobject = converter->FindBlenderObject(gameobj);
int nummeshes = gameobj->GetMeshCount();
RAS_MeshObject* meshobj = 0;
if (nummeshes > 0)
{
meshobj = gameobj->GetMesh(0);
}
int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0;
BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren);
}
//set ini linearVel and int angularVel //rcruiz
if (converter->addInitFromFrame)
for (i=0;i<sumolist->GetCount();i++)
{
KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
if (gameobj->IsDynamic()){
gameobj->setLinearVelocity(inivel[i],false);
gameobj->setAngularVelocity(iniang[i],false);
}
}
// create physics joints
for (i=0;i<sumolist->GetCount();i++)
{
KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i);
struct Object* blenderobject = converter->FindBlenderObject(gameobj);
ListBase *conlist;
bConstraint *curcon;
conlist = get_active_constraints2(blenderobject);
if (conlist) {
for (curcon = (bConstraint *)conlist->first; curcon; curcon=(bConstraint *)curcon->next) {
if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT){
bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data;
if (!dat->child){
PHY_IPhysicsController* physctr2 = 0;
if (dat->tar)
{
KX_GameObject *gotar=getGameOb(dat->tar->id.name,sumolist);
if (gotar && gotar->GetPhysicsController())
physctr2 = (PHY_IPhysicsController*) gotar->GetPhysicsController()->GetUserData();
}
if (gameobj->GetPhysicsController())
{
float radsPerDeg = 6.283185307179586232f / 360.f;
PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) gameobj->GetPhysicsController()->GetUserData();
//we need to pass a full constraint frame, not just axis
//localConstraintFrameBasis
MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*dat->axX,radsPerDeg*dat->axY,radsPerDeg*dat->axZ));
MT_Vector3 axis0 = localCFrame.getColumn(0);
MT_Vector3 axis1 = localCFrame.getColumn(1);
MT_Vector3 axis2 = localCFrame.getColumn(2);
int constraintId = kxscene->GetPhysicsEnvironment()->createConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX,
(float)dat->pivY,(float)dat->pivZ,
(float)axis0.x(),(float)axis0.y(),(float)axis0.z(),
(float)axis1.x(),(float)axis1.y(),(float)axis1.z(),
(float)axis2.x(),(float)axis2.y(),(float)axis2.z());
if (constraintId)
{
//if it is a generic 6DOF constraint, set all the limits accordingly
if (dat->type == PHY_GENERIC_6DOF_CONSTRAINT)
{
int dof;
int dofbit=1;
for (dof=0;dof<6;dof++)
{
if (dat->flag & dofbit)
{
kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]);
} else
{
//minLimit > maxLimit means free(disabled limit) for this degree of freedom
kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,1,-1);
}
dofbit<<=1;
}
}
}
}
}
}
}
}
}
templist->Release();
sumolist->Release();
int executePriority=0; /* incremented by converter routines */
// convert global sound stuff
/* XXX, glob is the very very wrong place for this
* to be, re-enable once the listener has been moved into
* the scene. */
#if 1
SND_Scene* soundscene = kxscene->GetSoundScene();
SND_SoundListener* listener = soundscene->GetListener();
if (listener && G.listener)
{
listener->SetDopplerFactor(G.listener->dopplerfactor);
listener->SetDopplerVelocity(G.listener->dopplervelocity);
listener->SetGain(G.listener->gain);
}
#endif
// convert world
KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene->world);
converter->RegisterWorldInfo(worldinfo);
kxscene->SetWorldInfo(worldinfo);
#define CONVERT_LOGIC
#ifdef CONVERT_LOGIC
// convert logic bricks, sensors, controllers and actuators
for (i=0;i<logicbrick_conversionlist->GetCount();i++)
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
struct Object* blenderobj = converter->FindBlenderObject(gameobj);
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, layerMask,isInActiveLayer,rendertools,converter);
}
for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
struct Object* blenderobj = converter->FindBlenderObject(gameobj);
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,layerMask,isInActiveLayer,converter);
}
for ( i=0;i<logicbrick_conversionlist->GetCount();i++)
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
struct Object* blenderobj = converter->FindBlenderObject(gameobj);
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter);
// set the init state to all objects
gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
}
// apply the initial state to controllers, only on the active objects as this registers the sensors
for ( i=0;i<objectlist->GetCount();i++)
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(objectlist->GetValue(i));
gameobj->ResetState();
}
#endif //CONVERT_LOGIC
logicbrick_conversionlist->Release();
// Calculate the scene btree -
// too slow - commented out.
//kxscene->SetNodeTree(tf.MakeTree());
// instantiate dupli group, we will loop trough the object
// that are in active layers. Note that duplicating group
// has the effect of adding objects at the end of objectlist.
// Only loop through the first part of the list.
int objcount = objectlist->GetCount();
for (i=0;i<objcount;i++)
{
KX_GameObject* gameobj = (KX_GameObject*) objectlist->GetValue(i);
if (gameobj->IsDupliGroup())
{
kxscene->DupliGroupRecurse(gameobj, 0);
}
}
KX_Camera *activecam = kxscene->GetActiveCamera();
MT_Scalar distance = (activecam)? activecam->GetCameraFar() - activecam->GetCameraNear(): 100.0f;
RAS_BucketManager *bucketmanager = kxscene->GetBucketManager();
bucketmanager->OptimizeBuckets(distance);
}