From 7afacb6ea86ffd3de726f93086ba3fedca428352 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 15 Jul 2008 20:05:23 +0000 Subject: BGE patch: DUPLIGROUP option supported in BGE. Blender duplicates groups in the 3D view at the location of objects having the DUPLIGROUP option set. This feature is now supported in the BGE: the groups will be instantiated as in the 3D view when the scene is converted. This is useful to populate a scene with multiple enemies without having to actually duplicate the objects in the blend file. Notes: * The BGE applies the same criteria to instantiate the group as Blender to display them: if you see the group in the 3D view, it will be instantiated in the BGE. * Groups are instantiated as if the object having the DUPLIGROUP option (usually an empty) executed an AddObject actuator on the top objects of the group (objects without parent). * As a result, only intra-group parent relationship is supported: the BGE will not instantiate objects that have parents outside the group. * Intra-group logic bricks connections are preserved between the duplicated objects, even between the top objects of the group. * For best result, the state engine of the objects in the group should be self-contained: logic bricks should only have intra-group connections. Use messages to communicate with state engines outside the group. * Nested groups are supported: if one or more objects in the group have the DUPLIGROUP option set, the corresponding groups will be instantiated at the corresponding position and orientation. * Nested groups are instantiated as separate groups, not as one big group. * Linked groups are supported as well as groups containing objects from the active layers. * There is a difference in the way Blender displays the groups in the 3D view and how BGE instantiates them: Blender does not take into account the parent relationship in the group and displays the objects as if they were all children of the object having the DUPLIGROUP option. That's correct for the top objects of the group but not for the children. Hence the orientation of the children objects may be different in the BGE. * An AddGroup actuator will be added in a future release. --- .../Converter/BL_BlenderDataConversion.cpp | 243 +++++++++++++++++++-- 1 file changed, 227 insertions(+), 16 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index f3e22cd297a..1f1ac6da119 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1847,7 +1847,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int aspect_width; int aspect_height; vector inivel,iniang; - + set grouplist; // list of groups to be converted + set allblobj; // all objects converted + set groupobj; // objects from groups (never in active layer) + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -1919,6 +1922,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for (SETLOOPER(blenderscene, base)) { Object* blenderobject = base->object; + allblobj.insert(blenderobject); + KX_GameObject* gameobj = gameobject_from_blenderobject( base->object, kxscene, @@ -2046,7 +2051,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); gameobj->Bucketize(); - + + if (gameobj->IsDupliGroup()) + grouplist.insert(blenderobject->dup_group); } else { @@ -2073,6 +2080,188 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } + if (!grouplist.empty()) + { + // now convert the group referenced by dupli group object + // keep track of all groups already converted + set allgrouplist = grouplist; + set tempglist; + // recurse + while (!grouplist.empty()) + { + set::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 is 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); + // TODO: expand to multiple ipos per mesh + Material *mat = give_current_material(blenderobject, 1); + if(mat) BL_ConvertMaterialIpos(mat, 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()); + parentinversenode->SetLocalOrientation(parinvtrans.getBasis()); + + parentinversenode->AddChild(gameobj->GetSGNode()); + } + + // needed for python scripting + logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); + + // needed for dynamic object morphing + logicmgr->RegisterGameObj(gameobj, blenderobject); + 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->Bucketize(); + + } + 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(); + } + } + } + } + } + if (blenderscene->camera) { KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera); @@ -2081,15 +2270,18 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } // Set up armatures - for(SETLOOPER(blenderscene, base)){ - if (base->object->type==OB_MESH){ - Mesh *me = (Mesh*)base->object->data; + set::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){ - KX_GameObject *obj = converter->FindGameObject(base->object); + KX_GameObject *obj = converter->FindGameObject(blenderobj); - if (base->object->parent && base->object->parent->type==OB_ARMATURE && base->object->partype==PARSKEL){ - KX_GameObject *par = converter->FindGameObject(base->object->parent); + if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ + KX_GameObject *par = converter->FindGameObject(blenderobj->parent); if (par) ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); } @@ -2174,7 +2366,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } processCompoundChildren = true; @@ -2189,7 +2382,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } @@ -2311,22 +2505,25 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, activeLayerBitInfo,isInActiveLayer,rendertools,converter); + 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;iGetCount();i++) { KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,activeLayerBitInfo,isInActiveLayer,converter); + 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;iGetCount();i++) { KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,activeLayerBitInfo,isInActiveLayer,canvas,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); } // apply the initial state to controllers for ( i=0;iGetCount();i++) @@ -2344,5 +2541,19 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // 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;iGetValue(i); + if (gameobj->IsDupliGroup()) + { + kxscene->DupliGroupRecurse(gameobj, 0); + } + } } -- cgit v1.2.3 From dbfc5f6b7110031a82da4482d62ed8b36873b369 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 16 Jul 2008 21:24:54 +0000 Subject: BGE patch: fix mesh deformation errors with duplicated objects sharing the same mesh in case of 1) armature+multiple material 2) shape drivers --- source/gameengine/Converter/BL_ShapeDeformer.cpp | 7 ++++ source/gameengine/Converter/BL_SkinDeformer.cpp | 48 ++++++++++++------------ source/gameengine/Converter/BL_SkinDeformer.h | 6 ++- 3 files changed, 36 insertions(+), 25 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index eb5c1467ea5..b2e54539b19 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -109,6 +109,13 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) vector::iterator it; void *poin; int type; + // the shape drivers use the bone matrix as input. Must + // update the matrix now + Object* par_arma = m_armobj->GetArmatureObject(); + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + PoseApplied(true); + for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver IpoCurve *icu = *it; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d3442fe5298..f96c40c098f 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -66,7 +66,8 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, m_armobj(arma), m_lastArmaUpdate(-1), m_defbase(&bmeshobj->defbase), - m_releaseobject(false) + m_releaseobject(false), + m_poseApplied(false) { Mat4CpyMat4(m_obmat, bmeshobj->obmat); }; @@ -98,32 +99,28 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } -bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *) +bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { size_t i, j; - if (!Update()) - // no need to update the cache - return false; + // update the vertex in m_transverts + Update(); - // Update all materials at once, so we can do the above update test - // without ending up with some materials not updated - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); - mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + // For each array + for (i=0; iGetArmatureObject(); - where_is_pose( par_arma ); + if (!PoseApplied()){ + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + } /* store verts locally */ VerifyStorage(); @@ -180,7 +179,8 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - + /* reset for next frame */ + PoseApplied(false); /* indicate that the m_transverts and normals are up to date */ return true; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index f35db8273c4..d3fc5ae2a81 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -81,10 +81,13 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool PoseApplied() + { return m_poseApplied; } + void PoseApplied(bool applied) + { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { - m_armobj->ApplyPose(); return true; } return false; @@ -102,6 +105,7 @@ protected: ListBase* m_defbase; float m_obmat[4][4]; // the reference matrix for skeleton deform bool m_releaseobject; + bool m_poseApplied; }; -- cgit v1.2.3 From 9ed079bf5cbe8a5a371190a8dedec970bcbd3ac2 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 19 Jul 2008 07:45:19 +0000 Subject: BGE patch: Relink actuators with target within group when duplicating group; generalize protection against object deletion for all actuators that point to objects. Certain actuators hold a pointer to an objects: Property, SceneCamera, AddObject, Camera, Parent, TractTo. When a group is duplicated, the actuators that point to objects within the group will be relinked to point to the replicated objects and not to the original objects. This helps to setup self-contained group with a camera following a character for example. This feature also works when adding a single object (and all its children) with the AddObject actuator. The second part of the patch extends the protection against object deletion to all the actuators of the above list (previously, only the TrackTo, AddObject and Property actuators were protected). In case the target object of these actuators is deleted, the BGE won't crash. --- source/gameengine/Converter/BL_DeformableGameObject.h | 1 + source/gameengine/Converter/KX_ConvertActuators.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 57a404ad72b..315ad18c42c 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -60,6 +60,7 @@ public: { if (m_pDeformer) m_pDeformer->Relink (map); + KX_GameObject::Relink(map); }; void ProcessReplica(KX_GameObject* replica); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 1cc1b2e27a3..8739fb109fd 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -503,7 +503,7 @@ void BL_ConvertActuators(char* maggiename, case ACT_PROPERTY: { bPropertyActuator* propact = (bPropertyActuator*) bact->data; - CValue* destinationObj = NULL; + SCA_IObject* destinationObj = NULL; /* here the destinationobject is searched. problem with multiple scenes: other scenes -- cgit v1.2.3 From a18c723d5514d3ee74b3d770f8e025091eee47c7 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 22 Jul 2008 23:05:06 +0000 Subject: BGE patch: Add min/max parameters to orientation constraint actuator The min/max parameters define a minimum/maximum angle that the object axis can have with the reference direction without being constrainted. The angle is expressed in degree and is limited to 0-180 range. The min/max parameters define a conical free zone around the reference direction. If the object axis is outside that free zone, the actuator will tend to put it back using as a temporary reference direction the vector that is exactly at min or max degree of the reference direction (depending if the axis angle is below the minimum or above the maximum) and is located in the plane formed by the axis and the reference direction. With a low damping value, this is equivalent to clamping the axis orientation within min/max degree of the reference direction. Backward compatibility corresponds to the absence of free zone: min = max = 0. --- source/gameengine/Converter/KX_ConvertActuators.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 8739fb109fd..f2ec01db839 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -628,6 +628,8 @@ void BL_ConvertActuators(char* maggiename, /* convert settings... degrees in the ui become radians */ /* internally */ if (conact->type == ACT_CONST_TYPE_ORI) { + min = (MT_2_PI * conact->minloc[0])/360.0; + max = (MT_2_PI * conact->maxloc[0])/360.0; switch (conact->mode) { case ACT_CONST_DIRPX: locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX; -- cgit v1.2.3 From 5eb14d70b9c70d155291446ad662ede658f69e6d Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 23 Jul 2008 21:37:37 +0000 Subject: BGE patch: Add PyDoc for new logic bricks, set exception message on Py error, remove args on Py functions that don't take any to save CPU time --- .../Converter/BL_ShapeActionActuator.cpp | 59 ++++++++++------------ .../gameengine/Converter/BL_ShapeActionActuator.h | 16 +++--- .../gameengine/Converter/KX_ConvertActuators.cpp | 12 ++--- 3 files changed, 40 insertions(+), 47 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 7196b393ed4..242d648b062 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -442,15 +442,15 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc}, - {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc}, - {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc}, - {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc}, - {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc}, - {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc}, - {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc}, - {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc}, - {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, - {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_VARARGS, SetType_doc}, + {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc}, + {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, GetStart_doc}, + {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, GetEnd_doc}, + {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, GetBlendin_doc}, + {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc}, + {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc}, + {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc}, + {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc}, + {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc}, {NULL,NULL} //Sentinel }; @@ -463,9 +463,7 @@ char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" "\tReturns a string containing the name of the current action.\n"; -PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) { PyObject *result; if (m_action){ @@ -484,9 +482,7 @@ char BL_ShapeActionActuator::GetProperty_doc[] = "getProperty()\n" "\tReturns the name of the property to be used in FromProp mode.\n"; -PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) { PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -499,9 +495,7 @@ char BL_ShapeActionActuator::GetFrame_doc[] = "getFrame()\n" "\tReturns the current frame number.\n"; -PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -514,9 +508,7 @@ char BL_ShapeActionActuator::GetEnd_doc[] = "getEnd()\n" "\tReturns the last frame of the action.\n"; -PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -529,9 +521,7 @@ char BL_ShapeActionActuator::GetStart_doc[] = "getStart()\n" "\tReturns the starting frame of the action.\n"; -PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -545,9 +535,7 @@ char BL_ShapeActionActuator::GetBlendin_doc[] = "\tReturns the number of interpolation animation frames to be\n" "\tgenerated when this actuator is triggered.\n"; -PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -561,9 +549,7 @@ char BL_ShapeActionActuator::GetPriority_doc[] = "\tReturns the priority for this actuator. Actuators with lower\n" "\tPriority numbers will override actuators with higher numbers.\n"; -PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) { PyObject *result; result = Py_BuildValue("i", m_priority); @@ -605,6 +591,7 @@ PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, } } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -627,6 +614,7 @@ PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, m_startframe = start; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -649,6 +637,7 @@ PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, m_endframe = end; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -672,6 +661,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, m_blendin = blendin; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -700,6 +690,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, m_blendframe = m_blendin; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -724,6 +715,7 @@ PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, m_priority = priority; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -750,6 +742,7 @@ PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, m_localtime=m_endframe; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -773,6 +766,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, m_propname = string; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -784,9 +778,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, char BL_ShapeActionActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; -PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) { return Py_BuildValue("h", m_playtype); } @@ -801,6 +793,7 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, short typeArg; if (!PyArg_ParseTuple(args, "h", &typeArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 434a62a1233..a9b9ad8fa86 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -87,15 +87,15 @@ public: KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetAction); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetBlendin); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetPriority); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetStart); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetEnd); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetFrame); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetProperty); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetAction); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetBlendin); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetPriority); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetStart); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetEnd); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrame); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetProperty); // KX_PYMETHOD(BL_ActionActuator,GetChannel); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetType); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); virtual PyObject* _getattr(const STR_String& attr); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index f2ec01db839..53ac730d203 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -658,18 +658,18 @@ void BL_ConvertActuators(char* maggiename, min = conact->minloc[2]; max = conact->maxloc[2]; break; - case ACT_CONST_DIRMX: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMX; + case ACT_CONST_DIRNX: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNX; min = conact->minloc[0]; max = conact->maxloc[0]; break; - case ACT_CONST_DIRMY: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMY; + case ACT_CONST_DIRNY: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY; min = conact->minloc[1]; max = conact->maxloc[1]; break; - case ACT_CONST_DIRMZ: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMZ; + case ACT_CONST_DIRNZ: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNZ; min = conact->minloc[2]; max = conact->maxloc[2]; break; -- cgit v1.2.3 From a7f951f25ef47a4ac98de0270b651dc74a27670d Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Fri, 25 Jul 2008 13:45:57 +0000 Subject: BGE patch: approve patch #17312: Multiple material IPOs per mesh in BGE. --- .../Converter/BL_BlenderDataConversion.cpp | 10 ++-- source/gameengine/Converter/KX_IpoConvert.cpp | 59 ++++++++++++++++------ source/gameengine/Converter/KX_IpoConvert.h | 2 +- 3 files changed, 47 insertions(+), 24 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 1f1ac6da119..ce37ea5907f 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1989,10 +1989,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); - // TODO: expand to multiple ipos per mesh - Material *mat = give_current_material(blenderobject, 1); - if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); - + BL_ConvertMaterialIpos(blenderobject, gameobj, converter); + sumolist->Add(gameobj->AddRef()); BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer); @@ -2171,9 +2169,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); - // TODO: expand to multiple ipos per mesh - Material *mat = give_current_material(blenderobject, 1); - if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); + BL_ConvertMaterialIpos(blenderobject,gameobj, converter); sumolist->Add(gameobj->AddRef()); diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 75ca59d01e7..7410beecaf4 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -36,6 +36,7 @@ #pragma warning (disable:4786) #endif +#include "BKE_material.h" /* give_current_material */ #include "KX_GameObject.h" #include "KX_IpoConvert.h" @@ -68,6 +69,8 @@ #include "SG_Node.h" +#include "STR_HashedString.h" + static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) { BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo); @@ -560,16 +563,15 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co } } - -void BL_ConvertMaterialIpos( - Material* blendermaterial, +static void ConvertMaterialIpos( + Material* blendermaterial, + dword matname_hash, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter ) { if (blendermaterial->ipo) { - - KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(); + KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); @@ -596,7 +598,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_R); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -610,7 +612,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -624,7 +626,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -638,7 +640,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_ALPHA); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -653,7 +655,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_R ); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -667,7 +669,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -681,7 +683,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -696,7 +698,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_HARD); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -710,7 +712,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -725,7 +727,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_REF); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -739,7 +741,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_EMIT); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -752,3 +754,28 @@ void BL_ConvertMaterialIpos( } } +void BL_ConvertMaterialIpos( + struct Object* blenderobject, + KX_GameObject* gameobj, + KX_BlenderSceneConverter *converter + ) +{ + if (blenderobject->totcol==1) + { + Material *mat = give_current_material(blenderobject, 1); + // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL + // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor + // because this yields a better performance as not all the vertex colors need to be edited + if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter); + } + else + { + for (int material_index=1; material_index <= blenderobject->totcol; material_index++) + { + Material *mat = give_current_material(blenderobject, material_index); + STR_HashedString matname = mat->id.name; + if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter); + } + } +} + diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index afcb1b22821..4ec9bd31062 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -46,7 +46,7 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera, class KX_GameObject* cameraobj, class KX_BlenderSceneConverter *converter); -void BL_ConvertMaterialIpos(struct Material* blendermaterial, +void BL_ConvertMaterialIpos(struct Object* blenderobject, class KX_GameObject* materialobj, class KX_BlenderSceneConverter *converter); -- cgit v1.2.3 From c4116a7f8de3738d9e771d8b1358d4e033c4e8fd Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 26 Jul 2008 11:00:21 +0000 Subject: BGE patch: support runtime duplication of groups. Adding an object with Dupligroup option set will cause the group to be instantiated. No special actuator is needed for this feature, just put dupligroup objects in inactive layers and add them dynamically --- source/gameengine/Converter/BL_BlenderDataConversion.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index ce37ea5907f..31a055fc734 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2027,8 +2027,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // needed for python scripting logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); - // needed for dynamic object morphing - logicmgr->RegisterGameObj(gameobj, blenderobject); + // needed for group duplication + logicmgr->RegisterGameObj(blenderobject, gameobj); for (int i = 0; i < gameobj->GetMeshCount(); i++) logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject); @@ -2050,8 +2050,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); gameobj->Bucketize(); - if (gameobj->IsDupliGroup()) - grouplist.insert(blenderobject->dup_group); } else { @@ -2059,6 +2057,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //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); @@ -2109,7 +2109,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, blenderscene); // this code is copied from above except that - // object from groups are never is active layer + // object from groups are never in active layer bool isInActiveLayer = false; bool addobj=true; @@ -2207,8 +2207,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // needed for python scripting logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); - // needed for dynamic object morphing - logicmgr->RegisterGameObj(gameobj, blenderobject); + // needed for group duplication + logicmgr->RegisterGameObj(blenderobject, gameobj); for (int i = 0; i < gameobj->GetMeshCount(); i++) logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject); -- cgit v1.2.3 From bc85f11e68d1c1af9e5d48afbe38c26686badcf3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 28 Jul 2008 14:28:19 +0000 Subject: Bugfix: game engine does not support non-camera type objects as a camera, would crash, so disabled using the object as a camera then. --- source/gameengine/Converter/BL_BlenderDataConversion.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 31a055fc734..320921722e1 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2258,7 +2258,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } - if (blenderscene->camera) { + // 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) -- cgit v1.2.3 From 908337bee11f6b55c34a5880ea241b3975c35287 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 29 Jul 2008 15:48:31 +0000 Subject: Game Engine: alpha blending and sorting ======================================= Alpha blending + sorting was revised, to fix bugs and get it to work more predictable. * A new per texture face "Sort" setting defines if the face is alpha sorted or not, instead of abusing the "ZTransp" setting as it did before. * Existing files are converted to hopefully match the old behavior as much as possible with a version patch. * On new meshes the Sort flag is disabled by the default, to avoid unexpected and hard to find slowdowns. * Alpha sorting for faces was incredibly slow. Sorting faces in a mesh with 600 faces lowered the framerate from 200 to 70 fps in my test.. the sorting there case goes about 15x faster now, but it is still advised to use Clip Alpha if possible instead of regular Alpha. * There still various limitations in the alpha sorting code, I've added some comments to the code about this. Some docs at the bottom of the page: http://www.blender.org/development/current-projects/changes-since-246/realtime-glsl-materials/ Merged some fixes from the apricot branch, most important change is that tangents are now exactly the same as the rest of Blender, instead of being computed in the game engine with a different algorithm. Also, the subversion was bumped to 1. --- .../Converter/BL_BlenderDataConversion.cpp | 637 +++++++++------------ 1 file changed, 278 insertions(+), 359 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 320921722e1..2cc5cfda84c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -136,8 +136,12 @@ #include "BKE_mesh.h" #include "MT_Point3.h" +#include "BLI_arithb.h" + extern "C" { - #include "BKE_customdata.h" +#include "BKE_customdata.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" } #include "BKE_material.h" /* give_current_material */ @@ -309,7 +313,6 @@ typedef struct MTF_localLayer // ------------------------------------ BL_Material* ConvertMaterial( - Mesh* mesh, Material *mat, MTFace* tface, const char *tfaceName, @@ -323,15 +326,16 @@ BL_Material* ConvertMaterial( //this needs some type of manager BL_Material *material = new BL_Material(); - int numchan = -1; + int numchan = -1, texalpha = 0; bool validmat = (mat!=0); - bool validface = (mesh->mtface && tface); + bool validface = (tface!=0); short type = 0; if( validmat ) type = 1; // material color material->IdMode = DEFAULT_BLENDER; + material->glslmat = (validmat)? glslmat: false; // -------------------------------- if(validmat) { @@ -367,12 +371,13 @@ BL_Material* ConvertMaterial( 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->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0; + if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; else @@ -430,6 +435,8 @@ BL_Material* ConvertMaterial( 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) { @@ -546,17 +553,7 @@ BL_Material* ConvertMaterial( material->ref = mat->ref; material->amb = mat->amb; - // set alpha testing without z-sorting - if( ( validface && (!(tface->transp &~ TF_CLIP))) && mat->mode & MA_ZTRA) { - // sets the RAS_IPolyMaterial::m_flag |RAS_FORCEALPHA - // this is so we don't have the overhead of the z-sorting code - material->ras_mode|=ALPHA_TEST; - } - else{ - // use regular z-sorting - material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0; - } - material->ras_mode |= ((mat->mode & MA_WIRE) != 0)?WIRE:0; + material->ras_mode |= (mat->mode & MA_WIRE)? WIRE: 0; } else { int valid = 0; @@ -574,7 +571,6 @@ BL_Material* ConvertMaterial( 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; - material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0; valid++; } } @@ -607,10 +603,6 @@ BL_Material* ConvertMaterial( material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; - - if(tface->transp&~TF_CLIP) - material->ras_mode |= TRANSP; - material->tile = tface->tile; material->mode = tface->mode; @@ -631,7 +623,15 @@ BL_Material* ConvertMaterial( 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->ras_mode |= ALPHA; + material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; + } // get uv sets if(validmat) @@ -711,132 +711,54 @@ BL_Material* ConvertMaterial( } -static void BL_ComputeTriTangentSpace(const MT_Vector3 &v1, const MT_Vector3 &v2, const MT_Vector3 &v3, - const MT_Vector2 &uv1, const MT_Vector2 &uv2, const MT_Vector2 &uv3, - MFace* mface, MT_Vector3 *tan1, MT_Vector3 *tan2) -{ - MT_Vector3 dx1(v2 - v1), dx2(v3 - v1); - MT_Vector2 duv1(uv2 - uv1), duv2(uv3 - uv1); - - MT_Scalar r = 1.0 / (duv1.x() * duv2.y() - duv2.x() * duv1.y()); - duv1 *= r; - duv2 *= r; - MT_Vector3 sdir(duv2.y() * dx1 - duv1.y() * dx2); - MT_Vector3 tdir(duv1.x() * dx2 - duv2.x() * dx1); - - tan1[mface->v1] += sdir; - tan1[mface->v2] += sdir; - tan1[mface->v3] += sdir; - - tan2[mface->v1] += tdir; - tan2[mface->v2] += tdir; - tan2[mface->v3] += tdir; -} - -static MT_Vector4* BL_ComputeMeshTangentSpace(Mesh* mesh) -{ - MFace* mface = static_cast(mesh->mface); - MTFace* tface = static_cast(mesh->mtface); - - MT_Vector3 *tan1 = new MT_Vector3[mesh->totvert]; - MT_Vector3 *tan2 = new MT_Vector3[mesh->totvert]; - - int v; - for (v = 0; v < mesh->totvert; v++) - { - tan1[v] = MT_Vector3(0.0, 0.0, 0.0); - tan2[v] = MT_Vector3(0.0, 0.0, 0.0); - } - - for (int p = 0; p < mesh->totface; p++, mface++, tface++) - { - MT_Vector3 v1(mesh->mvert[mface->v1].co), - v2(mesh->mvert[mface->v2].co), - v3(mesh->mvert[mface->v3].co); - - MT_Vector2 uv1(tface->uv[0]), - uv2(tface->uv[1]), - uv3(tface->uv[2]); - - BL_ComputeTriTangentSpace(v1, v2, v3, uv1, uv2, uv3, mface, tan1, tan2); - if (mface->v4) - { - MT_Vector3 v4(mesh->mvert[mface->v4].co); - MT_Vector2 uv4(tface->uv[3]); - - BL_ComputeTriTangentSpace(v1, v3, v4, uv1, uv3, uv4, mface, tan1, tan2); - } - } - - MT_Vector4 *tangent = new MT_Vector4[mesh->totvert]; - for (v = 0; v < mesh->totvert; v++) - { - const MT_Vector3 no(mesh->mvert[v].no[0]/32767.0, - mesh->mvert[v].no[1]/32767.0, - mesh->mvert[v].no[2]/32767.0); - // Gram-Schmidt orthogonalize - MT_Vector3 t(tan1[v] - no.cross(no.cross(tan1[v]))); - if (!MT_fuzzyZero(t)) - t /= t.length(); - - tangent[v].x() = t.x(); - tangent[v].y() = t.y(); - tangent[v].z() = t.z(); - // Calculate handedness - tangent[v].w() = no.dot(tan1[v].cross(tan2[v])) < 0.0 ? -1.0 : 1.0; - } - - delete [] tan1; - delete [] tan2; - - return tangent; -} - RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; - bool skinMesh = false; - + bool skinMesh = false; int lightlayer = blenderobj->lay; - - MFace* mface = static_cast(mesh->mface); - MTFace* tface = static_cast(mesh->mtface); + + // 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(dm->getFaceDataArray(dm, CD_MTFACE)); + MCol *mcol = static_cast(dm->getFaceDataArray(dm, CD_MCOL)); + float (*tangent)[3] = NULL; + int totface = dm->getNumFaces(dm); const char *tfaceName = ""; - MCol* mmcol = mesh->mcol; - MT_assert(mface || mesh->totface == 0); + 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){ + if (mesh->dvert || mesh->key) { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } - else { + else meshobj = new RAS_MeshObject(mesh, lightlayer); - } - MT_Vector4 *tangent = 0; - if (tface) - tangent = BL_ComputeMeshTangentSpace(mesh); - // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; - for (int lay=0; layfdata.totlayer; i++) + for (int i=0; ifaceData.totlayer; i++) { - if (mesh->fdata.layers[i].type == CD_MTFACE) + if (dm->faceData.layers[i].type == CD_MTFACE) { assert(validLayers <= 8); - layers[validLayers].face = (MTFace*)mesh->fdata.layers[i].data;; - layers[validLayers].name = mesh->fdata.layers[i].name; + 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++; @@ -844,271 +766,269 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert); - for (int f=0;ftotface;f++,mface++) + meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + + for (int f=0;fv3) - { - 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); - // rgb3 is set from the adjoint face in a square - unsigned int rgb0,rgb1,rgb2,rgb3 = 0; - MT_Vector3 no0(mesh->mvert[mface->v1].no[0], mesh->mvert[mface->v1].no[1], mesh->mvert[mface->v1].no[2]), - no1(mesh->mvert[mface->v2].no[0], mesh->mvert[mface->v2].no[1], mesh->mvert[mface->v2].no[2]), - no2(mesh->mvert[mface->v3].no[0], mesh->mvert[mface->v3].no[1], mesh->mvert[mface->v3].no[2]), - no3(0.0, 0.0, 0.0); - MT_Point3 pt0(mesh->mvert[mface->v1].co), - pt1(mesh->mvert[mface->v2].co), - pt2(mesh->mvert[mface->v3].co), - pt3(0.0, 0.0, 0.0); - MT_Vector4 tan0(0.0, 0.0, 0.0, 0.0), - tan1(0.0, 0.0, 0.0, 0.0), - tan2(0.0, 0.0, 0.0, 0.0), - tan3(0.0, 0.0, 0.0, 0.0); - - no0 /= 32767.0; - no1 /= 32767.0; - no2 /= 32767.0; - if (mface->v4) - { - pt3 = MT_Point3(mesh->mvert[mface->v4].co); - no3 = MT_Vector3(mesh->mvert[mface->v4].no[0], mesh->mvert[mface->v4].no[1], mesh->mvert[mface->v4].no[2]); - no3 /= 32767.0; + 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_Vector3 no0, no1, no2, no3; + MT_Point3 pt0, pt1, pt2, pt3; + MT_Vector4 tan0, tan1, tan2, tan3; + + /* 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 + no3 = MT_Vector3(0.0, 0.0, 0.0); + } + 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); - if(!(mface->flag & ME_SMOOTH)) - { - MT_Vector3 norm = ((pt1-pt0).cross(pt2-pt0)).safe_normalized(); - norm[0] = ((int) (10*norm[0]))/10.0; - norm[1] = ((int) (10*norm[1]))/10.0; - norm[2] = ((int) (10*norm[2]))/10.0; - no0=no1=no2=no3= norm; - + { + bool polyvisible = 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; + + polyvisible = ((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, blenderobj ); } + else { + /* do Texture Face materials */ + Image* bima = (tface)? (Image*)tface->tpage: NULL; + STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - { - Material* ma = 0; - bool polyvisible = true; - RAS_IPolyMaterial* polymat = NULL; - BL_Material *bl_mat = NULL; - - if(converter->GetMaterials()) - { - if(mesh->totcol > 1) - ma = mesh->mat[mface->mat_nr]; - else - ma = give_current_material(blenderobj, 1); - - bl_mat = ConvertMaterial(mesh, ma, tface, tfaceName, mface, mmcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - // set the index were dealing with - bl_mat->material_index = (int)mface->mat_nr; - - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); - collider = ((bl_mat->ras_mode & COLLIDER)!=0); + 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; - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); - unsigned int rgb[4]; - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; - MT_Point2 uv[4]; - 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]; - - if(tangent){ - tan0 = tangent[mface->v1]; - tan1 = tangent[mface->v2]; - tan2 = tangent[mface->v3]; - if (mface->v4) - tan3 = tangent[mface->v4]; - } + 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; } - else - { - ma = give_current_material(blenderobj, 1); - Image* bima = ((mesh->mtface && tface) ? (Image*) tface->tpage : NULL); - - STR_String imastr = - ((mesh->mtface && tface) ? - (bima? (bima)->id.name : "" ) : "" ); - - char transp=0; - short mode=0, tile=0; - int tilexrep=4,tileyrep = 4; + /* 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 (bima) - { - tilexrep = bima->xrep; - tileyrep = bima->yrep; - - } + if (mface->v4) + rgb3 = KX_Mcol2uint_new(mcol[3]); + } + else { + /* no vertex colors, take from material, otherwise white */ + unsigned int color = 0xFFFFFFFFL; - if (mesh->mtface && tface) + if (ma) { - // Use texface colors if available - //TF_DYNAMIC means the polygon is a collision face - collider = ((tface->mode & TF_DYNAMIC) != 0); - transp = tface->transp &~ TF_CLIP; - tile = tface->tile; - mode = tface->mode; - - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; - 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 + 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); - mode = default_face_mode; - transp = TF_SOLID; - tile = 0; + color = col_converter.integer; } - if (mmcol) - { - // Use vertex colors - rgb0 = KX_Mcol2uint_new(mmcol[0]); - rgb1 = KX_Mcol2uint_new(mmcol[1]); - rgb2 = KX_Mcol2uint_new(mmcol[2]); - - if (mface->v4) - rgb3 = KX_Mcol2uint_new(mmcol[3]); - } - else { - // no vertex colors: take from material if we have one, - // otherwise set to white - unsigned int color = 0xFFFFFFFFL; + rgb0 = KX_rgbaint2uint_new(color); + rgb1 = KX_rgbaint2uint_new(color); + rgb2 = KX_rgbaint2uint_new(color); + + if (mface->v4) + rgb3 = KX_rgbaint2uint_new(color); + } + + bool istriangle = (mface->v4==0); - 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; - } + // 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, istriangle, blenderobj, tface, (unsigned int*)mcol); - rgb0 = KX_rgbaint2uint_new(color); - rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(color); - } - - bool istriangle = (mface->v4==0); - bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; - - polymat = new KX_PolygonMaterial(imastr, ma, - tile, tilexrep, tileyrep, - mode, transp, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mmcol); - - 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); + 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; + } + } - } else - { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.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); } - - // 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(); + } 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; } - - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + polymat = bucket->GetPolyMaterial(); + } + + int nverts = mface->v4?4:3; + int vtxarray = meshobj->FindVertexArray(nverts,polymat); + RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - bool flat; + bool flat; - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else + if (skinMesh) { + /* If the face is set to solid, all fnors are the same */ + if (mface->flag & ME_SMOOTH) flat = false; + else + flat = true; + } + else + flat = false; - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); + if (nverts==4) + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - meshobj->AddPolygon(poly); - if (poly->IsCollider()) + meshobj->AddPolygon(poly); + if (poly->IsCollider()) + { + RAS_TriangleIndex idx; + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v2; + idx.m_index[2] = mface->v3; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + if (nverts==4) { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v3; + idx.m_index[2] = mface->v4; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); } - -// poly->SetVisibleWireframeEdges(mface->edcode); - poly->SetCollider(collider); } + +// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetCollider(collider); } + if (tface) tface++; - if (mmcol) - mmcol+=4; + if (mcol) + mcol+=4; for (int lay=0; layGetPolyMaterial()->OnConstruction(); } - if(tangent) - delete [] tangent; - if (layers) delete []layers; + + dm->release(dm); return meshobj; } @@ -1819,7 +1738,7 @@ KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){ return 0; } -#include "BLI_arithb.h" + // convert blender objects into ketsji gameobjects void BL_ConvertBlenderObjects(struct Main* maggie, const STR_String& scenename, -- cgit v1.2.3 From 7f170c18bbc3ef3cc8e3b459b8bcc8a789ba0438 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 30 Jul 2008 16:15:15 +0000 Subject: Bugfixes: fix for two memory leaks related to dupligroups, and a missing reference count in the trackto actuator. This showed up as leaked pose data, but actually the whole object was not being freed. --- source/gameengine/Converter/BL_ActionActuator.cpp | 24 ++++++---------------- source/gameengine/Converter/BL_ArmatureObject.cpp | 9 ++++---- .../Converter/BL_BlenderDataConversion.cpp | 5 +++-- 3 files changed, 13 insertions(+), 25 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 5d6dd694765..2ee8b54a014 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -57,24 +57,12 @@ BL_ActionActuator::~BL_ActionActuator() { - - if (m_pose) { - free_pose_channels(m_pose); - MEM_freeN(m_pose); - m_pose = NULL; - }; - - if (m_userpose){ - free_pose_channels(m_userpose); - MEM_freeN(m_userpose); - m_userpose=NULL; - } - if (m_blendpose) { - free_pose_channels(m_blendpose); - MEM_freeN(m_blendpose); - m_blendpose = NULL; - }; - + if (m_pose) + free_pose(m_pose); + if (m_userpose) + free_pose(m_userpose); + if (m_blendpose) + free_pose(m_blendpose); } void BL_ActionActuator::ProcessReplica(){ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index f73d5b42a01..09f1d9d4d87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -82,10 +82,8 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) BL_ArmatureObject::~BL_ArmatureObject() { - if (m_mrdPose){ - free_pose_channels(m_mrdPose); - MEM_freeN(m_mrdPose); - } + if (m_mrdPose) + free_pose(m_mrdPose); } /* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ @@ -172,12 +170,13 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) // copy_pose (&m_mrdPose, m_pose, 0); //} - if (!*pose) + if (!*pose) { // must duplicate the constraints too otherwise we have corruption in free_pose_channels() // because it will free the blender constraints. // Ideally, blender should rememeber that the constraints were not copied so that // free_pose_channels() would not free them. copy_pose(pose, m_objArma->pose, 1); + } else extract_pose_from_pose(*pose, m_objArma->pose); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 2cc5cfda84c..da1767793bb 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -628,7 +628,8 @@ BL_Material* ConvertMaterial( material->transp = TF_ALPHA; // always zsort alpha + add - if(material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) { + 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; } @@ -1856,7 +1857,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (converter->addInitFromFrame) if (!isInActiveLayer) addobj=false; - + if (gameobj&&addobj) { MT_Point3 posPrev; -- cgit v1.2.3 From 8a8a12ed846dc86b2f9b21582fd34d941beed7ed Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 30 Jul 2008 17:41:47 +0000 Subject: BGE patch: logic optimization part 2: remove inactive sensors from logic manager. With this patch, only sensors that are connected to active states are actually registered in the logic manager. Inactive sensors won't take any CPU, especially the Radar and Near sensors that use a physical object for the detection: these objects are removed from the physics engine. To take advantage of this optimization patch, you need to define very light idle state when the objects are inactive: make them transparent, suspend the physics, keep few sensors active (e,g a message sensor to wake up), etc. --- source/gameengine/Converter/BL_BlenderDataConversion.cpp | 10 +++++----- source/gameengine/Converter/KX_ConvertSensors.cpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'source/gameengine/Converter') diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index da1767793bb..f44318120e8 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2441,13 +2441,13 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,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 - for ( i=0;iGetCount();i++) + // apply the initial state to controllers, only on the active objects as this registers the sensors + for ( i=0;iGetCount();i++) { - KX_GameObject* gameobj = static_cast(logicbrick_conversionlist->GetValue(i)); - struct Object* blenderobj = converter->FindBlenderObject(gameobj); - gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + KX_GameObject* gameobj = static_cast(objectlist->GetValue(i)); gameobj->ResetState(); } diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 7c9df688d45..5e433bb821b 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -733,9 +733,9 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj->AddSensor(gamesensor); // only register to manager if it's in an active layer - - if (isInActiveLayer) - gamesensor->RegisterToManager(); + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); for (int i=0;itotlinks;i++) -- cgit v1.2.3