diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-02 16:33:29 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-02 16:33:29 +0400 |
commit | b56ffd2cdb51021d1a3456af9e8f4b5451407c61 (patch) | |
tree | f51e4af01e685d779ff498b69496f9ff3a0eada1 /source/gameengine | |
parent | fefbdc4376b6bacdaba0ad50da3c706289301b3d (diff) | |
parent | 15afd240e04ef3f220b6133cc920d964dbcfcf85 (diff) |
Cycles: svn merge -r39669:39870 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source/gameengine')
90 files changed, 2991 insertions, 1617 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index f00dd279361..40f1701e44a 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -95,10 +95,6 @@ extern float BKE_screen_view3d_zoom_to_fac(float camzoom); #include "BKE_ipo.h" /***/ -#ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -#endif - //XXX #include "BSE_headerbuttons.h" #include "BKE_context.h" #include "../../blender/windowmanager/WM_types.h" @@ -108,6 +104,11 @@ extern float BKE_screen_view3d_zoom_to_fac(float camzoom); } #endif +#ifdef WITH_AUDASPACE +# include "AUD_C-API.h" +# include "AUD_I3DDevice.h" +# include "AUD_IDevice.h" +#endif static BlendFileData *load_game_data(char *filename) { @@ -186,6 +187,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c #endif bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0); bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE; + bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES; if(animation_record) usefixed= true; /* override since you's always want fixed time for sim recording */ @@ -235,6 +237,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjiengine->SetRasterizer(rasterizer); ketsjiengine->SetUseFixedTime(usefixed); ketsjiengine->SetTimingDisplay(frameRate, profile, properties); + ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS); #ifdef WITH_PYTHON CValue::SetDeprecationWarnings(nodepwarnings); @@ -393,9 +396,13 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext); // initialize 3D Audio Settings - AUD_setSpeedOfSound(scene->audio.speed_of_sound); - AUD_setDopplerFactor(scene->audio.doppler_factor); - AUD_setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); + AUD_I3DDevice* dev = AUD_get3DDevice(); + if(dev) + { + dev->setSpeedOfSound(scene->audio.speed_of_sound); + dev->setDopplerFactor(scene->audio.doppler_factor); + dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); + } // from see blender.c: // FIXME: this version patching should really be part of the file-reading code, @@ -580,7 +587,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c { delete canvas; canvas = NULL; - } + } + + // stop all remaining playing sounds + AUD_getDevice()->stopAll(); } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME); diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 7e353d590bb..50e887a21a8 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -36,6 +36,7 @@ #include "BL_ActionActuator.h" #include "BL_ArmatureObject.h" #include "BL_SkinDeformer.h" +#include "BL_Action.h" #include "KX_GameObject.h" #include "STR_HashedString.h" #include "MEM_guardedalloc.h" @@ -60,6 +61,49 @@ extern "C" { #include "RNA_define.h" } +BL_ActionActuator::BL_ActionActuator(SCA_IObject* gameobj, + const STR_String& propname, + const STR_String& framepropname, + float starttime, + float endtime, + struct bAction *action, + short playtype, + short blendin, + short priority, + short layer, + float layer_weight, + short ipo_flags, + short end_reset, + float stride) + : SCA_IActuator(gameobj, KX_ACT_ACTION), + + m_lastpos(0, 0, 0), + m_blendframe(0), + m_flag(0), + m_startframe (starttime), + m_endframe(endtime) , + m_starttime(0), + m_localtime(starttime), + m_lastUpdate(-1), + m_blendin(blendin), + m_blendstart(0), + m_stridelength(stride), + m_playtype(playtype), + m_priority(priority), + m_layer(layer), + m_layer_weight(layer_weight), + m_ipo_flags(ipo_flags), + m_pose(NULL), + m_blendpose(NULL), + m_userpose(NULL), + m_action(action), + m_propname(propname), + m_framepropname(framepropname) +{ + if (!end_reset) + m_flag |= ACT_FLAG_CONTINUE; +}; + BL_ActionActuator::~BL_ActionActuator() { if (m_pose) @@ -85,370 +129,217 @@ void BL_ActionActuator::SetBlendTime (float newtime){ m_blendframe = newtime; } -CValue* BL_ActionActuator::GetReplica() { - BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName()); - replica->ProcessReplica(); - return replica; -} - -bool BL_ActionActuator::ClampLocalTime() +void BL_ActionActuator::SetLocalTime(float curtime) { - if (m_startframe < m_endframe) + float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); + + if (m_endframe < m_startframe) + dt = -dt; + + m_localtime = m_startframe + dt; + + // Handle wrap around + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { - if (m_localtime < m_startframe) - { - m_localtime = m_startframe; - return true; - } - else if (m_localtime > m_endframe) + switch(m_playtype) { + case ACT_ACTION_PLAY: + // Clamp m_localtime = m_endframe; - return true; - } - } else { - if (m_localtime > m_startframe) - { + break; + case ACT_ACTION_LOOP_END: + // Put the time back to the beginning m_localtime = m_startframe; - return true; - } - else if (m_localtime < m_endframe) - { - m_localtime = m_endframe; - return true; + m_starttime = curtime; + break; + case ACT_ACTION_PINGPONG: + // Swap the start and end frames + float temp = m_startframe; + m_startframe = m_endframe; + m_endframe = temp; + + m_starttime = curtime; + + break; } } - return false; } -void BL_ActionActuator::SetStartTime(float curtime) +void BL_ActionActuator::ResetStartTime(float curtime) { - float direction = m_startframe < m_endframe ? 1.0 : -1.0; - - if (!(m_flag & ACT_FLAG_REVERSE)) - m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate(); - else - m_starttime = curtime - direction*(m_endframe - m_localtime)/KX_KetsjiEngine::GetAnimFrameRate(); -} + float dt = m_localtime - m_startframe; -void BL_ActionActuator::SetLocalTime(float curtime) -{ - float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); - - if (m_endframe < m_startframe) - delta_time = -delta_time; - - if (!(m_flag & ACT_FLAG_REVERSE)) - m_localtime = m_startframe + delta_time; - else - m_localtime = m_endframe - delta_time; + m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()); + //SetLocalTime(curtime); } +CValue* BL_ActionActuator::GetReplica() { + BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName()); + replica->ProcessReplica(); + return replica; +} bool BL_ActionActuator::Update(double curtime, bool frame) { bool bNegativeEvent = false; bool bPositiveEvent = false; - bool keepgoing = true; - bool wrap = false; - bool apply=true; - int priority; - float newweight; + bool bUseContinue = false; + KX_GameObject *obj = (KX_GameObject*)GetParent(); + short playtype = BL_Action::ACT_MODE_PLAY; + float start = m_startframe; + float end = m_endframe; + + // If we don't have an action, we can't do anything + if (!m_action) + return false; + + // Convert our playtype to one that BL_Action likes + switch(m_playtype) + { + case ACT_ACTION_LOOP_END: + case ACT_ACTION_LOOP_STOP: + playtype = BL_Action::ACT_MODE_LOOP; + break; + + case ACT_ACTION_PINGPONG: + // We handle ping pong ourselves to increase compabitility + // with files made prior to animation changes from GSoC 2011. + playtype = BL_Action::ACT_MODE_PLAY; + + if (m_flag & ACT_FLAG_REVERSE) + { + m_localtime = start; + start = end; + end = m_localtime; + } + + break; + case ACT_ACTION_FROM_PROP: + CValue* prop = GetParent()->GetProperty(m_propname); + + playtype = BL_Action::ACT_MODE_PLAY; + start = end = prop->GetNumber(); - curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + break; + } + + // Continue only really makes sense for play stop and flipper. All other modes go until they are complete. + if (m_flag & ACT_FLAG_CONTINUE && + (m_playtype == ACT_ACTION_LOOP_STOP || + m_playtype == ACT_ACTION_FLIPPER)) + bUseContinue = true; + - // result = true if animation has to be continued, false if animation stops - // maybe there are events for us in the queue ! + // Handle events if (frame) { bNegativeEvent = m_negevent; bPositiveEvent = m_posevent; RemoveAllEvents(); - - if (bPositiveEvent) - m_flag |= ACT_FLAG_ACTIVE; - - if (bNegativeEvent) - { - // dont continue where we left off when restarting - if (m_end_reset) { - m_flag &= ~ACT_FLAG_LOCKINPUT; - } - - if (!(m_flag & ACT_FLAG_ACTIVE)) - return false; - m_flag &= ~ACT_FLAG_ACTIVE; - } } - - /* We know that action actuators have been discarded from all non armature objects: - if we're being called, we're attached to a BL_ArmatureObject */ - BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent(); - float length = m_endframe - m_startframe; - - priority = m_priority; - - /* Determine pre-incrementation behaviour and set appropriate flags */ - switch (m_playtype){ - case ACT_ACTION_MOTION: - if (bNegativeEvent){ - keepgoing=false; - apply=false; - }; - break; - case ACT_ACTION_FROM_PROP: - if (bNegativeEvent){ - apply=false; - keepgoing=false; - } - break; - case ACT_ACTION_LOOP_END: - if (bPositiveEvent){ - if (!(m_flag & ACT_FLAG_LOCKINPUT)){ - m_flag &= ~ACT_FLAG_KEYUP; - m_flag &= ~ACT_FLAG_REVERSE; - m_flag |= ACT_FLAG_LOCKINPUT; - m_localtime = m_startframe; - m_starttime = curtime; - } - } - if (bNegativeEvent){ - m_flag |= ACT_FLAG_KEYUP; - } - break; - case ACT_ACTION_LOOP_STOP: - if (bPositiveEvent){ - if (!(m_flag & ACT_FLAG_LOCKINPUT)){ - m_flag &= ~ACT_FLAG_REVERSE; - m_flag &= ~ACT_FLAG_KEYUP; - m_flag |= ACT_FLAG_LOCKINPUT; - SetStartTime(curtime); - } - } - if (bNegativeEvent){ - m_flag |= ACT_FLAG_KEYUP; - m_flag &= ~ACT_FLAG_LOCKINPUT; - keepgoing=false; - apply=false; - } - break; - case ACT_ACTION_PINGPONG: - if (bPositiveEvent){ - if (!(m_flag & ACT_FLAG_LOCKINPUT)){ - m_flag &= ~ACT_FLAG_KEYUP; - m_localtime = m_starttime; - m_starttime = curtime; - m_flag |= ACT_FLAG_LOCKINPUT; - } - } - break; - case ACT_ACTION_FLIPPER: - if (bPositiveEvent){ - if (!(m_flag & ACT_FLAG_LOCKINPUT)){ - m_flag &= ~ACT_FLAG_REVERSE; - m_flag |= ACT_FLAG_LOCKINPUT; - SetStartTime(curtime); - } - } - else if (bNegativeEvent){ - m_flag |= ACT_FLAG_REVERSE; - m_flag &= ~ACT_FLAG_LOCKINPUT; - SetStartTime(curtime); - } - break; - case ACT_ACTION_PLAY: - if (bPositiveEvent){ - if (!(m_flag & ACT_FLAG_LOCKINPUT)){ - m_flag &= ~ACT_FLAG_REVERSE; - m_localtime = m_starttime; - m_starttime = curtime; - m_flag |= ACT_FLAG_LOCKINPUT; - } - } - break; - default: - break; + + if (m_flag & ACT_FLAG_ATTEMPT_PLAY) + SetLocalTime(curtime); + + if (bUseContinue && (m_flag & ACT_FLAG_ACTIVE)) + { + m_localtime = obj->GetActionFrame(m_layer); + ResetStartTime(curtime); } - - /* Perform increment */ - if (keepgoing){ - if (m_playtype == ACT_ACTION_MOTION){ - MT_Point3 newpos; - MT_Point3 deltapos; - - newpos = obj->NodeGetWorldPosition(); - - /* Find displacement */ - deltapos = newpos-m_lastpos; - m_localtime += (length/m_stridelength) * deltapos.length(); - m_lastpos = newpos; - } - else{ - SetLocalTime(curtime); - } + + // Handle a frame property if it's defined + if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0) + { + CValue* oldprop = obj->GetProperty(m_framepropname); + CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer)); + if (oldprop) + oldprop->SetValue(newval); + else + obj->SetProperty(m_framepropname, newval); + + newval->Release(); } - - /* Check if a wrapping response is needed */ - if (length){ - if (m_localtime < m_startframe || m_localtime > m_endframe) - { - m_localtime = m_startframe + fmod(m_localtime, length); - wrap = true; - } + + // Handle a finished animation + if ((m_flag & ACT_FLAG_PLAY_END) && obj->IsActionDone(m_layer)) + { + m_flag &= ~ACT_FLAG_ACTIVE; + m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; + obj->StopAction(m_layer); + return false; } - else - m_localtime = m_startframe; - /* Perform post-increment tasks */ - switch (m_playtype){ - case ACT_ACTION_FROM_PROP: + // If a different action is playing, we've been overruled and are no longer active + if (obj->GetCurrentAction(m_layer) != m_action) + m_flag &= ~ACT_FLAG_ACTIVE; + + if (bPositiveEvent || (m_flag & ACT_FLAG_ATTEMPT_PLAY && !(m_flag & ACT_FLAG_ACTIVE))) + { + if (bPositiveEvent) + ResetStartTime(curtime); + + if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, playtype, m_layer_weight, m_ipo_flags)) { - CValue* propval = GetParent()->GetProperty(m_propname); - if (propval) - m_localtime = propval->GetNumber(); - - if (bNegativeEvent){ - keepgoing=false; - } - } - break; - case ACT_ACTION_MOTION: - break; - case ACT_ACTION_LOOP_STOP: - break; - case ACT_ACTION_PINGPONG: - if (wrap){ - if (!(m_flag & ACT_FLAG_REVERSE)) - m_localtime = m_endframe; - else - m_localtime = m_startframe; - - m_flag &= ~ACT_FLAG_LOCKINPUT; - m_flag ^= ACT_FLAG_REVERSE; //flip direction - keepgoing = false; - } - break; - case ACT_ACTION_FLIPPER: - if (wrap){ - if (!(m_flag & ACT_FLAG_REVERSE)){ - m_localtime=m_endframe; - //keepgoing = false; - } - else { - m_localtime=m_startframe; - keepgoing = false; - } - } - break; - case ACT_ACTION_LOOP_END: - if (wrap){ - if (m_flag & ACT_FLAG_KEYUP){ - keepgoing = false; - m_localtime = m_endframe; - m_flag &= ~ACT_FLAG_LOCKINPUT; - } - SetStartTime(curtime); - } - break; - case ACT_ACTION_PLAY: - if (wrap){ - m_localtime = m_endframe; - keepgoing = false; - m_flag &= ~ACT_FLAG_LOCKINPUT; + m_flag |= ACT_FLAG_ACTIVE; + if (bUseContinue) + obj->SetActionFrame(m_layer, m_localtime); + + if (m_playtype == ACT_ACTION_PLAY) + m_flag |= ACT_FLAG_PLAY_END; + else + m_flag &= ~ACT_FLAG_PLAY_END; } - break; - default: - keepgoing = false; - break; + m_flag |= ACT_FLAG_ATTEMPT_PLAY; } - - /* Set the property if its defined */ - if (m_framepropname[0] != '\0') { - CValue* propowner = GetParent(); - CValue* oldprop = propowner->GetProperty(m_framepropname); - CValue* newval = new CFloatValue(m_localtime); - if (oldprop) { - oldprop->SetValue(newval); - } else { - propowner->SetProperty(m_framepropname, newval); + else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent) + { + m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; + bAction *curr_action = obj->GetCurrentAction(m_layer); + if (curr_action && curr_action != m_action) + { + // Someone changed the action on us, so we wont mess with it + // Hopefully there wont be too many problems with two actuators using + // the same action... + m_flag &= ~ACT_FLAG_ACTIVE; + return false; } - newval->Release(); - } - - if (bNegativeEvent) - m_blendframe=0.0; - - /* Apply the pose if necessary*/ - if (apply){ - - /* Priority test */ - if (obj->SetActiveAction(this, priority, curtime)){ - - /* Get the underlying pose from the armature */ - obj->GetPose(&m_pose); - -// 2.4x function, - /* Override the necessary channels with ones from the action */ - // XXX extract_pose_from_action(m_pose, m_action, m_localtime); - - -// 2.5x - replacement for extract_pose_from_action(...) above. - { - struct PointerRNA id_ptr; - Object *arm= obj->GetArmatureObject(); - bPose *pose_back= arm->pose; - - arm->pose= m_pose; - RNA_id_pointer_create((ID *)arm, &id_ptr); - animsys_evaluate_action(&id_ptr, m_action, NULL, m_localtime); - - arm->pose= pose_back; - -// 2.5x - could also do this but looks too high level, constraints use this, it works ok. -// Object workob; /* evaluate using workob */ -// what_does_obaction(obj->GetArmatureObject(), &workob, m_pose, m_action, NULL, m_localtime); - } - // done getting the pose from the action - - /* Perform the user override (if any) */ - if (m_userpose){ - extract_pose_from_pose(m_pose, m_userpose); - game_free_pose(m_userpose); //cant use MEM_freeN(m_userpose) because the channels need freeing too. - m_userpose = NULL; - } -#if 1 - /* Handle blending */ - if (m_blendin && (m_blendframe<m_blendin)){ - /* If this is the start of a blending sequence... */ - if ((m_blendframe==0.0) || (!m_blendpose)){ - obj->GetMRDPose(&m_blendpose); - m_blendstart = curtime; - } - - /* Find percentages */ - newweight = (m_blendframe/(float)m_blendin); - game_blend_poses(m_pose, m_blendpose, 1.0 - newweight); - - /* Increment current blending percentage */ - m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); - if (m_blendframe>m_blendin) - m_blendframe = m_blendin; - - } -#endif - m_lastUpdate = m_localtime; - obj->SetPose (m_pose); - } - else{ - m_blendframe = 0.0; + + m_localtime = obj->GetActionFrame(m_layer); + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) + m_localtime = m_startframe; + + switch(m_playtype) + { + case ACT_ACTION_LOOP_STOP: + obj->StopAction(m_layer); // Stop the action after getting the frame + + // We're done + m_flag &= ~ACT_FLAG_ACTIVE; + return false; + case ACT_ACTION_PINGPONG: + m_flag ^= ACT_FLAG_REVERSE; + // Now fallthrough to LOOP_END code + case ACT_ACTION_LOOP_END: + // Convert into a play and let it finish + obj->SetPlayMode(m_layer, BL_Action::ACT_MODE_PLAY); + + m_flag |= ACT_FLAG_PLAY_END; + break; + + case ACT_ACTION_FLIPPER: + // Convert into a play action and play back to the beginning + end = start; + start = obj->GetActionFrame(m_layer); + obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags); + + m_flag |= ACT_FLAG_PLAY_END; + break; } } - - if (!keepgoing){ - m_blendframe = 0.0; - } - return keepgoing; -}; + + return true; +} #ifdef WITH_PYTHON @@ -633,10 +524,10 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action), KX_PYATTRIBUTE_RO_FUNCTION("channelNames", BL_ActionActuator, pyattr_get_channel_names), KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority), - KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame), + KX_PYATTRIBUTE_RW_FUNCTION("frame", BL_ActionActuator, pyattr_get_frame, pyattr_set_frame), KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname), KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname), - KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset), + KX_PYATTRIBUTE_RW_FUNCTION("useContinue", BL_ActionActuator, pyattr_get_use_continue, pyattr_set_use_continue), KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType), { NULL } //Sentinel @@ -696,4 +587,37 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA return ret; } +PyObject* BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + return PyBool_FromLong(self->m_flag & ACT_FLAG_CONTINUE); +} + +int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + + if (PyObject_IsTrue(value)) + self->m_flag |= ACT_FLAG_CONTINUE; + else + self->m_flag &= ~ACT_FLAG_CONTINUE; + + return PY_SET_ATTR_SUCCESS; +} + +PyObject* BL_ActionActuator::pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + return PyFloat_FromDouble(((KX_GameObject*)self->m_gameobj)->GetActionFrame(self->m_layer)); +} + +int BL_ActionActuator::pyattr_set_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v); + + ((KX_GameObject*)self->m_gameobj)->SetActionFrame(self->m_layer, PyFloat_AsDouble(value)); + + return PY_SET_ATTR_SUCCESS; +} + #endif // WITH_PYTHON diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index ff4ca785a96..357c2b4a05e 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -52,38 +52,20 @@ public: short playtype, short blendin, short priority, + short layer, + float layer_weight, + short ipo_flags, short end_reset, - float stride) - : SCA_IActuator(gameobj, KX_ACT_ACTION), - - m_lastpos(0, 0, 0), - m_blendframe(0), - m_flag(0), - m_startframe (starttime), - m_endframe(endtime) , - m_starttime(0), - m_localtime(starttime), - m_lastUpdate(-1), - m_blendin(blendin), - m_blendstart(0), - m_stridelength(stride), - m_playtype(playtype), - m_priority(priority), - m_end_reset(end_reset), - m_pose(NULL), - m_blendpose(NULL), - m_userpose(NULL), - m_action(action), - m_propname(propname), - m_framepropname(framepropname) - { - }; + float stride); + virtual ~BL_ActionActuator(); virtual bool Update(double curtime, bool frame); virtual CValue* GetReplica(); virtual void ProcessReplica(); void SetBlendTime (float newtime); + void SetLocalTime (float curtime); + void ResetStartTime (float curtime); bAction* GetAction() { return m_action; } void SetAction(bAction* act) { m_action= act; } @@ -96,18 +78,10 @@ public: static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - /* attribute check */ - static int CheckFrame(void *self, const PyAttributeDef*) - { - BL_ActionActuator* act = reinterpret_cast<BL_ActionActuator*>(self); - - if (act->m_localtime < act->m_startframe) - act->m_localtime = act->m_startframe; - else if (act->m_localtime > act->m_endframe) - act->m_localtime = act->m_endframe; - - return 0; - } + static PyObject* pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int CheckBlendTime(void *self, const PyAttributeDef*) { @@ -139,11 +113,6 @@ public: #endif // WITH_PYTHON protected: - - void SetStartTime(float curtime); - void SetLocalTime(float curtime); - bool ClampLocalTime(); - MT_Point3 m_lastpos; float m_blendframe; int m_flag; @@ -160,9 +129,11 @@ protected: float m_blendin; float m_blendstart; float m_stridelength; + float m_layer_weight; short m_playtype; short m_priority; - bool m_end_reset; + short m_layer; + short m_ipo_flags; struct bPose* m_pose; struct bPose* m_blendpose; struct bPose* m_userpose; @@ -171,11 +142,17 @@ protected: STR_String m_framepropname; }; +// Not all of these values are used in BL_ActionActuator anymore, +// but BL_ShapeActionActuator still uses them, so we keep them around +// for now. enum { - ACT_FLAG_REVERSE = 0x00000001, - ACT_FLAG_LOCKINPUT = 0x00000002, - ACT_FLAG_KEYUP = 0x00000004, - ACT_FLAG_ACTIVE = 0x00000008 + ACT_FLAG_REVERSE = 1<<0, + ACT_FLAG_LOCKINPUT = 1<<1, + ACT_FLAG_KEYUP = 1<<2, + ACT_FLAG_ACTIVE = 1<<3, + ACT_FLAG_CONTINUE = 1<<4, + ACT_FLAG_PLAY_END = 1<<5, + ACT_FLAG_ATTEMPT_PLAY = 1<<6, }; #endif diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index c6c20a96482..395cae4ba87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -218,7 +218,8 @@ BL_ArmatureObject::BL_ArmatureObject( void* sgReplicationInfo, SG_Callbacks callbacks, Object *armature, - Scene *scene) + Scene *scene, + int vert_deform_type) : KX_GameObject(sgReplicationInfo,callbacks), m_controlledConstraints(), @@ -232,7 +233,8 @@ BL_ArmatureObject::BL_ArmatureObject( m_activePriority(999), m_constraintNumber(0), m_channelNumber(0), - m_lastapplyframe(0.0) + m_lastapplyframe(0.0), + m_vert_deform_type(vert_deform_type) { m_armature = (bArmature *)armature->data; @@ -298,6 +300,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) case CONSTRAINT_TYPE_CLAMPTO: case CONSTRAINT_TYPE_TRANSFORM: case CONSTRAINT_TYPE_DISTLIMIT: + case CONSTRAINT_TYPE_TRANSLIKE: cti = constraint_get_typeinfo(pcon); gametarget = gamesubtarget = NULL; if (cti && cti->get_constraint_targets) { diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 2c3ca7404b3..1467f05c1bd 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -69,7 +69,8 @@ public: void* sgReplicationInfo, SG_Callbacks callbacks, Object *armature, - Scene *scene + Scene *scene, + int vert_deform_type ); virtual ~BL_ArmatureObject(); @@ -90,6 +91,8 @@ public: Object* GetArmatureObject() {return m_objArma;} + int GetVertDeformType() {return m_vert_deform_type;} + // for constraint python API void LoadConstraints(KX_BlenderSceneConverter* converter); size_t GetConstraintNumber() const { return m_constraintNumber; } @@ -136,6 +139,7 @@ protected: double m_timestep; // delta since last pose evaluation. class BL_ActionActuator *m_activeAct; short m_activePriority; + int m_vert_deform_type; size_t m_constraintNumber; size_t m_channelNumber; // store the original armature object matrix diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 7b9c5d4b4d6..fcfc07e631e 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -350,6 +350,8 @@ bool ConvertMaterial( // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; + // cast shadows? + material->ras_mode |= ( mat->mode & MA_SHADBUF )?CAST_SHADOW:0; MTex *mttmp = 0; numchan = getNumTexChannels(mat); int valid_index = 0; @@ -1481,7 +1483,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, { objprop.m_gamesoftFlag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT; - objprop.m_soft_linStiff = 0.5;; + objprop.m_soft_linStiff = 0.5; objprop.m_soft_angStiff = 1.f; /* angular stiffness 0..1 */ objprop.m_soft_volume= 1.f; /* volume preservation 0..1 */ @@ -1682,8 +1684,6 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, glslmat); - - BL_ConvertLampIpos(la, gamelight, converter); return gamelight; } @@ -1696,8 +1696,6 @@ static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_Blen gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata); gamecamera->SetName(ca->id.name + 2); - BL_ConvertCameraIpos(ca, gamecamera, converter); - return gamecamera; } @@ -1807,11 +1805,13 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_ARMATURE: { + bArmature *arm = (bArmature*)ob->data; gameobj = new BL_ArmatureObject( kxscene, KX_Scene::m_callbacks, ob, - kxscene->GetBlenderScene() // handle + kxscene->GetBlenderScene(), // handle + arm->gevertdeformer ); /* Get the current pose from the armature object and apply it as the rest pose */ break; @@ -1911,11 +1911,11 @@ void RBJconstraints(Object *ob)//not used KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc){//not used - for (int j=0;j<sumolist->GetCount();j++) + for (int j=0;j<sumolist->GetCount();j++) { - KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j); - if (gameobje->GetName()==busc) - return gameobje->GetPhysicsController(); + KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j); + if (gameobje->GetName()==busc) + return gameobje->GetPhysicsController(); } return 0; @@ -1924,11 +1924,11 @@ KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc){//not used KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){ - for (int j=0;j<sumolist->GetCount();j++) + for (int j=0;j<sumolist->GetCount();j++) { - KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j); - if (gameobje->GetName()==busc) - return gameobje; + KX_GameObject* gameobje = (KX_GameObject*) sumolist->GetValue(j); + if (gameobje->GetName()==busc) + return gameobje; } return 0; @@ -2090,8 +2090,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); gameobj->NodeSetLocalScale(scale); gameobj->NodeUpdateGS(0); - - BL_ConvertIpos(blenderobject,gameobj,converter); + BL_ConvertMaterialIpos(blenderobject, gameobj, converter); sumolist->Add(gameobj->AddRef()); @@ -2280,8 +2279,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); gameobj->NodeSetLocalScale(scale); gameobj->NodeUpdateGS(0); - - BL_ConvertIpos(blenderobject,gameobj,converter); + BL_ConvertMaterialIpos(blenderobject,gameobj, converter); sumolist->Add(gameobj->AddRef()); @@ -2631,7 +2629,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { 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(dat->axX,dat->axY,dat->axZ)); MT_Vector3 axis0 = localCFrame.getColumn(0); diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index bfba054d0d4..48392ee8dda 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -87,15 +87,16 @@ bool BL_DeformableGameObject::SetActiveAction(BL_ShapeActionActuator *act, short bool BL_DeformableGameObject::GetShape(vector<float> &shape) { shape.clear(); - if (m_pDeformer) + BL_ShapeDeformer* shape_deformer = dynamic_cast<BL_ShapeDeformer*>(m_pDeformer); + if (shape_deformer) { - Mesh* mesh = ((BL_MeshDeformer*)m_pDeformer)->GetMesh(); // this check is normally superfluous: a shape deformer can only be created if the mesh // has relative keys - if (mesh && mesh->key && mesh->key->type==KEY_RELATIVE) + Key* key = shape_deformer->GetKey(); + if (key && key->type==KEY_RELATIVE) { KeyBlock *kb; - for (kb = (KeyBlock*)mesh->key->block.first; kb; kb = (KeyBlock*)kb->next) + for (kb = (KeyBlock*)key->block.first; kb; kb = (KeyBlock*)kb->next) { shape.push_back(kb->curval); } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 615bb84ac2b..3ba55664007 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -82,23 +82,6 @@ public: bool SetActiveAction(class BL_ShapeActionActuator *act, short priority, double curtime); bool GetShape(vector<float> &shape); - Key* GetKey() - { - if(m_pDeformer) { - BL_MeshDeformer *deformer= dynamic_cast<BL_MeshDeformer *>(m_pDeformer); // incase its not a MeshDeformer - if(deformer) { - return deformer->GetMesh()->key; - } - -#if 0 // TODO. shape keys for softbody, currently they dont store a mesh. - KX_SoftBodyDeformer *deformer_soft= dynamic_cast<KX_SoftBodyDeformer *>(m_pDeformer); - if(deformer) { - return deformer->GetMesh()->key; - } -#endif - } - return NULL; - } virtual void SetDeformer(class RAS_Deformer* deformer); virtual class RAS_Deformer* GetDeformer() diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index bb53c2d6fe6..ac377cdb7ca 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -59,10 +59,49 @@ extern "C" { #include "BKE_animsys.h" + #include "BKE_key.h" + #include "RNA_access.h" } +BL_ShapeActionActuator::BL_ShapeActionActuator(SCA_IObject* gameobj, + const STR_String& propname, + const STR_String& framepropname, + float starttime, + float endtime, + struct bAction *action, + short playtype, + short blendin, + short priority, + float stride) + : SCA_IActuator(gameobj, KX_ACT_SHAPEACTION), + + m_lastpos(0, 0, 0), + m_blendframe(0), + m_flag(0), + m_startframe (starttime), + m_endframe(endtime) , + m_starttime(0), + m_localtime(starttime), + m_lastUpdate(-1), + m_blendin(blendin), + m_blendstart(0), + m_stridelength(stride), + m_playtype(playtype), + m_priority(priority), + m_action(action), + m_framepropname(framepropname), + m_propname(propname) +{ + m_idptr = new PointerRNA(); + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)GetParent(); + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_idptr); +}; + BL_ShapeActionActuator::~BL_ShapeActionActuator() { + if (m_idptr) + delete m_idptr; } void BL_ShapeActionActuator::ProcessReplica() @@ -382,7 +421,11 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) /* Priority test */ if (obj->SetActiveAction(this, priority, curtime)){ - Key *key = obj->GetKey(); + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + Key *key = NULL; + + if (shape_deformer) + key = shape_deformer->GetKey(); if (!key) { // this could happen if the mesh was changed in the middle of an action @@ -397,10 +440,14 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) obj->GetShape(m_blendshape); m_blendstart = curtime; } - // only interested in shape channel - // in 2.4x was // extract_ipochannels_from_action(&tchanbase, &key->id, m_action, "Shape", m_localtime); - BKE_animsys_evaluate_animdata(&key->id, key->adt, m_localtime, ADT_RECALC_ANIM); + KeyBlock *kb; + // We go through and clear out the keyblocks so there isn't any interference + // from other shape actions + for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) + kb->curval = 0.f; + + animsys_evaluate_action(m_idptr, m_action, NULL, m_localtime); // XXX - in 2.5 theres no way to do this. possibly not that important to support - Campbell if (0) { // XXX !execute_ipochannels(&tchanbase)) { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 7a4523d4554..efd24fc305f 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -54,27 +54,7 @@ public: short playtype, short blendin, short priority, - float stride) - : SCA_IActuator(gameobj, KX_ACT_SHAPEACTION), - - m_lastpos(0, 0, 0), - m_blendframe(0), - m_flag(0), - m_startframe (starttime), - m_endframe(endtime) , - m_starttime(0), - m_localtime(starttime), - m_lastUpdate(-1), - m_blendin(blendin), - m_blendstart(0), - m_stridelength(stride), - m_playtype(playtype), - m_priority(priority), - m_action(action), - m_framepropname(framepropname), - m_propname(propname) - { - }; + float stride); virtual ~BL_ShapeActionActuator(); virtual bool Update(double curtime, bool frame); virtual CValue* GetReplica(); @@ -160,6 +140,7 @@ protected: STR_String m_framepropname; STR_String m_propname; vector<float> m_blendshape; + struct PointerRNA *m_idptr; }; #endif diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index 8d8f149bb6c..f4c683f60ba 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -44,13 +44,12 @@ #include "RAS_MeshObject.h" //#include "BL_ArmatureController.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_action_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_ipo_types.h" -#include "DNA_curve_types.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_key.h" @@ -59,6 +58,7 @@ extern "C"{ #include "BKE_lattice.h" + #include "BKE_animsys.h" } @@ -68,9 +68,42 @@ extern "C"{ #define __NLA_DEFNORMALS //#undef __NLA_DEFNORMALS +BL_ShapeDeformer::BL_ShapeDeformer(BL_DeformableGameObject *gameobj, + Object *bmeshobj, + RAS_MeshObject *mesh) + : + BL_SkinDeformer(gameobj,bmeshobj, mesh), + m_useShapeDrivers(false), + m_lastShapeUpdate(-1) +{ + m_key = m_bmesh->key; + m_bmesh->key = copy_key(m_key); +}; + +/* this second constructor is needed for making a mesh deformable on the fly. */ +BL_ShapeDeformer::BL_ShapeDeformer(BL_DeformableGameObject *gameobj, + Object *bmeshobj_old, + Object *bmeshobj_new, + RAS_MeshObject *mesh, + bool release_object, + bool recalc_normal, + BL_ArmatureObject* arma) + : + BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, recalc_normal, arma), + m_useShapeDrivers(false), + m_lastShapeUpdate(-1) +{ + m_key = m_bmesh->key; + m_bmesh->key = copy_key(m_key); +}; BL_ShapeDeformer::~BL_ShapeDeformer() { + if (m_key && m_bmesh->key) + { + free_key(m_bmesh->key); + m_bmesh->key = m_key; + } }; RAS_Deformer *BL_ShapeDeformer::GetReplica() @@ -90,45 +123,23 @@ void BL_ShapeDeformer::ProcessReplica() bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma) { - IpoCurve *icu; - - m_shapeDrivers.clear(); - // check if this mesh has armature driven shape keys - if (m_bmesh->key && m_bmesh->key->ipo) { - for(icu= (IpoCurve*)m_bmesh->key->ipo->curve.first; icu; icu= (IpoCurve*)icu->next) { - if(icu->driver && - (icu->flag & IPO_MUTE) == 0 && - icu->driver->type == IPO_DRIVER_TYPE_NORMAL && - icu->driver->ob == arma && - icu->driver->blocktype == ID_AR) { - // this shape key ipo curve has a driver on the parent armature - // record this curve in the shape deformer so that the corresponding - m_shapeDrivers.push_back(icu); - } - } - } - return !m_shapeDrivers.empty(); + // This used to check if we had drivers from this armature, + // now we just assume we want to use shape drivers + // and let the animsys handle things. + m_useShapeDrivers = true; + + return true; } bool BL_ShapeDeformer::ExecuteShapeDrivers(void) { - if (!m_shapeDrivers.empty() && PoseUpdated()) { - vector<IpoCurve*>::iterator it; -// void *poin; -// int type; - + if (m_useShapeDrivers && PoseUpdated()) { // the shape drivers use the bone matrix as input. Must // update the matrix now m_armobj->ApplyPose(); - for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { - // no need to set a specific time: this curve has a driver - // XXX IpoCurve *icu = *it; - //calc_icu(icu, 1.0f); - //poin = get_ipo_poin((ID*)m_bmesh->key, icu, &type); - //if (poin) - // write_ipo_poin(poin, type, icu->curval); - } + // We don't need an actual time, just use 0 + BKE_animsys_evaluate_animdata(NULL, &GetKey()->id, GetKey()->adt, 0.f, ADT_RECALC_DRIVERS); ForceUpdate(); m_armobj->RestorePose(); @@ -190,3 +201,13 @@ bool BL_ShapeDeformer::Update(void) } return bSkinUpdate; } + +Key *BL_ShapeDeformer::GetKey() +{ + return m_bmesh->key; +} + +void BL_ShapeDeformer::SetKey(Key *key) +{ + m_bmesh->key = key; +} diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 8115af59d27..655cc9d7aeb 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -42,19 +42,12 @@ #include "BL_DeformableGameObject.h" #include <vector> -struct IpoCurve; - class BL_ShapeDeformer : public BL_SkinDeformer { public: BL_ShapeDeformer(BL_DeformableGameObject *gameobj, Object *bmeshobj, - RAS_MeshObject *mesh) - : - BL_SkinDeformer(gameobj,bmeshobj, mesh), - m_lastShapeUpdate(-1) - { - }; + RAS_MeshObject *mesh); /* this second constructor is needed for making a mesh deformable on the fly. */ BL_ShapeDeformer(BL_DeformableGameObject *gameobj, @@ -63,12 +56,7 @@ public: class RAS_MeshObject *mesh, bool release_object, bool recalc_normal, - BL_ArmatureObject* arma = NULL) - : - BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, recalc_normal, arma), - m_lastShapeUpdate(-1) - { - }; + BL_ArmatureObject* arma = NULL); virtual RAS_Deformer *GetReplica(); virtual void ProcessReplica(); @@ -78,14 +66,18 @@ public: bool LoadShapeDrivers(Object* arma); bool ExecuteShapeDrivers(void); + struct Key *GetKey(); + void SetKey(struct Key *key); + void ForceUpdate() { m_lastShapeUpdate = -1.0; }; protected: - vector<IpoCurve*> m_shapeDrivers; - double m_lastShapeUpdate; + bool m_useShapeDrivers; + double m_lastShapeUpdate; + struct Key* m_key; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 34f9cb56c27..3a379e8b0ed 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -36,6 +36,10 @@ #pragma warning (disable : 4786) #endif //WIN32 +// Eigen2 stuff used for BGEDeformVerts +#include <Eigen/Core> +#include <Eigen/LU> + #include "BL_SkinDeformer.h" #include "CTR_Map.h" #include "STR_HashedString.h" @@ -54,6 +58,7 @@ extern "C"{ #include "BKE_lattice.h" + #include "BKE_deform.h" } @@ -74,7 +79,9 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, //m_defbase(&bmeshobj->defbase), m_releaseobject(false), m_poseApplied(false), - m_recalcNormal(true) + m_recalcNormal(true), + m_copyNormals(false), + m_dfnrToPC(NULL) { copy_m4_m4(m_obmat, bmeshobj->obmat); }; @@ -92,7 +99,9 @@ BL_SkinDeformer::BL_SkinDeformer( m_lastArmaUpdate(-1), //m_defbase(&bmeshobj_old->defbase), m_releaseobject(release_object), - m_recalcNormal(recalc_normal) + m_recalcNormal(recalc_normal), + m_copyNormals(false), + m_dfnrToPC(NULL) { // this is needed to ensure correct deformation of mesh: // the deformation is done with Blender's armature_deform_verts() function @@ -106,6 +115,8 @@ BL_SkinDeformer::~BL_SkinDeformer() { if(m_releaseobject && m_armobj) m_armobj->Release(); + if(m_dfnrToPC) + delete [] m_dfnrToPC; } void BL_SkinDeformer::Relink(CTR_Map<class CTR_HashedPtr, void*>*map) @@ -152,9 +163,14 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) for(i=it.startvertex; i<it.endvertex; i++) { RAS_TexVert& v = it.vertex[i]; v.SetXYZ(m_transverts[v.getOrigIndex()]); + if (m_copyNormals) + v.SetNormal(m_transnors[v.getOrigIndex()]); } } } + + if (m_copyNormals) + m_copyNormals = false; } return true; } @@ -174,19 +190,126 @@ void BL_SkinDeformer::ProcessReplica() BL_MeshDeformer::ProcessReplica(); m_lastArmaUpdate = -1; m_releaseobject = false; + m_dfnrToPC = NULL; +} + +void BL_SkinDeformer::BlenderDeformVerts() +{ + float obmat[4][4]; // the original object matrix + Object* par_arma = m_armobj->GetArmatureObject(); + + // save matrix first + copy_m4_m4(obmat, m_objMesh->obmat); + // set reference matrix + copy_m4_m4(m_objMesh->obmat, m_obmat); + + armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL ); + + // restore matrix + copy_m4_m4(m_objMesh->obmat, obmat); + +#ifdef __NLA_DEFNORMALS + if (m_recalcNormal) + RecalcNormals(); +#endif +} + +void BL_SkinDeformer::BGEDeformVerts() +{ + Object *par_arma = m_armobj->GetArmatureObject(); + MDeformVert *dverts = m_bmesh->dvert; + bDeformGroup *dg; + int numGroups = BLI_countlist(&m_objMesh->defbase); + + if (!dverts) + return; + + if (m_dfnrToPC == NULL) + { + m_dfnrToPC = new bPoseChannel*[numGroups]; + int i; + for (i=0, dg=(bDeformGroup*)m_objMesh->defbase.first; + dg; + ++i, dg=(bDeformGroup*)dg->next) + { + m_dfnrToPC[i] = get_pose_channel(par_arma->pose, dg->name); + + if (m_dfnrToPC[i] && m_dfnrToPC[i]->bone->flag & BONE_NO_DEFORM) + m_dfnrToPC[i] = NULL; + } + } + + + for (int i=0; i<m_bmesh->totvert; ++i) + { + float contrib = 0.f, weight, max_weight=0.f; + Bone *bone; + bPoseChannel *pchan=NULL; + MDeformVert *dvert; + Eigen::Map<Eigen::Vector3f> norm(m_transnors[i]); + Eigen::Vector4f vec(0, 0, 0, 1); + Eigen::Matrix4f norm_chan_mat; + Eigen::Vector4f co(m_transverts[i][0], + m_transverts[i][1], + m_transverts[i][2], + 1.f); + + dvert = dverts+i; + + if (!dvert->totweight) + continue; + + for (int j=0; j<dvert->totweight; ++j) + { + int index = dvert->dw[j].def_nr; + + if (index < numGroups && (pchan=m_dfnrToPC[index])) + { + weight = dvert->dw[j].weight; + bone = pchan->bone; + + if (weight) + { + Eigen::Vector4f cop(co); + Eigen::Matrix4f chan_mat = Eigen::Matrix4f::Map((float*)pchan->chan_mat); + + // Update Vertex Position + cop = chan_mat*cop; + vec += (cop - co)*weight; + + // Save the most influential channel so we can use it to update the vertex normal + if (weight > max_weight) + { + max_weight = weight; + norm_chan_mat = chan_mat; + } + + contrib += weight; + } + } + } + + + // Update Vertex Normal + norm = norm_chan_mat.corner<3, 3>(Eigen::TopLeft)*norm; + + if (contrib > 0.0001f) + { + vec *= 1.f/contrib; + co += vec; + } + + m_transverts[i][0] = co[0]; + m_transverts[i][1] = co[1]; + m_transverts[i][2] = co[2]; + } + m_copyNormals = true; } -//void where_is_pose (Object *ob); -//void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); bool BL_SkinDeformer::UpdateInternal(bool shape_applied) { /* See if the armature has been updated for this frame */ if (PoseUpdated()){ - float obmat[4][4]; // the original object matrice - - /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ - /* but it requires the blender object pointer... */ - Object* par_arma = m_armobj->GetArmatureObject(); if(!shape_applied) { /* store verts locally */ @@ -194,25 +317,23 @@ bool BL_SkinDeformer::UpdateInternal(bool shape_applied) /* duplicate */ for (int v =0; v<m_bmesh->totvert; v++) + { VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + VECCOPY(m_transnors[v], m_bmesh->mvert[v].no); + } } m_armobj->ApplyPose(); - // save matrix first - copy_m4_m4(obmat, m_objMesh->obmat); - // set reference matrix - copy_m4_m4(m_objMesh->obmat, m_obmat); - - armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL ); - - // restore matrix - copy_m4_m4(m_objMesh->obmat, obmat); - -#ifdef __NLA_DEFNORMALS - if (m_recalcNormal) - RecalcNormals(); -#endif + switch (m_armobj->GetVertDeformType()) + { + case ARM_VDEF_BGE_CPU: + BGEDeformVerts(); + break; + case ARM_VDEF_BLENDER: + default: + BlenderDeformVerts(); + } /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index e53e21e946f..be974619281 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -109,6 +109,11 @@ protected: bool m_releaseobject; bool m_poseApplied; bool m_recalcNormal; + bool m_copyNormals; // dirty flag so we know if Apply() needs to copy normal information (used for BGEDeformVerts()) + struct bPoseChannel** m_dfnrToPC; + + void BlenderDeformVerts(); + void BGEDeformVerts(); #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index 8fc01032de7..f003a0049e5 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -170,10 +170,10 @@ float BlenderWorldInfo::getMistStart() float BlenderWorldInfo::getMistDistance() { return m_mistdistance; -} - +} + + - float BlenderWorldInfo::getMistColorRed() { return m_mistcolor[0]; diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 45a7701d404..3a217ce9d74 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -51,6 +51,7 @@ set(INC ../../blender/makesrna ../../blender/windowmanager ../../../extern/bullet2/src + ../../../extern/Eigen2 ../../../intern/container ../../../intern/guardedalloc ../../../intern/moto/include diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp index a9a3e66f996..75c0e012226 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp @@ -47,11 +47,11 @@ float BL_ScalarInterpolator::GetValue(float currentTime) const { return evaluate_fcurve(m_fcu, currentTime); } -BL_InterpolatorList::BL_InterpolatorList(struct AnimData *adt) { - if(adt->action==NULL) +BL_InterpolatorList::BL_InterpolatorList(bAction *action) { + if(action==NULL) return; - for(FCurve *fcu= (FCurve *)adt->action->curves.first; fcu; fcu= (FCurve *)fcu->next) { + for(FCurve *fcu= (FCurve *)action->curves.first; fcu; fcu= (FCurve *)fcu->next) { if(fcu->rna_path) { BL_ScalarInterpolator *new_ipo = new BL_ScalarInterpolator(fcu); //assert(new_ipo); diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h index bd786bae969..cca66b3771c 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h @@ -66,7 +66,7 @@ public: class BL_InterpolatorList : public std::vector<KX_IScalarInterpolator *> { public: - BL_InterpolatorList(struct AnimData *adt); + BL_InterpolatorList(struct bAction *action); ~BL_InterpolatorList(); KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index b04a0d24e78..ffb9a8ce691 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -566,18 +566,18 @@ void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) void KX_BlenderSceneConverter::RegisterInterpolatorList( - BL_InterpolatorList *adtList, - struct AnimData *for_adt) + BL_InterpolatorList *actList, + struct bAction *for_act) { - m_map_blender_to_gameAdtList.insert(CHashedPtr(for_adt), adtList); + m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); } BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList( - struct AnimData *for_adt) + struct bAction *for_act) { - BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_adt)]; + BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; return listp?*listp:NULL; } @@ -1083,7 +1083,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) { - int maggie_index; + int maggie_index= -1; int i=0; if(maggie==NULL) @@ -1101,6 +1101,10 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) i++; } + /* should never happen but just to be safe */ + if(maggie_index == -1) + return false; + m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); tag_main(maggie, 1); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index 2340e44d288..ba919eb9592 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -113,8 +113,8 @@ public: void RegisterBlenderMaterial(BL_Material *mat); - void RegisterInterpolatorList(BL_InterpolatorList *adtList, struct AnimData *for_adt); - BL_InterpolatorList *FindInterpolatorList(struct AnimData *for_adt); + void RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act); + BL_InterpolatorList *FindInterpolatorList(struct bAction *for_act); void RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator); SCA_IActuator *FindGameActuator(struct bActuator *for_actuator); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 51e0449a32e..a84a1419d0d 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -46,6 +46,7 @@ #ifdef WITH_AUDASPACE # include "AUD_C-API.h" +# include "AUD_ChannelMapperFactory.h" #endif // Actuators @@ -99,6 +100,7 @@ #include "BL_ActionActuator.h" #include "BL_ShapeActionActuator.h" #include "BL_ArmatureActuator.h" +#include "BL_Action.h" /* end of blender include block */ #include "BL_BlenderDataConversion.h" @@ -196,30 +198,37 @@ void BL_ConvertActuators(char* maggiename, } case ACT_ACTION: { - if (blenderobject->type==OB_ARMATURE){ - bActionActuator* actact = (bActionActuator*) bact->data; - STR_String propname = (actact->name ? actact->name : ""); - STR_String propframe = (actact->frameProp ? actact->frameProp : ""); + bActionActuator* actact = (bActionActuator*) bact->data; + STR_String propname = (actact->name ? actact->name : ""); + STR_String propframe = (actact->frameProp ? actact->frameProp : ""); + + short ipo_flags = 0; + + // Convert flags + if (actact->flag & ACT_IPOFORCE) ipo_flags |= BL_Action::ACT_IPOFLAG_FORCE; + if (actact->flag & ACT_IPOLOCAL) ipo_flags |= BL_Action::ACT_IPOFLAG_LOCAL; + if (actact->flag & ACT_IPOADD) ipo_flags |= BL_Action::ACT_IPOFLAG_ADD; + if (actact->flag & ACT_IPOCHILD) ipo_flags |= BL_Action::ACT_IPOFLAG_CHILD; - BL_ActionActuator* tmpbaseact = new BL_ActionActuator( - gameobj, - propname, - propframe, - actact->sta, - actact->end, - actact->act, - actact->type, // + 1, because Blender starts to count at zero, - actact->blendin, - actact->priority, - actact->end_reset, - actact->stridelength - // Ketsji at 1, because zero is reserved for "NoDef" - ); - baseact= tmpbaseact; - break; - } - else - printf ("Discarded action actuator from non-armature object [%s]\n", blenderobject->id.name+2); + BL_ActionActuator* tmpbaseact = new BL_ActionActuator( + gameobj, + propname, + propframe, + actact->sta, + actact->end, + actact->act, + actact->type, // + 1, because Blender starts to count at zero, + actact->blendin, + actact->priority, + actact->layer, + actact->layer_weight, + ipo_flags, + actact->end_reset, + actact->stridelength + // Ketsji at 1, because zero is reserved for "NoDef" + ); + baseact= tmpbaseact; + break; } case ACT_SHAPEACTION: { @@ -380,7 +389,7 @@ void BL_ConvertActuators(char* maggiename, { bSound* sound = soundact->sound; bool is3d = soundact->flag & ACT_SND_3D_SOUND ? true : false; - AUD_Sound* snd_sound = NULL; + AUD_Reference<AUD_IFactory> snd_sound; KX_3DSoundSettings settings; settings.cone_inner_angle = soundact->sound3D.cone_inner_angle; settings.cone_outer_angle = soundact->sound3D.cone_outer_angle; @@ -398,7 +407,23 @@ void BL_ConvertActuators(char* maggiename, "\" has no sound datablock." << std::endl; } else - snd_sound = sound->playback_handle; + { + snd_sound = *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->playback_handle); + + // if sound shall be 3D but isn't mono, we have to make it mono! + if(is3d) + { + AUD_Reference<AUD_IReader> reader = snd_sound->createReader(); + if(reader->getSpecs().channels != AUD_CHANNELS_MONO) + { + AUD_DeviceSpecs specs; + specs.channels = AUD_CHANNELS_MONO; + specs.rate = AUD_RATE_INVALID; + specs.format = AUD_FORMAT_INVALID; + snd_sound = new AUD_ChannelMapperFactory(snd_sound, specs); + } + } + } KX_SoundActuator* tmpsoundact = new KX_SoundActuator(gameobj, snd_sound, @@ -971,7 +996,7 @@ void BL_ConvertActuators(char* maggiename, filtermode = RAS_2DFilterManager::RAS_2DFILTER_NOFILTER; break; } - + tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),scene); @@ -987,8 +1012,8 @@ void BL_ConvertActuators(char* maggiename, } } - baseact = tmp; - + baseact = tmp; + } break; case ACT_PARENT: diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index 98afc3a690a..fafaaf5cef6 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -210,7 +210,11 @@ void BL_ConvertControllers( CIntValue* uniqueval = new CIntValue(uniqueint); uniquename += uniqueval->GetText(); uniqueval->Release(); - gamecontroller->SetName(uniquename); + //unique name was never implemented for sensors and actuators, only for controllers + //and it's producing difference in the keys for the lists: obj.controllers/sensors/actuators + //at some point it should either be implemented globally (and saved as a separate var) or removed. + //gamecontroller->SetName(uniquename); + gamecontroller->SetName(bcontr->name); gameobj->AddController(gamecontroller); converter->RegisterGameController(gamecontroller, bcontr); diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index ad6941dcdc7..a250bc6064b 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -276,7 +276,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gReverseKeyTranslateTable[ENDKEY ] = SCA_IInputDevice::KX_ENDKEY; } - int executePriority = 0; + int executePriority = 0; int uniqueint = 0; int count = 0; bSensor* sens = (bSensor*)blenderobject->sensors.first; diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 2ad56717e26..0ee99f5335b 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -54,6 +54,7 @@ #include "DNA_object_types.h" #include "DNA_action_types.h" +#include "DNA_anim_types.h" #include "DNA_ipo_types.h" #include "DNA_lamp_types.h" #include "DNA_world_types.h" @@ -72,226 +73,226 @@ #include "STR_HashedString.h" -static BL_InterpolatorList *GetAdtList(struct AnimData *for_adt, KX_BlenderSceneConverter *converter) { - BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_adt); +static BL_InterpolatorList *GetAdtList(struct bAction *for_act, KX_BlenderSceneConverter *converter) { + BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_act); if (!adtList) { - adtList = new BL_InterpolatorList(for_adt); - converter->RegisterInterpolatorList(adtList, for_adt); + adtList = new BL_InterpolatorList(for_act); + converter->RegisterInterpolatorList(adtList, for_act); } return adtList; } -void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter) +SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter) { - if (blenderobject->adt) { - - KX_IpoSGController* ipocontr = new KX_IpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(gameobj->GetSGNode()); - - // For ipo_as_force, we need to know which SM object and Scene the - // object associated with this ipo is in. Is this already known here? - // I think not.... then it must be done later :( -// ipocontr->SetSumoReference(gameobj->GetSumoScene(), -// gameobj->GetSumoObject()); - - ipocontr->SetGameObject(gameobj); - - ipocontr->GetIPOTransform().SetPosition( - MT_Point3( - blenderobject->loc[0]/*+blenderobject->dloc[0]*/, - blenderobject->loc[1]/*+blenderobject->dloc[1]*/, - blenderobject->loc[2]/*+blenderobject->dloc[2]*/ - ) - ); - ipocontr->GetIPOTransform().SetEulerAngles( - MT_Vector3( - blenderobject->rot[0], - blenderobject->rot[1], - blenderobject->rot[2] - ) - ); - ipocontr->GetIPOTransform().SetScaling( - MT_Vector3( - blenderobject->size[0], - blenderobject->size[1], - blenderobject->size[2] - ) - ); - - const char *rotmode, *drotmode; - - switch(blenderobject->rotmode) - { - case ROT_MODE_AXISANGLE: - rotmode = "rotation_axis_angle"; - drotmode = "delta_rotation_axis_angle"; - case ROT_MODE_QUAT: - rotmode = "rotation_quaternion"; - drotmode = "delta_rotation_quaternion"; - default: - rotmode = "rotation_euler"; - drotmode = "delta_rotation_euler"; - } + KX_IpoSGController* ipocontr = new KX_IpoSGController(); + ipocontr->SetGameObject(gameobj); + + Object* blenderobject = gameobj->GetBlenderObject(); + + ipocontr->GetIPOTransform().SetPosition(MT_Point3(blenderobject->loc)); + ipocontr->GetIPOTransform().SetEulerAngles(MT_Vector3(blenderobject->rot)); + ipocontr->GetIPOTransform().SetScaling(MT_Vector3(blenderobject->size)); + + const char *rotmode, *drotmode; + + switch(blenderobject->rotmode) { + case ROT_MODE_AXISANGLE: + rotmode = "rotation_axis_angle"; + drotmode = "delta_rotation_axis_angle"; + break; + case ROT_MODE_QUAT: + rotmode = "rotation_quaternion"; + drotmode = "delta_rotation_quaternion"; + break; + default: + rotmode = "rotation_euler"; + drotmode = "delta_rotation_euler"; + break; + } - BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter); + BL_InterpolatorList *adtList= GetAdtList(action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. + // For each active channel in the adtList add an + // interpolator to the game object. - KX_IInterpolator *interpolator; - KX_IScalarInterpolator *interp; + KX_IInterpolator *interpolator; + KX_IScalarInterpolator *interp; - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("location", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_LOC_X+i, true); - } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("location", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_LOC_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("delta_location", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("delta_location", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator(rotmode, i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_ROT_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator(rotmode, i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_ROT_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator(drotmode, i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DROT_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator(drotmode, i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DROT_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("scale", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("scale", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true); } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) { - interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true); - } + } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) { + interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true); } + } - { - KX_ObColorIpoSGController* ipocontr_obcol=NULL; + { + KX_ObColorIpoSGController* ipocontr_obcol=NULL; - for(int i=0; i<4; i++) { - if ((interp = adtList->GetScalarInterpolator("color", i))) { - if (!ipocontr_obcol) { - ipocontr_obcol = new KX_ObColorIpoSGController(); - gameobj->GetSGNode()->AddSGController(ipocontr_obcol); - ipocontr_obcol->SetObject(gameobj->GetSGNode()); - } - interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp); - ipocontr_obcol->AddInterpolator(interpolator); + for(int i=0; i<4; i++) { + if ((interp = adtList->GetScalarInterpolator("color", i))) { + if (!ipocontr_obcol) { + ipocontr_obcol = new KX_ObColorIpoSGController(); + gameobj->GetSGNode()->AddSGController(ipocontr_obcol); + ipocontr_obcol->SetObject(gameobj->GetSGNode()); } + interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp); + ipocontr_obcol->AddInterpolator(interpolator); } } } + + return ipocontr; } -void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter) +void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter) { + if (blenderobject->adt) { + SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter); + gameobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(gameobj->GetSGNode()); + } +} - if (blenderlamp->adt) { +SG_Controller *BL_CreateLampIPO(struct bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter) +{ + KX_LightIpoSGController* ipocontr = new KX_LightIpoSGController(); - KX_LightIpoSGController* ipocontr = new KX_LightIpoSGController(); - lightobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(lightobj->GetSGNode()); - - ipocontr->m_energy = blenderlamp->energy; - ipocontr->m_col_rgb[0] = blenderlamp->r; - ipocontr->m_col_rgb[1] = blenderlamp->g; - ipocontr->m_col_rgb[2] = blenderlamp->b; - ipocontr->m_dist = blenderlamp->dist; + Lamp *blenderlamp = (Lamp*)lightobj->GetBlenderObject()->data; - BL_InterpolatorList *adtList= GetAdtList(blenderlamp->adt, converter); + ipocontr->m_energy = blenderlamp->energy; + ipocontr->m_col_rgb[0] = blenderlamp->r; + ipocontr->m_col_rgb[1] = blenderlamp->g; + ipocontr->m_col_rgb[2] = blenderlamp->b; + ipocontr->m_dist = blenderlamp->dist; - // For each active channel in the adtList add an - // interpolator to the game object. + BL_InterpolatorList *adtList= GetAdtList(action, converter); + + // For each active channel in the adtList add an + // interpolator to the game object. - KX_IInterpolator *interpolator; - KX_IScalarInterpolator *interp; + KX_IInterpolator *interpolator; + KX_IScalarInterpolator *interp; - if ((interp= adtList->GetScalarInterpolator("energy", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_energy, interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyEnergy(true); - } + if ((interp= adtList->GetScalarInterpolator("energy", 0))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_energy, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyEnergy(true); + } - if ((interp = adtList->GetScalarInterpolator("distance", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_dist, interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyDist(true); - } + if ((interp = adtList->GetScalarInterpolator("distance", 0))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_dist, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyDist(true); + } - for(int i=0; i<3; i++) { - if ((interp = adtList->GetScalarInterpolator("color", i))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_col_rgb[i], interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyColor(true); - } + for(int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("color", i))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_col_rgb[i], interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyColor(true); } } + + return ipocontr; } +void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter) +{ + if (blenderlamp->adt) { + SG_Controller* ipocontr = BL_CreateLampIPO(blenderlamp->adt->action, lightobj, converter); + lightobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(lightobj->GetSGNode()); + + + } +} -void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter) +SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* cameraobj, KX_BlenderSceneConverter *converter) { + KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController(); - if (blendercamera->adt) { + Camera *blendercamera = (Camera*)cameraobj->GetBlenderObject()->data; - KX_CameraIpoSGController* ipocontr = new KX_CameraIpoSGController(); - cameraobj->GetSGNode()->AddSGController(ipocontr); - ipocontr->SetObject(cameraobj->GetSGNode()); - - ipocontr->m_lens = blendercamera->lens; - ipocontr->m_clipstart = blendercamera->clipsta; - ipocontr->m_clipend = blendercamera->clipend; + ipocontr->m_lens = blendercamera->lens; + ipocontr->m_clipstart = blendercamera->clipsta; + ipocontr->m_clipend = blendercamera->clipend; - BL_InterpolatorList *adtList= GetAdtList(blendercamera->adt, converter); + BL_InterpolatorList *adtList= GetAdtList(blendercamera->adt->action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. + // For each active channel in the adtList add an + // interpolator to the game object. - KX_IInterpolator *interpolator; - KX_IScalarInterpolator *interp; + KX_IInterpolator *interpolator; + KX_IScalarInterpolator *interp; - if ((interp = adtList->GetScalarInterpolator("lens", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_lens, interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyLens(true); - } + if ((interp = adtList->GetScalarInterpolator("lens", 0))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_lens, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyLens(true); + } - if ((interp = adtList->GetScalarInterpolator("clip_start", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipstart, interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyClipStart(true); - } + if ((interp = adtList->GetScalarInterpolator("clip_start", 0))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipstart, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyClipStart(true); + } - if ((interp = adtList->GetScalarInterpolator("clip_end", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipend, interp); - ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyClipEnd(true); - } + if ((interp = adtList->GetScalarInterpolator("clip_end", 0))) { + interpolator= new KX_ScalarInterpolator(&ipocontr->m_clipend, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyClipEnd(true); + } + + return ipocontr; +} +void BL_ConvertCameraIpos(struct Camera* blendercamera, KX_GameObject *cameraobj,KX_BlenderSceneConverter *converter) +{ + + if (blendercamera->adt) { + SG_Controller* ipocontr = BL_CreateCameraIPO(blendercamera->adt->action, cameraobj, converter); + cameraobj->GetSGNode()->AddSGController(ipocontr); + ipocontr->SetObject(cameraobj->GetSGNode()); } } @@ -314,7 +315,7 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co ipocontr->m_mist_rgb[1] = blenderworld->horg; ipocontr->m_mist_rgb[2] = blenderworld->horb; - BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt, converter); + BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter); // For each active channel in the adtList add an // interpolator to the game object. @@ -356,7 +357,7 @@ static void ConvertMaterialIpos( gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); - BL_InterpolatorList *adtList= GetAdtList(blendermaterial->adt, converter); + BL_InterpolatorList *adtList= GetAdtList(blendermaterial->adt->action, converter); ipocontr->m_rgba[0] = blendermaterial->r; diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index d77a72a82e2..60e695c68a7 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -36,10 +36,18 @@ struct Object; +class SG_Controller *BL_CreateIPO(struct bAction *action, + class KX_GameObject* gameobj, + class KX_BlenderSceneConverter *converter); + void BL_ConvertIpos(struct Object* blenderobject, class KX_GameObject* gameobj, class KX_BlenderSceneConverter *converter); +class SG_Controller *BL_CreateLampIPO(struct bAction *action, + class KX_GameObject* lightobj, + class KX_BlenderSceneConverter *converter); + void BL_ConvertLampIpos(struct Lamp* blenderlight, class KX_GameObject* lightobj, class KX_BlenderSceneConverter *converter); @@ -47,6 +55,10 @@ void BL_ConvertLampIpos(struct Lamp* blenderlight, void BL_ConvertWorldIpos(struct World* blenderworld, class KX_BlenderSceneConverter *converter); +class SG_Controller *BL_CreateCameraIPO(struct bAction *action, + class KX_GameObject* cameraobj, + class KX_BlenderSceneConverter *converter); + void BL_ConvertCameraIpos(struct Camera* blendercamera, class KX_GameObject* cameraobj, class KX_BlenderSceneConverter *converter); diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 9cfc3410748..0ae22d548c5 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -20,6 +20,7 @@ incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' incs += ' #source/blender/windowmanager' incs += ' #source/blender/makesrna' incs += ' #source/blender/ikplugin' +incs += ' #extern/Eigen2' incs += ' ' + env['BF_BULLET_INC'] diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 7957c82e7f9..27f4f0b10cb 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -192,89 +192,89 @@ void CParser::NextSym() switch(ch) { - case '(': - sym = lbracksym; NextCh(); - break; - case ')': - sym = rbracksym; NextCh(); - break; - case ',': - sym = commasym; NextCh(); - break; - case '%' : - sym = opsym; opkind = OPmodulus; NextCh(); - break; - case '+' : - sym = opsym; opkind = OPplus; NextCh(); - break; - case '-' : - sym = opsym; opkind = OPminus; NextCh(); - break; - case '*' : - sym = opsym; opkind = OPtimes; NextCh(); - break; - case '/' : - sym = opsym; opkind = OPdivide; NextCh(); - break; - case '&' : - sym = opsym; opkind = OPand; NextCh(); TermChar('&'); - break; - case '|' : - sym = opsym; opkind = OPor; NextCh(); TermChar('|'); - break; - case '=' : - sym = opsym; opkind = OPequal; NextCh(); TermChar('='); - break; - case '!' : - sym = opsym; - NextCh(); - if (ch == '=') - { - opkind = OPunequal; + case '(': + sym = lbracksym; NextCh(); + break; + case ')': + sym = rbracksym; NextCh(); + break; + case ',': + sym = commasym; NextCh(); + break; + case '%' : + sym = opsym; opkind = OPmodulus; NextCh(); + break; + case '+' : + sym = opsym; opkind = OPplus; NextCh(); + break; + case '-' : + sym = opsym; opkind = OPminus; NextCh(); + break; + case '*' : + sym = opsym; opkind = OPtimes; NextCh(); + break; + case '/' : + sym = opsym; opkind = OPdivide; NextCh(); + break; + case '&' : + sym = opsym; opkind = OPand; NextCh(); TermChar('&'); + break; + case '|' : + sym = opsym; opkind = OPor; NextCh(); TermChar('|'); + break; + case '=' : + sym = opsym; opkind = OPequal; NextCh(); TermChar('='); + break; + case '!' : + sym = opsym; NextCh(); - } - else - { - opkind = OPnot; - } - break; - case '>': - sym = opsym; - NextCh(); - if (ch == '=') - { - opkind = OPgreaterequal; + if (ch == '=') + { + opkind = OPunequal; + NextCh(); + } + else + { + opkind = OPnot; + } + break; + case '>': + sym = opsym; NextCh(); - } - else - { - opkind = OPgreater; - } - break; - case '<': - sym = opsym; - NextCh(); - if (ch == '=') { - opkind = OPlessequal; + if (ch == '=') + { + opkind = OPgreaterequal; + NextCh(); + } + else + { + opkind = OPgreater; + } + break; + case '<': + sym = opsym; NextCh(); - } else { - opkind = OPless; - } - break; - case '\"' : { - int start; - sym = constsym; - constkind = stringtype; - NextCh(); - start = chcount; - while ((ch != '\"') && (ch != 0x0)) + if (ch == '=') { + opkind = OPlessequal; + NextCh(); + } else { + opkind = OPless; + } + break; + case '\"' : { + int start; + sym = constsym; + constkind = stringtype; NextCh(); - GrabRealString(start); - TermChar('\"'); // check for eol before '\"' - break; - } - case 0x0: sym = eolsym; break; - default: + start = chcount; + while ((ch != '\"') && (ch != 0x0)) + NextCh(); + GrabRealString(start); + TermChar('\"'); // check for eol before '\"' + break; + } + case 0x0: sym = eolsym; break; + default: { int start; start = chcount; @@ -301,7 +301,7 @@ void CParser::NextSym() } GrabString(start); } else if (((ch >= 'a') && (ch <= 'z')) - || ((ch >= 'A') && (ch <= 'Z'))) + || ((ch >= 'A') && (ch <= 'Z'))) { // reserved word? start = chcount; @@ -358,18 +358,18 @@ STR_String CParser::Symbol2Str(int s) { // returns a string representation of of symbol s, // for use in Term when generating an error switch(s) { - case errorsym: return "error"; - case lbracksym: return "("; - case rbracksym: return ")"; - case commasym: return ","; - case opsym: return "operator"; - case constsym: return "constant"; - case sumsym: return "SUM"; - case ifsym: return "IF"; - case whocodedsym: return "WHOMADE"; - case eolsym: return "end of line"; - case idsym: return "identifier"; - default: return "unknown"; // should not happen + case errorsym: return "error"; + case lbracksym: return "("; + case rbracksym: return ")"; + case commasym: return ","; + case opsym: return "operator"; + case constsym: return "constant"; + case sumsym: return "SUM"; + case ifsym: return "IF"; + case whocodedsym: return "WHOMADE"; + case eolsym: return "end of line"; + case idsym: return "identifier"; + default: return "unknown"; // should not happen } } @@ -391,19 +391,19 @@ int CParser::Priority(int optorkind) { // returns the priority of an operator // higher number means higher priority switch(optorkind) { - case OPor: return 1; - case OPand: return 2; - case OPgreater: - case OPless: - case OPgreaterequal: - case OPlessequal: - case OPequal: - case OPunequal: return 3; - case OPplus: - case OPminus: return 4; - case OPmodulus: - case OPtimes: - case OPdivide: return 5; + case OPor: return 1; + case OPand: return 2; + case OPgreater: + case OPless: + case OPgreaterequal: + case OPlessequal: + case OPequal: + case OPunequal: return 3; + case OPplus: + case OPminus: return 4; + case OPmodulus: + case OPtimes: + case OPdivide: return 5; } MT_assert(false); return 0; // should not happen diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 51cfb5471c0..080e7196d5a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -255,12 +255,15 @@ typedef struct PyObjectPlus_Proxy { #define KX_PYMETHODTABLE_NOARGS(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (const char *)class_name::method_name##_doc} +#define KX_PYMETHODTABLE_KEYWORDS(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS|METH_KEYWORDS, (const char *)class_name::method_name##_doc} + /** * Function implementation macro */ #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject* args, PyObject*) +PyObject* class_name::Py##method_name(PyObject* args, PyObject* kwds) #define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index c270d9a312b..7c1824cd4eb 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -40,20 +40,20 @@ SCA_2DFilterActuator::~SCA_2DFilterActuator() } SCA_2DFilterActuator::SCA_2DFilterActuator( - SCA_IObject *gameobj, + SCA_IObject *gameobj, RAS_2DFilterManager::RAS_2DFILTER_MODE type, - short flag, - float float_arg, - int int_arg, - RAS_IRasterizer* rasterizer, - SCA_IScene* scene) + short flag, + float float_arg, + int int_arg, + RAS_IRasterizer* rasterizer, + SCA_IScene* scene) : SCA_IActuator(gameobj, KX_ACT_2DFILTER), - m_type(type), - m_disableMotionBlur(flag), - m_float_arg(float_arg), - m_int_arg(int_arg), - m_rasterizer(rasterizer), - m_scene(scene) + m_type(type), + m_disableMotionBlur(flag), + m_float_arg(float_arg), + m_int_arg(int_arg), + m_rasterizer(rasterizer), + m_scene(scene) { m_gameobj = NULL; if(gameobj){ @@ -65,9 +65,9 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( CValue* SCA_2DFilterActuator::GetReplica() { - SCA_2DFilterActuator* replica = new SCA_2DFilterActuator(*this); - replica->ProcessReplica(); - return replica; + SCA_2DFilterActuator* replica = new SCA_2DFilterActuator(*this); + replica->ProcessReplica(); + return replica; } @@ -94,7 +94,7 @@ bool SCA_2DFilterActuator::Update() m_scene->Update2DFilter(m_propNames, m_gameobj, m_type, m_int_arg, m_shaderText); } // once the filter is in place, no need to update it again => disable the actuator - return false; + return false; } diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 0d09e33a81b..85982bd3c0f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -216,8 +216,8 @@ void SCA_ISensor::UnregisterToManager() void SCA_ISensor::ActivateControllers(class SCA_LogicManager* logicmgr) { - for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); - c!=m_linkedcontrollers.end();++c) + for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); + c!=m_linkedcontrollers.end();++c) { SCA_IController* contr = *c; if (contr->IsActive()) diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 741448b1096..f90f1e19a67 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -105,7 +105,7 @@ public: }; SCA_ISensor(SCA_IObject* gameobj, - class SCA_EventManager* eventmgr);; + class SCA_EventManager* eventmgr); ~SCA_ISensor(); virtual void ReParent(SCA_IObject* parent); diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 513be43ec28..a2374ccb9da 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -132,7 +132,7 @@ bool SCA_KeyboardSensor::Evaluate() // cerr << "SCA_KeyboardSensor::Eval event, sensing for "<< m_hotkey << " at device " << inputdev << "\n"; /* See if we need to do logging: togPropState exists and is - * different from 0 */ + * different from 0 */ CValue* myparent = GetParent(); CValue* togPropState = myparent->GetProperty(m_toggleprop); if (togPropState && @@ -400,7 +400,7 @@ void SCA_KeyboardSensor::LogKeystrokes(void) int index = 0; /* Check on all keys whether they were pushed. This does not - * untangle the ordering, so don't type too fast :) */ + * untangle the ordering, so don't type too fast :) */ for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++) { const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i); diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index a1836163e9c..93d2ae2c1c5 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -50,12 +50,12 @@ /* ------------------------------------------------------------------------- */ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr, - int startx,int starty, - short int mousemode, - SCA_IObject* gameobj) + int startx,int starty, + short int mousemode, + SCA_IObject* gameobj) : SCA_ISensor(gameobj,eventmgr), - m_x(startx), - m_y(starty) + m_x(startx), + m_y(starty) { m_mousemode = mousemode; m_triggermode = true; @@ -72,7 +72,7 @@ void SCA_MouseSensor::Init() SCA_MouseSensor::~SCA_MouseSensor() { - /* Nothing to be done here. */ + /* Nothing to be done here. */ } void SCA_MouseSensor::UpdateHotkey(void *self) diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 3a6b00198e1..d76f3f775a5 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -152,7 +152,7 @@ bool SCA_RandomActuator::Update() /* If x_1, x_2, ... is a sequence of random numbers with uniform */ /* distribution between zero and one, k is the first integer for */ /* which the product x_1*x_2*...*x_k < exp(-\lamba). */ - float a = 0.0, b = 0.0; + float a, b; int res = 0; /* The - sign is important here! The number to test for, a, must be */ /* between 0 and 1. */ diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp index 06c24c8211b..67af6237a8d 100644 --- a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp @@ -68,12 +68,12 @@ SCA_RandomNumberGenerator::~SCA_RandomNumberGenerator() { void SCA_RandomNumberGenerator::SetStartVector(void) { /* setting initial seeds to mt[N] using */ - /* the generator Line 25 of Table 1 in */ - /* [KNUTH 1981, The Art of Computer Programming */ - /* Vol. 2 (2nd Ed.), pp102] */ - mt[0] = m_seed & 0xffffffff; - for (mti = 1; mti < N; mti++) - mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; + /* the generator Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming */ + /* Vol. 2 (2nd Ed.), pp102] */ + mt[0] = m_seed & 0xffffffff; + for (mti = 1; mti < N; mti++) + mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; } long SCA_RandomNumberGenerator::GetSeed() { return m_seed; } @@ -87,39 +87,39 @@ void SCA_RandomNumberGenerator::SetSeed(long newseed) * This is the important part: copied verbatim :) */ unsigned long SCA_RandomNumberGenerator::Draw() { - static unsigned long mag01[2] = { 0x0, MATRIX_A }; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - unsigned long y; - - if (mti >= N) { /* generate N words at one time */ - int kk; - - /* I set this in the constructor, so it is always satisfied ! */ -// if (mti == N+1) /* if sgenrand() has not been called, */ -// GEN_srand(4357); /* a default initial seed is used */ - - for (kk = 0; kk < N - M; kk++) { - y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); - mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; - } - for (; kk < N-1; kk++) { - y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); - mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; - } - y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; - - mti = 0; - } - - y = mt[mti++]; - y ^= TEMPERING_SHIFT_U(y); - y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; - y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; - y ^= TEMPERING_SHIFT_L(y); - - return y; + static unsigned long mag01[2] = { 0x0, MATRIX_A }; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + unsigned long y; + + if (mti >= N) { /* generate N words at one time */ + int kk; + + /* I set this in the constructor, so it is always satisfied ! */ + // if (mti == N+1) /* if sgenrand() has not been called, */ + // GEN_srand(4357); /* a default initial seed is used */ + + for (kk = 0; kk < N - M; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; + } + for (; kk < N-1; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); + mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; + } + y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + + mti = 0; + } + + y = mt[mti++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y ^= TEMPERING_SHIFT_L(y); + + return y; } float SCA_RandomNumberGenerator::DrawFloat() { diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 99e25042582..c23722d2d3c 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -48,8 +48,8 @@ /* ------------------------------------------------------------------------- */ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, - SCA_IObject* gameobj, - int startseed) + SCA_IObject* gameobj, + int startseed) : SCA_ISensor(gameobj,eventmgr) { m_basegenerator = new SCA_RandomNumberGenerator(startseed); @@ -65,10 +65,10 @@ SCA_RandomSensor::~SCA_RandomSensor() void SCA_RandomSensor::Init() { - m_iteration = 0; + m_iteration = 0; m_interval = 0; m_lastdraw = false; - m_currentDraw = m_basegenerator->Draw(); + m_currentDraw = m_basegenerator->Draw(); } @@ -97,19 +97,19 @@ bool SCA_RandomSensor::IsPositiveTrigger() bool SCA_RandomSensor::Evaluate() { - /* Random generator is the generator from Line 25 of Table 1 in */ - /* [KNUTH 1981, The Art of Computer Programming Vol. 2 */ - /* (2nd Ed.), pp102] */ - /* It's a very simple max. length sequence generator. We can */ - /* draw 32 bool values before having to generate the next */ - /* sequence value. There are some theorems that will tell you */ - /* this is a reasonable way of generating bools. Check Knuth. */ - /* Furthermore, we only draw each <delay>-eth frame. */ + /* Random generator is the generator from Line 25 of Table 1 in */ + /* [KNUTH 1981, The Art of Computer Programming Vol. 2 */ + /* (2nd Ed.), pp102] */ + /* It's a very simple max. length sequence generator. We can */ + /* draw 32 bool values before having to generate the next */ + /* sequence value. There are some theorems that will tell you */ + /* this is a reasonable way of generating bools. Check Knuth. */ + /* Furthermore, we only draw each <delay>-eth frame. */ bool evaluateResult = false; if (++m_interval > m_pulse_frequency) { - bool drawResult = false; + bool drawResult = false; m_interval = 0; if (m_iteration > 31) { m_currentDraw = m_basegenerator->Draw(); @@ -122,8 +122,8 @@ bool SCA_RandomSensor::Evaluate() evaluateResult = drawResult != m_lastdraw; m_lastdraw = drawResult; } - - /* now pass this result to some controller */ + + /* now pass this result to some controller */ return evaluateResult; } diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index f5eefd5cc08..4a03062b6ad 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -63,22 +63,22 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) bool sensorresult = false; for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin(); - !(is==m_linkedsensors.end());is++) + !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; if (sensor->GetState()) { if (sensorresult == true) { - sensorresult = false; + sensorresult = false; break; } - sensorresult = true; + sensorresult = true; } } for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); - !(i==m_linkedactuators.end());i++) + !(i==m_linkedactuators.end());i++) { SCA_IActuator* actua = *i; logicmgr->AddActiveActuator(actua,sensorresult); diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp index e3b900173d9..ecb2c4f3bd1 100644 --- a/source/gameengine/GamePlayer/common/bmfont.cpp +++ b/source/gameengine/GamePlayer/common/bmfont.cpp @@ -190,7 +190,7 @@ void detectBitmapFont(ImBuf *ibuf) long i; if (ibuf != NULL) { - // bitmap must have an x size that is a power of two + // bitmap must have an x size that is a power of two if (is_power_of_two(ibuf->x)) { rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1))); // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index a4824e0004d..c5daae9c963 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -139,7 +139,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) GPG_Application::~GPG_Application(void) { - if(m_pyGlobalDictString) { + if(m_pyGlobalDictString) { delete [] m_pyGlobalDictString; m_pyGlobalDictString = 0; m_pyGlobalDictString_Length = 0; @@ -545,6 +545,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0); bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0); + bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES; if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); @@ -626,6 +627,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) m_ketsjiengine->SetUseFixedTime(fixed_framerate); m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties); + m_ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS); m_engineInitialized = true; } diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index cbbeb9419d1..3f8bcf9e2ad 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -380,12 +380,12 @@ int main(int argc, char** argv) #endif /* __linux__ */ BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]); #ifdef __APPLE__ - // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh) - /* - IBNibRef nibRef; - WindowRef window; - OSStatus err; - + // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh) + /* + IBNibRef nibRef; + WindowRef window; + OSStatus err; + // Create a Nib reference passing the name of the nib file (without the .nib extension) // CreateNibReference only searches into the application bundle. err = ::CreateNibReference(CFSTR("main"), &nibRef); @@ -398,7 +398,7 @@ int main(int argc, char** argv) // We don't need the nib reference anymore. ::DisposeNibReference(nibRef); - */ + */ #endif // __APPLE__ // We don't use threads directly in the BGE, but we need to call this so things like @@ -421,7 +421,7 @@ int main(int argc, char** argv) BLF_init(11, U.dpi); BLF_lang_init(); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); - + // Parse command line options #if defined(DEBUG) printf("argv[0] = '%s'\n", argv[0]); diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp new file mode 100644 index 00000000000..08794042e37 --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -0,0 +1,453 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_Action.cpp + * \ingroup ketsji + */ + +#include <cstdlib> + +#include "BL_Action.h" +#include "BL_ArmatureObject.h" +#include "BL_DeformableGameObject.h" +#include "BL_ShapeDeformer.h" +#include "KX_IpoConvert.h" +#include "KX_GameObject.h" + +// These three are for getting the action from the logic manager +#include "KX_Scene.h" +#include "KX_PythonInit.h" +#include "SCA_LogicManager.h" + +extern "C" { +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "RNA_access.h" +#include "RNA_define.h" +} + +BL_Action::BL_Action(class KX_GameObject* gameobj) +: + m_action(NULL), + m_pose(NULL), + m_blendpose(NULL), + m_blendinpose(NULL), + m_ptrrna(NULL), + m_obj(gameobj), + m_startframe(0.f), + m_endframe(0.f), + m_endtime(0.f), + m_localtime(0.f), + m_blendin(0.f), + m_blendframe(0.f), + m_blendstart(0.f), + m_speed(0.f), + m_priority(0), + m_playmode(0), + m_ipo_flags(0), + m_done(true), + m_calc_localtime(true) +{ + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + + m_ptrrna = new PointerRNA(); + RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + if (shape_deformer) + { + m_ptrrna = new PointerRNA(); + RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna); + } + } +} + +BL_Action::~BL_Action() +{ + if (m_pose) + game_free_pose(m_pose); + if (m_blendpose) + game_free_pose(m_blendpose); + if (m_blendinpose) + game_free_pose(m_blendinpose); + if (m_ptrrna) + delete m_ptrrna; + ClearControllerList(); +} + +void BL_Action::ClearControllerList() +{ + // Clear out the controller list + std::vector<SG_Controller*>::iterator it; + for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++) + { + m_obj->GetSGNode()->RemoveSGController((*it)); + delete *it; + } + + m_sg_contr_list.clear(); +} + +bool BL_Action::Play(const char* name, + float start, + float end, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed) +{ + + // Only start playing a new action if we're done, or if + // the new action has a higher priority + if (priority != 0 && !IsDone() && priority >= m_priority) + return false; + m_priority = priority; + bAction* prev_action = m_action; + + // First try to load the action + m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); + if (!m_action) + { + printf("Failed to load action: %s\n", name); + m_done = true; + return false; + } + + if (prev_action != m_action) + { + // First get rid of any old controllers + ClearControllerList(); + + // Create an SG_Controller + SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + + // Extra controllers + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) + { + sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) + { + sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + } + + m_ipo_flags = ipo_flags; + InitIPO(); + + // Setup blendin shapes/poses + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + obj->GetMRDPose(&m_blendinpose); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + if (shape_deformer && shape_deformer->GetKey()) + { + obj->GetShape(m_blendinshape); + + // Now that we have the previous blend shape saved, we can clear out the key to avoid any + // further interference. + KeyBlock *kb; + for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) + kb->curval = 0.f; + } + } + + // Now that we have an action, we have something we can play + m_starttime = KX_GetActiveEngine()->GetFrameTime(); + m_startframe = m_localtime = start; + m_endframe = end; + m_blendin = blendin; + m_playmode = play_mode; + m_endtime = 0.f; + m_blendframe = 0.f; + m_blendstart = 0.f; + m_speed = playback_speed; + m_layer_weight = layer_weight; + + m_done = false; + + return true; +} + +void BL_Action::Stop() +{ + m_done = true; +} + +bool BL_Action::IsDone() +{ + return m_done; +} + +void BL_Action::InitIPO() +{ + // Initialize the IPOs + std::vector<SG_Controller*>::iterator it; + for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++) + { + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL); + } +} + +bAction *BL_Action::GetAction() +{ + return (IsDone()) ? NULL : m_action; +} + +float BL_Action::GetFrame() +{ + return m_localtime; +} + +void BL_Action::SetFrame(float frame) +{ + // Clamp the frame to the start and end frame + if (frame < min(m_startframe, m_endframe)) + frame = min(m_startframe, m_endframe); + else if (frame > max(m_startframe, m_endframe)) + frame = max(m_startframe, m_endframe); + + m_localtime = frame; + m_calc_localtime = false; +} + +void BL_Action::SetPlayMode(short play_mode) +{ + m_playmode = play_mode; +} + +void BL_Action::SetTimes(float start, float end) +{ + m_startframe = start; + m_endframe = end; +} + +void BL_Action::SetLocalTime(float curtime) +{ + float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed; + + if (m_endframe < m_startframe) + dt = -dt; + + m_localtime = m_startframe + dt; +} + +void BL_Action::ResetStartTime(float curtime) +{ + float dt = m_localtime - m_startframe; + + m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); + SetLocalTime(curtime); +} + +void BL_Action::IncrementBlending(float curtime) +{ + // Setup m_blendstart if we need to + if (m_blendstart == 0.f) + m_blendstart = curtime; + + // Bump the blend frame + m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); + + // Clamp + if (m_blendframe>m_blendin) + m_blendframe = m_blendin; +} + + +void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape) +{ + vector<float>::const_iterator it; + float dstweight; + KeyBlock *kb; + + dstweight = 1.0F - srcweight; + //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight); + for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; + kb && it != blendshape.end(); + kb = (KeyBlock*)kb->next, it++) { + //printf("OirgKeys: %f\t%f\n", kb->curval, (*it)); + kb->curval = kb->curval * dstweight + (*it) * srcweight; + //printf("NewKey: %f\n", kb->curval); + } + //printf("\n"); +} + +void BL_Action::Update(float curtime) +{ + // Don't bother if we're done with the animation + if (m_done) + return; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + + if (m_calc_localtime) + SetLocalTime(curtime); + else + { + ResetStartTime(curtime); + m_calc_localtime = true; + } + + // Handle wrap around + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) + { + switch(m_playmode) + { + case ACT_MODE_PLAY: + // Clamp + m_localtime = m_endframe; + m_done = true; + break; + case ACT_MODE_LOOP: + // Put the time back to the beginning + m_localtime = m_startframe; + m_starttime = curtime; + break; + case ACT_MODE_PING_PONG: + // Swap the start and end frames + float temp = m_startframe; + m_startframe = m_endframe; + m_endframe = temp; + + m_starttime = curtime; + + break; + } + + if (!m_done) + InitIPO(); + } + + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + obj->GetPose(&m_pose); + + // Extract the pose from the action + { + Object *arm = obj->GetArmatureObject(); + bPose *temp = arm->pose; + + arm->pose = m_pose; + animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); + + arm->pose = temp; + } + + // Handle blending between armature actions + if (m_blendin && m_blendframe<m_blendin) + { + IncrementBlending(curtime); + + // Calculate weight + float weight = 1.f - (m_blendframe/m_blendin); + + // Blend the poses + game_blend_poses(m_pose, m_blendinpose, weight); + } + + + // Handle layer blending + if (m_layer_weight >= 0) + { + obj->GetMRDPose(&m_blendpose); + game_blend_poses(m_pose, m_blendpose, m_layer_weight); + } + + obj->SetPose(m_pose); + + obj->SetActiveAction(NULL, 0, curtime); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + // Handle shape actions if we have any + if (shape_deformer && shape_deformer->GetKey()) + { + Key *key = shape_deformer->GetKey(); + + + animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); + + // Handle blending between shape actions + if (m_blendin && m_blendframe < m_blendin) + { + IncrementBlending(curtime); + + float weight = 1.f - (m_blendframe/m_blendin); + + // We go through and clear out the keyblocks so there isn't any interference + // from other shape actions + KeyBlock *kb; + for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) + kb->curval = 0.f; + + // Now blend the shape + BlendShape(key, weight, m_blendinshape); + } + + // Handle layer blending + if (m_layer_weight >= 0) + { + obj->GetShape(m_blendshape); + BlendShape(key, m_layer_weight, m_blendshape); + } + + obj->SetActiveAction(NULL, 0, curtime); + } + + + InitIPO(); + m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD); + } +} diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h new file mode 100644 index 00000000000..92fbe95fd54 --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.h @@ -0,0 +1,144 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_Action.h + * \ingroup ketsji + */ + +#ifndef __BL_ACTION +#define __BL_ACTION + + +#include <vector> + +#ifdef WITH_CXX_GUARDEDALLOC +#include "MEM_guardedalloc.h" +#endif + + +class BL_Action +{ +private: + struct bAction* m_action; + struct bPose* m_pose; + struct bPose* m_blendpose; + struct bPose* m_blendinpose; + struct PointerRNA *m_ptrrna; + std::vector<class SG_Controller*> m_sg_contr_list; + class KX_GameObject* m_obj; + std::vector<float> m_blendshape; + std::vector<float> m_blendinshape; + + float m_startframe; + float m_endframe; + float m_starttime; + float m_endtime; + float m_localtime; + + float m_blendin; + float m_blendframe; + float m_blendstart; + + float m_layer_weight; + + float m_speed; + + short m_priority; + + short m_playmode; + + short m_ipo_flags; + + bool m_done; + bool m_calc_localtime; + + void ClearControllerList(); + void InitIPO(); + void SetLocalTime(float curtime); + void ResetStartTime(float curtime); + void IncrementBlending(float curtime); + void BlendShape(struct Key* key, float srcweight, std::vector<float>& blendshape); +public: + BL_Action(class KX_GameObject* gameobj); + ~BL_Action(); + + /** + * Play an action + */ + bool Play(const char* name, + float start, + float end, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed); + /** + * Stop playing the action + */ + void Stop(); + /** + * Whether or not the action is still playing + */ + bool IsDone(); + /** + * Update the action's frame, etc. + */ + void Update(float curtime); + + // Accessors + float GetFrame(); + struct bAction *GetAction(); + + // Mutators + void SetFrame(float frame); + void SetPlayMode(short play_mode); + void SetTimes(float start, float end); + + enum + { + ACT_MODE_PLAY = 0, + ACT_MODE_LOOP, + ACT_MODE_PING_PONG, + ACT_MODE_MAX, + }; + + enum + { + ACT_IPOFLAG_FORCE = 1, + ACT_IPOFLAG_LOCAL = 2, + ACT_IPOFLAG_ADD = 4, + ACT_IPOFLAG_CHILD = 8, + }; + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_Action"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTION + diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp new file mode 100644 index 00000000000..4e4d3bc539e --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -0,0 +1,110 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_ActionManager.cpp + * \ingroup ketsji + */ + +#include "BL_ActionManager.h" + +BL_ActionManager::BL_ActionManager(class KX_GameObject *obj) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + m_layers[i] = new BL_Action(obj); +} + +BL_ActionManager::~BL_ActionManager() +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + delete m_layers[i]; +} + +float BL_ActionManager::GetActionFrame(short layer) +{ + return m_layers[layer]->GetFrame(); + + return 0.f; +} + +void BL_ActionManager::SetActionFrame(short layer, float frame) +{ + m_layers[layer]->SetFrame(frame); +} + +struct bAction *BL_ActionManager::GetCurrentAction(short layer) +{ + return m_layers[layer]->GetAction(); + + return 0; +} + +void BL_ActionManager::SetPlayMode(short layer, short mode) +{ + m_layers[layer]->SetPlayMode(mode); +} + +void BL_ActionManager::SetTimes(short layer, float start, float end) +{ + m_layers[layer]->SetTimes(start, end); +} + +bool BL_ActionManager::PlayAction(const char* name, + float start, + float end, + short layer, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed) +{ + // Disable layer blending on the first layer + if (layer == 0) layer_weight = -1.f; + + return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed); +} + +void BL_ActionManager::StopAction(short layer) +{ + m_layers[layer]->Stop(); +} + +bool BL_ActionManager::IsActionDone(short layer) +{ + return m_layers[layer]->IsDone(); + + return true; +} + +void BL_ActionManager::Update(float curtime) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + { + if (!m_layers[i]->IsDone()) + { + m_layers[i]->Update(curtime); + } + } +} diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h new file mode 100644 index 00000000000..a3c8379981e --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -0,0 +1,106 @@ +/** + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_ActionManager.cpp + * \ingroup ketsji + */ + +#ifndef __BL_ACTIONMANAGER +#define __BL_ACTIONMANAGER + +#include "BL_Action.h" + +#define MAX_ACTION_LAYERS 8 + +/** + * BL_ActionManager is responsible for handling a KX_GameObject's actions. + */ +class BL_ActionManager +{ +private: + BL_Action* m_layers[MAX_ACTION_LAYERS]; + +public: + BL_ActionManager(class KX_GameObject* obj); + ~BL_ActionManager(); + + bool PlayAction(const char* name, + float start, + float end, + short layer=0, + short priority=0, + float blendin=0.f, + short play_mode=0, + float layer_weight=0.f, + short ipo_flags=0, + float playback_speed=1.f); + /** + * Gets the current frame of an action + */ + float GetActionFrame(short layer); + + /** + * Sets the current frame of an action + */ + void SetActionFrame(short layer, float frame); + + /** + * Gets the currently running action on the given layer + */ + struct bAction *GetCurrentAction(short layer); + + /** + * Sets play mode of the action on the given layer + */ + void SetPlayMode(short layer, short mode); + + /** + * Sets the start and end times of the action on the given layer + */ + void SetTimes(short layer, float start, float end); + + /** + * Stop playing the action on the given layer + */ + void StopAction(short layer); + + /** + * Check if an action has finished playing + */ + bool IsActionDone(short layer); + + /** + * Update any running actions + */ + void Update(float); + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_ActionManager"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTIONMANAGER + diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 83c4daf4b9b..39e5361a27f 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -64,7 +64,7 @@ int BL_BlenderShader::GetAttribNum() GPU_material_vertex_attributes(mGPUMat, &attribs); - for(i = 0; i < attribs.totlayer; i++) + for(i = 0; i < attribs.totlayer; i++) if(attribs.layer[i].glindex+1 > enabled) enabled= attribs.layer[i].glindex+1; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index ef25c9218a3..c0440e66501 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -157,7 +157,8 @@ enum BL_ras_mode ALPHA=8, // TRIANGLE=16, USE_LIGHT=32, - WIRE=64 + WIRE=64, + CAST_SHADOW=128 }; // ------------------------------------- diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 621cabfe0cf..aea33246a3f 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -690,7 +690,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose) float value[9]; value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0]; value[3] = (float)vec[0][1]; value[4] = (float)vec[1][1]; value[5] = (float)vec[2][1]; - value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[7] = (float)vec[2][2]; + value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[8] = (float)vec[2][2]; glUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value); } } diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 8222bf4b65f..99c9fb25a65 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -45,6 +45,7 @@ set(INC ../../blender/gpu ../../blender/imbuf ../../blender/makesdna + ../../blender/makesrna ../../blender/python ../../blender/python/generic ../../blender/python/mathutils @@ -59,6 +60,8 @@ set(INC_SYS ) set(SRC + BL_Action.cpp + BL_ActionManager.cpp BL_BlenderShader.cpp BL_Material.cpp BL_Shader.cpp @@ -128,6 +131,8 @@ set(SRC KX_WorldInfo.cpp KX_WorldIpoController.cpp + BL_Action.h + BL_ActionManager.h BL_BlenderShader.h BL_Material.h BL_Shader.h @@ -223,6 +228,7 @@ endif() if(WITH_AUDASPACE) list(APPEND INC ../../../intern/audaspace/intern + ../../../intern/audaspace/FX ) add_definitions(-DWITH_AUDASPACE) endif() diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp index e8e65371d3a..72f1cee8855 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp @@ -66,8 +66,8 @@ void KX_NetworkEventManager::NextFrame() for (it.begin();!it.end();++it) { // printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime); - // process queue - (*it)->Activate(m_logicmgr); + // process queue + (*it)->Activate(m_logicmgr); } // now a list of triggerer sensors has been built diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 2e0abc0290c..9fd09506c0d 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -91,8 +91,7 @@ bool KX_NetworkMessageActuator::Update() CValue* KX_NetworkMessageActuator::GetReplica() { - KX_NetworkMessageActuator* replica = - new KX_NetworkMessageActuator(*this); + KX_NetworkMessageActuator* replica = new KX_NetworkMessageActuator(*this); replica->ProcessReplica(); return replica; diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 6dcf50fa18f..a795a4eddc6 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -50,11 +50,11 @@ #endif KX_NetworkMessageSensor::KX_NetworkMessageSensor( - class KX_NetworkEventManager* eventmgr, // our eventmanager - class NG_NetworkScene *NetworkScene, // our scene - SCA_IObject* gameobj, // the sensor controlling object - const STR_String &subject -) : + class KX_NetworkEventManager* eventmgr, // our eventmanager + class NG_NetworkScene *NetworkScene, // our scene + SCA_IObject* gameobj, // the sensor controlling object + const STR_String &subject + ) : SCA_ISensor(gameobj,eventmgr), m_NetworkScene(NetworkScene), m_subject(subject), @@ -67,7 +67,7 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor( void KX_NetworkMessageSensor::Init() { - m_IsUp = false; + m_IsUp = false; } KX_NetworkMessageSensor::~KX_NetworkMessageSensor() diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 9ff32ba57c5..33da17cc505 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -56,21 +56,21 @@ KX_BlenderMaterial::KX_BlenderMaterial() } void KX_BlenderMaterial::Initialize( - KX_Scene *scene, - BL_Material *data) + KX_Scene *scene, + BL_Material *data) { RAS_IPolyMaterial::Initialize( - data->texname[0], - data->matname, - data->materialindex, - data->tile, - data->tilexrep[0], - data->tileyrep[0], - data->mode, - data->transp, - ((data->ras_mode &ALPHA)!=0), - ((data->ras_mode &ZSORT)!=0) - ); + data->texname[0], + data->matname, + data->materialindex, + data->tile, + data->tilexrep[0], + data->tileyrep[0], + data->mode, + data->transp, + ((data->ras_mode &ALPHA)!=0), + ((data->ras_mode &ZSORT)!=0) + ); mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -80,11 +80,12 @@ void KX_BlenderMaterial::Initialize( mConstructed = false; mPass = 0; // -------------------------------- - // RAS_IPolyMaterial variables... + // RAS_IPolyMaterial variables... m_flag |= RAS_BLENDERMAT; m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0; m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0; m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; + m_flag |= ((mMaterial->ras_mode & CAST_SHADOW)!=0)? RAS_CASTSHADOW: 0; // figure max int enabled = mMaterial->num_enabled; @@ -92,14 +93,11 @@ void KX_BlenderMaterial::Initialize( mMaterial->num_enabled = enabled>=max?max:enabled; // test the sum of the various modes for equality - // so we can ether accept or reject this material - // as being equal, this is rather important to + // so we can ether accept or reject this material + // as being equal, this is rather important to // prevent material bleeding for(int i=0; i<mMaterial->num_enabled; i++) { - m_multimode += - ( mMaterial->flag[i] + - mMaterial->blend_mode[i] - ); + m_multimode += (mMaterial->flag[i] + mMaterial->blend_mode[i]); } m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); } diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index fde01961fd5..6e5513991f9 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -213,16 +213,16 @@ MT_Scalar KX_BulletPhysicsController::GetMass() MT_Vector3 KX_BulletPhysicsController::GetLocalInertia() { - MT_Vector3 inertia(0.f, 0.f, 0.f); - btVector3 inv_inertia; - if (GetRigidBody()) { - inv_inertia = GetRigidBody()->getInvInertiaDiagLocal(); - if (!btFuzzyZero(inv_inertia.getX()) && - !btFuzzyZero(inv_inertia.getY()) && - !btFuzzyZero(inv_inertia.getZ())) + MT_Vector3 inertia(0.f, 0.f, 0.f); + btVector3 inv_inertia; + if (GetRigidBody()) { + inv_inertia = GetRigidBody()->getInvInertiaDiagLocal(); + if (!btFuzzyZero(inv_inertia.getX()) && + !btFuzzyZero(inv_inertia.getY()) && + !btFuzzyZero(inv_inertia.getZ())) inertia = MT_Vector3(1.f/inv_inertia.getX(), 1.f/inv_inertia.getY(), 1.f/inv_inertia.getZ()); - } - return inertia; + } + return inertia; } MT_Vector3 KX_BulletPhysicsController::getReactionForce() diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index c60c931c33b..a488d646792 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -271,18 +271,18 @@ void KX_Camera::ExtractFrustumSphere() if (m_set_frustum_center) return; - // compute sphere for the general case and not only symmetric frustum: - // the mirror code in ImageRender can use very asymmetric frustum. - // We will put the sphere center on the line that goes from origin to the center of the far clipping plane - // This is the optimal position if the frustum is symmetric or very asymmetric and probably close - // to optimal for the general case. The sphere center position is computed so that the distance to - // the near and far extreme frustum points are equal. - - // get the transformation matrix from device coordinate to camera coordinate + // compute sphere for the general case and not only symmetric frustum: + // the mirror code in ImageRender can use very asymmetric frustum. + // We will put the sphere center on the line that goes from origin to the center of the far clipping plane + // This is the optimal position if the frustum is symmetric or very asymmetric and probably close + // to optimal for the general case. The sphere center position is computed so that the distance to + // the near and far extreme frustum points are equal. + + // get the transformation matrix from device coordinate to camera coordinate MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; clip_camcs_matrix.invert(); - if (m_projection_matrix[3][3] == MT_Scalar(0.0)) + if (m_projection_matrix[3][3] == MT_Scalar(0.0)) { // frustrum projection // detect which of the corner of the far clipping plane is the farthest to the origin @@ -302,7 +302,7 @@ void KX_Camera::ExtractFrustumSphere() MT_Scalar len; for (int i=0; i<4; i++) { - hpoint = clip_camcs_matrix*npoint; + hpoint = clip_camcs_matrix*npoint; point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); len = point.dot(point); if (len > F) @@ -321,7 +321,7 @@ void KX_Camera::ExtractFrustumSphere() farcenter *= 0.25; // the extreme near point is the opposite point on the near clipping plane nfar.setValue(-nfar[0], -nfar[1], -1., 1.); - nfar = clip_camcs_matrix*nfar; + nfar = clip_camcs_matrix*nfar; nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); // this is a frustrum projection N = nearpoint.dot(nearpoint); @@ -340,7 +340,7 @@ void KX_Camera::ExtractFrustumSphere() z = (F-N)/(2.0*(e-s+c*(f-n))); m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); m_frustum_radius = m_frustum_center.distance(farpoint); - } + } else { // orthographic projection diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index 2e1fb933ad0..00c5e5803a8 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -42,34 +42,34 @@ Developed as part of a Research and Development project for SAT - La Société d // constructor KX_Dome::KX_Dome ( - RAS_ICanvas* canvas, - /// rasterizer - RAS_IRasterizer* rasterizer, - /// render tools - RAS_IRenderTools* rendertools, - /// engine - KX_KetsjiEngine* engine, - - short res, //resolution of the mesh - short mode, //mode - fisheye, truncated, warped, panoramic, ... - short angle, - float resbuf, //size adjustment of the buffer - short tilt, - struct Text* warptext - -): - dlistSupported(false), - canvaswidth(-1), canvasheight(-1), - m_drawingmode(engine->GetDrawType()), - m_resolution(res), - m_mode(mode), - m_angle(angle), - m_resbuffer(resbuf), - m_tilt(tilt), - m_canvas(canvas), - m_rasterizer(rasterizer), - m_rendertools(rendertools), - m_engine(engine) + RAS_ICanvas* canvas, + /// rasterizer + RAS_IRasterizer* rasterizer, + /// render tools + RAS_IRenderTools* rendertools, + /// engine + KX_KetsjiEngine* engine, + + short res, //resolution of the mesh + short mode, //mode - fisheye, truncated, warped, panoramic, ... + short angle, + float resbuf, //size adjustment of the buffer + short tilt, + struct Text* warptext + + ): + dlistSupported(false), + canvaswidth(-1), canvasheight(-1), + m_drawingmode(engine->GetDrawType()), + m_resolution(res), + m_mode(mode), + m_angle(angle), + m_resbuffer(resbuf), + m_tilt(tilt), + m_canvas(canvas), + m_rasterizer(rasterizer), + m_rendertools(rendertools), + m_engine(engine) { warp.usemesh = false; fboSupported = false; @@ -1984,9 +1984,9 @@ void KX_Dome::DrawDomeWarped(void) int can_width = m_viewport.GetRight(); int can_height = m_viewport.GetTop(); - double screen_ratio = can_width/ (double) can_height; + double screen_ratio = can_width/ (double) can_height; - glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); + glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); glMatrixMode(GL_TEXTURE); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 7ca8e7e3b52..67178803457 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -74,6 +74,8 @@ typedef unsigned long uint_ptr; #include "SCA_IController.h" #include "NG_NetworkScene.h" //Needed for sendMessage() +#include "BL_ActionManager.h" + #include "PyObjectPlus.h" /* python stuff */ // This file defines relationships between parents and children @@ -85,31 +87,32 @@ typedef unsigned long uint_ptr; static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0); static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0); -static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0); +static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0); KX_GameObject::KX_GameObject( - void* sgReplicationInfo, - SG_Callbacks callbacks) - : SCA_IObject(), - m_bDyna(false), - m_layer(0), - m_pBlenderObject(NULL), - m_pBlenderGroupObject(NULL), - m_bSuspendDynamics(false), - m_bUseObjectColor(false), - m_bIsNegativeScaling(false), - m_bVisible(true), - m_bCulled(true), - m_bOccluder(false), - m_pPhysicsController1(NULL), - m_pGraphicController(NULL), - m_xray(false), - m_pHitObject(NULL), - m_isDeformable(false) -#ifdef WITH_PYTHON - , m_attr_dict(NULL) + void* sgReplicationInfo, + SG_Callbacks callbacks) + : SCA_IObject(), + m_bDyna(false), + m_layer(0), + m_pBlenderObject(NULL), + m_pBlenderGroupObject(NULL), + m_bSuspendDynamics(false), + m_bUseObjectColor(false), + m_bIsNegativeScaling(false), + m_bVisible(true), + m_bCulled(true), + m_bOccluder(false), + m_pPhysicsController1(NULL), + m_pGraphicController(NULL), + m_xray(false), + m_pHitObject(NULL), + m_actionManager(NULL), + m_isDeformable(false) + #ifdef WITH_PYTHON + , m_attr_dict(NULL) #endif { m_ignore_activity_culling = false; @@ -154,6 +157,10 @@ KX_GameObject::~KX_GameObject() { delete m_pGraphicController; } + if (m_actionManager) + { + delete m_actionManager; + } #ifdef WITH_PYTHON if (m_attr_dict) { PyDict_Clear(m_attr_dict); /* incase of circular refs or other weird cases */ @@ -344,6 +351,69 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) } } +BL_ActionManager* KX_GameObject::GetActionManager() +{ + // We only want to create an action manager if we need it + if (!m_actionManager) + m_actionManager = new BL_ActionManager(this); + + return m_actionManager; +} + +bool KX_GameObject::PlayAction(const char* name, + float start, + float end, + short layer, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed) +{ + return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed); +} + +void KX_GameObject::StopAction(short layer) +{ + GetActionManager()->StopAction(layer); +} + +bool KX_GameObject::IsActionDone(short layer) +{ + return GetActionManager()->IsActionDone(layer); +} + +void KX_GameObject::UpdateActionManager(float curtime) +{ + GetActionManager()->Update(curtime); +} + +float KX_GameObject::GetActionFrame(short layer) +{ + return GetActionManager()->GetActionFrame(layer); +} + +void KX_GameObject::SetActionFrame(short layer, float frame) +{ + GetActionManager()->SetActionFrame(layer, frame); +} + +bAction *KX_GameObject::GetCurrentAction(short layer) +{ + return GetActionManager()->GetCurrentAction(layer); +} + +void KX_GameObject::SetPlayMode(short layer, short mode) +{ + GetActionManager()->SetPlayMode(layer, mode); +} + +void KX_GameObject::SetTimes(short layer, float start, float end) +{ + GetActionManager()->SetTimes(layer, start, end); +} + void KX_GameObject::ProcessReplica() { SCA_IObject::ProcessReplica(); @@ -353,6 +423,8 @@ void KX_GameObject::ProcessReplica() m_pSGNode = NULL; m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); m_pClient_info->m_gameobject = this; + if (m_actionManager) + m_actionManager = new BL_ActionManager(this); m_state = 0; #ifdef WITH_PYTHON @@ -1497,6 +1569,12 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), KX_PYMETHODTABLE(KX_GameObject, sendMessage), + + KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction), + KX_PYMETHODTABLE(KX_GameObject, stopAction), + KX_PYMETHODTABLE(KX_GameObject, getActionFrame), + KX_PYMETHODTABLE(KX_GameObject, setActionFrame), + KX_PYMETHODTABLE(KX_GameObject, isPlayingAction), // dict style access for props {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS}, @@ -1839,7 +1917,7 @@ PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBU { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); - return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); + return PyFloat_FromDouble(spc ? spc->GetLinVelocityMin() : 0.0f); } int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -2975,6 +3053,112 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, Py_RETURN_NONE; } +static void layer_check(short &layer, const char *method_name) +{ + if (layer < 0 || layer >= MAX_ACTION_LAYERS) + { + printf("KX_GameObject.%s(): given layer (%d) is out of range (0 - %d), setting to 0.\n", method_name, layer, MAX_ACTION_LAYERS-1); + layer = 0; + } +} + +KX_PYMETHODDEF_DOC(KX_GameObject, playAction, + "playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)\n" + "Plays an action\n") +{ + const char* name; + float start, end, blendin=0.f, speed=1.f, layer_weight=0.f; + short layer=0, priority=0; + short ipo_flags=0; + short play_mode=0; + + static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist), + &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed)) + return NULL; + + layer_check(layer, "playAction"); + + if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX) + { + printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1); + play_mode = BL_Action::ACT_MODE_MAX; + } + + if (layer_weight < 0.f || layer_weight > 1.f) + { + printf("KX_GameObject.playAction(): given layer_weight (%f) is out of range (0.0 - 1.0), setting to 0.0", layer_weight); + layer_weight = 0.f; + } + + PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed); + + Py_RETURN_NONE; +} + +KX_PYMETHODDEF_DOC(KX_GameObject, stopAction, + "stopAction(layer=0)\n" + "Stop playing the action on the given layer\n") +{ + short layer=0; + + if (!PyArg_ParseTuple(args, "|h:stopAction", &layer)) + return NULL; + + layer_check(layer, "stopAction"); + + StopAction(layer); + + Py_RETURN_NONE; +} + +KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame, + "getActionFrame(layer=0)\n" + "Gets the current frame of the action playing in the supplied layer\n") +{ + short layer=0; + + if (!PyArg_ParseTuple(args, "|h:getActionFrame", &layer)) + return NULL; + + layer_check(layer, "getActionFrame"); + + return PyFloat_FromDouble(GetActionFrame(layer)); +} + +KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame, + "setActionFrame(frame, layer=0)\n" + "Set the current frame of the action playing in the supplied layer\n") +{ + short layer=0; + float frame; + + if (!PyArg_ParseTuple(args, "f|h:setActionFrame", &frame, &layer)) + return NULL; + + layer_check(layer, "setActionFrame"); + + SetActionFrame(layer, frame); + + Py_RETURN_NONE; +} + +KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction, + "isPlayingAction(layer=0)\n" + "Checks to see if there is an action playing in the given layer\n") +{ + short layer=0; + + if (!PyArg_ParseTuple(args, "|h:isPlayingAction", &layer)) + return NULL; + + layer_check(layer, "isPlayingAction"); + + return PyBool_FromLong(!IsActionDone(layer)); +} + + /* dict style access */ diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 50fbebe1341..6e79914172b 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -63,7 +63,9 @@ class RAS_MeshObject; class KX_IPhysicsController; class PHY_IGraphicController; class PHY_IPhysicsEnvironment; +class BL_ActionManager; struct Object; +struct bAction; #ifdef WITH_PYTHON /* utility conversion function */ @@ -112,6 +114,11 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + + // The action manager is used to play/stop/update actions + BL_ActionManager* m_actionManager; + + BL_ActionManager* GetActionManager(); public: bool m_isDeformable; @@ -198,6 +205,68 @@ public: */ void RemoveParent(KX_Scene *scene); + /********************************* + * Animation API + *********************************/ + + /** + * Adds an action to the object's action manager + */ + bool PlayAction(const char* name, + float start, + float end, + short layer=0, + short priority=0, + float blendin=0.f, + short play_mode=0, + float layer_weight=0.f, + short ipo_flags=0, + float playback_speed=1.f); + + /** + * Gets the current frame of an action + */ + float GetActionFrame(short layer); + + /** + * Sets the current frame of an action + */ + void SetActionFrame(short layer, float frame); + + /** + * Gets the currently running action on the given layer + */ + bAction *GetCurrentAction(short layer); + + /** + * Sets play mode of the action on the given layer + */ + void SetPlayMode(short layer, short mode); + + /** + * Sets the start and end times of the action on the given layer + */ + void SetTimes(short layer, float start, float end); + + /** + * Stop playing the action on the given layer + */ + void StopAction(short layer); + + /** + * Check if an action has finished playing + */ + bool IsActionDone(short layer); + + /** + * Kick the object's action manager + */ + void UpdateActionManager(float curtime); + + /********************************* + * End Animation API + *********************************/ + /** * Construct a game object. This class also inherits the * default constructors - use those with care! @@ -853,6 +922,12 @@ public: KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage); KX_PYMETHOD_VARARGS(KX_GameObject, ReinstancePhysicsMesh); + + KX_PYMETHOD_DOC(KX_GameObject, playAction); + KX_PYMETHOD_DOC(KX_GameObject, stopAction); + KX_PYMETHOD_DOC(KX_GameObject, getActionFrame); + KX_PYMETHOD_DOC(KX_GameObject, setActionFrame); + KX_PYMETHOD_DOC(KX_GameObject, isPlayingAction); /* Dict access */ KX_PYMETHOD_VARARGS(KX_GameObject,get); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 0aa36b4cd5f..ca67333166c 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -70,6 +70,7 @@ #ifdef WITH_AUDASPACE # include "AUD_C-API.h" +# include "AUD_I3DDevice.h" #endif #include "NG_NetworkScene.h" @@ -91,10 +92,10 @@ const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = { "Physics:", // tc_physics - "Logic", // tc_logic + "Logic:", // tc_logic + "Animations:", // tc_animations "Network:", // tc_network "Scenegraph:", // tc_scenegraph - "Sound:", // tc_sound "Rasterizer:", // tc_rasterizer "Services:", // tc_services "Overhead:", // tc_overhead @@ -108,13 +109,14 @@ double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; double KX_KetsjiEngine::m_average_framerate = 0.0; +bool KX_KetsjiEngine::m_restrict_anim_fps = false; /** * Constructor of the Ketsji Engine */ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) - : m_canvas(NULL), + : m_canvas(NULL), m_rasterizer(NULL), m_kxsystem(system), m_rendertools(NULL), @@ -137,6 +139,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_frameTime(0.f), m_clockTime(0.f), m_previousClockTime(0.f), + m_previousAnimTime(0.f), m_exitcode(KX_EXIT_REQUEST_NO_REQUEST), @@ -578,7 +581,7 @@ else framestep = (frames*timestep)/m_maxLogicFrame; frames = m_maxLogicFrame; } - + while (frames) { @@ -657,7 +660,14 @@ else m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE); scene->UpdateParents(m_frameTime); - + + if (!GetRestrictAnimationFPS()) + { + m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); + scene->UpdateAnimations(m_frameTime); + } + m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->GetPhysicsEnvironment()->beginFrame(); @@ -681,8 +691,6 @@ else else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); - - DoSound(scene); m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } @@ -758,14 +766,30 @@ else if(scene->getSuspendedTime()==0.0) scene->setSuspendedTime(m_clockTime); - DoSound(scene); - m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); } } + + // Handle the animations independently of the logic time step + if (GetRestrictAnimationFPS()) + { + m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); + SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); - m_previousClockTime = m_clockTime; + double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS(); + if (m_clockTime - m_previousAnimTime > anim_timestep) + { + // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep) + // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime)); + m_previousAnimTime = m_clockTime; + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) + { + (*sceneit)->UpdateAnimations(m_frameTime); + } + } + m_previousClockTime = m_clockTime; + } // Start logging time spend outside main loop m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true); @@ -974,29 +998,6 @@ const STR_String& KX_KetsjiEngine::GetExitString() } - -void KX_KetsjiEngine::DoSound(KX_Scene* scene) -{ - m_logger->StartLog(tc_sound, m_kxsystem->GetTimeInSeconds(), true); - - KX_Camera* cam = scene->GetActiveCamera(); - if (!cam) - return; - - float f[4]; - - cam->NodeGetWorldPosition().getValue(f); - AUD_setListenerLocation(f); - - cam->GetLinearVelocity().getValue(f); - AUD_setListenerVelocity(f); - - cam->NodeGetWorldOrientation().getRotation().getValue(f); - AUD_setListenerOrientation(f); -} - - - void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) { if (wi->hasWorld()) @@ -1334,6 +1335,9 @@ To run once per scene */ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) { + // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up) + m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); + m_rendertools->MotionBlur(m_rasterizer); scene->Render2DFilters(m_canvas); #ifdef WITH_PYTHON @@ -1799,6 +1803,16 @@ void KX_KetsjiEngine::SetMaxPhysicsFrame(int frame) m_maxPhysicsFrame = frame; } +bool KX_KetsjiEngine::GetRestrictAnimationFPS() +{ + return m_restrict_anim_fps; +} + +void KX_KetsjiEngine::SetRestrictAnimationFPS(bool bRestrictAnimFPS) +{ + m_restrict_anim_fps = bRestrictAnimFPS; +} + double KX_KetsjiEngine::GetAnimFrameRate() { return m_anim_framerate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 8cd6fdb8f5f..b1009c7d8f0 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -108,6 +108,7 @@ private: double m_frameTime;//discrete timestamp of the 'game logic frame' double m_clockTime;//current time double m_previousClockTime;//previous clock time + double m_previousAnimTime; //the last time animations were updated double m_remainingTime; static int m_maxLogicFrame; /* maximum number of consecutive logic frame */ @@ -115,6 +116,8 @@ private: static double m_ticrate; static double m_anim_framerate; /* for animation playback only - ipo and action */ + static bool m_restrict_anim_fps; + static double m_suspendedtime; static double m_suspendeddelta; @@ -147,9 +150,9 @@ private: tc_first = 0, tc_physics = 0, tc_logic, + tc_animations, tc_network, tc_scenegraph, - tc_sound, tc_rasterizer, tc_services, // time spend in miscelaneous activities tc_overhead, // profile info drawing overhead @@ -195,7 +198,6 @@ private: void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); void SetBackGround(KX_WorldInfo* worldinfo); - void DoSound(KX_Scene* scene); void RenderFonts(KX_Scene* scene); public: @@ -321,6 +323,16 @@ public: static void SetMaxPhysicsFrame(int frame); /** + * Gets whether or not to lock animation updates to the animframerate + */ + static bool GetRestrictAnimationFPS(); + + /** + * Sets whether or not to lock animation updates to the animframerate + */ + static void SetRestrictAnimationFPS(bool bRestrictAnimFPS); + + /** * Gets the framerate for playing animations. (actions and ipos) */ static double GetAnimFrameRate(); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 3f09eee013e..2f2c45cd5cc 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -355,11 +355,11 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT } else if (!strcmp(type, "NORMAL")) { retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); } - else { - /* should never happen */ - PyErr_SetString(PyExc_TypeError, "light.type: internal error, invalid light type"); - retvalue = NULL; - } + else { + /* should never happen */ + PyErr_SetString(PyExc_TypeError, "light.type: internal error, invalid light type"); + retvalue = NULL; + } return retvalue; } diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index ba41dc355f7..9ad09f9793b 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -119,7 +119,7 @@ CValue* KX_MeshProxy::GetReplica() { return NULL;} PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) { - int matid= 1; + int matid= 1; STR_String matname; if (PyArg_ParseTuple(args,"i:getMaterialName",&matid)) @@ -131,13 +131,13 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) } return PyUnicode_FromString(matname.Ptr()); - + } - + PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) { - int matid= 1; + int matid= 1; STR_String matname; if (PyArg_ParseTuple(args,"i:getTextureName",&matid)) @@ -154,7 +154,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) { - int matid= 0; + int matid= 0; int length = 0; @@ -177,7 +177,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) { - int vertexindex; + int vertexindex; int matindex; if (!PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex)) @@ -195,7 +195,7 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) { - int polyindex= 1; + int polyindex= 1; PyObject* polyob = NULL; if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex)) diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 6cb80028858..34f5c26415d 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -121,14 +121,14 @@ bool KX_MouseFocusSensor::Evaluate() } } if (reset) { - // force an event + // force an event result = true; } } else { /* No focus behaviour required: revert to the basic mode. This - * mode is never used, because the converter never makes this - * sensor for a mouse-key event. It is here for - * completeness. */ + * mode is never used, because the converter never makes this + * sensor for a mouse-key event. It is here for + * completeness. */ result = SCA_MouseSensor::Evaluate(); m_positive_event = (m_val!=0); } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index f643030e3a2..395e2048cb7 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -113,6 +113,7 @@ extern "C" { #include "NG_NetworkScene.h" //Needed for sendMessage() #include "BL_Shader.h" +#include "BL_Action.h" #include "KX_PyMath.h" @@ -388,10 +389,10 @@ static PyObject* gPyGetSpectrum(PyObject*) { PyObject* resultlist = PyList_New(512); - for (int index = 0; index < 512; index++) - { - PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(0.0)); - } + for (int index = 0; index < 512; index++) + { + PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(0.0)); + } return resultlist; } @@ -478,13 +479,13 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) char cpath[sizeof(gp_GamePythonPath)]; char *searchpath = NULL; PyObject* list, *value; - - DIR *dp; - struct dirent *dirp; - + + DIR *dp; + struct dirent *dirp; + if (!PyArg_ParseTuple(args, "|s:getBlendFileList", &searchpath)) return NULL; - + list = PyList_New(0); if (searchpath) { @@ -494,23 +495,23 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) /* Get the dir only */ BLI_split_dirfile(gp_GamePythonPath, cpath, NULL); } - - if((dp = opendir(cpath)) == NULL) { + + if((dp = opendir(cpath)) == NULL) { /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ fprintf(stderr, "Could not read directoty (%s) failed, code %d (%s)\n", cpath, errno, strerror(errno)); return list; - } + } - while ((dirp = readdir(dp)) != NULL) { + while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { value= PyUnicode_DecodeFSDefault(dirp->d_name); PyList_Append(list, value); Py_DECREF(value); } - } + } - closedir(dp); - return list; + closedir(dp); + return list; } static char gPyAddScene_doc[] = @@ -1207,6 +1208,28 @@ static PyObject* gPyGetMaterialType(PyObject*) return PyLong_FromSsize_t(flag); } +static PyObject* gPySetAnisotropicFiltering(PyObject*, PyObject* args) +{ + short level; + + if (!PyArg_ParseTuple(args, "h:setAnisotropicFiltering", &level)) + return NULL; + + if (level != 1 && level != 2 && level != 4 && level != 8 && level != 16) { + PyErr_SetString(PyExc_ValueError, "Rasterizer.setAnisotropicFiltering(level): Expected value of 1, 2, 4, 8, or 16 for value"); + return NULL; + } + + gp_Rasterizer->SetAnisotropicFiltering(level); + + Py_RETURN_NONE; +} + +static PyObject* gPyGetAnisotropicFiltering(PyObject*, PyObject* args) +{ + return PyLong_FromLong(gp_Rasterizer->GetAnisotropicFiltering()); +} + static PyObject* gPyDrawLine(PyObject*, PyObject* args) { PyObject* ob_from; @@ -1271,6 +1294,10 @@ static struct PyMethodDef rasterizer_methods[] = { METH_VARARGS, "set the state of a GLSL material setting"}, {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, METH_VARARGS, "get the state of a GLSL material setting"}, + {"setAnisotropicFiltering", (PyCFunction) gPySetAnisotropicFiltering, + METH_VARARGS, "set the anisotropic filtering level (must be one of 1, 2, 4, 8, 16)"}, + {"getAnisotropicFiltering", (PyCFunction) gPyGetAnisotropicFiltering, + METH_VARARGS, "get the anisotropic filtering level"}, {"drawLine", (PyCFunction) gPyDrawLine, METH_VARARGS, "draw a line on the screen"}, { NULL, (PyCFunction) NULL, 0, NULL } @@ -1628,11 +1655,16 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, ROT_MODE_ZXY, ROT_MODE_ZXY); KX_MACRO_addTypesToDict(d, ROT_MODE_ZYX, ROT_MODE_ZYX); + /* BL_Action play modes */ + KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PLAY, BL_Action::ACT_MODE_PLAY); + KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_LOOP, BL_Action::ACT_MODE_LOOP); + KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PING_PONG, BL_Action::ACT_MODE_PING_PONG); + // Check for errors if (PyErr_Occurred()) - { + { Py_FatalError("can't initialize module bge.logic"); - } + } return m; } @@ -1922,12 +1954,12 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) gp_Rasterizer = rasty; - PyObject* m; - PyObject* d; - PyObject* item; + PyObject* m; + PyObject* d; + PyObject* item; /* Use existing module where possible - * be careful not to init any runtime vars after this */ + * be careful not to init any runtime vars after this */ m = PyImport_ImportModule( "Rasterizer" ); if(m) { Py_DECREF(m); @@ -1935,32 +1967,32 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) } else { PyErr_Clear(); - + // Create the module and add the functions m = PyModule_Create(&Rasterizer_module_def); PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m); } - // Add some symbolic constants to the module - d = PyModule_GetDict(m); - ErrorObject = PyUnicode_FromString("Rasterizer.error"); - PyDict_SetItemString(d, "error", ErrorObject); - Py_DECREF(ErrorObject); + // Add some symbolic constants to the module + d = PyModule_GetDict(m); + ErrorObject = PyUnicode_FromString("Rasterizer.error"); + PyDict_SetItemString(d, "error", ErrorObject); + Py_DECREF(ErrorObject); - /* needed for get/setMaterialType */ - KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); - KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); - KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); + /* needed for get/setMaterialType */ + KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); - // XXXX Add constants here + // XXXX Add constants here - // Check for errors - if (PyErr_Occurred()) - { - Py_FatalError("can't initialize module Rasterizer"); - } + // Check for errors + if (PyErr_Occurred()) + { + Py_FatalError("can't initialize module Rasterizer"); + } - return d; + return d; } @@ -2199,9 +2231,9 @@ PyObject* initGameKeys() // Check for errors if (PyErr_Occurred()) - { + { Py_FatalError("can't initialize module GameKeys"); - } + } return d; } diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index a683c9857aa..aecf2ab3598 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -83,7 +83,7 @@ void KX_RaySensor::Init() KX_RaySensor::~KX_RaySensor() { - /* Nothing to be done here. */ + /* Nothing to be done here. */ } @@ -279,7 +279,7 @@ bool KX_RaySensor::Evaluate() /* now pass this result to some controller */ - if (m_rayHit) + if (m_rayHit) { if (!m_bTriggered) { @@ -288,14 +288,14 @@ bool KX_RaySensor::Evaluate() m_bTriggered = true; } else - { + { // notify logicsystem that ray is STILL hitting ... result = false; - - } + + } } - else - { + else + { if (m_bTriggered) { m_bTriggered = false; @@ -306,9 +306,9 @@ bool KX_RaySensor::Evaluate() { result = false; } - - } - if (reset) + + } + if (reset) // force an event result = true; diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 076669e325a..c5f3fefd4d3 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -44,11 +44,11 @@ #include "SCA_IScene.h" KX_SCA_EndObjectActuator::KX_SCA_EndObjectActuator(SCA_IObject *gameobj, - SCA_IScene* scene): - SCA_IActuator(gameobj, KX_ACT_END_OBJECT), - m_scene(scene) + SCA_IScene* scene): + SCA_IActuator(gameobj, KX_ACT_END_OBJECT), + m_scene(scene) { - // intentionally empty + // intentionally empty } /* End of constructor */ diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 28dc660037c..a49c1bf4b4c 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1502,7 +1502,12 @@ void KX_Scene::LogicBeginFrame(double curtime) m_logicmgr->BeginFrame(curtime, 1.0/KX_KetsjiEngine::GetTicRate()); } - +void KX_Scene::UpdateAnimations(double curtime) +{ + // Update any animations + for (int i=0; i<GetObjectList()->GetCount(); ++i) + ((KX_GameObject*)GetObjectList()->GetValue(i))->UpdateActionManager(curtime); +} void KX_Scene::LogicUpdateFrame(double curtime, bool frame) { @@ -1668,6 +1673,11 @@ double KX_Scene::getSuspendedDelta() return m_suspendeddelta; } +short KX_Scene::GetAnimationFPS() +{ + return m_blenderScene->r.frs_sec; +} + #ifdef USE_BULLET #include "KX_BulletPhysicsController.h" #endif diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 367bf0b82da..da9cc12c76a 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -340,6 +340,7 @@ public: */ void LogicBeginFrame(double curtime); void LogicUpdateFrame(double curtime, bool frame); + void UpdateAnimations(double curtime); void LogicEndFrame( @@ -565,6 +566,8 @@ public: void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv); void SetGravity(const MT_Vector3& gravity); + + short GetAnimationFPS(); /** * Sets the node tree for this scene. diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 75012181ac2..6c7b515c095 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -39,17 +39,22 @@ #ifdef WITH_AUDASPACE # include "AUD_C-API.h" +# include "AUD_PingPongFactory.h" +# include "AUD_IDevice.h" +# include "AUD_I3DHandle.h" #endif #include "KX_GameObject.h" #include "KX_PyMath.h" // needed for PyObjectFrom() +#include "KX_PythonInit.h" +#include "KX_Camera.h" #include <iostream> /* ------------------------------------------------------------------------- */ /* Native functions */ /* ------------------------------------------------------------------------- */ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, - AUD_Sound* sound, + AUD_Reference<AUD_IFactory> sound, float volume, float pitch, bool is3d, @@ -62,7 +67,6 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, m_pitch = pitch; m_is3d = is3d; m_3d = settings; - m_handle = NULL; m_type = type; m_isplaying = false; } @@ -71,22 +75,20 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - if(m_handle) - AUD_stop(m_handle); + if(!m_handle.isNull()) + m_handle->stop(); } void KX_SoundActuator::play() { - if(m_handle) - AUD_stop(m_handle); + if(!m_handle.isNull()) + m_handle->stop(); - if(!m_sound) + if(m_sound.isNull()) return; // this is the sound that will be played and not deleted afterwards - AUD_Sound* sound = m_sound; - // this sound is for temporary stacked sounds, will be deleted if not NULL - AUD_Sound* sound2 = NULL; + AUD_Reference<AUD_IFactory> sound = m_sound; bool loop = false; @@ -94,7 +96,7 @@ void KX_SoundActuator::play() { case KX_SOUNDACT_LOOPBIDIRECTIONAL: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: - sound = sound2 = AUD_pingpongSound(sound); + sound = new AUD_PingPongFactory(sound); // fall through case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPSTOP: @@ -106,32 +108,28 @@ void KX_SoundActuator::play() break; } - if(m_is3d) + m_handle = AUD_getDevice()->play(sound, 0); + + AUD_Reference<AUD_I3DHandle> handle3d = AUD_Reference<AUD_I3DHandle>(m_handle); + + if(m_is3d && !handle3d.isNull()) { - // sound shall be played 3D - m_handle = AUD_play(sound, 0); - - AUD_setRelative(m_handle, false); - AUD_setVolumeMaximum(m_handle, m_3d.max_gain); - AUD_setVolumeMinimum(m_handle, m_3d.min_gain); - AUD_setDistanceReference(m_handle, m_3d.reference_distance); - AUD_setDistanceMaximum(m_handle, m_3d.max_distance); - AUD_setAttenuation(m_handle, m_3d.rolloff_factor); - AUD_setConeAngleInner(m_handle, m_3d.cone_inner_angle); - AUD_setConeAngleOuter(m_handle, m_3d.cone_outer_angle); - AUD_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain); + handle3d->setRelative(true); + handle3d->setVolumeMaximum(m_3d.max_gain); + handle3d->setVolumeMinimum(m_3d.min_gain); + handle3d->setDistanceReference(m_3d.reference_distance); + handle3d->setDistanceMaximum(m_3d.max_distance); + handle3d->setAttenuation(m_3d.rolloff_factor); + handle3d->setConeAngleInner(m_3d.cone_inner_angle); + handle3d->setConeAngleOuter(m_3d.cone_outer_angle); + handle3d->setConeVolumeOuter(m_3d.cone_outer_gain); } - else - m_handle = AUD_play(sound, 0); if(loop) - AUD_setLoop(m_handle, -1); - AUD_setSoundPitch(m_handle, m_pitch); - AUD_setSoundVolume(m_handle, m_volume); + m_handle->setLoopCount(-1); + m_handle->setPitch(m_pitch); + m_handle->setVolume(m_volume); m_isplaying = true; - - if(sound2) - AUD_unload(sound2); } CValue* KX_SoundActuator::GetReplica() @@ -144,7 +142,7 @@ CValue* KX_SoundActuator::GetReplica() void KX_SoundActuator::ProcessReplica() { SCA_IActuator::ProcessReplica(); - m_handle = 0; + m_handle = AUD_Reference<AUD_IHandle>(); } bool KX_SoundActuator::Update(double curtime, bool frame) @@ -159,11 +157,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); - if(!m_sound) + if(m_sound.isNull()) return false; // actual audio device playing state - bool isplaying = AUD_getStatus(m_handle) == AUD_STATUS_PLAYING; + bool isplaying = m_handle.isNull() ? false : (m_handle->getStatus() == AUD_STATUS_PLAYING); if (bNegativeEvent) { @@ -177,7 +175,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: { // stop immediately - AUD_stop(m_handle); + if(!m_handle.isNull()) + m_handle->stop(); + m_handle = AUD_Reference<AUD_IHandle>(); break; } case KX_SOUNDACT_PLAYEND: @@ -189,7 +189,8 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL: { // stop the looping so that the sound stops when it finished - AUD_setLoop(m_handle, 0); + if(!m_handle.isNull()) + m_handle->setLoopCount(0); break; } default: @@ -215,21 +216,35 @@ bool KX_SoundActuator::Update(double curtime, bool frame) play(); } // verify that the sound is still playing - isplaying = AUD_getStatus(m_handle) == AUD_STATUS_PLAYING ? true : false; + isplaying = m_handle.isNull() ? false : (m_handle->getStatus() == AUD_STATUS_PLAYING); if (isplaying) { - if(m_is3d) + AUD_Reference<AUD_I3DHandle> handle3d = AUD_Reference<AUD_I3DHandle>(m_handle); + + if(m_is3d && !handle3d.isNull()) { - KX_GameObject* obj = (KX_GameObject*)this->GetParent(); - float f[4]; - - obj->NodeGetWorldPosition().getValue(f); - AUD_setSourceLocation(m_handle, f); - obj->GetLinearVelocity().getValue(f); - AUD_setSourceVelocity(m_handle, f); - obj->NodeGetWorldOrientation().getRotation().getValue(f); - AUD_setSourceOrientation(m_handle, f); + KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera(); + if (cam) + { + KX_GameObject* obj = (KX_GameObject*)this->GetParent(); + MT_Point3 p; + MT_Matrix3x3 Mo; + AUD_Vector3 v; + float q[4]; + + Mo = cam->NodeGetWorldOrientation().inverse(); + p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition()); + p = Mo * p; + p.getValue(v.get()); + handle3d->setSourceLocation(v); + p = (obj->GetLinearVelocity() - cam->GetLinearVelocity()); + p = Mo * p; + p.getValue(v.get()); + handle3d->setSourceVelocity(v); + (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(q); + handle3d->setSourceOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2])); + } } result = true; } @@ -241,7 +256,6 @@ bool KX_SoundActuator::Update(double curtime, bool frame) return result; } - #ifdef WITH_PYTHON /* ------------------------------------------------------------------------- */ @@ -290,6 +304,7 @@ PyAttributeDef KX_SoundActuator::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_inner", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), KX_PYATTRIBUTE_RW_FUNCTION("cone_volume_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("sound", KX_SoundActuator, pyattr_get_sound, pyattr_set_sound), KX_PYATTRIBUTE_RW_FUNCTION("time", KX_SoundActuator, pyattr_get_audposition, pyattr_set_audposition), KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain), @@ -303,15 +318,18 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, "startSound()\n" "\tStarts the sound.\n") { - switch(AUD_getStatus(m_handle)) + if(!m_handle.isNull()) { - case AUD_STATUS_PLAYING: - break; - case AUD_STATUS_PAUSED: - AUD_resume(m_handle); - break; - default: - play(); + switch(m_handle->getStatus()) + { + case AUD_STATUS_PLAYING: + break; + case AUD_STATUS_PAUSED: + m_handle->resume(); + break; + default: + play(); + } } Py_RETURN_NONE; } @@ -320,7 +338,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound, "pauseSound()\n" "\tPauses the sound.\n") { - AUD_pause(m_handle); + if(!m_handle.isNull()) + m_handle->pause(); Py_RETURN_NONE; } @@ -328,7 +347,9 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, "stopSound()\n" "\tStops the sound.\n") { - AUD_stop(m_handle); + if(!m_handle.isNull()) + m_handle->stop(); + m_handle = AUD_Reference<AUD_IHandle>(); Py_RETURN_NONE; } @@ -376,8 +397,8 @@ PyObject* KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); float position = 0.0; - if(actuator->m_handle) - position = AUD_getPosition(actuator->m_handle); + if(!actuator->m_handle.isNull()) + position = actuator->m_handle->getPosition(); PyObject* result = PyFloat_FromDouble(position); @@ -404,6 +425,15 @@ PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI return result; } +PyObject* KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + if(!actuator->m_sound.isNull()) + return AUD_getPythonFactory(&actuator->m_sound); + else + Py_RETURN_NONE; +} + int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); @@ -413,49 +443,50 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &prop_value)) return PY_SET_ATTR_FAIL; + AUD_Reference<AUD_I3DHandle> handle3d = AUD_Reference<AUD_I3DHandle>(actuator->m_handle); // if sound is working and 3D, set the new setting if(!actuator->m_is3d) return PY_SET_ATTR_FAIL; if(!strcmp(prop, "volume_maximum")) { actuator->m_3d.max_gain = prop_value; - if(actuator->m_handle) - AUD_setVolumeMaximum(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setVolumeMaximum(prop_value); } else if (!strcmp(prop, "volume_minimum")) { actuator->m_3d.min_gain = prop_value; - if(actuator->m_handle) - AUD_setVolumeMinimum(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setVolumeMinimum(prop_value); } else if (!strcmp(prop, "distance_reference")) { actuator->m_3d.reference_distance = prop_value; - if(actuator->m_handle) - AUD_setDistanceReference(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setDistanceReference(prop_value); } else if (!strcmp(prop, "distance_maximum")) { actuator->m_3d.max_distance = prop_value; - if(actuator->m_handle) - AUD_setDistanceMaximum(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setDistanceMaximum(prop_value); } else if (!strcmp(prop, "attenuation")) { actuator->m_3d.rolloff_factor = prop_value; - if(actuator->m_handle) - AUD_setAttenuation(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setAttenuation(prop_value); } else if (!!strcmp(prop, "cone_angle_inner")) { actuator->m_3d.cone_inner_angle = prop_value; - if(actuator->m_handle) - AUD_setConeAngleInner(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setConeAngleInner(prop_value); } else if (!strcmp(prop, "cone_angle_outer")) { actuator->m_3d.cone_outer_angle = prop_value; - if(actuator->m_handle) - AUD_setConeAngleOuter(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setConeAngleOuter(prop_value); } else if (!strcmp(prop, "cone_volume_outer")) { actuator->m_3d.cone_outer_gain = prop_value; - if(actuator->m_handle) - AUD_setConeVolumeOuter(actuator->m_handle, prop_value); + if(!handle3d.isNull()) + handle3d->setConeVolumeOuter(prop_value); } else { return PY_SET_ATTR_FAIL; @@ -472,8 +503,8 @@ int KX_SoundActuator::pyattr_set_audposition(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &position)) return PY_SET_ATTR_FAIL; - if(actuator->m_handle) - AUD_seek(actuator->m_handle, position); + if(!actuator->m_handle.isNull()) + actuator->m_handle->seek(position); return PY_SET_ATTR_SUCCESS; } @@ -485,8 +516,8 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE return PY_SET_ATTR_FAIL; actuator->m_volume = gain; - if(actuator->m_handle) - AUD_setSoundVolume(actuator->m_handle, gain); + if(!actuator->m_handle.isNull()) + actuator->m_handle->setVolume(gain); return PY_SET_ATTR_SUCCESS; } @@ -499,10 +530,28 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D return PY_SET_ATTR_FAIL; actuator->m_pitch = pitch; - if(actuator->m_handle) - AUD_setSoundPitch(actuator->m_handle, pitch); + if(!actuator->m_handle.isNull()) + actuator->m_handle->setPitch(pitch); return PY_SET_ATTR_SUCCESS; } +int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + PyObject* sound = NULL; + KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); + if (!PyArg_Parse(value, "O", &sound)) + return PY_SET_ATTR_FAIL; + + AUD_Reference<AUD_IFactory>* snd = reinterpret_cast<AUD_Reference<AUD_IFactory>*>(AUD_getPythonSound(sound)); + if(snd) + { + actuator->m_sound = *snd; + delete snd; + return PY_SET_ATTR_SUCCESS; + } + + return PY_SET_ATTR_FAIL; +} + #endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index eb6717f78f0..b1161e0cad2 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -38,6 +38,9 @@ #ifdef WITH_AUDASPACE # include "AUD_C-API.h" +# include "AUD_Reference.h" +# include "AUD_IFactory.h" +# include "AUD_IHandle.h" #endif #include "BKE_sound.h" @@ -56,14 +59,14 @@ typedef struct KX_3DSoundSettings class KX_SoundActuator : public SCA_IActuator { - Py_Header; - bool m_isplaying; - AUD_Sound* m_sound; + Py_Header; + bool m_isplaying; + AUD_Reference<AUD_IFactory> m_sound; float m_volume; float m_pitch; bool m_is3d; KX_3DSoundSettings m_3d; - AUD_Channel* m_handle; + AUD_Reference<AUD_IHandle> m_handle; void play(); @@ -84,7 +87,7 @@ public: KX_SOUNDACT_TYPE m_type; KX_SoundActuator(SCA_IObject* gameobj, - AUD_Sound* sound, + AUD_Reference<AUD_IFactory> sound, float volume, float pitch, bool is3d, @@ -113,12 +116,14 @@ public: static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); #endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index edcba969811..f13f152c5d5 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -54,16 +54,16 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, - SCA_IObject *ob, - int time, - bool allow3D, - int trackflag, - int upflag) - : SCA_IActuator(gameobj, KX_ACT_TRACKTO) + SCA_IObject *ob, + int time, + bool allow3D, + int trackflag, + int upflag) + : SCA_IActuator(gameobj, KX_ACT_TRACKTO) { - m_time = time; - m_allow3D = allow3D; - m_object = ob; + m_time = time; + m_allow3D = allow3D; + m_object = ob; m_trackflag = trackflag; m_upflag = upflag; m_parentobj = 0; diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 62caa602c23..c5509dd7de8 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -11,11 +11,11 @@ incs += ' #source/blender/python/mathutils' # Only for mathutils, be very carefu incs += ' #intern/string #intern/guardedalloc #intern/container' incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer' -incs += ' #intern/audaspace/intern #source/gameengine/Converter' +incs += ' #intern/audaspace/intern #intern/audaspace/FX #source/gameengine/Converter' incs += ' #source/gameengine/BlenderRoutines #source/blender/imbuf #intern/moto/include' incs += ' #source/gameengine/Ketsji #source/gameengine/Ketsji/KXNetwork #source/blender/blenlib #source/blender/blenfont' incs += ' #source/blender/blenkernel #source/blender #source/blender/editors/include' -incs += ' #source/blender/makesdna #source/blender/python #source/gameengine/Rasterizer' +incs += ' #source/blender/makesdna #source/blender/makesrna #source/blender/python #source/gameengine/Rasterizer' incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions #source/gameengine/Network' incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Dummy' @@ -35,7 +35,7 @@ if env['WITH_BF_PYTHON']: if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') - + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc', 'win32-mingw'): if env['BF_DEBUG']: defs.append('_DEBUG') # for Python diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 3f0c4cb95a1..526176481ed 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -1200,7 +1200,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac // Bullet returns the normal from "outside". // If the user requests the real normal, compute it now - if (filterCallback.m_faceNormal) + if (filterCallback.m_faceNormal) { if (shape->isSoftBody()) { diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 47f1dcb412a..5a1b52489b4 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -246,6 +246,11 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const return dolights; } +bool RAS_IPolyMaterial::CastsShadows() const +{ + return (m_flag & RAS_CASTSHADOW) != 0; +} + bool RAS_IPolyMaterial::UsesObjectColor() const { return !(m_flag & RAS_BLENDERGLSL); diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index b0e7daf81d7..2a5c6a179b6 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -62,7 +62,8 @@ enum MaterialProps RAS_AUTOGEN =128, RAS_NORMAL =256, RAS_DEFMULTI =512, - RAS_BLENDERGLSL =1024 + RAS_BLENDERGLSL =1024, + RAS_CASTSHADOW =2048 }; /** @@ -169,6 +170,7 @@ public: virtual void GetMaterialRGBAColor(unsigned char *rgba) const; virtual bool UsesLighting(RAS_IRasterizer *rasty) const; virtual bool UsesObjectColor() const; + virtual bool CastsShadows() const; virtual void Replace_IScene(SCA_IScene *val) {}; /* overridden by KX_BlenderMaterial */ diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 305e2bca756..c46ebf742a0 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -417,6 +417,9 @@ public: virtual void SetBlendingMode(int blendmode)=0; virtual void SetFrontFace(bool ccw)=0; + + virtual void SetAnisotropicFiltering(short level)=0; + virtual short GetAnisotropicFiltering()=0; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 7647f7d3f27..85284096bb9 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -586,6 +586,9 @@ bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_I RAS_IRenderTools *rendertools) { bool uselights; + + if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && !m_material->CastsShadows()) + return false; if(!rasty->SetMaterial(*m_material)) return false; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index ccff9559e32..47c0dee7ca8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -100,12 +100,16 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) hinterlace_mask[i] = (i&1)*0xFFFFFFFF; } hinterlace_mask[32] = 0; + + m_prevafvalue = GPU_get_anisotropic(); } RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { + // Restore the previous AF value + GPU_set_anisotropic(m_prevafvalue); } bool RAS_OpenGLRasterizer::Init() @@ -1205,3 +1209,12 @@ void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) m_last_frontface = ccw; } +void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level) +{ + GPU_set_anisotropic((float)level); +} + +short RAS_OpenGLRasterizer::GetAnisotropicFiltering() +{ + return (short)GPU_get_anisotropic(); +} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 54fab906049..61568df91eb 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -94,6 +94,8 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer bool m_setfocallength; int m_noOfScanlines; + short m_prevafvalue; + //motion blur int m_motionblur; float m_motionblurvalue; @@ -294,6 +296,9 @@ public: virtual void SetBlendingMode(int blendmode); virtual void SetFrontFace(bool ccw); + virtual void SetAnisotropicFiltering(short level); + virtual short GetAnisotropicFiltering(); + #ifdef WITH_CXX_GUARDEDALLOC public: diff --git a/source/gameengine/SceneGraph/SG_BBox.cpp b/source/gameengine/SceneGraph/SG_BBox.cpp index b5618ebbf03..01107557481 100644 --- a/source/gameengine/SceneGraph/SG_BBox.cpp +++ b/source/gameengine/SceneGraph/SG_BBox.cpp @@ -142,8 +142,8 @@ SG_BBox SG_BBox::transform(const MT_Transform &world) const bool SG_BBox::inside(const MT_Point3 &point) const { return point[0] >= m_min[0] && point[0] <= m_max[0] && - point[1] >= m_min[1] && point[1] <= m_max[1] && - point[2] >= m_min[2] && point[2] <= m_max[2]; + point[1] >= m_min[1] && point[1] <= m_max[1] && + point[2] >= m_min[2] && point[2] <= m_max[2]; } bool SG_BBox::inside(const SG_BBox& other) const diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp index 3064e6662b9..b22d210984d 100644 --- a/source/gameengine/SceneGraph/SG_IObject.cpp +++ b/source/gameengine/SceneGraph/SG_IObject.cpp @@ -34,6 +34,8 @@ #include "SG_IObject.h" #include "SG_Controller.h" +#include <algorithm> + SG_Stage gSG_Stage = SG_STAGE_UNKNOWN; SG_IObject:: @@ -71,6 +73,16 @@ AddSGController( void SG_IObject:: +RemoveSGController( + SG_Controller* cont +) { + SGControllerList::iterator contit; + + m_SGcontrollers.erase(std::remove(m_SGcontrollers.begin(), m_SGcontrollers.end(), cont)); +} + + void +SG_IObject:: RemoveAllControllers( ) { m_SGcontrollers.clear(); diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 26e317bdcd9..c42935bc487 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -49,6 +49,7 @@ enum SG_Stage SG_STAGE_CONTROLLER_UPDATE, SG_STAGE_ACTUATOR, SG_STAGE_ACTUATOR_UPDATE, + SG_STAGE_ANIMATION_UPDATE, SG_STAGE_PHYSICS2, SG_STAGE_PHYSICS2_UPDATE, SG_STAGE_SCENE, @@ -180,6 +181,16 @@ public: SG_Controller* cont ); + /** + * Remove a pointer to a controller from this node. + * This does not delete the controller itself! Be careful to + * avoid memory leaks. + */ + void + RemoveSGController( + SG_Controller* cont + ); + /** * Clear the array of pointers to controllers associated with * this node. This does not delete the controllers themselves! diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp index ca778d164c8..94b8584051e 100644 --- a/source/gameengine/SceneGraph/SG_Spatial.cpp +++ b/source/gameengine/SceneGraph/SG_Spatial.cpp @@ -109,18 +109,17 @@ SetParentRelation( */ - bool + bool SG_Spatial:: UpdateSpatialData( - const SG_Spatial *parent, - double time, - bool& parentUpdated + const SG_Spatial *parent, + double time, + bool& parentUpdated ){ - - bool bComputesWorldTransform = false; + bool bComputesWorldTransform = false; // update spatial controllers - + SGControllerList::iterator cit = GetSGControllerList().begin(); SGControllerList::const_iterator c_end = GetSGControllerList().end(); @@ -131,7 +130,7 @@ UpdateSpatialData( } // If none of the objects updated our values then we ask the - // parent_relation object owned by this class to update + // parent_relation object owned by this class to update // our world coordinates. if (!bComputesWorldTransform) diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 8c8258585a5..30a8af4b125 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -105,7 +105,7 @@ Exception::Exception (ExceptionID & expID, RESULT rslt, const char * fil, int li : m_expID (&expID), m_hRslt (rslt) { // set file and line - if (strlen(fil) > 0 || lin > 0) + if (fil[0] != '\0' || lin > 0) setFileLine (fil, lin); } @@ -201,20 +201,20 @@ void Exception::copy (const Exception & xpt) void registerAllExceptions(void) { - errGenerDesc.registerDesc(); - errNFoundDesc.registerDesc(); - MaterialNotAvailDesc.registerDesc(); - ImageSizesNotMatchDesc.registerDesc(); - ImageHasExportsDesc.registerDesc(); + errGenerDesc.registerDesc(); + errNFoundDesc.registerDesc(); + MaterialNotAvailDesc.registerDesc(); + ImageSizesNotMatchDesc.registerDesc(); + ImageHasExportsDesc.registerDesc(); InvalidColorChannelDesc.registerDesc(); - SceneInvalidDesc.registerDesc(); - CameraInvalidDesc.registerDesc(); - ObserverInvalidDesc.registerDesc(); - MirrorInvalidDesc.registerDesc(); - MirrorSizeInvalidDesc.registerDesc(); - MirrorNormalInvalidDesc.registerDesc(); - MirrorHorizontalDesc.registerDesc(); - MirrorTooSmallDesc.registerDesc(); - SourceVideoEmptyDesc.registerDesc(); - SourceVideoCreationDesc.registerDesc(); + SceneInvalidDesc.registerDesc(); + CameraInvalidDesc.registerDesc(); + ObserverInvalidDesc.registerDesc(); + MirrorInvalidDesc.registerDesc(); + MirrorSizeInvalidDesc.registerDesc(); + MirrorNormalInvalidDesc.registerDesc(); + MirrorHorizontalDesc.registerDesc(); + MirrorTooSmallDesc.registerDesc(); + SourceVideoEmptyDesc.registerDesc(); + SourceVideoCreationDesc.registerDesc(); } diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h index 2478727a6be..d0536ed2801 100644 --- a/source/gameengine/VideoTexture/FilterColor.h +++ b/source/gameengine/VideoTexture/FilterColor.h @@ -141,7 +141,7 @@ protected: /// calculate one color component unsigned int calcColor (unsigned int val, short idx) { - unsigned int col = VT_C(val,idx);; + unsigned int col = VT_C(val,idx); if (col <= levels[idx][0]) col = 0; else if (col >= levels[idx][1]) col = 0xFF; else col = (((col - levels[idx][0]) << 8) / levels[idx][2]) & 0xFF; diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index a70c56a070c..86de214e2d3 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -645,7 +645,7 @@ PyObject * Image_valid(PyImage * self, void * closure) int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) { unsigned int * image; - int ret; + int ret; try { @@ -667,25 +667,25 @@ int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) //return -1; goto error; } - if (view == NULL) + if (view == NULL) { - self->m_image->m_exports++; - return 0; - } - ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags); - if (ret >= 0) - self->m_image->m_exports++; - return ret; + self->m_image->m_exports++; + return 0; + } + ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags); + if (ret >= 0) + self->m_image->m_exports++; + return ret; error: // Return a empty buffer to avoid a crash in Python 3.1 // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is // updated, you can simply return -1 and set the error static char* buf = (char *)""; - ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags); - if (ret >= 0) - self->m_image->m_exports++; - return ret; + ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags); + if (ret >= 0) + self->m_image->m_exports++; + return ret; } diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index 7a8226aab03..aeef5d1694f 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -135,7 +135,7 @@ PyObject * setWeight (PyImage * self, PyObject * args) if (!getImageMix(self)->setWeight(id, weight)) { // if not set, report error - PyErr_SetString(PyExc_RuntimeError, "Invalid id of source");; + PyErr_SetString(PyExc_RuntimeError, "Invalid id of source"); return NULL; } // return none diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 6038416ba68..24833ace08f 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -65,29 +65,29 @@ ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : m_owncamera(false), m_observer(NULL), m_mirror(NULL), - m_clip(100.f) + m_clip(100.f) { // initialize background color setBackground(0, 0, 255, 255); - // retrieve rendering objects - m_engine = KX_GetActiveEngine(); - m_rasterizer = m_engine->GetRasterizer(); - m_canvas = m_engine->GetCanvas(); - m_rendertools = m_engine->GetRenderTools(); + // retrieve rendering objects + m_engine = KX_GetActiveEngine(); + m_rasterizer = m_engine->GetRasterizer(); + m_canvas = m_engine->GetCanvas(); + m_rendertools = m_engine->GetRenderTools(); } // destructor ImageRender::~ImageRender (void) { - if (m_owncamera) - m_camera->Release(); + if (m_owncamera) + m_camera->Release(); } // set background color void ImageRender::setBackground (int red, int green, int blue, int alpha) { - m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; + m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f; m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f; m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; @@ -97,157 +97,157 @@ void ImageRender::setBackground (int red, int green, int blue, int alpha) // capture image from viewport void ImageRender::calcImage (unsigned int texId, double ts) { - if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture - m_camera->GetViewport() || // camera must be inactive - m_camera == m_scene->GetActiveCamera()) - { - // no need to compute texture in non texture rendering - m_avail = false; - return; - } - // render the scene from the camera - Render(); + if (m_rasterizer->GetDrawingMode() != RAS_IRasterizer::KX_TEXTURED || // no need for texture + m_camera->GetViewport() || // camera must be inactive + m_camera == m_scene->GetActiveCamera()) + { + // no need to compute texture in non texture rendering + m_avail = false; + return; + } + // render the scene from the camera + Render(); // get image from viewport ImageViewport::calcImage(texId, ts); - // restore OpenGL state - m_canvas->EndFrame(); + // restore OpenGL state + m_canvas->EndFrame(); } void ImageRender::Render() { RAS_FrameFrustum frustrum; - if (!m_render) - return; - - if (m_mirror) - { - // mirror mode, compute camera frustrum, position and orientation - // convert mirror position and normal in world space - const MT_Matrix3x3 & mirrorObjWorldOri = m_mirror->GetSGNode()->GetWorldOrientation(); - const MT_Point3 & mirrorObjWorldPos = m_mirror->GetSGNode()->GetWorldPosition(); - const MT_Vector3 & mirrorObjWorldScale = m_mirror->GetSGNode()->GetWorldScaling(); - MT_Point3 mirrorWorldPos = - mirrorObjWorldPos + mirrorObjWorldScale * (mirrorObjWorldOri * m_mirrorPos); - MT_Vector3 mirrorWorldZ = mirrorObjWorldOri * m_mirrorZ; - // get observer world position - const MT_Point3 & observerWorldPos = m_observer->GetSGNode()->GetWorldPosition(); - // get plane D term = mirrorPos . normal - MT_Scalar mirrorPlaneDTerm = mirrorWorldPos.dot(mirrorWorldZ); - // compute distance of observer to mirror = D - observerPos . normal - MT_Scalar observerDistance = mirrorPlaneDTerm - observerWorldPos.dot(mirrorWorldZ); - // if distance < 0.01 => observer is on wrong side of mirror, don't render - if (observerDistance < 0.01f) - return; - // set camera world position = observerPos + normal * 2 * distance - MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ; - m_camera->GetSGNode()->SetLocalPosition(cameraWorldPos); - // set camera orientation: z=normal, y=mirror_up in world space, x= y x z - MT_Vector3 mirrorWorldY = mirrorObjWorldOri * m_mirrorY; - MT_Vector3 mirrorWorldX = mirrorObjWorldOri * m_mirrorX; - MT_Matrix3x3 cameraWorldOri( - mirrorWorldX[0], mirrorWorldY[0], mirrorWorldZ[0], - mirrorWorldX[1], mirrorWorldY[1], mirrorWorldZ[1], - mirrorWorldX[2], mirrorWorldY[2], mirrorWorldZ[2]); - m_camera->GetSGNode()->SetLocalOrientation(cameraWorldOri); - m_camera->GetSGNode()->UpdateWorldData(0.0); - // compute camera frustrum: - // get position of mirror relative to camera: offset = mirrorPos-cameraPos - MT_Vector3 mirrorOffset = mirrorWorldPos - cameraWorldPos; - // convert to camera orientation - mirrorOffset = mirrorOffset * cameraWorldOri; - // scale mirror size to world scale: - // get closest local axis for mirror Y and X axis and scale height and width by local axis scale - MT_Scalar x, y; - x = fabs(m_mirrorY[0]); - y = fabs(m_mirrorY[1]); - float height = (x > y) ? - ((x > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): - ((y > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); - x = fabs(m_mirrorX[0]); - y = fabs(m_mirrorX[1]); - float width = (x > y) ? - ((x > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): - ((y > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); - width *= m_mirrorHalfWidth; - height *= m_mirrorHalfHeight; - // left = offsetx-width - // right = offsetx+width - // top = offsety+height - // bottom = offsety-height - // near = -offsetz - // far = near+100 - frustrum.x1 = mirrorOffset[0]-width; - frustrum.x2 = mirrorOffset[0]+width; - frustrum.y1 = mirrorOffset[1]-height; - frustrum.y2 = mirrorOffset[1]+height; - frustrum.camnear = -mirrorOffset[2]; - frustrum.camfar = -mirrorOffset[2]+m_clip; - } + if (!m_render) + return; + + if (m_mirror) + { + // mirror mode, compute camera frustrum, position and orientation + // convert mirror position and normal in world space + const MT_Matrix3x3 & mirrorObjWorldOri = m_mirror->GetSGNode()->GetWorldOrientation(); + const MT_Point3 & mirrorObjWorldPos = m_mirror->GetSGNode()->GetWorldPosition(); + const MT_Vector3 & mirrorObjWorldScale = m_mirror->GetSGNode()->GetWorldScaling(); + MT_Point3 mirrorWorldPos = + mirrorObjWorldPos + mirrorObjWorldScale * (mirrorObjWorldOri * m_mirrorPos); + MT_Vector3 mirrorWorldZ = mirrorObjWorldOri * m_mirrorZ; + // get observer world position + const MT_Point3 & observerWorldPos = m_observer->GetSGNode()->GetWorldPosition(); + // get plane D term = mirrorPos . normal + MT_Scalar mirrorPlaneDTerm = mirrorWorldPos.dot(mirrorWorldZ); + // compute distance of observer to mirror = D - observerPos . normal + MT_Scalar observerDistance = mirrorPlaneDTerm - observerWorldPos.dot(mirrorWorldZ); + // if distance < 0.01 => observer is on wrong side of mirror, don't render + if (observerDistance < 0.01f) + return; + // set camera world position = observerPos + normal * 2 * distance + MT_Point3 cameraWorldPos = observerWorldPos + (MT_Scalar(2.0)*observerDistance)*mirrorWorldZ; + m_camera->GetSGNode()->SetLocalPosition(cameraWorldPos); + // set camera orientation: z=normal, y=mirror_up in world space, x= y x z + MT_Vector3 mirrorWorldY = mirrorObjWorldOri * m_mirrorY; + MT_Vector3 mirrorWorldX = mirrorObjWorldOri * m_mirrorX; + MT_Matrix3x3 cameraWorldOri( + mirrorWorldX[0], mirrorWorldY[0], mirrorWorldZ[0], + mirrorWorldX[1], mirrorWorldY[1], mirrorWorldZ[1], + mirrorWorldX[2], mirrorWorldY[2], mirrorWorldZ[2]); + m_camera->GetSGNode()->SetLocalOrientation(cameraWorldOri); + m_camera->GetSGNode()->UpdateWorldData(0.0); + // compute camera frustrum: + // get position of mirror relative to camera: offset = mirrorPos-cameraPos + MT_Vector3 mirrorOffset = mirrorWorldPos - cameraWorldPos; + // convert to camera orientation + mirrorOffset = mirrorOffset * cameraWorldOri; + // scale mirror size to world scale: + // get closest local axis for mirror Y and X axis and scale height and width by local axis scale + MT_Scalar x, y; + x = fabs(m_mirrorY[0]); + y = fabs(m_mirrorY[1]); + float height = (x > y) ? + ((x > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorY[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + x = fabs(m_mirrorX[0]); + y = fabs(m_mirrorX[1]); + float width = (x > y) ? + ((x > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[0] : mirrorObjWorldScale[2]): + ((y > fabs(m_mirrorX[2])) ? mirrorObjWorldScale[1] : mirrorObjWorldScale[2]); + width *= m_mirrorHalfWidth; + height *= m_mirrorHalfHeight; + // left = offsetx-width + // right = offsetx+width + // top = offsety+height + // bottom = offsety-height + // near = -offsetz + // far = near+100 + frustrum.x1 = mirrorOffset[0]-width; + frustrum.x2 = mirrorOffset[0]+width; + frustrum.y1 = mirrorOffset[1]-height; + frustrum.y2 = mirrorOffset[1]+height; + frustrum.camnear = -mirrorOffset[2]; + frustrum.camfar = -mirrorOffset[2]+m_clip; + } // Store settings to be restored later - const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); + const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); RAS_Rect area = m_canvas->GetWindowArea(); - // The screen area that ImageViewport will copy is also the rendering zone - m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0]-1, m_position[1]+m_capSize[1]-1); - m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); - m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); - m_rasterizer->BeginFrame(RAS_IRasterizer::KX_TEXTURED,m_engine->GetClockTime()); - m_rendertools->BeginFrame(m_rasterizer); - m_engine->SetWorldSettings(m_scene->GetWorldInfo()); - m_rendertools->SetAuxilaryClientInfo(m_scene); - m_rasterizer->DisplayFog(); - // matrix calculation, don't apply any of the stereo mode - m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO); - if (m_mirror) - { - // frustrum was computed above - // get frustrum matrix and set projection matrix + // The screen area that ImageViewport will copy is also the rendering zone + m_canvas->SetViewPort(m_position[0], m_position[1], m_position[0]+m_capSize[0]-1, m_position[1]+m_capSize[1]-1); + m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); + m_rasterizer->BeginFrame(RAS_IRasterizer::KX_TEXTURED,m_engine->GetClockTime()); + m_rendertools->BeginFrame(m_rasterizer); + m_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_rendertools->SetAuxilaryClientInfo(m_scene); + m_rasterizer->DisplayFog(); + // matrix calculation, don't apply any of the stereo mode + m_rasterizer->SetStereoMode(RAS_IRasterizer::RAS_STEREO_NOSTEREO); + if (m_mirror) + { + // frustrum was computed above + // get frustrum matrix and set projection matrix MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); m_camera->SetProjectionMatrix(projmat); - } else if (m_camera->hasValidProjectionMatrix()) + } else if (m_camera->hasValidProjectionMatrix()) { m_rasterizer->SetProjectionMatrix(m_camera->GetProjectionMatrix()); - } else - { + } else + { float lens = m_camera->GetLens(); bool orthographic = !m_camera->GetCameraData()->m_perspective; float nearfrust = m_camera->GetCameraNear(); float farfrust = m_camera->GetCameraFar(); - float aspect_ratio = 1.0f; - Scene *blenderScene = m_scene->GetBlenderScene(); + float aspect_ratio = 1.0f; + Scene *blenderScene = m_scene->GetBlenderScene(); MT_Matrix4x4 projmat; // compute the aspect ratio from frame blender scene settings so that render to texture - // works the same in Blender and in Blender player - if (blenderScene->r.ysch != 0) - aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); + // works the same in Blender and in Blender player + if (blenderScene->r.ysch != 0) + aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); if (orthographic) { RAS_FramingManager::ComputeDefaultOrtho( - nearfrust, - farfrust, - m_camera->GetScale(), - aspect_ratio, - frustrum - ); + nearfrust, + farfrust, + m_camera->GetScale(), + aspect_ratio, + frustrum + ); projmat = m_rasterizer->GetOrthoMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); - } else + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } else { RAS_FramingManager::ComputeDefaultFrustum( - nearfrust, - farfrust, - lens, - aspect_ratio, - frustrum); + nearfrust, + farfrust, + lens, + aspect_ratio, + frustrum); projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); } m_camera->SetProjectionMatrix(projmat); } @@ -257,8 +257,8 @@ void ImageRender::Render() m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldOrientation(), m_camera->NodeGetWorldPosition(), m_camera->GetCameraData()->m_perspective); m_camera->SetModelviewMatrix(viewmat); - // restore the stereo mode now that the matrix is computed - m_rasterizer->SetStereoMode(stereomode); + // restore the stereo mode now that the matrix is computed + m_rasterizer->SetStereoMode(stereomode); m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); @@ -433,24 +433,24 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds PyObject * scene; // reference object for mirror PyObject * observer; - // object holding the mirror - PyObject * mirror; - // material of the mirror - short materialID = 0; + // object holding the mirror + PyObject * mirror; + // material of the mirror + short materialID = 0; // parameter keywords static const char *kwlist[] = {"scene", "observer", "mirror", "material", NULL}; // get parameters if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|h", - const_cast<char**>(kwlist), &scene, &observer, &mirror, &materialID)) + const_cast<char**>(kwlist), &scene, &observer, &mirror, &materialID)) return -1; try { // get scene pointer KX_Scene * scenePtr (NULL); - if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) - scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene); + if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) + scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene); else - THRWEXCP(SceneInvalid, S_OK); + THRWEXCP(SceneInvalid, S_OK); if(scenePtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(SceneInvalid, S_OK); @@ -458,11 +458,11 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get observer pointer KX_GameObject * observerPtr (NULL); if (observer != NULL && PyObject_TypeCheck(observer, &KX_GameObject::Type)) - observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer); - else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) - observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer); + observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer); + else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) + observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer); else - THRWEXCP(ObserverInvalid, S_OK); + THRWEXCP(ObserverInvalid, S_OK); if(observerPtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(ObserverInvalid, S_OK); @@ -470,27 +470,27 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get mirror pointer KX_GameObject * mirrorPtr (NULL); if (mirror != NULL && PyObject_TypeCheck(mirror, &KX_GameObject::Type)) - mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror); + mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror); else - THRWEXCP(MirrorInvalid, S_OK); + THRWEXCP(MirrorInvalid, S_OK); if(mirrorPtr==NULL) /* incase the python proxy reference is invalid */ THRWEXCP(MirrorInvalid, S_OK); - // locate the material in the mirror + // locate the material in the mirror RAS_IPolyMaterial * material = getMaterial(mirror, materialID); if (material == NULL) - THRWEXCP(MaterialNotAvail, S_OK); + THRWEXCP(MaterialNotAvail, S_OK); // get pointer to image structure PyImage * self = reinterpret_cast<PyImage*>(pySelf); // create source object - if (self->m_image != NULL) - { - delete self->m_image; - self->m_image = NULL; - } + if (self->m_image != NULL) + { + delete self->m_image; + self->m_image = NULL; + } self->m_image = new ImageRender(scenePtr, observerPtr, mirrorPtr, material); } catch (Exception & exp) @@ -530,7 +530,7 @@ static PyGetSetDef imageMirrorGetSets[] = {(char*)"clip", (getter)getClip, (setter)setClip, (char*)"clipping distance", NULL}, // attribute from ImageRender {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, - // attribute from ImageViewport + // attribute from ImageViewport {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, @@ -552,164 +552,164 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj m_scene(scene), m_observer(observer), m_mirror(mirror), - m_clip(100.f) + m_clip(100.f) { - // this constructor is used for automatic planar mirror - // create a camera, take all data by default, in any case we will recompute the frustrum on each frame + // this constructor is used for automatic planar mirror + // create a camera, take all data by default, in any case we will recompute the frustrum on each frame RAS_CameraData camdata; - vector<RAS_TexVert*> mirrorVerts; - vector<RAS_TexVert*>::iterator it; - float mirrorArea = 0.f; - float mirrorNormal[3] = {0.f, 0.f, 0.f}; - float mirrorUp[3]; - float dist, vec[3], axis[3]; - float zaxis[3] = {0.f, 0.f, 1.f}; - float yaxis[3] = {0.f, 1.f, 0.f}; - float mirrorMat[3][3]; - float left, right, top, bottom, back; + vector<RAS_TexVert*> mirrorVerts; + vector<RAS_TexVert*>::iterator it; + float mirrorArea = 0.f; + float mirrorNormal[3] = {0.f, 0.f, 0.f}; + float mirrorUp[3]; + float dist, vec[3], axis[3]; + float zaxis[3] = {0.f, 0.f, 1.f}; + float yaxis[3] = {0.f, 1.f, 0.f}; + float mirrorMat[3][3]; + float left, right, top, bottom, back; // make sure this camera will delete its node m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata, true, true); m_camera->SetName("__mirror__cam__"); - // don't add the camera to the scene object list, it doesn't need to be accessible - m_owncamera = true; - // retrieve rendering objects - m_engine = KX_GetActiveEngine(); - m_rasterizer = m_engine->GetRasterizer(); - m_canvas = m_engine->GetCanvas(); - m_rendertools = m_engine->GetRenderTools(); - // locate the vertex assigned to mat and do following calculation in mesh coordinates - for (int meshIndex = 0; meshIndex < mirror->GetMeshCount(); meshIndex++) - { - RAS_MeshObject* mesh = mirror->GetMesh(meshIndex); - int numPolygons = mesh->NumPolygons(); - for (int polygonIndex=0; polygonIndex < numPolygons; polygonIndex++) - { - RAS_Polygon* polygon = mesh->GetPolygon(polygonIndex); - if (polygon->GetMaterial()->GetPolyMaterial() == mat) - { - RAS_TexVert *v1, *v2, *v3, *v4; - float normal[3]; - float area; - // this polygon is part of the mirror, - v1 = polygon->GetVertex(0); - v2 = polygon->GetVertex(1); - v3 = polygon->GetVertex(2); - mirrorVerts.push_back(v1); - mirrorVerts.push_back(v2); - mirrorVerts.push_back(v3); - if (polygon->VertexCount() == 4) - { - v4 = polygon->GetVertex(3); - mirrorVerts.push_back(v4); - area = normal_quad_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), (float*)v4->getXYZ()); - } else - { - area = normal_tri_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ()); - } - area = fabs(area); - mirrorArea += area; - mul_v3_fl(normal, area); - add_v3_v3v3(mirrorNormal, mirrorNormal, normal); - } - } - } - if (mirrorVerts.size() == 0 || mirrorArea < FLT_EPSILON) - { - // no vertex or zero size mirror - THRWEXCP(MirrorSizeInvalid, S_OK); - } - // compute average normal of mirror faces - mul_v3_fl(mirrorNormal, 1.0f/mirrorArea); - if (normalize_v3(mirrorNormal) == 0.f) - { - // no normal - THRWEXCP(MirrorNormalInvalid, S_OK); - } - // the mirror plane has an equation of the type ax+by+cz = d where (a,b,c) is the normal vector + // don't add the camera to the scene object list, it doesn't need to be accessible + m_owncamera = true; + // retrieve rendering objects + m_engine = KX_GetActiveEngine(); + m_rasterizer = m_engine->GetRasterizer(); + m_canvas = m_engine->GetCanvas(); + m_rendertools = m_engine->GetRenderTools(); + // locate the vertex assigned to mat and do following calculation in mesh coordinates + for (int meshIndex = 0; meshIndex < mirror->GetMeshCount(); meshIndex++) + { + RAS_MeshObject* mesh = mirror->GetMesh(meshIndex); + int numPolygons = mesh->NumPolygons(); + for (int polygonIndex=0; polygonIndex < numPolygons; polygonIndex++) + { + RAS_Polygon* polygon = mesh->GetPolygon(polygonIndex); + if (polygon->GetMaterial()->GetPolyMaterial() == mat) + { + RAS_TexVert *v1, *v2, *v3, *v4; + float normal[3]; + float area; + // this polygon is part of the mirror, + v1 = polygon->GetVertex(0); + v2 = polygon->GetVertex(1); + v3 = polygon->GetVertex(2); + mirrorVerts.push_back(v1); + mirrorVerts.push_back(v2); + mirrorVerts.push_back(v3); + if (polygon->VertexCount() == 4) + { + v4 = polygon->GetVertex(3); + mirrorVerts.push_back(v4); + area = normal_quad_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ(), (float*)v4->getXYZ()); + } else + { + area = normal_tri_v3( normal,(float*)v1->getXYZ(), (float*)v2->getXYZ(), (float*)v3->getXYZ()); + } + area = fabs(area); + mirrorArea += area; + mul_v3_fl(normal, area); + add_v3_v3v3(mirrorNormal, mirrorNormal, normal); + } + } + } + if (mirrorVerts.size() == 0 || mirrorArea < FLT_EPSILON) + { + // no vertex or zero size mirror + THRWEXCP(MirrorSizeInvalid, S_OK); + } + // compute average normal of mirror faces + mul_v3_fl(mirrorNormal, 1.0f/mirrorArea); + if (normalize_v3(mirrorNormal) == 0.f) + { + // no normal + THRWEXCP(MirrorNormalInvalid, S_OK); + } + // the mirror plane has an equation of the type ax+by+cz = d where (a,b,c) is the normal vector // if the mirror is more vertical then horizontal, the Z axis is the up direction. // otherwise the Y axis is the up direction. // If the mirror is not perfectly vertical(horizontal), the Z(Y) axis projection on the mirror // plan by the normal will be the up direction. if (fabs(mirrorNormal[2]) > fabs(mirrorNormal[1]) && - fabs(mirrorNormal[2]) > fabs(mirrorNormal[0])) + fabs(mirrorNormal[2]) > fabs(mirrorNormal[0])) { // the mirror is more horizontal than vertical - copy_v3_v3(axis, yaxis); + copy_v3_v3(axis, yaxis); } else { // the mirror is more vertical than horizontal - copy_v3_v3(axis, zaxis); + copy_v3_v3(axis, zaxis); + } + dist = dot_v3v3(mirrorNormal, axis); + if (fabs(dist) < FLT_EPSILON) + { + // the mirror is already fully aligned with up axis + copy_v3_v3(mirrorUp, axis); + } + else + { + // projection of axis to mirror plane through normal + copy_v3_v3(vec, mirrorNormal); + mul_v3_fl(vec, dist); + sub_v3_v3v3(mirrorUp, axis, vec); + if (normalize_v3(mirrorUp) == 0.f) + { + // should not happen + THRWEXCP(MirrorHorizontal, S_OK); + return; + } + } + // compute rotation matrix between local coord and mirror coord + // to match camera orientation, we select mirror z = -normal, y = up, x = y x z + negate_v3_v3(mirrorMat[2], mirrorNormal); + copy_v3_v3(mirrorMat[1], mirrorUp); + cross_v3_v3v3(mirrorMat[0], mirrorMat[1], mirrorMat[2]); + // transpose to make it a orientation matrix from local space to mirror space + transpose_m3(mirrorMat); + // transform all vertex to plane coordinates and determine mirror position + left = FLT_MAX; + right = -FLT_MAX; + bottom = FLT_MAX; + top = -FLT_MAX; + back = -FLT_MAX; // most backward vertex (=highest Z coord in mirror space) + for (it = mirrorVerts.begin(); it != mirrorVerts.end(); it++) + { + copy_v3_v3(vec, (float*)(*it)->getXYZ()); + mul_m3_v3(mirrorMat, vec); + if (vec[0] < left) + left = vec[0]; + if (vec[0] > right) + right = vec[0]; + if (vec[1] < bottom) + bottom = vec[1]; + if (vec[1] > top) + top = vec[1]; + if (vec[2] > back) + back = vec[2]; + } + // now store this information in the object for later rendering + m_mirrorHalfWidth = (right-left)*0.5f; + m_mirrorHalfHeight = (top-bottom)*0.5f; + if (m_mirrorHalfWidth < 0.01f || m_mirrorHalfHeight < 0.01f) + { + // mirror too small + THRWEXCP(MirrorTooSmall, S_OK); } - dist = dot_v3v3(mirrorNormal, axis); - if (fabs(dist) < FLT_EPSILON) - { - // the mirror is already fully aligned with up axis - copy_v3_v3(mirrorUp, axis); - } - else - { - // projection of axis to mirror plane through normal - copy_v3_v3(vec, mirrorNormal); - mul_v3_fl(vec, dist); - sub_v3_v3v3(mirrorUp, axis, vec); - if (normalize_v3(mirrorUp) == 0.f) - { - // should not happen - THRWEXCP(MirrorHorizontal, S_OK); - return; - } - } - // compute rotation matrix between local coord and mirror coord - // to match camera orientation, we select mirror z = -normal, y = up, x = y x z - negate_v3_v3(mirrorMat[2], mirrorNormal); - copy_v3_v3(mirrorMat[1], mirrorUp); - cross_v3_v3v3(mirrorMat[0], mirrorMat[1], mirrorMat[2]); - // transpose to make it a orientation matrix from local space to mirror space - transpose_m3(mirrorMat); - // transform all vertex to plane coordinates and determine mirror position - left = FLT_MAX; - right = -FLT_MAX; - bottom = FLT_MAX; - top = -FLT_MAX; - back = -FLT_MAX; // most backward vertex (=highest Z coord in mirror space) - for (it = mirrorVerts.begin(); it != mirrorVerts.end(); it++) - { - copy_v3_v3(vec, (float*)(*it)->getXYZ()); - mul_m3_v3(mirrorMat, vec); - if (vec[0] < left) - left = vec[0]; - if (vec[0] > right) - right = vec[0]; - if (vec[1] < bottom) - bottom = vec[1]; - if (vec[1] > top) - top = vec[1]; - if (vec[2] > back) - back = vec[2]; - } - // now store this information in the object for later rendering - m_mirrorHalfWidth = (right-left)*0.5f; - m_mirrorHalfHeight = (top-bottom)*0.5f; - if (m_mirrorHalfWidth < 0.01f || m_mirrorHalfHeight < 0.01f) - { - // mirror too small - THRWEXCP(MirrorTooSmall, S_OK); - } - // mirror position in mirror coord - vec[0] = (left+right)*0.5f; - vec[1] = (top+bottom)*0.5f; - vec[2] = back; - // convert it in local space: transpose again the matrix to get back to mirror to local transform - transpose_m3(mirrorMat); - mul_m3_v3(mirrorMat, vec); - // mirror position in local space - m_mirrorPos.setValue(vec[0], vec[1], vec[2]); - // mirror normal vector (pointed towards the back of the mirror) in local space - m_mirrorZ.setValue(-mirrorNormal[0], -mirrorNormal[1], -mirrorNormal[2]); - m_mirrorY.setValue(mirrorUp[0], mirrorUp[1], mirrorUp[2]); - m_mirrorX = m_mirrorY.cross(m_mirrorZ); - m_render = true; + // mirror position in mirror coord + vec[0] = (left+right)*0.5f; + vec[1] = (top+bottom)*0.5f; + vec[2] = back; + // convert it in local space: transpose again the matrix to get back to mirror to local transform + transpose_m3(mirrorMat); + mul_m3_v3(mirrorMat, vec); + // mirror position in local space + m_mirrorPos.setValue(vec[0], vec[1], vec[2]); + // mirror normal vector (pointed towards the back of the mirror) in local space + m_mirrorZ.setValue(-mirrorNormal[0], -mirrorNormal[1], -mirrorNormal[2]); + m_mirrorY.setValue(mirrorUp[0], mirrorUp[1], mirrorUp[2]); + m_mirrorX = m_mirrorY.cross(m_mirrorZ); + m_render = true; setBackground(0, 0, 255, 255); } diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index d0e5ee74f6e..0276ad6fd6b 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -123,34 +123,34 @@ void ImageViewport::calcImage (unsigned int texId, double ts) } // if texture can be directly created if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0]) - && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) + && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) { // just copy current viewport to texture - glBindTexture(GL_TEXTURE_2D, texId); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); - // image is not available - m_avail = false; + glBindTexture(GL_TEXTURE_2D, texId); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); + // image is not available + m_avail = false; } // otherwise copy viewport to buffer, if image is not available else if (!m_avail) { // get frame buffer data - if (m_alpha) - { - glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, - GL_UNSIGNED_BYTE, m_viewportImage); - // filter loaded data - FilterRGBA32 filt; - filterImage(filt, m_viewportImage, m_capSize); - } - else - { - glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, - GL_UNSIGNED_BYTE, m_viewportImage); - // filter loaded data - FilterRGB24 filt; - filterImage(filt, m_viewportImage, m_capSize); - } + if (m_alpha) + { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGBA32 filt; + filterImage(filt, m_viewportImage, m_capSize); + } + else + { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGB24 filt; + filterImage(filt, m_viewportImage, m_capSize); + } } } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index f8274756c8b..8a76b0c004d 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -544,11 +544,11 @@ void VideoFFmpeg::openFile (char * filename) // It would be good to find this information from the context but there are no simple indication !strncmp(filename, "http://", 7) || #ifdef FFMPEG_PB_IS_POINTER - (m_formatCtx->pb && m_formatCtx->pb->is_streamed) + (m_formatCtx->pb && m_formatCtx->pb->is_streamed) #else - m_formatCtx->pb.is_streamed + m_formatCtx->pb.is_streamed #endif - ) + ) { // the file is in fact a streaming source, treat as cam to prevent seeking m_isFile = false; diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index c1258bbb6e4..2cb3831de52 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -175,9 +175,9 @@ PyObject* initVideoTexture(void) // prepare classes registerAllTypes(); - registerAllExceptions(); + registerAllExceptions(); - if (!pyImageTypes.ready()) + if (!pyImageTypes.ready()) return NULL; if (!pyFilterTypes.ready()) return NULL; |