Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2008-10-03 00:39:57 +0400
committerMartin Poirier <theeth@yahoo.com>2008-10-03 00:39:57 +0400
commitc35a2d6ea9dc5226911bd90848e96a59233bdaf8 (patch)
treebe895ae3982a72a5b1cfd4ff9b1766037c07a6d0 /source/gameengine
parent39e66e4d6f48b7a54a510ec5504fd500cc07174f (diff)
parent06c43148a19ad7e8cddf9ba51549b51bdb1f6f0c (diff)
merge trunk 16118 -> 116886
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp100
-rw-r--r--source/gameengine/BlenderRoutines/CMakeLists.txt1
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.cpp75
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderGL.h3
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp262
-rw-r--r--source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h71
-rw-r--r--source/gameengine/BlenderRoutines/Makefile5
-rw-r--r--source/gameengine/BlenderRoutines/SConscript5
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp91
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.cpp91
-rw-r--r--source/gameengine/Converter/BL_ArmatureObject.h10
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp363
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.cpp8
-rw-r--r--source/gameengine/Converter/BL_DeformableGameObject.h14
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.cpp89
-rw-r--r--source/gameengine/Converter/BL_MeshDeformer.h5
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.cpp220
-rw-r--r--source/gameengine/Converter/BL_ShapeActionActuator.h5
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.cpp9
-rw-r--r--source/gameengine/Converter/BL_ShapeDeformer.h13
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.cpp51
-rw-r--r--source/gameengine/Converter/BL_SkinDeformer.h18
-rw-r--r--source/gameengine/Converter/BL_SkinMeshObject.cpp74
-rw-r--r--source/gameengine/Converter/BL_SkinMeshObject.h45
-rw-r--r--source/gameengine/Converter/CMakeLists.txt1
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.cpp72
-rw-r--r--source/gameengine/Converter/KX_BlenderSceneConverter.h2
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp168
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp8
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp49
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.h1
-rw-r--r--source/gameengine/Converter/Makefile1
-rw-r--r--source/gameengine/Converter/SConscript2
-rw-r--r--source/gameengine/Expressions/Makefile1
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp4
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h55
-rw-r--r--source/gameengine/Expressions/Value.cpp30
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp245
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_Joystick.h214
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h8
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp59
-rw-r--r--source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h7
-rw-r--r--source/gameengine/GameLogic/Makefile1
-rw-r--r--source/gameengine/GameLogic/SCA_2DFilterActuator.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_DelaySensor.cpp257
-rw-r--r--source/gameengine/GameLogic/SCA_DelaySensor.h77
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ILogicBrick.cpp1
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp103
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h14
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickManager.cpp35
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickManager.h4
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.cpp210
-rw-r--r--source/gameengine/GameLogic/SCA_JoystickSensor.h43
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp40
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h2
-rw-r--r--source/gameengine/GameLogic/SCA_MouseSensor.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp16
-rw-r--r--source/gameengine/GameLogic/SCA_PropertySensor.cpp24
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp41
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h10
-rw-r--r--source/gameengine/GameLogic/SCA_RandomActuator.cpp68
-rw-r--r--source/gameengine/GameLogic/SCA_RandomSensor.cpp12
-rw-r--r--source/gameengine/GameLogic/SConscript7
-rw-r--r--source/gameengine/GamePlayer/CMakeLists.txt4
-rw-r--r--source/gameengine/GamePlayer/common/CMakeLists.txt2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.cpp2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RawImage.h2
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.cpp538
-rw-r--r--source/gameengine/GamePlayer/common/GPC_RenderTools.h168
-rw-r--r--source/gameengine/GamePlayer/common/Makefile5
-rw-r--r--source/gameengine/GamePlayer/common/SConscript2
-rw-r--r--source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h4
-rw-r--r--source/gameengine/GamePlayer/ghost/CMakeLists.txt1
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.cpp104
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_Application.h17
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp119
-rw-r--r--source/gameengine/GamePlayer/ghost/Makefile6
-rw-r--r--source/gameengine/GamePlayer/ghost/SConscript4
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp124
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.h10
-rw-r--r--source/gameengine/Ketsji/BL_Material.h6
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp40
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h6
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt1
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp88
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h10
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp126
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h3
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_BulletPhysicsController.h4
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp42
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp357
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.h26
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObject.h42
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp655
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp74
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp369
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h118
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.cpp117
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.h6
-rw-r--r--source/gameengine/Ketsji/KX_IPhysicsController.h4
-rw-r--r--source/gameengine/Ketsji/KX_ISceneConverter.h4
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp95
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.h4
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp246
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h14
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp64
-rw-r--r--source/gameengine/Ketsji/KX_Light.h11
-rw-r--r--source/gameengine/Ketsji/KX_MaterialIpoController.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.cpp46
-rw-r--r--source/gameengine/Ketsji/KX_MeshProxy.h2
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp60
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h16
-rw-r--r--source/gameengine/Ketsji/KX_NearSensor.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_OdePhysicsController.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_OdePhysicsController.h2
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp265
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.h71
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.cpp50
-rw-r--r--source/gameengine/Ketsji/KX_PolygonMaterial.h2
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp40
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp918
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h6
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp12
-rw-r--r--source/gameengine/Ketsji/KX_RayCast.cpp85
-rw-r--r--source/gameengine/Ketsji/KX_RayCast.h60
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp74
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h8
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp142
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h30
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp43
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h2
-rw-r--r--source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp111
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h16
-rw-r--r--source/gameengine/Ketsji/KX_SceneActuator.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp64
-rw-r--r--source/gameengine/Ketsji/KX_StateActuator.cpp8
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_SumoPhysicsController.h1
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp26
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_VertexProxy.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_VisibilityActuator.h2
-rw-r--r--source/gameengine/Ketsji/Makefile11
-rw-r--r--source/gameengine/Ketsji/SConscript5
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsController.h2
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp5
-rw-r--r--source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h3
-rw-r--r--source/gameengine/Physics/Bullet/CMakeLists.txt4
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.cpp1098
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsController.h263
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp731
-rw-r--r--source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h22
-rw-r--r--source/gameengine/Physics/Bullet/Makefile5
-rw-r--r--source/gameengine/Physics/Bullet/SConscript2
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp3
-rw-r--r--source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h3
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsController.h1
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp31
-rw-r--r--source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h3
-rw-r--r--source/gameengine/Physics/common/PHY_DynamicTypes.h12
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsController.h3
-rw-r--r--source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h47
-rw-r--r--source/gameengine/PyDoc/BL_ActionActuator.py13
-rw-r--r--source/gameengine/PyDoc/BL_ShapeActionActuator.py13
-rw-r--r--source/gameengine/PyDoc/GameKeys.py9
-rw-r--r--source/gameengine/PyDoc/GameLogic.py21
-rw-r--r--source/gameengine/PyDoc/KX_GameObject.py90
-rw-r--r--source/gameengine/PyDoc/KX_MeshProxy.py15
-rw-r--r--source/gameengine/PyDoc/KX_ObjectActuator.py4
-rw-r--r--source/gameengine/PyDoc/KX_PolyProxy.py100
-rw-r--r--source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py17
-rw-r--r--source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py5
-rw-r--r--source/gameengine/PyDoc/KX_TrackToActuator.py2
-rw-r--r--source/gameengine/PyDoc/Rasterizer.py50
-rw-r--r--source/gameengine/PyDoc/SCA_DelaySensor.py56
-rw-r--r--source/gameengine/PyDoc/SCA_ISensor.py13
-rw-r--r--source/gameengine/Rasterizer/Makefile4
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.cpp2
-rw-r--r--source/gameengine/Rasterizer/RAS_2DFilterManager.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.cpp254
-rw-r--r--source/gameengine/Rasterizer/RAS_BucketManager.h21
-rw-r--r--source/gameengine/Rasterizer/RAS_Deformer.h6
-rw-r--r--source/gameengine/Rasterizer/RAS_FramingManager.h15
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp25
-rw-r--r--source/gameengine/Rasterizer/RAS_IPolygonMaterial.h9
-rw-r--r--source/gameengine/Rasterizer/RAS_IRasterizer.h52
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.cpp24
-rw-r--r--source/gameengine/Rasterizer/RAS_IRenderTools.h39
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.cpp576
-rw-r--r--source/gameengine/Rasterizer/RAS_MaterialBucket.h213
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.cpp725
-rw-r--r--source/gameengine/Rasterizer/RAS_MeshObject.h240
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Blur2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Dilation2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_GrayScale2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Invert2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Laplacian2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Prewitt2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sepia2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sharpen2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sobel2DFilter.h2
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt1
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile5
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp84
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h24
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp782
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h49
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp216
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h18
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript5
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.cpp83
-rw-r--r--source/gameengine/Rasterizer/RAS_Polygon.h56
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.cpp31
-rw-r--r--source/gameengine/Rasterizer/RAS_TexVert.h49
-rw-r--r--source/gameengine/Rasterizer/SConscript5
227 files changed, 9694 insertions, 6154 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index 7de3056e382..0d58810e156 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -79,6 +79,8 @@
#include "DNA_scene_types.h"
/***/
+#include "GPU_extensions.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -90,33 +92,10 @@ void update_for_newframe();
static BlendFileData *load_game_data(char *filename) {
BlendReadError error;
- //this doesn't work anymore for relative paths, so use BLO_read_from_memory instead
- //BlendFileData *bfd= BLO_read_from_file(filename, &error);
- FILE* file = fopen(filename,"rb");
- BlendFileData *bfd = 0;
- if (file)
- {
- fseek(file, 0L, SEEK_END);
- int len= ftell(file);
- fseek(file, 0L, SEEK_SET);
- char* filebuffer= new char[len];//MEM_mallocN(len, "text_buffer");
- int sizeread = fread(filebuffer,len,1,file);
- if (sizeread==1){
- bfd = BLO_read_from_memory(filebuffer, len, &error);
- } else {
- error = BRE_UNABLE_TO_READ;
- }
- fclose(file);
- // the memory is not released in BLO_read_from_memory, must do it here
- delete filebuffer;
- } else {
- error = BRE_UNABLE_TO_OPEN;
- }
-
+ BlendFileData *bfd= BLO_read_from_file(filename, &error);
if (!bfd) {
printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
}
-
return bfd;
}
@@ -139,7 +118,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
// Acquire Python's GIL (global interpreter lock)
// so we can safely run Python code and API calls
PyGILState_STATE gilstate = PyGILState_Ensure();
-
+
+ PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
+
bgl::InitExtensions(true);
do
@@ -157,7 +138,12 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
bool usemat = false, useglslmat = false;
if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
- usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0);
+ usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0);
+
+ if(GPU_extensions_minimum_support())
+ useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0);
+ else if(G.fileflags & G_FILE_GAME_MAT_GLSL)
+ usemat = false;
// create the canvas, rasterizer and rendertools
RAS_ICanvas* canvas = new KX_BlenderCanvas(area);
@@ -184,6 +170,13 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
NG_NetworkDeviceInterface* networkdevice = new
NG_LoopBackNetworkDeviceInterface();
+ //
+ SYS_SystemHandle hSystem = SYS_GetSystem();
+ bool noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
+
+ if (noaudio)/*(noaudio) intrr: disable game engine audio (openal) */
+ SND_DeviceManager::SetDeviceType(snd_e_dummydevice);
+
// get an audiodevice
SND_DeviceManager::Subscribe();
SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
@@ -212,6 +205,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
// some blender stuff
MT_CmMatrix4x4 projmat;
MT_CmMatrix4x4 viewmat;
+ float camzoom;
int i;
for (i = 0; i < 16; i++)
@@ -225,8 +219,13 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
projmat.setElem(i, projmat_linear[i]);
}
- float camzoom = (1.41421 + (v3d->camzoom / 50.0));
- camzoom *= camzoom;
+ if(v3d->persp==V3D_CAMOB) {
+ camzoom = (1.41421 + (v3d->camzoom / 50.0));
+ camzoom *= camzoom;
+ }
+ else
+ camzoom = 2.0;
+
camzoom = 4.0 / camzoom;
ketsjiengine->SetDrawType(v3d->drawtype);
@@ -307,6 +306,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO));
ketsjiengine->SetCameraOverrideProjectionMatrix(projmat);
ketsjiengine->SetCameraOverrideViewMatrix(viewmat);
+ ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
}
// create a scene converter, create and convert the startingscene
@@ -315,24 +315,28 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
sceneconverter->addInitFromFrame=false;
if (always_use_expand_framing)
sceneconverter->SetAlwaysUseExpandFraming(true);
-
- if(usemat)
+
+ if(usemat && (G.fileflags & G_FILE_GAME_MAT))
sceneconverter->SetMaterials(true);
- if(useglslmat)
+ if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL))
sceneconverter->SetGLSLMaterials(true);
KX_Scene* startscene = new KX_Scene(keyboarddevice,
mousedevice,
networkdevice,
audiodevice,
- startscenename);
+ startscenename,
+ blscene);
// some python things
PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
ketsjiengine->SetPythonDictionary(dictionaryobject);
initRasterizer(rasterizer, canvas);
- PyObject *gameLogic = initGameLogic(startscene);
+ PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
+ PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
+ PyObject *gameLogic_keys = PyDict_Keys(PyModule_GetDict(gameLogic));
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module.
+
initGameKeys();
initPythonConstraintBinding();
initMathutils();
@@ -362,6 +366,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
ketsjiengine->SetAnimFrameRate( (((double) blscene->r.frs_sec) / blscene->r.frs_sec_base) );
// the mainloop
+ printf("\nBlender Game Engine Started\n\n");
while (!exitrequested)
{
// first check if we want to exit
@@ -397,6 +402,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
mousedevice->ConvertBlenderEvent(event,val);
}
}
+ printf("\nBlender Game Engine Finished\n\n");
exitstring = ketsjiengine->GetExitString();
// when exiting the mainloop
@@ -406,7 +412,20 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
// inside the GameLogic dictionary when the python interpreter is finalized.
// which allows the scene to safely delete them :)
// see: (space.c)->start_game
- PyDict_Clear(PyModule_GetDict(gameLogic));
+
+ //PyDict_Clear(PyModule_GetDict(gameLogic));
+
+ // Keep original items, means python plugins will autocomplete members
+ int listIndex;
+ PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
+ for (listIndex=0; listIndex < PyList_Size(gameLogic_keys_new); listIndex++) {
+ PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
+ if (!PySequence_Contains(gameLogic_keys, item)) {
+ PyDict_DelItem( PyModule_GetDict(gameLogic), item);
+ }
+ }
+ Py_DECREF(gameLogic_keys_new);
+ gameLogic_keys_new = NULL;
ketsjiengine->StopEngine();
exitGamePythonScripting();
@@ -417,6 +436,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
delete sceneconverter;
sceneconverter = NULL;
}
+
+ Py_DECREF(gameLogic_keys);
+ gameLogic_keys = NULL;
}
// set the cursor back to normal
canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
@@ -545,8 +567,6 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
// create the ketsjiengine
KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
- int i;
-
Scene *blscene = NULL;
if (!bfd)
{
@@ -562,7 +582,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
} else {
blscene = bfd->curscene;
}
- int cframe,startFrame;
+ int cframe = 1, startFrame;
if (blscene)
{
cframe=blscene->r.cfra;
@@ -593,12 +613,14 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area,
mousedevice,
networkdevice,
audiodevice,
- startscenename);
+ startscenename,
+ blscene);
+
// some python things
PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest);
ketsjiengine->SetPythonDictionary(dictionaryobject);
initRasterizer(rasterizer, canvas);
- PyObject *gameLogic = initGameLogic(startscene);
+ PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt
index 1d72fb9cde1..340a1ae310b 100644
--- a/source/gameengine/BlenderRoutines/CMakeLists.txt
+++ b/source/gameengine/BlenderRoutines/CMakeLists.txt
@@ -31,6 +31,7 @@ SET(INC
../../../intern/SoundSystem
../../../source/blender/misc
../../../source/blender/blenloader
+ ../../../source/blender/gpu
../../../extern/bullet2/src
../../../extern/solid
../../../extern/glew/include
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
index da52be56d1b..669e7bd1b3f 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp
@@ -26,7 +26,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "GL/glew.h"
#include "KX_BlenderGL.h"
#ifdef HAVE_CONFIG_H
@@ -93,80 +92,6 @@ void BL_SwapBuffers()
myswapbuffers();
}
-void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface,
- unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3])
-{
- Image* ima;
-
- if(mode & TF_BMFONT) {
- //char string[MAX_PROPSTRING];
- int characters, index, character;
- float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
-
-// bProperty *prop;
-
- // string = "Frank van Beek";
-
- characters = textlen;
-
- ima = (struct Image*) tface->tpage;
- if (ima == NULL) {
- characters = 0;
- }
-
- /* When OBCOL flag is on the color is set in IndexPrimitives_3DText */
- if (tface->mode & TF_OBCOL) { /* Color has been set */
- col= NULL;
- } else {
- if(!col) glColor3f(1.0f, 1.0f, 1.0f);
- }
-
- glPushMatrix();
- for (index = 0; index < characters; index++) {
- // lets calculate offset stuff
- character = textstr[index];
-
- // space starts at offset 1
- // character = character - ' ' + 1;
-
- matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
-
- glBegin(GL_POLYGON);
- // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], );
- // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
- glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
-
- if(col) spack(col[0]);
- // glVertex3fv(v1);
- glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
-
- glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
- if(col) spack(col[1]);
- // glVertex3fv(v2);
- glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
-
- glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
- if(col) spack(col[2]);
- // glVertex3fv(v3);
- glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
-
- if(v4) {
- // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy);
- glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
- if(col) spack(col[3]);
- // glVertex3fv(v4);
- glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
- }
- glEnd();
-
- glTranslatef(advance, 0.0, 0.0);
- }
- glPopMatrix();
-
- }
-}
-
-
void DisableForText()
{
if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h
index c8e0d47afb6..b891a7343c2 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h
@@ -46,9 +46,6 @@ void BL_HideMouse();
void BL_NormalMouse();
void BL_WaitMouse();
-void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface,
- unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]);
-
void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height);
void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height);
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
index e4eff163d5b..1797d6c1a0f 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp
@@ -26,8 +26,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include "KX_BlenderRenderTools.h"
-
#include "GL/glew.h"
#include "RAS_IRenderTools.h"
@@ -36,23 +34,22 @@
#include "RAS_ICanvas.h"
#include "RAS_GLExtensionManager.h"
-// next two includes/dependencies come from the shadow feature
-// it needs the gameobject and the sumo physics scene for a raycast
#include "KX_GameObject.h"
-
#include "KX_PolygonMaterial.h"
#include "KX_BlenderMaterial.h"
+#include "KX_RayCast.h"
+#include "KX_IPhysicsController.h"
-#include "Value.h"
+#include "PHY_IPhysicsEnvironment.h"
-#include "KX_BlenderGL.h" // for text printing
#include "STR_String.h"
-#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting)
-#include "KX_RayCast.h"
-#include "KX_IPhysicsController.h"
-#include "PHY_IPhysicsEnvironment.h"
-#include "KX_Scene.h"
+#include "GPU_draw.h"
+
+#include "KX_BlenderGL.h" // for text printing
+#include "KX_BlenderRenderTools.h"
+
+unsigned int KX_BlenderRenderTools::m_numgllights;
KX_BlenderRenderTools::KX_BlenderRenderTools()
{
@@ -61,81 +58,98 @@ KX_BlenderRenderTools::KX_BlenderRenderTools()
m_numgllights = 8;
}
-/**
-ProcessLighting performs lighting on objects. the layer is a bitfield that contains layer information.
-There are 20 'official' layers in blender.
-A light is applied on an object only when they are in the same layer.
-OpenGL has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in a scene.
-*/
+KX_BlenderRenderTools::~KX_BlenderRenderTools()
+{
+}
-int KX_BlenderRenderTools::ProcessLighting(int layer)
+void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty)
{
-
- int result = false;
+ m_clientobject = NULL;
+ m_lastlightlayer = -1;
+ m_lastlighting = false;
+ DisableOpenGLLights();
+}
- if (layer < 0)
- {
- DisableOpenGLLights();
- result = false;
- } else
+void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty)
+{
+}
+
+/* ProcessLighting performs lighting on objects. the layer is a bitfield that
+ * contains layer information. There are 20 'official' layers in blender. A
+ * light is applied on an object only when they are in the same layer. OpenGL
+ * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
+ * a scene. */
+
+void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat)
+{
+ if(m_lastlightlayer == layer)
+ return;
+
+ m_lastlightlayer = layer;
+
+ bool enable = false;
+
+ if (layer >= 0)
{
if (m_clientobject)
{
if (layer == RAS_LIGHT_OBJECT_LAYER)
- {
layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
- }
- if (applyLights(layer))
- {
- EnableOpenGLLights();
- result = true;
- } else
- {
- DisableOpenGLLights();
- result = false;
- }
+
+ enable = applyLights(layer, viewmat);
}
}
- return result;
-
-
+
+ if(enable)
+ EnableOpenGLLights();
+ else
+ DisableOpenGLLights();
}
+void KX_BlenderRenderTools::EnableOpenGLLights()
+{
+ if(m_lastlighting == true)
+ return;
-void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty)
+ glEnable(GL_LIGHTING);
+ glEnable(GL_COLOR_MATERIAL);
+
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true);
+ if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
+ glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
+ m_lastlighting = true;
+}
+
+void KX_BlenderRenderTools::DisableOpenGLLights()
{
- m_clientobject = NULL;
- m_lastblenderobject = NULL;
- m_lastblenderlights = false;
- m_lastlayer = -1;
- m_lastlighting = false;
- m_modified = true;
- DisableOpenGLLights();
+ if(m_lastlighting == false)
+ return;
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ m_lastlighting = false;
}
-void KX_BlenderRenderTools::SetClientObject(void* obj)
+
+void KX_BlenderRenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj)
{
if (m_clientobject != obj)
{
- if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling())
- {
- glFrontFace(GL_CCW);
- } else
- {
- glFrontFace(GL_CW);
- }
+ bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling());
+ rasty->SetFrontFace(ccw);
+
m_clientobject = obj;
- m_modified = true;
}
}
-bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
{
double* const oglmatrix = (double* const) data;
- MT_Point3 resultpoint(hit_point);
- MT_Vector3 resultnormal(hit_normal);
+ MT_Point3 resultpoint(result->m_hitPoint);
+ MT_Vector3 resultnormal(result->m_hitNormal);
MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
left = (dir.cross(resultnormal)).safe_normalized();
@@ -182,7 +196,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
MT_Vector3 dir = (campos - objpos).safe_normalized();
MT_Vector3 up(0,0,1.0);
- KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject* gameobj = (KX_GameObject*)m_clientobject;
// get scaling of halo object
MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
@@ -218,7 +232,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
{
// shadow must be cast to the ground, physics system needed here!
MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
+ KX_GameObject *gameobj = (KX_GameObject*)m_clientobject;
MT_Vector3 direction = MT_Vector3(0,0,-1);
direction.normalize();
@@ -236,9 +250,8 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
if (parent)
parent->Release();
- MT_Point3 resultpoint;
- MT_Vector3 resultnormal;
- if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_BlenderRenderTools>(this, oglmatrix)))
+ KX_RayCast::Callback<KX_BlenderRenderTools> callback(this, physics_controller, oglmatrix);
+ if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
{
// couldn't find something to cast the shadow on...
glMultMatrixd(oglmatrix);
@@ -253,13 +266,29 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat
}
-/**
-Render Text renders text into a (series of) polygon, using a texture font,
-Each character consists of one polygon (one quad or two triangles)
-*/
-void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float v1[3],float v2[3],float v3[3],float v4[3])
+void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height)
+{
+ STR_String tmpstr(text);
+
+ if(mode == RAS_IRenderTools::RAS_TEXT_PADDED)
+ BL_print_gamedebug_line_padded(tmpstr.Ptr(), xco, yco, width, height);
+ else
+ BL_print_gamedebug_line(tmpstr.Ptr(), xco, yco, width, height);
+}
+
+/* Render Text renders text into a (series of) polygon, using a texture font,
+ * Each character consists of one polygon (one quad or two triangles) */
+
+void KX_BlenderRenderTools::RenderText(
+ int mode,
+ RAS_IPolyMaterial* polymat,
+ float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
-
STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
@@ -276,67 +305,9 @@ void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float
col = blenderpoly->GetMCol();
}
- BL_RenderText( mode,mytext,mytext.Length(),tface,col,v1,v2,v3,v4);
-
-}
-
-
-
-KX_BlenderRenderTools::~KX_BlenderRenderTools()
-{
-};
-
-
-void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty)
-{
+ GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib);
}
-
-
-void KX_BlenderRenderTools::DisableOpenGLLights()
-{
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
-}
-
-
-void KX_BlenderRenderTools::EnableOpenGLLights()
-{
- glEnable(GL_LIGHTING);
-
- glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true);
- if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
- glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
-
-}
-
-
-/**
- * Rendering text using 2D bitmap functionality.
- */
-void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
- const char* text,
- int xco,
- int yco,
- int width,
- int height)
-{
- switch (mode) {
- case RAS_IRenderTools::RAS_TEXT_PADDED: {
- STR_String tmpstr(text);
- BL_print_gamedebug_line_padded(tmpstr.Ptr(),xco,yco,width,height);
- break;
- }
- default: {
- STR_String tmpstr(text);
- BL_print_gamedebug_line(tmpstr.Ptr(),xco,yco,width,height);
- }
- }
-}
-
-
void KX_BlenderRenderTools::PushMatrix()
{
@@ -349,14 +320,13 @@ void KX_BlenderRenderTools::PopMatrix()
}
-
-int KX_BlenderRenderTools::applyLights(int objectlayer)
+int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat)
{
-// taken from blender source, incompatibility between Blender Object / GameObject
-
+ // taken from blender source, incompatibility between Blender Object / GameObject
+ float glviewmat[16];
unsigned int count;
float vec[4];
-
+
vec[3]= 1.0;
for(count=0; count<m_numgllights; count++)
@@ -364,9 +334,11 @@ int KX_BlenderRenderTools::applyLights(int objectlayer)
//std::vector<struct RAS_LightObject*> m_lights;
std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin();
+
+ viewmat.getValue(glviewmat);
glPushMatrix();
- glLoadMatrixf(m_viewmat);
+ glLoadMatrixf(glviewmat);
for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
{
RAS_LightObject* lightdata = (*lit);
@@ -434,7 +406,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer)
glEnable((GLenum)(GL_LIGHT0+count));
count++;
-
}
}
glPopMatrix();
@@ -443,22 +414,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer)
}
-
-
-RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial(
- const STR_String &texname,
- bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant,bool zsort, int lightlayer
- ,bool bIsTriangle,void* clientobject,void* tface)
-{
- assert(!"Deprecated");
-/* return new KX_BlenderPolyMaterial(
-
- texname,
- ba,matname,tile,tilexrep,tileyrep,mode,transparant,zsort, lightlayer
- ,bIsTriangle,clientobject,(struct MTFace*)tface);*/
- return NULL;
-}
-
void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
{
int state = rasterizer->GetMotionBlurState();
@@ -492,4 +447,3 @@ void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas)
m_filtermanager.RenderFilters(canvas);
}
-unsigned int KX_BlenderRenderTools::m_numgllights;
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
index 8abce1b8c3e..a7618462c9b 100644
--- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
+++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h
@@ -26,6 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
#ifndef __KX_BLENDERRENDERTOOLS
#define __KX_BLENDERRENDERTOOLS
@@ -37,67 +38,54 @@
#include "RAS_IRenderTools.h"
struct KX_ClientObjectInfo;
+class KX_RayCast;
-/**
-BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not
-part of the (polygon) Rasterizer.
-Effects like 2D text, 3D (polygon) text, lighting.
-*/
+/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which
+ * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon)
+ * text, lighting.
+ *
+ * Most of this code is duplicated in GPC_RenderTools, so this should be
+ * moved to some common location to avoid duplication. */
class KX_BlenderRenderTools : public RAS_IRenderTools
{
- bool m_lastblenderlights;
- void* m_lastblenderobject;
- int m_lastlayer;
+ int m_lastlightlayer;
bool m_lastlighting;
static unsigned int m_numgllights;
-
-
+
public:
-
KX_BlenderRenderTools();
virtual ~KX_BlenderRenderTools();
- virtual void EndFrame(class RAS_IRasterizer* rasty);
- virtual void BeginFrame(class RAS_IRasterizer* rasty);
- void DisableOpenGLLights();
+ void EndFrame(RAS_IRasterizer* rasty);
+ void BeginFrame(RAS_IRasterizer* rasty);
+
void EnableOpenGLLights();
- int ProcessLighting(int layer);
+ void DisableOpenGLLights();
+ void ProcessLighting(int layer, const MT_Transform& viewmat);
- virtual void RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ void RenderText2D(RAS_TEXT_RENDER_MODE mode,
const char* text,
int xco,
int yco,
int width,
int height);
- virtual void RenderText(int mode,
+ void RenderText(int mode,
class RAS_IPolyMaterial* polymat,
float v1[3],
float v2[3],
float v3[3],
- float v4[3]);
- void applyTransform(class RAS_IRasterizer* rasty,
- double* oglmatrix,
- int objectdrawmode );
- int applyLights(int objectlayer);
- virtual void PushMatrix();
- virtual void PopMatrix();
-
- virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(const STR_String &texname,
- bool ba,
- const STR_String& matname,
- int tile,
- int tilexrep,
- int tileyrep,
- int mode,
- bool transparant,
- bool zsort,
- int lightlayer,
- bool bIsTriangle,
- void* clientobject,
- void* tface);
-
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ float v4[3],
+ int glattrib);
+
+ void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode);
+ int applyLights(int objectlayer, const MT_Transform& viewmat);
+
+ void PushMatrix();
+ void PopMatrix();
+
+ bool RayHit(KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo*) { return true; }
virtual void MotionBlur(RAS_IRasterizer* rasterizer);
@@ -105,8 +93,7 @@ public:
virtual void Render2DFilters(RAS_ICanvas* canvas);
- virtual void SetClientObject(void* obj);
-
+ virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj);
};
#endif //__KX_BLENDERRENDERTOOLS
diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile
index a7394158a20..4b9a2a3af17 100644
--- a/source/gameengine/BlenderRoutines/Makefile
+++ b/source/gameengine/BlenderRoutines/Makefile
@@ -54,6 +54,7 @@ CPPFLAGS += -I../../blender/blenkernel
CPPFLAGS += -I../../blender/render/extern/include
CPPFLAGS += -I../../blender/blenloader
CPPFLAGS += -I../../blender/blenkernel
+CPPFLAGS += -I../../blender/gpu
CPPFLAGS += -I../Converter
CPPFLAGS += -I../Expressions
CPPFLAGS += -I../GameLogic
@@ -72,9 +73,5 @@ ifeq ($(OS),windows)
CPPFLAGS += -I../../blender
endif
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
-
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript
index 327f4798e04..78adbc83d9b 100644
--- a/source/gameengine/BlenderRoutines/SConscript
+++ b/source/gameengine/BlenderRoutines/SConscript
@@ -15,7 +15,7 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common'
incs += ' #source/gameengine/Physics/Bullet #source/gameengine/Physics/Sumo'
incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork'
incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader'
-incs += ' #extern/glew/include'
+incs += ' #extern/glew/include #source/blender/gpu'
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_SOLID_INC']
@@ -26,7 +26,4 @@ cxxflags = []
if env['OURPLATFORM']=='win32-vc':
cxxflags.append ('/GR')
-if env['WITH_BF_GLEXT'] == 1:
- env['CPPFLAGS'].append('-DWITH_GLEXT')
-
env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags)
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index d8b2e063a9d..4d748948c27 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -50,6 +50,7 @@
#include "MT_Matrix4x4.h"
#include "BKE_utildefines.h"
#include "FloatValue.h"
+#include "PyObjectPlus.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -58,11 +59,11 @@
BL_ActionActuator::~BL_ActionActuator()
{
if (m_pose)
- free_pose(m_pose);
+ game_free_pose(m_pose);
if (m_userpose)
- free_pose(m_userpose);
+ game_free_pose(m_userpose);
if (m_blendpose)
- free_pose(m_blendpose);
+ game_free_pose(m_blendpose);
}
void BL_ActionActuator::ProcessReplica(){
@@ -151,6 +152,8 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
bool apply=true;
int priority;
float newweight;
+
+ curtime -= KX_KetsjiEngine::GetSuspendedDelta();
// result = true if animation has to be continued, false if animation stops
// maybe there are events for us in the queue !
@@ -445,28 +448,28 @@ PyParentObject BL_ActionActuator::Parents[] = {
};
PyMethodDef BL_ActionActuator::Methods[] = {
- {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, SetAction_doc},
- {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, SetStart_doc},
- {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc},
- {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc},
- {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc},
- {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc},
- {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, SetFrameProperty_doc},
- {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
-
- {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc},
- {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc},
- {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc},
- {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc},
- {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc},
- {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc},
- {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, GetFrameProperty_doc},
- {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, SetChannel_doc},
+ {"setAction", (PyCFunction) BL_ActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc},
+ {"setStart", (PyCFunction) BL_ActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc},
+ {"setEnd", (PyCFunction) BL_ActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc},
+ {"setBlendin", (PyCFunction) BL_ActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc},
+ {"setPriority", (PyCFunction) BL_ActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc},
+ {"setFrame", (PyCFunction) BL_ActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc},
+ {"setProperty", (PyCFunction) BL_ActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"setFrameProperty", (PyCFunction) BL_ActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc},
+ {"setBlendtime", (PyCFunction) BL_ActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc},
+
+ {"getAction", (PyCFunction) BL_ActionActuator::sPyGetAction, METH_VARARGS, (PY_METHODCHAR)GetAction_doc},
+ {"getStart", (PyCFunction) BL_ActionActuator::sPyGetStart, METH_VARARGS, (PY_METHODCHAR)GetStart_doc},
+ {"getEnd", (PyCFunction) BL_ActionActuator::sPyGetEnd, METH_VARARGS, (PY_METHODCHAR)GetEnd_doc},
+ {"getBlendin", (PyCFunction) BL_ActionActuator::sPyGetBlendin, METH_VARARGS, (PY_METHODCHAR)GetBlendin_doc},
+ {"getPriority", (PyCFunction) BL_ActionActuator::sPyGetPriority, METH_VARARGS, (PY_METHODCHAR)GetPriority_doc},
+ {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, METH_VARARGS, (PY_METHODCHAR)GetFrame_doc},
+ {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"getFrameProperty", (PyCFunction) BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, (PY_METHODCHAR)GetFrameProperty_doc},
+ {"setChannel", (PyCFunction) BL_ActionActuator::sPySetChannel, METH_VARARGS, (PY_METHODCHAR)SetChannel_doc},
// {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_VARARGS},
- {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, GetType_doc},
- {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, SetType_doc},
+ {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc},
+ {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc},
{"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, METH_NOARGS, 0},
{"setContinue", (PyCFunction) BL_ActionActuator::sPySetContinue, METH_O, 0},
{NULL,NULL} //Sentinel
@@ -477,7 +480,7 @@ PyObject* BL_ActionActuator::_getattr(const STR_String& attr) {
}
/* setStart */
-char BL_ActionActuator::GetAction_doc[] =
+const char BL_ActionActuator::GetAction_doc[] =
"getAction()\n"
"\tReturns a string containing the name of the current action.\n";
@@ -491,7 +494,7 @@ PyObject* BL_ActionActuator::PyGetAction(PyObject* self,
}
/* getProperty */
-char BL_ActionActuator::GetProperty_doc[] =
+const char BL_ActionActuator::GetProperty_doc[] =
"getProperty()\n"
"\tReturns the name of the property to be used in FromProp mode.\n";
@@ -506,7 +509,7 @@ PyObject* BL_ActionActuator::PyGetProperty(PyObject* self,
}
/* getProperty */
-char BL_ActionActuator::GetFrameProperty_doc[] =
+const char BL_ActionActuator::GetFrameProperty_doc[] =
"getFrameProperty()\n"
"\tReturns the name of the property, that is set to the current frame number.\n";
@@ -521,7 +524,7 @@ PyObject* BL_ActionActuator::PyGetFrameProperty(PyObject* self,
}
/* getFrame */
-char BL_ActionActuator::GetFrame_doc[] =
+const char BL_ActionActuator::GetFrame_doc[] =
"getFrame()\n"
"\tReturns the current frame number.\n";
@@ -536,7 +539,7 @@ PyObject* BL_ActionActuator::PyGetFrame(PyObject* self,
}
/* getEnd */
-char BL_ActionActuator::GetEnd_doc[] =
+const char BL_ActionActuator::GetEnd_doc[] =
"getEnd()\n"
"\tReturns the last frame of the action.\n";
@@ -551,7 +554,7 @@ PyObject* BL_ActionActuator::PyGetEnd(PyObject* self,
}
/* getStart */
-char BL_ActionActuator::GetStart_doc[] =
+const char BL_ActionActuator::GetStart_doc[] =
"getStart()\n"
"\tReturns the starting frame of the action.\n";
@@ -566,7 +569,7 @@ PyObject* BL_ActionActuator::PyGetStart(PyObject* self,
}
/* getBlendin */
-char BL_ActionActuator::GetBlendin_doc[] =
+const char BL_ActionActuator::GetBlendin_doc[] =
"getBlendin()\n"
"\tReturns the number of interpolation animation frames to be\n"
"\tgenerated when this actuator is triggered.\n";
@@ -582,7 +585,7 @@ PyObject* BL_ActionActuator::PyGetBlendin(PyObject* self,
}
/* getPriority */
-char BL_ActionActuator::GetPriority_doc[] =
+const char BL_ActionActuator::GetPriority_doc[] =
"getPriority()\n"
"\tReturns the priority for this actuator. Actuators with lower\n"
"\tPriority numbers will override actuators with higher numbers.\n";
@@ -598,7 +601,7 @@ PyObject* BL_ActionActuator::PyGetPriority(PyObject* self,
}
/* setAction */
-char BL_ActionActuator::SetAction_doc[] =
+const char BL_ActionActuator::SetAction_doc[] =
"setAction(action, (reset))\n"
"\t - action : The name of the action to set as the current action.\n"
"\t - reset : Optional parameter indicating whether to reset the\n"
@@ -637,7 +640,7 @@ PyObject* BL_ActionActuator::PySetAction(PyObject* self,
}
/* setStart */
-char BL_ActionActuator::SetStart_doc[] =
+const char BL_ActionActuator::SetStart_doc[] =
"setStart(start)\n"
"\t - start : Specifies the starting frame of the animation.\n";
@@ -658,7 +661,7 @@ PyObject* BL_ActionActuator::PySetStart(PyObject* self,
}
/* setEnd */
-char BL_ActionActuator::SetEnd_doc[] =
+const char BL_ActionActuator::SetEnd_doc[] =
"setEnd(end)\n"
"\t - end : Specifies the ending frame of the animation.\n";
@@ -679,7 +682,7 @@ PyObject* BL_ActionActuator::PySetEnd(PyObject* self,
}
/* setBlendin */
-char BL_ActionActuator::SetBlendin_doc[] =
+const char BL_ActionActuator::SetBlendin_doc[] =
"setBlendin(blendin)\n"
"\t - blendin : Specifies the number of frames of animation to generate\n"
"\t when making transitions between actions.\n";
@@ -701,7 +704,7 @@ PyObject* BL_ActionActuator::PySetBlendin(PyObject* self,
}
/* setBlendtime */
-char BL_ActionActuator::SetBlendtime_doc[] =
+const char BL_ActionActuator::SetBlendtime_doc[] =
"setBlendtime(blendtime)\n"
"\t - blendtime : Allows the script to directly modify the internal timer\n"
"\t used when generating transitions between actions. This\n"
@@ -728,7 +731,7 @@ PyObject* BL_ActionActuator::PySetBlendtime(PyObject* self,
}
/* setPriority */
-char BL_ActionActuator::SetPriority_doc[] =
+const char BL_ActionActuator::SetPriority_doc[] =
"setPriority(priority)\n"
"\t - priority : Specifies the new priority. Actuators will lower\n"
"\t priority numbers will override actuators with higher\n"
@@ -751,7 +754,7 @@ PyObject* BL_ActionActuator::PySetPriority(PyObject* self,
}
/* setFrame */
-char BL_ActionActuator::SetFrame_doc[] =
+const char BL_ActionActuator::SetFrame_doc[] =
"setFrame(frame)\n"
"\t - frame : Specifies the new current frame for the animation\n";
@@ -776,7 +779,7 @@ PyObject* BL_ActionActuator::PySetFrame(PyObject* self,
}
/* setProperty */
-char BL_ActionActuator::SetProperty_doc[] =
+const char BL_ActionActuator::SetProperty_doc[] =
"setProperty(prop)\n"
"\t - prop : A string specifying the property name to be used in\n"
"\t FromProp playback mode.\n";
@@ -798,7 +801,7 @@ PyObject* BL_ActionActuator::PySetProperty(PyObject* self,
}
/* setFrameProperty */
-char BL_ActionActuator::SetFrameProperty_doc[] =
+const char BL_ActionActuator::SetFrameProperty_doc[] =
"setFrameProperty(prop)\n"
"\t - prop : A string specifying the property of the frame set up update.\n";
@@ -837,7 +840,7 @@ PyObject* BL_ActionActuator::PyGetChannel(PyObject* self,
*/
/* setChannel */
-char BL_ActionActuator::SetChannel_doc[] =
+const char BL_ActionActuator::SetChannel_doc[] =
"setChannel(channel, matrix)\n"
"\t - channel : A string specifying the name of the bone channel.\n"
"\t - matrix : A 4x4 matrix specifying the overriding transformation\n"
@@ -921,7 +924,7 @@ PyObject* BL_ActionActuator::PySetChannel(PyObject* self,
}
/* getType */
-char BL_ActionActuator::GetType_doc[] =
+const char BL_ActionActuator::GetType_doc[] =
"getType()\n"
"\tReturns the operation mode of the actuator.\n";
PyObject* BL_ActionActuator::PyGetType(PyObject* self,
@@ -931,7 +934,7 @@ PyObject* BL_ActionActuator::PyGetType(PyObject* self,
}
/* setType */
-char BL_ActionActuator::SetType_doc[] =
+const char BL_ActionActuator::SetType_doc[] =
"setType(mode)\n"
"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
"\tSet the operation mode of the actuator.\n";
diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp
index 09f1d9d4d87..d2001212f7d 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.cpp
+++ b/source/gameengine/Converter/BL_ArmatureObject.cpp
@@ -45,7 +45,6 @@
#include <config.h>
#endif
-
BL_ArmatureObject::BL_ArmatureObject(
void* sgReplicationInfo,
SG_Callbacks callbacks,
@@ -53,15 +52,20 @@ BL_ArmatureObject::BL_ArmatureObject(
: KX_GameObject(sgReplicationInfo,callbacks),
m_objArma(armature),
- m_mrdPose(NULL),
- m_lastframe(0.),
+ m_framePose(NULL),
+ m_lastframe(0.0),
m_activeAct(NULL),
- m_activePriority(999)
+ m_activePriority(999),
+ m_lastapplyframe(0.0)
{
m_armature = get_armature(m_objArma);
- m_pose = m_objArma->pose;
-}
+ /* we make a copy of blender object's pose, and then always swap it with
+ * the original pose before calling into blender functions, to deal with
+ * replica's or other objects using the same blender object */
+ m_pose = NULL;
+ game_copy_pose(&m_pose, m_objArma->pose);
+}
CValue* BL_ArmatureObject::GetReplica()
{
@@ -78,34 +82,37 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica)
{
KX_GameObject::ProcessReplica(replica);
+ replica->m_pose = NULL;
+ game_copy_pose(&replica->m_pose, m_pose);
}
BL_ArmatureObject::~BL_ArmatureObject()
{
- if (m_mrdPose)
- free_pose(m_mrdPose);
+ if (m_pose)
+ game_free_pose(m_pose);
}
-/* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */
-/* there is only 1 unique Pose per Armature */
void BL_ArmatureObject::ApplyPose()
{
- if (m_pose) {
- // copy to armature object
- if (m_objArma->pose != m_pose)/* This should never happen but it does - Campbell */
- extract_pose_from_pose(m_objArma->pose, m_pose);
-
- // is this needed anymore?
- //if (!m_mrdPose)
- // copy_pose (&m_mrdPose, m_pose, 0);
- //else
- // extract_pose_from_pose(m_mrdPose, m_pose);
+ m_armpose = m_objArma->pose;
+ m_objArma->pose = m_pose;
+
+ if(m_lastapplyframe != m_lastframe) {
+ where_is_pose(m_objArma);
+ m_lastapplyframe = m_lastframe;
}
}
+void BL_ArmatureObject::RestorePose()
+{
+ m_objArma->pose = m_armpose;
+ m_armpose = NULL;
+}
+
void BL_ArmatureObject::SetPose(bPose *pose)
{
- m_pose = pose;
+ extract_pose_from_pose(m_pose, pose);
+ m_lastapplyframe = -1.0;
}
bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime)
@@ -114,10 +121,15 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority,
m_activePriority = 9999;
m_lastframe= curtime;
m_activeAct = NULL;
+ // remember the pose at the start of the frame
+ m_framePose = m_pose;
}
if (priority<=m_activePriority)
{
+ if (priority<m_activePriority)
+ // this action overwrites the previous ones, start from initial pose to cancel their effects
+ m_pose = m_framePose;
if (m_activeAct && (m_activeAct!=act))
m_activeAct->SetBlendTime(0.0); /* Reset the blend timer */
m_activeAct = act;
@@ -149,13 +161,13 @@ void BL_ArmatureObject::GetPose(bPose **pose)
a crash and memory leakage when
&BL_ActionActuator::m_pose is freed
*/
- int copy_constraint_channels_hack = 1;
- copy_pose(pose, m_pose, copy_constraint_channels_hack);
+ game_copy_pose(pose, m_pose);
}
else {
if (*pose == m_pose)
// no need to copy if the pointers are the same
return;
+
extract_pose_from_pose(*pose, m_pose);
}
}
@@ -165,21 +177,10 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose)
/* If the caller supplies a null pose, create a new one. */
/* Otherwise, copy the armature's pose channels into the caller-supplied pose */
- // is this needed anymore?
- //if (!m_mrdPose){
- // copy_pose (&m_mrdPose, m_pose, 0);
- //}
-
- if (!*pose) {
- // must duplicate the constraints too otherwise we have corruption in free_pose_channels()
- // because it will free the blender constraints.
- // Ideally, blender should rememeber that the constraints were not copied so that
- // free_pose_channels() would not free them.
- copy_pose(pose, m_objArma->pose, 1);
- }
+ if (!*pose)
+ game_copy_pose(pose, m_pose);
else
- extract_pose_from_pose(*pose, m_objArma->pose);
-
+ extract_pose_from_pose(*pose, m_pose);
}
short BL_ArmatureObject::GetActivePriority()
@@ -192,17 +193,17 @@ double BL_ArmatureObject::GetLastFrame()
return m_lastframe;
}
-bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const
+bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix)
{
- Object* par_arma = m_objArma;
- where_is_pose(par_arma);
- bPoseChannel *pchan= get_pose_channel(par_arma->pose, bone->name);
+ bPoseChannel *pchan;
- if(pchan) {
+ ApplyPose();
+ pchan = get_pose_channel(m_objArma->pose, bone->name);
+ if(pchan)
matrix.setValue(&pchan->pose_mat[0][0]);
- return true;
- }
- return false;
+ RestorePose();
+
+ return (pchan != NULL);
}
float BL_ArmatureObject::GetBoneLength(Bone* bone) const
diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h
index 752bd5eb365..d68e37d9e37 100644
--- a/source/gameengine/Converter/BL_ArmatureObject.h
+++ b/source/gameengine/Converter/BL_ArmatureObject.h
@@ -59,7 +59,10 @@ public:
void GetMRDPose(struct bPose **pose);
void GetPose(struct bPose **pose);
void SetPose (struct bPose *pose);
+
void ApplyPose();
+ void RestorePose();
+
bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime);
struct bArmature * GetArmature() { return m_armature; }
@@ -69,7 +72,7 @@ public:
/// Retrieve the pose matrix for the specified bone.
/// Returns true on success.
- bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const;
+ bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix);
/// Returns the bone length. The end of the bone is in the local y direction.
float GetBoneLength(Bone* bone) const;
@@ -79,10 +82,13 @@ protected:
Object *m_objArma;
struct bArmature *m_armature;
struct bPose *m_pose;
- struct bPose *m_mrdPose;
+ struct bPose *m_armpose;
+ struct bPose *m_framePose;
double m_lastframe;
class BL_ActionActuator *m_activeAct;
short m_activePriority;
+
+ double m_lastapplyframe;
};
#endif
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index a6337403cd1..97ed6f4002a 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -129,6 +129,7 @@
#include "DNA_sound_types.h"
#include "DNA_key_types.h"
#include "DNA_armature_types.h"
+#include "DNA_object_force.h"
#include "MEM_guardedalloc.h"
#include "BKE_utildefines.h"
@@ -308,7 +309,7 @@ static void GetRGB(short type,
typedef struct MTF_localLayer
{
MTFace *face;
- char *name;
+ const char *name;
}MTF_localLayer;
// ------------------------------------
@@ -377,6 +378,7 @@ BL_Material* ConvertMaterial(
material->texname[i] = material->img[i]->id.name;
material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0;
material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0;
+ material->flag[i] |= MIPMAP;
if(material->img[i]->flag & IMA_REFLECT)
material->mapping[i].mapping |= USEREFL;
@@ -601,7 +603,6 @@ BL_Material* ConvertMaterial(
(tface->mode & TF_INVISIBLE)
)?POLY_VIS:0;
- material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0;
material->transp = tface->transp;
material->tile = tface->tile;
material->mode = tface->mode;
@@ -617,7 +618,7 @@ BL_Material* ConvertMaterial(
}
else {
// nothing at all
- material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT));
+ material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT));
material->mode = default_face_mode;
material->transp = TF_SOLID;
material->tile = 0;
@@ -627,13 +628,19 @@ BL_Material* ConvertMaterial(
if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID))
material->transp = TF_ALPHA;
- // always zsort alpha + add
- if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha)
- && (material->transp != TF_CLIP)) {
+ // always zsort alpha + add
+ if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) {
material->ras_mode |= ALPHA;
material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0;
}
+ // collider or not?
+ material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0;
+
+ // these flags are irrelevant at this point, remove so they
+ // don't hurt material bucketing
+ material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX);
+
// get uv sets
if(validmat)
{
@@ -644,6 +651,7 @@ BL_Material* ConvertMaterial(
for (int vind = 0; vind<material->num_enabled; vind++)
{
BL_Mapping &map = material->mapping[vind];
+
if (map.uvCoName.IsEmpty())
isFirstSet = false;
else
@@ -673,7 +681,7 @@ BL_Material* ConvertMaterial(
isFirstSet = false;
uvName = layer.name;
}
- else
+ else if(strcmp(layer.name, uvName) != 0)
{
uv2[0] = uvSet[0]; uv2[1] = uvSet[1];
uv2[2] = uvSet[2]; uv2[3] = uvSet[3];
@@ -702,7 +710,6 @@ BL_Material* ConvertMaterial(
material->SetConversionUV(uvName, uv);
material->SetConversionUV2(uv2Name, uv2);
- material->ras_mode |= (mface->v4==0)?TRIANGLE:0;
if(validmat)
material->matname =(mat->id.name);
@@ -737,7 +744,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
}
// Determine if we need to make a skinned mesh
- if (mesh->dvert || mesh->key) {
+ if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0))
+ {
meshobj = new BL_SkinMeshObject(mesh, lightlayer);
skinMesh = true;
}
@@ -767,7 +775,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
}
meshobj->SetName(mesh->id.name);
- meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert);
+ meshobj->m_sharedvertex_map.resize(totvert);
for (int f=0;f<totface;f++,mface++)
{
@@ -777,9 +785,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0);
unsigned int rgb0,rgb1,rgb2,rgb3 = 0;
- MT_Vector3 no0, no1, no2, no3;
MT_Point3 pt0, pt1, pt2, pt3;
- MT_Vector4 tan0, tan1, tan2, tan3;
+ MT_Vector3 no0(0,0,0), no1(0,0,0), no2(0,0,0), no3(0,0,0);
+ MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0);
/* get coordinates, normals and tangents */
pt0 = MT_Point3(mvert[mface->v1].co);
@@ -801,8 +809,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
NormalShortToFloat(n3, mvert[mface->v4].no);
no3 = n3;
}
- else
- no3 = MT_Vector3(0.0, 0.0, 0.0);
}
else {
float fno[3];
@@ -830,7 +836,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
ma = give_current_material(blenderobj, mface->mat_nr+1);
{
- bool polyvisible = true;
+ bool visible = true;
RAS_IPolyMaterial* polymat = NULL;
BL_Material *bl_mat = NULL;
@@ -845,7 +851,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
bl_mat->material_index = (int)mface->mat_nr;
- polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0);
+ visible = ((bl_mat->ras_mode & POLY_VIS)!=0);
collider = ((bl_mat->ras_mode & COLLIDER)!=0);
/* vertex colors and uv's were stored in bl_mat temporarily */
@@ -862,7 +868,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
uv22 = uv[2]; uv23 = uv[3];
/* then the KX_BlenderMaterial */
- polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj );
+ polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer);
}
else {
/* do Texture Face materials */
@@ -886,7 +892,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
tile = tface->tile;
mode = tface->mode;
- polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE));
+ visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE));
uv0 = MT_Point2(tface->uv[0]);
uv1 = MT_Point2(tface->uv[1]);
@@ -940,15 +946,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
rgb3 = KX_rgbaint2uint_new(color);
}
- bool istriangle = (mface->v4==0);
-
// only zsort alpha + add
bool alpha = (transp == TF_ALPHA || transp == TF_ADD);
bool zsort = (mode & TF_ALPHASORT)? alpha: 0;
polymat = new KX_PolygonMaterial(imastr, ma,
tile, tilexrep, tileyrep,
- mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol);
+ mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol);
if (ma) {
polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec;
@@ -961,6 +965,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
}
}
+ /* mark face as flat, so vertices are split */
+ bool flat = (mface->flag & ME_SMOOTH) == 0;
+
// see if a bucket was reused or a new one was created
// this way only one KX_BlenderMaterial object has to exist per bucket
bool bucketCreated;
@@ -981,49 +988,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
polymat = bucket->GetPolyMaterial();
}
- int nverts = mface->v4?4:3;
- int vtxarray = meshobj->FindVertexArray(nverts,polymat);
- RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray);
-
- bool flat;
-
- if (skinMesh) {
- /* If the face is set to solid, all fnors are the same */
- if (mface->flag & ME_SMOOTH)
- flat = false;
- else
- flat = true;
- }
- else
- flat = false;
-
- poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1));
- poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2));
- poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3));
- if (nverts==4)
- poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4));
+ int nverts = (mface->v4)? 4: 3;
+ RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts);
- meshobj->AddPolygon(poly);
- if (poly->IsCollider())
- {
- RAS_TriangleIndex idx;
- idx.m_index[0] = mface->v1;
- idx.m_index[1] = mface->v2;
- idx.m_index[2] = mface->v3;
- idx.m_collider = collider;
- meshobj->m_triangle_indices.push_back(idx);
- if (nverts==4)
- {
- idx.m_index[0] = mface->v1;
- idx.m_index[1] = mface->v3;
- idx.m_index[2] = mface->v4;
- idx.m_collider = collider;
- meshobj->m_triangle_indices.push_back(idx);
- }
- }
-
-// poly->SetVisibleWireframeEdges(mface->edcode);
+ poly->SetVisible(visible);
poly->SetCollider(collider);
+ //poly->SetEdgeCode(mface->edcode);
+
+ meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1);
+ meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2);
+ meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3);
+
+ if (nverts==4)
+ meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4);
}
if (tface)
@@ -1039,13 +1016,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
layer.face++;
}
}
- meshobj->m_xyz_index_to_vertex_index_mapping.clear();
- meshobj->UpdateMaterialList();
+ meshobj->m_sharedvertex_map.clear();
// pre calculate texture generation
- for(RAS_MaterialBucket::Set::iterator mit = meshobj->GetFirstMaterial();
+ for(list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
mit != meshobj->GetLastMaterial(); ++ mit) {
- (*mit)->GetPolyMaterial()->OnConstruction();
+ mit->m_bucket->GetPolyMaterial()->OnConstruction();
}
if (layers)
@@ -1305,6 +1281,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
//int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0);
//bool bRigidBody = (userigidbody == 0);
+ // object has physics representation?
+ if (!(blenderobject->gameflag & OB_COLLISION))
+ return;
+
// get Root Parent of blenderobject
struct Object* parent= blenderobject->parent;
while(parent && parent->parent) {
@@ -1336,19 +1316,97 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_isCompoundChild = isCompoundChild;
objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0;
-
- if ((objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0))
+ objprop.m_margin = blenderobject->margin;
+ // ACTOR is now a separate feature
+ objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0;
+ objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
+ objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
+ objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
+
+ if (objprop.m_softbody)
{
- objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
- objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
- objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0;
- objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag
- } else {
- objprop.m_dyna = false;
- objprop.m_angular_rigidbody = false;
- objprop.m_ghost = false;
- objprop.m_disableSleeping = false;
+ ///for game soft bodies
+ if (blenderobject->bsoft)
+ {
+ objprop.m_gamesoftFlag = blenderobject->bsoft->flag;
+ ///////////////////
+ objprop.m_soft_linStiff = blenderobject->bsoft->linStiff;
+ objprop.m_soft_angStiff = blenderobject->bsoft->angStiff; /* angular stiffness 0..1 */
+ objprop.m_soft_volume= blenderobject->bsoft->volume; /* volume preservation 0..1 */
+
+ objprop.m_soft_viterations= blenderobject->bsoft->viterations; /* Velocities solver iterations */
+ objprop.m_soft_piterations= blenderobject->bsoft->piterations; /* Positions solver iterations */
+ objprop.m_soft_diterations= blenderobject->bsoft->diterations; /* Drift solver iterations */
+ objprop.m_soft_citerations= blenderobject->bsoft->citerations; /* Cluster solver iterations */
+
+ objprop.m_soft_kSRHR_CL= blenderobject->bsoft->kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
+ objprop.m_soft_kSKHR_CL= blenderobject->bsoft->kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
+ objprop.m_soft_kSSHR_CL= blenderobject->bsoft->kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
+ objprop.m_soft_kSR_SPLT_CL= blenderobject->bsoft->kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+
+ objprop.m_soft_kSK_SPLT_CL= blenderobject->bsoft->kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ objprop.m_soft_kSS_SPLT_CL= blenderobject->bsoft->kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ objprop.m_soft_kVCF= blenderobject->bsoft->kVCF; /* Velocities correction factor (Baumgarte) */
+ objprop.m_soft_kDP= blenderobject->bsoft->kDP; /* Damping coefficient [0,1] */
+
+ objprop.m_soft_kDG= blenderobject->bsoft->kDG; /* Drag coefficient [0,+inf] */
+ objprop.m_soft_kLF= blenderobject->bsoft->kLF; /* Lift coefficient [0,+inf] */
+ objprop.m_soft_kPR= blenderobject->bsoft->kPR; /* Pressure coefficient [-inf,+inf] */
+ objprop.m_soft_kVC= blenderobject->bsoft->kVC; /* Volume conversation coefficient [0,+inf] */
+
+ objprop.m_soft_kDF= blenderobject->bsoft->kDF; /* Dynamic friction coefficient [0,1] */
+ objprop.m_soft_kMT= blenderobject->bsoft->kMT; /* Pose matching coefficient [0,1] */
+ objprop.m_soft_kCHR= blenderobject->bsoft->kCHR; /* Rigid contacts hardness [0,1] */
+ objprop.m_soft_kKHR= blenderobject->bsoft->kKHR; /* Kinetic contacts hardness [0,1] */
+
+ objprop.m_soft_kSHR= blenderobject->bsoft->kSHR; /* Soft contacts hardness [0,1] */
+ objprop.m_soft_kAHR= blenderobject->bsoft->kAHR; /* Anchors hardness [0,1] */
+ objprop.m_soft_collisionflags= blenderobject->bsoft->collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
+ objprop.m_soft_numclusteriterations= blenderobject->bsoft->numclusteriterations; /* number of iterations to refine collision clusters*/
+
+ } else
+ {
+ objprop.m_gamesoftFlag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT;
+
+ 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 */
+
+
+ objprop.m_soft_viterations= 0;
+ objprop.m_soft_piterations= 1;
+ objprop.m_soft_diterations= 0;
+ objprop.m_soft_citerations= 4;
+
+ objprop.m_soft_kSRHR_CL= 0.1f;
+ objprop.m_soft_kSKHR_CL= 1.f;
+ objprop.m_soft_kSSHR_CL= 0.5;
+ objprop.m_soft_kSR_SPLT_CL= 0.5f;
+
+ objprop.m_soft_kSK_SPLT_CL= 0.5f;
+ objprop.m_soft_kSS_SPLT_CL= 0.5f;
+ objprop.m_soft_kVCF= 1;
+ objprop.m_soft_kDP= 0;
+
+ objprop.m_soft_kDG= 0;
+ objprop.m_soft_kLF= 0;
+ objprop.m_soft_kPR= 0;
+ objprop.m_soft_kVC= 0;
+
+ objprop.m_soft_kDF= 0.2f;
+ objprop.m_soft_kMT= 0.05f;
+ objprop.m_soft_kCHR= 1.0f;
+ objprop.m_soft_kKHR= 0.1f;
+
+ objprop.m_soft_kSHR= 1.f;
+ objprop.m_soft_kAHR= 0.7f;
+ objprop.m_soft_collisionflags= OB_BSB_COL_SDF_RS + OB_BSB_COL_VF_SS;
+ objprop.m_soft_numclusteriterations= 16;
+ }
}
+
+ objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0;
+ objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag
//mmm, for now, taks this for the size of the dynamicobject
// Blender uses inertia for radius of dynamic object
objprop.m_radius = blenderobject->inertia;
@@ -1356,6 +1414,12 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_dynamic_parent=NULL;
objprop.m_isdeformable = ((blenderobject->gameflag2 & 2)) != 0;
objprop.m_boundclass = objprop.m_dyna?KX_BOUNDSPHERE:KX_BOUNDMESH;
+
+ if ((blenderobject->gameflag & OB_SOFT_BODY) && !(blenderobject->gameflag & OB_BOUNDS))
+ {
+ objprop.m_boundclass = KX_BOUNDMESH;
+ }
+
KX_BoxBounds bb;
my_get_local_bounds(blenderobject,objprop.m_boundobject.box.m_center,bb.m_extends);
if (blenderobject->gameflag & OB_BOUNDS)
@@ -1490,14 +1554,9 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l
lightobj.m_type = RAS_LightObject::LIGHT_NORMAL;
}
-#ifdef BLENDER_GLSL
- if(converter->GetGLSLMaterials())
- GPU_lamp_from_blender(ob, la);
-
- gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, ob->gpulamp);
-#else
- gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, NULL);
-#endif
+ gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools,
+ lightobj, converter->GetGLSLMaterials());
+
BL_ConvertLampIpos(la, gamelight, converter);
return gamelight;
@@ -1534,7 +1593,7 @@ static KX_GameObject *gameobject_from_blenderobject(
gamelight->AddRef();
kxscene->GetLightList()->Add(gamelight);
-
+
break;
}
@@ -1586,20 +1645,20 @@ static KX_GameObject *gameobject_from_blenderobject(
// not that we can have shape keys without dvert!
BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
- ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
+ ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
if (bHasArmature)
dcont->LoadShapeDrivers(ob->parent);
} else if (bHasArmature) {
BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
- ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
+ ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
} else if (bHasDvert) {
// this case correspond to a mesh that can potentially deform but not with the
// object to which it is attached for the moment. A skin mesh was created in
// BL_ConvertMesh() so must create a deformer too!
BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj,
ob, (BL_SkinMeshObject*)meshobj);
- ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
+ ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont);
}
MT_Point3 min = MT_Point3(center) - MT_Vector3(extents);
@@ -1634,6 +1693,8 @@ static KX_GameObject *gameobject_from_blenderobject(
gameobj->SetPhysicsEnvironment(kxscene->GetPhysicsEnvironment());
gameobj->SetLayer(ob->lay);
gameobj->SetBlenderObject(ob);
+ /* set the visibility state based on the objects render option in the outliner */
+ if(ob->restrictflag & OB_RESTRICT_RENDER) gameobj->SetVisible(0, 0);
}
return gameobj;
}
@@ -1643,20 +1704,6 @@ struct parentChildLink {
SG_Node* m_gamechildnode;
};
- /**
- * Find the specified scene by name, or the first
- * scene if nothing matches (shouldn't happen).
- */
-static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scenename) {
- Scene *sce;
-
- for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
- if (scenename == (sce->id.name+2))
- return sce;
-
- return (Scene*) maggie->scene.first;
-}
-
#include "DNA_constraint_types.h"
#include "BIF_editconstraint.h"
@@ -1755,7 +1802,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
)
{
- Scene *blenderscene = GetSceneForName(maggie, scenename);
+ Scene *blenderscene = converter->GetBlenderSceneForName(scenename);
// for SETLOOPER
Scene *sce;
Base *base;
@@ -1946,10 +1993,22 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
//parentinversenode->SetLocalOrientation(parinvtrans.getBasis());
// Extract the rotation and the scaling from the basis
- MT_Matrix3x3 inverseOrientation(parinvtrans.getRotation());
- parentinversenode->SetLocalOrientation(inverseOrientation);
- MT_Matrix3x3 scale(inverseOrientation.transposed()*parinvtrans.getBasis());
- parentinversenode->SetLocalScale(MT_Vector3(scale[0][0], scale[1][1], scale[2][2]));
+ MT_Matrix3x3 ori(parinvtrans.getBasis());
+ MT_Vector3 x(ori.getColumn(0));
+ MT_Vector3 y(ori.getColumn(1));
+ MT_Vector3 z(ori.getColumn(2));
+ MT_Vector3 scale(x.length(), y.length(), z.length());
+ if (!MT_fuzzyZero(scale[0]))
+ x /= scale[0];
+ if (!MT_fuzzyZero(scale[1]))
+ y /= scale[1];
+ if (!MT_fuzzyZero(scale[2]))
+ z /= scale[2];
+ ori.setColumn(0, x);
+ ori.setColumn(1, y);
+ ori.setColumn(2, z);
+ parentinversenode->SetLocalOrientation(ori);
+ parentinversenode->SetLocalScale(scale);
parentinversenode->AddChild(gameobj->GetSGNode());
}
@@ -1978,7 +2037,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
//tf.Add(gameobj->GetSGNode());
gameobj->NodeUpdateGS(0,true);
- gameobj->Bucketize();
+ gameobj->AddMeshUser();
}
else
@@ -2129,7 +2188,24 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
float* fl = (float*) blenderobject->parentinv;
MT_Transform parinvtrans(fl);
parentinversenode->SetLocalPosition(parinvtrans.getOrigin());
- parentinversenode->SetLocalOrientation(parinvtrans.getBasis());
+
+ // Extract the rotation and the scaling from the basis
+ MT_Matrix3x3 ori(parinvtrans.getBasis());
+ MT_Vector3 x(ori.getColumn(0));
+ MT_Vector3 y(ori.getColumn(1));
+ MT_Vector3 z(ori.getColumn(2));
+ MT_Vector3 scale(x.length(), y.length(), z.length());
+ if (!MT_fuzzyZero(scale[0]))
+ x /= scale[0];
+ if (!MT_fuzzyZero(scale[1]))
+ y /= scale[1];
+ if (!MT_fuzzyZero(scale[2]))
+ z /= scale[2];
+ ori.setColumn(0, x);
+ ori.setColumn(1, y);
+ ori.setColumn(2, z);
+ parentinversenode->SetLocalOrientation(ori);
+ parentinversenode->SetLocalScale(scale);
parentinversenode->AddChild(gameobj->GetSGNode());
}
@@ -2158,8 +2234,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
//tf.Add(gameobj->GetSGNode());
gameobj->NodeUpdateGS(0,true);
- gameobj->Bucketize();
-
+ gameobj->AddMeshUser();
}
else
{
@@ -2201,16 +2276,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
for(oit=allblobj.begin(); oit!=allblobj.end(); oit++)
{
Object* blenderobj = *oit;
- if (blenderobj->type==OB_MESH){
+ if (blenderobj->type==OB_MESH) {
Mesh *me = (Mesh*)blenderobj->data;
if (me->dvert){
- KX_GameObject *obj = converter->FindGameObject(blenderobj);
+ BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj);
if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){
KX_GameObject *par = converter->FindGameObject(blenderobj->parent);
- if (par)
- ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par);
+ if (par && obj->GetDeformer())
+ ((BL_SkinDeformer*)obj->GetDeformer())->SetArmature((BL_ArmatureObject*) par);
}
}
}
@@ -2224,6 +2299,41 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
{
struct Object* blenderchild = pcit->m_blenderchild;
+ struct Object* blenderparent = blenderchild->parent;
+ KX_GameObject* parentobj = converter->FindGameObject(blenderparent);
+ KX_GameObject* childobj = converter->FindGameObject(blenderchild);
+
+ assert(childobj);
+
+ if (!parentobj || objectlist->SearchValue(childobj) != objectlist->SearchValue(parentobj))
+ {
+ // special case: the parent and child object are not in the same layer.
+ // This weird situation is used in Apricot for test purposes.
+ // Resolve it by not converting the child
+ childobj->GetSGNode()->DisconnectFromParent();
+ delete pcit->m_gamechildnode;
+ // Now destroy the child object but also all its descendent that may already be linked
+ // Remove the child reference in the local list!
+ // Note: there may be descendents already if the children of the child were processed
+ // by this loop before the child. In that case, we must remove the children also
+ CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj);
+ childrenlist->Add(childobj->AddRef());
+ for ( i=0;i<childrenlist->GetCount();i++)
+ {
+ KX_GameObject* obj = static_cast<KX_GameObject*>(childrenlist->GetValue(i));
+ if (templist->RemoveValue(obj))
+ obj->Release();
+ if (sumolist->RemoveValue(obj))
+ obj->Release();
+ if (logicbrick_conversionlist->RemoveValue(obj))
+ obj->Release();
+ }
+ childrenlist->Release();
+ // now destroy recursively
+ kxscene->RemoveObject(childobj);
+ continue;
+ }
+
switch (blenderchild->partype)
{
case PARVERT1:
@@ -2244,8 +2354,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
{
// parent this to a bone
Bone *parent_bone = get_named_bone(get_armature(blenderchild->parent), blenderchild->parsubstr);
- KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone);
- pcit->m_gamechildnode->SetParentRelation(bone_parent_relation);
+
+ if(parent_bone) {
+ KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone);
+ pcit->m_gamechildnode->SetParentRelation(bone_parent_relation);
+ }
break;
}
@@ -2260,12 +2373,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
break;
}
- struct Object* blenderparent = blenderchild->parent;
- KX_GameObject* parentobj = converter->FindGameObject(blenderparent);
- if (parentobj)
- {
- parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode);
- }
+ parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode);
}
vec_parent_child.clear();
@@ -2450,7 +2558,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
struct Object* blenderobj = converter->FindBlenderObject(gameobj);
int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0;
bool isInActiveLayer = (blenderobj->lay & layerMask)!=0;
- BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter);
+ BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter);
// set the init state to all objects
gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
}
@@ -2482,5 +2590,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
kxscene->DupliGroupRecurse(gameobj, 0);
}
}
+
+ KX_Camera *activecam = kxscene->GetActiveCamera();
+ MT_Scalar distance = (activecam)? activecam->GetCameraFar() - activecam->GetCameraNear(): 100.0f;
+ RAS_BucketManager *bucketmanager = kxscene->GetBucketManager();
+ bucketmanager->OptimizeBuckets(distance);
}
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp
index d23274324ee..e2610d2b405 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.cpp
+++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp
@@ -41,12 +41,14 @@ BL_DeformableGameObject::~BL_DeformableGameObject()
delete m_pDeformer; // __NLA : Temporary until we decide where to put this
}
-void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica)
+void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica)
{
+ BL_MeshDeformer *deformer;
KX_GameObject::ProcessReplica(replica);
- if (m_pDeformer){
- ((BL_DeformableGameObject*)replica)->m_pDeformer = m_pDeformer->GetReplica();
+ if (m_pDeformer) {
+ deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(replica);
+ ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer;
}
}
diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h
index 315ad18c42c..126a1fcb1e7 100644
--- a/source/gameengine/Converter/BL_DeformableGameObject.h
+++ b/source/gameengine/Converter/BL_DeformableGameObject.h
@@ -83,9 +83,21 @@ public:
return (m_pDeformer) ? ((BL_MeshDeformer*)m_pDeformer)->GetMesh()->key : NULL;
}
+ virtual void SetDeformer(class RAS_Deformer* deformer)
+ {
+ m_pDeformer = deformer;
+ }
+ virtual class RAS_Deformer* GetDeformer()
+ {
+ return m_pDeformer;
+ }
+
public:
- RAS_Deformer *m_pDeformer;
+
protected:
+
+ RAS_Deformer *m_pDeformer;
+
class BL_ShapeActionActuator *m_activeAct;
double m_lastframe;
Object* m_blendobj;
diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp
index 39d66a90e92..fa3b8185fe2 100644
--- a/source/gameengine/Converter/BL_MeshDeformer.cpp
+++ b/source/gameengine/Converter/BL_MeshDeformer.cpp
@@ -50,26 +50,26 @@
bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
{
- size_t i, j;
+ size_t i;
float *co;
// only apply once per frame if the mesh is actually modified
if(m_pMeshObject->MeshModified() &&
m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
// For each material
- for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial();
+ for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial();
mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
- RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial();
+ if(!mit->m_slots[(void*)m_gameobj])
+ continue;
- vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat);
-
- // For each array
- for (i=0; i<vertexarrays.size(); i++){
- KX_VertexArray& vertexarray = (*vertexarrays[i]);
+ RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
+ RAS_MeshSlot::iterator it;
+ // for each array
+ for(slot->begin(it); !slot->end(it); slot->next(it)) {
// For each vertex
- for (j=0; j<vertexarray.size(); j++){
- RAS_TexVert& v = vertexarray[j];
+ for(i=it.startvertex; i<it.endvertex; i++) {
+ RAS_TexVert& v = it.vertex[i];
co = m_bmesh->mvert[v.getOrigIndex()].co;
v.SetXYZ(MT_Point3(co));
}
@@ -90,7 +90,17 @@ BL_MeshDeformer::~BL_MeshDeformer()
delete [] m_transverts;
if (m_transnors)
delete [] m_transnors;
-};
+}
+
+void BL_MeshDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
+{
+ void **h_obj = (*map)[m_gameobj];
+
+ if (h_obj)
+ m_gameobj = (BL_DeformableGameObject*)(*h_obj);
+ else
+ m_gameobj = NULL;
+}
/**
* @warning This function is expensive!
@@ -101,41 +111,41 @@ void BL_MeshDeformer::RecalcNormals()
* gives area-weight normals which often look better anyway, and use
* GL_NORMALIZE so we don't have to do per vertex normalization either
* since the GPU can do it faster */
- size_t i, j;
+ list<RAS_MeshMaterial>::iterator mit;
+ RAS_MeshSlot::iterator it;
+ size_t i;
/* set vertex normals to zero */
memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert);
/* add face normals to vertices. */
- for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial();
+ for(mit = m_pMeshObject->GetFirstMaterial();
mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
- RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial();
+ if(!mit->m_slots[(void*)m_gameobj])
+ continue;
- const vecIndexArrays& indexarrays = m_pMeshObject->GetIndexCache(mat);
- vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat);
+ RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
- for (i=0; i<indexarrays.size(); i++) {
- KX_VertexArray& vertexarray = (*vertexarrays[i]);
- const KX_IndexArray& indexarray = (*indexarrays[i]);
- int nvert = mat->UsesTriangles()? 3: 4;
+ for(slot->begin(it); !slot->end(it); slot->next(it)) {
+ int nvert = (int)it.array->m_type;
- for(j=0; j<indexarray.size(); j+=nvert) {
- RAS_TexVert& v1 = vertexarray[indexarray[j]];
- RAS_TexVert& v2 = vertexarray[indexarray[j+1]];
- RAS_TexVert& v3 = vertexarray[indexarray[j+2]];
+ for(i=0; i<it.totindex; i+=nvert) {
+ RAS_TexVert& v1 = it.vertex[it.index[i]];
+ RAS_TexVert& v2 = it.vertex[it.index[i+1]];
+ RAS_TexVert& v3 = it.vertex[it.index[i+2]];
RAS_TexVert *v4 = NULL;
- const float *co1 = v1.getLocalXYZ();
- const float *co2 = v2.getLocalXYZ();
- const float *co3 = v3.getLocalXYZ();
+ const float *co1 = v1.getXYZ();
+ const float *co2 = v2.getXYZ();
+ const float *co3 = v3.getXYZ();
const float *co4 = NULL;
/* compute face normal */
float fnor[3], n1[3], n2[3];
if(nvert == 4) {
- v4 = &vertexarray[indexarray[j+3]];
- co4 = v4->getLocalXYZ();
+ v4 = &it.vertex[it.index[i+3]];
+ co4 = v4->getXYZ();
n1[0]= co1[0]-co3[0];
n1[1]= co1[1]-co3[1];
@@ -174,7 +184,7 @@ void BL_MeshDeformer::RecalcNormals()
}
/* in case of flat - just assign, the vertices are split */
- if(v1.getFlag() & TV_CALCFACENORMAL) {
+ if(v1.getFlag() & RAS_TexVert::FLAT) {
v1.SetNormal(fnor);
v2.SetNormal(fnor);
v3.SetNormal(fnor);
@@ -186,19 +196,18 @@ void BL_MeshDeformer::RecalcNormals()
}
/* assign smooth vertex normals */
- for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial();
+ for(mit = m_pMeshObject->GetFirstMaterial();
mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
- RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial();
+ if(!mit->m_slots[(void*)m_gameobj])
+ continue;
- vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat);
+ RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
- for (i=0; i<vertexarrays.size(); i++) {
- KX_VertexArray& vertexarray = (*vertexarrays[i]);
-
- for(j=0; j<vertexarray.size(); j++) {
- RAS_TexVert& v = vertexarray[j];
+ for(slot->begin(it); !slot->end(it); slot->next(it)) {
+ for(i=it.startvertex; i<it.endvertex; i++) {
+ RAS_TexVert& v = it.vertex[i];
- if(!(v.getFlag() & TV_CALCFACENORMAL))
+ if(!(v.getFlag() & RAS_TexVert::FLAT))
v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized()
}
}
@@ -219,4 +228,4 @@ void BL_MeshDeformer::VerifyStorage()
m_tvtot = m_bmesh->totvert;
}
}
-
+
diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h
index e9f7f0b192f..8de59c1cdf3 100644
--- a/source/gameengine/Converter/BL_MeshDeformer.h
+++ b/source/gameengine/Converter/BL_MeshDeformer.h
@@ -47,7 +47,7 @@ class BL_MeshDeformer : public RAS_Deformer
public:
void VerifyStorage();
void RecalcNormals();
- virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map){};
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map);
BL_MeshDeformer(BL_DeformableGameObject *gameobj,
struct Object* obj,
class BL_SkinMeshObject *meshobj ):
@@ -64,9 +64,10 @@ public:
virtual void SetSimulatedTime(double time){};
virtual bool Apply(class RAS_IPolyMaterial *mat);
virtual bool Update(void){ return false; };
- virtual RAS_Deformer* GetReplica(){return NULL;};
+ virtual RAS_Deformer* GetReplica(class KX_GameObject* replica){return NULL;};
struct Mesh* GetMesh() { return m_bmesh; };
// virtual void InitDeform(double time){};
+
protected:
class BL_SkinMeshObject* m_pMeshObject;
struct Mesh* m_bmesh;
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
index 0f976bfb842..cbaa8668b26 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp
@@ -1,3 +1,4 @@
+<<<<<<< .working
/**
* $Id:BL_ShapeActionActuator.cpp 15330 2008-06-23 16:37:51Z theeth $
*
@@ -91,6 +92,102 @@ bool BL_ShapeActionActuator::ClampLocalTime()
{
m_localtime = m_endframe;
return true;
+=======
+/**
+* $Id$
+*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+#if defined (__sgi)
+#include <math.h>
+#else
+#include <cmath>
+#endif
+
+#include "SCA_LogicManager.h"
+#include "BL_ShapeActionActuator.h"
+#include "BL_ActionActuator.h"
+#include "BL_ShapeDeformer.h"
+#include "KX_GameObject.h"
+#include "STR_HashedString.h"
+#include "DNA_action_types.h"
+#include "DNA_nla_types.h"
+#include "DNA_actuator_types.h"
+#include "BKE_action.h"
+#include "DNA_armature_types.h"
+#include "MEM_guardedalloc.h"
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "MT_Matrix4x4.h"
+#include "BKE_utildefines.h"
+#include "FloatValue.h"
+#include "PyObjectPlus.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+BL_ShapeActionActuator::~BL_ShapeActionActuator()
+{
+}
+
+void BL_ShapeActionActuator::ProcessReplica()
+{
+ m_localtime=m_startframe;
+ m_lastUpdate=-1;
+}
+
+void BL_ShapeActionActuator::SetBlendTime (float newtime)
+{
+ m_blendframe = newtime;
+}
+
+CValue* BL_ShapeActionActuator::GetReplica()
+{
+ BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName());
+ replica->ProcessReplica();
+
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+}
+
+bool BL_ShapeActionActuator::ClampLocalTime()
+{
+ if (m_startframe < m_endframe) {
+ if (m_localtime < m_startframe)
+ {
+ m_localtime = m_startframe;
+ return true;
+ }
+ else if (m_localtime > m_endframe)
+ {
+ m_localtime = m_endframe;
+ return true;
}
} else {
if (m_localtime > m_startframe)
@@ -134,7 +231,6 @@ void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight)
{
vector<float>::const_iterator it;
float dstweight;
- int i;
KeyBlock *kb;
dstweight = 1.0F - srcweight;
@@ -155,6 +251,8 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
bool apply=true;
int priority;
float newweight;
+
+ curtime -= KX_KetsjiEngine::GetSuspendedDelta();
// result = true if animation has to be continued, false if animation stops
// maybe there are events for us in the queue !
@@ -340,6 +438,19 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame)
break;
}
+ /* 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);
+>>>>>>> .merge-right.r16886
+ }
+ newval->Release();
+ }
if (bNegativeEvent)
m_blendframe=0.0f;
@@ -433,24 +544,26 @@ PyParentObject BL_ShapeActionActuator::Parents[] = {
};
PyMethodDef BL_ShapeActionActuator::Methods[] = {
- {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, SetAction_doc},
- {"setStart", (PyCFunction) BL_ShapeActionActuator::sPySetStart, METH_VARARGS, SetStart_doc},
- {"setEnd", (PyCFunction) BL_ShapeActionActuator::sPySetEnd, METH_VARARGS, SetEnd_doc},
- {"setBlendin", (PyCFunction) BL_ShapeActionActuator::sPySetBlendin, METH_VARARGS, SetBlendin_doc},
- {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc},
- {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc},
- {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc},
-
- {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc},
- {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, GetStart_doc},
- {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, GetEnd_doc},
- {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, GetBlendin_doc},
- {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc},
- {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc},
- {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc},
- {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc},
- {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc},
+ {"setAction", (PyCFunction) BL_ShapeActionActuator::sPySetAction, METH_VARARGS, (PY_METHODCHAR)SetAction_doc},
+ {"setStart", (PyCFunction) BL_ShapeActionActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc},
+ {"setEnd", (PyCFunction) BL_ShapeActionActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc},
+ {"setBlendin", (PyCFunction) BL_ShapeActionActuator::sPySetBlendin, METH_VARARGS, (PY_METHODCHAR)SetBlendin_doc},
+ {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, (PY_METHODCHAR)SetPriority_doc},
+ {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, (PY_METHODCHAR)SetFrame_doc},
+ {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"setFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPySetFrameProperty, METH_VARARGS, (PY_METHODCHAR)SetFrameProperty_doc},
+ {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, (PY_METHODCHAR)SetBlendtime_doc},
+
+ {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, (PY_METHODCHAR)GetAction_doc},
+ {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, (PY_METHODCHAR)GetStart_doc},
+ {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, (PY_METHODCHAR)GetEnd_doc},
+ {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, (PY_METHODCHAR)GetBlendin_doc},
+ {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, (PY_METHODCHAR)GetPriority_doc},
+ {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, (PY_METHODCHAR)GetFrame_doc},
+ {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"getFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetFrameProperty, METH_NOARGS, (PY_METHODCHAR)GetFrameProperty_doc},
+ {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc},
+ {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, (PY_METHODCHAR)SetType_doc},
{NULL,NULL} //Sentinel
};
@@ -459,7 +572,7 @@ PyObject* BL_ShapeActionActuator::_getattr(const STR_String& attr) {
}
/* setStart */
-char BL_ShapeActionActuator::GetAction_doc[] =
+const char BL_ShapeActionActuator::GetAction_doc[] =
"getAction()\n"
"\tReturns a string containing the name of the current action.\n";
@@ -471,7 +584,7 @@ PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) {
}
/* getProperty */
-char BL_ShapeActionActuator::GetProperty_doc[] =
+const char BL_ShapeActionActuator::GetProperty_doc[] =
"getProperty()\n"
"\tReturns the name of the property to be used in FromProp mode.\n";
@@ -484,7 +597,7 @@ PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) {
}
/* getFrame */
-char BL_ShapeActionActuator::GetFrame_doc[] =
+const char BL_ShapeActionActuator::GetFrame_doc[] =
"getFrame()\n"
"\tReturns the current frame number.\n";
@@ -497,7 +610,7 @@ PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) {
}
/* getEnd */
-char BL_ShapeActionActuator::GetEnd_doc[] =
+const char BL_ShapeActionActuator::GetEnd_doc[] =
"getEnd()\n"
"\tReturns the last frame of the action.\n";
@@ -510,7 +623,7 @@ PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) {
}
/* getStart */
-char BL_ShapeActionActuator::GetStart_doc[] =
+const char BL_ShapeActionActuator::GetStart_doc[] =
"getStart()\n"
"\tReturns the starting frame of the action.\n";
@@ -523,7 +636,7 @@ PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) {
}
/* getBlendin */
-char BL_ShapeActionActuator::GetBlendin_doc[] =
+const char BL_ShapeActionActuator::GetBlendin_doc[] =
"getBlendin()\n"
"\tReturns the number of interpolation animation frames to be\n"
"\tgenerated when this actuator is triggered.\n";
@@ -537,7 +650,7 @@ PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) {
}
/* getPriority */
-char BL_ShapeActionActuator::GetPriority_doc[] =
+const char BL_ShapeActionActuator::GetPriority_doc[] =
"getPriority()\n"
"\tReturns the priority for this actuator. Actuators with lower\n"
"\tPriority numbers will override actuators with higher numbers.\n";
@@ -551,7 +664,7 @@ PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) {
}
/* setAction */
-char BL_ShapeActionActuator::SetAction_doc[] =
+const char BL_ShapeActionActuator::SetAction_doc[] =
"setAction(action, (reset))\n"
"\t - action : The name of the action to set as the current action.\n"
"\t Should be an action with Shape channels.\n"
@@ -591,7 +704,7 @@ PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self,
}
/* setStart */
-char BL_ShapeActionActuator::SetStart_doc[] =
+const char BL_ShapeActionActuator::SetStart_doc[] =
"setStart(start)\n"
"\t - start : Specifies the starting frame of the animation.\n";
@@ -612,7 +725,7 @@ PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self,
}
/* setEnd */
-char BL_ShapeActionActuator::SetEnd_doc[] =
+const char BL_ShapeActionActuator::SetEnd_doc[] =
"setEnd(end)\n"
"\t - end : Specifies the ending frame of the animation.\n";
@@ -633,7 +746,7 @@ PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self,
}
/* setBlendin */
-char BL_ShapeActionActuator::SetBlendin_doc[] =
+const char BL_ShapeActionActuator::SetBlendin_doc[] =
"setBlendin(blendin)\n"
"\t - blendin : Specifies the number of frames of animation to generate\n"
"\t when making transitions between actions.\n";
@@ -655,7 +768,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self,
}
/* setBlendtime */
-char BL_ShapeActionActuator::SetBlendtime_doc[] =
+const char BL_ShapeActionActuator::SetBlendtime_doc[] =
"setBlendtime(blendtime)\n"
"\t - blendtime : Allows the script to directly modify the internal timer\n"
"\t used when generating transitions between actions. This\n"
@@ -682,7 +795,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self,
}
/* setPriority */
-char BL_ShapeActionActuator::SetPriority_doc[] =
+const char BL_ShapeActionActuator::SetPriority_doc[] =
"setPriority(priority)\n"
"\t - priority : Specifies the new priority. Actuators will lower\n"
"\t priority numbers will override actuators with higher\n"
@@ -704,8 +817,22 @@ PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self,
Py_RETURN_NONE;
}
+/* getProperty */
+const char BL_ShapeActionActuator::GetFrameProperty_doc[] =
+"getFrameProperty()\n"
+"\tReturns the name of the property, that is set to the current frame number.\n";
+
+PyObject* BL_ShapeActionActuator::PyGetFrameProperty(PyObject* self) {
+ PyObject *result;
+
+ result = Py_BuildValue("s", (const char *)m_framepropname);
+
+ return result;
+}
+
+
/* setFrame */
-char BL_ShapeActionActuator::SetFrame_doc[] =
+const char BL_ShapeActionActuator::SetFrame_doc[] =
"setFrame(frame)\n"
"\t - frame : Specifies the new current frame for the animation\n";
@@ -730,7 +857,7 @@ PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self,
}
/* setProperty */
-char BL_ShapeActionActuator::SetProperty_doc[] =
+const char BL_ShapeActionActuator::SetProperty_doc[] =
"setProperty(prop)\n"
"\t - prop : A string specifying the property name to be used in\n"
"\t FromProp playback mode.\n";
@@ -751,8 +878,29 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self,
Py_RETURN_NONE;
}
+/* setFrameProperty */
+const char BL_ShapeActionActuator::SetFrameProperty_doc[] =
+"setFrameProperty(prop)\n"
+"\t - prop : A string specifying the property of the frame set up update.\n";
+
+PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ char *string;
+
+ if (PyArg_ParseTuple(args,"s",&string))
+ {
+ m_framepropname = string;
+ }
+ else {
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
/* getType */
-char BL_ShapeActionActuator::GetType_doc[] =
+const char BL_ShapeActionActuator::GetType_doc[] =
"getType()\n"
"\tReturns the operation mode of the actuator.\n";
PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) {
@@ -760,7 +908,7 @@ PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) {
}
/* setType */
-char BL_ShapeActionActuator::SetType_doc[] =
+const char BL_ShapeActionActuator::SetType_doc[] =
"setType(mode)\n"
"\t - mode: Play (0), Flipper (2), LoopStop (3), LoopEnd (4) or Property (6)\n"
"\tSet the operation mode of the actuator.\n";
diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h
index 10cbe9f1ac3..92f75d12764 100644
--- a/source/gameengine/Converter/BL_ShapeActionActuator.h
+++ b/source/gameengine/Converter/BL_ShapeActionActuator.h
@@ -42,6 +42,7 @@ public:
Py_Header;
BL_ShapeActionActuator(SCA_IObject* gameobj,
const STR_String& propname,
+ const STR_String& framepropname,
float starttime,
float endtime,
struct bAction *action,
@@ -66,6 +67,7 @@ public:
m_playtype(playtype),
m_priority(priority),
m_action(action),
+ m_framepropname(framepropname),
m_propname(propname)
{
};
@@ -84,6 +86,7 @@ public:
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetEnd);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrame);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetProperty);
+ KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrameProperty);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel);
@@ -94,6 +97,7 @@ public:
KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetEnd);
KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrame);
KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetProperty);
+ KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrameProperty);
// KX_PYMETHOD(BL_ActionActuator,GetChannel);
KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType);
KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType);
@@ -126,6 +130,7 @@ protected:
short m_priority;
struct bAction *m_action;
STR_String m_propname;
+ STR_String m_framepropname;
vector<float> m_blendshape;
};
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp
index d3fbb795b23..264deb26eb0 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.cpp
+++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp
@@ -68,7 +68,7 @@ BL_ShapeDeformer::~BL_ShapeDeformer()
{
};
-RAS_Deformer *BL_ShapeDeformer::GetReplica()
+RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica)
{
BL_ShapeDeformer *result;
@@ -109,12 +109,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void)
vector<IpoCurve*>::iterator it;
void *poin;
int type;
+
// the shape drivers use the bone matrix as input. Must
// update the matrix now
- Object* par_arma = m_armobj->GetArmatureObject();
m_armobj->ApplyPose();
- where_is_pose( par_arma );
- PoseApplied(true);
for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) {
// no need to set a specific time: this curve has a driver
@@ -124,7 +122,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void)
if (poin)
write_ipo_poin(poin, type, icu->curval);
}
+
ForceUpdate();
+ m_armobj->RestorePose();
+
return true;
}
return false;
diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h
index d3d699b8ddc..b5443ae4dd1 100644
--- a/source/gameengine/Converter/BL_ShapeDeformer.h
+++ b/source/gameengine/Converter/BL_ShapeDeformer.h
@@ -43,17 +43,6 @@ struct IpoCurve;
class BL_ShapeDeformer : public BL_SkinDeformer
{
public:
- virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
- {
- void **h_obj = (*map)[m_gameobj];
- if (h_obj){
- m_gameobj = (BL_DeformableGameObject*)(*h_obj);
- }
- else
- m_gameobj=NULL;
- // relink the underlying skin deformer
- BL_SkinDeformer::Relink(map);
- };
BL_ShapeDeformer(BL_DeformableGameObject *gameobj,
Object *bmeshobj,
BL_SkinMeshObject *mesh)
@@ -77,7 +66,7 @@ public:
};
virtual void ProcessReplica();
- virtual RAS_Deformer *GetReplica();
+ virtual RAS_Deformer *GetReplica(class KX_GameObject* replica);
virtual ~BL_ShapeDeformer();
bool Update (void);
diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp
index f96c40c098f..d8563763954 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.cpp
+++ b/source/gameengine/Converter/BL_SkinDeformer.cpp
@@ -99,9 +99,26 @@ BL_SkinDeformer::~BL_SkinDeformer()
m_armobj->Release();
}
+void BL_SkinDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
+{
+ if (m_armobj) {
+ void **h_obj = (*map)[m_armobj];
+
+ if (h_obj)
+ SetArmature( (BL_ArmatureObject*)(*h_obj) );
+ else
+ m_armobj=NULL;
+ }
+
+ BL_MeshDeformer::Relink(map);
+}
+
bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
{
- size_t i, j;
+ RAS_MeshSlot::iterator it;
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ size_t i;
// update the vertex in m_transverts
Update();
@@ -110,16 +127,18 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
// Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
// share the same mesh (=the same cache). As the rendering is done per polymaterial
// cycling through the objects, the entire mesh cache cannot be updated in one shot.
- vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat);
+ mmat = m_pMeshObject->GetMeshMaterial(mat);
+ if(!mmat->m_slots[(void*)m_gameobj])
+ return true;
- // For each array
- for (i=0; i<vertexarrays.size(); i++) {
- KX_VertexArray& vertexarray = (*vertexarrays[i]);
+ slot = *mmat->m_slots[(void*)m_gameobj];
- // For each vertex
+ // for each array
+ for(slot->begin(it); !slot->end(it); slot->next(it)) {
+ // for each vertex
// copy the untransformed data from the original mvert
- for (j=0; j<vertexarray.size(); j++) {
- RAS_TexVert& v = vertexarray[j];
+ for(i=it.startvertex; i<it.endvertex; i++) {
+ RAS_TexVert& v = it.vertex[i];
v.SetXYZ(m_transverts[v.getOrigIndex()]);
}
}
@@ -127,7 +146,7 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
return true;
}
-RAS_Deformer *BL_SkinDeformer::GetReplica()
+RAS_Deformer *BL_SkinDeformer::GetReplica(class KX_GameObject* replica)
{
BL_SkinDeformer *result;
@@ -147,14 +166,10 @@ bool BL_SkinDeformer::Update(void)
/* 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 (!PoseApplied()){
- m_armobj->ApplyPose();
- where_is_pose( par_arma );
- }
/* store verts locally */
VerifyStorage();
@@ -163,6 +178,8 @@ bool BL_SkinDeformer::Update(void)
for (int v =0; v<m_bmesh->totvert; v++)
VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
+ m_armobj->ApplyPose();
+
// save matrix first
Mat4CpyMat4(obmat, m_objMesh->obmat);
// set reference matrix
@@ -179,11 +196,13 @@ bool BL_SkinDeformer::Update(void)
/* Update the current frame */
m_lastArmaUpdate=m_armobj->GetLastFrame();
- /* reset for next frame */
- PoseApplied(false);
+
+ m_armobj->RestorePose();
+
/* indicate that the m_transverts and normals are up to date */
return true;
}
+
return false;
}
diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h
index d3fc5ae2a81..f87860021c6 100644
--- a/source/gameengine/Converter/BL_SkinDeformer.h
+++ b/source/gameengine/Converter/BL_SkinDeformer.h
@@ -50,17 +50,7 @@ class BL_SkinDeformer : public BL_MeshDeformer
{
public:
// void SetArmatureController (BL_ArmatureController *cont);
- virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
- {
- if (m_armobj){
- void **h_obj = (*map)[m_armobj];
- if (h_obj){
- SetArmature( (BL_ArmatureObject*)(*h_obj) );
- }
- else
- m_armobj=NULL;
- }
- }
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map);
void SetArmature (class BL_ArmatureObject *armobj);
BL_SkinDeformer(BL_DeformableGameObject *gameobj,
@@ -77,14 +67,10 @@ public:
BL_ArmatureObject* arma = NULL);
virtual void ProcessReplica();
- virtual RAS_Deformer *GetReplica();
+ virtual RAS_Deformer *GetReplica(class KX_GameObject* replica);
virtual ~BL_SkinDeformer();
bool Update (void);
bool Apply (class RAS_IPolyMaterial *polymat);
- bool PoseApplied()
- { return m_poseApplied; }
- void PoseApplied(bool applied)
- { m_poseApplied = applied; }
bool PoseUpdated(void)
{
if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) {
diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp
index fa215df1e1c..eb3f9d0588d 100644
--- a/source/gameengine/Converter/BL_SkinMeshObject.cpp
+++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp
@@ -28,42 +28,69 @@
* Deformer that supports armature skinning
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef WIN32
#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
#endif //WIN32
-#include "RAS_IPolygonMaterial.h"
-#include "BL_SkinMeshObject.h"
-#include "BL_DeformableGameObject.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "KX_GameObject.h"
+
#include "RAS_BucketManager.h"
+#include "RAS_IPolygonMaterial.h"
-//void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr)
-void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec)
-{
+#include "KX_GameObject.h"
+
+#include "BL_SkinMeshObject.h"
+#include "BL_DeformableGameObject.h"
- KX_MeshSlot ms;
- ms.m_clientObj = clientobj;
- ms.m_mesh = this;
- ms.m_OpenGLMatrix = oglmatrix;
- ms.m_bObjectColor = useObjectColor;
- ms.m_RGBAcolor = rgbavec;
- ms.m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer;
-
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();it++)
+BL_SkinMeshObject::BL_SkinMeshObject(Mesh* mesh, int lightlayer)
+ : RAS_MeshObject (mesh, lightlayer)
+{
+ m_bDeformed = true;
+
+ if (m_mesh && m_mesh->key)
{
+ KeyBlock *kb;
+ int count=0;
+ // initialize weight cache for shape objects
+ // count how many keys in this mesh
+ for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next)
+ count++;
+ m_cacheWeightIndex.resize(count,-1);
+ }
+}
- RAS_MaterialBucket* materialbucket = (*it);
+BL_SkinMeshObject::~BL_SkinMeshObject()
+{
+ if (m_mesh && m_mesh->key)
+ {
+ KeyBlock *kb;
+ // remove the weight cache to avoid memory leak
+ for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) {
+ if(kb->weights)
+ MEM_freeN(kb->weights);
+ kb->weights= NULL;
+ }
+ }
+}
+
+void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool useObjectColor,const MT_Vector4& rgbavec, bool visible, bool culled)
+{
+ list<RAS_MeshMaterial>::iterator it;
+ list<RAS_MeshSlot*>::iterator sit;
+
+ for(it = m_materials.begin();it!=m_materials.end();++it) {
+ if(!it->m_slots[clientobj])
+ continue;
-// KX_ArrayOptimizer* oa = GetArrayOptimizer(materialbucket->GetPolyMaterial());
- materialbucket->SetMeshSlot(ms);
+ RAS_MeshSlot *slot = *it->m_slots[clientobj];
+ slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->GetDeformer();
}
+ RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled);
}
static int get_def_index(Object* ob, const char* vgroup)
@@ -74,6 +101,7 @@ static int get_def_index(Object* ob, const char* vgroup)
for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++)
if (!strcmp(curdef->name, vgroup))
return index;
+
return -1;
}
diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h
index c21fb64204b..8544a2b958c 100644
--- a/source/gameengine/Converter/BL_SkinMeshObject.h
+++ b/source/gameengine/Converter/BL_SkinMeshObject.h
@@ -33,62 +33,27 @@
#ifdef WIN32
#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning
#endif //WIN32
-#include "MEM_guardedalloc.h"
+
#include "RAS_MeshObject.h"
#include "RAS_Deformer.h"
#include "RAS_IPolygonMaterial.h"
#include "BL_MeshDeformer.h"
-#include "DNA_mesh_types.h"
-#include "DNA_key_types.h"
-#include "DNA_meshdata_types.h"
-
class BL_SkinMeshObject : public RAS_MeshObject
{
-
-// enum { BUCKET_MAX_INDICES = 16384};//2048};//8192};
-// enum { BUCKET_MAX_TRIANGLES = 4096};
-
protected:
vector<int> m_cacheWeightIndex;
public:
- void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec);
-// void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr);
-
- BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer)
- {
- m_class = 1;
- if (m_mesh && m_mesh->key)
- {
- KeyBlock *kb;
- int count=0;
- // initialize weight cache for shape objects
- // count how many keys in this mesh
- for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next)
- count++;
- m_cacheWeightIndex.resize(count,-1);
- }
- };
+ BL_SkinMeshObject(Mesh* mesh, int lightlayer);
+ ~BL_SkinMeshObject();
- virtual ~BL_SkinMeshObject()
- {
- if (m_mesh && m_mesh->key)
- {
- KeyBlock *kb;
- // remove the weight cache to avoid memory leak
- for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) {
- if(kb->weights)
- MEM_freeN(kb->weights);
- kb->weights= NULL;
- }
- }
- };
+ void UpdateBuckets(void* clientobj, double* oglmatrix,
+ bool useObjectColor, const MT_Vector4& rgbavec, bool visible, bool culled);
// for shape keys,
void CheckWeightCache(struct Object* obj);
-
};
#endif
diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt
index adb7304b10e..217bdb30907 100644
--- a/source/gameengine/Converter/CMakeLists.txt
+++ b/source/gameengine/Converter/CMakeLists.txt
@@ -64,6 +64,7 @@ SET(INC
../../../source/gameengine/Network/LoopBackNetwork
../../../source/blender/misc
../../../source/blender/blenloader
+ ../../../source/blender/gpu
../../../extern/bullet2/src
../../../extern/solid
${PYTHON_INC}
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
index de91bce2ab1..7eec93dc402 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp
@@ -184,20 +184,21 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile()
return result;
}
-
+Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
+{
+ Scene *sce;
/**
* Find the specified scene by name, or the first
* scene if nothing matches (shouldn't happen).
*/
-static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) {
- Scene *sce;
- for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
- if (scenename == (sce->id.name+2))
+ for (sce= (Scene*) m_maggie->scene.first; sce; sce= (Scene*) sce->id.next)
+ if (name == (sce->id.name+2))
return sce;
- return (Scene*) maggie->scene.first;
+ return (Scene*)m_maggie->scene.first;
+
}
#include "KX_PythonInit.h"
@@ -245,6 +246,11 @@ struct BlenderDebugDraw : public btIDebugDraw
{
return m_debugMode;
}
+ ///todo: find out if Blender can do this
+ virtual void draw3dText(const btVector3& location,const char* textString)
+ {
+
+ }
};
@@ -258,7 +264,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
class RAS_ICanvas* canvas)
{
//find out which physics engine
- Scene *blenderscene = GetSceneForName2(m_maggie, scenename);
+ Scene *blenderscene = GetBlenderSceneForName(scenename);
e_PhysicsEngine physics_engine = UseBullet;
// hook for registration function during conversion.
@@ -495,7 +501,17 @@ void KX_BlenderSceneConverter::RegisterGameObject(
void KX_BlenderSceneConverter::UnregisterGameObject(
KX_GameObject *gameobject)
{
- m_map_gameobject_to_blender.remove(CHashedPtr(gameobject));
+ CHashedPtr gptr(gameobject);
+ struct Object **bobp= m_map_gameobject_to_blender[gptr];
+ if (bobp) {
+ CHashedPtr bptr(*bobp);
+ KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
+ if (gobp && *gobp == gameobject)
+ // also maintain m_map_blender_to_gameobject if the gameobject
+ // being removed is matching the blender object
+ m_map_blender_to_gameobject.remove(bptr);
+ m_map_gameobject_to_blender.remove(gptr);
+ }
}
@@ -644,13 +660,13 @@ extern "C"
{
Ipo *add_ipo( char *name, int idcode );
char *getIpoCurveName( IpoCurve * icu );
- struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int);
+ struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short);
void testhandles_ipocurve(struct IpoCurve *icu);
+ void insert_vert_icu(struct IpoCurve *, float, float, short);
void Mat3ToEul(float tmat[][3], float *eul);
-
}
-IpoCurve* findIpoCurve(IpoCurve* first,char* searchName)
+IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName)
{
IpoCurve* icu1;
for( icu1 = first; icu1; icu1 = icu1->next )
@@ -818,7 +834,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
if (gameObj->IsDynamic())
{
- KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
+ //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
Object* blenderObject = FindBlenderObject(gameObj);
if (blenderObject)
@@ -846,7 +862,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
- const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
+ //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
const MT_Point3& position = gameObj->NodeGetWorldPosition();
Ipo* ipo = blenderObject->ipo;
@@ -857,27 +873,27 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1);
@@ -974,7 +990,7 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
if (gameObj->IsDynamic())
{
- KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
+ //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
Object* blenderObject = FindBlenderObject(gameObj);
if (blenderObject)
@@ -1002,8 +1018,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
- const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
- const MT_Point3& position = gameObj->NodeGetWorldPosition();
+ //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
+ //const MT_Point3& position = gameObj->NodeGetWorldPosition();
Ipo* ipo = blenderObject->ipo;
if (ipo)
@@ -1013,27 +1029,27 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1);
icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
if (!icu1)
- icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z);
+ icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1);
diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h
index e5d6ccc5caf..2317e952a0a 100644
--- a/source/gameengine/Converter/KX_BlenderSceneConverter.h
+++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h
@@ -45,6 +45,7 @@ class BL_Material;
struct IpoCurve;
struct Main;
struct SpaceIpo;
+struct Scene;
class KX_BlenderSceneConverter : public KX_ISceneConverter
{
@@ -151,6 +152,7 @@ public:
virtual void SetGLSLMaterials(bool val);
virtual bool GetGLSLMaterials();
+ struct Scene* GetBlenderSceneForName(const STR_String& name);
};
#endif //__KX_BLENDERSCENECONVERTER_H
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index cb2521de9a4..d5f304c38e7 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -74,6 +74,8 @@
#include "BKE_text.h"
#include "BLI_blenlib.h"
+#define FILE_MAX 240 // repeated here to avoid dependency from BKE_utildefines.h
+
#include "KX_NetworkMessageActuator.h"
#ifdef WIN32
@@ -208,10 +210,12 @@ void BL_ConvertActuators(char* maggiename,
if (blenderobject->type==OB_MESH){
bActionActuator* actact = (bActionActuator*) bact->data;
STR_String propname = (actact->name ? actact->name : "");
+ STR_String propframe = (actact->frameProp ? actact->frameProp : "");
BL_ShapeActionActuator* tmpbaseact = new BL_ShapeActionActuator(
gameobj,
propname,
+ propframe,
actact->sta,
actact->end,
actact->act,
@@ -231,7 +235,8 @@ void BL_ConvertActuators(char* maggiename,
{
bIpoActuator* ipoact = (bIpoActuator*) bact->data;
bool ipochild = (ipoact->flag & ACT_IPOCHILD) !=0;
- STR_String propname = ( ipoact->name ? ipoact->name : "");
+ STR_String propname = ipoact->name;
+ STR_String frameProp = ipoact->frameProp;
// first bit?
bool ipo_as_force = (ipoact->flag & ACT_IPOFORCE);
bool local = (ipoact->flag & ACT_IPOLOCAL);
@@ -240,6 +245,7 @@ void BL_ConvertActuators(char* maggiename,
KX_IpoActuator* tmpbaseact = new KX_IpoActuator(
gameobj,
propname ,
+ frameProp,
ipoact->sta,
ipoact->end,
ipochild,
@@ -355,22 +361,26 @@ void BL_ConvertActuators(char* maggiename,
if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF)
{
- SND_SoundObject* sndobj = NULL;
+ SND_Scene* soundscene = scene->GetSoundScene();
+ STR_String samplename = "";
+ bool sampleisloaded = false;
- if (soundact->sound)
- {
- SND_Scene* soundscene = scene->GetSoundScene();
- STR_String samplename = soundact->sound->name;
+ if (soundact->sound) {
+ /* Need to convert the samplename into absolute path
+ * before checking if its loaded */
+ char fullpath[FILE_MAX];
- bool sampleisloaded = false;
+ /* dont modify soundact->sound->name, only change a copy */
+ BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath));
+ BLI_convertstringcode(fullpath, maggiename);
+ samplename = fullpath;
/* let's see if the sample was already loaded */
if (soundscene->IsSampleLoaded(samplename))
{
sampleisloaded = true;
}
- else
- {
+ else {
/* if not, make it so */
PackedFile* pf = soundact->sound->newpackedfile;
@@ -383,21 +393,33 @@ void BL_ConvertActuators(char* maggiename,
/* or else load it from disk */
else
{
- /* but we need to convert the samplename into absolute pathname first */
- BLI_convertstringcode(soundact->sound->name, maggiename);
- samplename = soundact->sound->name;
-
- /* and now we can load it */
- if (soundscene->LoadSample(samplename, NULL, 0) > -1)
+ if (soundscene->LoadSample(samplename, NULL, 0) > -1) {
sampleisloaded = true;
+ }
+ else {
+ std::cout << "WARNING: Sound actuator \"" << bact->name <<
+ "\" from object \"" << blenderobject->id.name+2 <<
+ "\" failed to load sample." << std::endl;
+ }
}
}
-
- if (sampleisloaded)
- {
- sndobj = new SND_SoundObject();
- sndobj->SetSampleName(samplename.Ptr());
- sndobj->SetObjectName(bact->name);
+ } else {
+ std::cout << "WARNING: Sound actuator \"" << bact->name <<
+ "\" from object \"" << blenderobject->id.name+2 <<
+ "\" has no sound datablock." << std::endl;
+ }
+
+ /* Note, allowing actuators for sounds that are not there was added since 2.47
+ * This is because python may expect the actuator and raise an exception if it dosnt find it
+ * better just to add a dummy sound actuator. */
+ SND_SoundObject* sndobj = NULL;
+ if (sampleisloaded)
+ {
+ /* setup the SND_SoundObject */
+ sndobj = new SND_SoundObject();
+ sndobj->SetSampleName(samplename.Ptr());
+ sndobj->SetObjectName(bact->name);
+ if (soundact->sound) {
sndobj->SetRollOffFactor(soundact->sound->attenuation);
sndobj->SetGain(soundact->sound->volume);
sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0)));
@@ -410,8 +432,9 @@ void BL_ConvertActuators(char* maggiename,
else
sndobj->SetLoopMode(SND_LOOP_NORMAL);
}
- else
+ else {
sndobj->SetLoopMode(SND_LOOP_OFF);
+ }
if (soundact->sound->flags & SOUND_FLAGS_PRIORITY)
sndobj->SetHighPriority(true);
@@ -422,22 +445,30 @@ void BL_ConvertActuators(char* maggiename,
sndobj->Set3D(true);
else
sndobj->Set3D(false);
-
- KX_SoundActuator* tmpsoundact =
- new KX_SoundActuator(gameobj,
- sndobj,
- scene->GetSoundScene(), // needed for replication!
- soundActuatorType,
- startFrame,
- stopFrame);
-
- tmpsoundact->SetName(bact->name);
- baseact = tmpsoundact;
- soundscene->AddObject(sndobj);
- } else {
- std::cout << "WARNING: Sound actuator " << bact->name << " failed to load sample." << std::endl;
+ }
+ else {
+ /* dummy values for a NULL sound
+ * see editsound.c - defaults are unlikely to change soon */
+ sndobj->SetRollOffFactor(1.0);
+ sndobj->SetGain(1.0);
+ sndobj->SetPitch(1.0);
+ sndobj->SetLoopMode(SND_LOOP_OFF);
+ sndobj->SetHighPriority(false);
+ sndobj->Set3D(false);
}
}
+ KX_SoundActuator* tmpsoundact =
+ new KX_SoundActuator(gameobj,
+ sndobj,
+ scene->GetSoundScene(), // needed for replication!
+ soundActuatorType,
+ startFrame,
+ stopFrame);
+
+ tmpsoundact->SetName(bact->name);
+ baseact = tmpsoundact;
+ if (sndobj)
+ soundscene->AddObject(sndobj);
}
break;
}
@@ -550,10 +581,16 @@ void BL_ConvertActuators(char* maggiename,
originalval = converter->FindGameObject(editobact->ob);
}
}
- MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]),
+ MT_Vector3 linvelvec (
+ KX_BLENDERTRUNC(editobact->linVelocity[0]),
KX_BLENDERTRUNC(editobact->linVelocity[1]),
KX_BLENDERTRUNC(editobact->linVelocity[2]));
-
+
+ MT_Vector3 angvelvec (
+ KX_BLENDERTRUNC(editobact->angVelocity[0]),
+ KX_BLENDERTRUNC(editobact->angVelocity[1]),
+ KX_BLENDERTRUNC(editobact->angVelocity[2]));
+
KX_SCA_AddObjectActuator* tmpaddact =
new KX_SCA_AddObjectActuator(
gameobj,
@@ -561,7 +598,9 @@ void BL_ConvertActuators(char* maggiename,
editobact->time,
scene,
linvelvec.getValue(),
- editobact->localflag!=0
+ (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0,
+ angvelvec.getValue(),
+ (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0
);
//editobact->ob to gameobj
@@ -682,6 +721,40 @@ void BL_ConvertActuators(char* maggiename,
break;
}
prop = conact->matprop;
+ } else if (conact->type == ACT_CONST_TYPE_FH) {
+ switch (conact->mode) {
+ case ACT_CONST_DIRPX:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX;
+ min = conact->minloc[0];
+ max = conact->maxloc[0];
+ break;
+ case ACT_CONST_DIRPY:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY;
+ min = conact->minloc[1];
+ max = conact->maxloc[1];
+ break;
+ case ACT_CONST_DIRPZ:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ;
+ min = conact->minloc[2];
+ max = conact->maxloc[2];
+ break;
+ case ACT_CONST_DIRNX:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX;
+ min = conact->minloc[0];
+ max = conact->maxloc[0];
+ break;
+ case ACT_CONST_DIRNY:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY;
+ min = conact->minloc[1];
+ max = conact->maxloc[1];
+ break;
+ case ACT_CONST_DIRNZ:
+ locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ;
+ min = conact->minloc[2];
+ max = conact->maxloc[2];
+ break;
+ }
+ prop = conact->matprop;
} else {
switch (conact->flag) {
case ACT_CONST_LOCX:
@@ -843,6 +916,16 @@ void BL_ConvertActuators(char* maggiename,
mode = KX_GameActuator::KX_GAME_QUIT;
break;
}
+ case ACT_GAME_SAVECFG:
+ {
+ mode = KX_GameActuator::KX_GAME_SAVECFG;
+ break;
+ }
+ case ACT_GAME_LOADCFG:
+ {
+ mode = KX_GameActuator::KX_GAME_LOADCFG;
+ break;
+ }
default:
; /* flag error */
}
@@ -929,10 +1012,9 @@ void BL_ConvertActuators(char* maggiename,
bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data;
KX_VisibilityActuator * tmp_vis_act = NULL;
bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0);
+ bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0);
- tmp_vis_act =
- new KX_VisibilityActuator(gameobj,
- !v);
+ tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive);
baseact = tmp_vis_act;
}
@@ -1031,7 +1113,7 @@ void BL_ConvertActuators(char* maggiename,
{
bParentActuator *parAct = (bParentActuator *) bact->data;
int mode = KX_ParentActuator::KX_PARENT_NODEF;
- KX_GameObject *tmpgob;
+ KX_GameObject *tmpgob = NULL;
switch(parAct->type)
{
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
index aae8752671f..dfbc6f0c48d 100644
--- a/source/gameengine/Converter/KX_ConvertProperties.cpp
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -132,6 +132,10 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
prop = prop->next;
}
-
-
+ // check if state needs to be debugged
+ if (object->scaflag & OB_DEBUGSTATE)
+ {
+ // reserve name for object state
+ scene->AddDebugProperty(gameobj,STR_String("__state__"));
+ }
}
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index 5e433bb821b..be0bb8103c0 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -65,6 +65,7 @@ probably misplaced */
#include "SCA_JoystickSensor.h"
#include "KX_NetworkMessageSensor.h"
#include "SCA_ActuatorSensor.h"
+#include "SCA_DelaySensor.h"
#include "SCA_PropertySensor.h"
@@ -91,6 +92,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
class KX_GameObject* gameobj,
SCA_LogicManager* logicmgr,
KX_Scene* kxscene,
+ KX_KetsjiEngine* kxengine,
SCA_IInputDevice* keydev,
int & executePriority,
int activeLayerBitInfo,
@@ -281,6 +283,22 @@ void BL_ConvertSensors(struct Object* blenderobject,
break;
}
+ case SENS_DELAY:
+ {
+ // we can reuse the Always event manager for the delay sensor
+ SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::ALWAYS_EVENTMGR);
+ if (eventmgr)
+ {
+ bDelaySensor* delaysensor = (bDelaySensor*)sens->data;
+ gamesensor = new SCA_DelaySensor(eventmgr,
+ gameobj,
+ delaysensor->delay,
+ delaysensor->duration,
+ (delaysensor->flag & SENS_DELAY_REPEAT) != 0);
+ }
+ break;
+ }
+
case SENS_COLLISION:
{
SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR);
@@ -491,6 +509,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
trackfocus,
canvas,
kxscene,
+ kxengine,
gameobj);
}
} else {
@@ -616,6 +635,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
if (eventmgr)
{
bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL);
+ bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY);
STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname);
@@ -628,6 +648,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
gameobj,
checkname,
bFindMaterial,
+ bXRay,
distance,
axis,
kxscene);
@@ -694,6 +715,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
gamesensor = new SCA_JoystickSensor(
eventmgr,
gameobj,
+ bjoy->joyindex,
joysticktype,
axis,axisf,
prec,
@@ -741,12 +763,33 @@ void BL_ConvertSensors(struct Object* blenderobject,
for (int i=0;i<sens->totlinks;i++)
{
bController* linkedcont = (bController*) sens->links[i];
- SCA_IController* gamecont = converter->FindGameController(linkedcont);
+ if (linkedcont) {
+ SCA_IController* gamecont = converter->FindGameController(linkedcont);
- if (gamecont) {
- logicmgr->RegisterToSensor(gamecont,gamesensor);
+ if (gamecont) {
+ logicmgr->RegisterToSensor(gamecont,gamesensor);
+ } else {
+ printf(
+ "Warning, sensor \"%s\" could not find its controller "
+ "(link %d of %d) from object \"%s\"\n"
+ "\tthere has been an error converting the blender controller for the game engine,"
+ "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
+ }
+ } else {
+ printf(
+ "Warning, sensor \"%s\" has lost a link to a controller "
+ "(link %d of %d) from object \"%s\"\n"
+ "\tpossible causes are partially appended objects or an error reading the file,"
+ "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2);
}
}
+ // special case: Keyboard sensor with no link
+ // this combination is usually used for key logging.
+ if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) {
+ // Force the registration so that the sensor runs
+ gamesensor->IncLink();
+ }
+
// done with gamesensor
gamesensor->Release();
diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h
index 73da51f47f0..b18ffc10a2a 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.h
+++ b/source/gameengine/Converter/KX_ConvertSensors.h
@@ -33,6 +33,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
class KX_GameObject* gameobj,
class SCA_LogicManager* logicmgr,
class KX_Scene* kxscene,
+ class KX_KetsjiEngine* kxengine,
class SCA_IInputDevice* keydev,
int & executePriority ,
int activeLayerBitInfo,
diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile
index f312fc13221..4dd63e428bd 100644
--- a/source/gameengine/Converter/Makefile
+++ b/source/gameengine/Converter/Makefile
@@ -51,6 +51,7 @@ CPPFLAGS += -I../../blender/include
CPPFLAGS += -I../../blender/blenlib
CPPFLAGS += -I../../blender/blenkernel
CPPFLAGS += -I../../blender/render/extern/include
+CPPFLAGS += -I../../blender/gpu
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic
CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph
diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript
index f5e382b471e..3be352c568b 100644
--- a/source/gameengine/Converter/SConscript
+++ b/source/gameengine/Converter/SConscript
@@ -16,7 +16,7 @@ incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/game
incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet #source/gameengine/Physics/BlOde'
incs += ' #source/gameengine/Physics/Dummy #source/gameengine/Physics/Sumo'
incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork'
-incs += ' #source/blender/misc #source/blender/blenloader'
+incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu'
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_SOLID_INC']
diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile
index e9c02eedcf2..6736149bbcd 100644
--- a/source/gameengine/Expressions/Makefile
+++ b/source/gameengine/Expressions/Makefile
@@ -36,6 +36,7 @@ include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 8937f481922..1eca527151a 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -119,6 +119,7 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr)
int PyObjectPlus::_delattr(const STR_String& attr)
{
+ PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted");
return 1;
}
@@ -126,7 +127,8 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value)
{
//return PyObject::_setattr(attr,value);
//cerr << "Unknown attribute" << endl;
- return 1;
+ PyErr_SetString(PyExc_AttributeError, "attribute cant be set");
+ return 1;
}
/*------------------------------
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index f433a08faba..3a054454a0b 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -43,10 +43,39 @@
* Python defines
------------------------------*/
+/*
+ Py_RETURN_NONE
+ Python 2.4 macro.
+ defined here until we switch to 2.4
+ also in api2_2x/gen_utils.h
+*/
+#ifndef Py_RETURN_NONE
+#define Py_RETURN_NONE return Py_BuildValue("O", Py_None)
+#endif
+#ifndef Py_RETURN_FALSE
+#define Py_RETURN_FALSE return PyBool_FromLong(0)
+#endif
+#ifndef Py_RETURN_TRUE
+#define Py_RETURN_TRUE return PyBool_FromLong(1)
+#endif
+
+/* for pre Py 2.5 */
+#if PY_VERSION_HEX < 0x02050000
+typedef int Py_ssize_t;
+#define PY_SSIZE_T_MAX INT_MAX
+#define PY_SSIZE_T_MIN INT_MIN
+#define PY_METHODCHAR char *
+#else
+/* Py 2.5 and later */
+#define intargfunc ssizeargfunc
+#define intintargfunc ssizessizeargfunc
+#define PY_METHODCHAR const char *
+#endif
+
// some basic python macros
#define Py_Return { Py_INCREF(Py_None); return Py_None;}
-static inline void Py_Fatal(char *M) {
+static inline void Py_Fatal(const char *M) {
//cout << M << endl;
exit(-1);
};
@@ -102,6 +131,12 @@ static inline void Py_Fatal(char *M) {
return ((class_name*) self)->Py##method_name(self, args, kwds); \
}; \
+#define KX_PYMETHOD_VARARGS(class_name, method_name) \
+ PyObject* Py##method_name(PyObject* self, PyObject* args); \
+ static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
+ return ((class_name*) self)->Py##method_name(self, args); \
+ }; \
+
#define KX_PYMETHOD_NOARGS(class_name, method_name) \
PyObject* Py##method_name(PyObject* self); \
static PyObject* sPy##method_name( PyObject* self) { \
@@ -119,28 +154,28 @@ static inline void Py_Fatal(char *M) {
static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
return ((class_name*) self)->Py##method_name(self, args, kwds); \
}; \
- static char method_name##_doc[]; \
+ static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \
PyObject* Py##method_name(PyObject* self, PyObject* args); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
return ((class_name*) self)->Py##method_name(self, args); \
}; \
- static char method_name##_doc[]; \
+ static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_O(class_name, method_name) \
PyObject* Py##method_name(PyObject* self, PyObject* value); \
static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
return ((class_name*) self)->Py##method_name(self, value); \
}; \
- static char method_name##_doc[]; \
+ static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \
PyObject* Py##method_name(PyObject* self); \
static PyObject* sPy##method_name( PyObject* self) { \
return ((class_name*) self)->Py##method_name(self); \
}; \
- static char method_name##_doc[]; \
+ static const char method_name##_doc[]; \
/* The line above should remain empty */
@@ -148,15 +183,21 @@ static inline void Py_Fatal(char *M) {
* Method table macro (with doc)
*/
#define KX_PYMETHODTABLE(class_name, method_name) \
- {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc}
+ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, (PY_METHODCHAR)class_name::method_name##_doc}
+
+#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \
+ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, (PY_METHODCHAR)class_name::method_name##_doc}
/**
* Function implementation macro
*/
#define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \
-char class_name::method_name##_doc[] = doc_string; \
+const char class_name::method_name##_doc[] = doc_string; \
PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*)
+#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \
+const char class_name::method_name##_doc[] = doc_string; \
+PyObject* class_name::Py##method_name(PyObject*)
/*------------------------------
* PyObjectPlus
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 7bcb45228db..7296dfbec10 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -391,16 +391,23 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
bool CValue::RemoveProperty(const STR_String & inName)
{
// Check if there are properties at all which can be removed
- if (m_pNamedPropertyArray == NULL)
- return false;
-
- CValue* val = GetProperty(inName);
- if (NULL != val)
- {
- val->Release();
- m_pNamedPropertyArray->erase(inName);
- return true;
- }
+ if (m_pNamedPropertyArray) {
+ CValue* val = GetProperty(inName);
+ if (NULL != val)
+ {
+ val->Release();
+ m_pNamedPropertyArray->erase(inName);
+ return true;
+ }
+ }
+
+ char err[128];
+ if (m_pNamedPropertyArray)
+ sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr());
+ else
+ sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr());
+
+ PyErr_SetString(PyExc_AttributeError, err);
return false;
}
@@ -755,7 +762,8 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
int CValue::_delattr(const STR_String& attr)
{
- RemoveProperty(attr);
+ if (!RemoveProperty(attr)) /* sets error */
+ return 1;
return 0;
}
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index 18d7b6ffcd0..092956e6489 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -29,9 +29,9 @@
#include "SCA_Joystick.h"
#include "SCA_JoystickPrivate.h"
-
-SCA_Joystick::SCA_Joystick()
+SCA_Joystick::SCA_Joystick(short int index)
:
+ m_joyindex(index),
m_axis10(0),
m_axis11(0),
m_axis20(0),
@@ -42,92 +42,74 @@ SCA_Joystick::SCA_Joystick()
m_isinit(0),
m_istrig(0)
{
+#ifndef DISABLE_SDL
m_private = new PrivateData();
+#endif
}
SCA_Joystick::~SCA_Joystick()
{
+#ifndef DISABLE_SDL
delete m_private;
+#endif
}
-SCA_Joystick *SCA_Joystick::m_instance = NULL;
+SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX];
int SCA_Joystick::m_refCount = 0;
-SCA_Joystick *SCA_Joystick::GetInstance()
+SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
{
- if (m_instance == 0)
+#ifdef DISABLE_SDL
+ return NULL;
+#else
+ if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
+ echo("Error-invalid joystick index: " << joyindex);
+ return NULL;
+ }
+
+ if (m_refCount == 0)
{
- m_instance = new SCA_Joystick();
- m_instance->CreateJoystickDevice();
+ int i;
+ // do this once only
+ if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){
+ echo("Error-Initializing-SDL: " << SDL_GetError());
+ return NULL;
+ }
+ for (i=0; i<JOYINDEX_MAX; i++) {
+ m_instance[i] = new SCA_Joystick(i);
+ m_instance[i]->CreateJoystickDevice();
+ }
m_refCount = 1;
}
else
{
m_refCount++;
}
- return m_instance;
+ return m_instance[joyindex];
+#endif
}
void SCA_Joystick::ReleaseInstance()
{
if (--m_refCount == 0)
{
- DestroyJoystickDevice();
- delete m_instance;
- m_instance = NULL;
- }
-}
-
-
-bool SCA_Joystick::CreateJoystickDevice()
-{
- bool init = false;
- init = pCreateJoystickDevice();
- return init;
-}
-
-
-void SCA_Joystick::DestroyJoystickDevice()
-{
- if(m_isinit)
- pDestroyJoystickDevice();
-}
-
-
-void SCA_Joystick::HandleEvents()
-{
- if(m_isinit)
- {
- if(SDL_PollEvent(&m_private->m_event))
- {
- switch(m_private->m_event.type)
- {
- case SDL_JOYAXISMOTION:
- HANDLE_AXISMOTION(OnAxisMotion);
- break;
- case SDL_JOYHATMOTION:
- HANDLE_HATMOTION(OnHatMotion);
- break;
- case SDL_JOYBUTTONUP:
- HANDLE_BUTTONUP(OnButtonUp);
- break;
- case SDL_JOYBUTTONDOWN:
- HANDLE_BUTTONDOWN(OnButtonDown);
- break;
- case SDL_JOYBALLMOTION:
- HANDLE_BALLMOTION(OnBallMotion);
- break;
- default:
- HANDLE_NOEVENT(OnNothing);
- break;
+#ifndef DISABLE_SDL
+ int i;
+ for (i=0; i<JOYINDEX_MAX; i++) {
+ if (m_instance[i]) {
+ m_instance[i]->DestroyJoystickDevice();
+ delete m_instance[i];
}
+ m_instance[i]= NULL;
}
+
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO );
+#endif
}
}
-
void SCA_Joystick::cSetPrecision(int val)
{
m_prec = val;
@@ -176,19 +158,27 @@ bool SCA_Joystick::aDownAxisIsPositive(int axis)
bool SCA_Joystick::aButtonPressIsPositive(int button)
{
+#ifdef DISABLE_SDL
+ return false;
+#else
bool result;
SDL_JoystickGetButton(m_private->m_joystick, button)? result = true:result = false;
m_istrig = result;
return result;
+#endif
}
bool SCA_Joystick::aButtonReleaseIsPositive(int button)
{
+#ifdef DISABLE_SDL
+ return false;
+#else
bool result;
SDL_JoystickGetButton(m_private->m_joystick, button)? result = false : result = true;
m_istrig = result;
return result;
+#endif
}
@@ -226,78 +216,11 @@ int SCA_Joystick::pGetHat(int direction)
return 0;
}
-
-bool SCA_Joystick::GetJoyAxisMotion()
-{
- bool result = false;
- if(m_isinit){
- if(SDL_PollEvent(&m_private->m_event)){
- switch(m_private->m_event.type)
- {
- case SDL_JOYAXISMOTION:
- result = true;
- break;
- }
- }
- }
- return result;
-}
-
-
-bool SCA_Joystick::GetJoyButtonPress()
-{
- bool result = false;
- if(m_isinit){
- if(SDL_PollEvent(&m_private->m_event)){
- switch(m_private->m_event.type)
- {
- case SDL_JOYBUTTONDOWN:
- result = true;
- break;
- }
- }
- }
- return result;
-}
-
-
-bool SCA_Joystick::GetJoyButtonRelease()
-{
- bool result = false;
- if(m_isinit)
- {
- if(SDL_PollEvent(&m_private->m_event)){
- switch(m_private->m_event.type)
- {
- case SDL_JOYBUTTONUP:
- result = true;
- break;
- }
- }
- }
- return result;
-}
-
-
-bool SCA_Joystick::GetJoyHatMotion()
-{
- bool result = false;
- if(m_isinit){
- if(SDL_PollEvent(&m_private->m_event)){
- switch(m_private->m_event.type)
- {
- case SDL_JOYHATMOTION:
- result = true;
- break;
- }
- }
- }
- return 0;
-}
-
-
int SCA_Joystick::GetNumberOfAxes()
{
+#ifdef DISABLE_SDL
+ return -1;
+#else
int number;
if(m_isinit){
if(m_private->m_joystick){
@@ -306,11 +229,15 @@ int SCA_Joystick::GetNumberOfAxes()
}
}
return -1;
+#endif
}
int SCA_Joystick::GetNumberOfButtons()
{
+#ifdef DISABLE_SDL
+ return -1;
+#else
int number;
if(m_isinit){
if(m_private->m_joystick){
@@ -319,11 +246,15 @@ int SCA_Joystick::GetNumberOfButtons()
}
}
return -1;
+#endif
}
int SCA_Joystick::GetNumberOfHats()
{
+#ifdef DISABLE_SDL
+ return -1;
+#else
int number;
if(m_isinit){
if(m_private->m_joystick){
@@ -332,47 +263,57 @@ int SCA_Joystick::GetNumberOfHats()
}
}
return -1;
+#endif
}
-bool SCA_Joystick::pCreateJoystickDevice()
+bool SCA_Joystick::CreateJoystickDevice(void)
{
+#ifdef DISABLE_SDL
+ return false;
+#else
if(m_isinit == false){
- if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){
- echo("Error-Initializing-SDL: " << SDL_GetError());
- return false;
- }
- if(SDL_NumJoysticks() > 0){
- for(int i=0; i<SDL_NumJoysticks();i++){
- m_private->m_joystick = SDL_JoystickOpen(i);
- SDL_JoystickEventState(SDL_ENABLE);
- m_numjoys = i;
- }
- echo("Joystick-initialized");
- m_isinit = true;
- return true;
- }else{
- echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
+ if (m_joyindex>=SDL_NumJoysticks()) {
+ // don't print a message, because this is done anyway
+ //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
return false;
}
+
+ m_private->m_joystick = SDL_JoystickOpen(m_joyindex);
+ SDL_JoystickEventState(SDL_ENABLE);
+
+ echo("Joystick " << m_joyindex << " initialized");
+ m_isinit = true;
}
- return false;
+ return true;
+#endif
}
-void SCA_Joystick::pDestroyJoystickDevice()
+void SCA_Joystick::DestroyJoystickDevice(void)
{
- echo("Closing-");
- for(int i=0; i<SDL_NumJoysticks(); i++){
- if(SDL_JoystickOpened(i)){
+#ifndef DISABLE_SDL
+ if (m_isinit){
+ if(SDL_JoystickOpened(m_joyindex)){
+ echo("Closing-joystick " << m_joyindex);
SDL_JoystickClose(m_private->m_joystick);
}
+ m_isinit = false;
}
- SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO );
+#endif
}
+int SCA_Joystick::Connected(void)
+{
+#ifndef DISABLE_SDL
+ if (m_isinit && SDL_JoystickOpened(m_joyindex))
+ return 1;
+#endif
+ return 0;
+}
void SCA_Joystick::pFillAxes()
{
+#ifndef DISABLE_SDL
if(GetNumberOfAxes() == 1){
m_axis10 = SDL_JoystickGetAxis(m_private->m_joystick, 0);
m_axis11 = SDL_JoystickGetAxis(m_private->m_joystick, 1);
@@ -382,18 +323,20 @@ void SCA_Joystick::pFillAxes()
m_axis20 = SDL_JoystickGetAxis(m_private->m_joystick, 2);
m_axis21 = SDL_JoystickGetAxis(m_private->m_joystick, 3);
}else{
- m_axis10 = 0;m_axis11 = 0;
- m_axis20 = 0;m_axis21 = 0;
+ m_axis10 = m_axis11 = m_axis20 = m_axis21 = 0;
}
+#endif
}
int SCA_Joystick::pGetAxis(int axisnum, int udlr)
{
+#ifndef DISABLE_SDL
if(axisnum == 1 && udlr == 1)return m_axis10; //u/d
if(axisnum == 1 && udlr == 0)return m_axis11; //l/r
if(axisnum == 2 && udlr == 0)return m_axis20; //...
if(axisnum == 2 && udlr == 1)return m_axis21;
+#endif
return 0;
}
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
index 1e853070b09..ea7ecf7cefe 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h
@@ -1,72 +1,37 @@
/**
-
* ***** BEGIN GPL LICENSE BLOCK *****
-
*
-
* This program is free software; you can redistribute it and/or
-
* modify it under the terms of the GNU General Public License
-
* as published by the Free Software Foundation; either version 2
-
* of the License, or (at your option) any later version.
-
-
-
-
*
-
* This program is distributed in the hope that it will be useful,
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-
* GNU General Public License for more details.
-
*
-
* You should have received a copy of the GNU General Public License
-
* along with this program; if not, write to the Free Software Foundation,
-
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
*
-
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
-
* All rights reserved.
-
*
-
* The Original Code is: all of this file.
-
*
-
* Contributor(s): snailrose.
-
*
-
* ***** END GPL LICENSE BLOCK *****
-
*/
#ifndef _SCA_JOYSTICK_H_
-
#define _SCA_JOYSTICK_H_
-
-
#include "SCA_JoystickDefines.h"
-
-
-
-
+#include "SDL.h"
/*
-
* Basic Joystick class
* I will make this class a singleton because there should be only one joystick
* even if there are more than one scene using it and count how many scene are using it.
@@ -76,235 +41,145 @@
class SCA_Joystick
{
- static SCA_Joystick *m_instance;
+ static SCA_Joystick *m_instance[JOYINDEX_MAX];
static int m_refCount;
class PrivateData;
-
+#ifndef DISABLE_SDL
PrivateData *m_private;
-
+#endif
int m_joyindex;
- /*!
-
- * the number of avail joysticks
-
- */
-
- int m_numjoys;
-
/*
-
*support for 2 axes
-
*/
int m_axis10,m_axis11;
-
int m_axis20,m_axis21;
- /*
-
+ /*
* Precision or range of the axes
-
*/
-
int m_prec;
/*
-
* multiple axis values stored here
-
*/
-
int m_axisnum;
-
int m_axisvalue;
/*
-
* max # of axes avail
-
*/
-
/*disabled
-
int m_axismax;
-
*/
/*
-
* button values stored here
-
*/
-
int m_buttonnum;
/*
-
* max # of buttons avail
-
*/
int m_buttonmax;
-
/*
-
* hat values stored here
-
*/
-
int m_hatnum;
-
int m_hatdir;
/*
* max # of hats avail
-
disabled
-
int m_hatmax;
-
*/
-
/* is the joystick initialized ?*/
-
bool m_isinit;
-
/* is triggered */
-
bool m_istrig;
+#ifndef DISABLE_SDL
/*
-
- * Open the joystick
-
+ * event callbacks
*/
-
- bool pCreateJoystickDevice(void);
-
+ void OnAxisMotion(SDL_Event *sdl_event);
+ void OnHatMotion(SDL_Event *sdl_event);
+ void OnButtonUp(SDL_Event *sdl_event);
+ void OnButtonDown(SDL_Event *sdl_event);
+ void OnNothing(SDL_Event *sdl_event);
+ void OnBallMotion(SDL_Event *sdl_event){}
+#endif
/*
-
- * Close the joystick
-
+ * Open the joystick
*/
-
- void pDestroyJoystickDevice(void);
-
-
+ bool CreateJoystickDevice(void);
/*
-
- * event callbacks
-
+ * Close the joystick
*/
-
- void OnAxisMotion(void);
-
- void OnHatMotion(void);
-
- void OnButtonUp(void);
-
- void OnButtonDown(void);
-
- void OnNothing(void);
-
- void OnBallMotion(void){}
+ void DestroyJoystickDevice(void);
/*
-
* fills the axis mnember values
-
*/
-
void pFillAxes(void);
-
-
-
void pFillButtons(void);
/*
-
* returns m_axis10,m_axis11...
-
*/
-
int pGetAxis(int axisnum, int udlr);
-
+
/*
-
* gets the current button
-
*/
int pGetButtonPress(int button);
/*
-
* returns if no button is pressed
-
*/
-
int pGetButtonRelease(int button);
/*
-
* gets the current hat direction
-
*/
-
int pGetHat(int direction);
- SCA_Joystick();
+ SCA_Joystick(short int index);
~SCA_Joystick();
- bool CreateJoystickDevice(void);
-
- void DestroyJoystickDevice(void);
-
-
public:
- static SCA_Joystick *GetInstance();
-
+ static SCA_Joystick *GetInstance( short int joyindex );
+ static void HandleEvents( void );
void ReleaseInstance();
- void HandleEvents();
-
/*
-
*/
bool aUpAxisIsPositive(int axis);
-
bool aDownAxisIsPositive(int axis);
-
bool aLeftAxisIsPositive(int axis);
-
bool aRightAxisIsPositive(int axis);
-
bool aButtonPressIsPositive(int button);
-
bool aButtonReleaseIsPositive(int button);
-
bool aHatIsPositive(int dir);
/*
-
* precision is default '3200' which is overridden by input
-
*/
void cSetPrecision(int val);
-
-
int GetAxis10(void){
return m_axis10;
@@ -312,80 +187,49 @@ public:
}
int GetAxis11(void){
-
return m_axis11;
-
}
int GetAxis20(void){
-
return m_axis20;
-
}
int GetAxis21(void){
-
return m_axis21;
-
}
int GetButton(void){
-
return m_buttonnum;
-
}
int GetHat(void){
-
return m_hatdir;
-
}
int GetThreshold(void){
-
return m_prec;
-
}
bool IsTrig(void){
-
return m_istrig;
-
}
-
-
- /*
-
- * returns true if an event is being processed
-
- */
-
- bool GetJoyAxisMotion(void);
-
- bool GetJoyButtonPress(void);
-
- bool GetJoyButtonRelease(void);
-
- bool GetJoyHatMotion(void);
-
/*
-
* returns the # of...
-
*/
int GetNumberOfAxes(void);
-
int GetNumberOfButtons(void);
-
int GetNumberOfHats(void);
-
-
+ /*
+ * Test if the joystick is connected
+ */
+ int Connected(void);
};
-
-
+#ifndef DISABLE_SDL
+void Joystick_HandleEvents( void );
+#endif
#endif
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
index 15a421188b9..73ffe1406d9 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
@@ -38,12 +38,6 @@
#define echo(x) std::cout << x << std::endl;
#endif
-/* function callbacks */
-#define HANDLE_AXISMOTION(fn) ((fn)(), 0L)
-#define HANDLE_HATMOTION(fn) ((fn)(), 0L)
-#define HANDLE_BUTTONUP(fn) ((fn)(), 0L)
-#define HANDLE_BUTTONDOWN(fn) ((fn)(), 0L)
-#define HANDLE_BALLMOTION(fn) ((fn)(), 0L)
-#define HANDLE_NOEVENT(fn) ((fn)(), 0L)
+#define JOYINDEX_MAX 8
#endif
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
index ab523470e21..0e2078265c9 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp
@@ -29,42 +29,77 @@
#include "SCA_JoystickPrivate.h"
-
-void SCA_Joystick::OnAxisMotion(void)
+#ifndef DISABLE_SDL
+void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event)
{
pFillAxes();
- m_axisnum = m_private->m_event.jaxis.axis;
- m_axisvalue = m_private->m_event.jaxis.value;
+ m_axisnum = sdl_event->jaxis.axis;
+ m_axisvalue = sdl_event->jaxis.value;
m_istrig = 1;
}
-void SCA_Joystick::OnHatMotion(void)
+void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event)
{
- m_hatdir = m_private->m_event.jhat.value;
- m_hatnum = m_private->m_event.jhat.hat;
+ m_hatdir = sdl_event->jhat.value;
+ m_hatnum = sdl_event->jhat.hat;
m_istrig = 1;
}
-void SCA_Joystick::OnButtonUp(void)
+void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event)
{
m_buttonnum = -2;
}
-void SCA_Joystick::OnButtonDown(void)
+void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event)
{
m_buttonmax = GetNumberOfButtons();
- if(m_private->m_event.jbutton.button >= 1 || m_private->m_event.jbutton.button <= m_buttonmax)
+ if(sdl_event->jbutton.button >= 1 || sdl_event->jbutton.button <= m_buttonmax)
{
m_istrig = 1;
- m_buttonnum = m_private->m_event.jbutton.button;
+ m_buttonnum = sdl_event->jbutton.button;
}
}
-void SCA_Joystick::OnNothing(void)
+void SCA_Joystick::OnNothing(SDL_Event* sdl_event)
{
m_istrig = 0;
}
+
+/* only handle events for 1 joystick */
+
+void SCA_Joystick::HandleEvents(void)
+{
+ SDL_Event sdl_event;
+
+ if(SDL_PollEvent(&sdl_event))
+ {
+ /* Note! m_instance[sdl_event.jaxis.which]
+ * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */
+ switch(sdl_event.type)
+ {
+ case SDL_JOYAXISMOTION:
+ SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event);
+ break;
+ case SDL_JOYHATMOTION:
+ SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event);
+ break;
+ case SDL_JOYBUTTONUP:
+ SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event);
+ break;
+ case SDL_JOYBUTTONDOWN:
+ SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event);
+ break;
+ case SDL_JOYBALLMOTION:
+ SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event);
+ break;
+ default:
+ printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n");
+ break;
+ }
+ }
+}
+#endif
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h
index 23fad3cd55d..acbbcae9cd7 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h
@@ -29,14 +29,11 @@
#define __SCA_JOYSTICKPRIVATE_H__
#include "SCA_Joystick.h"
+#ifndef DISABLE_SDL
class SCA_Joystick::PrivateData
{
public:
/*
- * SDL events structure
- */
- SDL_Event m_event;
- /*
* The Joystick
*/
SDL_Joystick* m_joystick;
@@ -47,3 +44,5 @@ public:
}
};
#endif
+
+#endif
diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile
index b3eae5d67dc..355ece6e8bd 100644
--- a/source/gameengine/GameLogic/Makefile
+++ b/source/gameengine/GameLogic/Makefile
@@ -42,6 +42,7 @@ CPPFLAGS += -I../Expressions
CPPFLAGS += -I../Rasterizer
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
CPPFLAGS += $(NAN_SDLCFLAGS)
diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
index 96a770a553f..9ec4ea00337 100644
--- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp
@@ -23,8 +23,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator(
: SCA_IActuator(gameobj, T),
m_type(type),
m_flag(flag),
- m_int_arg(int_arg),
m_float_arg(float_arg),
+ m_int_arg(int_arg),
m_rasterizer(rasterizer),
m_rendertools(rendertools)
{
@@ -64,13 +64,11 @@ bool SCA_2DFilterActuator::Update()
if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR )
{
if(!m_flag)
- {
m_rasterizer->EnableMotionBlur(m_float_arg);
- }
else
- {
m_rasterizer->DisableMotionBlur();
- }
+
+ return false;
}
else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS)
{
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
index 6501a3173a7..6d6a059207b 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
@@ -149,8 +149,8 @@ PyParentObject SCA_ActuatorSensor::Parents[] = {
};
PyMethodDef SCA_ActuatorSensor::Methods[] = {
- {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, GetActuator_doc},
- {"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, SetActuator_doc},
+ {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, (PY_METHODCHAR)GetActuator_doc},
+ {"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, (PY_METHODCHAR)SetActuator_doc},
{NULL,NULL} //Sentinel
};
@@ -159,7 +159,7 @@ PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) {
}
/* 3. getActuator */
-char SCA_ActuatorSensor::GetActuator_doc[] =
+const char SCA_ActuatorSensor::GetActuator_doc[] =
"getActuator()\n"
"\tReturn the Actuator with which the sensor operates.\n";
PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self)
@@ -168,7 +168,7 @@ PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self)
}
/* 4. setActuator */
-char SCA_ActuatorSensor::SetActuator_doc[] =
+const char SCA_ActuatorSensor::SetActuator_doc[] =
"setActuator(name)\n"
"\t- name: string\n"
"\tSets the Actuator with which to operate. If there is no Actuator\n"
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
new file mode 100644
index 00000000000..f15d4c7249f
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp
@@ -0,0 +1,257 @@
+/**
+ * Delay trigger
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef WIN32
+// This warning tells us about truncation of __long__ stl-generated names.
+// It can occasionally cause DevStudio to have internal compiler warnings.
+#pragma warning( disable : 4786 )
+#endif
+
+#include "SCA_DelaySensor.h"
+#include "SCA_LogicManager.h"
+#include "SCA_EventManager.h"
+
+/* ------------------------------------------------------------------------- */
+/* Native functions */
+/* ------------------------------------------------------------------------- */
+
+SCA_DelaySensor::SCA_DelaySensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ int delay,
+ int duration,
+ bool repeat,
+ PyTypeObject* T)
+ : SCA_ISensor(gameobj,eventmgr, T),
+ m_delay(delay),
+ m_duration(duration),
+ m_repeat(repeat)
+{
+ Init();
+}
+
+void SCA_DelaySensor::Init()
+{
+ m_lastResult = false;
+ m_frameCount = -1;
+ m_reset = true;
+}
+
+SCA_DelaySensor::~SCA_DelaySensor()
+{
+ /* intentionally empty */
+}
+
+CValue* SCA_DelaySensor::GetReplica()
+{
+ CValue* replica = new SCA_DelaySensor(*this);
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+
+ return replica;
+}
+
+
+
+bool SCA_DelaySensor::IsPositiveTrigger()
+{
+ return (m_invert ? !m_lastResult : m_lastResult);
+}
+
+bool SCA_DelaySensor::Evaluate(CValue* event)
+{
+ bool trigger = false;
+ bool result;
+
+ if (m_frameCount==-1) {
+ // this is needed to ensure ON trigger in case delay==0
+ // and avoid spurious OFF trigger when duration==0
+ m_lastResult = false;
+ m_frameCount = 0;
+ }
+
+ if (m_frameCount<m_delay) {
+ m_frameCount++;
+ result = false;
+ } else if (m_duration > 0) {
+ if (m_frameCount < m_delay+m_duration) {
+ m_frameCount++;
+ result = true;
+ } else {
+ result = false;
+ if (m_repeat)
+ m_frameCount = -1;
+ }
+ } else {
+ result = true;
+ if (m_repeat)
+ m_frameCount = -1;
+ }
+ if ((m_reset && m_level) || result != m_lastResult)
+ trigger = true;
+ m_reset = false;
+ m_lastResult = result;
+ return trigger;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject SCA_DelaySensor::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "SCA_DelaySensor",
+ sizeof(SCA_DelaySensor),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject SCA_DelaySensor::Parents[] = {
+ &SCA_DelaySensor::Type,
+ &SCA_ISensor::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef SCA_DelaySensor::Methods[] = {
+ /* setProperty */
+ {"setDelay", (PyCFunction) SCA_DelaySensor::sPySetDelay, METH_VARARGS, (PY_METHODCHAR)SetDelay_doc},
+ {"setDuration", (PyCFunction) SCA_DelaySensor::sPySetDuration, METH_VARARGS, (PY_METHODCHAR)SetDuration_doc},
+ {"setRepeat", (PyCFunction) SCA_DelaySensor::sPySetRepeat, METH_VARARGS, (PY_METHODCHAR)SetRepeat_doc},
+ /* getProperty */
+ {"getDelay", (PyCFunction) SCA_DelaySensor::sPyGetDelay, METH_NOARGS, (PY_METHODCHAR)GetDelay_doc},
+ {"getDuration", (PyCFunction) SCA_DelaySensor::sPyGetDuration, METH_NOARGS, (PY_METHODCHAR)GetDuration_doc},
+ {"getRepeat", (PyCFunction) SCA_DelaySensor::sPyGetRepeat, METH_NOARGS, (PY_METHODCHAR)GetRepeat_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject* SCA_DelaySensor::_getattr(const STR_String& attr) {
+ _getattr_up(SCA_ISensor);
+}
+
+const char SCA_DelaySensor::SetDelay_doc[] =
+"setDelay(delay)\n"
+"\t- delay: length of the initial OFF period as number of frame\n"
+"\t 0 for immediate trigger\n"
+"\tSet the initial delay before the positive trigger\n";
+PyObject* SCA_DelaySensor::PySetDelay(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int delay;
+
+ if(!PyArg_ParseTuple(args, "i", &delay)) {
+ return NULL;
+ }
+ if (delay < 0) {
+ PyErr_SetString(PyExc_ValueError, "Delay cannot be negative");
+ return NULL;
+ }
+ m_delay = delay;
+ Py_Return;
+}
+
+const char SCA_DelaySensor::SetDuration_doc[] =
+"setDuration(duration)\n"
+"\t- duration: length of the ON period in number of frame after the initial off period\n"
+"\t 0 for no ON period\n"
+"\tSet the duration of the ON pulse after initial delay.\n"
+"\tIf > 0, a negative trigger is fired at the end of the ON pulse.\n";
+PyObject* SCA_DelaySensor::PySetDuration(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int duration;
+
+ if(!PyArg_ParseTuple(args, "i", &duration)) {
+ return NULL;
+ }
+ if (duration < 0) {
+ PyErr_SetString(PyExc_ValueError, "Duration cannot be negative");
+ return NULL;
+ }
+ m_duration = duration;
+ Py_Return;
+}
+
+const char SCA_DelaySensor::SetRepeat_doc[] =
+"setRepeat(repeat)\n"
+"\t- repeat: 1 if the initial OFF-ON cycle should be repeated indefinately\n"
+"\t 0 if the initial OFF-ON cycle should run only once\n"
+"\tSet the sensor repeat mode\n";
+PyObject* SCA_DelaySensor::PySetRepeat(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ int repeat;
+
+ if(!PyArg_ParseTuple(args, "i", &repeat)) {
+ return NULL;
+ }
+ m_repeat = (repeat != 0);
+ Py_Return;
+}
+
+const char SCA_DelaySensor::GetDelay_doc[] =
+"getDelay()\n"
+"\tReturn the delay parameter value\n";
+PyObject* SCA_DelaySensor::PyGetDelay(PyObject* self)
+{
+ return PyInt_FromLong(m_delay);
+}
+
+const char SCA_DelaySensor::GetDuration_doc[] =
+"getDuration()\n"
+"\tReturn the duration parameter value\n";
+PyObject* SCA_DelaySensor::PyGetDuration(PyObject* self)
+{
+ return PyInt_FromLong(m_duration);
+}
+
+const char SCA_DelaySensor::GetRepeat_doc[] =
+"getRepeat()\n"
+"\tReturn the repeat parameter value\n";
+PyObject* SCA_DelaySensor::PyGetRepeat(PyObject* self)
+{
+ return BoolToPyArg(m_repeat);
+}
+
+/* eof */
diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h
new file mode 100644
index 00000000000..a997fabe3cd
--- /dev/null
+++ b/source/gameengine/GameLogic/SCA_DelaySensor.h
@@ -0,0 +1,77 @@
+/**
+ * SCA_DelaySensor.h
+ *
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __KX_DELAYSENSOR
+#define __KX_DELAYSENSOR
+#include "SCA_ISensor.h"
+
+class SCA_DelaySensor : public SCA_ISensor
+{
+ Py_Header;
+ bool m_lastResult;
+ bool m_repeat;
+ int m_delay;
+ int m_duration;
+ int m_frameCount;
+
+public:
+ SCA_DelaySensor(class SCA_EventManager* eventmgr,
+ SCA_IObject* gameobj,
+ int delay,
+ int duration,
+ bool repeat,
+ PyTypeObject* T =&Type);
+ virtual ~SCA_DelaySensor();
+ virtual CValue* GetReplica();
+ virtual bool Evaluate(CValue* event);
+ virtual bool IsPositiveTrigger();
+ virtual void Init();
+
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(const STR_String& attr);
+
+ /* setProperty */
+ KX_PYMETHOD_DOC(SCA_DelaySensor,SetDelay);
+ KX_PYMETHOD_DOC(SCA_DelaySensor,SetDuration);
+ KX_PYMETHOD_DOC(SCA_DelaySensor,SetRepeat);
+ /* getProperty */
+ KX_PYMETHOD_DOC_NOARGS(SCA_DelaySensor,GetDelay);
+ KX_PYMETHOD_DOC_NOARGS(SCA_DelaySensor,GetDuration);
+ KX_PYMETHOD_DOC_NOARGS(SCA_DelaySensor,GetRepeat);
+
+};
+
+#endif //__KX_ALWAYSSENSOR
+
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index 8f156cc63e7..0bd20117f31 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -188,6 +188,8 @@ void SCA_IController::ApplyState(unsigned int state)
for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
{
(*sensit)->IncLink();
+ // remember that this controller just activated that sensor
+ (*sensit)->AddNewController(this);
}
SetActive(true);
}
diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
index f5512664d8f..abd049e9d64 100644
--- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
+++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
@@ -27,6 +27,7 @@
*/
#include "SCA_ILogicBrick.h"
+#include "PyObjectPlus.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index 2dc49924062..b10ac676464 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -32,6 +32,8 @@
#include "SCA_ISensor.h"
#include "SCA_EventManager.h"
#include "SCA_LogicManager.h"
+// needed for IsTriggered()
+#include "SCA_PythonController.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -132,10 +134,8 @@ void SCA_ISensor::DecLink() {
}
if (!m_links)
{
- // sensor is detached from all controllers, initialize it so that it
- // is fresh as at startup when it is reattached again.
+ // sensor is detached from all controllers, remove it from manager
UnregisterToManager();
- Init();
}
}
@@ -168,27 +168,31 @@ PyParentObject SCA_ISensor::Parents[] = {
};
PyMethodDef SCA_ISensor::Methods[] = {
{"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive,
- METH_VARARGS, IsPositive_doc},
+ METH_NOARGS, (PY_METHODCHAR)IsPositive_doc},
+ {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered,
+ METH_VARARGS, (PY_METHODCHAR)IsTriggered_doc},
{"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode,
- METH_NOARGS, GetUsePosPulseMode_doc},
+ METH_NOARGS, (PY_METHODCHAR)GetUsePosPulseMode_doc},
{"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode,
- METH_VARARGS, SetUsePosPulseMode_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetUsePosPulseMode_doc},
{"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency,
- METH_NOARGS, GetFrequency_doc},
+ METH_NOARGS, (PY_METHODCHAR)GetFrequency_doc},
{"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency,
- METH_VARARGS, SetFrequency_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetFrequency_doc},
{"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode,
- METH_NOARGS, GetUseNegPulseMode_doc},
+ METH_NOARGS, (PY_METHODCHAR)GetUseNegPulseMode_doc},
{"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode,
- METH_VARARGS, SetUseNegPulseMode_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetUseNegPulseMode_doc},
{"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert,
- METH_NOARGS, GetInvert_doc},
+ METH_NOARGS, (PY_METHODCHAR)GetInvert_doc},
{"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert,
- METH_VARARGS, SetInvert_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetInvert_doc},
{"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel,
- METH_NOARGS, GetLevel_doc},
+ METH_NOARGS, (PY_METHODCHAR)GetLevel_doc},
{"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel,
- METH_VARARGS, SetLevel_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetLevel_doc},
+ {"reset", (PyCFunction) SCA_ISensor::sPyReset,
+ METH_NOARGS, (PY_METHODCHAR)Reset_doc},
{NULL,NULL} //Sentinel
};
@@ -202,6 +206,9 @@ SCA_ISensor::_getattr(const STR_String& attr)
void SCA_ISensor::RegisterToManager()
{
+ // sensor is just activated, initialize it
+ Init();
+ m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
m_eventmgr->RegisterSensor(this);
}
@@ -219,6 +226,9 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event)
bool result = this->Evaluate(event);
if (result) {
logicmgr->AddActivatedSensor(this);
+ // reset these counters so that pulse are synchronized with transition
+ m_pos_ticks = 0;
+ m_neg_ticks = 0;
} else
{
/* First, the pulsing behaviour, if pulse mode is
@@ -247,23 +257,51 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event)
}
}
}
+ if (!m_newControllers.empty())
+ {
+ if (!IsActive() && m_level)
+ {
+ // This level sensor is connected to at least one controller that was just made
+ // active but it did not generate an event yet, do it now to those controllers only
+ for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin();
+ ci != m_newControllers.end(); ci++)
+ {
+ logicmgr->AddTriggeredController(*ci, this);
+ }
+ }
+ // clear the list. Instead of using clear, which also release the memory,
+ // use erase, which keeps the memory available for next time.
+ m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
+ }
}
}
/* Python functions: */
-char SCA_ISensor::IsPositive_doc[] =
+const char SCA_ISensor::IsPositive_doc[] =
"isPositive()\n"
-"\tReturns whether the sensor is registered a positive event.\n";
-PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds)
+"\tReturns whether the sensor is in an active state.\n";
+PyObject* SCA_ISensor::PyIsPositive(PyObject* self)
{
int retval = IsPositiveTrigger();
return PyInt_FromLong(retval);
}
+const char SCA_ISensor::IsTriggered_doc[] =
+"isTriggered()\n"
+"\tReturns whether the sensor has triggered the current controller.\n";
+PyObject* SCA_ISensor::PyIsTriggered(PyObject* self)
+{
+ // check with the current controller
+ int retval = 0;
+ if (SCA_PythonController::m_sCurrentController)
+ retval = SCA_PythonController::m_sCurrentController->IsTriggered(this);
+ return PyInt_FromLong(retval);
+}
+
/**
* getUsePulseMode: getter for the pulse mode (KX_TRUE = on)
*/
-char SCA_ISensor::GetUsePosPulseMode_doc[] =
+const char SCA_ISensor::GetUsePosPulseMode_doc[] =
"getUsePosPulseMode()\n"
"\tReturns whether positive pulse mode is active.\n";
PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self)
@@ -274,7 +312,7 @@ PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self)
/**
* setUsePulseMode: setter for the pulse mode (KX_TRUE = on)
*/
-char SCA_ISensor::SetUsePosPulseMode_doc[] =
+const char SCA_ISensor::SetUsePosPulseMode_doc[] =
"setUsePosPulseMode(pulse?)\n"
"\t - pulse? : Pulse when a positive event occurs?\n"
"\t (KX_TRUE, KX_FALSE)\n"
@@ -290,7 +328,7 @@ PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyOb
/**
* getFrequency: getter for the pulse mode interval
*/
-char SCA_ISensor::GetFrequency_doc[] =
+const char SCA_ISensor::GetFrequency_doc[] =
"getFrequency()\n"
"\tReturns the frequency of the updates in pulse mode.\n" ;
PyObject* SCA_ISensor::PyGetFrequency(PyObject* self)
@@ -301,7 +339,7 @@ PyObject* SCA_ISensor::PyGetFrequency(PyObject* self)
/**
* setFrequency: setter for the pulse mode (KX_TRUE = on)
*/
-char SCA_ISensor::SetFrequency_doc[] =
+const char SCA_ISensor::SetFrequency_doc[] =
"setFrequency(pulse_frequency)\n"
"\t- pulse_frequency: The frequency of the updates in pulse mode (integer)"
"\tSet the frequency of the updates in pulse mode.\n"
@@ -325,7 +363,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject*
}
-char SCA_ISensor::GetInvert_doc[] =
+const char SCA_ISensor::GetInvert_doc[] =
"getInvert()\n"
"\tReturns whether or not pulses from this sensor are inverted.\n" ;
PyObject* SCA_ISensor::PyGetInvert(PyObject* self)
@@ -333,7 +371,7 @@ PyObject* SCA_ISensor::PyGetInvert(PyObject* self)
return BoolToPyArg(m_invert);
}
-char SCA_ISensor::SetInvert_doc[] =
+const char SCA_ISensor::SetInvert_doc[] =
"setInvert(invert?)\n"
"\t- invert?: Invert the event-values? (KX_TRUE, KX_FALSE)\n"
"\tSet whether to invert pulses.\n";
@@ -345,7 +383,7 @@ PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwd
Py_Return;
}
-char SCA_ISensor::GetLevel_doc[] =
+const char SCA_ISensor::GetLevel_doc[] =
"getLevel()\n"
"\tReturns whether this sensor is a level detector or a edge detector.\n"
"\tIt makes a difference only in case of logic state transition (state actuator).\n"
@@ -357,7 +395,7 @@ PyObject* SCA_ISensor::PyGetLevel(PyObject* self)
return BoolToPyArg(m_level);
}
-char SCA_ISensor::SetLevel_doc[] =
+const char SCA_ISensor::SetLevel_doc[] =
"setLevel(level?)\n"
"\t- level?: Detect level instead of edge? (KX_TRUE, KX_FALSE)\n"
"\tSet whether to detect level or edge transition when entering a state.\n";
@@ -369,7 +407,7 @@ PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds
Py_Return;
}
-char SCA_ISensor::GetUseNegPulseMode_doc[] =
+const char SCA_ISensor::GetUseNegPulseMode_doc[] =
"getUseNegPulseMode()\n"
"\tReturns whether negative pulse mode is active.\n";
PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self)
@@ -377,7 +415,7 @@ PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self)
return BoolToPyArg(m_neg_pulsemode);
}
-char SCA_ISensor::SetUseNegPulseMode_doc[] =
+const char SCA_ISensor::SetUseNegPulseMode_doc[] =
"setUseNegPulseMode(pulse?)\n"
"\t - pulse? : Pulse when a negative event occurs?\n"
"\t (KX_TRUE, KX_FALSE)\n"
@@ -390,4 +428,15 @@ PyObject* SCA_ISensor::PySetUseNegPulseMode(PyObject* self, PyObject* args, PyOb
Py_Return;
}
+const char SCA_ISensor::Reset_doc[] =
+"reset()\n"
+"\tReset sensor internal state, effect depends on the type of sensor and settings.\n"
+"\tThe sensor is put in its initial state as if it was just activated.\n";
+PyObject* SCA_ISensor::PyReset(PyObject* self)
+{
+ Init();
+ Py_Return;
+}
+
+
/* eof */
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index d5dabbce3ee..0d65270dc7b 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -34,6 +34,8 @@
#include "SCA_ILogicBrick.h"
+#include <vector>
+
/**
* Interface Class for all logic Sensors. Implements
* pulsemode,pulsefrequency */
@@ -73,9 +75,9 @@ class SCA_ISensor : public SCA_ILogicBrick
/** number of connections to controller */
int m_links;
- /** Pass the activation on to the logic manager.*/
- void SignalActivation(class SCA_LogicManager* logicmgr);
-
+ /** list of controllers that have just activated this sensor because of a state change */
+ std::vector<class SCA_IController*> m_newControllers;
+
public:
SCA_ISensor(SCA_IObject* gameobj,
class SCA_EventManager* eventmgr,
@@ -128,6 +130,8 @@ public:
/** Resume sensing. */
void Resume();
+ void AddNewController(class SCA_IController* controller)
+ { m_newControllers.push_back(controller); }
void ClrLink()
{ m_links = 0; }
void IncLink()
@@ -137,7 +141,8 @@ public:
{ return !m_links; }
/* Python functions: */
- KX_PYMETHOD_DOC(SCA_ISensor,IsPositive);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode);
KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency);
@@ -148,6 +153,7 @@ public:
KX_PYMETHOD_DOC(SCA_ISensor,SetInvert);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel);
KX_PYMETHOD_DOC(SCA_ISensor,SetLevel);
+ KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,Reset);
};
diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
index 8ff28ba0b51..d874b5b013a 100644
--- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp
@@ -40,35 +40,48 @@ SCA_JoystickManager::SCA_JoystickManager(class SCA_LogicManager* logicmgr)
: SCA_EventManager(JOY_EVENTMGR),
m_logicmgr(logicmgr)
{
- m_joystick = SCA_Joystick::GetInstance();
+ int i;
+ for (i=0; i<JOYINDEX_MAX; i++) {
+ m_joystick[i] = SCA_Joystick::GetInstance( i );
+ }
}
SCA_JoystickManager::~SCA_JoystickManager()
{
- m_joystick->ReleaseInstance();
+ int i;
+ for (i=0; i<JOYINDEX_MAX; i++) {
+ m_joystick[i]->ReleaseInstance();
+ }
}
void SCA_JoystickManager::NextFrame(double curtime,double deltatime)
{
- set<SCA_ISensor*>::iterator it;
- for (it = m_sensors.begin(); it != m_sensors.end(); it++)
- {
- SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it);
- if(!joysensor->IsSuspended())
+ if (m_sensors.size()==0) {
+ return;
+ }
+ else {
+ set<SCA_ISensor*>::iterator it;
+#ifndef DISABLE_SDL
+ SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */
+#endif
+ for (it = m_sensors.begin(); it != m_sensors.end(); it++)
{
- m_joystick->HandleEvents();
- joysensor->Activate(m_logicmgr, NULL);
+ SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it);
+ if(!joysensor->IsSuspended())
+ {
+ joysensor->Activate(m_logicmgr, NULL);
+ }
}
}
}
-SCA_Joystick *SCA_JoystickManager::GetJoystickDevice()
+SCA_Joystick *SCA_JoystickManager::GetJoystickDevice( short int joyindex)
{
/*
*Return the instance of SCA_Joystick for use
*/
- return m_joystick;
+ return m_joystick[joyindex];
}
diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h
index f2bb27965fa..d3a7ac95bea 100644
--- a/source/gameengine/GameLogic/SCA_JoystickManager.h
+++ b/source/gameengine/GameLogic/SCA_JoystickManager.h
@@ -40,12 +40,12 @@ class SCA_JoystickManager : public SCA_EventManager
/**
* SDL Joystick Class Instance
*/
- SCA_Joystick *m_joystick;
+ SCA_Joystick *m_joystick[JOYINDEX_MAX];
public:
SCA_JoystickManager(class SCA_LogicManager* logicmgr);
virtual ~SCA_JoystickManager();
virtual void NextFrame(double curtime,double deltatime);
- SCA_Joystick* GetJoystickDevice(void);
+ SCA_Joystick* GetJoystickDevice(short int joyindex);
};
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
index 3fb439eb25b..58818240009 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
@@ -30,8 +30,11 @@
#include "SCA_EventManager.h"
#include "SCA_LogicManager.h"
+#include "PyObjectPlus.h"
+
#include <iostream>
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -39,6 +42,7 @@
SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
SCA_IObject* gameobj,
+ short int joyindex,
short int joymode,
int axis, int axisf,int prec,
int button, int buttonf,
@@ -53,7 +57,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
m_hat(hat),
m_hatf(hatf),
m_precision(prec),
- m_joymode(joymode)
+ m_joymode(joymode),
+ m_joyindex(joyindex)
{
/*
std::cout << " axis " << m_axis << std::endl;
@@ -99,10 +104,13 @@ bool SCA_JoystickSensor::IsPositiveTrigger()
bool SCA_JoystickSensor::Evaluate(CValue* event)
{
- SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice();
+ SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
bool result = false;
bool reset = m_reset && m_level;
+ if(js==NULL)
+ return false;
+
m_reset = false;
switch(m_joymode)
{
@@ -118,7 +126,7 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
js->cSetPrecision(m_precision);
if(m_axisf == 1){
if(js->aUpAxisIsPositive(m_axis)){
- m_istrig =1;
+ m_istrig = 1;
result = true;
}else{
if(m_istrig){
@@ -241,11 +249,31 @@ bool SCA_JoystickSensor::Evaluate(CValue* event)
printf("Error invalid switch statement\n");
break;
}
- if(!js->IsTrig()){
+
+ if (js->IsTrig()) {
+ /* The if below detects changes with the joystick trigger state.
+ * js->IsTrig() will stay true as long as the key is held.
+ * even though the event from SDL will only be sent once.
+ * (js->IsTrig() && m_istrig_lastjs) - when true it means this sensor
+ * had the same joystick trigger state last time,
+ * Setting the result false this time means it wont run the sensors
+ * controller every time (like a pulse sensor)
+ *
+ * This is not done with the joystick its self incase other sensors use
+ * it or become active.
+ */
+ if (m_istrig_lastjs) {
+ result = false;
+ }
+ m_istrig_lastjs = true;
+ } else {
m_istrig = 0;
+ m_istrig_lastjs = false;
}
+
if (reset)
result = true;
+
return result;
}
@@ -293,18 +321,21 @@ PyParentObject SCA_JoystickSensor::Parents[] = {
PyMethodDef SCA_JoystickSensor::Methods[] = {
- {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, GetAxis_doc},
- {"setAxis", (PyCFunction) SCA_JoystickSensor::sPySetAxis, METH_VARARGS, SetAxis_doc},
- {"getAxisValue", (PyCFunction) SCA_JoystickSensor::sPyGetRealAxis, METH_NOARGS, GetRealAxis_doc},
- {"getThreshold", (PyCFunction) SCA_JoystickSensor::sPyGetThreshold, METH_NOARGS, GetThreshold_doc},
- {"setThreshold", (PyCFunction) SCA_JoystickSensor::sPySetThreshold, METH_VARARGS, SetThreshold_doc},
- {"getButton", (PyCFunction) SCA_JoystickSensor::sPyGetButton, METH_NOARGS, GetButton_doc},
- {"setButton", (PyCFunction) SCA_JoystickSensor::sPySetButton, METH_VARARGS, SetButton_doc},
- {"getHat", (PyCFunction) SCA_JoystickSensor::sPyGetHat, METH_NOARGS, GetHat_doc},
- {"setHat", (PyCFunction) SCA_JoystickSensor::sPySetHat, METH_VARARGS, SetHat_doc},
- {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, NumberOfAxes_doc},
- {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, NumberOfButtons_doc},
- {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, NumberOfHats_doc},
+ {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, (PY_METHODCHAR)GetIndex_doc},
+ {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, (PY_METHODCHAR)SetIndex_doc},
+ {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, (PY_METHODCHAR)GetAxis_doc},
+ {"setAxis", (PyCFunction) SCA_JoystickSensor::sPySetAxis, METH_VARARGS, (PY_METHODCHAR)SetAxis_doc},
+ {"getAxisValue", (PyCFunction) SCA_JoystickSensor::sPyGetRealAxis, METH_NOARGS, (PY_METHODCHAR)GetRealAxis_doc},
+ {"getThreshold", (PyCFunction) SCA_JoystickSensor::sPyGetThreshold, METH_NOARGS, (PY_METHODCHAR)GetThreshold_doc},
+ {"setThreshold", (PyCFunction) SCA_JoystickSensor::sPySetThreshold, METH_VARARGS, (PY_METHODCHAR)SetThreshold_doc},
+ {"getButton", (PyCFunction) SCA_JoystickSensor::sPyGetButton, METH_NOARGS, (PY_METHODCHAR)GetButton_doc},
+ {"setButton", (PyCFunction) SCA_JoystickSensor::sPySetButton, METH_VARARGS, (PY_METHODCHAR)SetButton_doc},
+ {"getHat", (PyCFunction) SCA_JoystickSensor::sPyGetHat, METH_NOARGS, (PY_METHODCHAR)GetHat_doc},
+ {"setHat", (PyCFunction) SCA_JoystickSensor::sPySetHat, METH_VARARGS, (PY_METHODCHAR)SetHat_doc},
+ {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, (PY_METHODCHAR)NumberOfAxes_doc},
+ {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, (PY_METHODCHAR)NumberOfButtons_doc},
+ {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, (PY_METHODCHAR)NumberOfHats_doc},
+ {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, (PY_METHODCHAR)Connected_doc},
{NULL,NULL} //Sentinel
};
@@ -314,24 +345,44 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) {
}
+/* get index ---------------------------------------------------------- */
+const char SCA_JoystickSensor::GetIndex_doc[] =
+"getIndex\n"
+"\tReturns the joystick index to use.\n";
+PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) {
+ return PyInt_FromLong(m_joyindex);
+}
+
+
+/* set index ---------------------------------------------------------- */
+const char SCA_JoystickSensor::SetIndex_doc[] =
+"setIndex\n"
+"\tSets the joystick index to use.\n";
+PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) {
+ int index = PyInt_AsLong( value ); /* -1 on error, will raise an error in this case */
+ if (index < 0 || index >= JOYINDEX_MAX) {
+ PyErr_SetString(PyExc_ValueError, "joystick index out of range or not an int");
+ return NULL;
+ }
+
+ m_joyindex = index;
+ Py_RETURN_NONE;
+}
+
/* get axis ---------------------------------------------------------- */
-char SCA_JoystickSensor::GetAxis_doc[] =
+const char SCA_JoystickSensor::GetAxis_doc[] =
"getAxis\n"
"\tReturns the current state of the axis.\n";
-PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- return Py_BuildValue("[ii]",m_axis, m_axisf);
+PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) {
+ return PyInt_FromLong(m_joyindex);
}
/* set axis ---------------------------------------------------------- */
-char SCA_JoystickSensor::SetAxis_doc[] =
+const char SCA_JoystickSensor::SetAxis_doc[] =
"setAxis\n"
"\tSets the current state of the axis.\n";
-PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) {
int axis,axisflag;
if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){
@@ -339,145 +390,126 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self,
}
m_axis = axis;
m_axisf = axisflag;
- Py_Return;
+ Py_RETURN_NONE;
}
/* get axis value ----------------------------------------------------- */
-char SCA_JoystickSensor::GetRealAxis_doc[] =
+const char SCA_JoystickSensor::GetRealAxis_doc[] =
"getAxisValue\n"
"\tReturns a list of the values for each axis .\n";
-PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- int a,b,c,d;
- SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
- a = joy->GetAxis10();
- b = joy->GetAxis11();
- c = joy->GetAxis20();
- d = joy->GetAxis21();
- return Py_BuildValue("[iiii]",a,b,c,d);
+PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) {
+ SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
+ if(joy)
+ return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21());
+ else
+ return Py_BuildValue("[iiii]", 0, 0, 0, 0);
}
/* get threshold ----------------------------------------------------- */
-char SCA_JoystickSensor::GetThreshold_doc[] =
+const char SCA_JoystickSensor::GetThreshold_doc[] =
"getThreshold\n"
"\tReturns the threshold of the axis.\n";
-PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- return Py_BuildValue("i", m_precision);
+PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) {
+ return PyInt_FromLong(m_precision);
}
/* set threshold ----------------------------------------------------- */
-char SCA_JoystickSensor::SetThreshold_doc[] =
+const char SCA_JoystickSensor::SetThreshold_doc[] =
"setThreshold\n"
"\tSets the threshold of the axis.\n";
-PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) {
int thresh;
if(!PyArg_ParseTuple(args, "i", &thresh)){
return NULL;
}
m_precision = thresh;
- Py_Return;
+ Py_RETURN_NONE;
}
/* get button -------------------------------------------------------- */
-char SCA_JoystickSensor::GetButton_doc[] =
+const char SCA_JoystickSensor::GetButton_doc[] =
"getButton\n"
"\tReturns the currently pressed button.\n";
-PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) {
return Py_BuildValue("[ii]",m_button, m_buttonf);
}
/* set button -------------------------------------------------------- */
-char SCA_JoystickSensor::SetButton_doc[] =
+const char SCA_JoystickSensor::SetButton_doc[] =
"setButton\n"
"\tSets the button the sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PySetButton( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* args ) {
int button,buttonflag;
if(!PyArg_ParseTuple(args, "ii", &button, &buttonflag)){
return NULL;
}
m_button = button;
m_buttonf = buttonflag;
- Py_Return;
+ Py_RETURN_NONE;
}
/* get hat ----------------------------------------------------------- */
-char SCA_JoystickSensor::GetHat_doc[] =
+const char SCA_JoystickSensor::GetHat_doc[] =
"getHat\n"
"\tReturns the current direction of the hat.\n";
-PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) {
return Py_BuildValue("[ii]",m_hat, m_hatf);
}
/* set hat ----------------------------------------------------------- */
-char SCA_JoystickSensor::SetHat_doc[] =
+const char SCA_JoystickSensor::SetHat_doc[] =
"setHat\n"
"\tSets the hat the sensor reacts to.\n";
-PyObject* SCA_JoystickSensor::PySetHat( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
+PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) {
int hat,hatflag;
if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){
return NULL;
}
m_hat = hat;
m_hatf = hatflag;
- Py_Return;
+ Py_RETURN_NONE;
}
/* get # of ----------------------------------------------------- */
-char SCA_JoystickSensor::NumberOfAxes_doc[] =
+const char SCA_JoystickSensor::NumberOfAxes_doc[] =
"getNumAxes\n"
"\tReturns the number of axes .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- int num;
- SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
- num = joy->GetNumberOfAxes();
- return Py_BuildValue("i",num);
+PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) {
+ SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
+ // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected()
+ return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 );
}
-char SCA_JoystickSensor::NumberOfButtons_doc[] =
+const char SCA_JoystickSensor::NumberOfButtons_doc[] =
"getNumButtons\n"
"\tReturns the number of buttons .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- int num;
- SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
- num = joy->GetNumberOfButtons();
- return Py_BuildValue("i",num);
+PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) {
+ SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
+ return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 );
}
-char SCA_JoystickSensor::NumberOfHats_doc[] =
+const char SCA_JoystickSensor::NumberOfHats_doc[] =
"getNumHats\n"
"\tReturns the number of hats .\n";
-PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self,
- PyObject* args,
- PyObject* kwds) {
- int num;
- SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice();
- num = joy->GetNumberOfHats();
- return Py_BuildValue("i",num);
+PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) {
+ SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
+ return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 );
+}
+
+const char SCA_JoystickSensor::Connected_doc[] =
+"getConnected\n"
+"\tReturns True if a joystick is connected at this joysticks index.\n";
+PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) {
+ SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
+ return PyBool_FromLong( joy ? joy->Connected() : 0 );
}
diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h
index 69068da6494..8b74f6e0296 100644
--- a/source/gameengine/GameLogic/SCA_JoystickSensor.h
+++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h
@@ -69,9 +69,19 @@ class SCA_JoystickSensor :public SCA_ISensor
*/
bool m_istrig;
/**
+ * Last trigger state for this sensors joystick,
+ * Otherwise it will trigger all the time
+ * this is used to see if the trigger state changes.
+ */
+ bool m_istrig_lastjs;
+ /**
* The mode to determine axis,button or hat
*/
short int m_joymode;
+ /**
+ * Select which joystick to use
+ */
+ short int m_joyindex;
enum KX_JOYSENSORMODE {
KX_JOYSENSORMODE_NODEF = 0,
@@ -85,6 +95,7 @@ class SCA_JoystickSensor :public SCA_ISensor
public:
SCA_JoystickSensor(class SCA_JoystickManager* eventmgr,
SCA_IObject* gameobj,
+ short int joyindex,
short int joymode,
int axis, int axisf,int prec,
int button, int buttonf,
@@ -97,28 +108,36 @@ public:
virtual bool IsPositiveTrigger();
virtual void Init();
+ short int GetJoyIndex(void){
+ return m_joyindex;
+ }
+
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
virtual PyObject* _getattr(const STR_String& attr);
+ /* Joystick Index */
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex);
+ KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex);
/* Axes*/
- KX_PYMETHOD_DOC(SCA_JoystickSensor,GetAxis);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,SetAxis);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,GetRealAxis);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,GetThreshold);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,SetThreshold);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetAxis);
+ KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetAxis);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetRealAxis);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetThreshold);
+ KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetThreshold);
/* Buttons */
- KX_PYMETHOD_DOC(SCA_JoystickSensor,GetButton);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,SetButton);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton);
+ KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetButton);
/* Hats */
- KX_PYMETHOD_DOC(SCA_JoystickSensor,GetHat);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,SetHat);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat);
+ KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat);
/* number of */
- KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfAxes);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfButtons);
- KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfHats);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfAxes);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats);
+ KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected);
};
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index a7a6fa93db4..d09a5394965 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -505,12 +505,12 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self,
PyObject* kwds)
{
// printf("sPyIsPositive\n");
- return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
+ return ((SCA_KeyboardSensor*) self)->PyIsPositive(self);
}
/** 1. GetKey : check which key this sensor looks at */
-char SCA_KeyboardSensor::GetKey_doc[] =
+const char SCA_KeyboardSensor::GetKey_doc[] =
"getKey()\n"
"\tReturn the code of the key this sensor is listening to.\n" ;
PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject* kwds)
@@ -519,7 +519,7 @@ PyObject* SCA_KeyboardSensor::PyGetKey(PyObject* self, PyObject* args, PyObject*
}
/** 2. SetKey: change the key to look at */
-char SCA_KeyboardSensor::SetKey_doc[] =
+const char SCA_KeyboardSensor::SetKey_doc[] =
"setKey(keycode)\n"
"\t- keycode: any code from GameKeys\n"
"\tSet the key this sensor should listen to.\n" ;
@@ -539,7 +539,7 @@ PyObject* SCA_KeyboardSensor::PySetKey(PyObject* self, PyObject* args, PyObject*
}
/** 3. GetHold1 : set the first bucky bit */
-char SCA_KeyboardSensor::GetHold1_doc[] =
+const char SCA_KeyboardSensor::GetHold1_doc[] =
"getHold1()\n"
"\tReturn the code of the first key modifier to the key this \n"
"\tsensor is listening to.\n" ;
@@ -549,7 +549,7 @@ PyObject* SCA_KeyboardSensor::PyGetHold1(PyObject* self, PyObject* args, PyObjec
}
/** 4. SetHold1: change the first bucky bit */
-char SCA_KeyboardSensor::SetHold1_doc[] =
+const char SCA_KeyboardSensor::SetHold1_doc[] =
"setHold1(keycode)\n"
"\t- keycode: any code from GameKeys\n"
"\tSet the first modifier to the key this sensor should listen to.\n" ;
@@ -569,7 +569,7 @@ PyObject* SCA_KeyboardSensor::PySetHold1(PyObject* self, PyObject* args, PyObjec
}
/** 5. GetHold2 : get the second bucky bit */
-char SCA_KeyboardSensor::GetHold2_doc[] =
+const char SCA_KeyboardSensor::GetHold2_doc[] =
"getHold2()\n"
"\tReturn the code of the second key modifier to the key this \n"
"\tsensor is listening to.\n" ;
@@ -579,7 +579,7 @@ PyObject* SCA_KeyboardSensor::PyGetHold2(PyObject* self, PyObject* args, PyObjec
}
/** 6. SetHold2: change the second bucky bit */
-char SCA_KeyboardSensor::SetHold2_doc[] =
+const char SCA_KeyboardSensor::SetHold2_doc[] =
"setHold2(keycode)\n"
"\t- keycode: any code from GameKeys\n"
"\tSet the first modifier to the key this sensor should listen to.\n" ;
@@ -599,7 +599,7 @@ PyObject* SCA_KeyboardSensor::PySetHold2(PyObject* self, PyObject* args, PyObjec
}
-char SCA_KeyboardSensor::GetPressedKeys_doc[] =
+const char SCA_KeyboardSensor::GetPressedKeys_doc[] =
"getPressedKeys()\n"
"\tGet a list of pressed keys that have either been pressed, or just released this frame.\n" ;
@@ -639,7 +639,7 @@ PyObject* SCA_KeyboardSensor::PyGetPressedKeys(PyObject* self, PyObject* args, P
-char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] =
+const char SCA_KeyboardSensor::GetCurrentlyPressedKeys_doc[] =
"getCurrentlyPressedKeys()\n"
"\tGet a list of keys that are currently pressed.\n" ;
@@ -710,17 +710,17 @@ PyParentObject SCA_KeyboardSensor::Parents[] = {
};
PyMethodDef SCA_KeyboardSensor::Methods[] = {
- {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, GetKey_doc},
- {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, SetKey_doc},
- {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, GetHold1_doc},
- {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, SetHold1_doc},
- {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, GetHold2_doc},
- {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, SetHold2_doc},
-// {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, GetUseAllKeys_doc},
-// {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, SetUseAllKeys_doc},
- {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, GetPressedKeys_doc},
- {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, GetCurrentlyPressedKeys_doc},
-// {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, GetKeyEvents_doc},
+ {"getKey", (PyCFunction) SCA_KeyboardSensor::sPyGetKey, METH_VARARGS, (PY_METHODCHAR)GetKey_doc},
+ {"setKey", (PyCFunction) SCA_KeyboardSensor::sPySetKey, METH_VARARGS, (PY_METHODCHAR)SetKey_doc},
+ {"getHold1", (PyCFunction) SCA_KeyboardSensor::sPyGetHold1, METH_VARARGS, (PY_METHODCHAR)GetHold1_doc},
+ {"setHold1", (PyCFunction) SCA_KeyboardSensor::sPySetHold1, METH_VARARGS, (PY_METHODCHAR)SetHold1_doc},
+ {"getHold2", (PyCFunction) SCA_KeyboardSensor::sPyGetHold2, METH_VARARGS, (PY_METHODCHAR)GetHold2_doc},
+ {"setHold2", (PyCFunction) SCA_KeyboardSensor::sPySetHold2, METH_VARARGS, (PY_METHODCHAR)SetHold2_doc},
+// {"getUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)GetUseAllKeys_doc},
+// {"setUseAllKeys", (PyCFunction) SCA_KeyboardSensor::sPySetUseAllKeys, METH_VARARGS, (PY_METHODCHAR)SetUseAllKeys_doc},
+ {"getPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetPressedKeys_doc},
+ {"getCurrentlyPressedKeys", (PyCFunction) SCA_KeyboardSensor::sPyGetCurrentlyPressedKeys, METH_VARARGS, (PY_METHODCHAR)GetCurrentlyPressedKeys_doc},
+// {"getKeyEvents", (PyCFunction) SCA_KeyboardSensor::sPyGetKeyEvents, METH_VARARGS, (PY_METHODCHAR)GetKeyEvents_doc},
{NULL,NULL} //Sentinel
};
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index 91e66aea359..b584b37180f 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -33,6 +33,7 @@
#include "SCA_IController.h"
#include "SCA_IActuator.h"
#include "SCA_EventManager.h"
+#include "SCA_PythonController.h"
#include <set>
#ifdef HAVE_CONFIG_H
@@ -232,8 +233,6 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
// for this frame, look up for activated sensors, and build the collection of triggered controllers
// int numsensors = this->m_activatedsensors.size(); /*unused*/
- set<SmartControllerPtr> triggeredControllerSet;
-
for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
!(is==m_activatedsensors.end());is++)
{
@@ -244,19 +243,28 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
{
SCA_IController* contr = *c;//controllerarray->at(c);
if (contr->IsActive())
- triggeredControllerSet.insert(SmartControllerPtr(contr,0));
+ {
+ m_triggeredControllerSet.insert(SmartControllerPtr(contr,0));
+ // So that the controller knows which sensor has activited it.
+ // Only needed for the python controller though.
+ if (contr->GetType() == &SCA_PythonController::Type)
+ {
+ SCA_PythonController* pythonController = (SCA_PythonController*)contr;
+ pythonController->AddTriggeredSensor(sensor);
+ }
+ }
}
//sensor->SetActive(false);
}
// int numtriggered = triggeredControllerSet.size(); /*unused*/
- for (set<SmartControllerPtr>::iterator tit=triggeredControllerSet.begin();
- !(tit==triggeredControllerSet.end());tit++)
+ for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin();
+ !(tit==m_triggeredControllerSet.end());tit++)
{
(*tit)->Trigger(this);
}
- triggeredControllerSet.clear();
+ m_triggeredControllerSet.clear();
}
@@ -382,6 +390,17 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor)
}
}
+void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor)
+{
+ m_triggeredControllerSet.insert(SmartControllerPtr(controller,0));
+ // so that the controller knows which sensor has activited it
+ // only needed for python controller
+ if (controller->GetType() == &SCA_PythonController::Type)
+ {
+ SCA_PythonController* pythonController = (SCA_PythonController*)controller;
+ pythonController->AddTriggeredSensor(sensor);
+ }
+}
void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event)
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index e0d3d506702..50383879d8f 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -99,6 +99,7 @@ class SCA_LogicManager
vector<class SCA_ISensor*> m_activatedsensors;
set<class SmartActuatorPtr> m_activeActuators;
+ set<class SmartControllerPtr> m_triggeredControllerSet;
map<SCA_ISensor*,controllerlist > m_sensorcontrollermapje;
@@ -127,6 +128,7 @@ public:
void EndFrame();
void AddActivatedSensor(SCA_ISensor* sensor);
void AddActiveActuator(SCA_IActuator* sensor,class CValue* event);
+ void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor);
SCA_EventManager* FindEventManager(int eventmgrtype);
void RemoveGameObject(const STR_String& gameobjname);
diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
index 2298ddb0743..d4952ce4777 100644
--- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp
@@ -283,8 +283,8 @@ PyParentObject SCA_MouseSensor::Parents[] = {
};
PyMethodDef SCA_MouseSensor::Methods[] = {
- {"getXPosition", (PyCFunction) SCA_MouseSensor::sPyGetXPosition, METH_VARARGS, GetXPosition_doc},
- {"getYPosition", (PyCFunction) SCA_MouseSensor::sPyGetYPosition, METH_VARARGS, GetYPosition_doc},
+ {"getXPosition", (PyCFunction) SCA_MouseSensor::sPyGetXPosition, METH_VARARGS, (PY_METHODCHAR)GetXPosition_doc},
+ {"getYPosition", (PyCFunction) SCA_MouseSensor::sPyGetYPosition, METH_VARARGS, (PY_METHODCHAR)GetYPosition_doc},
{NULL,NULL} //Sentinel
};
@@ -293,7 +293,7 @@ PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) {
}
/* get x position ---------------------------------------------------------- */
-char SCA_MouseSensor::GetXPosition_doc[] =
+const char SCA_MouseSensor::GetXPosition_doc[] =
"getXPosition\n"
"\tReturns the x-coordinate of the mouse sensor, in frame coordinates.\n"
"\tThe lower-left corner is the origin. The coordinate is given in\n"
@@ -305,7 +305,7 @@ PyObject* SCA_MouseSensor::PyGetXPosition(PyObject* self,
}
/* get y position ---------------------------------------------------------- */
-char SCA_MouseSensor::GetYPosition_doc[] =
+const char SCA_MouseSensor::GetYPosition_doc[] =
"getYPosition\n"
"\tReturns the y-coordinate of the mouse sensor, in frame coordinates.\n"
"\tThe lower-left corner is the origin. The coordinate is given in\n"
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index 7062f2cef6a..3b541e87f02 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -245,10 +245,10 @@ PyParentObject SCA_PropertyActuator::Parents[] = {
};
PyMethodDef SCA_PropertyActuator::Methods[] = {
- {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, SetValue_doc},
- {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, GetValue_doc},
+ {"setProperty", (PyCFunction) SCA_PropertyActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"getProperty", (PyCFunction) SCA_PropertyActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"setValue", (PyCFunction) SCA_PropertyActuator::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc},
+ {"getValue", (PyCFunction) SCA_PropertyActuator::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc},
{NULL,NULL} //Sentinel
};
@@ -257,7 +257,7 @@ PyObject* SCA_PropertyActuator::_getattr(const STR_String& attr) {
}
/* 1. setProperty */
-char SCA_PropertyActuator::SetProperty_doc[] =
+const char SCA_PropertyActuator::SetProperty_doc[] =
"setProperty(name)\n"
"\t- name: string\n"
"\tSet the property on which to operate. If there is no property\n"
@@ -283,7 +283,7 @@ PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, Py
}
/* 2. getProperty */
-char SCA_PropertyActuator::GetProperty_doc[] =
+const char SCA_PropertyActuator::GetProperty_doc[] =
"getProperty(name)\n"
"\tReturn the property on which the actuator operates.\n";
PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
@@ -292,7 +292,7 @@ PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* self, PyObject* args, Py
}
/* 3. setValue */
-char SCA_PropertyActuator::SetValue_doc[] =
+const char SCA_PropertyActuator::SetValue_doc[] =
"setValue(value)\n"
"\t- value: string\n"
"\tSet the value with which the actuator operates. If the value\n"
@@ -311,7 +311,7 @@ PyObject* SCA_PropertyActuator::PySetValue(PyObject* self, PyObject* args, PyObj
}
/* 4. getValue */
-char SCA_PropertyActuator::GetValue_doc[] =
+const char SCA_PropertyActuator::GetValue_doc[] =
"getValue()\n"
"\tReturns the value with which the actuator operates.\n";
PyObject* SCA_PropertyActuator::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
index c50c011cc63..64e3d49c6cb 100644
--- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp
@@ -333,12 +333,12 @@ PyParentObject SCA_PropertySensor::Parents[] = {
};
PyMethodDef SCA_PropertySensor::Methods[] = {
- {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, GetType_doc},
- {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, SetType_doc},
- {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, GetValue_doc},
- {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, SetValue_doc},
+ {"getType", (PyCFunction) SCA_PropertySensor::sPyGetType, METH_VARARGS, (PY_METHODCHAR)GetType_doc},
+ {"setType", (PyCFunction) SCA_PropertySensor::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc},
+ {"getProperty", (PyCFunction) SCA_PropertySensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"setProperty", (PyCFunction) SCA_PropertySensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"getValue", (PyCFunction) SCA_PropertySensor::sPyGetValue, METH_VARARGS, (PY_METHODCHAR)GetValue_doc},
+ {"setValue", (PyCFunction) SCA_PropertySensor::sPySetValue, METH_VARARGS, (PY_METHODCHAR)SetValue_doc},
{NULL,NULL} //Sentinel
};
@@ -347,7 +347,7 @@ PyObject* SCA_PropertySensor::_getattr(const STR_String& attr) {
}
/* 1. getType */
-char SCA_PropertySensor::GetType_doc[] =
+const char SCA_PropertySensor::GetType_doc[] =
"getType()\n"
"\tReturns the type of check this sensor performs.\n";
PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject* kwds)
@@ -356,7 +356,7 @@ PyObject* SCA_PropertySensor::PyGetType(PyObject* self, PyObject* args, PyObject
}
/* 2. setType */
-char SCA_PropertySensor::SetType_doc[] =
+const char SCA_PropertySensor::SetType_doc[] =
"setType(type)\n"
"\t- type: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL,\n"
"\t KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED,\n"
@@ -379,7 +379,7 @@ PyObject* SCA_PropertySensor::PySetType(PyObject* self, PyObject* args, PyObject
}
/* 3. getProperty */
-char SCA_PropertySensor::GetProperty_doc[] =
+const char SCA_PropertySensor::GetProperty_doc[] =
"getProperty()\n"
"\tReturn the property with which the sensor operates.\n";
PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyObject* kwds)
@@ -388,7 +388,7 @@ PyObject* SCA_PropertySensor::PyGetProperty(PyObject* self, PyObject* args, PyOb
}
/* 4. setProperty */
-char SCA_PropertySensor::SetProperty_doc[] =
+const char SCA_PropertySensor::SetProperty_doc[] =
"setProperty(name)\n"
"\t- name: string\n"
"\tSets the property with which to operate. If there is no property\n"
@@ -414,7 +414,7 @@ PyObject* SCA_PropertySensor::PySetProperty(PyObject* self, PyObject* args, PyOb
}
/* 5. getValue */
-char SCA_PropertySensor::GetValue_doc[] =
+const char SCA_PropertySensor::GetValue_doc[] =
"getValue()\n"
"\tReturns the value with which the sensor operates.\n";
PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObject* kwds)
@@ -423,7 +423,7 @@ PyObject* SCA_PropertySensor::PyGetValue(PyObject* self, PyObject* args, PyObjec
}
/* 6. setValue */
-char SCA_PropertySensor::SetValue_doc[] =
+const char SCA_PropertySensor::SetValue_doc[] =
"setValue(value)\n"
"\t- value: string\n"
"\tSet the value with which the sensor operates. If the value\n"
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index cd1b029fc34..4cb9bc8fe53 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -33,8 +33,11 @@
#include "SCA_LogicManager.h"
#include "SCA_ISensor.h"
#include "SCA_IActuator.h"
+#include "PyObjectPlus.h"
#include "compile.h"
#include "eval.h"
+#include <algorithm>
+
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -139,8 +142,16 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary)
m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */
}
+int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
+{
+ if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) !=
+ m_triggeredSensors.end())
+ return 1;
+ return 0;
+}
+
#if 0
-static char* sPyGetCurrentController__doc__;
+static const char* sPyGetCurrentController__doc__;
#endif
@@ -151,7 +162,7 @@ PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self)
}
#if 0
-static char* sPyAddActiveActuator__doc__;
+static const char* sPyAddActiveActuator__doc__;
#endif
PyObject* SCA_PythonController::sPyAddActiveActuator(
@@ -188,9 +199,9 @@ PyObject* SCA_PythonController::sPyAddActiveActuator(
}
-char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
-char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)";
-char SCA_PythonController::GetActuators_doc[] = "getActuator";
+const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()";
+const char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)";
+const char SCA_PythonController::GetActuators_doc[] = "getActuator";
PyTypeObject SCA_PythonController::Type = {
PyObject_HEAD_INIT(&PyType_Type)
@@ -218,10 +229,10 @@ PyParentObject SCA_PythonController::Parents[] = {
NULL
};
PyMethodDef SCA_PythonController::Methods[] = {
- {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, SCA_PythonController::GetActuators_doc},
- {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, SCA_PythonController::GetActuator_doc},
- {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, SCA_PythonController::GetSensors_doc},
- {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, SCA_PythonController::GetSensor_doc},
+ {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc},
+ {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc},
+ {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc},
+ {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc},
{"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS},
{"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O},
{"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS},
@@ -248,7 +259,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
{
// didn't compile, so instead of compile, complain
// something is wrong, tell the user what went wrong
- printf("PYTHON SCRIPT ERROR:\n");
+ printf("Python compile error from controller \"%s\": \n", GetName().Ptr());
//PyRun_SimpleString(m_scriptText.Ptr());
PyErr_Print();
return;
@@ -285,7 +296,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
else
{
// something is wrong, tell the user what went wrong
- printf("PYTHON SCRIPT ERROR:\n");
+ printf("Python script error from controller \"%s\": \n", GetName().Ptr());
PyErr_Print();
//PyRun_SimpleString(m_scriptText.Ptr());
}
@@ -294,7 +305,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
// something in this dictionary and crash?
PyDict_Clear(excdict);
Py_DECREF(excdict);
-
+ m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end());
m_sCurrentController = NULL;
}
@@ -318,7 +329,7 @@ PyObject* SCA_PythonController::PyGetActuators(PyObject* self)
return resultlist;
}
-char SCA_PythonController::GetSensor_doc[] =
+const char SCA_PythonController::GetSensor_doc[] =
"GetSensor (char sensorname) return linked sensor that is named [sensorname]\n";
PyObject*
SCA_PythonController::PyGetSensor(PyObject* self, PyObject* value)
@@ -348,7 +359,7 @@ SCA_PythonController::PyGetSensor(PyObject* self, PyObject* value)
-char SCA_PythonController::GetActuator_doc[] =
+const char SCA_PythonController::GetActuator_doc[] =
"GetActuator (char sensorname) return linked actuator that is named [actuatorname]\n";
PyObject*
SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value)
@@ -377,7 +388,7 @@ SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value)
}
-char SCA_PythonController::GetSensors_doc[] = "getSensors returns a list of all attached sensors";
+const char SCA_PythonController::GetSensors_doc[] = "getSensors returns a list of all attached sensors";
PyObject*
SCA_PythonController::PyGetSensors(PyObject* self)
{
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index 39b6c68c359..d9b2e242bea 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -36,6 +36,8 @@
#include "SCA_LogicManager.h"
#include "BoolValue.h"
+#include <vector>
+
class SCA_IObject;
class SCA_PythonController : public SCA_IController
{
@@ -47,6 +49,7 @@ class SCA_PythonController : public SCA_IController
STR_String m_scriptText;
STR_String m_scriptName;
PyObject* m_pythondictionary;
+ std::vector<class SCA_ISensor*> m_triggeredSensors;
public:
static SCA_PythonController* m_sCurrentController; // protected !!!
@@ -64,10 +67,13 @@ class SCA_PythonController : public SCA_IController
void SetScriptText(const STR_String& text);
void SetScriptName(const STR_String& name);
void SetDictionary(PyObject* pythondictionary);
+ void AddTriggeredSensor(class SCA_ISensor* sensor)
+ { m_triggeredSensors.push_back(sensor); }
+ int IsTriggered(class SCA_ISensor* sensor);
- static char* sPyGetCurrentController__doc__;
+ static const char* sPyGetCurrentController__doc__;
static PyObject* sPyGetCurrentController(PyObject* self);
- static char* sPyAddActiveActuator__doc__;
+ static const char* sPyAddActiveActuator__doc__;
static PyObject* sPyAddActiveActuator(PyObject* self,
PyObject* args);
virtual PyObject* _getattr(const STR_String& attr);
diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
index 0a1ac2d0668..7b50a483cd8 100644
--- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp
@@ -339,23 +339,23 @@ PyParentObject SCA_RandomActuator::Parents[] = {
};
PyMethodDef SCA_RandomActuator::Methods[] = {
- {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, SetSeed_doc},
- {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, GetSeed_doc},
- {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, GetPara1_doc},
- {"getPara2", (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, GetPara2_doc},
- {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, GetDistribution_doc},
- {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, SetBoolConst_doc},
- {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, SetBoolUniform_doc},
- {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, SetBoolBernouilli_doc},
- {"setIntConst", (PyCFunction) SCA_RandomActuator::sPySetIntConst, METH_VARARGS, SetIntConst_doc},
- {"setIntUniform", (PyCFunction) SCA_RandomActuator::sPySetIntUniform, METH_VARARGS, SetIntUniform_doc},
- {"setIntPoisson", (PyCFunction) SCA_RandomActuator::sPySetIntPoisson, METH_VARARGS, SetIntPoisson_doc},
- {"setFloatConst", (PyCFunction) SCA_RandomActuator::sPySetFloatConst, METH_VARARGS, SetFloatConst_doc},
- {"setFloatUniform", (PyCFunction) SCA_RandomActuator::sPySetFloatUniform, METH_VARARGS, SetFloatUniform_doc},
- {"setFloatNormal", (PyCFunction) SCA_RandomActuator::sPySetFloatNormal, METH_VARARGS, SetFloatNormal_doc},
- {"setFloatNegativeExponential", (PyCFunction) SCA_RandomActuator::sPySetFloatNegativeExponential, METH_VARARGS, SetFloatNegativeExponential_doc},
+ {"setSeed", (PyCFunction) SCA_RandomActuator::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc},
+ {"getSeed", (PyCFunction) SCA_RandomActuator::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc},
+ {"getPara1", (PyCFunction) SCA_RandomActuator::sPyGetPara1, METH_VARARGS, (PY_METHODCHAR)GetPara1_doc},
+ {"getPara2", (PyCFunction) SCA_RandomActuator::sPyGetPara2, METH_VARARGS, (PY_METHODCHAR)GetPara2_doc},
+ {"getDistribution", (PyCFunction) SCA_RandomActuator::sPyGetDistribution, METH_VARARGS, (PY_METHODCHAR)GetDistribution_doc},
+ {"setProperty", (PyCFunction) SCA_RandomActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"getProperty", (PyCFunction) SCA_RandomActuator::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"setBoolConst", (PyCFunction) SCA_RandomActuator::sPySetBoolConst, METH_VARARGS, (PY_METHODCHAR)SetBoolConst_doc},
+ {"setBoolUniform", (PyCFunction) SCA_RandomActuator::sPySetBoolUniform, METH_VARARGS, (PY_METHODCHAR)SetBoolUniform_doc},
+ {"setBoolBernouilli",(PyCFunction) SCA_RandomActuator::sPySetBoolBernouilli, METH_VARARGS, (PY_METHODCHAR)SetBoolBernouilli_doc},
+ {"setIntConst", (PyCFunction) SCA_RandomActuator::sPySetIntConst, METH_VARARGS, (PY_METHODCHAR)SetIntConst_doc},
+ {"setIntUniform", (PyCFunction) SCA_RandomActuator::sPySetIntUniform, METH_VARARGS, (PY_METHODCHAR)SetIntUniform_doc},
+ {"setIntPoisson", (PyCFunction) SCA_RandomActuator::sPySetIntPoisson, METH_VARARGS, (PY_METHODCHAR)SetIntPoisson_doc},
+ {"setFloatConst", (PyCFunction) SCA_RandomActuator::sPySetFloatConst, METH_VARARGS, (PY_METHODCHAR)SetFloatConst_doc},
+ {"setFloatUniform", (PyCFunction) SCA_RandomActuator::sPySetFloatUniform, METH_VARARGS, (PY_METHODCHAR)SetFloatUniform_doc},
+ {"setFloatNormal", (PyCFunction) SCA_RandomActuator::sPySetFloatNormal, METH_VARARGS, (PY_METHODCHAR)SetFloatNormal_doc},
+ {"setFloatNegativeExponential", (PyCFunction) SCA_RandomActuator::sPySetFloatNegativeExponential, METH_VARARGS, (PY_METHODCHAR)SetFloatNegativeExponential_doc},
{NULL,NULL} //Sentinel
};
@@ -364,7 +364,7 @@ PyObject* SCA_RandomActuator::_getattr(const STR_String& attr) {
}
/* 1. setSeed */
-char SCA_RandomActuator::SetSeed_doc[] =
+const char SCA_RandomActuator::SetSeed_doc[] =
"setSeed(seed)\n"
"\t- seed: integer\n"
"\tSet the initial seed of the generator. Equal seeds produce\n"
@@ -381,7 +381,7 @@ PyObject* SCA_RandomActuator::PySetSeed(PyObject* self, PyObject* args, PyObject
Py_Return;
}
/* 2. getSeed */
-char SCA_RandomActuator::GetSeed_doc[] =
+const char SCA_RandomActuator::GetSeed_doc[] =
"getSeed()\n"
"\tReturns the initial seed of the generator. Equal seeds produce\n"
"\tequal series.\n";
@@ -390,7 +390,7 @@ PyObject* SCA_RandomActuator::PyGetSeed(PyObject* self, PyObject* args, PyObject
}
/* 4. getPara1 */
-char SCA_RandomActuator::GetPara1_doc[] =
+const char SCA_RandomActuator::GetPara1_doc[] =
"getPara1()\n"
"\tReturns the first parameter of the active distribution. Refer\n"
"\tto the documentation of the generator types for the meaning\n"
@@ -400,7 +400,7 @@ PyObject* SCA_RandomActuator::PyGetPara1(PyObject* self, PyObject* args, PyObjec
}
/* 6. getPara2 */
-char SCA_RandomActuator::GetPara2_doc[] =
+const char SCA_RandomActuator::GetPara2_doc[] =
"getPara2()\n"
"\tReturns the first parameter of the active distribution. Refer\n"
"\tto the documentation of the generator types for the meaning\n"
@@ -410,7 +410,7 @@ PyObject* SCA_RandomActuator::PyGetPara2(PyObject* self, PyObject* args, PyObjec
}
/* 8. getDistribution */
-char SCA_RandomActuator::GetDistribution_doc[] =
+const char SCA_RandomActuator::GetDistribution_doc[] =
"getDistribution()\n"
"\tReturns the type of the active distribution.\n";
PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args, PyObject* kwds) {
@@ -418,7 +418,7 @@ PyObject* SCA_RandomActuator::PyGetDistribution(PyObject* self, PyObject* args,
}
/* 9. setProperty */
-char SCA_RandomActuator::SetProperty_doc[] =
+const char SCA_RandomActuator::SetProperty_doc[] =
"setProperty(name)\n"
"\t- name: string\n"
"\tSet the property to which the random value is assigned. If the \n"
@@ -441,7 +441,7 @@ PyObject* SCA_RandomActuator::PySetProperty(PyObject* self, PyObject* args, PyOb
Py_Return;
}
/* 10. getProperty */
-char SCA_RandomActuator::GetProperty_doc[] =
+const char SCA_RandomActuator::GetProperty_doc[] =
"getProperty(name)\n"
"\tReturn the property to which the random value is assigned. If the \n"
"\tgenerator and property types do not match, the assignment is ignored.\n";
@@ -450,7 +450,7 @@ PyObject* SCA_RandomActuator::PyGetProperty(PyObject* self, PyObject* args, PyOb
}
/* 11. setBoolConst */
-char SCA_RandomActuator::SetBoolConst_doc[] =
+const char SCA_RandomActuator::SetBoolConst_doc[] =
"setBoolConst(value)\n"
"\t- value: 0 or 1\n"
"\tSet this generator to produce a constant boolean value.\n";
@@ -470,7 +470,7 @@ PyObject* SCA_RandomActuator::PySetBoolConst(PyObject* self,
Py_Return;
}
/* 12. setBoolUniform, */
-char SCA_RandomActuator::SetBoolUniform_doc[] =
+const char SCA_RandomActuator::SetBoolUniform_doc[] =
"setBoolUniform()\n"
"\tSet this generator to produce true and false, each with 50%% chance of occuring\n";
PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self,
@@ -482,7 +482,7 @@ PyObject* SCA_RandomActuator::PySetBoolUniform(PyObject* self,
Py_Return;
}
/* 13. setBoolBernouilli, */
-char SCA_RandomActuator::SetBoolBernouilli_doc[] =
+const char SCA_RandomActuator::SetBoolBernouilli_doc[] =
"setBoolBernouilli(value)\n"
"\t- value: a float between 0 and 1\n"
"\tReturn false value * 100%% of the time.\n";
@@ -500,7 +500,7 @@ PyObject* SCA_RandomActuator::PySetBoolBernouilli(PyObject* self,
Py_Return;
}
/* 14. setIntConst,*/
-char SCA_RandomActuator::SetIntConst_doc[] =
+const char SCA_RandomActuator::SetIntConst_doc[] =
"setIntConst(value)\n"
"\t- value: integer\n"
"\tAlways return value\n";
@@ -518,7 +518,7 @@ PyObject* SCA_RandomActuator::PySetIntConst(PyObject* self,
Py_Return;
}
/* 15. setIntUniform,*/
-char SCA_RandomActuator::SetIntUniform_doc[] =
+const char SCA_RandomActuator::SetIntUniform_doc[] =
"setIntUniform(lower_bound, upper_bound)\n"
"\t- lower_bound: integer\n"
"\t- upper_bound: integer\n"
@@ -539,7 +539,7 @@ PyObject* SCA_RandomActuator::PySetIntUniform(PyObject* self,
Py_Return;
}
/* 16. setIntPoisson, */
-char SCA_RandomActuator::SetIntPoisson_doc[] =
+const char SCA_RandomActuator::SetIntPoisson_doc[] =
"setIntPoisson(value)\n"
"\t- value: float\n"
"\tReturn a Poisson-distributed number. This performs a series\n"
@@ -559,7 +559,7 @@ PyObject* SCA_RandomActuator::PySetIntPoisson(PyObject* self,
Py_Return;
}
/* 17. setFloatConst,*/
-char SCA_RandomActuator::SetFloatConst_doc[] =
+const char SCA_RandomActuator::SetFloatConst_doc[] =
"setFloatConst(value)\n"
"\t- value: float\n"
"\tAlways return value\n";
@@ -577,7 +577,7 @@ PyObject* SCA_RandomActuator::PySetFloatConst(PyObject* self,
Py_Return;
}
/* 18. setFloatUniform, */
-char SCA_RandomActuator::SetFloatUniform_doc[] =
+const char SCA_RandomActuator::SetFloatUniform_doc[] =
"setFloatUniform(lower_bound, upper_bound)\n"
"\t- lower_bound: float\n"
"\t- upper_bound: float\n"
@@ -598,7 +598,7 @@ PyObject* SCA_RandomActuator::PySetFloatUniform(PyObject* self,
Py_Return;
}
/* 19. setFloatNormal, */
-char SCA_RandomActuator::SetFloatNormal_doc[] =
+const char SCA_RandomActuator::SetFloatNormal_doc[] =
"setFloatNormal(mean, standard_deviation)\n"
"\t- mean: float\n"
"\t- standard_deviation: float\n"
@@ -619,7 +619,7 @@ PyObject* SCA_RandomActuator::PySetFloatNormal(PyObject* self,
Py_Return;
}
/* 20. setFloatNegativeExponential, */
-char SCA_RandomActuator::SetFloatNegativeExponential_doc[] =
+const char SCA_RandomActuator::SetFloatNegativeExponential_doc[] =
"setFloatNegativeExponential(half_life)\n"
"\t- half_life: float\n"
"\tReturn negative-exponentially distributed numbers. The half-life 'time'\n"
diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
index 3626522e49a..202fd6382e6 100644
--- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp
@@ -154,9 +154,9 @@ PyParentObject SCA_RandomSensor::Parents[] = {
};
PyMethodDef SCA_RandomSensor::Methods[] = {
- {"setSeed", (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, SetSeed_doc},
- {"getSeed", (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_VARARGS, GetSeed_doc},
- {"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_VARARGS, GetLastDraw_doc},
+ {"setSeed", (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc},
+ {"getSeed", (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_VARARGS, (PY_METHODCHAR)GetSeed_doc},
+ {"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_VARARGS, (PY_METHODCHAR)GetLastDraw_doc},
{NULL,NULL} //Sentinel
};
@@ -165,7 +165,7 @@ PyObject* SCA_RandomSensor::_getattr(const STR_String& attr) {
}
/* 1. setSeed */
-char SCA_RandomSensor::SetSeed_doc[] =
+const char SCA_RandomSensor::SetSeed_doc[] =
"setSeed(seed)\n"
"\t- seed: integer\n"
"\tSet the initial seed of the generator. Equal seeds produce\n"
@@ -183,7 +183,7 @@ PyObject* SCA_RandomSensor::PySetSeed(PyObject* self, PyObject* args, PyObject*
}
/* 2. getSeed */
-char SCA_RandomSensor::GetSeed_doc[] =
+const char SCA_RandomSensor::GetSeed_doc[] =
"getSeed()\n"
"\tReturns the initial seed of the generator. Equal seeds produce\n"
"\tequal series.\n";
@@ -192,7 +192,7 @@ PyObject* SCA_RandomSensor::PyGetSeed(PyObject* self, PyObject* args, PyObject*
}
/* 3. getLastDraw */
-char SCA_RandomSensor::GetLastDraw_doc[] =
+const char SCA_RandomSensor::GetLastDraw_doc[] =
"getLastDraw()\n"
"\tReturn the last value that was drawn.\n";
PyObject* SCA_RandomSensor::PyGetLastDraw(PyObject* self, PyObject* args, PyObject* kwds) {
diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript
index 1ca884f6dec..fa5a3123215 100644
--- a/source/gameengine/GameLogic/SConscript
+++ b/source/gameengine/GameLogic/SConscript
@@ -10,4 +10,9 @@ incs += ' #/source/gameengine/Rasterizer'
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_SDL_INC']
-env.BlenderLib ( 'bf_logic', sources, Split(incs), [], libtype=['game','player'], priority=[30, 110] )
+defs = ''
+
+if not env['WITH_BF_SDL']:
+ defs += ' DISABLE_SDL'
+
+env.BlenderLib ( 'bf_logic', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[30, 110] )
diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt
index ff1040bfb40..fc5912155cf 100644
--- a/source/gameengine/GamePlayer/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/CMakeLists.txt
@@ -25,3 +25,7 @@
# ***** END GPL LICENSE BLOCK *****
SUBDIRS(common ghost)
+
+IF(WITH_WEBPLUGIN)
+ SUBDIRS(xembed)
+ENDIF(WITH_WEBPLUGIN)
diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt
index e26f8b9d69a..0c6c4179e2d 100644
--- a/source/gameengine/GamePlayer/common/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/common/CMakeLists.txt
@@ -30,7 +30,6 @@ SET(SRC
GPC_Engine.cpp
GPC_KeyboardDevice.cpp
GPC_MouseDevice.cpp
- GPC_PolygonMaterial.cpp
GPC_RawImage.cpp
GPC_RawLoadDotBlendArray.cpp
GPC_RawLogoArrays.cpp
@@ -69,6 +68,7 @@ SET(INC
../../../../source/gameengine/GamePlayer/ghost
../../../../source/blender/misc
../../../../source/blender/blenloader
+ ../../../../source/blender/gpu
../../../../extern/glew/include
${PYTHON_INC}
${SOLID_INC}
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
index a9cfb0a9366..e6e97cbdfd3 100644
--- a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp
@@ -45,7 +45,7 @@ GPC_RawImage::GPC_RawImage()
bool GPC_RawImage::Load(
- char *srcName,
+ const char *srcName,
int destWidth, int destHeight,
TImageAlignment alignment, int offsetX, int offsetY)
{
diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.h b/source/gameengine/GamePlayer/common/GPC_RawImage.h
index 17c00d2fcc3..49a3043bffc 100644
--- a/source/gameengine/GamePlayer/common/GPC_RawImage.h
+++ b/source/gameengine/GamePlayer/common/GPC_RawImage.h
@@ -61,7 +61,7 @@ public:
* @param offsetX Amount of horzontal offset applied to the resource image.
* @param offsetY Amount of vertical offset applied to the resource image.
*/
- virtual bool Load(char *srcName,
+ virtual bool Load(const char *srcName,
int destWidth, int destHeight,
TImageAlignment alignment = alignTopLeft,
int offsetX = 0, int offsetY = 0);
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
index 8b828393c67..78d8eaf2aa3 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp
@@ -27,141 +27,256 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#include <assert.h>
-
-#ifdef WIN32
-#pragma warning (disable : 4786)
-#include <windows.h>
-#endif
-
#include "GL/glew.h"
-#include <iostream>
-
-#include "GPC_RenderTools.h"
-
#include "RAS_IRenderTools.h"
#include "RAS_IRasterizer.h"
#include "RAS_LightObject.h"
#include "RAS_ICanvas.h"
#include "RAS_GLExtensionManager.h"
-// next two includes/dependencies come from the shadow feature
-// it needs the gameobject and the sumo physics scene for a raycast
#include "KX_GameObject.h"
-
-#include "GPC_PolygonMaterial.h"
#include "KX_PolygonMaterial.h"
-#include "Value.h"
+#include "KX_BlenderMaterial.h"
+#include "KX_RayCast.h"
+#include "KX_IPhysicsController.h"
+
+#include "PHY_IPhysicsEnvironment.h"
-//#include "KX_BlenderGL.h" // for text printing
-//#include "KX_BlenderClientObject.h"
#include "STR_String.h"
-#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting)
-
-
-// Blender includes
-/* This list includes only data type definitions */
-#include "DNA_object_types.h"
-#include "DNA_material_types.h"
-#include "DNA_image_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_group_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_property_types.h"
-#include "DNA_text_types.h"
-#include "DNA_sensor_types.h"
-#include "DNA_controller_types.h"
-#include "DNA_actuator_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_world_types.h"
-
-#include "BKE_global.h"
-#include "BKE_image.h"
-#include "BKE_bmfont.h"
+
+#include "GPU_draw.h"
+
+#include "BKE_bmfont.h" // for text printing
#include "BKE_bmfont_types.h"
-#include "BKE_main.h"
-#include "IMB_imbuf_types.h"
-// End of Blender includes
+#include "GPC_RenderTools.h"
-#include "KX_Scene.h"
-#include "KX_RayCast.h"
-#include "KX_IPhysicsController.h"
-#include "PHY_IPhysicsEnvironment.h"
-#include "KX_BlenderMaterial.h"
+unsigned int GPC_RenderTools::m_numgllights;
GPC_RenderTools::GPC_RenderTools()
{
m_font = BMF_GetFont(BMF_kHelvetica10);
+
glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights);
if (m_numgllights < 8)
m_numgllights = 8;
}
-
GPC_RenderTools::~GPC_RenderTools()
{
}
+void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty)
+{
+ m_clientobject = NULL;
+ m_lastlightlayer = -1;
+ m_lastlighting = false;
+ DisableOpenGLLights();
+}
void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty)
{
}
+/* ProcessLighting performs lighting on objects. the layer is a bitfield that
+ * contains layer information. There are 20 'official' layers in blender. A
+ * light is applied on an object only when they are in the same layer. OpenGL
+ * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
+ * a scene. */
-void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty)
+void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat)
{
- m_clientobject=NULL;
- m_modified=true;
- DisableOpenGLLights();
+ if(m_lastlightlayer == layer)
+ return;
-}
+ m_lastlightlayer = layer;
-int GPC_RenderTools::ProcessLighting(int layer)
-{
- int result = false;
+ bool enable = false;
- if (layer < 0)
- {
- DisableOpenGLLights();
- result = false;
- } else
+ if (layer >= 0)
{
if (m_clientobject)
- {
- if (applyLights(layer))
- {
- EnableOpenGLLights();
- result = true;
- } else
- {
- DisableOpenGLLights();
- result = false;
- }
+ {
+ if (layer == RAS_LIGHT_OBJECT_LAYER)
+ layer = static_cast<KX_GameObject*>(m_clientobject)->GetLayer();
+
+ enable = applyLights(layer, viewmat);
}
}
- return result;
+
+ if(enable)
+ EnableOpenGLLights();
+ else
+ DisableOpenGLLights();
}
void GPC_RenderTools::EnableOpenGLLights()
{
+ if(m_lastlighting == true)
+ return;
+
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
- glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
+
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true);
if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
+ m_lastlighting = true;
+}
+
+void GPC_RenderTools::DisableOpenGLLights()
+{
+ if(m_lastlighting == false)
+ return;
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+
+ m_lastlighting = false;
+}
+
+
+void GPC_RenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj)
+{
+ if (m_clientobject != obj)
+ {
+ bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling());
+ rasty->SetFrontFace(ccw);
+
+ m_clientobject = obj;
+ }
+}
+
+bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
+{
+ double* const oglmatrix = (double* const) data;
+ MT_Point3 resultpoint(result->m_hitPoint);
+ MT_Vector3 resultnormal(result->m_hitNormal);
+ MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
+ MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
+ left = (dir.cross(resultnormal)).safe_normalized();
+ // for the up vector, we take the 'resultnormal' returned by the physics
+
+ double maat[16]={
+ left[0], left[1], left[2], 0,
+ dir[0], dir[1], dir[2], 0,
+ resultnormal[0],resultnormal[1],resultnormal[2], 0,
+ 0, 0, 0, 1};
+ glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
+ //glMultMatrixd(oglmatrix);
+ glMultMatrixd(maat);
+ return true;
}
-void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
- const char* text,
- int xco,
- int yco,
- int width,
- int height)
+void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode )
+{
+ /* FIXME:
+ blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const
+ MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed.
+
+ Program received signal SIGABRT, Aborted.
+ [Switching to Thread 16384 (LWP 1519)]
+ 0x40477571 in kill () from /lib/libc.so.6
+ (gdb) bt
+ #7 0x08334368 in MT_Vector3::normalized() const ()
+ #8 0x0833e6ec in GPC_RenderTools::applyTransform(RAS_IRasterizer*, double*, int) ()
+ */
+
+ if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
+ objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
+ {
+ // rotate the billboard/halo
+ //page 360/361 3D Game Engine Design, David Eberly for a discussion
+ // on screen aligned and axis aligned billboards
+ // assumed is that the preprocessor transformed all billboard polygons
+ // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0)
+ // when new parenting for objects is done, this rotation
+ // will be moved into the object
+
+ MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ MT_Point3 campos = rasty->GetCameraPosition();
+ MT_Vector3 dir = (campos - objpos).safe_normalized();
+ MT_Vector3 up(0,0,1.0);
+
+ KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
+ // get scaling of halo object
+ MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
+
+ bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
+ if (screenaligned)
+ {
+ up = (up - up.dot(dir) * dir).safe_normalized();
+ } else
+ {
+ dir = (dir - up.dot(dir)*up).safe_normalized();
+ }
+
+ MT_Vector3 left = dir.normalized();
+ dir = (left.cross(up)).normalized();
+
+ // we have calculated the row vectors, now we keep
+ // local scaling into account:
+
+ left *= size[0];
+ dir *= size[1];
+ up *= size[2];
+ double maat[16]={
+ left[0], left[1],left[2], 0,
+ dir[0], dir[1],dir[2],0,
+ up[0],up[1],up[2],0,
+ 0,0,0,1};
+ glTranslated(objpos[0],objpos[1],objpos[2]);
+ glMultMatrixd(maat);
+
+ } else
+ {
+ if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
+ {
+ // shadow must be cast to the ground, physics system needed here!
+ MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
+ KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
+ MT_Vector3 direction = MT_Vector3(0,0,-1);
+
+ direction.normalize();
+ direction *= 100000;
+
+ MT_Point3 topoint = frompoint + direction;
+
+ KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
+ PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
+ KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
+
+ KX_GameObject *parent = gameobj->GetParent();
+ if (!physics_controller && parent)
+ physics_controller = parent->GetPhysicsController();
+ if (parent)
+ parent->Release();
+
+ KX_RayCast::Callback<GPC_RenderTools> callback(this, physics_controller, oglmatrix);
+ if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback))
+ {
+ // couldn't find something to cast the shadow on...
+ glMultMatrixd(oglmatrix);
+ }
+ } else
+ {
+
+ // 'normal' object
+ glMultMatrixd(oglmatrix);
+ }
+ }
+}
+
+
+void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height)
{
STR_String tmpstr(text);
int lines;
@@ -234,21 +349,19 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode,
glDisable(GL_LIGHTING);
}
-/**
- * Copied from KX_BlenderRenderTools.cpp in KX_blenderhook
- * Renders text into a (series of) polygon(s), using a texture font,
- * Each character consists of one polygon (one quad or two triangles)
- */
+/* Render Text renders text into a (series of) polygon, using a texture font,
+ * Each character consists of one polygon (one quad or two triangles) */
+
void GPC_RenderTools::RenderText(
int mode,
RAS_IPolyMaterial* polymat,
- float v1[3], float v2[3], float v3[3], float v4[3])
+ float v1[3], float v2[3], float v3[3], float v4[3], int glattrib)
{
STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
const unsigned int flag = polymat->GetFlag();
struct MTFace* tface = 0;
- unsigned int* col = 0;
+ unsigned int *col = 0;
if(flag & RAS_BLENDERMAT) {
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat);
@@ -259,110 +372,29 @@ void GPC_RenderTools::RenderText(
tface = blenderpoly->GetMTFace();
col = blenderpoly->GetMCol();
}
-
- BL_RenderText(mode, mytext, mytext.Length(), tface, col, v1, v2, v3, v4);
+
+ GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib);
}
-
-/**
- * Copied from KX_BlenderGL.cpp in KX_blenderhook
- */
-void GPC_RenderTools::BL_RenderText(
- int mode,
- const char* textstr,
- int textlen,
- struct MTFace* tface,
- unsigned int* col,
- float v1[3],float v2[3],float v3[3],float v4[3])
+void GPC_RenderTools::PushMatrix()
{
- struct Image* ima;
-
- if (mode & TF_BMFONT) {
- //char string[MAX_PROPSTRING];
-// float tmat[4][4];
- int characters, index, character;
- float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
-
-// bProperty *prop;
-
- // string = "Frank van Beek";
-
- characters = textlen;
-
- ima = (struct Image*) tface->tpage;
- if (ima == NULL) {
- characters = 0;
- }
-
- if(!col) glColor3f(1.0f, 1.0f, 1.0f);
-
- glPushMatrix();
- for (index = 0; index < characters; index++) {
- // lets calculate offset stuff
- character = textstr[index];
-
- // space starts at offset 1
- // character = character - ' ' + 1;
-
- matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
-
- glBegin(GL_POLYGON);
- // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], );
- // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
- glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
-
- if(col) BL_spack(col[0]);
- // glVertex3fv(v1);
- glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
-
- glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
- if(col) BL_spack(col[1]);
- // glVertex3fv(v2);
- glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
-
- glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
- if(col) BL_spack(col[2]);
- // glVertex3fv(v3);
- glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
-
- if(v4) {
- // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy);
- glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
- if(col) BL_spack(col[3]);
- // glVertex3fv(v4);
- glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
- }
- glEnd();
-
- glTranslatef(advance, 0.0, 0.0);
- }
- glPopMatrix();
-
- }
+ glPushMatrix();
}
-
-RAS_IPolyMaterial* GPC_RenderTools::CreateBlenderPolyMaterial(
- const STR_String &texname,
- bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant, bool zsort,
- int lightlayer,bool bIsTriangle,void* clientobject,void* tface)
+void GPC_RenderTools::PopMatrix()
{
- assert(!"Deprecated");
-/* return new GPC_PolygonMaterial(texname, ba,matname,tile,tilexrep,tileyrep,
- mode,transparant,zsort,lightlayer,bIsTriangle,clientobject,tface);
- */
- return NULL;
+ glPopMatrix();
}
-int GPC_RenderTools::applyLights(int objectlayer)
+int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat)
{
-// taken from blender source, incompatibility between Blender Object / GameObject
-
- int count;
+ // taken from blender source, incompatibility between Blender Object / GameObject
+ float glviewmat[16];
+ unsigned int count;
float vec[4];
-
+
vec[3]= 1.0;
for(count=0; count<m_numgllights; count++)
@@ -371,23 +403,20 @@ int GPC_RenderTools::applyLights(int objectlayer)
//std::vector<struct RAS_LightObject*> m_lights;
std::vector<struct RAS_LightObject*>::iterator lit = m_lights.begin();
+ viewmat.getValue(glviewmat);
+ glPushMatrix();
+ glLoadMatrixf(glviewmat);
for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit)
{
RAS_LightObject* lightdata = (*lit);
if (lightdata->m_layer & objectlayer)
{
-
- glPushMatrix();
- glLoadMatrixf(m_viewmat);
-
-
vec[0] = (*(lightdata->m_worldmatrix))(0,3);
vec[1] = (*(lightdata->m_worldmatrix))(1,3);
vec[2] = (*(lightdata->m_worldmatrix))(2,3);
vec[3] = 1;
-
if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) {
vec[0] = (*(lightdata->m_worldmatrix))(0,2);
@@ -443,142 +472,16 @@ int GPC_RenderTools::applyLights(int objectlayer)
}
glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec);
glEnable((GLenum)(GL_LIGHT0+count));
-
- count++;
- glPopMatrix();
+ count++;
}
}
+ glPopMatrix();
return count;
}
-void GPC_RenderTools::SetClientObject(void* obj)
-{
- if (m_clientobject != obj)
- {
- if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling())
- {
- glFrontFace(GL_CCW);
- } else
- {
- glFrontFace(GL_CW);
- }
- m_clientobject = obj;
- m_modified = true;
- }
-}
-
-bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
-{
- double* const oglmatrix = (double* const) data;
- MT_Point3 resultpoint(hit_point);
- MT_Vector3 resultnormal(hit_normal);
- MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]);
- MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized();
- left = (dir.cross(resultnormal)).safe_normalized();
- // for the up vector, we take the 'resultnormal' returned by the physics
-
- double maat[16]={
- left[0], left[1], left[2], 0,
- dir[0], dir[1], dir[2], 0,
- resultnormal[0],resultnormal[1],resultnormal[2], 0,
- 0, 0, 0, 1};
- glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]);
- //glMultMatrixd(oglmatrix);
- glMultMatrixd(maat);
- return true;
-}
-
-void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode )
-{
- if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED ||
- objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED)
- {
- // rotate the billboard/halo
- //page 360/361 3D Game Engine Design, David Eberly for a discussion
- // on screen aligned and axis aligned billboards
- // assumed is that the preprocessor transformed all billboard polygons
- // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0)
- // when new parenting for objects is done, this rotation
- // will be moved into the object
-
- MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- MT_Point3 campos = rasty->GetCameraPosition();
- MT_Vector3 dir = (campos - objpos).safe_normalized();
- MT_Vector3 up(0,0,1.0);
-
- KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject;
- // get scaling of halo object
- MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale();
-
- bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned
- if (screenaligned)
- {
- up = (up - up.dot(dir) * dir).safe_normalized();
- } else
- {
- dir = (dir - up.dot(dir)*up).safe_normalized();
- }
-
- MT_Vector3 left = dir.normalized();
- dir = (left.cross(up)).normalized();
-
- // we have calculated the row vectors, now we keep
- // local scaling into account:
-
- left *= size[0];
- dir *= size[1];
- up *= size[2];
- double maat[16]={
- left[0], left[1],left[2], 0,
- dir[0], dir[1],dir[2],0,
- up[0],up[1],up[2],0,
- 0,0,0,1};
- glTranslated(objpos[0],objpos[1],objpos[2]);
- glMultMatrixd(maat);
-
- } else
- {
- if (objectdrawmode & RAS_IPolyMaterial::SHADOW)
- {
- // shadow must be cast to the ground, physics system needed here!
- MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]);
- KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject;
- MT_Vector3 direction = MT_Vector3(0,0,-1);
-
- direction.normalize();
- direction *= 100000;
-
- MT_Point3 topoint = frompoint + direction;
-
- KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo;
- PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment();
- KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController();
-
- KX_GameObject *parent = gameobj->GetParent();
- if (!physics_controller && parent)
- physics_controller = parent->GetPhysicsController();
- if (parent)
- parent->Release();
-
- MT_Point3 resultpoint;
- MT_Vector3 resultnormal;
- if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<GPC_RenderTools>(this, oglmatrix)))
- {
- // couldn't find something to cast the shadow on...
- glMultMatrixd(oglmatrix);
- }
- } else
- {
-
- // 'normal' object
- glMultMatrixd(oglmatrix);
- }
- }
-}
-
void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer)
{
int state = rasterizer->GetMotionBlurState();
@@ -609,7 +512,6 @@ void GPC_RenderTools::Update2DFilter(vector<STR_String>& propNames, void* gameOb
void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas)
{
- m_filtermanager.RenderFilters( canvas);
+ m_filtermanager.RenderFilters(canvas);
}
-unsigned int GPC_RenderTools::m_numgllights;
diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
index 8fae3d2b305..382956e73ea 100644
--- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h
+++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h
@@ -31,114 +31,67 @@
#define __GPC_RENDERTOOLS_H
#ifdef WIN32
- #include <windows.h>
+// don't show stl-warnings
+#pragma warning (disable:4786)
+#include <windows.h>
#endif // WIN32
-#include "GL/glew.h"
-
#include "RAS_IRenderTools.h"
#include "BMF_Api.h"
struct KX_ClientObjectInfo;
+class KX_RayCast;
+/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which
+ * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon)
+ * text, lighting.
+ *
+ * Most of this code is duplicated in KX_BlenderRenderTools, so this should be
+ * moved to some common location to avoid duplication. */
class GPC_RenderTools : public RAS_IRenderTools
{
+ int m_lastlightlayer;
+ bool m_lastlighting;
+ static unsigned int m_numgllights;
+
+ BMF_Font* m_font;
+
public:
- GPC_RenderTools();
- virtual ~GPC_RenderTools();
-
- virtual void EndFrame(RAS_IRasterizer* rasty);
- virtual void BeginFrame(RAS_IRasterizer* rasty);
-
- void DisableOpenGLLights()
- {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- }
-
- void EnableOpenGLLights();
-
- int ProcessLighting(int layer);
-
- void Perspective(int a, int width, int height, float mat[4][4], float viewmat[4][4])
- {
- if(a== 0)
- {
- glMatrixMode(GL_PROJECTION);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
- else
- {
- if(a== 1)
- {
- glMatrixMode(GL_PROJECTION);
- glMatrixMode(GL_MODELVIEW);
- }
- }
- }
-
- /**
- * @attention mode is ignored here
- */
- virtual void RenderText2D(
- RAS_TEXT_RENDER_MODE mode,
- const char* text,
- int xco,
- int yco,
- int width,
- int height);
-
- /**
- * Renders text into a (series of) polygon(s), using a texture font,
- * Each character consists of one polygon (one quad or two triangles)
- */
- virtual void RenderText(
- int mode,
- RAS_IPolyMaterial* polymat,
- float v1[3],
- float v2[3],
- float v3[3],
- float v4[3]);
-
- void Render(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode)
- {
- glPopMatrix();
- glPushMatrix();
- glMultMatrixd(oglmatrix);
- }
-
- void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode);
-
- virtual void PushMatrix()
- {
- glPushMatrix();
- }
-
- virtual void PopMatrix()
- {
- glPopMatrix();
- }
-
- virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(
- const STR_String &texname,
- bool ba,
- const STR_String& matname,
- int tile,
- int tilexrep,int tileyrep,
- int mode,
- bool transparant,
- bool zsort,
- int lightlayer,
- bool bIsTriangle,
- void* clientobject,
- void* tface);
-
- int applyLights(int objectlayer);
-
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ GPC_RenderTools();
+ virtual ~GPC_RenderTools();
+
+ void EndFrame(RAS_IRasterizer* rasty);
+ void BeginFrame(RAS_IRasterizer* rasty);
+
+ void EnableOpenGLLights();
+ void DisableOpenGLLights();
+ void ProcessLighting(int layer, const MT_Transform& viewmat);
+
+ /* @attention mode is ignored here */
+ void RenderText2D(RAS_TEXT_RENDER_MODE mode,
+ const char* text,
+ int xco,
+ int yco,
+ int width,
+ int height);
+ void RenderText(int mode,
+ class RAS_IPolyMaterial* polymat,
+ float v1[3],
+ float v2[3],
+ float v3[3],
+ float v4[3],
+ int glattrib);
+
+ void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode);
+ int applyLights(int objectlayer, const MT_Transform& viewmat);
+
+ void PushMatrix();
+ void PopMatrix();
+
+ bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
virtual void MotionBlur(RAS_IRasterizer* rasterizer);
@@ -146,28 +99,7 @@ public:
virtual void Render2DFilters(RAS_ICanvas* canvas);
- virtual void SetClientObject(void* obj);
-
-protected:
- /**
- * Copied from KX_BlenderGL.cpp in KX_blenderhook
- */
- void BL_RenderText(
- int mode,
- const char* textstr,
- int textlen,
- struct MTFace* tface,
- unsigned int* col,
- float v1[3],float v2[3],float v3[3],float v4[3]);
- void BL_spack(unsigned int ucol)
- {
- char *cp = (char *)&ucol;
- glColor3ub(cp[3], cp[2], cp[1]);
- }
-
-
- BMF_Font* m_font;
- static unsigned int m_numgllights;
+ virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj);
};
#endif // __GPC_RENDERTOOLS_H
diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile
index 19d792ddbdb..6a12e659be6 100644
--- a/source/gameengine/GamePlayer/common/Makefile
+++ b/source/gameengine/GamePlayer/common/Makefile
@@ -43,6 +43,7 @@ CPPFLAGS += -I../../../blender/blenloader
CPPFLAGS += -I../../../blender/blenlib
CPPFLAGS += -I../../../blender/imbuf
CPPFLAGS += -I../../../blender/makesdna
+CPPFLAGS += -I../../../blender/gpu
CPPFLAGS += -I../../../kernel/gen_system
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
@@ -72,10 +73,6 @@ CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer
CPPFLAGS += -I../../../gameengine/Physics/Sumo
CPPFLAGS += -I../../../gameengine/Physics/common
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
-
###############################
SOURCEDIR = source/gameengine/GamePlayer/common
diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript
index 3b2367d2592..30f20a670d3 100644
--- a/source/gameengine/GamePlayer/common/SConscript
+++ b/source/gameengine/GamePlayer/common/SConscript
@@ -8,7 +8,6 @@ source_files = ['bmfont.cpp',
'GPC_Engine.cpp',
'GPC_KeyboardDevice.cpp',
'GPC_MouseDevice.cpp',
- 'GPC_PolygonMaterial.cpp',
'GPC_RawImage.cpp',
'GPC_RawLoadDotBlendArray.cpp',
'GPC_RawLogoArrays.cpp',
@@ -46,6 +45,7 @@ incs = ['.',
'#source/gameengine/GamePlayer/ghost',
'#source/blender/misc',
'#source/blender/blenloader',
+ '#source/blender/gpu',
'#extern/glew/include']
#This is all plugin stuff!
diff --git a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
index fee729a84ac..e5ed7f39811 100644
--- a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
+++ b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h
@@ -37,9 +37,9 @@ class GPU_PolygonMaterial : public BP_PolygonMaterial
public:
GPUPolygonMaterial(const STR_String& texname, bool ba,const STR_String& matname,
int tile, int tileXrep, int tileYrep, int mode, int transparant,
- int lightlayer,bool bIsTriangle,void* clientobject,void* tpage) :
+ int lightlayer,,void* tpage) :
BP_PolygonMaterial(texname, ba,matname, tile, tileXrep, tileYrep,
- mode, transparant, lightlayer, bIsTriangle, clientobject),
+ mode, transparant, lightlayer),
m_tface(tpage)
{
}
diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
index d9f0675001f..5e0ca93ac06 100644
--- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt
+++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt
@@ -64,6 +64,7 @@ SET(INC
../../../../source/gameengine/GamePlayer/common
../../../../source/blender/misc
../../../../source/blender/blenloader
+ ../../../../source/blender/gpu
../../../../extern/solid
../../../../extern/glew/include
${PYTHON_INC}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
index 7be3b94d8ae..a9196a1a5e3 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp
@@ -38,6 +38,7 @@
#endif
#include "GL/glew.h"
+#include "GPU_extensions.h"
#include "GPG_Application.h"
@@ -56,6 +57,7 @@ extern "C"
#include "BLO_readfile.h"
#include "BKE_global.h"
#include "BKE_main.h"
+#include "IMB_imbuf.h"
#include "DNA_scene_types.h"
#ifdef __cplusplus
}
@@ -98,15 +100,15 @@ extern "C"
#include "GHOST_IWindow.h"
#include "GHOST_Rect.h"
-
static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
static GHOST_ISystem* fSystem = 0;
static const int kTimerFreq = 10;
-GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName)
- : m_startSceneName(startSceneName),
- m_maggie(maggie),
+GPG_Application::GPG_Application(GHOST_ISystem* system)
+ : m_startSceneName(""),
+ m_startScene(0),
+ m_maggie(0),
m_exitRequested(0),
m_system(system),
m_mainWindow(0),
@@ -114,6 +116,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
m_cursor(GHOST_kStandardCursorFirstCursor),
m_engineInitialized(0),
m_engineRunning(0),
+ m_isEmbedded(false),
m_ketsjiengine(0),
m_kxsystem(0),
m_keyboard(0),
@@ -125,7 +128,9 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
m_networkdevice(0),
m_audiodevice(0),
m_blendermat(0),
- m_blenderglslmat(0)
+ m_blenderglslmat(0),
+ m_pyGlobalDictString(0),
+ m_pyGlobalDictString_Length(0)
{
fSystem = system;
}
@@ -134,21 +139,28 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
GPG_Application::~GPG_Application(void)
{
+ if(m_pyGlobalDictString) {
+ delete [] m_pyGlobalDictString;
+ m_pyGlobalDictString = 0;
+ m_pyGlobalDictString_Length = 0;
+ }
+
exitEngine();
fSystem->disposeWindow(m_mainWindow);
}
-bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSceneName)
+bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene)
{
bool result = false;
- if (maggie != NULL && startSceneName != "")
+ if (maggie != NULL && scene != NULL)
{
- G.scene = (Scene*)maggie->scene.first;
+ G.scene = scene;
m_maggie = maggie;
- m_startSceneName = startSceneName;
+ m_startSceneName = scene->id.name+2;
+ m_startScene = scene;
result = true;
}
@@ -320,6 +332,26 @@ bool GPG_Application::startWindow(STR_String& title,
return success;
}
+bool GPG_Application::startEmbeddedWindow(STR_String& title,
+ const GHOST_TEmbedderWindowID parentWindow,
+ const bool stereoVisual,
+ const int stereoMode) {
+
+ m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, GHOST_kWindowStateNormal,
+ GHOST_kDrawingContextTypeOpenGL, stereoVisual, parentWindow);
+
+ if (!m_mainWindow) {
+ printf("error: could not create main window\n");
+ exit(-1);
+ }
+ m_isEmbedded = true;
+
+ bool success = initEngine(m_mainWindow, stereoMode);
+ if (success) {
+ success = startEngine();
+ }
+ return success;
+}
bool GPG_Application::startFullScreen(
@@ -478,7 +510,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
{
if (!m_engineInitialized)
{
- glewInit();
+ GPU_extensions_init();
bgl::InitExtensions(true);
// get and set the preferences
@@ -497,13 +529,16 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0);
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
- bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0);
+ bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0);
+
+ if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
+ m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0);
+
+ if(GPU_extensions_minimum_support())
+ m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0);
+ else if(G.fileflags & G_FILE_GAME_MAT_GLSL)
+ m_blendermat = false;
- if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) {
- int gameflag =(G.fileflags & G_FILE_GAME_MAT);
- m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0);
- }
-
// create the canvas, rasterizer and rendertools
m_canvas = new GPG_Canvas(window);
if (!m_canvas)
@@ -626,33 +661,36 @@ bool GPG_Application::startEngine(void)
{
STR_String startscenename = m_startSceneName.Ptr();
m_ketsjiengine->SetSceneConverter(m_sceneconverter);
-
+
// if (always_use_expand_framing)
// sceneconverter->SetAlwaysUseExpandFraming(true);
- if(m_blendermat)
+ if(m_blendermat && (G.fileflags & G_FILE_GAME_MAT))
m_sceneconverter->SetMaterials(true);
- if(m_blenderglslmat)
+ if(m_blenderglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL))
m_sceneconverter->SetGLSLMaterials(true);
KX_Scene* startscene = new KX_Scene(m_keyboard,
m_mouse,
m_networkdevice,
m_audiodevice,
- startscenename);
+ startscenename,
+ m_startScene);
// some python things
PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
m_ketsjiengine->SetPythonDictionary(dictionaryobject);
initRasterizer(m_rasterizer, m_canvas);
- PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
+ PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene);
+ PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
initMathutils();
-
-
-
+ // Set the GameLogic.globalDict from marshal'd data, so we can
+ // load new blend files and keep data in GameLogic.globalDict
+ loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
+
m_sceneconverter->ConvertScene(
startscenename,
startscene,
@@ -688,6 +726,16 @@ bool GPG_Application::startEngine(void)
void GPG_Application::stopEngine()
{
+ // GameLogic.globalDict gets converted into a buffer, and sorted in
+ // m_pyGlobalDictString so we can restore after python has stopped
+ // and started between .blend file loads.
+ if(m_pyGlobalDictString) {
+ delete [] m_pyGlobalDictString;
+ m_pyGlobalDictString = 0;
+ }
+
+ m_pyGlobalDictString_Length = saveGamePythonConfig(&m_pyGlobalDictString);
+
// when exiting the mainloop
exitGamePythonScripting();
m_ketsjiengine->StopEngine();
@@ -754,6 +802,12 @@ void GPG_Application::exitEngine()
m_canvas = 0;
}
+ libtiff_exit();
+#ifdef WITH_QUICKTIME
+ quicktime_exit();
+#endif
+ GPU_extensions_exit();
+
m_exitRequested = 0;
m_engineInitialized = false;
}
@@ -833,7 +887,7 @@ bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
//no need for this test
//if (fSystem->getFullScreen()) {
- if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) {
+ if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc && !m_isEmbedded) {
m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
}
//}
diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h
index 17f5add8b19..38408f919b4 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_Application.h
+++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h
@@ -50,17 +50,19 @@ class GPG_Canvas;
class GPG_KeyboardDevice;
class GPG_System;
struct Main;
+struct Scene;
class GPG_Application : public GHOST_IEventConsumer
{
public:
- GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName);
+ GPG_Application(GHOST_ISystem* system);
~GPG_Application(void);
- bool SetGameEngineData(struct Main* maggie,STR_String startSceneName);
+ bool SetGameEngineData(struct Main* maggie, struct Scene* scene);
bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight,
const bool stereoVisual, const int stereoMode);
bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
+ bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode);
#ifdef WIN32
bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode);
bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode);
@@ -100,6 +102,7 @@ protected:
/* The game data */
STR_String m_startSceneName;
+ struct Scene* m_startScene;
struct Main* m_maggie;
/* Exit state. */
@@ -118,6 +121,8 @@ protected:
bool m_engineInitialized;
/** Engine state. */
bool m_engineRunning;
+ /** Running on embedded window */
+ bool m_isEmbedded;
/** the gameengine itself */
KX_KetsjiEngine* m_ketsjiengine;
@@ -142,6 +147,12 @@ protected:
bool m_blendermat;
bool m_blenderglslmat;
-
+
+ /*
+ * GameLogic.globalDict as a string so that loading new blend files can use the same dict.
+ * Do this because python starts/stops when loading blend files.
+ */
+ char* m_pyGlobalDictString;
+ int m_pyGlobalDictString_Length;
};
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 8222e5c8bac..9700e6387f2 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -52,25 +52,31 @@
extern "C"
{
#endif // __cplusplus
+#include "MEM_guardedalloc.h"
+#include "BKE_blender.h"
#include "BKE_global.h"
#include "BKE_icons.h"
+#include "BKE_node.h"
#include "BLI_blenlib.h"
#include "DNA_scene_types.h"
#include "BLO_readfile.h"
#include "BLO_readblenfile.h"
+#include "IMB_imbuf.h"
int GHOST_HACK_getFirstFile(char buf[]);
#ifdef __cplusplus
}
#endif // __cplusplus
+
+#include "GPU_draw.h"
+
/**********************************
* End Blender include block
**********************************/
#include "SYS_System.h"
#include "GPG_Application.h"
-#include "GPC_PolygonMaterial.h"
#include "GHOST_ISystem.h"
#include "RAS_IRasterizer.h"
@@ -146,9 +152,9 @@ static BOOL scr_saver_init(int argc, char **argv)
#endif /* WIN32 */
-void usage(char* program)
+void usage(const char* program)
{
- char * consoleoption;
+ const char * consoleoption;
#ifdef _WIN32
consoleoption = "-c ";
#else
@@ -176,9 +182,13 @@ void usage(char* program)
printf(" anaglyph (Red-Blue glasses)\n");
printf(" vinterlace (Vertical interlace for autostereo display)\n");
printf(" depending on the type of stereo you want\n");
+#ifndef _WIN32
+ printf(" -i: parent windows ID \n");
+#endif
#ifdef _WIN32
printf(" -c: keep console window open\n");
#endif
+ printf(" -d: turn debugging on\n");
printf(" -g: game engine options:\n");
printf(" Name Default Description\n");
printf(" ----------------------------------------\n");
@@ -193,7 +203,8 @@ void usage(char* program)
printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program);
}
-char *get_filename(int argc, char **argv) {
+static void get_filename(int argc, char **argv, char *filename)
+{
#ifdef __APPLE__
/* On Mac we park the game file (called game.blend) in the application bundle.
* The executable is located in the bundle as well.
@@ -201,22 +212,18 @@ char *get_filename(int argc, char **argv) {
*/
int srclen = ::strlen(argv[0]);
int len = 0;
- char *filename = NULL;
+ char *gamefile = NULL;
+ filename[0] = '\0';
+
if (argc > 1) {
if (BLI_exists(argv[argc-1])) {
- len = ::strlen(argv[argc-1]);
- filename = new char [len + 1];
- ::strcpy(filename, argv[argc-1]);
- return(filename);
+ BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
}
if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
static char firstfilebuf[512];
if (GHOST_HACK_getFirstFile(firstfilebuf)) {
- len = ::strlen(firstfilebuf);
- filename = new char [len + 1];
- ::strcpy(filename, firstfilebuf);
- return(filename);
+ BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE);
}
}
}
@@ -224,23 +231,26 @@ char *get_filename(int argc, char **argv) {
srclen -= ::strlen("MacOS/blenderplayer");
if (srclen > 0) {
len = srclen + ::strlen("Resources/game.blend");
- filename = new char [len + 1];
- ::strcpy(filename, argv[0]);
- ::strcpy(filename + srclen, "Resources/game.blend");
+ gamefile = new char [len + 1];
+ ::strcpy(gamefile, argv[0]);
+ ::strcpy(gamefile + srclen, "Resources/game.blend");
//::printf("looking for file: %s\n", filename);
- if (BLI_exists(filename)) {
- return (filename);
- }
+ if (BLI_exists(gamefile))
+ BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE);
+
+ delete gamefile;
}
- return(NULL);
#else
- return (argc>1)?argv[argc-1]:NULL;
+ filename[0] = '\0';
+
+ if(argc > 1)
+ BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
#endif // !_APPLE
}
-static BlendFileData *load_game_data(char *progname, char *filename = NULL) {
+static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) {
BlendReadError error;
BlendFileData *bfd = NULL;
@@ -282,7 +292,7 @@ int main(int argc, char** argv)
bool fullScreenParFound = false;
bool windowParFound = false;
bool closeConsole = true;
- RAS_IRasterizer::StereoMode stereomode;
+ RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
bool stereoWindow = false;
bool stereoParFound = false;
int windowLeft = 100;
@@ -293,7 +303,10 @@ int main(int argc, char** argv)
GHOST_TUns32 fullScreenHeight= 0;
int fullScreenBpp = 32;
int fullScreenFrequency = 60;
+ GHOST_TEmbedderWindowID parentWindow = 0;
+
+
#ifdef __linux__
#ifdef __alpha__
signal (SIGFPE, SIG_IGN);
@@ -321,8 +334,18 @@ int main(int argc, char** argv)
::DisposeNibReference(nibRef);
*/
#endif // __APPLE__
+
+ init_nodesystem();
+ initglobals();
+
GEN_init_messaging_system();
+
+#ifdef WITH_QUICKTIME
+ quicktime_init();
+#endif
+
+ libtiff_init();
// Parse command line options
#ifndef NDEBUG
@@ -401,6 +424,12 @@ int main(int argc, char** argv)
}
}
break;
+
+ case 'd':
+ i++;
+ G.f |= G_DEBUG; /* std output printf's */
+ MEM_set_memory_debug();
+ break;
case 'p':
// Parse window position and size options
@@ -453,6 +482,16 @@ int main(int argc, char** argv)
usage(argv[0]);
return 0;
break;
+#ifndef _WIN32
+ case 'i':
+ i++;
+ if ( (i + 1) < argc )
+ parentWindow = atoi(argv[i++]);
+#ifndef NDEBUG
+ printf("XWindows ID = %d\n", parentWindow);
+#endif //NDEBUG
+
+#endif // _WIN32
case 'c':
i++;
closeConsole = false;
@@ -523,21 +562,19 @@ int main(int argc, char** argv)
return 0;
}
- if (!stereoParFound) stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
-
#ifdef WIN32
if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
#endif
{
#ifdef __APPLE__
//SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
- SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
+ //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
//fullScreen = false; // Can't use full screen
#endif
if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
{
- GPC_PolygonMaterial::SetMipMappingEnabled(0);
+ GPU_set_mipmap(0);
}
// Create the system
@@ -559,11 +596,15 @@ int main(int argc, char** argv)
{
int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
STR_String exitstring = "";
- GPG_Application app(system, NULL, exitstring);
+ GPG_Application app(system);
bool firstTimeRunning = true;
- char *filename = get_filename(argc, argv);
+ char filename[FILE_MAXDIR + FILE_MAXFILE];
char *titlename;
char pathname[160];
+
+ get_filename(argc, argv, filename);
+ if(filename[0])
+ BLI_convertstringcwd(filename);
do
{
@@ -595,7 +636,7 @@ int main(int argc, char** argv)
}
else
{
- bfd = load_game_data(argv[0], filename);
+ bfd = load_game_data(bprogname, filename[0]? filename: NULL);
}
//::printf("game data loaded from %s\n", filename);
@@ -617,7 +658,7 @@ int main(int argc, char** argv)
#endif // WIN32
Main *maggie = bfd->main;
Scene *scene = bfd->curscene;
- char *startscenename = scene->id.name + 2;
+ G.main = maggie;
G.fileflags = bfd->fileflags;
//Seg Fault; icon.c gIcons == 0
@@ -655,7 +696,7 @@ int main(int argc, char** argv)
}
// GPG_Application app (system, maggie, startscenename);
- app.SetGameEngineData(maggie, startscenename);
+ app.SetGameEngineData(maggie, scene);
if (firstTimeRunning)
{
@@ -723,7 +764,10 @@ int main(int argc, char** argv)
else
#endif
{
- app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
+ if (parentWindow != 0)
+ app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode);
+ else
+ app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
stereoWindow, stereomode);
}
}
@@ -750,13 +794,8 @@ int main(int argc, char** argv)
}
}
app.StopGameEngine();
+
BLO_blendfiledata_free(bfd);
-
-#ifdef __APPLE__
- if (filename) {
- delete [] filename;
- }
-#endif // __APPLE__
}
} while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
}
@@ -772,6 +811,8 @@ int main(int argc, char** argv)
}
}
+ free_nodesystem();
+
return error ? -1 : 0;
}
diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile
index 13940ac3fc8..52e219db8f2 100644
--- a/source/gameengine/GamePlayer/ghost/Makefile
+++ b/source/gameengine/GamePlayer/ghost/Makefile
@@ -41,6 +41,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_BMFONT)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
CPPFLAGS += -I../../GamePlayer/common
@@ -69,6 +70,7 @@ CPPFLAGS += -I../../../blender/blenloader
CPPFLAGS += -I../../../blender/imbuf
CPPFLAGS += -I../../../blender/makesdna
CPPFLAGS += -I../../../blender/readblenfile
+CPPFLAGS += -I../../../blender/gpu
CPPFLAGS += -I../../../gameengine/BlenderRoutines
@@ -80,7 +82,3 @@ CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_GHOST)/include
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
-
diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript
index f3cce6c7443..33cf07b6211 100644
--- a/source/gameengine/GamePlayer/ghost/SConscript
+++ b/source/gameengine/GamePlayer/ghost/SConscript
@@ -40,6 +40,7 @@ incs = ['.',
'#source/gameengine/GamePlayer/common',
'#source/blender/misc',
'#source/blender/blenloader',
+ '#source/blender/gpu',
'#extern/glew/include']
incs += Split(env['BF_PYTHON_INC'])
@@ -48,8 +49,5 @@ cflags = []
if env['OURPLATFORM']=='win32-vc':
cflags = ['/GR']
-if env['WITH_BF_GLEXT'] == 1:
- env['CPPFLAGS'].append('-DWITH_GLEXT')
-
env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags)
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index a9a0771936c..8ec463be6ff 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -9,108 +9,64 @@
#include "BL_BlenderShader.h"
#include "BL_Material.h"
-#ifdef BLENDER_GLSL
#include "GPU_extensions.h"
#include "GPU_material.h"
-#endif
#include "RAS_BucketManager.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
- /* this is evil, but we need the scene to create materials with
- * lights from the correct scene .. */
-static struct Scene *GetSceneForName(const STR_String& scenename)
-{
- Scene *sce;
-
- for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next)
- if (scenename == (sce->id.name+2))
- return sce;
-
- return (Scene*)G.main->scene.first;
-}
-
-bool BL_BlenderShader::Ok()
-{
-#ifdef BLENDER_GLSL
- VerifyShader();
-
- return (mMat && mMat->gpumaterial);
-#else
- return 0;
-#endif
-}
-
BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer)
:
-#ifdef BLENDER_GLSL
mScene(scene),
mMat(ma),
- mGPUMat(NULL),
-#endif
- mBound(false),
mLightLayer(lightlayer)
{
-#ifdef BLENDER_GLSL
- mBlenderScene = GetSceneForName(scene->GetName());
+ mBlenderScene = scene->GetBlenderScene();
mBlendMode = GPU_BLEND_SOLID;
- if(mMat) {
+ if(mMat)
GPU_material_from_blender(mBlenderScene, mMat);
- mGPUMat = mMat->gpumaterial;
- }
-#endif
}
BL_BlenderShader::~BL_BlenderShader()
{
-#ifdef BLENDER_GLSL
- if(mMat && mMat->gpumaterial)
- GPU_material_unbind(mMat->gpumaterial);
-#endif
+ if(mMat && GPU_material_from_blender(mBlenderScene, mMat))
+ GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat));
}
-bool BL_BlenderShader::VerifyShader()
+bool BL_BlenderShader::Ok()
{
-#ifdef BLENDER_GLSL
- if(mMat && !mMat->gpumaterial)
- GPU_material_from_blender(mBlenderScene, mMat);
+ return VerifyShader();
+}
- mGPUMat = mMat->gpumaterial;
-
- return (mMat && mGPUMat);
-#else
- return false;
-#endif
+bool BL_BlenderShader::VerifyShader()
+{
+ if(mMat)
+ return (GPU_material_from_blender(mBlenderScene, mMat) != 0);
+ else
+ return false;
}
-void BL_BlenderShader::SetProg(bool enable)
+void BL_BlenderShader::SetProg(bool enable, double time)
{
-#ifdef BLENDER_GLSL
if(VerifyShader()) {
- if(enable) {
- GPU_material_bind(mGPUMat, mLightLayer);
- mBound = true;
- }
- else {
- GPU_material_unbind(mGPUMat);
- mBound = false;
- }
+ if(enable)
+ GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, ~0, time);
+ else
+ GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat));
}
-#endif
}
int BL_BlenderShader::GetAttribNum()
{
-#ifdef BLENDER_GLSL
GPUVertexAttribs attribs;
int i, enabled = 0;
if(!VerifyShader())
return enabled;
- GPU_material_vertex_attributes(mGPUMat, &attribs);
+ GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs);
for(i = 0; i < attribs.totlayer; i++)
if(attribs.layer[i].glindex+1 > enabled)
@@ -120,24 +76,23 @@ int BL_BlenderShader::GetAttribNum()
enabled = BL_MAX_ATTRIB;
return enabled;
-#else
- return 0;
-#endif
}
void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
{
-#ifdef BLENDER_GLSL
GPUVertexAttribs attribs;
+ GPUMaterial *gpumat;
int i, attrib_num;
ras->SetAttribNum(0);
if(!VerifyShader())
return;
+
+ gpumat = GPU_material_from_blender(mBlenderScene, mMat);
if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
- GPU_material_vertex_attributes(mGPUMat, &attribs);
+ GPU_material_vertex_attributes(gpumat, &attribs);
attrib_num = GetAttribNum();
ras->SetTexCoordNum(0);
@@ -168,44 +123,37 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat)
else
ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex);
}
-
- ras->EnableTextures(true);
}
- else
- ras->EnableTextures(false);
-#endif
}
-void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
+void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
{
-#ifdef BLENDER_GLSL
float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4];
+ GPUMaterial *gpumat;
- VerifyShader();
+ gpumat = GPU_material_from_blender(mBlenderScene, mMat);
- if(!mGPUMat) // || !mBound)
+ if(!gpumat || !GPU_material_bound(gpumat))
return;
MT_Matrix4x4 model;
model.setValue(ms.m_OpenGLMatrix);
- MT_Matrix4x4 view;
- rasty->GetViewMatrix(view);
+ const MT_Matrix4x4& view = rasty->GetViewMatrix();
+ const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix();
+ // note: getValue gives back column major as needed by OpenGL
model.getValue((float*)obmat);
view.getValue((float*)viewmat);
-
- view.invert();
- view.getValue((float*)viewinvmat);
+ viewinv.getValue((float*)viewinvmat);
if(ms.m_bObjectColor)
ms.m_RGBAcolor.getValue((float*)obcol);
else
obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f;
- GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol);
+ GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol);
- mBlendMode = GPU_material_blend_mode(mGPUMat, obcol);
-#endif
+ mBlendMode = GPU_material_blend_mode(gpumat, obcol);
}
int BL_BlenderShader::GetBlendMode()
@@ -215,12 +163,8 @@ int BL_BlenderShader::GetBlendMode()
bool BL_BlenderShader::Equals(BL_BlenderShader *blshader)
{
-#ifdef BLENDER_GLSL
/* to avoid unneeded state switches */
- return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer);
-#else
- return true;
-#endif
+ return (blshader && mMat == blshader->mMat && mLightLayer == blshader->mLightLayer);
}
// eof
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h
index da9765dafa4..5c1f59f94ad 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.h
+++ b/source/gameengine/Ketsji/BL_BlenderShader.h
@@ -2,9 +2,7 @@
#ifndef __BL_GPUSHADER_H__
#define __BL_GPUSHADER_H__
-#ifdef BLENDER_GLSL
#include "GPU_material.h"
-#endif
#include "MT_Matrix4x4.h"
#include "MT_Matrix3x3.h"
@@ -29,13 +27,9 @@ class BL_Material;
class BL_BlenderShader
{
private:
-#ifdef BLENDER_GLSL
KX_Scene *mScene;
struct Scene *mBlenderScene;
struct Material *mMat;
- GPUMaterial *mGPUMat;
-#endif
- bool mBound;
int mLightLayer;
int mBlendMode;
@@ -46,11 +40,11 @@ public:
virtual ~BL_BlenderShader();
bool Ok();
- void SetProg(bool enable);
+ void SetProg(bool enable, double time=0.0);
int GetAttribNum();
void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat);
- void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty);
+ void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty);
int GetBlendMode();
bool Equals(BL_BlenderShader *blshader);
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index dcb66ea2579..0eaa234566c 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -18,9 +18,9 @@ struct EnvMap;
this will default to users available units
to build with more available, just increment this value
although the more you add the slower the search time will be.
- we will go for three, which should be enough
+ we will go for eight, which should be enough
*/
-#define MAXTEX 3 //match in RAS_TexVert & RAS_OpenGLRasterizer
+#define MAXTEX 8 //match in RAS_TexVert & RAS_OpenGLRasterizer
// different mapping modes
class BL_Mapping
@@ -139,7 +139,7 @@ enum BL_ras_mode
COLLIDER=2,
ZSORT=4,
ALPHA=8,
- TRIANGLE=16,
+ // TRIANGLE=16,
USE_LIGHT=32,
WIRE=64
};
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 57d0fe4140f..80892764089 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -433,7 +433,7 @@ void BL_Shader::SetProg(bool enable)
}
}
-void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
+void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
{
if(!Ok() || !mPreDef.size())
return;
@@ -445,8 +445,7 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
{
MT_Matrix4x4 model;
model.setValue(ms.m_OpenGLMatrix);
- MT_Matrix4x4 view;
- rasty->GetViewMatrix(view);
+ const MT_Matrix4x4& view = rasty->GetViewMatrix();
if(mAttr==SHD_TANGENT)
ms.m_mesh->SetMeshModified(true);
@@ -525,13 +524,15 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
}
case VIEWMATRIX_INVERSE:
{
- view.invert();
+ MT_Matrix4x4 viewinv = view;
+ viewinv.invert();
SetUniform(uni->mLoc, view);
break;
}
case VIEWMATRIX_INVERSETRANSPOSE:
{
- view.invert();
+ MT_Matrix4x4 viewinv = view;
+ viewinv.invert();
SetUniform(uni->mLoc, view, true);
break;
}
@@ -670,6 +671,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
)
{
float value[16];
+ // note: getValue gives back column major as needed by OpenGL
vec.getValue(value);
glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
}
@@ -879,7 +881,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int index=-1;
if(PyArg_ParseTuple(args, "si", &uniform, &index))
{
@@ -920,7 +922,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
float value=0;
if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
{
@@ -944,7 +946,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
float array[2]={ 0,0 };
if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
{
@@ -968,7 +970,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
float array[3]={0,0,0};
if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
{
@@ -993,7 +995,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) "
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
float array[4]={0,0,0,0};
if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
{
@@ -1017,7 +1019,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int value=0;
if(PyArg_ParseTuple(args, "si", &uniform, &value ))
{
@@ -1041,7 +1043,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int array[2]={ 0,0 };
if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
{
@@ -1066,7 +1068,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int array[3]={0,0,0};
if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
{
@@ -1089,7 +1091,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) "
if(mError) {
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int array[4]={0,0,0, 0};
if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
{
@@ -1112,7 +1114,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or lis
if(mError) {
Py_RETURN_NONE;
}
- char*uniform = "";
+ const char *uniform = "";
PyObject *listPtr =0;
float array_data[4] = {0.f,0.f,0.f,0.f};
@@ -1181,7 +1183,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3
if(mError) {
Py_RETURN_NONE;
}
- char*uniform = "";
+ const char *uniform = "";
PyObject *listPtr =0;
int array_data[4] = {0,0,0,0};
@@ -1261,7 +1263,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4,
0,0,0,1
};
- char *uniform="";
+ const char *uniform="";
PyObject *matrix=0;
int transp=1; // MT_ is row major so transpose by default....
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
@@ -1302,7 +1304,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
0,0,1,
};
- char *uniform="";
+ const char *uniform="";
PyObject *matrix=0;
int transp=1; // MT_ is row major so transpose by default....
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
@@ -1356,7 +1358,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
Py_RETURN_NONE;
}
- char *uniform="";
+ const char *uniform="";
int nloc=0;
if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
{
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 8f303454087..18ca8f8b4f8 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -102,8 +102,8 @@ private:
bool mUse; // ...
//BL_Sampler mSampler[MAXTEX]; // Number of samplers
int mAttr; // Tangent attribute
- char* vertProg; // Vertex program string
- char* fragProg; // Fragment program string
+ const char* vertProg; // Vertex program string
+ const char* fragProg; // Fragment program string
bool mError; // ...
bool mDirty; //
@@ -177,7 +177,7 @@ public:
void UnloadShader();
// Update predefined uniforms each render call
- void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty);
+ void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty);
//// Set sampler units (copied)
//void InitializeSampler(int unit, BL_Texture* texture );
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index be009d94701..58411f6d25e 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -69,6 +69,7 @@ SET(INC
../../../intern/SoundSystem
../../../source/blender/misc
../../../source/blender/blenloader
+ ../../../source/blender/gpu
../../../extern/bullet2/src
../../../extern/solid
../../../extern/glew/include
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index 0c66ac1fde3..8956df9c96b 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -196,20 +196,20 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = {
PyMethodDef KX_NetworkMessageSensor::Methods[] = {
{"setSubjectFilterText", (PyCFunction)
- KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS,
- SetSubjectFilterText_doc},
+ KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O,
+ (PY_METHODCHAR)SetSubjectFilterText_doc},
{"getFrameMessageCount", (PyCFunction)
- KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS,
- GetFrameMessageCount_doc},
+ KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS,
+ (PY_METHODCHAR)GetFrameMessageCount_doc},
{"getBodies", (PyCFunction)
- KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS,
- GetBodies_doc},
+ KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS,
+ (PY_METHODCHAR)GetBodies_doc},
{"getSubject", (PyCFunction)
- KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS,
- GetSubject_doc},
+ KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS,
+ (PY_METHODCHAR)GetSubject_doc},
{"getSubjects", (PyCFunction)
- KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS,
- GetSubjects_doc},
+ KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS,
+ (PY_METHODCHAR)GetSubjects_doc},
{NULL,NULL} //Sentinel
};
@@ -218,88 +218,66 @@ PyObject* KX_NetworkMessageSensor::_getattr(const STR_String& attr) {
}
// 1. Set the message subject that this sensor listens for
-char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] =
+const char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] =
"\tsetSubjectFilterText(value)\n"
"\tChange the message subject text that this sensor is listening to.\n";
-PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText(
- PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value)
{
- char* Subject;
-
- if (PyArg_ParseTuple(args, "s", &Subject))
- {
- m_subject = Subject;
- }
- else {
+ char* Subject = PyString_AsString(value);
+ if (Subject==NULL) {
+ PyErr_SetString(PyExc_TypeError, "expected a string message");
return NULL;
}
-
- Py_Return;
+
+ m_subject = Subject;
+ Py_RETURN_NONE;
}
// 2. Get the number of messages received since the last frame
-char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
+const char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] =
"\tgetFrameMessageCount()\n"
"\tGet the number of messages received since the last frame.\n";
-PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount(
- PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* )
{
return PyInt_FromLong(long(m_frame_message_count));
}
// 3. Get the message bodies
-char KX_NetworkMessageSensor::GetBodies_doc[] =
+const char KX_NetworkMessageSensor::GetBodies_doc[] =
"\tgetBodies()\n"
"\tGet the list of message bodies.\n";
-PyObject* KX_NetworkMessageSensor::PyGetBodies(
- PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* )
{
if (m_BodyList) {
return ((PyObject*) m_BodyList->AddRef());
+ } else {
+ return ((PyObject*) new CListValue());
}
-
- Py_Return;
}
// 4. Get the message subject: field of the message sensor
-char KX_NetworkMessageSensor::GetSubject_doc[] =
+const char KX_NetworkMessageSensor::GetSubject_doc[] =
"\tgetSubject()\n"
"\tGet the subject: field of the message sensor.\n";
-PyObject* KX_NetworkMessageSensor::PyGetSubject(
- PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* )
{
- if (m_subject) {
- return PyString_FromString(m_subject);
- }
-
- Py_Return;
+ return PyString_FromString(m_subject ? m_subject : "");
}
// 5. Get the message subjects
-char KX_NetworkMessageSensor::GetSubjects_doc[] =
+const char KX_NetworkMessageSensor::GetSubjects_doc[] =
"\tgetSubjects()\n"
"\tGet list of message subjects.\n";
-PyObject* KX_NetworkMessageSensor::PyGetSubjects(
- PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* )
{
if (m_SubjectList) {
- return ((PyObject*) m_SubjectList->AddRef());
- }
-
- Py_Return;
+ return ((PyObject*) m_SubjectList->AddRef());
+ } else {
+ return ((PyObject*) new CListValue());
+ }
}
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
index 6fd92d17be3..8cdfd6cdb5a 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -74,11 +74,11 @@ public:
virtual PyObject* _getattr(const STR_String& attr);
- KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText);
- KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount);
- KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies);
- KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject);
- KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubjects);
+ KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText);
+ KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount);
+ KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies);
+ KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject);
+ KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects);
};
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index a67e5b26667..f92200780d5 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -19,13 +19,12 @@
#include "MT_Vector4.h"
#include "MT_Matrix4x4.h"
+#include "RAS_BucketManager.h"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
-extern "C" {
-#include "BDR_drawmesh.h"
-}
+#include "GPU_draw.h"
#include "STR_HashedString.h"
@@ -48,7 +47,6 @@ KX_BlenderMaterial::KX_BlenderMaterial(
BL_Material *data,
bool skin,
int lightlayer,
- void *clientobject,
PyTypeObject *T
)
: PyObjectPlus(T),
@@ -62,9 +60,7 @@ KX_BlenderMaterial::KX_BlenderMaterial(
data->transp,
((data->ras_mode &ALPHA)!=0),
((data->ras_mode &ZSORT)!=0),
- lightlayer,
- ((data->ras_mode &TRIANGLE)!=0),
- clientobject
+ lightlayer
),
mMaterial(data),
mShader(0),
@@ -78,9 +74,10 @@ KX_BlenderMaterial::KX_BlenderMaterial(
{
// --------------------------------
// 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 |= 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;
// figure max
int enabled = mMaterial->num_enabled;
@@ -97,7 +94,7 @@ KX_BlenderMaterial::KX_BlenderMaterial(
mMaterial->blend_mode[i]
);
}
- m_multimode += mMaterial->IdMode+mMaterial->ras_mode;
+ m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT));
}
@@ -204,7 +201,7 @@ void KX_BlenderMaterial::OnExit()
}
if( mMaterial->tface )
- set_tpage(mMaterial->tface);
+ GPU_set_tpage(mMaterial->tface);
}
@@ -256,25 +253,28 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras)
void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras)
{
if( !enable || !mBlenderShader->Ok() ) {
+ ras->SetBlendingMode(TF_SOLID);
+
// frame cleanup.
if(mLastBlenderShader) {
mLastBlenderShader->SetProg(false);
mLastBlenderShader= NULL;
}
+ else
+ BL_Texture::DisableAllTextures();
- ras->SetBlendingMode(TF_SOLID);
- BL_Texture::DisableAllTextures();
return;
}
if(!mBlenderShader->Equals(mLastBlenderShader)) {
ras->SetBlendingMode(mMaterial->transp);
- BL_Texture::DisableAllTextures();
if(mLastBlenderShader)
mLastBlenderShader->SetProg(false);
+ else
+ BL_Texture::DisableAllTextures();
- mBlenderShader->SetProg(true);
+ mBlenderShader->SetProg(true, ras->GetTime());
mLastBlenderShader= mBlenderShader;
}
}
@@ -354,21 +354,22 @@ KX_BlenderMaterial::ActivatShaders(
if (GetCachingInfo() != cachingInfo) {
if (!cachingInfo)
- tmp->setShaderData( false, rasty);
+ tmp->setShaderData(false, rasty);
cachingInfo = GetCachingInfo();
if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
- tmp->setShaderData( true, rasty);
+ tmp->setShaderData(true, rasty);
else
- tmp->setShaderData( false, rasty);
+ tmp->setShaderData(false, rasty);
if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
rasty->SetCullFace(false);
else
rasty->SetCullFace(true);
- if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
+ if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
+ (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
{
if((mMaterial->ras_mode &WIRE)!=0)
rasty->SetCullFace(false);
@@ -394,31 +395,24 @@ KX_BlenderMaterial::ActivateBlenderShaders(
mLastShader= NULL;
}
- // reset...
- if(tmp->mMaterial->IsShared())
- cachingInfo =0;
-
if (GetCachingInfo() != cachingInfo) {
if (!cachingInfo)
tmp->setBlenderShaderData(false, rasty);
cachingInfo = GetCachingInfo();
- if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
+ if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)
tmp->setBlenderShaderData(true, rasty);
- rasty->EnableTextures(true);
- }
- else {
+ else
tmp->setBlenderShaderData(false, rasty);
- rasty->EnableTextures(false);
- }
if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
rasty->SetCullFace(false);
else
rasty->SetCullFace(true);
- if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
+ if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
+ (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
{
if((mMaterial->ras_mode &WIRE)!=0)
rasty->SetCullFace(false);
@@ -426,10 +420,10 @@ KX_BlenderMaterial::ActivateBlenderShaders(
}
else
rasty->SetLines(false);
- }
- ActivatGLMaterials(rasty);
- mBlenderShader->SetAttribs(rasty, mMaterial);
+ ActivatGLMaterials(rasty);
+ mBlenderShader->SetAttribs(rasty, mMaterial);
+ }
}
void
@@ -466,7 +460,8 @@ KX_BlenderMaterial::ActivateMat(
else
rasty->SetCullFace(true);
- if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
+ if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) ||
+ (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
{
if((mMaterial->ras_mode &WIRE)!=0)
rasty->SetCullFace(false);
@@ -486,12 +481,10 @@ KX_BlenderMaterial::Activate(
TCachingInfo& cachingInfo
)const
{
- bool dopass = false;
- if( GLEW_ARB_shader_objects && ( mShader && mShader->Ok() ) ) {
- if( (mPass++) < mShader->getNumPass() ) {
+ if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) {
+ if((mPass++) < mShader->getNumPass() ) {
ActivatShaders(rasty, cachingInfo);
- dopass = true;
- return dopass;
+ return true;
}
else {
if(mShader == mLastShader) {
@@ -499,36 +492,29 @@ KX_BlenderMaterial::Activate(
mLastShader = NULL;
}
mPass = 0;
- dopass = false;
- return dopass;
+ return false;
}
}
- else if( GLEW_ARB_shader_objects && ( mBlenderShader && mBlenderShader->Ok() ) ) {
- if( (mPass++) == 0 ) {
+ else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) {
+ if(mPass++ == 0) {
ActivateBlenderShaders(rasty, cachingInfo);
- dopass = true;
- return dopass;
+ return true;
}
else {
mPass = 0;
- dopass = false;
- return dopass;
+ return false;
}
}
else {
- switch (mPass++)
- {
- case 0:
- ActivateMat(rasty, cachingInfo);
- dopass = true;
- break;
- default:
- mPass = 0;
- dopass = false;
- break;
+ if(mPass++ == 0) {
+ ActivateMat(rasty, cachingInfo);
+ return true;
+ }
+ else {
+ mPass = 0;
+ return false;
}
}
- return dopass;
}
bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
@@ -536,14 +522,15 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const
if(!RAS_IPolyMaterial::UsesLighting(rasty))
return false;
- if(mShader && mShader->Ok());
+ if(mShader && mShader->Ok())
+ return true;
else if(mBlenderShader && mBlenderShader->Ok())
return false;
-
- return true;
+ else
+ return true;
}
-void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const
+void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const
{
if(mShader && GLEW_ARB_shader_objects) {
mShader->Update(ms, rasty);
@@ -554,7 +541,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterize
mBlenderShader->Update(ms, rasty);
/* we do blend modes here, because they can change per object
- * with the same material due to obcolor */
+ * with the same material due to obcolor/obalpha */
blendmode = mBlenderShader->GetBlendMode();
if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID)
blendmode = mMaterial->transp;
@@ -633,11 +620,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const
else
ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i);
}
-
- ras->EnableTextures(true);
}
- else
- ras->EnableTextures(false);
}
void KX_BlenderMaterial::setTexMatrixData(int i)
@@ -712,8 +695,7 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras)
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
- MT_Matrix4x4 mvmat;
- ras->GetViewMatrix(mvmat);
+ const MT_Matrix4x4& mvmat = ras->GetViewMatrix();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
@@ -835,7 +817,9 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
}
if(mShader && !mShader->GetError()) {
+ m_flag &= ~RAS_BLENDERGLSL;
mMaterial->SetSharedMaterial(true);
+ mScene->GetBucketManager()->ReleaseDisplayLists(this);
Py_INCREF(mShader);
return mShader;
}else
@@ -870,8 +854,6 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void)
delete mBlenderShader;
mBlenderShader = 0;
}
- else
- m_flag |= RAS_BLENDERGLSL;
}
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index 0d7657b8cdb..4ddf5a924df 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -28,7 +28,6 @@ public:
BL_Material* mat,
bool skin,
int lightlayer,
- void* clientobject,
PyTypeObject* T=&Type
);
@@ -47,7 +46,7 @@ public:
virtual
void ActivateMeshSlot(
- const KX_MeshSlot & ms,
+ const RAS_MeshSlot & ms,
RAS_IRasterizer* rasty
) const;
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
index 539eaec4a7b..bf838e60210 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
@@ -14,6 +14,7 @@
#include "PHY_IPhysicsEnvironment.h"
#include "CcdPhysicsEnvironment.h"
+#include "BulletSoftBody/btSoftBody.h"
KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna)
@@ -114,7 +115,7 @@ MT_Vector3 KX_BulletPhysicsController::GetAngularVelocity()
MT_Vector3 KX_BulletPhysicsController::GetVelocity(const MT_Point3& pos)
{
float linVel[3];
- CcdPhysicsController::GetLinearVelocity(linVel[0],linVel[1],linVel[2]);
+ CcdPhysicsController::GetVelocity(pos[0], pos[1], pos[2], linVel[0],linVel[1],linVel[2]);
return MT_Vector3(linVel[0],linVel[1],linVel[2]);
}
@@ -148,13 +149,23 @@ void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling)
}
MT_Scalar KX_BulletPhysicsController::GetMass()
{
-
- MT_Scalar invmass = GetRigidBody()->getInvMass();
+ if (GetSoftBody())
+ return GetSoftBody()->getTotalMass();
+
+ MT_Scalar invmass = 0.f;
+ if (GetRigidBody())
+ invmass = GetRigidBody()->getInvMass();
if (invmass)
return 1.f/invmass;
return 0.f;
}
+
+MT_Scalar KX_BulletPhysicsController::GetRadius()
+{
+ return MT_Scalar(CcdPhysicsController::GetRadius());
+}
+
MT_Vector3 KX_BulletPhysicsController::getReactionForce()
{
assert(0);
@@ -167,7 +178,7 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid)
void KX_BulletPhysicsController::SuspendDynamics(bool ghost)
{
btRigidBody *body = GetRigidBody();
- if (body->getActivationState() != DISABLE_SIMULATION)
+ if (body && body->getActivationState() != DISABLE_SIMULATION)
{
btBroadphaseProxy* handle = body->getBroadphaseHandle();
m_savedCollisionFlags = body->getCollisionFlags();
@@ -186,7 +197,7 @@ void KX_BulletPhysicsController::SuspendDynamics(bool ghost)
void KX_BulletPhysicsController::RestoreDynamics()
{
btRigidBody *body = GetRigidBody();
- if (body->getActivationState() == DISABLE_SIMULATION)
+ if (body && body->getActivationState() == DISABLE_SIMULATION)
{
GetPhysicsEnvironment()->updateCcdPhysicsController(this,
m_savedMass,
@@ -206,6 +217,9 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
//parentcontroller is here be able to avoid collisions between parent/child
PHY_IPhysicsController* parentctrl = NULL;
+ KX_BulletPhysicsController* parentKxCtrl = NULL;
+ CcdPhysicsController* ccdParent = NULL;
+
if (destnode != destnode->GetRootSGParent())
{
@@ -225,12 +239,15 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
if (clientgameobj)
{
- parentctrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController();
+ parentKxCtrl = (KX_BulletPhysicsController*)clientgameobj->GetPhysicsController();
+ parentctrl = parentKxCtrl;
+ ccdParent = parentKxCtrl;
}
}
}
}
+ physicsreplica->setParentCtrl(ccdParent);
physicsreplica->PostProcessReplica(motionstate,parentctrl);
physicsreplica->m_userdata = (PHY_IPhysicsController*)physicsreplica;
return physicsreplica;
@@ -241,18 +258,22 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode)
void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly)
{
- GetRigidBody()->activate(true);
+ if (GetRigidBody())
+ GetRigidBody()->activate(true);
if (!m_bDyna)
{
- GetRigidBody()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ GetCollisionObject()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
} else
{
if (!nondynaonly)
{
btTransform worldTrans;
- GetRigidBody()->getMotionState()->getWorldTransform(worldTrans);
- GetRigidBody()->setCenterOfMassTransform(worldTrans);
+ if (GetRigidBody())
+ {
+ GetRigidBody()->getMotionState()->getWorldTransform(worldTrans);
+ GetRigidBody()->setCenterOfMassTransform(worldTrans);
+ }
/*
scaling?
diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
index 2efe0474b30..cdcb82c87ca 100644
--- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h
@@ -49,9 +49,7 @@ public:
virtual SG_Controller* GetReplica(class SG_Node* destnode);
- void SetDyna(bool isDynamic) {
- m_bDyna = isDynamic;
- }
+ virtual MT_Scalar GetRadius();
virtual void SetSumoTransform(bool nondynaonly);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index 42b909927fd..4d24e83843e 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -35,6 +35,8 @@
#include <math.h>
#include "KX_GameObject.h"
+#include "PyObjectPlus.h"
+
STR_String KX_CameraActuator::X_AXIS_STRING = "x";
STR_String KX_CameraActuator::Y_AXIS_STRING = "y";
@@ -395,16 +397,16 @@ PyParentObject KX_CameraActuator::Parents[] = {
};
PyMethodDef KX_CameraActuator::Methods[] = {
- {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O, SetObject_doc},
- {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
- {"setMin" ,(PyCFunction) KX_CameraActuator::sPySetMin, METH_VARARGS, SetMin_doc},
- {"getMin" ,(PyCFunction) KX_CameraActuator::sPyGetMin, METH_NOARGS, GetMin_doc},
- {"setMax" ,(PyCFunction) KX_CameraActuator::sPySetMax, METH_VARARGS, SetMax_doc},
- {"getMax" ,(PyCFunction) KX_CameraActuator::sPyGetMax, METH_NOARGS, GetMax_doc},
- {"setHeight",(PyCFunction) KX_CameraActuator::sPySetHeight, METH_VARARGS, SetHeight_doc},
- {"getHeight",(PyCFunction) KX_CameraActuator::sPyGetHeight, METH_NOARGS, GetHeight_doc},
- {"setXY" ,(PyCFunction) KX_CameraActuator::sPySetXY, METH_VARARGS, SetXY_doc},
- {"getXY" ,(PyCFunction) KX_CameraActuator::sPyGetXY, METH_VARARGS, GetXY_doc},
+ {"setObject",(PyCFunction) KX_CameraActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc},
+ {"getObject",(PyCFunction) KX_CameraActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc},
+ {"setMin" ,(PyCFunction) KX_CameraActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetMin_doc},
+ {"getMin" ,(PyCFunction) KX_CameraActuator::sPyGetMin, METH_NOARGS, (PY_METHODCHAR)GetMin_doc},
+ {"setMax" ,(PyCFunction) KX_CameraActuator::sPySetMax, METH_VARARGS, (PY_METHODCHAR)SetMax_doc},
+ {"getMax" ,(PyCFunction) KX_CameraActuator::sPyGetMax, METH_NOARGS, (PY_METHODCHAR)GetMax_doc},
+ {"setHeight",(PyCFunction) KX_CameraActuator::sPySetHeight, METH_VARARGS, (PY_METHODCHAR)SetHeight_doc},
+ {"getHeight",(PyCFunction) KX_CameraActuator::sPyGetHeight, METH_NOARGS, (PY_METHODCHAR)GetHeight_doc},
+ {"setXY" ,(PyCFunction) KX_CameraActuator::sPySetXY, METH_VARARGS, (PY_METHODCHAR)SetXY_doc},
+ {"getXY" ,(PyCFunction) KX_CameraActuator::sPyGetXY, METH_VARARGS, (PY_METHODCHAR)GetXY_doc},
{NULL,NULL,NULL,NULL} //Sentinel
};
@@ -412,7 +414,7 @@ PyObject* KX_CameraActuator::_getattr(const STR_String& attr) {
_getattr_up(SCA_IActuator);
}
/* get obj ---------------------------------------------------------- */
-char KX_CameraActuator::GetObject_doc[] =
+const char KX_CameraActuator::GetObject_doc[] =
"getObject(name_only = 1)\n"
"name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
"\tReturns the object this sensor reacts to.\n";
@@ -431,7 +433,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args)
return m_ob->AddRef();
}
/* set obj ---------------------------------------------------------- */
-char KX_CameraActuator::SetObject_doc[] =
+const char KX_CameraActuator::SetObject_doc[] =
"setObject(object)\n"
"\t- object: KX_GameObject, string or None\n"
"\tSets the object this sensor reacts to.\n";
@@ -453,7 +455,7 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* value)
}
/* get min ---------------------------------------------------------- */
-char KX_CameraActuator::GetMin_doc[] =
+const char KX_CameraActuator::GetMin_doc[] =
"getMin\n"
"\tReturns the minimum value set in the Min: field.\n";
PyObject* KX_CameraActuator::PyGetMin(PyObject* self,
@@ -463,7 +465,7 @@ PyObject* KX_CameraActuator::PyGetMin(PyObject* self,
return PyFloat_FromDouble(m_minHeight);
}
/* set min ---------------------------------------------------------- */
-char KX_CameraActuator::SetMin_doc[] =
+const char KX_CameraActuator::SetMin_doc[] =
"setMin\n"
"\tSets the minimum value.\n";
PyObject* KX_CameraActuator::PySetMin(PyObject* self,
@@ -479,7 +481,7 @@ PyObject* KX_CameraActuator::PySetMin(PyObject* self,
return NULL;
}
/* get min ---------------------------------------------------------- */
-char KX_CameraActuator::GetMax_doc[] =
+const char KX_CameraActuator::GetMax_doc[] =
"getMax\n"
"\tReturns the maximum value set in the Max: field.\n";
PyObject* KX_CameraActuator::PyGetMax(PyObject* self,
@@ -489,7 +491,7 @@ PyObject* KX_CameraActuator::PyGetMax(PyObject* self,
return PyFloat_FromDouble(m_maxHeight);
}
/* set min ---------------------------------------------------------- */
-char KX_CameraActuator::SetMax_doc[] =
+const char KX_CameraActuator::SetMax_doc[] =
"setMax\n"
"\tSets the maximum value.\n";
PyObject* KX_CameraActuator::PySetMax(PyObject* self,
@@ -505,7 +507,7 @@ PyObject* KX_CameraActuator::PySetMax(PyObject* self,
return NULL;
}
/* get height ---------------------------------------------------------- */
-char KX_CameraActuator::GetHeight_doc[] =
+const char KX_CameraActuator::GetHeight_doc[] =
"getHeight\n"
"\tReturns the height value set in the height: field.\n";
PyObject* KX_CameraActuator::PyGetHeight(PyObject* self,
@@ -515,7 +517,7 @@ PyObject* KX_CameraActuator::PyGetHeight(PyObject* self,
return PyFloat_FromDouble(m_height);
}
/* set height ---------------------------------------------------------- */
-char KX_CameraActuator::SetHeight_doc[] =
+const char KX_CameraActuator::SetHeight_doc[] =
"setHeight\n"
"\tSets the height value.\n";
PyObject* KX_CameraActuator::PySetHeight(PyObject* self,
@@ -531,7 +533,7 @@ PyObject* KX_CameraActuator::PySetHeight(PyObject* self,
return NULL;
}
/* set XY ---------------------------------------------------------- */
-char KX_CameraActuator::SetXY_doc[] =
+const char KX_CameraActuator::SetXY_doc[] =
"setXY\n"
"\tSets axis the camera tries to get behind.\n"
"\t1=x, 0=y\n";
@@ -549,7 +551,7 @@ PyObject* KX_CameraActuator::PySetXY(PyObject* self,
}
/* get XY -------------------------------------------------------------*/
-char KX_CameraActuator::GetXY_doc[] =
+const char KX_CameraActuator::GetXY_doc[] =
"getXY\n"
"\tGets the axis the camera tries to get behind.\n"
"\tTrue = X, False = Y\n";
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index e00ec68ad33..76357e9c58f 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -109,16 +109,11 @@ KX_ConstraintActuator::~KX_ConstraintActuator()
// there's nothing to be done here, really....
} /* end of destructor */
-bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
{
- KX_GameObject* hitKXObj = client->m_gameobject;
+ m_hitObject = client->m_gameobject;
- if (client->m_type > KX_ClientObjectInfo::ACTOR)
- {
- // false hit
- return false;
- }
bool bFound = false;
if (m_property[0] == 0)
@@ -136,11 +131,29 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_p
}
else
{
- bFound = hitKXObj->GetProperty(m_property) != NULL;
+ bFound = m_hitObject->GetProperty(m_property) != NULL;
}
}
+ // update the hit status
+ result->m_hitFound = bFound;
+ // stop looking
+ return true;
+}
- return bFound;
+/* this function is used to pre-filter the object before casting the ray on them.
+ This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client)
+{
+ if (client->m_type > KX_ClientObjectInfo::ACTOR)
+ {
+ // Unknown type of object, skip it.
+ // Should not occur as the sensor objects are filtered in RayTest()
+ printf("Invalid client type %d found in ray casting\n", client->m_type);
+ return false;
+ }
+ // no X-Ray function yet
+ return true;
}
bool KX_ConstraintActuator::Update(double curtime, bool frame)
@@ -159,13 +172,15 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
KX_GameObject *obj = (KX_GameObject*) GetParent();
MT_Point3 position = obj->NodeGetWorldPosition();
MT_Point3 newposition;
- MT_Vector3 direction, refDirection;
+ MT_Vector3 normal, direction, refDirection;
MT_Matrix3x3 rotation = obj->NodeGetWorldOrientation();
MT_Scalar filter, newdistance, cosangle;
int axis, sign;
if (m_posDampTime) {
filter = m_posDampTime/(1.0+m_posDampTime);
+ } else {
+ filter = 0.0;
}
switch (m_locrot) {
case KX_ACT_CONSTRAINT_ORIX:
@@ -225,12 +240,8 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
} else {
refDirection = m_refDirection;
}
- if (m_posDampTime) {
- // apply damping on the direction
- direction = filter*direction + (1.0-filter)*refDirection;
- } else {
- direction = refDirection;
- }
+ // apply damping on the direction
+ direction = filter*direction + (1.0-filter)*refDirection;
obj->AlignAxisToVect(direction, axis);
result = true;
goto CHECK_TIME;
@@ -242,53 +253,76 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
case KX_ACT_CONSTRAINT_DIRNZ:
switch (m_locrot) {
case KX_ACT_CONSTRAINT_DIRPX:
- direction[0] = rotation[0][0];
- direction[1] = rotation[1][0];
- direction[2] = rotation[2][0];
+ normal[0] = rotation[0][0];
+ normal[1] = rotation[1][0];
+ normal[2] = rotation[2][0];
axis = 0; // axis according to KX_GameObject::AlignAxisToVect()
- sign = 1; // X axis will be anti parrallel to normal
+ sign = 0; // X axis will be parrallel to direction of ray
break;
case KX_ACT_CONSTRAINT_DIRPY:
- direction[0] = rotation[0][1];
- direction[1] = rotation[1][1];
- direction[2] = rotation[2][1];
+ normal[0] = rotation[0][1];
+ normal[1] = rotation[1][1];
+ normal[2] = rotation[2][1];
axis = 1;
- sign = 1;
+ sign = 0;
break;
case KX_ACT_CONSTRAINT_DIRPZ:
- direction[0] = rotation[0][2];
- direction[1] = rotation[1][2];
- direction[2] = rotation[2][2];
+ normal[0] = rotation[0][2];
+ normal[1] = rotation[1][2];
+ normal[2] = rotation[2][2];
axis = 2;
- sign = 1;
+ sign = 0;
break;
case KX_ACT_CONSTRAINT_DIRNX:
- direction[0] = -rotation[0][0];
- direction[1] = -rotation[1][0];
- direction[2] = -rotation[2][0];
+ normal[0] = -rotation[0][0];
+ normal[1] = -rotation[1][0];
+ normal[2] = -rotation[2][0];
axis = 0;
- sign = 0;
+ sign = 1;
break;
case KX_ACT_CONSTRAINT_DIRNY:
- direction[0] = -rotation[0][1];
- direction[1] = -rotation[1][1];
- direction[2] = -rotation[2][1];
+ normal[0] = -rotation[0][1];
+ normal[1] = -rotation[1][1];
+ normal[2] = -rotation[2][1];
axis = 1;
- sign = 0;
+ sign = 1;
break;
case KX_ACT_CONSTRAINT_DIRNZ:
- direction[0] = -rotation[0][2];
- direction[1] = -rotation[1][2];
- direction[2] = -rotation[2][2];
+ normal[0] = -rotation[0][2];
+ normal[1] = -rotation[1][2];
+ normal[2] = -rotation[2][2];
axis = 2;
- sign = 0;
+ sign = 1;
break;
}
- direction.normalize();
+ normal.normalize();
+ if (m_option & KX_ACT_CONSTRAINT_LOCAL) {
+ // direction of the ray is along the local axis
+ direction = normal;
+ } else {
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_DIRPX:
+ direction = MT_Vector3(1.0,0.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_DIRPY:
+ direction = MT_Vector3(0.0,1.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_DIRPZ:
+ direction = MT_Vector3(0.0,0.0,1.0);
+ break;
+ case KX_ACT_CONSTRAINT_DIRNX:
+ direction = MT_Vector3(-1.0,0.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_DIRNY:
+ direction = MT_Vector3(0.0,-1.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_DIRNZ:
+ direction = MT_Vector3(0.0,0.0,-1.0);
+ break;
+ }
+ }
{
MT_Point3 topoint = position + (m_maximumBound) * direction;
- MT_Point3 resultpoint;
- MT_Vector3 resultnormal;
PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment();
KX_IPhysicsController *spc = obj->GetPhysicsController();
@@ -304,9 +338,10 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
parent->Release();
}
}
- result = KX_RayCast::RayTest(spc, pe, position, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_ConstraintActuator>(this));
-
+ KX_RayCast::Callback<KX_ConstraintActuator> callback(this,spc);
+ result = KX_RayCast::RayTest(pe, position, topoint, callback);
if (result) {
+ MT_Vector3 newnormal = callback.m_hitNormal;
// compute new position & orientation
if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) {
// if none option is set, the actuator does nothing but detect ray
@@ -314,29 +349,40 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
goto CHECK_TIME;
}
if (m_option & KX_ACT_CONSTRAINT_NORMAL) {
- // the new orientation must be so that the axis is parallel to normal
- if (sign)
- resultnormal = -resultnormal;
+ MT_Scalar rotFilter;
// apply damping on the direction
if (m_rotDampTime) {
- MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime);
- resultnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*resultnormal;
- } else if (m_posDampTime) {
- resultnormal = -filter*direction + (1.0-filter)*resultnormal;
+ rotFilter = m_rotDampTime/(1.0+m_rotDampTime);
+ } else {
+ rotFilter = filter;
+ }
+ newnormal = rotFilter*normal - (1.0-rotFilter)*newnormal;
+ obj->AlignAxisToVect((sign)?-newnormal:newnormal, axis);
+ if (m_option & KX_ACT_CONSTRAINT_LOCAL) {
+ direction = newnormal;
+ direction.normalize();
}
- obj->AlignAxisToVect(resultnormal, axis);
- direction = -resultnormal;
}
if (m_option & KX_ACT_CONSTRAINT_DISTANCE) {
if (m_posDampTime) {
- newdistance = filter*(position-resultpoint).length()+(1.0-filter)*m_minimumBound;
+ newdistance = filter*(position-callback.m_hitPoint).length()+(1.0-filter)*m_minimumBound;
} else {
newdistance = m_minimumBound;
}
+ // logically we should cancel the speed along the ray direction as we set the
+ // position along that axis
+ spc = obj->GetPhysicsController();
+ if (spc && spc->IsDyna()) {
+ MT_Vector3 linV = spc->GetLinearVelocity();
+ // cancel the projection along the ray direction
+ MT_Scalar fallspeed = linV.dot(direction);
+ if (!MT_fuzzyZero(fallspeed))
+ spc->SetLinearVelocity(linV-fallspeed*direction,false);
+ }
} else {
- newdistance = (position-resultpoint).length();
+ newdistance = (position-callback.m_hitPoint).length();
}
- newposition = resultpoint-newdistance*direction;
+ newposition = callback.m_hitPoint-newdistance*direction;
} else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) {
// no contact but still keep running
result = true;
@@ -344,10 +390,114 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
}
}
break;
+ case KX_ACT_CONSTRAINT_FHPX:
+ case KX_ACT_CONSTRAINT_FHPY:
+ case KX_ACT_CONSTRAINT_FHPZ:
+ case KX_ACT_CONSTRAINT_FHNX:
+ case KX_ACT_CONSTRAINT_FHNY:
+ case KX_ACT_CONSTRAINT_FHNZ:
+ switch (m_locrot) {
+ case KX_ACT_CONSTRAINT_FHPX:
+ normal[0] = -rotation[0][0];
+ normal[1] = -rotation[1][0];
+ normal[2] = -rotation[2][0];
+ direction = MT_Vector3(1.0,0.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_FHPY:
+ normal[0] = -rotation[0][1];
+ normal[1] = -rotation[1][1];
+ normal[2] = -rotation[2][1];
+ direction = MT_Vector3(0.0,1.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_FHPZ:
+ normal[0] = -rotation[0][2];
+ normal[1] = -rotation[1][2];
+ normal[2] = -rotation[2][2];
+ direction = MT_Vector3(0.0,0.0,1.0);
+ break;
+ case KX_ACT_CONSTRAINT_FHNX:
+ normal[0] = rotation[0][0];
+ normal[1] = rotation[1][0];
+ normal[2] = rotation[2][0];
+ direction = MT_Vector3(-1.0,0.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_FHNY:
+ normal[0] = rotation[0][1];
+ normal[1] = rotation[1][1];
+ normal[2] = rotation[2][1];
+ direction = MT_Vector3(0.0,-1.0,0.0);
+ break;
+ case KX_ACT_CONSTRAINT_FHNZ:
+ normal[0] = rotation[0][2];
+ normal[1] = rotation[1][2];
+ normal[2] = rotation[2][2];
+ direction = MT_Vector3(0.0,0.0,-1.0);
+ break;
+ }
+ normal.normalize();
+ {
+ PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment();
+ KX_IPhysicsController *spc = obj->GetPhysicsController();
+
+ if (!pe) {
+ std::cout << "WARNING: Constraint actuator " << GetName() << ": There is no physics environment!" << std::endl;
+ goto CHECK_TIME;
+ }
+ if (!spc || !spc->IsDyna()) {
+ // the object is not dynamic, it won't support setting speed
+ goto CHECK_TIME;
+ }
+ m_hitObject = NULL;
+ // distance of Fh area is stored in m_minimum
+ MT_Point3 topoint = position + (m_minimumBound+spc->GetRadius()) * direction;
+ KX_RayCast::Callback<KX_ConstraintActuator> callback(this,spc);
+ result = KX_RayCast::RayTest(pe, position, topoint, callback);
+ // we expect a hit object
+ if (!m_hitObject)
+ result = false;
+ if (result)
+ {
+ MT_Vector3 newnormal = callback.m_hitNormal;
+ // compute new position & orientation
+ MT_Scalar distance = (callback.m_hitPoint-position).length()-spc->GetRadius();
+ // estimate the velocity of the hit point
+ MT_Point3 relativeHitPoint;
+ relativeHitPoint = (callback.m_hitPoint-m_hitObject->NodeGetWorldPosition());
+ MT_Vector3 velocityHitPoint = m_hitObject->GetVelocity(relativeHitPoint);
+ MT_Vector3 relativeVelocity = spc->GetLinearVelocity() - velocityHitPoint;
+ MT_Scalar relativeVelocityRay = direction.dot(relativeVelocity);
+ MT_Scalar springExtent = 1.0 - distance/m_minimumBound;
+ // Fh force is stored in m_maximum
+ MT_Scalar springForce = springExtent * m_maximumBound;
+ // damping is stored in m_refDirection [0] = damping, [1] = rot damping
+ MT_Scalar springDamp = relativeVelocityRay * m_refDirection[0];
+ MT_Vector3 newVelocity = spc->GetLinearVelocity()-(springForce+springDamp)*direction;
+ if (m_option & KX_ACT_CONSTRAINT_NORMAL)
+ {
+ newVelocity+=(springForce+springDamp)*(newnormal-newnormal.dot(direction)*direction);
+ }
+ spc->SetLinearVelocity(newVelocity, false);
+ if (m_option & KX_ACT_CONSTRAINT_DOROTFH)
+ {
+ MT_Vector3 angSpring = (normal.cross(newnormal))*m_maximumBound;
+ MT_Vector3 angVelocity = spc->GetAngularVelocity();
+ // remove component that is parallel to normal
+ angVelocity -= angVelocity.dot(newnormal)*newnormal;
+ MT_Vector3 angDamp = angVelocity * ((m_refDirection[1]>MT_EPSILON)?m_refDirection[1]:m_refDirection[0]);
+ spc->SetAngularVelocity(spc->GetAngularVelocity()+(angSpring-angDamp), false);
+ }
+ } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) {
+ // no contact but still keep running
+ result = true;
+ }
+ // don't set the position with this constraint
+ goto CHECK_TIME;
+ }
+ break;
case KX_ACT_CONSTRAINT_LOCX:
case KX_ACT_CONSTRAINT_LOCY:
case KX_ACT_CONSTRAINT_LOCZ:
- newposition = position;
+ newposition = position = obj->GetSGNode()->GetLocalPosition();
switch (m_locrot) {
case KX_ACT_CONSTRAINT_LOCX:
Clamp(newposition[0], m_minimumBound, m_maximumBound);
@@ -363,7 +513,8 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame)
if (m_posDampTime) {
newposition = filter*position + (1.0-filter)*newposition;
}
- break;
+ obj->NodeSetLocalPosition(newposition);
+ goto CHECK_TIME;
}
if (result) {
// set the new position but take into account parent if any
@@ -436,28 +587,28 @@ PyParentObject KX_ConstraintActuator::Parents[] = {
};
PyMethodDef KX_ConstraintActuator::Methods[] = {
- {"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, SetDamp_doc},
- {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, GetDamp_doc},
- {"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, SetRotDamp_doc},
- {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_NOARGS, GetRotDamp_doc},
- {"setDirection", (PyCFunction) KX_ConstraintActuator::sPySetDirection, METH_VARARGS, SetDirection_doc},
- {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_NOARGS, GetDirection_doc},
- {"setOption", (PyCFunction) KX_ConstraintActuator::sPySetOption, METH_VARARGS, SetOption_doc},
- {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_NOARGS, GetOption_doc},
- {"setTime", (PyCFunction) KX_ConstraintActuator::sPySetTime, METH_VARARGS, SetTime_doc},
- {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_NOARGS, GetTime_doc},
- {"setProperty", (PyCFunction) KX_ConstraintActuator::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc},
- {"setMin", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetMin_doc},
- {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetMin_doc},
- {"setDistance", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetDistance_doc},
- {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetDistance_doc},
- {"setMax", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetMax_doc},
- {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetMax_doc},
- {"setRayLength", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetRayLength_doc},
- {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetRayLength_doc},
- {"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, SetLimit_doc},
- {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, GetLimit_doc},
+ {"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, (PY_METHODCHAR)SetDamp_doc},
+ {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, (PY_METHODCHAR)GetDamp_doc},
+ {"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, (PY_METHODCHAR)SetRotDamp_doc},
+ {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_NOARGS, (PY_METHODCHAR)GetRotDamp_doc},
+ {"setDirection", (PyCFunction) KX_ConstraintActuator::sPySetDirection, METH_VARARGS, (PY_METHODCHAR)SetDirection_doc},
+ {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_NOARGS, (PY_METHODCHAR)GetDirection_doc},
+ {"setOption", (PyCFunction) KX_ConstraintActuator::sPySetOption, METH_VARARGS, (PY_METHODCHAR)SetOption_doc},
+ {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_NOARGS, (PY_METHODCHAR)GetOption_doc},
+ {"setTime", (PyCFunction) KX_ConstraintActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc},
+ {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc},
+ {"setProperty", (PyCFunction) KX_ConstraintActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"setMin", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetMin_doc},
+ {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, (PY_METHODCHAR)GetMin_doc},
+ {"setDistance", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, (PY_METHODCHAR)SetDistance_doc},
+ {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, (PY_METHODCHAR)GetDistance_doc},
+ {"setMax", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, (PY_METHODCHAR)SetMax_doc},
+ {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, (PY_METHODCHAR)GetMax_doc},
+ {"setRayLength", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, (PY_METHODCHAR)SetRayLength_doc},
+ {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, (PY_METHODCHAR)GetRayLength_doc},
+ {"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, (PY_METHODCHAR)SetLimit_doc},
+ {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, (PY_METHODCHAR)GetLimit_doc},
{NULL,NULL} //Sentinel
};
@@ -466,7 +617,7 @@ PyObject* KX_ConstraintActuator::_getattr(const STR_String& attr) {
}
/* 2. setDamp */
-char KX_ConstraintActuator::SetDamp_doc[] =
+const char KX_ConstraintActuator::SetDamp_doc[] =
"setDamp(duration)\n"
"\t- duration: integer\n"
"\tSets the time constant of the orientation and distance constraint.\n"
@@ -485,7 +636,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self,
Py_Return;
}
/* 3. getDamp */
-char KX_ConstraintActuator::GetDamp_doc[] =
+const char KX_ConstraintActuator::GetDamp_doc[] =
"getDamp()\n"
"\tReturns the damping parameter.\n";
PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){
@@ -493,7 +644,7 @@ PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){
}
/* 2. setRotDamp */
-char KX_ConstraintActuator::SetRotDamp_doc[] =
+const char KX_ConstraintActuator::SetRotDamp_doc[] =
"setRotDamp(duration)\n"
"\t- duration: integer\n"
"\tSets the time constant of the orientation constraint.\n"
@@ -512,7 +663,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self,
Py_Return;
}
/* 3. getRotDamp */
-char KX_ConstraintActuator::GetRotDamp_doc[] =
+const char KX_ConstraintActuator::GetRotDamp_doc[] =
"getRotDamp()\n"
"\tReturns the damping time for application of the constraint.\n";
PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){
@@ -520,7 +671,7 @@ PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){
}
/* 2. setDirection */
-char KX_ConstraintActuator::SetDirection_doc[] =
+const char KX_ConstraintActuator::SetDirection_doc[] =
"setDirection(vector)\n"
"\t- vector: 3-tuple\n"
"\tSets the reference direction in world coordinate for the orientation constraint.\n";
@@ -547,7 +698,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self,
Py_Return;
}
/* 3. getDirection */
-char KX_ConstraintActuator::GetDirection_doc[] =
+const char KX_ConstraintActuator::GetDirection_doc[] =
"getDirection()\n"
"\tReturns the reference direction of the orientation constraint as a 3-tuple.\n";
PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){
@@ -560,7 +711,7 @@ PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){
}
/* 2. setOption */
-char KX_ConstraintActuator::SetOption_doc[] =
+const char KX_ConstraintActuator::SetOption_doc[] =
"setOption(option)\n"
"\t- option: integer\n"
"\tSets several options of the distance constraint.\n"
@@ -582,7 +733,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self,
Py_Return;
}
/* 3. getOption */
-char KX_ConstraintActuator::GetOption_doc[] =
+const char KX_ConstraintActuator::GetOption_doc[] =
"getOption()\n"
"\tReturns the option parameter.\n";
PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){
@@ -590,7 +741,7 @@ PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){
}
/* 2. setTime */
-char KX_ConstraintActuator::SetTime_doc[] =
+const char KX_ConstraintActuator::SetTime_doc[] =
"setTime(duration)\n"
"\t- duration: integer\n"
"\tSets the activation time of the actuator.\n"
@@ -611,7 +762,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self,
Py_Return;
}
/* 3. getTime */
-char KX_ConstraintActuator::GetTime_doc[] =
+const char KX_ConstraintActuator::GetTime_doc[] =
"getTime()\n"
"\tReturns the time parameter.\n";
PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){
@@ -619,7 +770,7 @@ PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){
}
/* 2. setProperty */
-char KX_ConstraintActuator::SetProperty_doc[] =
+const char KX_ConstraintActuator::SetProperty_doc[] =
"setProperty(property)\n"
"\t- property: string\n"
"\tSets the name of the property or material for the ray detection of the distance constraint.\n"
@@ -641,7 +792,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self,
Py_Return;
}
/* 3. getProperty */
-char KX_ConstraintActuator::GetProperty_doc[] =
+const char KX_ConstraintActuator::GetProperty_doc[] =
"getProperty()\n"
"\tReturns the property parameter.\n";
PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){
@@ -649,12 +800,12 @@ PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){
}
/* 4. setDistance */
-char KX_ConstraintActuator::SetDistance_doc[] =
+const char KX_ConstraintActuator::SetDistance_doc[] =
"setDistance(distance)\n"
"\t- distance: float\n"
"\tSets the target distance in distance constraint\n";
/* 4. setMin */
-char KX_ConstraintActuator::SetMin_doc[] =
+const char KX_ConstraintActuator::SetMin_doc[] =
"setMin(lower_bound)\n"
"\t- lower_bound: float\n"
"\tSets the lower value of the interval to which the value\n"
@@ -681,11 +832,11 @@ PyObject* KX_ConstraintActuator::PySetMin(PyObject* self,
Py_Return;
}
/* 5. getDistance */
-char KX_ConstraintActuator::GetDistance_doc[] =
+const char KX_ConstraintActuator::GetDistance_doc[] =
"getDistance()\n"
"\tReturns the distance parameter \n";
/* 5. getMin */
-char KX_ConstraintActuator::GetMin_doc[] =
+const char KX_ConstraintActuator::GetMin_doc[] =
"getMin()\n"
"\tReturns the lower value of the interval to which the value\n"
"\tis clipped.\n";
@@ -694,12 +845,12 @@ PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self) {
}
/* 6. setRayLength */
-char KX_ConstraintActuator::SetRayLength_doc[] =
+const char KX_ConstraintActuator::SetRayLength_doc[] =
"setRayLength(length)\n"
"\t- length: float\n"
"\tSets the maximum ray length of the distance constraint\n";
/* 6. setMax */
-char KX_ConstraintActuator::SetMax_doc[] =
+const char KX_ConstraintActuator::SetMax_doc[] =
"setMax(upper_bound)\n"
"\t- upper_bound: float\n"
"\tSets the upper value of the interval to which the value\n"
@@ -726,11 +877,11 @@ PyObject* KX_ConstraintActuator::PySetMax(PyObject* self,
Py_Return;
}
/* 7. getRayLength */
-char KX_ConstraintActuator::GetRayLength_doc[] =
+const char KX_ConstraintActuator::GetRayLength_doc[] =
"getRayLength()\n"
"\tReturns the length of the ray\n";
/* 7. getMax */
-char KX_ConstraintActuator::GetMax_doc[] =
+const char KX_ConstraintActuator::GetMax_doc[] =
"getMax()\n"
"\tReturns the upper value of the interval to which the value\n"
"\tis clipped.\n";
@@ -741,7 +892,7 @@ PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self) {
/* This setter/getter probably for the constraint type */
/* 8. setLimit */
-char KX_ConstraintActuator::SetLimit_doc[] =
+const char KX_ConstraintActuator::SetLimit_doc[] =
"setLimit(type)\n"
"\t- type: integer\n"
"\t 1 : LocX\n"
@@ -770,7 +921,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self,
Py_Return;
}
/* 9. getLimit */
-char KX_ConstraintActuator::GetLimit_doc[] =
+const char KX_ConstraintActuator::GetLimit_doc[] =
"getLimit()\n"
"\tReturns the type of constraint.\n";
PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self) {
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h
index d9f39124cac..28b9b1e6a0b 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.h
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h
@@ -37,6 +37,9 @@
#include "MT_Vector3.h"
#include "KX_ClientObjectInfo.h"
+class KX_RayCast;
+class KX_GameObject;
+
class KX_ConstraintActuator : public SCA_IActuator
{
Py_Header;
@@ -63,6 +66,8 @@ protected:
int m_option;
// property to check
char m_property[32];
+ // hit object
+ KX_GameObject* m_hitObject;
/**
* Clamp <var> to <min>, <max>. Borders are included (in as far as
@@ -90,6 +95,12 @@ protected:
KX_ACT_CONSTRAINT_ORIX,
KX_ACT_CONSTRAINT_ORIY,
KX_ACT_CONSTRAINT_ORIZ,
+ KX_ACT_CONSTRAINT_FHPX,
+ KX_ACT_CONSTRAINT_FHPY,
+ KX_ACT_CONSTRAINT_FHPZ,
+ KX_ACT_CONSTRAINT_FHNX,
+ KX_ACT_CONSTRAINT_FHNY,
+ KX_ACT_CONSTRAINT_FHNZ,
KX_ACT_CONSTRAINT_MAX
};
// match ACT_CONST_... values from BIF_interface.h
@@ -97,10 +108,13 @@ protected:
KX_ACT_CONSTRAINT_NORMAL = 64,
KX_ACT_CONSTRAINT_MATERIAL = 128,
KX_ACT_CONSTRAINT_PERMANENT = 256,
- KX_ACT_CONSTRAINT_DISTANCE = 512
+ KX_ACT_CONSTRAINT_DISTANCE = 512,
+ KX_ACT_CONSTRAINT_LOCAL = 1024,
+ KX_ACT_CONSTRAINT_DOROTFH = 2048
};
bool IsValidMode(KX_CONSTRAINTTYPE m);
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo*);
KX_ConstraintActuator(SCA_IObject* gameobj,
int posDamptime,
@@ -144,12 +158,12 @@ protected:
KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetProperty);
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin);
KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMin);
- static char SetDistance_doc[];
- static char GetDistance_doc[];
+ static const char SetDistance_doc[];
+ static const char GetDistance_doc[];
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax);
KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMax);
- static char SetRayLength_doc[];
- static char GetRayLength_doc[];
+ static const char SetRayLength_doc[];
+ static const char GetRayLength_doc[];
KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit);
KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetLimit);
};
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index b54da6eb753..c9095ff34f6 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -27,6 +27,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
#include <Python.h>
+#include "PyObjectPlus.h"
#include "KX_ConstraintWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
index 6653026f28a..53486cecf73 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
@@ -75,6 +75,7 @@ struct KX_CBounds
struct KX_ObjectProperties
{
bool m_dyna;
+ bool m_softbody;
double m_radius;
bool m_angular_rigidbody;
bool m_in_active_layer;
@@ -86,6 +87,47 @@ struct KX_ObjectProperties
bool m_disableSleeping;
bool m_hasCompoundChildren;
bool m_isCompoundChild;
+
+ /////////////////////////
+
+ int m_gamesoftFlag;
+ float m_soft_linStiff; /* linear stiffness 0..1 */
+ float m_soft_angStiff; /* angular stiffness 0..1 */
+ float m_soft_volume; /* volume preservation 0..1 */
+
+ int m_soft_viterations; /* Velocities solver iterations */
+ int m_soft_piterations; /* Positions solver iterations */
+ int m_soft_diterations; /* Drift solver iterations */
+ int m_soft_citerations; /* Cluster solver iterations */
+
+ float m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
+ float m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
+ float m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
+ float m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+
+ float m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ float m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ float m_soft_kVCF; /* Velocities correction factor (Baumgarte) */
+ float m_soft_kDP; /* Damping coefficient [0,1] */
+
+ float m_soft_kDG; /* Drag coefficient [0,+inf] */
+ float m_soft_kLF; /* Lift coefficient [0,+inf] */
+ float m_soft_kPR; /* Pressure coefficient [-inf,+inf] */
+ float m_soft_kVC; /* Volume conversation coefficient [0,+inf] */
+
+ float m_soft_kDF; /* Dynamic friction coefficient [0,1] */
+ float m_soft_kMT; /* Pose matching coefficient [0,1] */
+ float m_soft_kCHR; /* Rigid contacts hardness [0,1] */
+ float m_soft_kKHR; /* Kinetic contacts hardness [0,1] */
+
+ float m_soft_kSHR; /* Soft contacts hardness [0,1] */
+ float m_soft_kAHR; /* Anchors hardness [0,1] */
+ int m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
+ int m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/
+
+ /////////////////////////
+
+ double m_margin;
KX_BoundBoxClass m_boundclass;
union {
KX_BoxBounds box;
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index e0cd5a3bc9e..0e7a6d92ec1 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -38,6 +38,8 @@
#include "RAS_MeshObject.h"
#include "KX_Scene.h"
#include "SYS_System.h"
+#include "BL_SkinMeshObject.h"
+#include "BulletSoftBody/btSoftBody.h"
#include "PHY_Pro.h" //todo cleanup
#include "KX_ClientObjectInfo.h"
@@ -76,16 +78,16 @@
struct KX_PhysicsInstance
{
DT_VertexBaseHandle m_vertexbase;
- int m_vtxarray;
+ RAS_DisplayArray* m_darray;
RAS_IPolyMaterial* m_material;
-
- KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat)
+
+ KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat)
: m_vertexbase(vertex_base),
- m_vtxarray(vtxarray),
- m_material(mat)
+ m_darray(darray),
+ m_material(mat)
{
}
-
+
~KX_PhysicsInstance()
{
DT_DeleteVertexBase(m_vertexbase);
@@ -100,11 +102,11 @@ static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoSce
static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
void KX_ConvertSumoObject( KX_GameObject* gameobj,
- RAS_MeshObject* meshobj,
- KX_Scene* kxscene,
- PHY_ShapeProps* kxshapeprops,
- PHY_MaterialProps* kxmaterial,
- struct KX_ObjectProperties* objprop)
+ RAS_MeshObject* meshobj,
+ KX_Scene* kxscene,
+ PHY_ShapeProps* kxshapeprops,
+ PHY_MaterialProps* kxmaterial,
+ struct KX_ObjectProperties* objprop)
{
@@ -150,23 +152,23 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
objprop->m_boundobject.box.m_extends[1],
objprop->m_boundobject.box.m_extends[2]);
smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
- objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
- objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
+ objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
+ objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
break;
case KX_BOUNDCYLINDER:
shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
- smprop->m_mass*smprop->m_radius*smprop->m_radius,
- smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
+ smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
break;
case KX_BOUNDCONE:
shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
- smprop->m_mass*smprop->m_radius*smprop->m_radius,
- smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
+ smprop->m_mass*smprop->m_radius*smprop->m_radius,
+ smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
break;
- /* Dynamic mesh objects. WARNING! slow. */
+ /* Dynamic mesh objects. WARNING! slow. */
case KX_BOUNDPOLYTOPE:
polytope = true;
// fall through
@@ -186,15 +188,15 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
shape = DT_NewSphere(objprop->m_radius);
smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
break;
-
+
}
-
+
sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
-
+
sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
-
+
BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
-
+
}
else {
// non physics object
@@ -320,12 +322,11 @@ static void BL_RegisterSumoObject(
physicscontroller->SetObject(gameobj->GetSGNode());
}
-static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
+static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
{
// instance a mesh from a single vertex array & material
- const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
- //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
- DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
+ const RAS_TexVert *vertex_array = &darray->m_vertex[0];
+ DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
@@ -337,15 +338,19 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
- DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray);
+ DT_Begin();
+ DT_VertexIndex(poly->GetVertexOffset(0));
+ DT_VertexIndex(poly->GetVertexOffset(1));
+ DT_VertexIndex(poly->GetVertexOffset(2));
+ DT_End();
// tesselate
if (poly->VertexCount() == 4)
{
DT_Begin();
- DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[0]);
- DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]);
- DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]);
+ DT_VertexIndex(poly->GetVertexOffset(0));
+ DT_VertexIndex(poly->GetVertexOffset(2));
+ DT_VertexIndex(poly->GetVertexOffset(3));
DT_End();
}
}
@@ -354,16 +359,15 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr
//DT_VertexIndices(indices.size(), &indices[0]);
DT_EndComplexShape();
- map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat));
+ map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
return shape;
}
-static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
+static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
{
// instance a mesh from a single vertex array & material
- const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
- //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
- DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
+ const RAS_TexVert *vertex_array = &darray->m_vertex[0];
+ DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
std::vector<DT_Index> indices;
for (int p = 0; p < meshobj->NumPolygons(); p++)
@@ -373,12 +377,12 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
- indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]);
- indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]);
- indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]);
+ indices.push_back(poly->GetVertexOffset(0));
+ indices.push_back(poly->GetVertexOffset(1));
+ indices.push_back(poly->GetVertexOffset(2));
if (poly->VertexCount() == 4)
- indices.push_back(poly->GetVertexIndexBase().m_indexarray[3]);
+ indices.push_back(poly->GetVertexOffset(3));
}
}
@@ -386,7 +390,7 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar
DT_VertexIndices(indices.size(), &indices[0]);
DT_EndPolytope();
- map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat));
+ map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
return shape;
}
@@ -398,8 +402,8 @@ bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj)
KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)];
if (instance)
{
- const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]);
- DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ());
+ const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0];
+ DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ());
return true;
}
return false;
@@ -425,7 +429,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
// Count the number of collision polygons and check they all come from the same
// vertex array
int numvalidpolys = 0;
- int vtxarray = -1;
+ RAS_DisplayArray *darray = NULL;
RAS_IPolyMaterial *poly_material = NULL;
bool reinstance = true;
@@ -437,14 +441,14 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
if (poly->IsCollider())
{
// check polygon is from the same vertex array
- if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
+ if (poly->GetDisplayArray() != darray)
{
- if (vtxarray < 0)
- vtxarray = poly->GetVertexIndexBase().m_vtxarray;
+ if (darray == NULL)
+ darray = poly->GetDisplayArray();
else
{
reinstance = false;
- vtxarray = -1;
+ darray = NULL;
}
}
@@ -478,9 +482,9 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
if (reinstance)
{
if (polytope)
- shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material);
+ shape = InstancePhysicsPolytope(meshobj, darray, poly_material);
else
- shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material);
+ shape = InstancePhysicsComplex(meshobj, darray, poly_material);
}
else
{
@@ -489,7 +493,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl;
if (!poly_material)
std::cout << " Check mesh materials." << std::endl;
- if (vtxarray < 0)
+ if (darray == NULL)
std::cout << " Check number of vertices." << std::endl;
}
@@ -505,18 +509,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
if (poly->IsCollider())
{ /* We have to tesselate here because SOLID can only raycast triangles */
DT_Begin();
- /* V1 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
- /* V2 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[1],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
- /* V3 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
+ /* V1, V2, V3 */
+ DT_Vertex(poly->GetVertex(2)->getXYZ());
+ DT_Vertex(poly->GetVertex(1)->getXYZ());
+ DT_Vertex(poly->GetVertex(0)->getXYZ());
numvalidpolys++;
DT_End();
@@ -524,18 +520,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope
if (poly->VertexCount() == 4)
{
DT_Begin();
- /* V1 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[3],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
- /* V3 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
- /* V4 */
- DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
+ /* V1, V3, V4 */
+ DT_Vertex(poly->GetVertex(3)->getXYZ());
+ DT_Vertex(poly->GetVertex(2)->getXYZ());
+ DT_Vertex(poly->GetVertex(0)->getXYZ());
numvalidpolys++;
DT_End();
@@ -679,189 +667,107 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
#endif //WIN32
-// forward declarations
-static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
-{
- if (!meshobj)
- return 0;
-
- btCollisionShape* collisionMeshShape = 0;
- btConvexHullShape* convexHullShape = 0;
- btTriangleMeshShape* concaveShape = 0;
-
- btTriangleMesh* collisionMeshData = 0;
-
- //see if there is any polygons, if not, bail out.
-
- int numPoints = 0;
- btVector3* points = 0;
-
- // Mesh has no polygons!
- int numpolys = meshobj->NumPolygons();
- if (!numpolys)
+
+ class KX_SoftBodyDeformer : public RAS_Deformer
{
- return NULL;
- }
+ class RAS_MeshObject* m_pMeshObject;
+ class KX_GameObject* m_gameobj;
- // Count the number of collision polygons and check they all come from the same
- // vertex array
- int numvalidpolys = 0;
- int vtxarray = -1;
- RAS_IPolyMaterial *poly_material = NULL;
- bool reinstance = true;
-
- for (int p=0; p<numpolys; p++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p);
-
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
+ public:
+ KX_SoftBodyDeformer(RAS_MeshObject* pMeshObject,KX_GameObject* gameobj)
+ :m_pMeshObject(pMeshObject),
+ m_gameobj(gameobj)
{
- // check polygon is from the same vertex array
- if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
- {
- if (vtxarray < 0)
- vtxarray = poly->GetVertexIndexBase().m_vtxarray;
- else
- {
- reinstance = false;
- vtxarray = -1;
- }
- }
-
- // check poly is from the same material
- if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
- {
- if (poly_material)
- {
- reinstance = false;
- poly_material = NULL;
- }
- else
- poly_material = poly->GetMaterial()->GetPolyMaterial();
- }
-
- // count the number of collision polys
- numvalidpolys++;
+ //printf("KX_SoftBodyDeformer\n");
+ };
- // We have one collision poly, and we can't reinstance, so we
- // might as well break here.
- if (!reinstance)
- break;
+ virtual ~KX_SoftBodyDeformer()
+ {
+ //printf("~KX_SoftBodyDeformer\n");
+ };
+ virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
+ {
+ //printf("relink\n");
}
- }
+ virtual bool Apply(class RAS_IPolyMaterial *polymat)
+ {
+ KX_BulletPhysicsController* ctrl = (KX_BulletPhysicsController*) m_gameobj->GetPhysicsController();
+ if (!ctrl)
+ return false;
- // No collision polygons
- if (numvalidpolys < 1)
- return NULL;
+ btSoftBody* softBody= ctrl->GetSoftBody();
+ if (!softBody)
+ return false;
+ //printf("apply\n");
+ RAS_MeshSlot::iterator it;
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ size_t i;
- if (polytope)
- {
- convexHullShape = new btConvexHullShape(&points[0].getX(),numPoints);
- collisionMeshShape = convexHullShape;
- } else
- {
- collisionMeshData = new btTriangleMesh();
-// concaveShape = new btTriangleMeshShape(collisionMeshData);
- //collisionMeshShape = concaveShape;
-
- }
+ // update the vertex in m_transverts
+ Update();
- numvalidpolys = 0;
- for (int p2=0; p2<numpolys; p2++)
- {
- RAS_Polygon* poly = meshobj->GetPolygon(p2);
+ // The vertex cache can only be updated for this deformer:
+ // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
+ // share the same mesh (=the same cache). As the rendering is done per polymaterial
+ // cycling through the objects, the entire mesh cache cannot be updated in one shot.
+ mmat = m_pMeshObject->GetMeshMaterial(polymat);
+ if(!mmat->m_slots[(void*)m_gameobj])
+ return true;
- // only add polygons that have the collisionflag set
- if (poly->IsCollider())
- {
- //Bullet can raycast any shape, so
- if (polytope)
- {
- for (int i=0;i<poly->VertexCount();i++)
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[i],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 point(vtx[0],vtx[1],vtx[2]);
- convexHullShape->addPoint(point);
- }
- if (poly->VertexCount())
- numvalidpolys++;
+ slot = *mmat->m_slots[(void*)m_gameobj];
- } else
+ // for each array
+ for(slot->begin(it); !slot->end(it); slot->next(it))
{
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[1],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
- collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
- numvalidpolys++;
- }
- if (poly->VertexCount() == 4)
- {
- const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[3],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[2],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
- vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
- poly->GetVertexIndexBase().m_indexarray[0],
- poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
- btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
- collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
- numvalidpolys++;
- }
+ btSoftBody::tNodeArray& nodes(softBody->m_nodes);
- }
- }
- }
+ int index = 0;
+ for(i=it.startvertex; i<it.endvertex; i++,index++) {
+ RAS_TexVert& v = it.vertex[i];
+ btAssert(v.getSoftBodyIndex() >= 0);
+ MT_Point3 pt (
+ nodes[v.getSoftBodyIndex()].m_x.getX(),
+ nodes[v.getSoftBodyIndex()].m_x.getY(),
+ nodes[v.getSoftBodyIndex()].m_x.getZ());
+ v.SetXYZ(pt);
+ MT_Vector3 normal (
+ nodes[v.getSoftBodyIndex()].m_n.getX(),
+ nodes[v.getSoftBodyIndex()].m_n.getY(),
+ nodes[v.getSoftBodyIndex()].m_n.getZ());
+ v.SetNormal(normal);
- if (numvalidpolys > 0)
- {
-
- if (!polytope)
+ }
+ }
+ return true;
+ }
+ virtual bool Update(void)
{
- bool useQuantization = true;
- concaveShape = new btBvhTriangleMeshShape( collisionMeshData, useQuantization );
- //concaveShape = new btTriangleMeshShape( collisionMeshData );
-
- concaveShape->recalcLocalAabb();
- if (collisionMeshShape)
- delete collisionMeshShape;
- collisionMeshShape = concaveShape;
+ //printf("update\n");
+ return true;//??
+ }
+ virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)
+ {
+ KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(replica->GetMesh(0),replica);
+ return deformer;
+ }
- }
-
-
+ virtual bool SkipVertexTransform()
+ {
+ return true;
+ }
- return collisionMeshShape;
- }
- if (collisionMeshShape)
- delete collisionMeshShape;
- if (collisionMeshData)
- delete collisionMeshData;
- return NULL;
+ protected:
+ //class RAS_MeshObject *m_pMesh;
+ };
-}
+// forward declarations
void KX_ConvertBulletObject( class KX_GameObject* gameobj,
class RAS_MeshObject* meshobj,
@@ -878,6 +784,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
bool isbulletdyna = false;
CcdConstructionInfo ci;
class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
+ class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
@@ -894,120 +801,99 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_gravity = btVector3(0,0,0);
ci.m_localInertiaTensor =btVector3(0,0,0);
ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
+ ci.m_margin = objprop->m_margin;
+ shapeInfo->m_radius = objprop->m_radius;
isbulletdyna = objprop->m_dyna;
ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
- btTransform trans;
- trans.setIdentity();
-
btCollisionShape* bm = 0;
switch (objprop->m_boundclass)
{
case KX_BOUNDSPHERE:
{
- float radius = objprop->m_radius;
- btVector3 inertiaHalfExtents (
- radius,
- radius,
- radius);
+ //float radius = objprop->m_radius;
+ //btVector3 inertiaHalfExtents (
+ // radius,
+ // radius,
+ // radius);
//blender doesn't support multisphere, but for testing:
//bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
- bm = new btSphereShape(objprop->m_radius);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ shapeInfo->m_shapeType = PHY_SHAPE_SPHERE;
+ bm = shapeInfo->CreateBulletShape();
break;
};
case KX_BOUNDBOX:
{
- MT_Vector3 halfExtents (
+ shapeInfo->m_halfExtend.setValue(
objprop->m_boundobject.box.m_extends[0],
- objprop->m_boundobject.box.m_extends[1],
- objprop->m_boundobject.box.m_extends[2]);
-
- halfExtents /= 2.f;
-
- //btVector3 he (halfExtents[0]-CONVEX_DISTANCE_MARGIN ,halfExtents[1]-CONVEX_DISTANCE_MARGIN ,halfExtents[2]-CONVEX_DISTANCE_MARGIN );
- //he = he.absolute();
-
- btVector3 he (halfExtents[0],halfExtents[1],halfExtents[2]);
- he = he.absolute();
-
+ objprop->m_boundobject.box.m_extends[1],
+ objprop->m_boundobject.box.m_extends[2]);
- bm = new btBoxShape(he);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ shapeInfo->m_halfExtend /= 2.0;
+ shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute();
+ shapeInfo->m_shapeType = PHY_SHAPE_BOX;
+ bm = shapeInfo->CreateBulletShape();
break;
};
case KX_BOUNDCYLINDER:
{
- btVector3 halfExtents (
+ shapeInfo->m_halfExtend.setValue(
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_radius,
objprop->m_boundobject.c.m_height * 0.5f
);
- bm = new btCylinderShapeZ(halfExtents);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+ shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER;
+ bm = shapeInfo->CreateBulletShape();
break;
}
- case KX_BOUNDCONE:
+ case KX_BOUNDCONE:
{
- btVector3 halfExtents (objprop->m_boundobject.box.m_extends[0],
- objprop->m_boundobject.box.m_extends[1],
- objprop->m_boundobject.box.m_extends[2]);
-
-
- halfExtents /= 2.f;
-
- bm = new btConeShapeZ(objprop->m_boundobject.c.m_radius,objprop->m_boundobject.c.m_height);
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
-
+ shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
+ shapeInfo->m_height = objprop->m_boundobject.c.m_height;
+ shapeInfo->m_shapeType = PHY_SHAPE_CONE;
+ bm = shapeInfo->CreateBulletShape();
break;
}
- case KX_BOUNDPOLYTOPE:
- {
- bm = CreateBulletShapeFromMesh(meshobj,true);
- if (bm)
+ case KX_BOUNDPOLYTOPE:
+ {
+ shapeInfo->SetMesh(meshobj, true,false);
+ bm = shapeInfo->CreateBulletShape();
+ break;
+ }
+ case KX_BOUNDMESH:
+ {
+
+ if (!ci.m_mass ||objprop->m_softbody)
+ {
+ // mesh shapes can be shared, check first if we already have a shape on that mesh
+ class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, false);
+ if (sharedShapeInfo != NULL)
{
- bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
- }
- break;
- }
- case KX_BOUNDMESH:
- {
- if (!ci.m_mass)
- {
- bm = CreateBulletShapeFromMesh(meshobj,false);
- ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
- //no moving concave meshes, so don't bother calculating inertia
- //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ delete shapeInfo;
+ shapeInfo = sharedShapeInfo;
+ shapeInfo->AddRef();
+ } else
+ {
+ shapeInfo->SetMesh(meshobj, false,false);
}
+ if (objprop->m_softbody)
+ shapeInfo->setVertexWeldingThreshold(0.01f); //todo: expose this to the UI
- break;
- }
-
- default:
- //interpret the shape as a concave triangle-mesh
- {
- if (meshobj)
+ bm = shapeInfo->CreateBulletShape();
+ //no moving concave meshes, so don't bother calculating inertia
+ //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
+ } else
{
- bm = CreateBulletShapeFromMesh(meshobj,false);
- ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
-
- // assert(0);
-
- /*
- meshobj->ScheduleCollisionPolygons();
-
- KX_DeformableMesh* gfxmesh = new KX_DeformableMesh(meshobj);
- gfxmesh->sendFixedMapping();
- //trianglemesh
- bm = new TriangleMeshInterface(gfxmesh,trans);
- */
+ shapeInfo->SetMesh(meshobj, false,true);
+ bm = shapeInfo->CreateBulletShape();
}
+
+ break;
}
}
@@ -1017,11 +903,11 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
if (!bm)
{
delete motionstate;
+ delete shapeInfo;
return;
}
- bm->setMargin(0.06);
-
+ bm->setMargin(ci.m_margin);
if (objprop->m_isCompoundChild)
@@ -1030,31 +916,46 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
//take relative transform into account!
KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
assert(parentCtrl);
+ CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
btRigidBody* rigidbody = parentCtrl->GetRigidBody();
btCollisionShape* colShape = rigidbody->getCollisionShape();
assert(colShape->isCompound());
btCompoundShape* compoundShape = (btCompoundShape*)colShape;
- btTransform childTrans;
- childTrans.setIdentity();
- NodeList& children = objprop->m_dynamic_parent->GetSGNode()->GetSGChildren();
- MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition();
- MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation();
- MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale();
+ // compute the local transform from parent, this may include a parent inverse node
+ SG_Node* gameNode = gameobj->GetSGNode();
+ SG_Node* parentInverseNode = gameNode->GetSGParent();
+ if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL)
+ // this is not a parent inverse node, cancel it
+ parentInverseNode = NULL;
+ // now combine the parent inverse node and the game node
+ MT_Point3 childPos = gameNode->GetLocalPosition();
+ MT_Matrix3x3 childRot = gameNode->GetLocalOrientation();
+ MT_Vector3 childScale = gameNode->GetLocalScale();
+ if (parentInverseNode)
+ {
+ const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition();
+ const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation();
+ const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale();
+ childRot = parentInverseRot * childRot;
+ childScale = parentInverseScale * childScale;
+ childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos);
+ }
- bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z()));
- childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
+ shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z());
+ bm->setLocalScaling(shapeInfo->m_childScale);
+
+ shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
float rotval[12];
childRot.getValue(rotval);
btMatrix3x3 newRot;
newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]);
newRot = newRot.transpose();
- childTrans.setBasis(newRot);
-
-
- compoundShape->addChildShape(childTrans,bm);
- kxscene->AddShape(bm);
+ shapeInfo->m_childTrans.setBasis(newRot);
+ parentShapeInfo->AddShape(shapeInfo);
+
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
//do some recalc?
//recalc inertia for rigidbody
if (!rigidbody->isStaticOrKinematicObject())
@@ -1069,15 +970,16 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
if (objprop->m_hasCompoundChildren)
{
- //replace shape by compoundShape
+ // create a compound shape info
+ CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo();
+ compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND;
+ compoundShapeInfo->AddShape(shapeInfo);
+ // create the compound shape manually as we already have the child shape
btCompoundShape* compoundShape = new btCompoundShape();
- btTransform identTrans;
- identTrans.setIdentity();
- compoundShape->addChildShape(identTrans,bm);
- //note abount compoundShape: Bullet does not delete the child shapes when
- //the compound shape is deleted, so insert also the child shapes
- kxscene->AddShape(bm);
+ compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
+ // now replace the shape
bm = compoundShape;
+ shapeInfo = compoundShapeInfo;
}
@@ -1113,6 +1015,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_collisionShape = bm;
+ ci.m_shapeInfo = shapeInfo;
ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
ci.m_restitution = smmaterial->m_restitution;
ci.m_physicsEnv = env;
@@ -1121,12 +1024,70 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_angularDamping = 1.f - shapeprops->m_ang_drag;
//need a bit of damping, else system doesn't behave well
ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour
+
+ ci.m_do_anisotropic = shapeprops->m_do_anisotropic;
+ ci.m_anisotropicFriction.setValue(shapeprops->m_friction_scaling[0],shapeprops->m_friction_scaling[1],shapeprops->m_friction_scaling[2]);
+
+
+//////////
+ //do Fh, do Rot Fh
+ ci.m_do_fh = shapeprops->m_do_fh;
+ ci.m_do_rot_fh = shapeprops->m_do_rot_fh ;
+ ci.m_fh_damping = smmaterial->m_fh_damping;
+ ci.m_fh_distance = smmaterial->m_fh_distance;
+ ci.m_fh_normal = smmaterial->m_fh_normal;
+ ci.m_fh_spring = smmaterial->m_fh_spring;
+ ci.m_radius = objprop->m_radius;
+
+
+ ///////////////////
+ ci.m_gamesoftFlag = objprop->m_gamesoftFlag;
+ ci.m_soft_linStiff = objprop->m_soft_linStiff;
+ ci.m_soft_angStiff = objprop->m_soft_angStiff; /* angular stiffness 0..1 */
+ ci.m_soft_volume= objprop->m_soft_volume; /* volume preservation 0..1 */
+
+ ci.m_soft_viterations= objprop->m_soft_viterations; /* Velocities solver iterations */
+ ci.m_soft_piterations= objprop->m_soft_piterations; /* Positions solver iterations */
+ ci.m_soft_diterations= objprop->m_soft_diterations; /* Drift solver iterations */
+ ci.m_soft_citerations= objprop->m_soft_citerations; /* Cluster solver iterations */
+
+ ci.m_soft_kSRHR_CL= objprop->m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
+ ci.m_soft_kSKHR_CL= objprop->m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
+ ci.m_soft_kSSHR_CL= objprop->m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
+ ci.m_soft_kSR_SPLT_CL= objprop->m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+
+ ci.m_soft_kSK_SPLT_CL= objprop->m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ ci.m_soft_kSS_SPLT_CL= objprop->m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ ci.m_soft_kVCF= objprop->m_soft_kVCF; /* Velocities correction factor (Baumgarte) */
+ ci.m_soft_kDP= objprop->m_soft_kDP; /* Damping coefficient [0,1] */
+
+ ci.m_soft_kDG= objprop->m_soft_kDG; /* Drag coefficient [0,+inf] */
+ ci.m_soft_kLF= objprop->m_soft_kLF; /* Lift coefficient [0,+inf] */
+ ci.m_soft_kPR= objprop->m_soft_kPR; /* Pressure coefficient [-inf,+inf] */
+ ci.m_soft_kVC= objprop->m_soft_kVC; /* Volume conversation coefficient [0,+inf] */
+
+ ci.m_soft_kDF= objprop->m_soft_kDF; /* Dynamic friction coefficient [0,1] */
+ ci.m_soft_kMT= objprop->m_soft_kMT; /* Pose matching coefficient [0,1] */
+ ci.m_soft_kCHR= objprop->m_soft_kCHR; /* Rigid contacts hardness [0,1] */
+ ci.m_soft_kKHR= objprop->m_soft_kKHR; /* Kinetic contacts hardness [0,1] */
+
+ ci.m_soft_kSHR= objprop->m_soft_kSHR; /* Soft contacts hardness [0,1] */
+ ci.m_soft_kAHR= objprop->m_soft_kAHR; /* Anchors hardness [0,1] */
+ ci.m_soft_collisionflags= objprop->m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
+ ci.m_soft_numclusteriterations= objprop->m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/
+
+ ////////////////////
+
ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter);
ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
+ ci.m_bSoft = objprop->m_softbody;
+ MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
+ ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
- //remember that we created a shape so that we can delete it when the scene is removed (bullet will not delete it)
- kxscene->AddShape(bm);
+ // shapeInfo is reference counted, decrement now as we don't use it anymore
+ if (shapeInfo)
+ shapeInfo->Release();
if (objprop->m_in_active_layer)
{
@@ -1137,10 +1098,16 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
gameobj->SetPhysicsController(physicscontroller,isbulletdyna);
physicscontroller->setNewClientInfo(gameobj->getClientInfo());
- btRigidBody* rbody = physicscontroller->GetRigidBody();
+ {
+ btRigidBody* rbody = physicscontroller->GetRigidBody();
+
+ if (rbody && objprop->m_disableSleeping)
+ rbody->setActivationState(DISABLE_DEACTIVATION);
+ }
+
+ CcdPhysicsController* parentCtrl = objprop->m_dynamic_parent ? (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController() : 0;
+ physicscontroller->setParentCtrl(parentCtrl);
- if (objprop->m_disableSleeping)
- rbody->setActivationState(DISABLE_DEACTIVATION);
//Now done directly in ci.m_collisionFlags so that it propagates to replica
//if (objprop->m_ghost)
@@ -1189,6 +1156,20 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
physicscontroller->SetObject(gameobj->GetSGNode());
+
+ ///test for soft bodies
+ if (objprop->m_softbody && physicscontroller)
+ {
+ btSoftBody* softBody = physicscontroller->GetSoftBody();
+ if (softBody && gameobj->GetMesh(0))//only the first mesh, if any
+ {
+ //should be a mesh then, so add a soft body deformer
+ KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),gameobj);
+ gameobj->SetDeformer(softbodyDeformer);
+
+ }
+ }
+
}
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
index fcd32d5f4fe..76459e46731 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.cpp
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -34,6 +34,7 @@
//#include <iostream>
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h"
+#include "KX_PythonInit.h" /* for config load/saving */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -125,6 +126,71 @@ bool KX_GameActuator::Update()
}
break;
}
+ case KX_GAME_SAVECFG:
+ {
+ if (m_ketsjiengine)
+ {
+ char mashal_path[512];
+ char *marshal_buffer = NULL;
+ int marshal_length;
+ FILE *fp = NULL;
+
+ pathGamePythonConfig(mashal_path);
+ marshal_length = saveGamePythonConfig(&marshal_buffer);
+
+ if (marshal_length && marshal_buffer) {
+ fp = fopen(mashal_path, "wb");
+ if (fp) {
+ if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) {
+ printf("Warning: could not write marshal data\n");
+ }
+ fclose(fp);
+ } else {
+ printf("Warning: could not open marshal file\n");
+ }
+ } else {
+ printf("Warning: could not create marshal buffer\n");
+ }
+ }
+ break;
+ }
+ case KX_GAME_LOADCFG:
+ {
+ if (m_ketsjiengine)
+ {
+ char mashal_path[512];
+ char *marshal_buffer;
+ int marshal_length;
+ FILE *fp = NULL;
+ int result;
+
+ pathGamePythonConfig(mashal_path);
+
+ fp = fopen(mashal_path, "rb");
+ if (fp) {
+ // obtain file size:
+ fseek (fp , 0 , SEEK_END);
+ marshal_length = ftell(fp);
+ rewind(fp);
+
+ marshal_buffer = (char*) malloc (sizeof(char)*marshal_length);
+
+ result = fread (marshal_buffer, 1, marshal_length, fp);
+
+ if (result == marshal_length) {
+ loadGamePythonConfig(marshal_buffer, marshal_length);
+ } else {
+ printf("warning: could not read all of '%s'\n", mashal_path);
+ }
+
+ free(marshal_buffer);
+ fclose(fp);
+ } else {
+ printf("warning: could not open '%s'\n", mashal_path);
+ }
+ }
+ break;
+ }
default:
; /* do nothing? this is an internal error !!! */
}
@@ -175,13 +241,13 @@ PyParentObject KX_GameActuator::Parents[] =
PyMethodDef KX_GameActuator::Methods[] =
{
- {"getFile", (PyCFunction) KX_GameActuator::sPyGetFile, METH_VARARGS, GetFile_doc},
- {"setFile", (PyCFunction) KX_GameActuator::sPySetFile, METH_VARARGS, SetFile_doc},
+ {"getFile", (PyCFunction) KX_GameActuator::sPyGetFile, METH_VARARGS, (PY_METHODCHAR)GetFile_doc},
+ {"setFile", (PyCFunction) KX_GameActuator::sPySetFile, METH_VARARGS, (PY_METHODCHAR)SetFile_doc},
{NULL,NULL} //Sentinel
};
/* getFile */
-char KX_GameActuator::GetFile_doc[] =
+const char KX_GameActuator::GetFile_doc[] =
"getFile()\n"
"get the name of the file to start.\n";
PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* kwds)
@@ -190,7 +256,7 @@ PyObject* KX_GameActuator::PyGetFile(PyObject* self, PyObject* args, PyObject* k
}
/* setFile */
-char KX_GameActuator::SetFile_doc[] =
+const char KX_GameActuator::SetFile_doc[] =
"setFile(name)\n"
"set the name of the file to start.\n";
PyObject* KX_GameActuator::PySetFile(PyObject* self, PyObject* args, PyObject* kwds)
diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h
index 8565dc46caa..bb3448995dc 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.h
+++ b/source/gameengine/Ketsji/KX_GameActuator.h
@@ -54,6 +54,8 @@ protected:
KX_GAME_START,
KX_GAME_RESTART,
KX_GAME_QUIT,
+ KX_GAME_SAVECFG,
+ KX_GAME_LOADCFG,
KX_GAME_MAX
};
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 700cc00e996..1b57b9acc1d 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -51,6 +51,7 @@ typedef unsigned long uint_ptr;
#include "KX_GameObject.h"
#include "RAS_MeshObject.h"
#include "KX_MeshProxy.h"
+#include "KX_PolyProxy.h"
#include <stdio.h> // printf
#include "SG_Controller.h"
#include "KX_IPhysicsController.h"
@@ -64,6 +65,8 @@ typedef unsigned long uint_ptr;
#include "SCA_IActuator.h"
#include "SCA_ISensor.h"
+#include "PyObjectPlus.h" /* python stuff */
+
// This file defines relationships between parents and children
// in the game engine.
@@ -78,12 +81,15 @@ KX_GameObject::KX_GameObject(
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_pPhysicsController1(NULL),
m_pPhysicsEnvironment(NULL),
+ m_xray(false),
m_pHitObject(NULL),
m_isDeformable(false)
{
@@ -99,8 +105,11 @@ KX_GameObject::KX_GameObject(
};
+
KX_GameObject::~KX_GameObject()
{
+ RemoveMeshes();
+
// is this delete somewhere ?
//if (m_sumoObj)
// delete m_sumoObj;
@@ -162,7 +171,6 @@ STR_String KX_GameObject::GetName()
void KX_GameObject::SetName(STR_String name)
{
m_name = name;
-
}; // Set the name of the value
@@ -227,11 +235,12 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
m_pPhysicsController1->SuspendDynamics(true);
}
// Set us to our new scale, position, and orientation
- scale1[0] = scale1[0]/scale2[0];
- scale1[1] = scale1[1]/scale2[1];
- scale1[2] = scale1[2]/scale2[2];
+ scale2[0] = 1.0/scale2[0];
+ scale2[1] = 1.0/scale2[1];
+ scale2[2] = 1.0/scale2[2];
+ scale1 = scale1 * scale2;
MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
- MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
+ MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
NodeSetLocalScale(scale1);
NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
@@ -283,11 +292,11 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica)
CValue* KX_GameObject::GetReplica()
{
KX_GameObject* replica = new KX_GameObject(*this);
-
+
// this will copy properties and so on...
CValue::AddDataToReplica(replica);
ProcessReplica(replica);
-
+
return replica;
}
@@ -353,24 +362,47 @@ double* KX_GameObject::GetOpenGLMatrix()
return fl;
}
+void KX_GameObject::AddMeshUser()
+{
+ for (size_t i=0;i<m_meshes.size();i++)
+ m_meshes[i]->AddMeshUser(this);
+
+ UpdateBuckets(false);
+}
+static void UpdateBuckets_recursive(SG_Node* node)
+{
+ NodeList& children = node->GetSGChildren();
-void KX_GameObject::Bucketize()
+ for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+ {
+ SG_Node* childnode = (*childit);
+ KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj != NULL) // This is a GameObject
+ clientgameobj->UpdateBuckets(0);
+
+ // if the childobj is NULL then this may be an inverse parent link
+ // so a non recursive search should still look down this node.
+ UpdateBuckets_recursive(childnode);
+ }
+}
+
+void KX_GameObject::UpdateBuckets( bool recursive )
{
double* fl = GetOpenGLMatrix();
for (size_t i=0;i<m_meshes.size();i++)
- m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
+ m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
+
+ if (recursive) {
+ UpdateBuckets_recursive(m_pSGNode);
+ }
}
-
-
void KX_GameObject::RemoveMeshes()
{
- double* fl = GetOpenGLMatrix();
-
for (size_t i=0;i<m_meshes.size();i++)
- m_meshes[i]->RemoveFromBuckets(fl, this);
+ m_meshes[i]->RemoveFromBuckets(this);
//note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
@@ -453,13 +485,14 @@ KX_GameObject::UpdateMaterialData(
)
{
int mesh = 0;
-
if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
- RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial();
+ list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
+
for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
{
- RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
- if(poly->GetFlag() & RAS_BLENDERMAT)
+ RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
+
+ if(poly->GetFlag() & RAS_BLENDERMAT )
{
KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly);
@@ -467,8 +500,7 @@ KX_GameObject::UpdateMaterialData(
{
m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
// if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
- if(!(poly->GetFlag() & RAS_BLENDERGLSL))
- SetObjectColor(rgba);
+ SetObjectColor(rgba);
}
else
{
@@ -494,72 +526,75 @@ KX_GameObject::GetVisible(
return m_bVisible;
}
+static void setVisible_recursive(SG_Node* node, bool v)
+{
+ NodeList& children = node->GetSGChildren();
+
+ for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+ {
+ SG_Node* childnode = (*childit);
+ KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj != NULL) // This is a GameObject
+ clientgameobj->SetVisible(v, 0);
+
+ // if the childobj is NULL then this may be an inverse parent link
+ // so a non recursive search should still look down this node.
+ setVisible_recursive(childnode, v);
+ }
+}
+
+
void
KX_GameObject::SetVisible(
- bool v
+ bool v,
+ bool recursive
)
{
m_bVisible = v;
+ if (recursive)
+ setVisible_recursive(m_pSGNode, v);
}
-void
-KX_GameObject::SetLayer(
- int l
+bool
+KX_GameObject::GetCulled(
+ void
)
{
- m_layer = l;
+ return m_bCulled;
}
-int
-KX_GameObject::GetLayer(
- void
+void
+KX_GameObject::SetCulled(
+ bool c
)
{
- return m_layer;
+ m_bCulled = c;
}
-// used by Python, and the actuatorshould _not_ be misused by the
-// scene!
-void
-KX_GameObject::MarkVisible(
- bool visible
+
+void
+KX_GameObject::SetLayer(
+ int l
)
{
- /* If explicit visibility settings are used, this is
- * determined on this level. Maybe change this to mesh level
- * later on? */
-
- double* fl = GetOpenGLMatrixPtr()->getPointer();
- for (size_t i=0;i<m_meshes.size();i++)
- {
- m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
- }
+ m_layer = l;
}
-
-// Always use the flag?
-void
-KX_GameObject::MarkVisible(
+int
+KX_GameObject::GetLayer(
void
)
{
- double* fl = GetOpenGLMatrixPtr()->getPointer();
- for (size_t i=0;i<m_meshes.size();i++)
- {
- m_meshes[i]->MarkVisible(fl,
- this,
- m_bVisible,
- m_bUseObjectColor,
- m_objectColor
- );
- }
+ return m_layer;
}
-
void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
{
- if (m_pPhysicsController1)
- m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
+ if (m_pPhysicsController1)
+ {
+ MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
+ m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0);
+ }
}
@@ -737,7 +772,14 @@ MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
return velocity;
}
-
+MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
+{
+ if (m_pPhysicsController1)
+ {
+ return m_pPhysicsController1->GetVelocity(point);
+ }
+ return MT_Vector3(0.0,0.0,0.0);
+}
// scenegraph node stuff
@@ -788,7 +830,17 @@ void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
{
if (GetSGNode())
+ {
GetSGNode()->RelativeScale(scale);
+ if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
+ {
+ // see note above
+ // we can use the local scale: it's the same thing for a root object
+ // and the world scale is not yet updated
+ MT_Vector3 newscale = GetSGNode()->GetLocalScale();
+ m_pPhysicsController1->setScaling(newscale);
+ }
+ }
}
void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
@@ -883,15 +935,18 @@ void KX_GameObject::Suspend()
PyMethodDef KX_GameObject::Methods[] = {
{"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
{"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
+ {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
{"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
{"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
+ {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
+ {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
{"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
{"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
{"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
{"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
{"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
{"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
- {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O},
+ {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
{"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
{"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
{"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
@@ -1032,18 +1087,23 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr)
int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method
{
- if (attr == "mass")
+ if (attr == "mass") {
+ PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only");
return 1;
+ }
- if (attr == "parent")
+ if (attr == "parent") {
+ PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()");
return 1;
+ }
if (PyInt_Check(value))
{
int val = PyInt_AsLong(value);
if (attr == "visible")
{
- SetVisible(val != 0);
+ SetVisible(val != 0, false);
+ UpdateBuckets(false);
return 0;
}
}
@@ -1102,7 +1162,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
}
return 1;
}
-
+ PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence");
return 1;
}
@@ -1146,9 +1206,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
}
-PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
{
// only can get the velocity if we have a physics object connected to us...
int local = 0;
@@ -1162,9 +1220,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self,
}
}
-PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
{
int local = 0;
PyObject* pyvect;
@@ -1179,17 +1235,43 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self,
return NULL;
}
-PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
+PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
{
- int visible = PyInt_AsLong(value);
-
- if (visible==-1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
+ // only can get the velocity if we have a physics object connected to us...
+ int local = 0;
+ if (PyArg_ParseTuple(args,"|i",&local))
+ {
+ return PyObjectFrom(GetAngularVelocity((local!=0)));
+ }
+ else
+ {
return NULL;
}
+}
+
+PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
+{
+ int local = 0;
+ PyObject* pyvect;
+
+ if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
+ MT_Vector3 velocity;
+ if (PyVecTo(pyvect, velocity)) {
+ setAngularVelocity(velocity, (local!=0));
+ Py_RETURN_NONE;
+ }
+ }
+ return NULL;
+}
+
+PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
+{
+ int visible, recursive = 0;
+ if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive))
+ return NULL;
- MarkVisible(visible!=0);
- m_bVisible = (visible!=0);
+ SetVisible(visible ? true:false, recursive ? true:false);
+ UpdateBuckets(recursive ? true:false);
Py_RETURN_NONE;
}
@@ -1228,9 +1310,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
-PyObject* KX_GameObject::PyGetVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
{
// only can get the velocity if we have a physics object connected to us...
MT_Vector3 velocity(0.0,0.0,0.0);
@@ -1362,9 +1442,7 @@ PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
return list;
}
-PyObject* KX_GameObject::PyGetMesh(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
{
int mesh = 0;
@@ -1404,9 +1482,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
-PyObject* KX_GameObject::PyApplyImpulse(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
{
PyObject* pyattach;
PyObject* pyimpulse;
@@ -1477,9 +1553,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
return NULL;
}
-PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
{
PyObject* pyvect;
int axis = 2; //z axis is the default
@@ -1524,6 +1598,19 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
return NULL;
}
+PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value)
+{
+ MT_Point3 pos;
+ if (PyVecTo(value, pos))
+ {
+ NodeSetWorldPosition(pos);
+ NodeUpdateGS(0.f,true);
+ Py_RETURN_NONE;
+ }
+
+ return NULL;
+}
+
PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
{
KX_IPhysicsController* ctrl = GetPhysicsController();
@@ -1609,25 +1696,45 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo,
return returnValue;
}
-bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
{
+ KX_GameObject* hitKXObj = client->m_gameobject;
+
+ // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
+ // if not, all objects were tested and the front one may not be the correct one.
+ if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+ {
+ m_pHitObject = hitKXObj;
+ return true;
+ }
+ // return true to stop RayCast::RayTest from looping, the above test was decisive
+ // We would want to loop only if we want to get more than one hit point
+ return true;
+}
+/* this function is used to pre-filter the object before casting the ray on them.
+ This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
+{
KX_GameObject* hitKXObj = client->m_gameobject;
if (client->m_type > KX_ClientObjectInfo::ACTOR)
{
- // false hit
+ // Unknown type of object, skip it.
+ // Should not occur as the sensor objects are filtered in RayTest()
+ printf("Invalid client type %d found in ray casting\n", client->m_type);
return false;
}
-
- if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
+
+ // if X-Ray option is selected, skip object that don't match the criteria as we see through them
+ // if not, test all objects because we don't know yet which one will be on front
+ if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
{
- m_pHitObject = hitKXObj;
return true;
}
-
+ // skip the object
return false;
-
}
KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
@@ -1667,8 +1774,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
toPoint = fromPoint + (dist) * toDir;
}
- MT_Point3 resultPoint;
- MT_Vector3 resultNormal;
PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
KX_IPhysicsController *spc = GetPhysicsController();
KX_GameObject *parent = GetParent();
@@ -1682,7 +1787,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
m_testPropName = propName;
else
m_testPropName.SetLength(0);
- KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
+ KX_RayCast::Callback<KX_GameObject> callback(this,spc);
+ KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
if (m_pHitObject)
{
@@ -1693,13 +1799,24 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
}
KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
- "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n"
-" prop = property name that object must have; can be omitted => detect any object\n"
-" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
+ "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n"
+ " If no hit, return (None,None,None) or (None,None,None,None).\n"
+" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
" from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
" Can be None or omitted => start from self object center\n"
-" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
-"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
+" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
+" prop = property name that object must have; can be omitted => detect any object\n"
+" face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
+" xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
+" poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
+" which can be None if hit object has no mesh or if there is no hit\n"
+" If 0 or omitted, return value is a 3-tuple\n"
+"Note: The object on which you call this method matters: the ray will ignore it.\n"
+" prop and xray option interact as follow:\n"
+" prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
+" prop off, xray on : idem\n"
+" prop on, xray off: return closest hit if it matches prop, no hit otherwise\n"
+" prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n")
{
MT_Point3 toPoint;
MT_Point3 fromPoint;
@@ -1708,8 +1825,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
float dist = 0.0f;
char *propName = NULL;
KX_GameObject *other;
+ int face=0, xray=0, poly=0;
- if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
+ if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
return NULL; // Python sets a simple error
}
@@ -1755,8 +1873,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
}
- MT_Point3 resultPoint;
- MT_Vector3 resultNormal;
PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
KX_IPhysicsController *spc = GetPhysicsController();
KX_GameObject *parent = GetParent();
@@ -1770,20 +1886,41 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
m_testPropName = propName;
else
m_testPropName.SetLength(0);
- KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
+ m_xray = xray;
+ // to get the hit results
+ KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
+ KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
- if (m_pHitObject)
+ if (m_pHitObject)
{
- PyObject* returnValue = PyTuple_New(3);
+ PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
if (returnValue) { // unlikely this would ever fail, if it does python sets an error
PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
- PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
- PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
+ PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
+ PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
+ if (poly)
+ {
+ if (callback.m_hitMesh)
+ {
+ // if this field is set, then we can trust that m_hitPolygon is a valid polygon
+ RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
+ KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly);
+ PyTuple_SET_ITEM(returnValue, 3, polyproxy);
+ }
+ else
+ {
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(returnValue, 3, Py_None);
+ }
+ }
}
return returnValue;
}
- return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
- //Py_RETURN_NONE;
+ // no hit
+ if (poly)
+ return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
+ else
+ return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
}
/* ---------------------------------------------------------------------
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index a7ac2d75a93..472d31362dd 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -54,6 +54,7 @@
//Forward declarations.
struct KX_ClientObjectInfo;
+class KX_RayCast;
class RAS_MeshObject;
class KX_IPhysicsController;
class PHY_IPhysicsEnvironment;
@@ -74,20 +75,23 @@ protected:
int m_layer;
std::vector<RAS_MeshObject*> m_meshes;
struct Object* m_pBlenderObject;
+ struct Object* m_pBlenderGroupObject;
bool m_bSuspendDynamics;
bool m_bUseObjectColor;
bool m_bIsNegativeScaling;
MT_Vector4 m_objectColor;
- // Is this object set to be visible? Only useful for the
- // visibility subsystem right now.
- bool m_bVisible;
+ // visible = user setting
+ // culled = while rendering, depending on camera
+ bool m_bVisible;
+ bool m_bCulled;
KX_IPhysicsController* m_pPhysicsController1;
// used for ray casting
PHY_IPhysicsEnvironment* m_pPhysicsEnvironment;
STR_String m_testPropName;
+ bool m_xray;
KX_GameObject* m_pHitObject;
SG_Node* m_pSGNode;
@@ -260,6 +264,15 @@ public:
bool local=false
);
+ /**
+ * Return the linear velocity of a given point in world coordinate
+ * but relative to center of object ([0,0,0]=center of object)
+ */
+ MT_Vector3
+ GetVelocity(
+ const MT_Point3& position
+ );
+
/**
* Return the mass of the object
*/
@@ -328,6 +341,14 @@ public:
m_pPhysicsController1 = physicscontroller;
}
+ virtual class RAS_Deformer* GetDeformer()
+ {
+ return 0;
+ }
+ virtual void SetDeformer(class RAS_Deformer* deformer)
+ {
+
+ }
/**
* @section Coordinate system manipulation functions
@@ -393,6 +414,16 @@ public:
{
m_pBlenderObject = obj;
}
+
+ struct Object* GetBlenderGroupObject( )
+ {
+ return m_pBlenderGroupObject;
+ }
+
+ void SetBlenderGroupObject( struct Object* obj)
+ {
+ m_pBlenderGroupObject = obj;
+ }
bool IsDupliGroup()
{
@@ -428,7 +459,8 @@ public:
return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent());
}
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo* client);
/**
@@ -535,18 +567,23 @@ public:
/**
* @section Mesh accessor functions.
*/
+
+ /**
+ * Update buckets to indicate that there is a new
+ * user of this object's meshes.
+ */
+ void
+ AddMeshUser(
+ );
/**
- * Run through the meshes associated with this
- * object and bucketize them. See RAS_Mesh for
- * more details on this function. Interesting to
- * note that polygon bucketizing seems to happen on a per
- * object basis. Which may explain why there is such
- * a big performance gain when all static objects
- * are joined into 1.
+ * Update buckets with data about the mesh after
+ * creating or duplicating the object, changing
+ * visibility, object color, .. .
*/
void
- Bucketize(
+ UpdateBuckets(
+ bool recursive
);
/**
@@ -607,38 +644,38 @@ public:
ResetDebugColor(
);
- /**
- * Set the visibility of the meshes associated with this
- * object.
+ /**
+ * Was this object marked visible? (only for the explicit
+ * visibility system).
*/
- void
- MarkVisible(
- bool visible
+ bool
+ GetVisible(
+ void
);
- /**
- * Set the visibility according to the visibility flag.
+ /**
+ * Set visibility flag of this object
*/
- void
- MarkVisible(
void
+ SetVisible(
+ bool b,
+ bool recursive
);
/**
- * Was this object marked visible? (only for the ewxplicit
- * visibility system).
+ * Was this object culled?
*/
bool
- GetVisible(
+ GetCulled(
void
);
/**
- * Set visibility flag of this object
+ * Set culled flag of this object
*/
void
- SetVisible(
- bool b
+ SetCulled(
+ bool c
);
/**
@@ -667,6 +704,14 @@ public:
) { return m_bIsNegativeScaling; }
/**
+ * Is this a light?
+ */
+ virtual bool
+ IsLight(
+ void
+ ) { return false; }
+
+ /**
* @section Logic bubbling methods.
*/
@@ -726,31 +771,34 @@ public:
KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition);
KX_PYMETHOD_O(KX_GameObject,SetPosition);
- KX_PYMETHOD(KX_GameObject,GetLinearVelocity);
- KX_PYMETHOD(KX_GameObject,SetLinearVelocity);
- KX_PYMETHOD(KX_GameObject,GetVelocity);
+ KX_PYMETHOD_O(KX_GameObject,SetWorldPosition);
+ KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);
KX_PYMETHOD_NOARGS(KX_GameObject,GetMass);
KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);
KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation);
KX_PYMETHOD_O(KX_GameObject,SetOrientation);
KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible);
- KX_PYMETHOD_O(KX_GameObject,SetVisible);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible);
KX_PYMETHOD_NOARGS(KX_GameObject,GetState);
KX_PYMETHOD_O(KX_GameObject,SetState);
- KX_PYMETHOD(KX_GameObject,AlignAxisToVect);
+ KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect);
KX_PYMETHOD_O(KX_GameObject,GetAxisVect);
KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics);
KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody);
KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody);
- KX_PYMETHOD(KX_GameObject,ApplyImpulse);
+ KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse);
KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin);
KX_PYMETHOD_NOARGS(KX_GameObject,GetParent);
KX_PYMETHOD_O(KX_GameObject,SetParent);
KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent);
KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren);
KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive);
- KX_PYMETHOD(KX_GameObject,GetMesh);
+ KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh);
KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId);
KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames);
KX_PYMETHOD_NOARGS(KX_GameObject,EndObject);
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
index d3aa924665e..67d54cf0b0b 100644
--- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
@@ -59,7 +59,9 @@ KX_IpoSGController::KX_IpoSGController()
m_ipo_local(false),
m_modified(true),
m_ipo_start_initialized(false),
- m_ipotime(1.0)
+ m_ipotime(1.0),
+ m_ipo_start_euler(0.0,0.0,0.0),
+ m_ipo_euler_initialized(false)
{
m_game_object = NULL;
for (int i=0; i < KX_MAX_IPO_CHANNELS; i++)
@@ -136,6 +138,11 @@ bool KX_IpoSGController::Update(double currentTime)
m_ipo_start_orient = ob->GetLocalOrientation();
m_ipo_start_scale = ob->GetLocalScale();
m_ipo_start_initialized = true;
+ if (!m_ipo_euler_initialized) {
+ // do it only once to avoid angle discontinuities
+ m_ipo_start_orient.getEuler(m_ipo_start_euler[0], m_ipo_start_euler[1], m_ipo_start_euler[2]);
+ m_ipo_euler_initialized = true;
+ }
}
//modifies position?
@@ -143,7 +150,7 @@ bool KX_IpoSGController::Update(double currentTime)
{
if (m_ipo_as_force == true)
{
- if (m_game_object && ob)
+ if (m_game_object && ob && m_game_object->GetPhysicsController())
{
m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ?
ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
@@ -199,51 +206,87 @@ bool KX_IpoSGController::Update(double currentTime)
ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false);
}
- } else {
- double yaw=0, pitch=0, roll=0; //final Euler angles
- double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders
- if (!m_ipo_add)
- ob->GetLocalOrientation().getEuler(yaw, pitch, roll);
+ } else if (m_ipo_add) {
+ if (m_ipo_start_initialized) {
+ double yaw=0, pitch=0, roll=0; //delta Euler angles
- //RotX and dRotX
- if (m_ipo_channels_active[OB_ROT_X]) {
- yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] );
- }
- else if (m_ipo_channels_active[OB_DROT_X] && m_ipo_start_initialized) {
- if (!m_ipo_add)
- m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
- yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0];
- }
+ //RotX and dRotX
+ if (m_ipo_channels_active[OB_ROT_X])
+ yaw += m_ipo_xform.GetEulerAngles()[0];
+ if (m_ipo_channels_active[OB_DROT_X])
+ yaw += m_ipo_xform.GetDeltaEulerAngles()[0];
+
+ //RotY dRotY
+ if (m_ipo_channels_active[OB_ROT_Y])
+ pitch += m_ipo_xform.GetEulerAngles()[1];
+ if (m_ipo_channels_active[OB_DROT_Y])
+ pitch += m_ipo_xform.GetDeltaEulerAngles()[1];
+
+ //RotZ and dRotZ
+ if (m_ipo_channels_active[OB_ROT_Z])
+ roll += m_ipo_xform.GetEulerAngles()[2];
+ if (m_ipo_channels_active[OB_DROT_Z])
+ roll += m_ipo_xform.GetDeltaEulerAngles()[2];
- //RotY dRotY
- if (m_ipo_channels_active[OB_ROT_Y]) {
- pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] );
- }
- else if (m_ipo_channels_active[OB_DROT_Y] && m_ipo_start_initialized) {
- if (!m_ipo_add)
- m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
- pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1];
- }
-
- //RotZ and dRotZ
- if (m_ipo_channels_active[OB_ROT_Z]) {
- roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] );
- }
- else if (m_ipo_channels_active[OB_DROT_Z] && m_ipo_start_initialized) {
- if (!m_ipo_add)
- m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
- roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2];
- }
- if (m_ipo_add) {
MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll));
if (m_ipo_local)
rotation = m_ipo_start_orient * rotation;
else
rotation = rotation * m_ipo_start_orient;
ob->SetLocalOrientation(rotation);
- } else {
+ }
+ } else if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z]) {
+ if (m_ipo_euler_initialized) {
+ // assume all channel absolute
+ // All 3 channels should be specified but if they are not, we will take
+ // the value at the start of the game to avoid angle sign reversal
+ double yaw=m_ipo_start_euler[0], pitch=m_ipo_start_euler[1], roll=m_ipo_start_euler[2];
+
+ //RotX and dRotX
+ if (m_ipo_channels_active[OB_ROT_X]) {
+ yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] );
+ }
+ else if (m_ipo_channels_active[OB_DROT_X]) {
+ yaw += m_ipo_xform.GetDeltaEulerAngles()[0];
+ }
+
+ //RotY dRotY
+ if (m_ipo_channels_active[OB_ROT_Y]) {
+ pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] );
+ }
+ else if (m_ipo_channels_active[OB_DROT_Y]) {
+ pitch += m_ipo_xform.GetDeltaEulerAngles()[1];
+ }
+
+ //RotZ and dRotZ
+ if (m_ipo_channels_active[OB_ROT_Z]) {
+ roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] );
+ }
+ else if (m_ipo_channels_active[OB_DROT_Z]) {
+ roll += m_ipo_xform.GetDeltaEulerAngles()[2];
+ }
ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll));
}
+ } else if (m_ipo_start_initialized) {
+ // only DROT, treat as Add
+ double yaw=0, pitch=0, roll=0; //delta Euler angles
+
+ //dRotX
+ if (m_ipo_channels_active[OB_DROT_X])
+ yaw = m_ipo_xform.GetDeltaEulerAngles()[0];
+
+ //dRotY
+ if (m_ipo_channels_active[OB_DROT_Y])
+ pitch = m_ipo_xform.GetDeltaEulerAngles()[1];
+
+ //dRotZ
+ if (m_ipo_channels_active[OB_DROT_Z])
+ roll = m_ipo_xform.GetDeltaEulerAngles()[2];
+
+ // dRot are always local
+ MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll));
+ rotation = m_ipo_start_orient * rotation;
+ ob->SetLocalOrientation(rotation);
}
}
//modifies scale?
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h
index 0bd8980f11c..031b74294ce 100644
--- a/source/gameengine/Ketsji/KX_IPO_SGController.h
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.h
@@ -72,6 +72,12 @@ class KX_IpoSGController : public SG_Controller
/** if IPO initial position has been set for local normal IPO */
bool m_ipo_start_initialized;
+ /** Euler angles at the start of the game, needed for incomplete ROT Ipo curves */
+ class MT_Vector3 m_ipo_start_euler;
+
+ /** true is m_ipo_start_euler has been initialized */
+ bool m_ipo_euler_initialized;
+
/** A reference to the original game object. */
class KX_GameObject* m_game_object;
diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h
index ecfdb8c4275..4ea283e9f98 100644
--- a/source/gameengine/Ketsji/KX_IPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_IPhysicsController.h
@@ -88,7 +88,11 @@ public:
m_bDyna = isDynamic;
}
+ bool IsDyna(void) {
+ return m_bDyna;
+ }
+ virtual MT_Scalar GetRadius()=0;
virtual void SetSumoTransform(bool nondynaonly)=0;
// todo: remove next line !
virtual void SetSimulatedTime(double time)=0;
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index f069048cd3d..3709fa8c784 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -32,6 +32,8 @@
#include "STR_String.h"
#include "KX_Python.h"
+struct Scene;
+
class KX_ISceneConverter
{
@@ -77,6 +79,8 @@ public:
// use blender glsl materials
virtual void SetGLSLMaterials(bool val) =0;
virtual bool GetGLSLMaterials()=0;
+
+ virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0;
};
#endif //__KX_ISCENECONVERTER_H
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index a203ea6a6ff..f5e17118ffb 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -37,6 +37,7 @@
#include "KX_IpoActuator.h"
#include "KX_GameObject.h"
+#include "FloatValue.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -62,6 +63,7 @@ STR_String KX_IpoActuator::S_KX_ACT_IPO_FROM_PROP_STRING = "FromProp";
KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
const STR_String& propname,
+ const STR_String& framePropname,
float starttime,
float endtime,
bool recurse,
@@ -78,6 +80,7 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
m_localtime(starttime),
m_direction(1),
m_propname(propname),
+ m_framepropname(framePropname),
m_ipo_as_force(ipo_as_force),
m_ipo_add(ipo_add),
m_ipo_local(ipo_local),
@@ -130,7 +133,6 @@ void KX_IpoActuator::SetStartTime(float curtime)
{
float direction = m_startframe < m_endframe ? 1.0f : -1.0f;
- curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
if (m_direction > 0)
m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate();
else
@@ -139,7 +141,7 @@ void KX_IpoActuator::SetStartTime(float curtime)
void KX_IpoActuator::SetLocalTime(float curtime)
{
- float delta_time = ((curtime - m_starttime) - KX_KetsjiEngine::GetSuspendedDelta())*KX_KetsjiEngine::GetAnimFrameRate();
+ float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
// negative delta_time is caused by floating point inaccuracy
// perhaps the inaccuracy could be reduced a bit
@@ -165,6 +167,8 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
int numevents = 0;
bool bIpoStart = false;
+ curtime -= KX_KetsjiEngine::GetSuspendedDelta();
+
if (frame)
{
numevents = m_events.size();
@@ -180,7 +184,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
if (m_starttime < -2.0f*start_smaller_then_end*(m_endframe - m_startframe))
{
// start for all Ipo, initial start for LOOP_STOP
- m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
+ m_starttime = curtime;
m_bIpoPlaying = true;
bIpoStart = true;
}
@@ -355,7 +359,20 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
default:
result = false;
}
-
+
+ /* 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);
+ }
+ newval->Release();
+ }
+
if (!result)
{
if (m_type != KX_ACT_IPO_LOOPSTOP)
@@ -423,34 +440,20 @@ PyParentObject KX_IpoActuator::Parents[] = {
};
PyMethodDef KX_IpoActuator::Methods[] = {
- {"set", (PyCFunction) KX_IpoActuator::sPySet,
- METH_VARARGS, Set_doc},
- {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty,
- METH_VARARGS, SetProperty_doc},
- {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart,
- METH_VARARGS, SetStart_doc},
- {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart,
- METH_NOARGS, GetStart_doc},
- {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd,
- METH_VARARGS, SetEnd_doc},
- {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd,
- METH_NOARGS, GetEnd_doc},
- {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce,
- METH_VARARGS, SetIpoAsForce_doc},
- {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce,
- METH_NOARGS, GetIpoAsForce_doc},
- {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd,
- METH_VARARGS, SetIpoAdd_doc},
- {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd,
- METH_NOARGS, GetIpoAdd_doc},
- {"setType", (PyCFunction) KX_IpoActuator::sPySetType,
- METH_VARARGS, SetType_doc},
- {"getType", (PyCFunction) KX_IpoActuator::sPyGetType,
- METH_NOARGS, GetType_doc},
- {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal,
- METH_VARARGS, SetForceIpoActsLocal_doc},
- {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal,
- METH_NOARGS, GetForceIpoActsLocal_doc},
+ {"set", (PyCFunction) KX_IpoActuator::sPySet, METH_VARARGS, (PY_METHODCHAR)Set_doc},
+ {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc},
+ {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, METH_NOARGS, (PY_METHODCHAR)GetStart_doc},
+ {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd, METH_VARARGS, (PY_METHODCHAR)SetEnd_doc},
+ {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd, METH_NOARGS, (PY_METHODCHAR)GetEnd_doc},
+ {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce, METH_VARARGS, (PY_METHODCHAR)SetIpoAsForce_doc},
+ {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, METH_NOARGS, (PY_METHODCHAR)GetIpoAsForce_doc},
+ {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd, METH_VARARGS, (PY_METHODCHAR)SetIpoAdd_doc},
+ {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd, METH_NOARGS, (PY_METHODCHAR)GetIpoAdd_doc},
+ {"setType", (PyCFunction) KX_IpoActuator::sPySetType, METH_VARARGS, (PY_METHODCHAR)SetType_doc},
+ {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, METH_NOARGS, (PY_METHODCHAR)GetType_doc},
+ {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal, METH_VARARGS, (PY_METHODCHAR)SetForceIpoActsLocal_doc},
+ {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal, METH_NOARGS, (PY_METHODCHAR)GetForceIpoActsLocal_doc},
{NULL,NULL} //Sentinel
};
@@ -461,7 +464,7 @@ PyObject* KX_IpoActuator::_getattr(const STR_String& attr) {
/* set --------------------------------------------------------------------- */
-char KX_IpoActuator::Set_doc[] =
+const char KX_IpoActuator::Set_doc[] =
"set(type, startframe, endframe, mode?)\n"
"\t - type: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
"\t - startframe: first frame to use (int)\n"
@@ -504,7 +507,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self,
}
/* set property ----------------------------------------------------------- */
-char KX_IpoActuator::SetProperty_doc[] =
+const char KX_IpoActuator::SetProperty_doc[] =
"setProperty(propname)\n"
"\t - propname: name of the property (string)\n"
"\tSet the property to be used in FromProp mode.\n";
@@ -524,7 +527,7 @@ PyObject* KX_IpoActuator::PySetProperty(PyObject* self,
}
/* 4. setStart: */
-char KX_IpoActuator::SetStart_doc[] =
+const char KX_IpoActuator::SetStart_doc[] =
"setStart(frame)\n"
"\t - frame: first frame to use (int)\n"
"\tSet the frame from which the ipo starts playing.\n";
@@ -541,7 +544,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self,
Py_Return;
}
/* 5. getStart: */
-char KX_IpoActuator::GetStart_doc[] =
+const char KX_IpoActuator::GetStart_doc[] =
"getStart()\n"
"\tReturns the frame from which the ipo starts playing.\n";
PyObject* KX_IpoActuator::PyGetStart(PyObject* self) {
@@ -549,7 +552,7 @@ PyObject* KX_IpoActuator::PyGetStart(PyObject* self) {
}
/* 6. setEnd: */
-char KX_IpoActuator::SetEnd_doc[] =
+const char KX_IpoActuator::SetEnd_doc[] =
"setEnd(frame)\n"
"\t - frame: last frame to use (int)\n"
"\tSet the frame at which the ipo stops playing.\n";
@@ -566,7 +569,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self,
Py_Return;
}
/* 7. getEnd: */
-char KX_IpoActuator::GetEnd_doc[] =
+const char KX_IpoActuator::GetEnd_doc[] =
"getEnd()\n"
"\tReturns the frame at which the ipo stops playing.\n";
PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) {
@@ -574,7 +577,7 @@ PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) {
}
/* 6. setIpoAsForce: */
-char KX_IpoActuator::SetIpoAsForce_doc[] =
+const char KX_IpoActuator::SetIpoAsForce_doc[] =
"setIpoAsForce(force?)\n"
"\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)\n"
"\tSet whether to interpret the ipo as a force rather than a displacement.\n";
@@ -594,7 +597,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
Py_Return;
}
/* 7. getIpoAsForce: */
-char KX_IpoActuator::GetIpoAsForce_doc[] =
+const char KX_IpoActuator::GetIpoAsForce_doc[] =
"getIpoAsForce()\n"
"\tReturns whether to interpret the ipo as a force rather than a displacement.\n";
PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) {
@@ -602,7 +605,7 @@ PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) {
}
/* 6. setIpoAsForce: */
-char KX_IpoActuator::SetIpoAdd_doc[] =
+const char KX_IpoActuator::SetIpoAdd_doc[] =
"setIpoAdd(add?)\n"
"\t - add? : add flag (KX_TRUE, KX_FALSE)\n"
"\tSet whether to interpret the ipo as additive rather than absolute.\n";
@@ -622,7 +625,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self,
Py_Return;
}
/* 7. getIpoAsForce: */
-char KX_IpoActuator::GetIpoAdd_doc[] =
+const char KX_IpoActuator::GetIpoAdd_doc[] =
"getIpoAsAdd()\n"
"\tReturns whether to interpret the ipo as additive rather than absolute.\n";
PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) {
@@ -630,7 +633,7 @@ PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) {
}
/* 8. setType: */
-char KX_IpoActuator::SetType_doc[] =
+const char KX_IpoActuator::SetType_doc[] =
"setType(mode)\n"
"\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
"\tSet the operation mode of the actuator.\n";
@@ -651,7 +654,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self,
Py_Return;
}
/* 9. getType: */
-char KX_IpoActuator::GetType_doc[] =
+const char KX_IpoActuator::GetType_doc[] =
"getType()\n"
"\tReturns the operation mode of the actuator.\n";
PyObject* KX_IpoActuator::PyGetType(PyObject* self) {
@@ -659,7 +662,7 @@ PyObject* KX_IpoActuator::PyGetType(PyObject* self) {
}
/* 10. setForceIpoActsLocal: */
-char KX_IpoActuator::SetForceIpoActsLocal_doc[] =
+const char KX_IpoActuator::SetForceIpoActsLocal_doc[] =
"setForceIpoActsLocal(local?)\n"
"\t - local? : Apply the ipo-as-force in the object's local\n"
"\t coordinates? (KX_TRUE, KX_FALSE)\n"
@@ -679,7 +682,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self,
Py_Return;
}
/* 11. getForceIpoActsLocal: */
-char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
+const char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
"getForceIpoActsLocal()\n"
"\tReturn whether to apply the force in the object's local\n"
"\tcoordinates rather than the world global coordinates.\n";
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
index d6f52f8d59d..8e5baed0530 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.h
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -72,6 +72,9 @@ protected:
/** Name of the property (only used in from_prop mode). */
STR_String m_propname;
+ /** Name of the property where we write the current frame number */
+ STR_String m_framepropname;
+
/** Interpret the ipo as a force? */
bool m_ipo_as_force;
@@ -111,6 +114,7 @@ public:
KX_IpoActuator(SCA_IObject* gameobj,
const STR_String& propname,
+ const STR_String& framePropname,
float starttime,
float endtime,
bool recurse,
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 1d6cc975ab5..b1ab8e3e7de 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -96,6 +96,7 @@ double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
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;
/**
@@ -134,6 +135,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_overrideCam(false),
m_overrideCamUseOrtho(false),
+ m_overrideCamNear(0.0),
+ m_overrideCamFar(0.0),
m_stereo(false),
m_curreye(0),
@@ -275,30 +278,73 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo)
}
-bool KX_KetsjiEngine::BeginFrame()
+void KX_KetsjiEngine::ClearFrame()
{
- bool result = false;
+ // clear unless we're drawing overlapping stereo
+ if(m_rasterizer->InterlacedStereo() &&
+ m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE)
+ return;
- RAS_Rect vp;
- KX_Scene* firstscene = *m_scenes.begin();
- const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
+ // clear the viewports with the background color of the first scene
+ bool doclear = false;
+ KX_SceneList::iterator sceneit;
+ RAS_Rect clearvp, area, viewport;
- // set the area used for rendering
- m_rasterizer->SetRenderArea();
+ for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++)
+ {
+ KX_Scene* scene = *sceneit;
+ //const RAS_FrameSettings &framesettings = scene->GetFramingType();
+ list<class KX_Camera*>* cameras = scene->GetCameras();
+
+ list<KX_Camera*>::iterator it;
+ for(it = cameras->begin(); it != cameras->end(); it++)
+ {
+ GetSceneViewport(scene, (*it), area, viewport);
+
+ if(!doclear) {
+ clearvp = viewport;
+ doclear = true;
+ }
+ else {
+ if(viewport.GetLeft() < clearvp.GetLeft())
+ clearvp.SetLeft(viewport.GetLeft());
+ if(viewport.GetBottom() < clearvp.GetBottom())
+ clearvp.SetBottom(viewport.GetBottom());
+ if(viewport.GetRight() > clearvp.GetRight())
+ clearvp.SetRight(viewport.GetRight());
+ if(viewport.GetTop() > clearvp.GetTop())
+ clearvp.SetTop(viewport.GetTop());
+
+ }
+ }
+ }
+
+ if(doclear) {
+ KX_Scene* firstscene = *m_scenes.begin();
+ SetBackGround(firstscene->GetWorldInfo());
+
+ m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
+ clearvp.GetRight(), clearvp.GetTop());
+ m_rasterizer->ClearColorBuffer();
+ }
+}
- RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp);
+bool KX_KetsjiEngine::BeginFrame()
+{
+ // set the area used for rendering (stereo can assign only a subset)
+ m_rasterizer->SetRenderArea();
if (m_canvas->BeginDraw())
{
- result = true;
+ ClearFrame();
- m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop());
- SetBackGround( firstscene->GetWorldInfo() );
- m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds());
- m_rendertools->BeginFrame( m_rasterizer);
+ m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds());
+ m_rendertools->BeginFrame(m_rasterizer);
+
+ return true;
}
- return result;
+ return false;
}
@@ -310,6 +356,12 @@ void KX_KetsjiEngine::EndFrame()
{
RenderDebugProperties();
}
+
+ m_average_framerate = m_logger->GetAverage();
+ if (m_average_framerate < 1e-6)
+ m_average_framerate = 1e-6;
+ m_average_framerate = 1.0/m_average_framerate;
+
// Go to next profiling measurement, time spend after this call is shown in the next frame.
m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
@@ -321,8 +373,6 @@ void KX_KetsjiEngine::EndFrame()
m_canvas->EndDraw();
-
-
}
//#include "PIL_time.h"
@@ -601,7 +651,7 @@ void KX_KetsjiEngine::Render()
);
}
// clear the -whole- viewport
- m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
+ m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
}
m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
@@ -630,9 +680,6 @@ void KX_KetsjiEngine::Render()
m_rendertools->SetAuxilaryClientInfo(scene);
- //Initialize scene viewport.
- SetupRenderFrame(scene, cam);
-
// do the rendering
RenderFrame(scene, cam);
}
@@ -650,9 +697,6 @@ void KX_KetsjiEngine::Render()
m_rendertools->SetAuxilaryClientInfo(scene);
- //Initialize scene viewport.
- SetupRenderFrame(scene, (*it));
-
// do the rendering
RenderFrame(scene, (*it));
}
@@ -685,10 +729,6 @@ void KX_KetsjiEngine::Render()
//pass the scene, for picking and raycasting (shadows)
m_rendertools->SetAuxilaryClientInfo(scene);
- //Initialize scene viewport.
- //SetupRenderFrame(scene);
- SetupRenderFrame(scene, cam);
-
// do the rendering
//RenderFrame(scene);
RenderFrame(scene, cam);
@@ -848,8 +888,13 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
m_overrideCamViewMat = mat;
}
-
-void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam)
+void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
+{
+ m_overrideCamNear = near;
+ m_overrideCamFar = far;
+}
+
+void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport)
{
// In this function we make sure the rasterizer settings are upto
// date. We compute the viewport so that logic
@@ -857,17 +902,26 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam)
// Note we postpone computation of the projection matrix
// so that we are using the latest camera position.
+ if (cam->GetViewport()) {
+ RAS_Rect userviewport;
- RAS_Rect viewport;
+ userviewport.SetLeft(cam->GetViewportLeft());
+ userviewport.SetBottom(cam->GetViewportBottom());
+ userviewport.SetRight(cam->GetViewportRight());
+ userviewport.SetTop(cam->GetViewportTop());
- if (!cam)
- return;
+ // Don't do bars on user specified viewport
+ RAS_FrameSettings settings = scene->GetFramingType();
+ if(settings.FrameType() == RAS_FrameSettings::e_frame_bars)
+ settings.SetFrameType(RAS_FrameSettings::e_frame_extend);
- if (cam->GetViewport()) {
- viewport.SetLeft(cam->GetViewportLeft());
- viewport.SetBottom(cam->GetViewportBottom());
- viewport.SetRight(cam->GetViewportRight());
- viewport.SetTop(cam->GetViewportTop());
+ RAS_FramingManager::ComputeViewport(
+ scene->GetFramingType(),
+ userviewport,
+ viewport
+ );
+
+ area = userviewport;
}
else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) {
RAS_FramingManager::ComputeViewport(
@@ -875,33 +929,32 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam)
m_canvas->GetDisplayArea(),
viewport
);
+
+ area = m_canvas->GetDisplayArea();
} else {
viewport.SetLeft(0);
viewport.SetBottom(0);
viewport.SetRight(int(m_canvas->GetWidth()));
viewport.SetTop(int(m_canvas->GetHeight()));
- }
- // store the computed viewport in the scene
-
- scene->SetSceneViewport(viewport);
-
- // set the viewport for this frame and scene
- m_canvas->SetViewPort(
- viewport.GetLeft(),
- viewport.GetBottom(),
- viewport.GetRight(),
- viewport.GetTop()
- );
+ area = m_canvas->GetDisplayArea();
+ }
}
void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
{
- CListValue *lightlist = scene->GetLightList();
+ CListValue *objectlist = scene->GetObjectList();
int i, drawmode;
- for(i=0; i<lightlist->GetCount(); i++) {
- KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i);
+ m_rendertools->SetAuxilaryClientInfo(scene);
+
+ for(i=0; i<objectlist->GetCount(); i++) {
+ KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i);
+
+ if(!gameobj->IsLight())
+ continue;
+
+ KX_LightObject *light = (KX_LightObject*)gameobj;
light->Update();
@@ -939,18 +992,32 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
// update graphics
void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
{
+ bool override_camera;
+ RAS_Rect viewport, area;
float left, right, bottom, top, nearfrust, farfrust, focallength;
const float ortho = 100.0;
// KX_Camera* cam = scene->GetActiveCamera();
if (!cam)
return;
+
+ GetSceneViewport(scene, cam, area, viewport);
+
+ // store the computed viewport in the scene
+ scene->SetSceneViewport(viewport);
+
+ // set the viewport for this frame and scene
+ m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
+ viewport.GetRight(), viewport.GetTop());
// see KX_BlenderMaterial::Activate
//m_rasterizer->SetAmbient();
m_rasterizer->DisplayFog();
- if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) {
+ override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName);
+ override_camera = override_camera && (cam->GetName() == "__default__cam__");
+
+ if (override_camera && m_overrideCamUseOrtho) {
MT_CmMatrix4x4 projmat = m_overrideCamProjMat;
m_rasterizer->SetProjectionMatrix(projmat);
} else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() )
@@ -960,12 +1027,17 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
{
RAS_FrameFrustum frustum;
float lens = cam->GetLens();
+ bool orthographic = !cam->GetCameraData()->m_perspective;
nearfrust = cam->GetCameraNear();
farfrust = cam->GetCameraFar();
focallength = cam->GetFocalLength();
- if (!cam->GetCameraData()->m_perspective)
- {
+ if(override_camera) {
+ nearfrust = m_overrideCamNear;
+ farfrust = m_overrideCamFar;
+ }
+
+ if (orthographic) {
lens *= ortho;
nearfrust = (nearfrust + 1.0)*ortho;
farfrust *= ortho;
@@ -973,8 +1045,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
RAS_FramingManager::ComputeFrustum(
scene->GetFramingType(),
- m_canvas->GetDisplayArea(),
- scene->GetSceneViewport(),
+ area,
+ viewport,
lens,
nearfrust,
farfrust,
@@ -990,7 +1062,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(
left, right, bottom, top, nearfrust, farfrust, focallength);
-
+
cam->SetProjectionMatrix(projmat);
// Otherwise the projection matrix for each eye will be the same...
@@ -1171,19 +1243,49 @@ void KX_KetsjiEngine::RenderDebugProperties()
CValue* propobj = (*it)->m_obj;
STR_String objname = propobj->GetName();
STR_String propname = (*it)->m_name;
- CValue* propval = propobj->GetProperty(propname);
- if (propval)
+ if (propname == "__state__")
{
- STR_String text = propval->GetText();
- debugtxt = objname + "." + propname + " = " + text;
+ // reserve name for object state
+ KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
+ unsigned int state = gameobj->GetState();
+ debugtxt = objname + "." + propname + " = ";
+ bool first = true;
+ for (int statenum=1;state;state >>= 1, statenum++)
+ {
+ if (state & 1)
+ {
+ if (!first)
+ {
+ debugtxt += ",";
+ }
+ debugtxt += STR_String(statenum);
+ first = false;
+ }
+ }
m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
- debugtxt.Ptr(),
- xcoord,
- ycoord,
- m_canvas->GetWidth(),
- m_canvas->GetHeight());
+ debugtxt.Ptr(),
+ xcoord,
+ ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
ycoord += 14;
}
+ else
+ {
+ CValue* propval = propobj->GetProperty(propname);
+ if (propval)
+ {
+ STR_String text = propval->GetText();
+ debugtxt = objname + "." + propname + " = " + text;
+ m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED,
+ debugtxt.Ptr(),
+ xcoord,
+ ycoord,
+ m_canvas->GetWidth(),
+ m_canvas->GetHeight());
+ ycoord += 14;
+ }
+ }
}
}
}
@@ -1281,12 +1383,13 @@ void KX_KetsjiEngine::RemoveScheduledScenes()
KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
{
-
+ Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
m_mousedevice,
m_networkdevice,
m_audiodevice,
- scenename);
+ scenename,
+ scene);
m_sceneconverter->ConvertScene(scenename,
tmpscene,
@@ -1442,6 +1545,11 @@ void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
m_anim_framerate = framerate;
}
+double KX_KetsjiEngine::GetAverageFrameRate()
+{
+ return m_average_framerate;
+}
+
void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
{
m_show_framerate = frameRate;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 77b69ec2d9e..1aa067a9962 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -124,6 +124,8 @@ private:
bool m_overrideCamUseOrtho;
MT_CmMatrix4x4 m_overrideCamProjMat;
MT_CmMatrix4x4 m_overrideCamViewMat;
+ float m_overrideCamNear;
+ float m_overrideCamFar;
bool m_stereo;
int m_curreye;
@@ -149,6 +151,8 @@ private:
/** Labels for profiling display. */
static const char m_profileLabels[tc_numCategories][15];
+ /** Last estimated framerate */
+ static double m_average_framerate;
/** Show the framerate on the game display? */
bool m_show_framerate;
/** Show profiling info on the game display? */
@@ -175,7 +179,6 @@ private:
/** Blue component of framing bar color. */
float m_overrideFrameColorB;
- void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam);
void RenderFrame(KX_Scene* scene, KX_Camera* cam);
void PostRenderFrame();
void RenderDebugProperties();
@@ -226,6 +229,8 @@ public:
void SuspendScene(const STR_String& scenename);
void ResumeScene(const STR_String& scenename);
+ void GetSceneViewport(KX_Scene* scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport);
+
void SetDrawType(int drawingtype);
void SetCameraZoom(float camzoom);
@@ -234,6 +239,7 @@ public:
void SetCameraOverrideUseOrtho(bool useOrtho);
void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat);
void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat);
+ void SetCameraOverrideClipping(float near, float far);
/**
* Sets display of all frames.
@@ -272,6 +278,11 @@ public:
static void SetAnimFrameRate(double framerate);
/**
+ * Gets the last estimated average framerate
+ */
+ static double GetAverageFrameRate();
+
+ /**
* Activates or deactivates timing information display.
* @param frameRate Display for frame rate on or off.
* @param profile Display for individual components on or off.
@@ -348,6 +359,7 @@ protected:
KX_Scene* CreateScene(const STR_String& scenename);
bool BeginFrame();
+ void ClearFrame();
void EndFrame();
};
diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp
index 4e3d6180d22..e0f171e78e0 100644
--- a/source/gameengine/Ketsji/KX_Light.cpp
+++ b/source/gameengine/Ketsji/KX_Light.cpp
@@ -42,14 +42,13 @@
#include "KX_PyMath.h"
-#ifdef BLENDER_GLSL
+#include "DNA_object_types.h"
#include "GPU_material.h"
-#endif
KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
class RAS_IRenderTools* rendertools,
const RAS_LightObject& lightobj,
- struct GPULamp *gpulamp,
+ bool glsl,
PyTypeObject* T
)
:
@@ -59,12 +58,20 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,
m_lightobj = lightobj;
m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr();
m_rendertools->AddLight(&m_lightobj);
- m_gpulamp = gpulamp;
+ m_glsl = glsl;
+ m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene();
};
KX_LightObject::~KX_LightObject()
{
+ GPULamp *lamp;
+
+ if((lamp = GetGPULamp())) {
+ float obmat[4][4] = {{0}};
+ GPU_lamp_update(lamp, 0, obmat);
+ }
+
m_rendertools->RemoveLight(&m_lightobj);
}
@@ -73,7 +80,7 @@ CValue* KX_LightObject::GetReplica()
{
KX_LightObject* replica = new KX_LightObject(*this);
-
+
// this will copy properties and so on...
CValue::AddDataToReplica(replica);
@@ -81,13 +88,23 @@ CValue* KX_LightObject::GetReplica()
replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr();
m_rendertools->AddLight(&replica->m_lightobj);
+
return replica;
}
+GPULamp *KX_LightObject::GetGPULamp()
+{
+ if(m_glsl)
+ return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject());
+ else
+ return false;
+}
+
void KX_LightObject::Update()
{
-#ifdef BLENDER_GLSL
- if(m_gpulamp) {
+ GPULamp *lamp;
+
+ if((lamp = GetGPULamp())) {
float obmat[4][4];
double *dobmat = GetOpenGLMatrixPtr()->getPointer();
@@ -95,38 +112,39 @@ void KX_LightObject::Update()
for(int j=0; j<4; j++, dobmat++)
obmat[i][j] = (float)*dobmat;
- GPU_lamp_update(m_gpulamp, obmat);
+ GPU_lamp_update(lamp, m_lightobj.m_layer, obmat);
}
-#endif
}
bool KX_LightObject::HasShadowBuffer()
{
-#ifdef BLENDER_GLSL
- return (m_gpulamp && GPU_lamp_has_shadow_buffer(m_gpulamp));
-#else
- return false;
-#endif
+ GPULamp *lamp;
+
+ if((lamp = GetGPULamp()))
+ return GPU_lamp_has_shadow_buffer(lamp);
+ else
+ return false;
}
int KX_LightObject::GetShadowLayer()
{
-#ifdef BLENDER_GLSL
- if(m_gpulamp)
- return GPU_lamp_shadow_layer(m_gpulamp);
+ GPULamp *lamp;
+
+ if((lamp = GetGPULamp()))
+ return GPU_lamp_shadow_layer(lamp);
else
-#endif
return 0;
}
void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans)
{
-#ifdef BLENDER_GLSL
+ GPULamp *lamp;
float viewmat[4][4], winmat[4][4];
int winsize;
/* bind framebuffer */
- GPU_lamp_shadow_buffer_bind(m_gpulamp, viewmat, &winsize, winmat);
+ lamp = GetGPULamp();
+ GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat);
/* setup camera transformation */
MT_Matrix4x4 modelviewmat((float*)viewmat);
@@ -146,14 +164,12 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T
ras->SetProjectionMatrix(projectionmat);
ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(),
cam->GetCameraLocation(), cam->GetCameraOrientation());
-#endif
}
void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras)
{
-#ifdef BLENDER_GLSL
- GPU_lamp_shadow_buffer_unbind(m_gpulamp);
-#endif
+ GPULamp *lamp = GetGPULamp();
+ GPU_lamp_shadow_buffer_unbind(lamp);
}
PyObject* KX_LightObject::_getattr(const STR_String& attr)
diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h
index 62eb26c61a8..e5dbf0b7f4a 100644
--- a/source/gameengine/Ketsji/KX_Light.h
+++ b/source/gameengine/Ketsji/KX_Light.h
@@ -33,6 +33,7 @@
#include "KX_GameObject.h"
struct GPULamp;
+struct Scene;
class KX_Camera;
class RAS_IRasterizer;
class RAS_IRenderTools;
@@ -44,16 +45,18 @@ class KX_LightObject : public KX_GameObject
protected:
RAS_LightObject m_lightobj;
class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj
- struct GPULamp *m_gpulamp;
- static char doc[];
+ bool m_glsl;
+ Scene* m_blenderscene;
+ static char doc[];
public:
- KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, struct GPULamp *gpulamp, PyTypeObject *T = &Type);
+ KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type);
virtual ~KX_LightObject();
virtual CValue* GetReplica();
RAS_LightObject* GetLightData() { return &m_lightobj;}
/* GLSL shadow */
+ struct GPULamp *GetGPULamp();
bool HasShadowBuffer();
int GetShadowLayer();
void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans);
@@ -62,6 +65,8 @@ public:
virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */
virtual int _setattr(const STR_String& attr, PyObject *pyvalue);
+
+ virtual bool IsLight(void) { return true; }
};
#endif //__KX_LIGHT
diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
index 2ce5d469380..85d514bd22f 100644
--- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
+++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp
@@ -3,6 +3,8 @@
#include "KX_ScalarInterpolator.h"
#include "KX_GameObject.h"
+#include "BLO_sys_types.h" // for intptr_t support
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -76,10 +78,10 @@ SG_Controller* KX_MaterialIpoController::GetReplica(class SG_Node* destnode)
iporeplica->AddInterpolator(copyipo);
MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
- long orgbase = (long)this;
- long orgloc = (long)scaal;
- long offset = orgloc-orgbase;
- long newaddrbase = (long)iporeplica + offset;
+ intptr_t orgbase = (intptr_t)this;
+ intptr_t orgloc = (intptr_t)scaal;
+ intptr_t offset = orgloc-orgbase;
+ intptr_t newaddrbase = (intptr_t)iporeplica + offset;
MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
copyipo->SetNewTarget((MT_Scalar*)blaptr);
}
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index a0ac9cfd4ff..5cc102248f2 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -35,6 +35,7 @@
#include "RAS_MeshObject.h"
#include "KX_VertexProxy.h"
+#include "KX_PolyProxy.h"
#include "KX_PolygonMaterial.h"
#include "KX_BlenderMaterial.h"
@@ -42,6 +43,8 @@
#include "KX_PyMath.h"
#include "KX_ConvertPhysicsObject.h"
+#include "PyObjectPlus.h"
+
PyTypeObject KX_MeshProxy::Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
@@ -71,10 +74,12 @@ PyParentObject KX_MeshProxy::Parents[] = {
PyMethodDef KX_MeshProxy::Methods[] = {
{"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS},
+{"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS},
{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS},
{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS},
{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS},
{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS},
+{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS},
KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh),
//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS},
@@ -93,10 +98,11 @@ KX_MeshProxy::_getattr(const STR_String& attr)
if (attr == "materials")
{
PyObject *materials = PyList_New(0);
- RAS_MaterialBucket::Set::iterator mit = m_meshobj->GetFirstMaterial();
+ list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
for(; mit != m_meshobj->GetLastMaterial(); ++mit)
{
- RAS_IPolyMaterial *polymat = (*mit)->GetPolyMaterial();
+ RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial();
+
if(polymat->GetFlag() & RAS_BLENDERMAT)
{
KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat);
@@ -146,6 +152,12 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self,
return PyInt_FromLong(num);
}
+PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self)
+{
+ int num = m_meshobj->NumPolygons();
+ return PyInt_FromLong(num);
+}
+
PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self,
PyObject* args,
PyObject* kwds)
@@ -195,11 +207,11 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self,
if (PyArg_ParseTuple(args,"i",&matid))
{
- RAS_IPolyMaterial* mat = m_meshobj->GetMaterialBucket(matid)->GetPolyMaterial();
+ RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid);
+ RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial();
+
if (mat)
- {
- length = m_meshobj->GetVertexArrayLength(mat);
- }
+ length = m_meshobj->NumVertices(mat);
}
else {
return NULL;
@@ -234,6 +246,28 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self,
}
+PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ int polyindex= 1;
+ PyObject* polyob = NULL;
+
+ if (!PyArg_ParseTuple(args,"i",&polyindex))
+ return NULL;
+
+ RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex);
+ if (polygon)
+ {
+ polyob = new KX_PolyProxy(m_meshobj, polygon);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_AttributeError, "Invalid polygon index");
+ }
+ return polyob;
+}
+
KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh,
"Reinstance the physics mesh.")
{
diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h
index 7c6202c15a4..3335c349673 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.h
+++ b/source/gameengine/Ketsji/KX_MeshProxy.h
@@ -57,10 +57,12 @@ public:
KX_PYMETHOD(KX_MeshProxy,GetNumMaterials);
KX_PYMETHOD(KX_MeshProxy,GetMaterialName);
KX_PYMETHOD(KX_MeshProxy,GetTextureName);
+ KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons);
// both take materialid (int)
KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength);
KX_PYMETHOD(KX_MeshProxy,GetVertex);
+ KX_PYMETHOD(KX_MeshProxy,GetPolygon);
KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh);
};
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index db0bef8b7e1..28279b9a6b8 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -62,12 +62,14 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
int focusmode,
RAS_ICanvas* canvas,
KX_Scene* kxscene,
+ KX_KetsjiEngine *kxengine,
SCA_IObject* gameobj,
PyTypeObject* T)
: SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T),
m_focusmode(focusmode),
m_gp_canvas(canvas),
- m_kxscene(kxscene)
+ m_kxscene(kxscene),
+ m_kxengine(kxengine)
{
Init();
}
@@ -122,16 +124,10 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event)
return result;
}
-bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* result, void * const data)
{
KX_GameObject* hitKXObj = client_info->m_gameobject;
- if (client_info->m_type > KX_ClientObjectInfo::ACTOR)
- {
- // false hit
- return false;
- }
-
/* Is this me? In the ray test, there are a lot of extra checks
* for aliasing artefacts from self-hits. That doesn't happen
* here, so a simple test suffices. Or does the camera also get
@@ -142,8 +138,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hi
if ((m_focusmode == 2) || hitKXObj == thisObj)
{
m_hitObject = hitKXObj;
- m_hitPosition = hit_point;
- m_hitNormal = hit_normal;
+ m_hitPosition = result->m_hitPoint;
+ m_hitNormal = result->m_hitNormal;
return true;
}
@@ -158,8 +154,6 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
m_hitObject = 0;
m_hitPosition = MT_Vector3(0,0,0);
m_hitNormal = MT_Vector3(1,0,0);
- MT_Point3 resultpoint;
- MT_Vector3 resultnormal;
/* All screen handling in the gameengine is done by GL,
* specifically the model/view and projection parts. The viewport
@@ -201,11 +195,14 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
* calculations don't bomb. Maybe we should explicitly guard for
* division by 0.0...*/
- /**
- * Get the scenes current viewport.
- */
+ KX_Camera* cam = m_kxscene->GetActiveCamera();
- const RAS_Rect & viewport = m_kxscene->GetSceneViewport();
+ /* get the scenes current viewport. we recompute it because there
+ * may be multiple cameras and m_kxscene->GetSceneViewport() only
+ * has the one that was last drawn */
+
+ RAS_Rect area, viewport;
+ m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport);
float height = float(viewport.m_y2 - viewport.m_y1 + 1);
float width = float(viewport.m_x2 - viewport.m_x1 + 1);
@@ -213,9 +210,9 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
float x_lb = float(viewport.m_x1);
float y_lb = float(viewport.m_y1);
- KX_Camera* cam = m_kxscene->GetActiveCamera();
/* There's some strangeness I don't fully get here... These values
* _should_ be wrong! */
+
/* old: */
float nearclip = 0.0;
@@ -280,7 +277,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void)
bool result = false;
- result = KX_RayCast::RayTest(physics_controller, physics_environment, frompoint3, topoint3, resultpoint, resultnormal, KX_RayCast::Callback<KX_MouseFocusSensor>(this));
+ KX_RayCast::Callback<KX_MouseFocusSensor> callback(this,physics_controller);
+ KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback);
result = (m_hitObject!=0);
@@ -322,14 +320,12 @@ PyParentObject KX_MouseFocusSensor::Parents[] = {
};
PyMethodDef KX_MouseFocusSensor::Methods[] = {
- {"getRayTarget", (PyCFunction) KX_MouseFocusSensor::sPyGetRayTarget,
- METH_VARARGS, GetRayTarget_doc},
- {"getRaySource", (PyCFunction) KX_MouseFocusSensor::sPyGetRaySource,
- METH_VARARGS, GetRaySource_doc},
- {"getHitObject",(PyCFunction) KX_MouseFocusSensor::sPyGetHitObject,METH_VARARGS, GetHitObject_doc},
- {"getHitPosition",(PyCFunction) KX_MouseFocusSensor::sPyGetHitPosition,METH_VARARGS, GetHitPosition_doc},
- {"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_VARARGS, GetHitNormal_doc},
- {"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_VARARGS, GetRayDirection_doc},
+ {"getRayTarget", (PyCFunction) KX_MouseFocusSensor::sPyGetRayTarget, METH_VARARGS, (PY_METHODCHAR)GetRayTarget_doc},
+ {"getRaySource", (PyCFunction) KX_MouseFocusSensor::sPyGetRaySource, METH_VARARGS, (PY_METHODCHAR)GetRaySource_doc},
+ {"getHitObject",(PyCFunction) KX_MouseFocusSensor::sPyGetHitObject,METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc},
+ {"getHitPosition",(PyCFunction) KX_MouseFocusSensor::sPyGetHitPosition,METH_VARARGS, (PY_METHODCHAR)GetHitPosition_doc},
+ {"getHitNormal",(PyCFunction) KX_MouseFocusSensor::sPyGetHitNormal,METH_VARARGS, (PY_METHODCHAR)GetHitNormal_doc},
+ {"getRayDirection",(PyCFunction) KX_MouseFocusSensor::sPyGetRayDirection,METH_VARARGS, (PY_METHODCHAR)GetRayDirection_doc},
{NULL,NULL} //Sentinel
@@ -340,7 +336,7 @@ PyObject* KX_MouseFocusSensor::_getattr(const STR_String& attr) {
}
-char KX_MouseFocusSensor::GetHitObject_doc[] =
+const char KX_MouseFocusSensor::GetHitObject_doc[] =
"getHitObject()\n"
"\tReturns the name of the object that was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self,
@@ -355,7 +351,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self,
}
-char KX_MouseFocusSensor::GetHitPosition_doc[] =
+const char KX_MouseFocusSensor::GetHitPosition_doc[] =
"getHitPosition()\n"
"\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self,
@@ -375,7 +371,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitPosition(PyObject* self,
}
-char KX_MouseFocusSensor::GetRayDirection_doc[] =
+const char KX_MouseFocusSensor::GetRayDirection_doc[] =
"getRayDirection()\n"
"\tReturns the direction from the ray (in worldcoordinates) .\n";
PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self,
@@ -396,7 +392,7 @@ PyObject* KX_MouseFocusSensor::PyGetRayDirection(PyObject* self,
}
-char KX_MouseFocusSensor::GetHitNormal_doc[] =
+const char KX_MouseFocusSensor::GetHitNormal_doc[] =
"getHitNormal()\n"
"\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n";
PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self,
@@ -417,7 +413,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitNormal(PyObject* self,
/* getRayTarget */
-char KX_MouseFocusSensor::GetRayTarget_doc[] =
+const char KX_MouseFocusSensor::GetRayTarget_doc[] =
"getRayTarget()\n"
"\tReturns the target of the ray that seeks the focus object,\n"
"\tin worldcoordinates.";
@@ -434,7 +430,7 @@ PyObject* KX_MouseFocusSensor::PyGetRayTarget(PyObject* self,
}
/* getRayTarget */
-char KX_MouseFocusSensor::GetRaySource_doc[] =
+const char KX_MouseFocusSensor::GetRaySource_doc[] =
"getRaySource()\n"
"\tReturns the source of the ray that seeks the focus object,\n"
"\tin worldcoordinates.";
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index b011ebe1288..6731444699b 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -33,6 +33,8 @@
#include "SCA_MouseSensor.h"
+class KX_RayCast;
+
/**
* The mouse focus sensor extends the basic SCA_MouseSensor. It has
* been placed in KX because it needs access to the rasterizer and
@@ -54,6 +56,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
int focusmode,
RAS_ICanvas* canvas,
KX_Scene* kxscene,
+ KX_KetsjiEngine* kxengine,
SCA_IObject* gameobj,
PyTypeObject* T=&Type );
@@ -76,7 +79,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
return result;
};
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo* client) { return true; }
+
/* --------------------------------------------------------------------- */
@@ -139,12 +144,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
/**
- * Ref to the engine, for retrieving a reference to the current
- * scene. */
- class KX_KetsjiEngine* m_engine;
-
-
- /**
* The active canvas. The size of this canvas determines a part of
* the start position of the picking ray. */
RAS_ICanvas* m_gp_canvas;
@@ -154,6 +153,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
* determines a part of the start location of the picking ray. */
KX_Scene* m_kxscene;
+ /**
+ * The KX engine is needed for computing the viewport */
+ KX_KetsjiEngine* m_kxengine;
};
#endif //__KX_MOUSESENSOR
diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp
index 140dd37f5c6..397aedb3fa3 100644
--- a/source/gameengine/Ketsji/KX_NearSensor.cpp
+++ b/source/gameengine/Ketsji/KX_NearSensor.cpp
@@ -190,13 +190,13 @@ bool KX_NearSensor::Evaluate(CValue* event)
{
if (m_physCtrl)
{
- m_physCtrl->SetMargin(m_ResetMargin);
+ m_physCtrl->SetRadius(m_ResetMargin);
}
} else
{
if (m_physCtrl)
{
- m_physCtrl->SetMargin(m_Margin);
+ m_physCtrl->SetRadius(m_Margin);
}
}
@@ -309,14 +309,10 @@ PyParentObject KX_NearSensor::Parents[] = {
PyMethodDef KX_NearSensor::Methods[] = {
- {"setProperty",
- (PyCFunction) KX_NearSensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
- {"getProperty",
- (PyCFunction) KX_NearSensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
- {"getHitObject",
- (PyCFunction) KX_NearSensor::sPyGetHitObject, METH_VARARGS, GetHitObject_doc},
- {"getHitObjectList",
- (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+ {"setProperty", (PyCFunction) KX_NearSensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
+ {"getProperty", (PyCFunction) KX_NearSensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
+ {"getHitObject",(PyCFunction) KX_NearSensor::sPyGetHitObject, METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc},
+ {"getHitObjectList", (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, (PY_METHODCHAR)GetHitObjectList_doc},
{NULL,NULL} //Sentinel
};
diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp
index 05feb11a2bc..6a701a5f25b 100644
--- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp
@@ -169,6 +169,11 @@ MT_Scalar KX_OdePhysicsController::GetMass()
return ODEPhysicsController::getMass();
}
+MT_Scalar KX_OdePhysicsController::GetRadius()
+{
+ return MT_Scalar(0.f);
+}
+
MT_Vector3 KX_OdePhysicsController::getReactionForce()
{
return MT_Vector3(0,0,0);
diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h
index 18f9edc6835..53050f6ce3e 100644
--- a/source/gameengine/Ketsji/KX_OdePhysicsController.h
+++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h
@@ -76,7 +76,7 @@ public:
virtual void SuspendDynamics(bool);
virtual void RestoreDynamics();
-
+ virtual MT_Scalar GetRadius();
virtual SG_Controller* GetReplica(class SG_Node* destnode);
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 344e0fccc35..eb56e8de679 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -36,6 +36,8 @@
#include "KX_GameObject.h"
#include "KX_PythonInit.h"
+#include "PyObjectPlus.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -164,8 +166,8 @@ PyParentObject KX_ParentActuator::Parents[] = {
};
PyMethodDef KX_ParentActuator::Methods[] = {
- {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, SetObject_doc},
- {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
+ {"setObject", (PyCFunction) KX_ParentActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc},
+ {"getObject", (PyCFunction) KX_ParentActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc},
{NULL,NULL} //Sentinel
};
@@ -174,7 +176,7 @@ PyObject* KX_ParentActuator::_getattr(const STR_String& attr) {
}
/* 1. setObject */
-char KX_ParentActuator::SetObject_doc[] =
+const char KX_ParentActuator::SetObject_doc[] =
"setObject(object)\n"
"\t- object: KX_GameObject, string or None\n"
"\tSet the object to set as parent.\n";
@@ -197,7 +199,7 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* value) {
/* 2. getObject */
/* get obj ---------------------------------------------------------- */
-char KX_ParentActuator::GetObject_doc[] =
+const char KX_ParentActuator::GetObject_doc[] =
"getObject(name_only = 1)\n"
"name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
"\tReturns the object that is set to.\n";
diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
index 9291199d859..da4f05ced7c 100644
--- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp
@@ -27,6 +27,8 @@
* ***** END GPL LICENSE BLOCK *****
*/
#include <Python.h>
+#include "PyObjectPlus.h"
+
#include "KX_PhysicsObjectWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
#include "PHY_IPhysicsController.h"
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
new file mode 100644
index 00000000000..c6f6bc2db01
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -0,0 +1,265 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "KX_PolyProxy.h"
+#include "KX_MeshProxy.h"
+#include "RAS_MeshObject.h"
+#include "KX_BlenderMaterial.h"
+#include "KX_PolygonMaterial.h"
+
+#include "KX_PyMath.h"
+
+PyTypeObject KX_PolyProxy::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_PolyProxy",
+ sizeof(KX_PolyProxy),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject KX_PolyProxy::Parents[] = {
+ &KX_PolyProxy::Type,
+ &SCA_IObject::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef KX_PolyProxy::Methods[] = {
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialIndex),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getNumVertex),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isVisible),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isCollider),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialName),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getTextureName),
+ KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMesh),
+ KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterial),
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_PolyProxy::_getattr(const STR_String& attr)
+{
+ if (attr == "matname")
+ {
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+ }
+ if (attr == "texture")
+ {
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+ }
+ if (attr == "material")
+ {
+ RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
+ if(polymat->GetFlag() & RAS_BLENDERMAT)
+ {
+ KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
+ Py_INCREF(mat);
+ return mat;
+ }
+ else
+ {
+ KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
+ Py_INCREF(mat);
+ return mat;
+ }
+ }
+ if (attr == "matid")
+ {
+ // we'll have to scan through the material bucket of the mes and compare with
+ // the one of the polygon
+ RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
+ unsigned int matid;
+ for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+ {
+ RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
+ if (meshMat->m_bucket == polyBucket)
+ // found it
+ break;
+ }
+ return PyInt_FromLong(matid);
+ }
+ if (attr == "v1")
+ {
+ return PyInt_FromLong(m_polygon->GetVertexOffset(0));
+ }
+ if (attr == "v2")
+ {
+ return PyInt_FromLong(m_polygon->GetVertexOffset(1));
+ }
+ if (attr == "v3")
+ {
+ return PyInt_FromLong(m_polygon->GetVertexOffset(2));
+ }
+ if (attr == "v4")
+ {
+ return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0));
+ }
+ if (attr == "visible")
+ {
+ return PyInt_FromLong(m_polygon->IsVisible());
+ }
+ if (attr == "collide")
+ {
+ return PyInt_FromLong(m_polygon->IsCollider());
+ }
+ _getattr_up(SCA_IObject);
+}
+
+KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon)
+: m_mesh((RAS_MeshObject*)mesh),
+ m_polygon(polygon)
+{
+}
+
+KX_PolyProxy::~KX_PolyProxy()
+{
+}
+
+
+// stuff for cvalue related things
+CValue* KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;}
+CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;}
+STR_String sPolyName="polygone";
+const STR_String & KX_PolyProxy::GetText() {return sPolyName;};
+float KX_PolyProxy::GetNumber() { return -1;}
+STR_String KX_PolyProxy::GetName() { return sPolyName;}
+void KX_PolyProxy::SetName(STR_String) { };
+CValue* KX_PolyProxy::GetReplica() { return NULL;}
+void KX_PolyProxy::ReplicaSetName(STR_String) {};
+
+
+// stuff for python integration
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex,
+"getMaterialIndex() : return the material index of the polygon in the mesh\n")
+{
+ RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial();
+ unsigned int matid;
+ for (matid=0; matid<m_mesh->NumMaterials(); matid++)
+ {
+ RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid);
+ if (meshMat->m_bucket == polyBucket)
+ // found it
+ break;
+ }
+ return PyInt_FromLong(matid);
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getNumVertex,
+"getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n")
+{
+ return PyInt_FromLong(m_polygon->VertexCount());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isVisible,
+"isVisible() : returns whether the polygon is visible or not\n")
+{
+ return PyInt_FromLong(m_polygon->IsVisible());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isCollider,
+"isCollider() : returns whether the polygon is receives collision or not\n")
+{
+ return PyInt_FromLong(m_polygon->IsCollider());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialName,
+"getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n")
+{
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName());
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getTextureName,
+"getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n")
+{
+ return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName());
+}
+
+KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
+"getVertexIndex(vertex) : returns the mesh vertex index of a polygon vertex\n"
+"vertex: index of the vertex in the polygon: 0->3\n"
+"return value can be used to retrieve the vertex details through mesh proxy\n"
+"Note: getVertexIndex(3) on a triangle polygon returns 0\n")
+{
+ int index;
+ if (!PyArg_ParseTuple(args,"i",&index))
+ {
+ return NULL;
+ }
+ if (index < 0 || index > 3)
+ {
+ PyErr_SetString(PyExc_AttributeError, "Valid range for index is 0-3");
+ return NULL;
+ }
+ if (index < m_polygon->VertexCount())
+ {
+ return PyInt_FromLong(m_polygon->GetVertexOffset(index));
+ }
+ return PyInt_FromLong(0);
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMesh,
+"getMesh() : returns a mesh proxy\n")
+{
+ KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh);
+ return meshproxy;
+}
+
+KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterial,
+"getMaterial() : returns a material\n")
+{
+ RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial();
+ if(polymat->GetFlag() & RAS_BLENDERMAT)
+ {
+ KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat);
+ Py_INCREF(mat);
+ return mat;
+ }
+ else
+ {
+ KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat);
+ Py_INCREF(mat);
+ return mat;
+ }
+}
diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h
new file mode 100644
index 00000000000..506e2c2a656
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_PolyProxy.h
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __KX_POLYROXY
+#define __KX_POLYPROXY
+
+#include "SCA_IObject.h"
+
+class KX_PolyProxy : public SCA_IObject
+{
+ Py_Header;
+protected:
+ class RAS_Polygon* m_polygon;
+ class RAS_MeshObject* m_mesh;
+public:
+ KX_PolyProxy(const class RAS_MeshObject*mesh, class RAS_Polygon* polygon);
+ virtual ~KX_PolyProxy();
+
+ // stuff for cvalue related things
+ CValue* Calc(VALUE_OPERATOR op, CValue *val) ;
+ CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
+ const STR_String & GetText();
+ float GetNumber();
+ STR_String GetName();
+ void SetName(STR_String name); // Set the name of the value
+ void ReplicaSetName(STR_String name);
+ CValue* GetReplica();
+
+
+// stuff for python integration
+ virtual PyObject* _getattr(const STR_String& attr);
+
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isVisible)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isCollider)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialName)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getTextureName)
+ KX_PYMETHOD_DOC(KX_PolyProxy,getVertexIndex)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMesh)
+ KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterial)
+
+};
+
+#endif //__KX_POLYPROXY
+
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
index 144f74a1a4c..c9180bf3a80 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp
@@ -35,10 +35,6 @@
#include "BKE_global.h"
#include "BKE_image.h"
-extern "C" {
-#include "BDR_drawmesh.h"
-}
-
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
@@ -46,6 +42,8 @@ extern "C" {
#include "IMB_imbuf_types.h"
+#include "GPU_draw.h"
+
#include "MEM_guardedalloc.h"
#include "RAS_LightObject.h"
@@ -63,8 +61,6 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname,
bool alpha,
bool zsort,
int lightlayer,
- bool bIsTriangle,
- void* clientobject,
struct MTFace* tface,
unsigned int* mcol,
PyTypeObject *T)
@@ -78,9 +74,7 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname,
transp,
alpha,
zsort,
- lightlayer,
- bIsTriangle,
- clientobject),
+ lightlayer),
m_tface(tface),
m_mcol(mcol),
m_material(material),
@@ -140,38 +134,29 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c
if (GetCachingInfo() != cachingInfo)
{
if (!cachingInfo)
- {
- set_tpage(NULL);
- }
+ GPU_set_tpage(NULL);
+
cachingInfo = GetCachingInfo();
if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED))
{
- update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime());
- set_tpage(m_tface);
- rasty->EnableTextures(true);
+ Image *ima = (Image*)m_tface->tpage;
+ GPU_update_image_time(ima, rasty->GetTime());
+ GPU_set_tpage(m_tface);
}
else
- {
- set_tpage(NULL);
- rasty->EnableTextures(false);
- }
+ GPU_set_tpage(NULL);
if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE)
- {
rasty->SetCullFace(false);
- }
else
- {
rasty->SetCullFace(true);
- }
- if (m_drawingmode & RAS_IRasterizer::KX_LINES) {
+ if ((m_drawingmode & RAS_IRasterizer::KX_LINES) ||
+ (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME))
rasty->SetLines(true);
- }
- else {
+ else
rasty->SetLines(false);
- }
}
rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity);
@@ -253,7 +238,8 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr)
if (attr == "lightlayer")
return PyInt_FromLong(m_lightlayer);
if (attr == "triangle")
- return PyInt_FromLong(m_bIsTriangle);
+ // deprecated, triangle/quads shouldn't have been a material property
+ return 0;
if (attr == "diffuse")
return PyObjectFrom(m_diffuse);
@@ -333,7 +319,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue)
// This probably won't work...
if (attr == "triangle")
{
- m_bIsTriangle = value;
+ // deprecated, triangle/quads shouldn't have been a material property
return 0;
}
}
@@ -386,7 +372,9 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast
{
MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty);
- update_realtime_texture(tface, rasty->GetTime());
+ Image *ima = (Image*)tface->tpage;
+ GPU_update_image_time(ima, rasty->GetTime());
+
Py_Return;
}
@@ -399,7 +387,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)")
if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface))
{
MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface);
- set_tpage(tface);
+ GPU_set_tpage(tface);
Py_Return;
}
diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h
index 11c8baa8b1f..fe116f757db 100644
--- a/source/gameengine/Ketsji/KX_PolygonMaterial.h
+++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h
@@ -68,8 +68,6 @@ public:
bool alpha,
bool zsort,
int lightlayer,
- bool bIsTriangle,
- void* clientobject,
struct MTFace* tface,
unsigned int* mcol,
PyTypeObject *T = &Type);
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index 26243c7dba1..dea6225edc2 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -34,6 +34,8 @@
#include "PHY_IPhysicsController.h"
#include "PHY_IVehicle.h"
+#include "PyObjectPlus.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -508,54 +510,54 @@ static PyObject* gPyRemoveConstraint(PyObject* self,
static struct PyMethodDef physicsconstraints_methods[] = {
{"setGravity",(PyCFunction) gPySetGravity,
- METH_VARARGS, gPySetGravity__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetGravity__doc__},
{"setDebugMode",(PyCFunction) gPySetDebugMode,
- METH_VARARGS, gPySetDebugMode__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetDebugMode__doc__},
/// settings that influence quality of the rigidbody dynamics
{"setNumIterations",(PyCFunction) gPySetNumIterations,
- METH_VARARGS, gPySetNumIterations__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetNumIterations__doc__},
{"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps,
- METH_VARARGS, gPySetNumTimeSubSteps__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetNumTimeSubSteps__doc__},
{"setDeactivationTime",(PyCFunction) gPySetDeactivationTime,
- METH_VARARGS, gPySetDeactivationTime__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetDeactivationTime__doc__},
{"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold,
- METH_VARARGS, gPySetDeactivationLinearTreshold__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetDeactivationLinearTreshold__doc__},
{"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold,
- METH_VARARGS, gPySetDeactivationAngularTreshold__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetDeactivationAngularTreshold__doc__},
{"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold,
- METH_VARARGS, gPySetContactBreakingTreshold__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetContactBreakingTreshold__doc__},
{"setCcdMode",(PyCFunction) gPySetCcdMode,
- METH_VARARGS, gPySetCcdMode__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetCcdMode__doc__},
{"setSorConstant",(PyCFunction) gPySetSorConstant,
- METH_VARARGS, gPySetSorConstant__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetSorConstant__doc__},
{"setSolverTau",(PyCFunction) gPySetSolverTau,
- METH_VARARGS, gPySetSolverTau__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetSolverTau__doc__},
{"setSolverDamping",(PyCFunction) gPySetSolverDamping,
- METH_VARARGS, gPySetSolverDamping__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetSolverDamping__doc__},
{"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping,
- METH_VARARGS, gPySetLinearAirDamping__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetLinearAirDamping__doc__},
{"setUseEpa",(PyCFunction) gPySetUseEpa,
- METH_VARARGS, gPySetUseEpa__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetUseEpa__doc__},
{"setSolverType",(PyCFunction) gPySetSolverType,
- METH_VARARGS, gPySetSolverType__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPySetSolverType__doc__},
{"createConstraint",(PyCFunction) gPyCreateConstraint,
- METH_VARARGS, gPyCreateConstraint__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPyCreateConstraint__doc__},
{"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint,
- METH_VARARGS, gPyGetVehicleConstraint__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPyGetVehicleConstraint__doc__},
{"removeConstraint",(PyCFunction) gPyRemoveConstraint,
- METH_VARARGS, gPyRemoveConstraint__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPyRemoveConstraint__doc__},
{"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse,
- METH_VARARGS, gPyGetAppliedImpulse__doc__},
+ METH_VARARGS, (PY_METHODCHAR)gPyGetAppliedImpulse__doc__},
//sentinel
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 868439546c3..fc836234e2b 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -30,7 +30,13 @@
#include "GL/glew.h"
+// directory header for py function getBlendFileList
#include <stdlib.h>
+#ifndef WIN32
+ #include <dirent.h>
+#else
+ #include "BLI_winstuff.h"
+#endif
#ifdef WIN32
#pragma warning (disable : 4786)
@@ -51,21 +57,25 @@
#include "BL_ActionActuator.h"
#include "RAS_IRasterizer.h"
#include "RAS_ICanvas.h"
+#include "RAS_BucketManager.h"
#include "MT_Vector3.h"
#include "MT_Point3.h"
#include "ListValue.h"
#include "KX_Scene.h"
#include "SND_DeviceManager.h"
-#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
#include "BL_Shader.h"
#include "KX_PyMath.h"
+#include "PyObjectPlus.h"
+
extern "C" {
#include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use.
}
+#include "marshal.h" /* python header for loading/saving dicts */
+
#include "PHY_IPhysicsEnvironment.h"
// FIXME: Enable for access to blender python modules. This is disabled because
// python has dependencies on a lot of other modules and is a pain to link.
@@ -77,6 +87,7 @@ extern "C" {
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BLI_blenlib.h"
+#include "GPU_material.h"
static void setSandbox(TPythonSecurityLevel level);
@@ -84,6 +95,7 @@ static void setSandbox(TPythonSecurityLevel level);
// 'local' copy of canvas ptr, for window height/width python scripts
static RAS_ICanvas* gp_Canvas = NULL;
static KX_Scene* gp_KetsjiScene = NULL;
+static KX_KetsjiEngine* gp_KetsjiEngine = NULL;
static RAS_IRasterizer* gp_Rasterizer = NULL;
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
@@ -112,20 +124,16 @@ static PyObject* gPyGetRandomFloat(PyObject*)
return PyFloat_FromDouble(MT_random());
}
-static PyObject* gPySetGravity(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetGravity(PyObject*, PyObject* args)
{
MT_Vector3 vec = MT_Vector3(0., 0., 0.);
- if (PyVecArgTo(args, vec))
- {
- if (gp_KetsjiScene)
- gp_KetsjiScene->SetGravity(vec);
-
- Py_Return;
- }
+ if (!PyVecArgTo(args, vec))
+ return NULL;
+
+ if (gp_KetsjiScene)
+ gp_KetsjiScene->SetGravity(vec);
- return NULL;
+ Py_RETURN_NONE;
}
static char gPyExpandPath_doc[] =
@@ -138,20 +146,17 @@ file to make a full path name (doesn't change during the game, even if you load\
other .blend).\n\
The function also converts the directory separator to the local file system format.";
-static PyObject* gPyExpandPath(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyExpandPath(PyObject*, PyObject* args)
{
char expanded[FILE_MAXDIR + FILE_MAXFILE];
char* filename;
- if (PyArg_ParseTuple(args,"s",&filename))
- {
- BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE);
- BLI_convertstringcode(expanded, G.sce);
- return PyString_FromString(expanded);
- }
- return NULL;
+ if (!PyArg_ParseTuple(args,"s",&filename))
+ return NULL;
+
+ BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE);
+ BLI_convertstringcode(expanded, G.sce);
+ return PyString_FromString(expanded);
}
@@ -179,62 +184,62 @@ static PyObject* gPyGetSpectrum(PyObject*)
PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index]));
}
}
+ else {
+ for (int index = 0; index < 512; index++)
+ {
+ PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0));
+ }
+ }
return resultlist;
}
-static PyObject* gPyStartDSP(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyStartDSP(PyObject*, PyObject* args)
{
SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
- if (audiodevice)
- {
- if (!usedsp)
- {
- audiodevice->StartUsingDSP();
- usedsp = true;
- Py_Return;
- }
+ if (!audiodevice) {
+ PyErr_SetString(PyExc_RuntimeError, "no audio device available");
+ return NULL;
}
- return NULL;
+
+ if (!usedsp) {
+ audiodevice->StartUsingDSP();
+ usedsp = true;
+ }
+
+ Py_RETURN_NONE;
}
-static PyObject* gPyStopDSP(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyStopDSP(PyObject*, PyObject* args)
{
SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
- if (audiodevice)
- {
- if (usedsp)
- {
- audiodevice->StopUsingDSP();
- usedsp = false;
- Py_Return;
- }
+ if (!audiodevice) {
+ PyErr_SetString(PyExc_RuntimeError, "no audio device available");
+ return NULL;
}
- return NULL;
+
+ if (usedsp) {
+ audiodevice->StopUsingDSP();
+ usedsp = true;
+ }
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetLogicTicRate(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args)
{
float ticrate;
- if (PyArg_ParseTuple(args, "f", &ticrate))
- {
- KX_KetsjiEngine::SetTicRate(ticrate);
- Py_Return;
- }
+ if (!PyArg_ParseTuple(args, "f", &ticrate))
+ return NULL;
- return NULL;
+ KX_KetsjiEngine::SetTicRate(ticrate);
+ Py_RETURN_NONE;
}
static PyObject* gPyGetLogicTicRate(PyObject*)
@@ -242,33 +247,24 @@ static PyObject* gPyGetLogicTicRate(PyObject*)
return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate());
}
-static PyObject* gPySetPhysicsTicRate(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args)
{
float ticrate;
- if (PyArg_ParseTuple(args, "f", &ticrate))
- {
-
- PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate);
- Py_Return;
- }
+ if (!PyArg_ParseTuple(args, "f", &ticrate))
+ return NULL;
- return NULL;
+ PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate);
+ Py_RETURN_NONE;
}
-static PyObject* gPySetPhysicsDebug(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args)
{
int debugMode;
- if (PyArg_ParseTuple(args, "i", &debugMode))
- {
- PHY_GetActiveEnvironment()->setDebugMode(debugMode);
- Py_Return;
- }
+ if (!PyArg_ParseTuple(args, "i", &debugMode))
+ return NULL;
- return NULL;
+ PHY_GetActiveEnvironment()->setDebugMode(debugMode);
+ Py_RETURN_NONE;
}
@@ -278,6 +274,51 @@ static PyObject* gPyGetPhysicsTicRate(PyObject*)
return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep());
}
+static PyObject* gPyGetAverageFrameRate(PyObject*)
+{
+ return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate());
+}
+
+static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args)
+{
+ char cpath[sizeof(G.sce)];
+ char *searchpath = NULL;
+ PyObject* list, *value;
+
+ DIR *dp;
+ struct dirent *dirp;
+
+ if (!PyArg_ParseTuple(args, "|s", &searchpath))
+ return NULL;
+
+ list = PyList_New(0);
+
+ if (searchpath) {
+ BLI_strncpy(cpath, searchpath, FILE_MAXDIR + FILE_MAXFILE);
+ BLI_convertstringcode(cpath, G.sce);
+ } else {
+ /* Get the dir only */
+ BLI_split_dirfile_basic(G.sce, 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) {
+ if (BLI_testextensie(dirp->d_name, ".blend")) {
+ value = PyString_FromString(dirp->d_name);
+ PyList_Append(list, value);
+ Py_DECREF(value);
+ }
+ }
+
+ closedir(dp);
+ return list;
+}
+
static STR_String gPyGetCurrentScene_doc =
"getCurrentScene()\n"
"Gets a reference to the current scene.\n";
@@ -360,50 +401,40 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *)
static struct PyMethodDef game_methods[] = {
- {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, gPyExpandPath_doc},
+ {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (PY_METHODCHAR)gPyExpandPath_doc},
{"getCurrentController",
(PyCFunction) SCA_PythonController::sPyGetCurrentController,
- METH_NOARGS, SCA_PythonController::sPyGetCurrentController__doc__},
+ METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::sPyGetCurrentController__doc__},
{"getCurrentScene", (PyCFunction) gPyGetCurrentScene,
- METH_NOARGS, gPyGetCurrentScene_doc.Ptr()},
+ METH_NOARGS, (PY_METHODCHAR)gPyGetCurrentScene_doc.Ptr()},
{"addActiveActuator",(PyCFunction) SCA_PythonController::sPyAddActiveActuator,
- METH_VARARGS, SCA_PythonController::sPyAddActiveActuator__doc__},
+ METH_VARARGS, (PY_METHODCHAR)SCA_PythonController::sPyAddActiveActuator__doc__},
{"getRandomFloat",(PyCFunction) gPyGetRandomFloat,
- METH_NOARGS,gPyGetRandomFloat_doc.Ptr()},
- {"setGravity",(PyCFunction) gPySetGravity, METH_VARARGS,"set Gravitation"},
- {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS,"get audio spectrum"},
- {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS,"stop using the audio dsp (for performance reasons)"},
- {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, "Gets the logic tic rate"},
- {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"},
- {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, "Gets the physics tic rate"},
- {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"},
- {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"},
+ METH_NOARGS, (PY_METHODCHAR)gPyGetRandomFloat_doc.Ptr()},
+ {"setGravity",(PyCFunction) gPySetGravity, METH_VARARGS, (PY_METHODCHAR)"set Gravitation"},
+ {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"},
+ {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"},
+ {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"},
+ {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (PY_METHODCHAR)"Sets the logic tic rate"},
+ {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the physics tic rate"},
+ {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, (PY_METHODCHAR)"Sets the physics tic rate"},
+ {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (PY_METHODCHAR)"Gets the estimated average frame rate"},
+ {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (PY_METHODCHAR)"Gets a list of blend files in the same directory as the current blend file"},
+ {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (PY_METHODCHAR)"Prints GL Extension Info"},
{NULL, (PyCFunction) NULL, 0, NULL }
};
-static PyObject* gPyGetWindowHeight(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args)
{
- int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0);
-
- PyObject* heightval = PyInt_FromLong(height);
- return heightval;
+ return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0));
}
-static PyObject* gPyGetWindowWidth(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args)
{
-
-
- int width = (gp_Canvas ? gp_Canvas->GetWidth() : 0);
-
- PyObject* widthval = PyInt_FromLong(width);
- return widthval;
+ return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0));
}
@@ -411,282 +442,403 @@ static PyObject* gPyGetWindowWidth(PyObject*,
// temporarility visibility thing, will be moved to rasterizer/renderer later
bool gUseVisibilityTemp = false;
-static PyObject* gPyEnableVisibility(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyEnableVisibility(PyObject*, PyObject* args)
{
int visible;
- if (PyArg_ParseTuple(args,"i",&visible))
- {
- gUseVisibilityTemp = (visible != 0);
- }
- else
- {
+ if (!PyArg_ParseTuple(args,"i",&visible))
return NULL;
- }
- Py_Return;
+
+ gUseVisibilityTemp = (visible != 0);
+ Py_RETURN_NONE;
}
-static PyObject* gPyShowMouse(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyShowMouse(PyObject*, PyObject* args)
{
int visible;
- if (PyArg_ParseTuple(args,"i",&visible))
- {
- if (visible)
- {
- if (gp_Canvas)
- gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
- } else
- {
- if (gp_Canvas)
- gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
- }
- }
- else {
+ if (!PyArg_ParseTuple(args,"i",&visible))
return NULL;
+
+ if (visible)
+ {
+ if (gp_Canvas)
+ gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
+ } else
+ {
+ if (gp_Canvas)
+ gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
}
- Py_Return;
+ Py_RETURN_NONE;
}
-static PyObject* gPySetMousePosition(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetMousePosition(PyObject*, PyObject* args)
{
int x,y;
- if (PyArg_ParseTuple(args,"ii",&x,&y))
- {
- if (gp_Canvas)
- gp_Canvas->SetMousePosition(x,y);
- }
- else {
+ if (!PyArg_ParseTuple(args,"ii",&x,&y))
return NULL;
- }
- Py_Return;
+ if (gp_Canvas)
+ gp_Canvas->SetMousePosition(x,y);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetEyeSeparation(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args)
{
float sep;
- if (PyArg_ParseTuple(args, "f", &sep))
- {
- if (gp_Rasterizer)
- gp_Rasterizer->SetEyeSeparation(sep);
-
- Py_Return;
+ if (!PyArg_ParseTuple(args, "f", &sep))
+ return NULL;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
}
- return NULL;
+ gp_Rasterizer->SetEyeSeparation(sep);
+
+ Py_RETURN_NONE;
}
static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*)
{
- if (gp_Rasterizer)
- return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation());
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
- return NULL;
+ return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation());
}
-static PyObject* gPySetFocalLength(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetFocalLength(PyObject*, PyObject* args)
{
float focus;
- if (PyArg_ParseTuple(args, "f", &focus))
- {
- if (gp_Rasterizer)
- gp_Rasterizer->SetFocalLength(focus);
- Py_Return;
+ if (!PyArg_ParseTuple(args, "f", &focus))
+ return NULL;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
}
+
+ gp_Rasterizer->SetFocalLength(focus);
- return NULL;
+ Py_RETURN_NONE;
}
static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*)
{
- if (gp_Rasterizer)
- return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength());
- return NULL;
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
+
+ return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength());
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetBackgroundColor(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args)
{
MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.);
- if (PyVecArgTo(args, vec))
+ if (!PyVecArgTo(args, vec))
+ return NULL;
+
+ if (gp_Canvas)
{
- if (gp_Canvas)
- {
- gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]);
- }
- Py_Return;
+ gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]);
}
-
- return NULL;
+ Py_RETURN_NONE;
}
-static PyObject* gPySetMistColor(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetMistColor(PyObject*, PyObject* args)
{
MT_Vector3 vec = MT_Vector3(0., 0., 0.);
- if (PyVecArgTo(args, vec))
- {
- if (gp_Rasterizer)
- {
- gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]);
- }
- Py_Return;
- }
+ if (!PyVecArgTo(args, vec))
+ return NULL;
- return NULL;
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
+ gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetMistStart(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetMistStart(PyObject*, PyObject* args)
{
float miststart;
- if (PyArg_ParseTuple(args,"f",&miststart))
- {
- if (gp_Rasterizer)
- {
- gp_Rasterizer->SetFogStart(miststart);
- }
- }
- else {
+ if (!PyArg_ParseTuple(args,"f",&miststart))
+ return NULL;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
return NULL;
}
- Py_Return;
+
+ gp_Rasterizer->SetFogStart(miststart);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetMistEnd(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetMistEnd(PyObject*, PyObject* args)
{
float mistend;
- if (PyArg_ParseTuple(args,"f",&mistend))
- {
- if (gp_Rasterizer)
- {
- gp_Rasterizer->SetFogEnd(mistend);
- }
- }
- else {
+ if (!PyArg_ParseTuple(args,"f",&mistend))
+ return NULL;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
return NULL;
}
- Py_Return;
+
+ gp_Rasterizer->SetFogEnd(mistend);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPySetAmbientColor(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPySetAmbientColor(PyObject*, PyObject* args)
{
MT_Vector3 vec = MT_Vector3(0., 0., 0.);
- if (PyVecArgTo(args, vec))
- {
- if (gp_Rasterizer)
- {
- gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]);
- }
- Py_Return;
- }
+ if (!PyVecArgTo(args, vec))
+ return NULL;
- return NULL;
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
+ gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPyMakeScreenshot(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args)
{
char* filename;
- if (PyArg_ParseTuple(args,"s",&filename))
+ if (!PyArg_ParseTuple(args,"s",&filename))
+ return NULL;
+
+ if (gp_Canvas)
{
- if (gp_Canvas)
- {
- gp_Canvas->MakeScreenShot(filename);
- }
+ gp_Canvas->MakeScreenShot(filename);
}
- else {
+
+ Py_RETURN_NONE;
+}
+
+static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args)
+{
+ float motionblurvalue;
+ if (!PyArg_ParseTuple(args,"f",&motionblurvalue))
+ return NULL;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
return NULL;
}
- Py_Return;
+
+ gp_Rasterizer->EnableMotionBlur(motionblurvalue);
+
+ Py_RETURN_NONE;
}
-static PyObject* gPyEnableMotionBlur(PyObject*,
- PyObject* args,
- PyObject*)
+static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args)
{
- float motionblurvalue;
- if (PyArg_ParseTuple(args,"f",&motionblurvalue))
- {
- if(gp_Rasterizer)
- {
- gp_Rasterizer->EnableMotionBlur(motionblurvalue);
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
+
+ gp_Rasterizer->DisableMotionBlur();
+
+ Py_RETURN_NONE;
+}
+
+int getGLSLSettingFlag(char *setting)
+{
+ if(strcmp(setting, "lights") == 0)
+ return G_FILE_GLSL_NO_LIGHTS;
+ else if(strcmp(setting, "shaders") == 0)
+ return G_FILE_GLSL_NO_SHADERS;
+ else if(strcmp(setting, "shadows") == 0)
+ return G_FILE_GLSL_NO_SHADOWS;
+ else if(strcmp(setting, "ramps") == 0)
+ return G_FILE_GLSL_NO_RAMPS;
+ else if(strcmp(setting, "nodes") == 0)
+ return G_FILE_GLSL_NO_NODES;
+ else if(strcmp(setting, "extra_textures") == 0)
+ return G_FILE_GLSL_NO_EXTRA_TEX;
+ else
+ return -1;
+}
+
+static PyObject* gPySetGLSLMaterialSetting(PyObject*,
+ PyObject* args,
+ PyObject*)
+{
+ char *setting;
+ int enable, flag, fileflags;
+
+ if (!PyArg_ParseTuple(args,"si",&setting,&enable))
+ return NULL;
+
+ flag = getGLSLSettingFlag(setting);
+
+ if (flag==-1) {
+ PyErr_SetString(PyExc_ValueError, "glsl setting is not known");
+ return NULL;
+ }
+
+ fileflags = G.fileflags;
+
+ if (enable)
+ G.fileflags &= ~flag;
+ else
+ G.fileflags |= flag;
+
+ /* display lists and GLSL materials need to be remade */
+ if(G.fileflags != fileflags) {
+ if(gp_KetsjiEngine) {
+ KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes();
+ KX_SceneList::iterator it;
+
+ for(it=scenes->begin(); it!=scenes->end(); it++)
+ if((*it)->GetBucketManager())
+ (*it)->GetBucketManager()->ReleaseDisplayLists();
}
+
+ GPU_materials_free();
}
- else {
+
+ Py_RETURN_NONE;
+}
+
+static PyObject* gPyGetGLSLMaterialSetting(PyObject*,
+ PyObject* args,
+ PyObject*)
+{
+ char *setting;
+ int enabled = 0, flag;
+
+ if (!PyArg_ParseTuple(args,"s",&setting))
+ return NULL;
+
+ flag = getGLSLSettingFlag(setting);
+
+ if (flag==-1) {
+ PyErr_SetString(PyExc_ValueError, "glsl setting is not known");
return NULL;
}
- Py_Return;
+
+ enabled = ((G.fileflags & flag) != 0);
+ return PyInt_FromLong(enabled);
}
-static PyObject* gPyDisableMotionBlur(PyObject*,
+#define KX_TEXFACE_MATERIAL 0
+#define KX_BLENDER_MULTITEX_MATERIAL 1
+#define KX_BLENDER_GLSL_MATERIAL 2
+
+static PyObject* gPySetMaterialType(PyObject*,
PyObject* args,
PyObject*)
{
- if(gp_Rasterizer)
- {
- gp_Rasterizer->DisableMotionBlur();
+ int flag, type;
+
+ if (!PyArg_ParseTuple(args,"i",&type))
+ return NULL;
+
+ if(type == KX_BLENDER_GLSL_MATERIAL)
+ flag = G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL;
+ else if(type == KX_BLENDER_MULTITEX_MATERIAL)
+ flag = G_FILE_GAME_MAT;
+ else if(type == KX_TEXFACE_MATERIAL)
+ flag = 0;
+ else {
+ PyErr_SetString(PyExc_ValueError, "material type is not known");
+ return NULL;
}
- Py_Return;
+
+ G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL);
+ G.fileflags |= flag;
+
+ Py_RETURN_NONE;
+}
+
+static PyObject* gPyGetMaterialType(PyObject*)
+{
+ int flag;
+
+ if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL))
+ flag = KX_BLENDER_GLSL_MATERIAL;
+ else if(G.fileflags & G_FILE_GAME_MAT)
+ flag = KX_BLENDER_MULTITEX_MATERIAL;
+ else
+ flag = KX_TEXFACE_MATERIAL;
+
+ return PyInt_FromLong(flag);
}
-STR_String gPyGetWindowHeight__doc__="getWindowHeight doc";
-STR_String gPyGetWindowWidth__doc__="getWindowWidth doc";
-STR_String gPyEnableVisibility__doc__="enableVisibility doc";
-STR_String gPyMakeScreenshot__doc__="make Screenshot doc";
-STR_String gPyShowMouse__doc__="showMouse(bool visible)";
-STR_String gPySetMousePosition__doc__="setMousePosition(int x,int y)";
+static PyObject* gPyDrawLine(PyObject*, PyObject* args)
+{
+ PyObject* ob_from;
+ PyObject* ob_to;
+ PyObject* ob_color;
+
+ if (!gp_Rasterizer) {
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color))
+ return NULL;
+
+ MT_Vector3 from(0., 0., 0.);
+ MT_Vector3 to(0., 0., 0.);
+ MT_Vector3 color(0., 0., 0.);
+ if (!PyVecTo(ob_from, from))
+ return NULL;
+ if (!PyVecTo(ob_to, to))
+ return NULL;
+ if (!PyVecTo(ob_color, color))
+ return NULL;
+
+ gp_Rasterizer->DrawDebugLine(from,to,color);
+
+ Py_RETURN_NONE;
+}
static struct PyMethodDef rasterizer_methods[] = {
{"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
- METH_VARARGS, gPyGetWindowWidth__doc__.Ptr()},
+ METH_VARARGS, "getWindowWidth doc"},
{"getWindowHeight",(PyCFunction) gPyGetWindowHeight,
- METH_VARARGS, gPyGetWindowHeight__doc__.Ptr()},
+ METH_VARARGS, "getWindowHeight doc"},
{"makeScreenshot",(PyCFunction)gPyMakeScreenshot,
- METH_VARARGS, gPyMakeScreenshot__doc__.Ptr()},
+ METH_VARARGS, "make Screenshot doc"},
{"enableVisibility",(PyCFunction) gPyEnableVisibility,
- METH_VARARGS, gPyEnableVisibility__doc__.Ptr()},
+ METH_VARARGS, "enableVisibility doc"},
{"showMouse",(PyCFunction) gPyShowMouse,
- METH_VARARGS, gPyShowMouse__doc__.Ptr()},
+ METH_VARARGS, "showMouse(bool visible)"},
{"setMousePosition",(PyCFunction) gPySetMousePosition,
- METH_VARARGS, gPySetMousePosition__doc__.Ptr()},
+ METH_VARARGS, "setMousePosition(int x,int y)"},
{"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_VARARGS,"set Background Color (rgb)"},
{"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_VARARGS,"set Ambient Color (rgb)"},
{"setMistColor",(PyCFunction)gPySetMistColor,METH_VARARGS,"set Mist Color (rgb)"},
@@ -700,11 +852,19 @@ static struct PyMethodDef rasterizer_methods[] = {
{"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"},
{"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"},
{"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"},
+ {"setMaterialMode",(PyCFunction) gPySetMaterialType,
+ METH_VARARGS, "set the material mode to use for OpenGL rendering"},
+ {"getMaterialMode",(PyCFunction) gPyGetMaterialType,
+ METH_NOARGS, "get the material mode being used for OpenGL rendering"},
+ {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting,
+ METH_VARARGS, "set the state of a GLSL material setting"},
+ {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting,
+ METH_VARARGS, "get the state of a GLSL material setting"},
+ {"drawLine", (PyCFunction) gPyDrawLine,
+ METH_VARARGS, "draw a line on the screen"},
{ NULL, (PyCFunction) NULL, 0, NULL }
};
-
-
// Initialization function for the module (*must* be called initGameLogic)
static char GameLogic_module_documentation[] =
@@ -717,11 +877,12 @@ static char Rasterizer_module_documentation[] =
-PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
+PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
{
PyObject* m;
PyObject* d;
+ gp_KetsjiEngine = engine;
gp_KetsjiScene = scene;
gUseVisibilityTemp=false;
@@ -733,6 +894,10 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
+
+ // can be overwritten later for gameEngine instances that can load new blend files and re-initialize this module
+ // for now its safe to make sure it exists for other areas such as the web plugin
+ PyDict_SetItemString(d, "globalDict", PyDict_New());
ErrorObject = PyString_FromString("GameLogic.error");
PyDict_SetItemString(d, "error", ErrorObject);
@@ -834,6 +999,38 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
KX_MACRO_addTypesToDict(d, CAM_POS, BL_Shader::CAM_POS);
KX_MACRO_addTypesToDict(d, CONSTANT_TIMER, BL_Shader::CONSTANT_TIMER);
+ /* 10 state actuator */
+ KX_MACRO_addTypesToDict(d, KX_STATE1, (1<<0));
+ KX_MACRO_addTypesToDict(d, KX_STATE2, (1<<1));
+ KX_MACRO_addTypesToDict(d, KX_STATE3, (1<<2));
+ KX_MACRO_addTypesToDict(d, KX_STATE4, (1<<3));
+ KX_MACRO_addTypesToDict(d, KX_STATE5, (1<<4));
+ KX_MACRO_addTypesToDict(d, KX_STATE6, (1<<5));
+ KX_MACRO_addTypesToDict(d, KX_STATE7, (1<<6));
+ KX_MACRO_addTypesToDict(d, KX_STATE8, (1<<7));
+ KX_MACRO_addTypesToDict(d, KX_STATE9, (1<<8));
+ KX_MACRO_addTypesToDict(d, KX_STATE10, (1<<9));
+ KX_MACRO_addTypesToDict(d, KX_STATE11, (1<<10));
+ KX_MACRO_addTypesToDict(d, KX_STATE12, (1<<11));
+ KX_MACRO_addTypesToDict(d, KX_STATE13, (1<<12));
+ KX_MACRO_addTypesToDict(d, KX_STATE14, (1<<13));
+ KX_MACRO_addTypesToDict(d, KX_STATE15, (1<<14));
+ KX_MACRO_addTypesToDict(d, KX_STATE16, (1<<15));
+ KX_MACRO_addTypesToDict(d, KX_STATE17, (1<<16));
+ KX_MACRO_addTypesToDict(d, KX_STATE18, (1<<17));
+ KX_MACRO_addTypesToDict(d, KX_STATE19, (1<<18));
+ KX_MACRO_addTypesToDict(d, KX_STATE20, (1<<19));
+ KX_MACRO_addTypesToDict(d, KX_STATE21, (1<<20));
+ KX_MACRO_addTypesToDict(d, KX_STATE22, (1<<21));
+ KX_MACRO_addTypesToDict(d, KX_STATE23, (1<<22));
+ KX_MACRO_addTypesToDict(d, KX_STATE24, (1<<23));
+ KX_MACRO_addTypesToDict(d, KX_STATE25, (1<<24));
+ KX_MACRO_addTypesToDict(d, KX_STATE26, (1<<25));
+ KX_MACRO_addTypesToDict(d, KX_STATE27, (1<<26));
+ KX_MACRO_addTypesToDict(d, KX_STATE28, (1<<27));
+ KX_MACRO_addTypesToDict(d, KX_STATE29, (1<<28));
+ KX_MACRO_addTypesToDict(d, KX_STATE30, (1<<29));
+
// Check for errors
if (PyErr_Occurred())
{
@@ -847,13 +1044,30 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook
// override builtin functions import() and open()
-PyObject *KXpy_open(PyObject *self, PyObject *args)
-{
+PyObject *KXpy_open(PyObject *self, PyObject *args) {
PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function.");
return NULL;
}
+PyObject *KXpy_reload(PyObject *self, PyObject *args) {
+ PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function.");
+ return NULL;
+}
+
+PyObject *KXpy_file(PyObject *self, PyObject *args) {
+ PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function.");
+ return NULL;
+}
+PyObject *KXpy_execfile(PyObject *self, PyObject *args) {
+ PyErr_SetString(PyExc_RuntimeError, "Sandbox: execfile() function disabled!\nGame Scripts should not use this function.");
+ return NULL;
+}
+
+PyObject *KXpy_compile(PyObject *self, PyObject *args) {
+ PyErr_SetString(PyExc_RuntimeError, "Sandbox: compile() function disabled!\nGame Scripts should not use this function.");
+ return NULL;
+}
PyObject *KXpy_import(PyObject *self, PyObject *args)
{
@@ -889,40 +1103,67 @@ PyObject *KXpy_import(PyObject *self, PyObject *args)
}
+/* override python file type functions */
+#if 0
+static int
+file_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ KXpy_file(NULL, NULL);
+ return -1;
+}
+static PyObject *
+file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ return KXpy_file(NULL, NULL);
+}
+#endif
-static PyMethodDef meth_open[] = {
- { "open", KXpy_open, METH_VARARGS,
- "(disabled)"}
-};
-
-
-static PyMethodDef meth_import[] = {
- { "import", KXpy_import, METH_VARARGS,
- "our own import"}
-};
-
+static PyMethodDef meth_open[] = {{ "open", KXpy_open, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_reload[] = {{ "reload", KXpy_reload, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_file[] = {{ "file", KXpy_file, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_execfile[] = {{ "execfile", KXpy_execfile, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_compile[] = {{ "compile", KXpy_compile, METH_VARARGS, "(disabled)"}};
+static PyMethodDef meth_import[] = {{ "import", KXpy_import, METH_VARARGS, "our own import"}};
//static PyObject *g_oldopen = 0;
//static PyObject *g_oldimport = 0;
//static int g_security = 0;
-
void setSandbox(TPythonSecurityLevel level)
{
PyObject *m = PyImport_AddModule("__builtin__");
PyObject *d = PyModule_GetDict(m);
- PyObject *meth = PyCFunction_New(meth_open, NULL);
switch (level) {
case psl_Highest:
//if (!g_security) {
//g_oldopen = PyDict_GetItemString(d, "open");
- PyDict_SetItemString(d, "open", meth);
- meth = PyCFunction_New(meth_import, NULL);
- PyDict_SetItemString(d, "__import__", meth);
+
+ // functions we cant trust
+ PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL));
+ PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL));
+ PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL));
+ PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL));
+ PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL));
+
+ // our own import
+ PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL));
//g_security = level;
+
+ // Overiding file dosnt stop it being accessed if your sneaky
+ // f = [ t for t in (1).__class__.__mro__[-1].__subclasses__() if t.__name__ == 'file'][0]('/some_file.txt', 'w')
+ // f.write('...')
+ // so overwrite the file types functions. be very careful here still, since python uses python.
+ // ps - python devs frown deeply upon this.
+
+ /* this could mess up pythons internals, if we are serious about sandboxing
+ * issues like the one above need to be solved, possibly modify __subclasses__ is safer? */
+#if 0
+ PyFile_Type.tp_init = file_init;
+ PyFile_Type.tp_new = file_new;
+#endif
//}
break;
/*
@@ -1005,6 +1246,11 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
ErrorObject = PyString_FromString("Rasterizer.error");
PyDict_SetItemString(d, "error", 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);
+
// XXXX Add constants here
// Check for errors
@@ -1026,9 +1272,38 @@ static char GameKeys_module_documentation[] =
"This modules provides defines for key-codes"
;
+static char gPyEventToString_doc[] =
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
+;
+static PyObject* gPyEventToString(PyObject*, PyObject* value)
+{
+ PyObject* mod, *dict, *key, *val, *ret = NULL;
+ Py_ssize_t pos = 0;
+
+ mod = PyImport_ImportModule( "GameKeys" );
+ if (!mod)
+ return NULL;
+
+ dict = PyModule_GetDict(mod);
+
+ while (PyDict_Next(dict, &pos, &key, &val)) {
+ if (PyObject_Compare(value, val)==0) {
+ ret = key;
+ break;
+ }
+ }
+
+ PyErr_Clear(); // incase there was an error clearing
+ Py_DECREF(mod);
+ if (!ret) PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event");
+ else Py_INCREF(ret);
+
+ return ret;
+}
static struct PyMethodDef gamekeys_methods[] = {
+ {"EventToString", (PyCFunction)gPyEventToString, METH_O, (PY_METHODCHAR)gPyEventToString_doc},
{ NULL, (PyCFunction) NULL, 0, NULL }
};
@@ -1186,3 +1461,76 @@ class KX_Scene* PHY_GetActiveScene()
{
return gp_KetsjiScene;
}
+
+// utility function for loading and saving the globalDict
+int saveGamePythonConfig( char **marshal_buffer)
+{
+ int marshal_length = 0;
+ PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+ if (gameLogic) {
+ PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
+ if (pyGlobalDict) {
+#ifdef Py_MARSHAL_VERSION
+ PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
+#else
+ PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict );
+#endif
+ if (pyGlobalDictMarshal) {
+ // for testing only
+ // PyObject_Print(pyGlobalDictMarshal, stderr, 0);
+
+ marshal_length= PyString_Size(pyGlobalDictMarshal);
+ *marshal_buffer = new char[marshal_length + 1];
+ memcpy(*marshal_buffer, PyString_AsString(pyGlobalDictMarshal), marshal_length);
+
+ Py_DECREF(pyGlobalDictMarshal);
+ } else {
+ printf("Error, GameLogic.globalDict could not be marshal'd\n");
+ }
+ } else {
+ printf("Error, GameLogic.globalDict was removed\n");
+ }
+ Py_DECREF(gameLogic);
+ } else {
+ printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
+ }
+ return marshal_length;
+}
+
+int loadGamePythonConfig(char *marshal_buffer, int marshal_length)
+{
+ /* Restore the dict */
+ if (marshal_buffer) {
+ PyObject* gameLogic = PyImport_ImportModule("GameLogic");
+
+ if (gameLogic) {
+ PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length);
+
+ if (pyGlobalDict) {
+ PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
+ Py_DECREF(gameLogic);
+ return 1;
+ } else {
+ Py_DECREF(gameLogic);
+ PyErr_Clear();
+ printf("Error could not marshall string\n");
+ }
+ } else {
+ printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
+ }
+ }
+ return 0;
+}
+
+void pathGamePythonConfig( char *path )
+{
+ int len = strlen(G.sce);
+
+ strncpy(path, G.sce, sizeof(G.sce));
+ /* replace extension */
+ if (BLI_testextensie(path, ".blend")) {
+ strcpy(path+(len-6), ".bgeconf");
+ } else {
+ strcpy(path+len, ".bgeconf");
+ }
+}
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index f094a1ca575..28d9d72a4c3 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -40,7 +40,7 @@ typedef enum {
extern bool gUseVisibilityTemp;
-PyObject* initGameLogic(class KX_Scene* ketsjiscene);
+PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene);
PyObject* initGameKeys();
PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas);
PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level);
@@ -49,6 +49,10 @@ void exitGamePlayerPythonScripting();
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
void exitGamePythonScripting();
+void pathGamePythonConfig( char *path );
+int saveGamePythonConfig( char **marshal_buffer);
+int loadGamePythonConfig(char *marshal_buffer, int marshal_length);
+
void PHY_SetActiveScene(class KX_Scene* scene);
class KX_Scene* PHY_GetActiveScene();
#include "MT_Vector3.h"
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index d371626b597..244e9b75d8e 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -221,11 +221,11 @@ PyParentObject KX_RadarSensor::Parents[] = {
PyMethodDef KX_RadarSensor::Methods[] = {
{"getConeOrigin", (PyCFunction) KX_RadarSensor::sPyGetConeOrigin,
- METH_VARARGS, GetConeOrigin_doc},
+ METH_VARARGS, (PY_METHODCHAR)GetConeOrigin_doc},
{"getConeTarget", (PyCFunction) KX_RadarSensor::sPyGetConeTarget,
- METH_VARARGS, GetConeTarget_doc},
+ METH_VARARGS, (PY_METHODCHAR)GetConeTarget_doc},
{"getConeHeight", (PyCFunction) KX_RadarSensor::sPyGetConeHeight,
- METH_VARARGS, GetConeHeight_doc},
+ METH_VARARGS, (PY_METHODCHAR)GetConeHeight_doc},
{NULL,NULL,NULL,NULL} //Sentinel
};
@@ -234,7 +234,7 @@ PyObject* KX_RadarSensor::_getattr(const STR_String& attr) {
}
/* getConeOrigin */
-char KX_RadarSensor::GetConeOrigin_doc[] =
+const char KX_RadarSensor::GetConeOrigin_doc[] =
"getConeOrigin()\n"
"\tReturns the origin of the cone with which to test. The origin\n"
"\tis in the middle of the cone.";
@@ -251,7 +251,7 @@ PyObject* KX_RadarSensor::PyGetConeOrigin(PyObject* self,
}
/* getConeOrigin */
-char KX_RadarSensor::GetConeTarget_doc[] =
+const char KX_RadarSensor::GetConeTarget_doc[] =
"getConeTarget()\n"
"\tReturns the center of the bottom face of the cone with which to test.\n";
PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self,
@@ -267,7 +267,7 @@ PyObject* KX_RadarSensor::PyGetConeTarget(PyObject* self,
}
/* getConeOrigin */
-char KX_RadarSensor::GetConeHeight_doc[] =
+const char KX_RadarSensor::GetConeHeight_doc[] =
"getConeHeight()\n"
"\tReturns the height of the cone with which to test.\n";
PyObject* KX_RadarSensor::PyGetConeHeight(PyObject* self,
diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp
index 89e2d645d54..974d4b992a6 100644
--- a/source/gameengine/Ketsji/KX_RayCast.cpp
+++ b/source/gameengine/Ketsji/KX_RayCast.cpp
@@ -40,7 +40,21 @@
#include "PHY_IPhysicsEnvironment.h"
#include "PHY_IPhysicsController.h"
-bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, MT_Point3& result_point, MT_Vector3& result_normal, const KX_RayCast& callback)
+KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal)
+ :PHY_IRayCastFilterCallback(dynamic_cast<PHY_IPhysicsController*>(ignoreController), faceNormal)
+{
+}
+
+void KX_RayCast::reportHit(PHY_RayCastResult* result)
+{
+ m_hitFound = true;
+ m_hitPoint.setValue((const float*)result->m_hitPoint);
+ m_hitNormal.setValue((const float*)result->m_hitNormal);
+ m_hitMesh = result->m_meshObject;
+ m_hitPolygon = result->m_polygon;
+}
+
+bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
{
// Loops over all physics objects between frompoint and topoint,
// calling callback.RayHit for each one.
@@ -50,58 +64,51 @@ bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsE
// returns true if an object was found, false if not.
MT_Point3 frompoint(_frompoint);
const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
+ MT_Point3 prevpoint(_frompoint+todir*(-1.f));
PHY_IPhysicsController* hit_controller;
- PHY__Vector3 phy_pos;
- PHY__Vector3 phy_normal;
- while((hit_controller = physics_environment->rayTest(dynamic_cast<PHY_IPhysicsController*>(ignore_controller),
+ while((hit_controller = physics_environment->rayTest(callback,
frompoint.x(),frompoint.y(),frompoint.z(),
- topoint.x(),topoint.y(),topoint.z(),
- phy_pos[0],phy_pos[1],phy_pos[2],
- phy_normal[0],phy_normal[1],phy_normal[2])))
+ topoint.x(),topoint.y(),topoint.z())) != NULL)
{
- result_point = MT_Point3(phy_pos);
- result_normal = MT_Vector3(phy_normal);
KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hit_controller->getNewClientInfo());
if (!info)
{
printf("no info!\n");
MT_assert(info && "Physics controller with no client object info");
- return false;
+ break;
}
- if (callback.RayHit(info, result_point, result_normal))
- return true;
-
- // There is a bug in the code below: the delta is computed with the wrong
- // sign on the face opposite to the center, resulting in infinite looping.
- // In Blender 2.45 this code was never executed because callback.RayHit() always
- // returned true, causing the ray sensor to stop on the first object.
- // To avoid changing the behaviour will simply return false here.
- // It should be discussed if we want the ray sensor to "see" through objects
- // that don't have the required property/material (condition to get here)
- return false;
-
- // skip past the object and keep tracing
- /* We add 0.01 of fudge, so that if the margin && radius == 0., we don't endless loop. */
- MT_Scalar marg = 0.01 + hit_controller->GetMargin();
- marg += 2.f * hit_controller->GetMargin();
+ // The biggest danger to to endless loop, prevent this by checking that the
+ // hit point always progresses along the ray direction..
+ prevpoint -= callback.m_hitPoint;
+ if (prevpoint.length2() < MT_EPSILON)
+ break;
+
+ if (callback.RayHit(info))
+ // caller may decide to stop the loop and still cancel the hit
+ return callback.m_hitFound;
+
+ // Skip past the object and keep tracing.
+ // Note that retrieving in a single shot multiple hit points would be possible
+ // but it would require some change in Bullet.
+ prevpoint = callback.m_hitPoint;
+ /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */
+ MT_Scalar marg = 0.001 + hit_controller->GetMargin();
+ marg *= 2.f;
/* Calculate the other side of this object */
- PHY__Vector3 hitpos;
- hit_controller->getPosition(hitpos);
- MT_Point3 hitObjPos(hitpos);
-
- MT_Vector3 hitvector = hitObjPos - result_point;
- if (hitvector.dot(hitvector) > MT_EPSILON)
- {
- hitvector.normalize();
- marg *= 2.*todir.dot(hitvector);
- }
- frompoint = result_point + marg * todir;
+ MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal));
+ if (h <= 0.01)
+ // the normal is almost orthogonal to the ray direction, cannot compute the other side
+ break;
+ marg /= h;
+ frompoint = callback.m_hitPoint + marg * todir;
+ // verify that we are not passed the to point
+ if ((topoint - frompoint).dot(todir) < 0.f)
+ break;
}
-
- return hit_controller;
+ return false;
}
diff --git a/source/gameengine/Ketsji/KX_RayCast.h b/source/gameengine/Ketsji/KX_RayCast.h
index 607dabd8afc..c3084c997a1 100644
--- a/source/gameengine/Ketsji/KX_RayCast.h
+++ b/source/gameengine/Ketsji/KX_RayCast.h
@@ -30,12 +30,14 @@
#ifndef __KX_RAYCAST_H__
#define __KX_RAYCAST_H__
-class MT_Point3;
-class MT_Vector3;
-class KX_IPhysicsController;
-class PHY_IPhysicsEnvironment;
+#include "PHY_IPhysicsEnvironment.h"
+#include "PHY_IPhysicsController.h"
+#include "MT_Point3.h"
+#include "MT_Vector3.h"
+class RAS_MeshObject;
struct KX_ClientObjectInfo;
+class KX_IPhysicsController;
/**
* Defines a function for doing a ray cast.
@@ -49,17 +51,27 @@ struct KX_ClientObjectInfo;
*
* Returns true if a client was accepted, false if nothing found.
*/
-class KX_RayCast
+class KX_RayCast : public PHY_IRayCastFilterCallback
{
-protected:
- KX_RayCast() {};
public:
+ bool m_hitFound;
+ MT_Point3 m_hitPoint;
+ MT_Vector3 m_hitNormal;
+ const RAS_MeshObject* m_hitMesh;
+ int m_hitPolygon;
+
+ KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal);
virtual ~KX_RayCast() {}
+ /**
+ * The physic environment returns the ray casting result through this function
+ */
+ virtual void reportHit(PHY_RayCastResult* result);
+
/** ray test callback.
* either override this in your class, or use a callback wrapper.
*/
- virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const = 0;
+ virtual bool RayHit(KX_ClientObjectInfo* client) = 0;
/**
* Callback wrapper.
@@ -71,13 +83,11 @@ public:
/// Public interface.
/// Implement bool RayHit in your class to receive ray callbacks.
- static bool RayTest(KX_IPhysicsController* physics_controller,
+ static bool RayTest(
PHY_IPhysicsEnvironment* physics_environment,
- const MT_Point3& _frompoint,
+ const MT_Point3& frompoint,
const MT_Point3& topoint,
- MT_Point3& result_point,
- MT_Vector3& result_normal,
- const KX_RayCast& callback);
+ KX_RayCast& callback);
};
@@ -86,18 +96,32 @@ template<class T> class KX_RayCast::Callback : public KX_RayCast
T *self;
void *data;
public:
- Callback(T *_self, void *_data = NULL)
- : self(_self),
+ Callback(T *_self, KX_IPhysicsController* controller=NULL, void *_data = NULL, bool faceNormal=false)
+ : KX_RayCast(controller, faceNormal),
+ self(_self),
data(_data)
{
}
~Callback() {}
-
- virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const
+
+ virtual bool RayHit(KX_ClientObjectInfo* client)
{
- return self->RayHit(client, hit_point, hit_normal, data);
+ return self->RayHit(client, this, data);
}
+
+ virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller)
+ {
+ KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(controller->getNewClientInfo());
+
+ if (!info)
+ {
+ MT_assert(info && "Physics controller with no client object info");
+ return false;
+ }
+ return self->NeedRayCast(info);
+ }
+
};
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index a416c8c9f89..e24fb773eac 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -51,6 +51,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
const STR_String& propname,
bool bFindMaterial,
+ bool bXRay,
double distance,
int axis,
KX_Scene* ketsjiScene,
@@ -58,6 +59,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
: SCA_ISensor(gameobj,eventmgr, T),
m_propertyname(propname),
m_bFindMaterial(bFindMaterial),
+ m_bXRay(bXRay),
m_distance(distance),
m_scene(ketsjiScene),
m_axis(axis)
@@ -104,16 +106,10 @@ bool KX_RaySensor::IsPositiveTrigger()
return result;
}
-bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
+bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
{
KX_GameObject* hitKXObj = client->m_gameobject;
-
- if (client->m_type > KX_ClientObjectInfo::ACTOR)
- {
- // false hit
- return false;
- }
bool bFound = false;
if (m_propertyname.Length() == 0)
@@ -139,16 +135,43 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_
{
m_rayHit = true;
m_hitObject = hitKXObj;
- m_hitPosition = hit_point;
- m_hitNormal = hit_normal;
+ m_hitPosition = result->m_hitPoint;
+ m_hitNormal = result->m_hitNormal;
}
-
- return bFound;
-
+ // no multi-hit search yet
+ return true;
}
-
+/* this function is used to pre-filter the object before casting the ray on them.
+ This is useful for "X-Ray" option when we want to see "through" unwanted object.
+ */
+bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client)
+{
+ if (client->m_type > KX_ClientObjectInfo::ACTOR)
+ {
+ // Unknown type of object, skip it.
+ // Should not occur as the sensor objects are filtered in RayTest()
+ printf("Invalid client type %d found ray casting\n", client->m_type);
+ return false;
+ }
+ if (m_bXRay && m_propertyname.Length() != 0)
+ {
+ if (m_bFindMaterial)
+ {
+ // not quite correct: an object may have multiple material
+ // should check all the material and not only the first one
+ if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ return false;
+ }
+ else
+ {
+ if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ return false;
+ }
+ }
+ return true;
+}
bool KX_RaySensor::Evaluate(CValue* event)
{
@@ -215,8 +238,6 @@ bool KX_RaySensor::Evaluate(CValue* event)
m_rayDirection = todir;
MT_Point3 topoint = frompoint + (m_distance) * todir;
- MT_Point3 resultpoint;
- MT_Vector3 resultnormal;
PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment();
if (!pe)
@@ -238,7 +259,8 @@ bool KX_RaySensor::Evaluate(CValue* event)
PHY_IPhysicsEnvironment* physics_environment = this->m_scene->GetPhysicsEnvironment();
- result = KX_RayCast::RayTest(spc, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback<KX_RaySensor>(this));
+ KX_RayCast::Callback<KX_RaySensor> callback(this, spc);
+ KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback);
/* now pass this result to some controller */
@@ -265,6 +287,10 @@ bool KX_RaySensor::Evaluate(CValue* event)
// notify logicsystem that ray JUST left the Object
result = true;
}
+ else
+ {
+ result = false;
+ }
}
if (reset)
@@ -309,14 +335,14 @@ PyParentObject KX_RaySensor::Parents[] = {
};
PyMethodDef KX_RaySensor::Methods[] = {
- {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_VARARGS, GetHitObject_doc},
- {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_VARARGS, GetHitPosition_doc},
- {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_VARARGS, GetHitNormal_doc},
- {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_VARARGS, GetRayDirection_doc},
+ {"getHitObject",(PyCFunction) KX_RaySensor::sPyGetHitObject,METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc},
+ {"getHitPosition",(PyCFunction) KX_RaySensor::sPyGetHitPosition,METH_VARARGS, (PY_METHODCHAR)GetHitPosition_doc},
+ {"getHitNormal",(PyCFunction) KX_RaySensor::sPyGetHitNormal,METH_VARARGS, (PY_METHODCHAR)GetHitNormal_doc},
+ {"getRayDirection",(PyCFunction) KX_RaySensor::sPyGetRayDirection,METH_VARARGS, (PY_METHODCHAR)GetRayDirection_doc},
{NULL,NULL} //Sentinel
};
-char KX_RaySensor::GetHitObject_doc[] =
+const char KX_RaySensor::GetHitObject_doc[] =
"getHitObject()\n"
"\tReturns the name of the object that was hit by this ray.\n";
PyObject* KX_RaySensor::PyGetHitObject(PyObject* self,
@@ -331,7 +357,7 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self,
}
-char KX_RaySensor::GetHitPosition_doc[] =
+const char KX_RaySensor::GetHitPosition_doc[] =
"getHitPosition()\n"
"\tReturns the position (in worldcoordinates) where the object was hit by this ray.\n";
PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self,
@@ -351,7 +377,7 @@ PyObject* KX_RaySensor::PyGetHitPosition(PyObject* self,
}
-char KX_RaySensor::GetRayDirection_doc[] =
+const char KX_RaySensor::GetRayDirection_doc[] =
"getRayDirection()\n"
"\tReturns the direction from the ray (in worldcoordinates) .\n";
PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self,
@@ -371,7 +397,7 @@ PyObject* KX_RaySensor::PyGetRayDirection(PyObject* self,
}
-char KX_RaySensor::GetHitNormal_doc[] =
+const char KX_RaySensor::GetHitNormal_doc[] =
"getHitNormal()\n"
"\tReturns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray.\n";
PyObject* KX_RaySensor::PyGetHitNormal(PyObject* self,
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index f4305b053d1..02a755fedc1 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -36,12 +36,14 @@
#include "MT_Point3.h"
struct KX_ClientObjectInfo;
+class KX_RayCast;
class KX_RaySensor : public SCA_ISensor
{
Py_Header;
STR_String m_propertyname;
bool m_bFindMaterial;
+ bool m_bXRay;
double m_distance;
class KX_Scene* m_scene;
bool m_bTriggered;
@@ -56,7 +58,8 @@ public:
KX_RaySensor(class SCA_EventManager* eventmgr,
SCA_IObject* gameobj,
const STR_String& propname,
- bool fFindMaterial,
+ bool bFindMaterial,
+ bool bXRay,
double distance,
int axis,
class KX_Scene* ketsjiScene,
@@ -68,7 +71,8 @@ public:
virtual bool IsPositiveTrigger();
virtual void Init();
- bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
+ bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data);
+ bool NeedRayCast(KX_ClientObjectInfo* client);
KX_PYMETHOD_DOC(KX_RaySensor,GetHitObject);
KX_PYMETHOD_DOC(KX_RaySensor,GetHitPosition);
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index ca0106d64d9..5777f54b799 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -39,6 +39,8 @@
#include "KX_GameObject.h"
#include "KX_IPhysicsController.h"
+#include "PyObjectPlus.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,14 +54,20 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj,
int time,
SCA_IScene* scene,
const MT_Vector3& linvel,
- bool local,
+ bool linv_local,
+ const MT_Vector3& angvel,
+ bool angv_local,
PyTypeObject* T)
:
SCA_IActuator(gameobj, T),
m_OriginalObject(original),
m_scene(scene),
+
m_linear_velocity(linvel),
- m_localFlag(local)
+ m_localLinvFlag(linv_local),
+
+ m_angular_velocity(angvel),
+ m_localAngvFlag(angv_local)
{
if (m_OriginalObject)
m_OriginalObject->RegisterActuator(this);
@@ -180,14 +188,16 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = {
NULL
};
PyMethodDef KX_SCA_AddObjectActuator::Methods[] = {
- {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, SetObject_doc},
- {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc},
- {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
- {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
- {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc},
- {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc},
- {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"},
- {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"},
+ {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc},
+ {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, (PY_METHODCHAR)SetTime_doc},
+ {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc},
+ {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, (PY_METHODCHAR)GetTime_doc},
+ {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, (PY_METHODCHAR)GetLinearVelocity_doc},
+ {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, (PY_METHODCHAR)SetLinearVelocity_doc},
+ {"getAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetAngularVelocity, METH_NOARGS, (PY_METHODCHAR)GetAngularVelocity_doc},
+ {"setAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetAngularVelocity, METH_VARARGS, (PY_METHODCHAR)SetAngularVelocity_doc},
+ {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"},
+ {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"},
{NULL,NULL} //Sentinel
};
@@ -199,7 +209,7 @@ PyObject* KX_SCA_AddObjectActuator::_getattr(const STR_String& attr)
}
/* 1. setObject */
-char KX_SCA_AddObjectActuator::SetObject_doc[] =
+const char KX_SCA_AddObjectActuator::SetObject_doc[] =
"setObject(object)\n"
"\t- object: KX_GameObject, string or None\n"
"\tSets the object that will be added. There has to be an object\n"
@@ -224,46 +234,43 @@ PyObject* KX_SCA_AddObjectActuator::PySetObject(PyObject* self, PyObject* value)
/* 2. setTime */
-char KX_SCA_AddObjectActuator::SetTime_doc[] =
+const char KX_SCA_AddObjectActuator::SetTime_doc[] =
"setTime(duration)\n"
"\t- duration: integer\n"
"\tSets the lifetime of the object that will be added, in frames. \n"
"\tIf the duration is negative, it is set to 0.\n";
-PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value)
{
- int deltatime;
-
- if (!PyArg_ParseTuple(args, "i", &deltatime))
+ int deltatime = PyInt_AsLong(value);
+ if (deltatime==-1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "expected an int");
return NULL;
+ }
m_timeProp = deltatime;
if (m_timeProp < 0) m_timeProp = 0;
- Py_Return;
+ Py_RETURN_NONE;
}
/* 3. getTime */
-char KX_SCA_AddObjectActuator::GetTime_doc[] =
+const char KX_SCA_AddObjectActuator::GetTime_doc[] =
"GetTime()\n"
"\tReturns the lifetime of the object that will be added.\n";
-PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self)
{
return PyInt_FromLong(m_timeProp);
}
/* 4. getObject */
-char KX_SCA_AddObjectActuator::GetObject_doc[] =
+const char KX_SCA_AddObjectActuator::GetObject_doc[] =
"getObject(name_only = 1)\n"
"name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
"\tReturns the name of the object that will be added.\n";
@@ -285,22 +292,18 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args)
/* 5. getLinearVelocity */
-char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] =
+const char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] =
"GetLinearVelocity()\n"
"\tReturns the linear velocity that will be assigned to \n"
"\tthe created object.\n";
-
-
-PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self)
{
PyObject *retVal = PyList_New(3);
- PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
- PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
- PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
+ PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
+ PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
+ PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
return retVal;
}
@@ -308,17 +311,15 @@ PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self,
/* 6. setLinearVelocity */
-char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] =
+const char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] =
"setLinearVelocity(vx, vy, vz)\n"
"\t- vx: float\n"
"\t- vy: float\n"
"\t- vz: float\n"
+"\t- local: bool\n"
"\tAssign this velocity to the created object. \n";
-
-PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args)
{
float vecArg[3];
@@ -326,7 +327,46 @@ PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self,
return NULL;
m_linear_velocity.setValue(vecArg);
- Py_Return;
+ Py_RETURN_NONE;
+}
+
+/* 7. getAngularVelocity */
+const char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] =
+"GetAngularVelocity()\n"
+"\tReturns the angular velocity that will be assigned to \n"
+"\tthe created object.\n";
+
+PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self)
+{
+ PyObject *retVal = PyList_New(3);
+
+ PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
+ PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
+ PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
+
+ return retVal;
+}
+
+
+
+/* 8. setAngularVelocity */
+const char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] =
+"setAngularVelocity(vx, vy, vz)\n"
+"\t- vx: float\n"
+"\t- vy: float\n"
+"\t- vz: float\n"
+"\t- local: bool\n"
+"\tAssign this angular velocity to the created object. \n";
+
+PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args)
+{
+
+ float vecArg[3];
+ if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2]))
+ return NULL;
+
+ m_angular_velocity.setValue(vecArg);
+ Py_RETURN_NONE;
}
void KX_SCA_AddObjectActuator::InstantAddObject()
@@ -337,8 +377,9 @@ void KX_SCA_AddObjectActuator::InstantAddObject()
// Now it needs to be added to the current scene.
SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp );
KX_GameObject * game_obj = static_cast<KX_GameObject *>(replica);
- game_obj->setLinearVelocity(m_linear_velocity,m_localFlag);
- game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false);
+ game_obj->setLinearVelocity(m_linear_velocity,m_localLinvFlag);
+ game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag);
+ game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag);
// keep a copy of the last object, to allow python scripters to change it
if (m_lastCreatedObject)
@@ -355,33 +396,32 @@ void KX_SCA_AddObjectActuator::InstantAddObject()
}
}
-PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self)
{
InstantAddObject();
- Py_Return;
+ Py_RETURN_NONE;
}
/* 7. GetLastCreatedObject */
-char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] =
+const char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] =
"getLastCreatedObject()\n"
"\tReturn the last created object. \n";
-PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self)
{
SCA_IObject* result = this->GetLastCreatedObject();
- if (result)
+
+ // if result->GetSGNode() is NULL
+ // it means the object has ended, The BGE python api crashes in many places if the object is returned.
+ if (result && (static_cast<KX_GameObject *>(result))->GetSGNode())
{
result->AddRef();
return result;
}
// don't return NULL to python anymore, it gives trouble in the scripts
- Py_Return;
+ Py_RETURN_NONE;
}
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
index e7fdb2fbfbc..278d4180284 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
@@ -60,9 +60,13 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator
/// Linear velocity upon creation of the object.
MT_Vector3 m_linear_velocity;
+
+ /// Angular velocity upon creation of the object.
+ MT_Vector3 m_angular_velocity;
/// Apply the velocity locally
- bool m_localFlag;
+ bool m_localLinvFlag;
+ bool m_localAngvFlag;
SCA_IObject* m_lastCreatedObject;
@@ -79,7 +83,9 @@ public:
int time,
SCA_IScene* scene,
const MT_Vector3& linvel,
- bool local,
+ bool linv_local,
+ const MT_Vector3& angvel,
+ bool angv_local,
PyTypeObject* T=&Type
);
@@ -115,19 +121,23 @@ public:
/* 1. setObject */
KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetObject);
/* 2. setTime */
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetTime);
+ KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetTime);
/* 3. getTime */
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetTime);
+ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetTime);
/* 4. getObject */
KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,GetObject);
/* 5. getLinearVelocity */
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLinearVelocity);
+ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLinearVelocity);
/* 6. setLinearVelocity */
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetLinearVelocity);
- /* 7. getLastCreatedObject */
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLastCreatedObject);
- /* 8. instantAddObject*/
- KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,InstantAddObject);
+ KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetLinearVelocity);
+ /* 7. getAngularVelocity */
+ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetAngularVelocity);
+ /* 8. setAngularVelocity */
+ KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetAngularVelocity);
+ /* 9. getLastCreatedObject */
+ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLastCreatedObject);
+ /* 10. instantAddObject*/
+ KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject);
}; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index 630df2d21d9..261d9ec8f0c 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -37,6 +37,8 @@
#include "KX_SCA_ReplaceMeshActuator.h"
+#include "PyObjectPlus.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -80,7 +82,7 @@ PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = {
PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = {
- {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_VARARGS, SetMesh_doc},
+ {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, (PY_METHODCHAR)SetMesh_doc},
KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh),
KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, getMesh),
@@ -97,30 +99,31 @@ PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr)
/* 1. setMesh */
-char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] =
+const char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] =
"setMesh(name)\n"
- "\t- name: string\n"
+ "\t- name: string or None\n"
"\tSet the mesh that will be substituted for the current one.\n";
-PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self,
- PyObject* args,
- PyObject* kwds)
+PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value)
{
- char* meshname;
-
- if (!PyArg_ParseTuple(args, "s", &meshname))
- {
- return NULL;
- }
-
- void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
-
- if (mesh) {
+ if (value == Py_None) {
+ m_mesh = NULL;
+ } else {
+ char* meshname = PyString_AsString(value);
+ if (!meshname) {
+ PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None");
+ return NULL;
+ }
+ void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
+
+ if (mesh==NULL) {
+ PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist");
+ return NULL;
+ }
m_mesh= (class RAS_MeshObject*)mesh;
- Py_Return;
}
- return NULL;
+ Py_RETURN_NONE;
}
KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh,
@@ -129,7 +132,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh,
)
{
if (!m_mesh)
- Py_Return;
+ Py_RETURN_NONE;
return PyString_FromString(const_cast<char *>(m_mesh->GetName().ReadPtr()));
}
@@ -139,7 +142,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh,
"instantReplaceMesh() : immediately replace mesh without delay\n")
{
InstantReplaceMesh();
- Py_Return;
+ Py_RETURN_NONE;
}
/* ------------------------------------------------------------------------- */
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
index 5ba0a099b14..1da154cc222 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h
@@ -76,7 +76,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator
void InstantReplaceMesh();
/* 1. setMesh */
- KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,SetMesh);
+ KX_PYMETHOD_DOC_O(KX_SCA_ReplaceMeshActuator,SetMesh);
KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,getMesh);
KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh);
diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
index f085ff435dc..d651373869a 100644
--- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
+++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp
@@ -78,7 +78,7 @@ UpdateChildCoordinates(
if (parent)
{
- const BL_ArmatureObject *armature = (const BL_ArmatureObject*)(parent->GetSGClientObject());
+ BL_ArmatureObject *armature = (BL_ArmatureObject*)(parent->GetSGClientObject());
if (armature)
{
MT_Matrix4x4 parent_matrix;
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 2828663c63d..f5d6d7e8e0a 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -68,6 +68,7 @@
#include "SG_IObject.h"
#include "SG_Tree.h"
#include "DNA_group_types.h"
+#include "DNA_scene_types.h"
#include "BKE_anim.h"
#include "KX_SG_NodeRelationships.h"
@@ -116,7 +117,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SCA_IInputDevice* mousedevice,
class NG_NetworkDeviceInterface *ndi,
class SND_IAudioDevice* adi,
- const STR_String& sceneName):
+ const STR_String& sceneName,
+ Scene *scene):
PyObjectPlus(&KX_Scene::Type),
m_keyboardmgr(NULL),
m_mousemgr(NULL),
@@ -126,7 +128,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_adi(adi),
m_networkDeviceInterface(ndi),
m_active_camera(NULL),
- m_ueberExecutionPriority(0)
+ m_ueberExecutionPriority(0),
+ m_blenderScene(scene)
{
m_suspendedtime = 0.0;
m_suspendeddelta = 0.0;
@@ -156,7 +159,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
KX_NetworkEventManager* netmgr = new KX_NetworkEventManager(m_logicmgr, ndi);
- SCA_JoystickManager *joymgr = new SCA_JoystickManager(m_logicmgr);
+
m_logicmgr->RegisterEventManager(alwaysmgr);
m_logicmgr->RegisterEventManager(propmgr);
@@ -167,7 +170,15 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_logicmgr->RegisterEventManager(rndmgr);
m_logicmgr->RegisterEventManager(raymgr);
m_logicmgr->RegisterEventManager(netmgr);
- m_logicmgr->RegisterEventManager(joymgr);
+
+
+ SYS_SystemHandle hSystem = SYS_GetSystem();
+ bool nojoystick= SYS_GetCommandLineInt(hSystem,"nojoystick",0);
+ if (!nojoystick)
+ {
+ SCA_JoystickManager *joymgr = new SCA_JoystickManager(m_logicmgr);
+ m_logicmgr->RegisterEventManager(joymgr);
+ }
m_soundScene = new SND_Scene(adi);
MT_assert (m_networkDeviceInterface != NULL);
@@ -234,40 +245,9 @@ KX_Scene::~KX_Scene()
{
delete m_bucketmanager;
}
-#ifdef USE_BULLET
- // This is a fix for memory leaks in bullet: the collision shapes is not destroyed
- // when the physical controllers are destroyed. The reason is that shapes are shared
- // between replicas of an object. There is no reference count in Bullet so the
- // only workaround that does not involve changes in Bullet is to save in this array
- // the list of shapes that are created when the scene is created (see KX_ConvertPhysicsObjects.cpp)
- class btCollisionShape* shape;
- class btTriangleMeshShape* meshShape;
- vector<class btCollisionShape*>::iterator it = m_shapes.begin();
- while (it != m_shapes.end()) {
- shape = *it;
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- meshShape = static_cast<btTriangleMeshShape*>(shape);
- // shapes based on meshes use an interface that contains the vertices.
- // Again the idea is to be able to share the interface between shapes but
- // this is not used in Blender: each base object will have its own interface
- btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
- if (meshInterface)
- delete meshInterface;
- }
- delete shape;
- it++;
- }
-#endif
//Py_DECREF(m_attrlist);
}
-void KX_Scene::AddShape(class btCollisionShape*shape)
-{
- m_shapes.push_back(shape);
-}
-
-
void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
{
m_projectionmat = pmat;
@@ -484,7 +464,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
// this is the list of object that are send to the graphics pipeline
m_objectlist->Add(newobj->AddRef());
- newobj->Bucketize();
+ newobj->AddMeshUser();
// logic cannot be replicated, until the whole hierarchy is replicated.
m_logicHierarchicalGameObjects.push_back(newobj);
@@ -654,6 +634,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
if (blgroupobj == blenderobj)
// this check is also in group_duplilist()
continue;
+
gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj);
if (gameobj == NULL)
{
@@ -661,6 +642,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
// Should not happen as dupli group are created automatically
continue;
}
+
+ gameobj->SetBlenderGroupObject(blgroupobj);
+
if ((blenderobj->lay & group->layer)==0)
{
// object is not visible in the 3D view, will not be instantiated
@@ -718,17 +702,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition());
replica->NodeSetLocalPosition(newpos);
- if (replica->GetPhysicsController())
- {
- // not required, already done in NodeSetLocalOrientation..
- //replica->GetPhysicsController()->setPosition(newpos);
- //replica->GetPhysicsController()->setOrientation(newori.getRotation());
- // Scaling has been set relatively hereabove, this does not
- // set the scaling of the controller. I don't know why it's just the
- // relative scale and not the full scale that has to be put here...
- replica->GetPhysicsController()->setScaling(newscale);
- }
-
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius());
@@ -853,18 +826,6 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
// set the replica's relative scale with the rootnode's scale
replica->NodeSetRelativeScale(newscale);
- if (replica->GetPhysicsController())
- {
- // not needed, already done in NodeSetLocalPosition()
- //replica->GetPhysicsController()->setPosition(newpos);
- //replica->GetPhysicsController()->setOrientation(newori.getRotation());
- replica->GetPhysicsController()->setScaling(newscale);
- }
-
- // here we want to set the relative scale: the rootnode's scale will override all other
- // scalings, so lets better prepare for it
-
-
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
@@ -975,6 +936,8 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
newobj->RemoveMeshes();
ret = 1;
+ if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell
+ ret = newobj->Release();
if (m_objectlist->RemoveValue(newobj))
ret = newobj->Release();
if (m_tempObjectList->RemoveValue(newobj))
@@ -1022,13 +985,13 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
{
BL_DeformableGameObject* newobj = static_cast<BL_DeformableGameObject*>( gameobj );
- if (newobj->m_pDeformer)
+ if (newobj->GetDeformer())
{
- delete newobj->m_pDeformer;
- newobj->m_pDeformer = NULL;
+ delete newobj->GetDeformer();
+ newobj->SetDeformer(NULL);
}
- if (mesh->m_class == 1)
+ if (mesh->IsDeformed())
{
// we must create a new deformer but which one?
KX_GameObject* parentobj = newobj->GetParent();
@@ -1075,7 +1038,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
NULL
);
}
- newobj->m_pDeformer = shapeDeformer;
+ newobj->SetDeformer( shapeDeformer);
}
else if (bHasArmature)
{
@@ -1087,14 +1050,14 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
static_cast<BL_ArmatureObject*>( parentobj )
);
releaseParent= false;
- newobj->m_pDeformer = skinDeformer;
+ newobj->SetDeformer(skinDeformer);
}
else if (bHasDvert)
{
BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(
newobj, oldblendobj, static_cast<BL_SkinMeshObject*>(mesh)
);
- newobj->m_pDeformer = meshdeformer;
+ newobj->SetDeformer(meshdeformer);
}
// release parent reference if its not being used
@@ -1102,7 +1065,8 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj)
parentobj->Release();
}
}
- gameobj->Bucketize();
+
+ gameobj->AddMeshUser();
}
@@ -1254,7 +1218,9 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi
for (int m=0;m<nummeshes;m++)
(gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode());
}
- gameobj->MarkVisible(visible);
+
+ gameobj->SetCulled(!visible);
+ gameobj->UpdateBuckets(false);
}
}
if (node->Left())
@@ -1271,7 +1237,8 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
// Shadow lamp layers
if(layer && !(gameobj->GetLayer() & layer)) {
- gameobj->MarkVisible(false);
+ gameobj->SetCulled(true);
+ gameobj->UpdateBuckets(false);
return;
}
@@ -1317,9 +1284,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam
}
// Visibility/ non-visibility are marked
// elsewhere now.
- gameobj->MarkVisible();
+ gameobj->SetCulled(false);
+ gameobj->UpdateBuckets(false);
} else {
- gameobj->MarkVisible(false);
+ gameobj->SetCulled(true);
+ gameobj->UpdateBuckets(false);
}
}
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 80a2abe287a..5f7e1167e27 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -54,6 +54,7 @@
*/
struct SM_MaterialProps;
struct SM_ShapeProps;
+struct Scene;
class GEN_HashedPtr;
class CListValue;
@@ -122,11 +123,6 @@ protected:
*/
list<class KX_Camera*> m_cameras;
/**
- * The set of bullet shapes that must be deleted at the end of the scene
- * to avoid memory leak (not deleted by bullet because shape are shared between replicas)
- */
- vector<class btCollisionShape*> m_shapes;
- /**
* Various SCA managers used by the scene
*/
SCA_LogicManager* m_logicmgr;
@@ -282,12 +278,15 @@ protected:
*/
PyObject* m_attrlist;
+ struct Scene* m_blenderScene;
+
public:
KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SCA_IInputDevice* mousedevice,
class NG_NetworkDeviceInterface* ndi,
class SND_IAudioDevice* adi,
- const STR_String& scenename );
+ const STR_String& scenename,
+ struct Scene* scene);
virtual
~KX_Scene();
@@ -322,7 +321,6 @@ public:
int NewRemoveObject(CValue* gameobj);
void ReplaceMesh(CValue* gameobj,
void* meshobj);
- void AddShape(class btCollisionShape* shape);
/**
* @section Logic stuff
* Initiate an update of the logic system.
@@ -588,6 +586,10 @@ public:
* was running and not suspended) and the "curtime"
*/
double getSuspendedDelta();
+ /**
+ * Returns the Blender scene this was made from
+ */
+ struct Scene *GetBlenderScene() { return m_blenderScene; }
};
typedef std::vector<KX_Scene*> KX_SceneList;
diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp
index d6164dc812a..35484699b17 100644
--- a/source/gameengine/Ketsji/KX_SceneActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp
@@ -259,12 +259,12 @@ PyParentObject KX_SceneActuator::Parents[] =
PyMethodDef KX_SceneActuator::Methods[] =
{
- {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, SetUseRestart_doc},
- {"setScene", (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, SetScene_doc},
- {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, SetCamera_doc},
- {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_VARARGS, GetUseRestart_doc},
- {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_VARARGS, GetScene_doc},
- {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_VARARGS, GetCamera_doc},
+ {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, (PY_METHODCHAR)SetUseRestart_doc},
+ {"setScene", (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, (PY_METHODCHAR)SetScene_doc},
+ {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, (PY_METHODCHAR)SetCamera_doc},
+ {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_VARARGS, (PY_METHODCHAR)GetUseRestart_doc},
+ {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_VARARGS, (PY_METHODCHAR)GetScene_doc},
+ {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_VARARGS, (PY_METHODCHAR)GetCamera_doc},
{NULL,NULL} //Sentinel
};
@@ -278,7 +278,7 @@ PyObject* KX_SceneActuator::_getattr(const STR_String& attr)
/* 2. setUseRestart--------------------------------------------------------- */
-char KX_SceneActuator::SetUseRestart_doc[] =
+const char KX_SceneActuator::SetUseRestart_doc[] =
"setUseRestart(flag)\n"
"\t- flag: 0 or 1.\n"
"\tSet flag to 1 to restart the scene.\n" ;
@@ -301,7 +301,7 @@ PyObject* KX_SceneActuator::PySetUseRestart(PyObject* self,
/* 3. getUseRestart: */
-char KX_SceneActuator::GetUseRestart_doc[] =
+const char KX_SceneActuator::GetUseRestart_doc[] =
"getUseRestart()\n"
"\tReturn whether the scene will be restarted.\n" ;
PyObject* KX_SceneActuator::PyGetUseRestart(PyObject* self,
@@ -314,7 +314,7 @@ PyObject* KX_SceneActuator::PyGetUseRestart(PyObject* self,
/* 4. set scene------------------------------------------------------------- */
-char KX_SceneActuator::SetScene_doc[] =
+const char KX_SceneActuator::SetScene_doc[] =
"setScene(scene)\n"
"\t- scene: string\n"
"\tSet the name of scene the actuator will switch to.\n" ;
@@ -339,7 +339,7 @@ PyObject* KX_SceneActuator::PySetScene(PyObject* self,
/* 5. getScene: */
-char KX_SceneActuator::GetScene_doc[] =
+const char KX_SceneActuator::GetScene_doc[] =
"getScene()\n"
"\tReturn the name of the scene the actuator wants to switch to.\n" ;
PyObject* KX_SceneActuator::PyGetScene(PyObject* self,
@@ -352,7 +352,7 @@ PyObject* KX_SceneActuator::PyGetScene(PyObject* self,
/* 6. set camera------------------------------------------------------------ */
-char KX_SceneActuator::SetCamera_doc[] =
+const char KX_SceneActuator::SetCamera_doc[] =
"setCamera(camera)\n"
"\t- camera: string\n"
"\tSet the camera to switch to.\n" ;
@@ -394,7 +394,7 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self,
/* 7. getCamera: */
-char KX_SceneActuator::GetCamera_doc[] =
+const char KX_SceneActuator::GetCamera_doc[] =
"getCamera()\n"
"\tReturn the name of the camera to switch to.\n" ;
PyObject* KX_SceneActuator::PyGetCamera(PyObject* self,
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 34a3baec093..f75a1ee5c62 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -69,11 +69,11 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
KX_SoundActuator::~KX_SoundActuator()
{
- //m_soundScene->RemoveObject(this->m_soundObject);
- //(this->m_soundObject)->DeleteWhenFinished();
- m_soundScene->RemoveActiveObject(m_soundObject);
-// m_soundScene->DeleteObjectWhenFinished(m_soundObject);
- m_soundScene->DeleteObject(m_soundObject);
+ if (m_soundObject)
+ {
+ m_soundScene->RemoveActiveObject(m_soundObject);
+ m_soundScene->DeleteObject(m_soundObject);
+ }
}
@@ -82,9 +82,12 @@ CValue* KX_SoundActuator::GetReplica()
{
KX_SoundActuator* replica = new KX_SoundActuator(*this);
replica->ProcessReplica();
- SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
- replica->setSoundObject(soundobj);
- m_soundScene->AddObject(soundobj);
+ if (m_soundObject)
+ {
+ SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject);
+ replica->setSoundObject(soundobj);
+ m_soundScene->AddObject(soundobj);
+ }
// this will copy properties and so on...
CValue::AddDataToReplica(replica);
@@ -104,6 +107,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
RemoveAllEvents();
+ if (!m_soundObject)
+ return false;
+
if (m_pino)
{
bNegativeEvent = true;
@@ -287,6 +293,10 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje
PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds)
{
+ if (!m_soundObject)
+ {
+ return PyString_FromString("");
+ }
STR_String objectname = m_soundObject->GetObjectName();
char* name = objectname.Ptr();
@@ -301,7 +311,8 @@ PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObje
PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds)
{
- m_soundObject->StartSound();
+ if (m_soundObject)
+ m_soundObject->StartSound();
Py_Return;
}
@@ -309,7 +320,8 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec
PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds)
{
- m_soundObject->PauseSound();
+ if (m_soundObject)
+ m_soundObject->PauseSound();
Py_Return;
}
@@ -317,7 +329,8 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec
PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds)
{
- m_soundObject->StopSound();
+ if (m_soundObject)
+ m_soundObject->StopSound();
Py_Return;
}
@@ -329,7 +342,8 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject*
if (!PyArg_ParseTuple(args, "f", &gain))
return NULL;
- m_soundObject->SetGain(gain);
+ if (m_soundObject)
+ m_soundObject->SetGain(gain);
Py_Return;
}
@@ -338,7 +352,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject*
PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds)
{
- float gain = m_soundObject->GetGain();
+ float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f;
PyObject* result = PyFloat_FromDouble(gain);
return result;
@@ -352,7 +366,8 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject*
if (!PyArg_ParseTuple(args, "f", &pitch))
return NULL;
- m_soundObject->SetPitch(pitch);
+ if (m_soundObject)
+ m_soundObject->SetPitch(pitch);
Py_Return;
}
@@ -361,7 +376,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject*
PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds)
{
- float pitch = m_soundObject->GetPitch();
+ float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0;
PyObject* result = PyFloat_FromDouble(pitch);
return result;
@@ -375,7 +390,8 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P
if (!PyArg_ParseTuple(args, "f", &rollofffactor))
return NULL;
- m_soundObject->SetRollOffFactor(rollofffactor);
+ if (m_soundObject)
+ m_soundObject->SetRollOffFactor(rollofffactor);
Py_Return;
}
@@ -384,7 +400,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P
PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds)
{
- float rollofffactor = m_soundObject->GetRollOffFactor();
+ float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0;
PyObject* result = PyFloat_FromDouble(rollofffactor);
return result;
@@ -398,7 +414,8 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec
if (!PyArg_ParseTuple(args, "i", &looping))
return NULL;
- m_soundObject->SetLoopMode(looping);
+ if (m_soundObject)
+ m_soundObject->SetLoopMode(looping);
Py_Return;
}
@@ -407,7 +424,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec
PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds)
{
- int looping = m_soundObject->GetLoopMode();
+ int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : SND_LOOP_OFF;
PyObject* result = PyInt_FromLong(looping);
return result;
@@ -425,7 +442,8 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje
if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2]))
return NULL;
- m_soundObject->SetPosition(pos);
+ if (m_soundObject)
+ m_soundObject->SetPosition(pos);
Py_Return;
}
@@ -442,7 +460,8 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje
if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2]))
return NULL;
- m_soundObject->SetVelocity(vel);
+ if (m_soundObject)
+ m_soundObject->SetVelocity(vel);
Py_Return;
}
@@ -465,7 +484,8 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO
if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2]))
return NULL;
- m_soundObject->SetOrientation(ori);
+ if (m_soundObject)
+ m_soundObject->SetOrientation(ori);
Py_Return;
}
diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp
index 95a79f0c480..e360c4bac1f 100644
--- a/source/gameengine/Ketsji/KX_StateActuator.cpp
+++ b/source/gameengine/Ketsji/KX_StateActuator.cpp
@@ -140,9 +140,9 @@ KX_StateActuator::Parents[] = {
PyMethodDef
KX_StateActuator::Methods[] = {
{"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation,
- METH_VARARGS, SetOperation_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetOperation_doc},
{"setMask", (PyCFunction) KX_StateActuator::sPySetMask,
- METH_VARARGS, SetMask_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetMask_doc},
{NULL,NULL} //Sentinel
};
@@ -157,7 +157,7 @@ KX_StateActuator::_getattr(
/* set operation ---------------------------------------------------------- */
-char
+const char
KX_StateActuator::SetOperation_doc[] =
"setOperation(op)\n"
"\t - op : bit operation (0=Copy, 1=Set, 2=Clear, 3=Negate)"
@@ -180,7 +180,7 @@ KX_StateActuator::PySetOperation(PyObject* self,
}
/* set mask ---------------------------------------------------------- */
-char
+const char
KX_StateActuator::SetMask_doc[] =
"setMask(mask)\n"
"\t - mask : bits that will be modified"
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
index 4032a795ce3..c842ca1ee14 100644
--- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp
@@ -205,6 +205,11 @@ MT_Scalar KX_SumoPhysicsController::GetMass()
return SumoPhysicsController::getMass();
}
+MT_Scalar KX_SumoPhysicsController::GetRadius()
+{
+ return SumoPhysicsController::GetRadius();
+}
+
MT_Vector3 KX_SumoPhysicsController::getReactionForce()
{
float force[3];
diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
index 1dd930bf3d9..abe48d99043 100644
--- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h
+++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h
@@ -84,6 +84,7 @@ public:
virtual void setPosition(const MT_Point3& pos);
virtual void setScaling(const MT_Vector3& scaling);
virtual MT_Scalar GetMass();
+ virtual MT_Scalar GetRadius();
virtual MT_Vector3 getReactionForce();
virtual void setRigidBody(bool rigid);
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index 60e1d87d318..41757a23f7a 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -240,13 +240,13 @@ PyParentObject KX_TouchSensor::Parents[] = {
PyMethodDef KX_TouchSensor::Methods[] = {
{"setProperty",
- (PyCFunction) KX_TouchSensor::sPySetProperty, METH_VARARGS, SetProperty_doc},
+ (PyCFunction) KX_TouchSensor::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc},
{"getProperty",
- (PyCFunction) KX_TouchSensor::sPyGetProperty, METH_VARARGS, GetProperty_doc},
+ (PyCFunction) KX_TouchSensor::sPyGetProperty, METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
{"getHitObject",
- (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_VARARGS, GetHitObject_doc},
+ (PyCFunction) KX_TouchSensor::sPyGetHitObject, METH_VARARGS, (PY_METHODCHAR)GetHitObject_doc},
{"getHitObjectList",
- (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+ (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_VARARGS, (PY_METHODCHAR)GetHitObjectList_doc},
{NULL,NULL} //Sentinel
};
@@ -257,7 +257,7 @@ PyObject* KX_TouchSensor::_getattr(const STR_String& attr) {
/* Python API */
/* 1. setProperty */
-char KX_TouchSensor::SetProperty_doc[] =
+const char KX_TouchSensor::SetProperty_doc[] =
"setProperty(name)\n"
"\t- name: string\n"
"\tSet the property or material to collide with. Use\n"
@@ -283,7 +283,7 @@ PyObject* KX_TouchSensor::PySetProperty(PyObject* self,
Py_Return;
}
/* 2. getProperty */
-char KX_TouchSensor::GetProperty_doc[] =
+const char KX_TouchSensor::GetProperty_doc[] =
"getProperty(name)\n"
"\tReturns the property or material to collide with. Use\n"
"\tgetTouchMaterial() to find out whether this sensor\n"
@@ -294,7 +294,7 @@ PyObject* KX_TouchSensor::PyGetProperty(PyObject* self,
return PyString_FromString(m_touchedpropname);
}
-char KX_TouchSensor::GetHitObject_doc[] =
+const char KX_TouchSensor::GetHitObject_doc[] =
"getHitObject()\n"
;
PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self,
@@ -310,7 +310,7 @@ PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self,
Py_Return;
}
-char KX_TouchSensor::GetHitObjectList_doc[] =
+const char KX_TouchSensor::GetHitObjectList_doc[] =
"getHitObjectList()\n"
"\tReturn a list of the objects this object collided with,\n"
"\tbut only those matching the property/material condition.\n";
@@ -364,7 +364,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self,
}
/* 5. getTouchMaterial */
-char KX_TouchSensor::GetTouchMaterial_doc[] =
+const char KX_TouchSensor::GetTouchMaterial_doc[] =
"getTouchMaterial()\n"
"\tReturns KX_TRUE if this sensor looks for a specific material,\n"
"\tKX_FALSE if it looks for a specific property.\n" ;
@@ -376,7 +376,7 @@ PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self,
}
/* 6. setTouchMaterial */
-char KX_TouchSensor::SetTouchMaterial_doc[] =
+const char KX_TouchSensor::SetTouchMaterial_doc[] =
"setTouchMaterial(flag)\n"
"\t- flag: KX_TRUE or KX_FALSE.\n"
"\tSet flag to KX_TRUE to switch on positive pulse mode,\n"
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 67937d5c579..acc4a6ab5d7 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -42,6 +42,8 @@
#include <iostream>
#include "KX_GameObject.h"
+#include "PyObjectPlus.h"
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -454,12 +456,12 @@ PyParentObject KX_TrackToActuator::Parents[] = {
PyMethodDef KX_TrackToActuator::Methods[] = {
- {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, SetObject_doc},
- {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, GetObject_doc},
- {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, SetTime_doc},
- {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, GetTime_doc},
- {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, SetUse3D_doc},
- {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, GetUse3D_doc},
+ {"setObject", (PyCFunction) KX_TrackToActuator::sPySetObject, METH_O, (PY_METHODCHAR)SetObject_doc},
+ {"getObject", (PyCFunction) KX_TrackToActuator::sPyGetObject, METH_VARARGS, (PY_METHODCHAR)GetObject_doc},
+ {"setTime", (PyCFunction) KX_TrackToActuator::sPySetTime, METH_VARARGS, (PY_METHODCHAR)SetTime_doc},
+ {"getTime", (PyCFunction) KX_TrackToActuator::sPyGetTime, METH_VARARGS, (PY_METHODCHAR)GetTime_doc},
+ {"setUse3D", (PyCFunction) KX_TrackToActuator::sPySetUse3D, METH_VARARGS, (PY_METHODCHAR)SetUse3D_doc},
+ {"getUse3D", (PyCFunction) KX_TrackToActuator::sPyGetUse3D, METH_VARARGS, (PY_METHODCHAR)GetUse3D_doc},
{NULL,NULL} //Sentinel
};
@@ -473,7 +475,7 @@ PyObject* KX_TrackToActuator::_getattr(const STR_String& attr)
/* 1. setObject */
-char KX_TrackToActuator::SetObject_doc[] =
+const char KX_TrackToActuator::SetObject_doc[] =
"setObject(object)\n"
"\t- object: KX_GameObject, string or None\n"
"\tSet the object to track with the parent of this actuator.\n";
@@ -497,7 +499,7 @@ PyObject* KX_TrackToActuator::PySetObject(PyObject* self, PyObject* value)
/* 2. getObject */
-char KX_TrackToActuator::GetObject_doc[] =
+const char KX_TrackToActuator::GetObject_doc[] =
"getObject(name_only = 1)\n"
"name_only - optional arg, when true will return the KX_GameObject rather then its name\n"
"\tReturns the object to track with the parent of this actuator\n";
@@ -519,7 +521,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args)
/* 3. setTime */
-char KX_TrackToActuator::SetTime_doc[] =
+const char KX_TrackToActuator::SetTime_doc[] =
"setTime(time)\n"
"\t- time: integer\n"
"\tSet the time in frames with which to delay the tracking motion.\n";
@@ -540,7 +542,7 @@ PyObject* KX_TrackToActuator::PySetTime(PyObject* self, PyObject* args, PyObject
/* 4.getTime */
-char KX_TrackToActuator::GetTime_doc[] =
+const char KX_TrackToActuator::GetTime_doc[] =
"getTime()\n"
"\t- time: integer\n"
"\tReturn the time in frames with which the tracking motion is delayed.\n";
@@ -552,7 +554,7 @@ PyObject* KX_TrackToActuator::PyGetTime(PyObject* self, PyObject* args, PyObject
/* 5. getUse3D */
-char KX_TrackToActuator::GetUse3D_doc[] =
+const char KX_TrackToActuator::GetUse3D_doc[] =
"getUse3D()\n"
"\tReturns 1 if the motion is allowed to extend in the z-direction.\n";
PyObject* KX_TrackToActuator::PyGetUse3D(PyObject* self, PyObject* args, PyObject* kwds)
@@ -563,7 +565,7 @@ PyObject* KX_TrackToActuator::PyGetUse3D(PyObject* self, PyObject* args, PyObjec
/* 6. setUse3D */
-char KX_TrackToActuator::SetUse3D_doc[] =
+const char KX_TrackToActuator::SetUse3D_doc[] =
"setUse3D(value)\n"
"\t- value: 0 or 1\n"
"\tSet to 1 to allow the tracking motion to extend in the z-direction,\n"
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index f5a2b5e02fe..342e71c5093 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -1,6 +1,8 @@
#include <Python.h>
+#include "PyObjectPlus.h"
+
#include "KX_VehicleWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
#include "PHY_IVehicle.h"
diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp
index 5cec65dff1c..25205714308 100644
--- a/source/gameengine/Ketsji/KX_VertexProxy.cpp
+++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp
@@ -82,7 +82,7 @@ PyObject*
KX_VertexProxy::_getattr(const STR_String& attr)
{
if (attr == "XYZ")
- return PyObjectFrom(MT_Vector3(m_vertex->getLocalXYZ()));
+ return PyObjectFrom(MT_Vector3(m_vertex->getXYZ()));
if (attr == "UV")
return PyObjectFrom(MT_Point2(m_vertex->getUV1()));
@@ -102,11 +102,11 @@ KX_VertexProxy::_getattr(const STR_String& attr)
// pos
if (attr == "x")
- return PyFloat_FromDouble(m_vertex->getLocalXYZ()[0]);
+ return PyFloat_FromDouble(m_vertex->getXYZ()[0]);
if (attr == "y")
- return PyFloat_FromDouble(m_vertex->getLocalXYZ()[1]);
+ return PyFloat_FromDouble(m_vertex->getXYZ()[1]);
if (attr == "z")
- return PyFloat_FromDouble(m_vertex->getLocalXYZ()[2]);
+ return PyFloat_FromDouble(m_vertex->getXYZ()[2]);
// Col
if (attr == "r")
@@ -184,7 +184,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue)
{
float val = PyFloat_AsDouble(pyvalue);
// pos
- MT_Point3 pos(m_vertex->getLocalXYZ());
+ MT_Point3 pos(m_vertex->getXYZ());
if (attr == "x")
{
pos.x() = val;
@@ -312,7 +312,7 @@ PyObject* KX_VertexProxy::PyGetXYZ(PyObject*,
PyObject*,
PyObject*)
{
- return PyObjectFrom(MT_Point3(m_vertex->getLocalXYZ()));
+ return PyObjectFrom(MT_Point3(m_vertex->getXYZ()));
}
PyObject* KX_VertexProxy::PySetXYZ(PyObject*,
@@ -426,7 +426,7 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject*,
{
if (PyVecTo(list, vec))
{
- m_vertex->SetFlag((m_vertex->getFlag()|TV_2NDUV));
+ m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV));
m_vertex->SetUnit(unit);
m_vertex->SetUV2(vec);
m_mesh->SetMeshModified(true);
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
index b4693a7a7db..4b0db5a7953 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp
@@ -38,10 +38,12 @@
KX_VisibilityActuator::KX_VisibilityActuator(
SCA_IObject* gameobj,
bool visible,
+ bool recursive,
PyTypeObject* T
)
: SCA_IActuator(gameobj,T),
- m_visible(visible)
+ m_visible(visible),
+ m_recursive(recursive)
{
// intentionally empty
}
@@ -75,10 +77,10 @@ KX_VisibilityActuator::Update()
KX_GameObject *obj = (KX_GameObject*) GetParent();
- obj->SetVisible(m_visible);
- obj->MarkVisible();
+ obj->SetVisible(m_visible, m_recursive);
+ obj->UpdateBuckets(m_recursive);
- return true;
+ return false;
}
/* ------------------------------------------------------------------------- */
@@ -120,7 +122,7 @@ KX_VisibilityActuator::Parents[] = {
PyMethodDef
KX_VisibilityActuator::Methods[] = {
{"set", (PyCFunction) KX_VisibilityActuator::sPySetVisible,
- METH_VARARGS, SetVisible_doc},
+ METH_VARARGS, (PY_METHODCHAR)SetVisible_doc},
{NULL,NULL} //Sentinel
};
@@ -135,7 +137,7 @@ KX_VisibilityActuator::_getattr(
/* set visibility ---------------------------------------------------------- */
-char
+const char
KX_VisibilityActuator::SetVisible_doc[] =
"setVisible(visible?)\n"
"\t - visible? : Make the object visible? (KX_TRUE, KX_FALSE)"
diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h
index 9b4753033fb..d1b85ab998c 100644
--- a/source/gameengine/Ketsji/KX_VisibilityActuator.h
+++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h
@@ -39,12 +39,14 @@ class KX_VisibilityActuator : public SCA_IActuator
/** Make visible? */
bool m_visible;
+ bool m_recursive;
public:
KX_VisibilityActuator(
SCA_IObject* gameobj,
bool visible,
+ bool recursive,
PyTypeObject* T=&Type
);
diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile
index 47a4855b00c..0b48ad8b8c3 100644
--- a/source/gameengine/Ketsji/Makefile
+++ b/source/gameengine/Ketsji/Makefile
@@ -35,10 +35,13 @@ include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
+CPPFLAGS += $(NAN_SDLCFLAGS)
CPPFLAGS += $(OGL_CPPFLAGS)
CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += -I$(OPENGL_HEADERS)
-CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -I../../blender/python
+CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
+CPPFLAGS += -I../../blender/python
+CPPFLAGS += -I../../blender/python/api2_2x
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include
@@ -61,13 +64,9 @@ CPPFLAGS += -I../../blender/blenlib
CPPFLAGS += -I../../blender/include
CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I../../blender/imbuf
+CPPFLAGS += -I../../blender/gpu
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
-
-
###########################
SOURCEDIR = source/gameengine/Ketsji
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index f6f744b199a..02e7aed82a5 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -32,16 +32,13 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #sourc
incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy'
incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include'
incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork'
-incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include'
+incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu'
cflags = []
if env['OURPLATFORM'] == 'win32-vc':
cflags.append('/GR')
cflags.append('/Ox')
-if env['WITH_BF_GLEXT'] == 1:
- env['CPPFLAGS'].append('-DWITH_GLEXT')
-
incs += ' ' + env['BF_SOLID_INC']
incs += ' ' + env['BF_PYTHON_INC']
incs += ' ' + env['BF_SDL_INC']
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h
index d3eb443ed3a..925f5b6686a 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsController.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsController.h
@@ -111,6 +111,8 @@ public:
virtual void calcXform(){}
virtual void SetMargin(float margin) {}
virtual float GetMargin() const {return 0.f;}
+ virtual float GetRadius() const {return 0.f;}
+ virtual void SetRadius(float margin) {}
// clientinfo for raycasts for example
virtual void* getNewClientInfo() { return m_clientInfo;}
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
index a04560aaf09..2e8ee31058f 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp
@@ -198,7 +198,7 @@ int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
}
-void ODEPhysicsEnvironment::removeConstraint(int constraintid)
+void ODEPhysicsEnvironment::removeConstraint(void *constraintid)
{
if (constraintid)
{
@@ -206,8 +206,7 @@ void ODEPhysicsEnvironment::removeConstraint(int constraintid)
}
}
-PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
+PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
{
//m_OdeWorld
diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
index 7c61902f8e2..dcc87d614c0 100644
--- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
+++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h
@@ -54,8 +54,7 @@ public:
float axisX,float axisY,float axisZ);
virtual void removeConstraint(void * constraintid);
- virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt
index b610fd1bbb0..6c733786caf 100644
--- a/source/gameengine/Physics/Bullet/CMakeLists.txt
+++ b/source/gameengine/Physics/Bullet/CMakeLists.txt
@@ -30,6 +30,10 @@ SET(INC
.
../common
../../../../extern/bullet2/src
+ ../../../../intern/moto/include
+ ../../../kernel/gen_system
+ ../../../../intern/string
+ ../../Rasterizer
)
BLENDERLIB(bf_bullet "${SRC}" "${INC}")
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
index b872fae6138..c9c30c1b450 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
@@ -15,10 +15,18 @@ subject to the following restrictions:
#include "CcdPhysicsController.h"
#include "btBulletDynamicsCommon.h"
-
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
#include "PHY_IMotionState.h"
#include "CcdPhysicsEnvironment.h"
+#include "RAS_MeshObject.h"
+#include "BulletSoftBody/btSoftBody.h"
+#include "BulletSoftBody//btSoftBodyInternals.h"
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+#include "LinearMath/btConvexHull.h"
+#include "BulletCollision/Gimpact/btGImpactShape.h"
+
+#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
class BP_Proxy;
@@ -40,22 +48,36 @@ btVector3 startVel(0,0,0);//-10000);
CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
:m_cci(ci)
{
+ m_prototypeTransformInitialized = false;
+ m_softbodyMappingDone = false;
m_collisionDelay = 0;
m_newClientInfo = 0;
m_registerCount = 0;
-
+ m_softBodyTransformInitialized = false;
+ m_parentCtrl = 0;
+ // copy pointers locally to allow smart release
m_MotionState = ci.m_MotionState;
+ m_collisionShape = ci.m_collisionShape;
+ // apply scaling before creating rigid body
+ m_collisionShape->setLocalScaling(m_cci.m_scaling);
+ if (m_cci.m_mass)
+ m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+ // shape info is shared, increment ref count
+ m_shapeInfo = ci.m_shapeInfo;
+ if (m_shapeInfo)
+ m_shapeInfo->AddRef();
+
m_bulletMotionState = 0;
CreateRigidbody();
-
- #ifdef WIN32
- if (m_body->getInvMass())
- m_body->setLinearVelocity(startVel);
- #endif
+///???
+#ifdef WIN32
+ if (GetRigidBody() && !GetRigidBody()->isStaticObject())
+ GetRigidBody()->setLinearVelocity(startVel);
+#endif
}
@@ -107,20 +129,351 @@ public:
};
-void CcdPhysicsController::CreateRigidbody()
+btRigidBody* CcdPhysicsController::GetRigidBody()
+{
+ return btRigidBody::upcast(m_object);
+}
+btCollisionObject* CcdPhysicsController::GetCollisionObject()
+{
+ return m_object;
+}
+btSoftBody* CcdPhysicsController::GetSoftBody()
{
+ return btSoftBody::upcast(m_object);
+}
+
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+
- btTransform trans = GetTransformFromMotionState(m_MotionState);
+void CcdPhysicsController::CreateRigidbody()
+{
+
+ //btTransform trans = GetTransformFromMotionState(m_MotionState);
m_bulletMotionState = new BlenderBulletMotionState(m_MotionState);
- m_body = new btRigidBody(m_cci.m_mass,
- m_bulletMotionState,
- m_cci.m_collisionShape,
- m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor,
- m_cci.m_linearDamping,m_cci.m_angularDamping,
- m_cci.m_friction,m_cci.m_restitution);
+ ///either create a btCollisionObject, btRigidBody or btSoftBody
+
+ //create a collision object
+
+ int shapeType = m_cci.m_collisionShape ? m_cci.m_collisionShape->getShapeType() : 0;
+
+ //disable soft body until first sneak preview is ready
+ if (m_cci.m_bSoft && m_cci.m_collisionShape &&
+ (shapeType == CONVEX_HULL_SHAPE_PROXYTYPE)|
+ (shapeType == TRIANGLE_MESH_SHAPE_PROXYTYPE) |
+ (shapeType == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE))
+ {
+ btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+ rbci.m_linearDamping = m_cci.m_linearDamping;
+ rbci.m_angularDamping = m_cci.m_angularDamping;
+ rbci.m_friction = m_cci.m_friction;
+ rbci.m_restitution = m_cci.m_restitution;
+
+
+ int nodecount = 0;
+
+ int numtriangles = 1;
+
+ btVector3 p(0,0,0);// = getOrigin();
+ btScalar h = 1.f;
+
+ btSoftRigidDynamicsWorld* softDynaWorld = (btSoftRigidDynamicsWorld*)m_cci.m_physicsEnv->getDynamicsWorld();
+
+ PHY__Vector3 grav;
+ grav[0] = softDynaWorld->getGravity().getX();
+ grav[1] = softDynaWorld->getGravity().getY();
+ grav[2] = softDynaWorld->getGravity().getZ();
+ softDynaWorld->getWorldInfo().m_gravity.setValue(grav[0],grav[1],grav[2]); //??
+
+
+ //btSoftBody* psb=btSoftBodyHelpers::CreateRope(sbi, btVector3(-10,0,i*0.25),btVector3(10,0,i*0.25), 16,1+2);
+
+ btSoftBody* psb = 0;
+
+ if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE)
+ {
+ btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape;
+
+ //psb = btSoftBodyHelpers::CreateFromConvexHull(sbi,&transformedVertices[0],convexHull->getNumPoints());
+
+ {
+ int nvertices = convexHull->getNumPoints();
+ const btVector3* vertices = convexHull->getPoints();
+ btSoftBodyWorldInfo& worldInfo = softDynaWorld->getWorldInfo();
+
+ HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
+ HullResult hres;
+ HullLibrary hlib;/*??*/
+ hdsc.mMaxVertices=nvertices;
+ hlib.CreateConvexHull(hdsc,hres);
+
+ psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
+ &hres.m_OutputVertices[0],0);
+ for(int i=0;i<(int)hres.mNumFaces;++i)
+ {
+ const int idx[]={ hres.m_Indices[i*3+0],
+ hres.m_Indices[i*3+1],
+ hres.m_Indices[i*3+2]};
+ if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
+ if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
+ if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
+ psb->appendFace(idx[0],idx[1],idx[2]);
+ }
+
+
+
+ hlib.ReleaseResult(hres);
+
+
+ }
+
+
+
+
+
+
+ } else
+ {
+
+ btSoftBodyWorldInfo& sbi= softDynaWorld->getWorldInfo();
+
+ if (m_cci.m_collisionShape->getShapeType() ==SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ btScaledBvhTriangleMeshShape* scaledtrimeshshape = (btScaledBvhTriangleMeshShape*) m_cci.m_collisionShape;
+ btBvhTriangleMeshShape* trimeshshape = scaledtrimeshshape->getChildShape();
+
+ ///only deal with meshes that have 1 sub part/component, for now
+ if (trimeshshape->getMeshInterface()->getNumSubParts()==1)
+ {
+ unsigned char* vertexBase;
+ PHY_ScalarType vertexType;
+ int numverts;
+ int vertexstride;
+ unsigned char* indexbase;
+ int indexstride;
+ int numtris;
+ PHY_ScalarType indexType;
+ trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType);
+
+ psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,(const btScalar*)vertexBase,(const int*)indexbase,numtris);
+ }
+ } else
+ {
+ btBvhTriangleMeshShape* trimeshshape = (btBvhTriangleMeshShape*) m_cci.m_collisionShape;
+ ///only deal with meshes that have 1 sub part/component, for now
+ if (trimeshshape->getMeshInterface()->getNumSubParts()==1)
+ {
+ unsigned char* vertexBase;
+ PHY_ScalarType vertexType;
+ int numverts;
+ int vertexstride;
+ unsigned char* indexbase;
+ int indexstride;
+ int numtris;
+ PHY_ScalarType indexType;
+ trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType);
+
+ psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,(const btScalar*)vertexBase,(const int*)indexbase,numtris);
+ }
+
+
+ //psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,&pts[0].getX(),triangles,numtriangles);
+ }
+
+ }
+
+
+
+ m_object = psb;
+
+ //psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS;
+
+ //psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::VF_SS;//CL_SS;
+
+
+ //btSoftBody::Material* pm=psb->appendMaterial();
+ btSoftBody::Material* pm=psb->m_materials[0];
+ pm->m_kLST = m_cci.m_soft_linStiff;
+ pm->m_kAST = m_cci.m_soft_angStiff;
+ pm->m_kVST = m_cci.m_soft_volume;
+ psb->m_cfg.collisions = 0;
+
+ if (m_cci.m_soft_collisionflags & CCD_BSB_COL_CL_RS)
+ {
+ psb->m_cfg.collisions += btSoftBody::fCollision::CL_RS;
+ } else
+ {
+ psb->m_cfg.collisions += btSoftBody::fCollision::SDF_RS;
+ }
+ if (m_cci.m_soft_collisionflags & CCD_BSB_COL_CL_SS)
+ {
+ psb->m_cfg.collisions += btSoftBody::fCollision::CL_SS;
+ } else
+ {
+ psb->m_cfg.collisions += btSoftBody::fCollision::VF_SS;
+ }
+
+
+ psb->m_cfg.kSRHR_CL = m_cci.m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
+ psb->m_cfg.kSKHR_CL = m_cci.m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
+ psb->m_cfg.kSSHR_CL = m_cci.m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
+ psb->m_cfg.kSR_SPLT_CL = m_cci.m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+
+ psb->m_cfg.kSK_SPLT_CL = m_cci.m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ psb->m_cfg.kSS_SPLT_CL = m_cci.m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ psb->m_cfg.kVCF = m_cci.m_soft_kVCF; /* Velocities correction factor (Baumgarte) */
+ psb->m_cfg.kDP = m_cci.m_soft_kDP; /* Damping coefficient [0,1] */
+
+ psb->m_cfg.kDG = m_cci.m_soft_kDG; /* Drag coefficient [0,+inf] */
+ psb->m_cfg.kLF = m_cci.m_soft_kLF; /* Lift coefficient [0,+inf] */
+ psb->m_cfg.kPR = m_cci.m_soft_kPR; /* Pressure coefficient [-inf,+inf] */
+ psb->m_cfg.kVC = m_cci.m_soft_kVC; /* Volume conversation coefficient [0,+inf] */
+
+ psb->m_cfg.kDF = m_cci.m_soft_kDF; /* Dynamic friction coefficient [0,1] */
+ psb->m_cfg.kMT = m_cci.m_soft_kMT; /* Pose matching coefficient [0,1] */
+ psb->m_cfg.kCHR = m_cci.m_soft_kCHR; /* Rigid contacts hardness [0,1] */
+ psb->m_cfg.kKHR = m_cci.m_soft_kKHR; /* Kinetic contacts hardness [0,1] */
+
+ psb->m_cfg.kSHR = m_cci.m_soft_kSHR; /* Soft contacts hardness [0,1] */
+ psb->m_cfg.kAHR = m_cci.m_soft_kAHR; /* Anchors hardness [0,1] */
+
+
+ if (m_cci.m_gamesoftFlag & CCD_BSB_BENDING_CONSTRAINTS)//OB_SB_GOAL)
+ {
+ psb->generateBendingConstraints(2,pm);
+ }
+
+ psb->m_cfg.piterations = m_cci.m_soft_piterations;
+ psb->m_cfg.viterations = m_cci.m_soft_viterations;
+ psb->m_cfg.diterations = m_cci.m_soft_diterations;
+ psb->m_cfg.citerations = m_cci.m_soft_citerations;
+
+ if (m_cci.m_gamesoftFlag & CCD_BSB_SHAPE_MATCHING)//OB_SB_GOAL)
+ {
+ psb->setPose(false,true);//
+ } else
+ {
+ psb->setPose(true,false);
+ }
+
+
+
+ psb->randomizeConstraints();
+
+ if (m_cci.m_soft_collisionflags & (CCD_BSB_COL_CL_RS+CCD_BSB_COL_CL_SS))
+ {
+ psb->generateClusters(m_cci.m_soft_numclusteriterations);
+ }
+
+// psb->activate();
+// psb->setActivationState(1);
+// psb->setDeactivationTime(1.f);
+
+ //psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9;
+ psb->setTotalMass(m_cci.m_mass);
+
+ psb->setCollisionFlags(0);
+
+ ///create a mapping between graphics mesh vertices and soft body vertices
+ {
+ RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh();
+
+ if (rasMesh && !m_softbodyMappingDone)
+ {
+
+ //printf("apply\n");
+ RAS_MeshSlot::iterator it;
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ size_t i;
+
+ //for each material
+ for (int m=0;m<rasMesh->NumMaterials();m++)
+ {
+ // The vertex cache can only be updated for this deformer:
+ // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
+ // share the same mesh (=the same cache). As the rendering is done per polymaterial
+ // cycling through the objects, the entire mesh cache cannot be updated in one shot.
+ mmat = rasMesh->GetMeshMaterial(m);
+
+ slot = mmat->m_baseslot;
+ for(slot->begin(it); !slot->end(it); slot->next(it))
+ {
+ int index = 0;
+ for(i=it.startvertex; i<it.endvertex; i++,index++)
+ {
+ RAS_TexVert* vertex = &it.vertex[i];
+
+
+ //search closest index, and store it in vertex
+ vertex->setSoftBodyIndex(0);
+ btScalar maxDistSqr = 1e30;
+ btSoftBody::tNodeArray& nodes(psb->m_nodes);
+ btVector3 xyz = btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]);
+ for (int n=0;n<nodes.size();n++)
+ {
+ btScalar distSqr = (nodes[n].m_x - xyz).length2();
+ if (distSqr<maxDistSqr)
+ {
+ maxDistSqr = distSqr;
+
+ vertex->setSoftBodyIndex(n);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_softbodyMappingDone = true;
+
+
+
+
+
+
+// m_object->setCollisionShape(rbci.m_collisionShape);
+ btTransform startTrans;
+
+ if (rbci.m_motionState)
+ {
+ rbci.m_motionState->getWorldTransform(startTrans);
+ } else
+ {
+ startTrans = rbci.m_startWorldTransform;
+ }
+ //startTrans.setIdentity();
+
+ //m_object->setWorldTransform(startTrans);
+ //m_object->setInterpolationWorldTransform(startTrans);
+ m_MotionState->setWorldPosition(startTrans.getOrigin().getX(),startTrans.getOrigin().getY(),startTrans.getOrigin().getZ());
+ m_MotionState->setWorldOrientation(0,0,0,1);
+
+ if (!m_prototypeTransformInitialized)
+ {
+ m_prototypeTransformInitialized = true;
+ m_softBodyTransformInitialized = true;
+ GetSoftBody()->transform(startTrans);
+ }
+
+// btVector3 wp = m_softBody->getWorldTransform().getOrigin();
+// MT_Point3 center(wp.getX(),wp.getY(),wp.getZ());
+// m_gameobj->NodeSetWorldPosition(center);
+
+
+ } else
+ {
+ btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+ rbci.m_linearDamping = m_cci.m_linearDamping;
+ rbci.m_angularDamping = m_cci.m_angularDamping;
+ rbci.m_friction = m_cci.m_friction;
+ rbci.m_restitution = m_cci.m_restitution;
+ m_object = new btRigidBody(rbci);
+ }
+
//
// init the rigidbody properly
//
@@ -132,16 +485,39 @@ void CcdPhysicsController::CreateRigidbody()
if ((m_cci.m_collisionFilterGroup & CcdConstructionInfo::SensorFilter) != 0)
{
// reset the flags that have been set so far
- m_body->setCollisionFlags(0);
+ GetCollisionObject()->setCollisionFlags(0);
}
- m_body->setCollisionFlags(m_body->getCollisionFlags() | m_cci.m_collisionFlags);
- m_body->setGravity( m_cci.m_gravity);
- m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping);
+ GetCollisionObject()->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags);
+ btRigidBody* body = GetRigidBody();
+
+ if (body)
+ {
+ body->setGravity( m_cci.m_gravity);
+ body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping);
+
+ if (!m_cci.m_bRigid)
+ {
+ body->setAngularFactor(0.f);
+ }
+ }
+ if (m_object && m_cci.m_do_anisotropic)
+ {
+ m_object->setAnisotropicFriction(m_cci.m_anisotropicFriction);
+ }
+
+}
- if (!m_cci.m_bRigid)
+static void DeleteBulletShape(btCollisionShape* shape)
+{
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
- m_body->setAngularFactor(0.f);
+ // shapes based on meshes use an interface that contains the vertices.
+ btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape);
+ btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
+ if (meshInterface)
+ delete meshInterface;
}
+ delete shape;
}
CcdPhysicsController::~CcdPhysicsController()
@@ -154,7 +530,28 @@ CcdPhysicsController::~CcdPhysicsController()
delete m_MotionState;
if (m_bulletMotionState)
delete m_bulletMotionState;
- delete m_body;
+ delete m_object;
+
+ if (m_collisionShape)
+ {
+ // collision shape is always unique to the controller, can delete it here
+ if (m_collisionShape->isCompound())
+ {
+ // bullet does not delete the child shape, must do it here
+ btCompoundShape* compoundShape = (btCompoundShape*)m_collisionShape;
+ int numChild = compoundShape->getNumChildShapes();
+ for (int i=numChild-1 ; i >= 0; i--)
+ {
+ btCollisionShape* childShape = compoundShape->getChildShape(i);
+ DeleteBulletShape(childShape);
+ }
+ }
+ DeleteBulletShape(m_collisionShape);
+ }
+ if (m_shapeInfo)
+ {
+ m_shapeInfo->Release();
+ }
}
@@ -165,12 +562,26 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
{
//sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.)
- if (!m_body->isStaticObject())
+ btSoftBody* sb = GetSoftBody();
+ if (sb)
{
- const btVector3& worldPos = m_body->getCenterOfMassPosition();
+ btVector3 aabbMin,aabbMax;
+ sb->getAabb(aabbMin,aabbMax);
+ btVector3 worldPos = (aabbMax+aabbMin)*0.5f;
+ m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
+ m_MotionState->calculateWorldTransformations();
+ return true;
+ }
+
+ btRigidBody* body = GetRigidBody();
+
+ if (body && !body->isStaticObject())
+ {
+
+ const btVector3& worldPos = body->getCenterOfMassPosition();
m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
- const btQuaternion& worldquat = m_body->getOrientation();
+ const btQuaternion& worldquat = body->getOrientation();
m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
m_MotionState->calculateWorldTransformations();
@@ -189,7 +600,7 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time)
btTransform oldTrans = m_body->getCenterOfMassTransform();
btTransform newTrans(worldquat,worldPos);
- m_body->setCenterOfMassTransform(newTrans);
+ SetCenterOfMassTransform(newTrans);
//need to keep track of previous position for friction effects...
m_MotionState->calculateWorldTransformations();
@@ -217,13 +628,41 @@ void CcdPhysicsController::WriteDynamicsToMotionState()
// controller replication
void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
{
+
+ m_softBodyTransformInitialized=false;
m_MotionState = motionstate;
m_registerCount = 0;
-
+ m_collisionShape = NULL;
- m_body = 0;
+ // always create a new shape to avoid scaling bug
+ if (m_shapeInfo)
+ {
+ m_shapeInfo->AddRef();
+ m_collisionShape = m_shapeInfo->CreateBulletShape();
+
+ if (m_collisionShape)
+ {
+ // new shape has no scaling, apply initial scaling
+ m_collisionShape->setMargin(m_cci.m_margin);
+ m_collisionShape->setLocalScaling(m_cci.m_scaling);
+
+ if (m_cci.m_mass)
+ m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+ }
+ }
+
+ m_object = 0;
CreateRigidbody();
-
+
+ btRigidBody* body = GetRigidBody();
+
+ if (body)
+ {
+ if (m_cci.m_mass)
+ {
+ body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+ }
+ }
m_cci.m_physicsEnv->addCcdPhysicsController(this);
@@ -259,40 +698,75 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta
}
+
+void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform)
+{
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ body->setCenterOfMassTransform(xform);
+ } else
+ {
+ //either collision object or soft body?
+ if (GetSoftBody())
+ {
+
+ } else
+ {
+
+ if (m_object->isStaticOrKinematicObject())
+ {
+ m_object->setInterpolationWorldTransform(m_object->getWorldTransform());
+ } else
+ {
+ m_object->setInterpolationWorldTransform(xform);
+ }
+ if (body)
+ {
+ body->setInterpolationLinearVelocity(body->getLinearVelocity());
+ body->setInterpolationAngularVelocity(body->getAngularVelocity());
+ body->updateInertiaTensor();
+ }
+ m_object->setWorldTransform(xform);
+ }
+ }
+}
+
// kinematic methods
void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
{
- if (m_body)
+ if (m_object)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
+ btRigidBody* body = GetRigidBody();
btVector3 dloc(dlocX,dlocY,dlocZ);
- btTransform xform = m_body->getCenterOfMassTransform();
-
+ btTransform xform = m_object->getWorldTransform();
+
if (local)
{
dloc = xform.getBasis()*dloc;
}
xform.setOrigin(xform.getOrigin() + dloc);
- m_body->setCenterOfMassTransform(xform);
+ SetCenterOfMassTransform(xform);
}
}
void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local)
{
- if (m_body)
+ if (m_object)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
btMatrix3x3 drotmat( rotval[0],rotval[4],rotval[8],
@@ -303,16 +777,16 @@ void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local)
btMatrix3x3 currentOrn;
GetWorldOrientation(currentOrn);
- btTransform xform = m_body->getCenterOfMassTransform();
-
+ btTransform xform = m_object->getWorldTransform();
+
xform.setBasis(xform.getBasis()*(local ?
drotmat : (currentOrn.inverse() * drotmat * currentOrn)));
- m_body->setCenterOfMassTransform(xform);
+ SetCenterOfMassTransform(xform);
}
-
}
+
void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat)
{
float orn[4];
@@ -323,7 +797,7 @@ void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat)
void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
{
- btQuaternion q = m_body->getCenterOfMassTransform().getRotation();
+ btQuaternion q = m_object->getWorldTransform().getRotation();
quatImag0 = q[0];
quatImag1 = q[1];
quatImag2 = q[2];
@@ -331,58 +805,72 @@ void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,flo
}
void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
{
- if (m_body)
+ if (m_object)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
// not required
//m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal));
- m_body->setCenterOfMassTransform(xform);
+ SetCenterOfMassTransform(xform);
// not required
//m_bulletMotionState->setWorldTransform(xform);
+
+
+
}
}
void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn)
{
- if (m_body)
+ if (m_object)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
// not required
//m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
xform.setBasis(orn);
- m_body->setCenterOfMassTransform(xform);
+ SetCenterOfMassTransform(xform);
// not required
//m_bulletMotionState->setWorldTransform(xform);
+ //only once!
+ if (!m_softBodyTransformInitialized && GetSoftBody())
+ {
+ m_softbodyStartTrans.setBasis(orn);
+ xform.setOrigin(m_softbodyStartTrans.getOrigin());
+ GetSoftBody()->transform(xform);
+ m_softBodyTransformInitialized = true;
+ }
+
}
}
void CcdPhysicsController::setPosition(float posX,float posY,float posZ)
{
- if (m_body)
+ if (m_object)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
// not required, this function is only used to update the physic controller
//m_MotionState->setWorldPosition(posX,posY,posZ);
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
xform.setOrigin(btVector3(posX,posY,posZ));
- m_body->setCenterOfMassTransform(xform);
+ SetCenterOfMassTransform(xform);
+ if (!m_softBodyTransformInitialized)
+ m_softbodyStartTrans.setOrigin(xform.getOrigin());
// not required
//m_bulletMotionState->setWorldTransform(xform);
}
@@ -395,7 +883,7 @@ void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvel
void CcdPhysicsController::getPosition(PHY__Vector3& pos) const
{
- const btTransform& xform = m_body->getCenterOfMassTransform();
+ const btTransform& xform = m_object->getWorldTransform();
pos[0] = xform.getOrigin().x();
pos[1] = xform.getOrigin().y();
pos[2] = xform.getOrigin().z();
@@ -409,15 +897,16 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
{
m_cci.m_scaling = btVector3(scaleX,scaleY,scaleZ);
- if (m_body && m_body->getCollisionShape())
+ if (m_object && m_object->getCollisionShape())
{
- m_body->getCollisionShape()->setLocalScaling(m_cci.m_scaling);
+ m_object->getCollisionShape()->setLocalScaling(m_cci.m_scaling);
//printf("no inertia recalc for fixed objects with mass=0\n");
- if (m_cci.m_mass)
+ btRigidBody* body = GetRigidBody();
+ if (body && m_cci.m_mass)
{
- m_body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
- m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
+ body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
+ body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
}
}
@@ -428,19 +917,23 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
{
btVector3 torque(torqueX,torqueY,torqueZ);
- btTransform xform = m_body->getCenterOfMassTransform();
- if (m_body && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+ btTransform xform = m_object->getWorldTransform();
+
+
+ if (m_object && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON))
{
- m_body->activate();
- if (m_body->isStaticObject())
+ btRigidBody* body = GetRigidBody();
+ m_object->activate();
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
if (local)
{
torque = xform.getBasis()*torque;
}
- m_body->applyTorque(torque);
+ if (body)
+ body->applyTorque(torque);
}
}
@@ -448,41 +941,57 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo
{
btVector3 force(forceX,forceY,forceZ);
- if (m_body && force.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+
+ if (m_object && force.length2() > (SIMD_EPSILON*SIMD_EPSILON))
{
- m_body->activate();
- if (m_body->isStaticObject())
+ m_object->activate();
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
+
{
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
+
if (local)
{
force = xform.getBasis()*force;
}
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ body->applyCentralForce(force);
+ btSoftBody* soft = GetSoftBody();
+ if (soft)
+ {
+ // the force is applied on each node, must reduce it in the same extend
+ if (soft->m_nodes.size() > 0)
+ force /= soft->m_nodes.size();
+ soft->addForce(force);
+ }
}
- m_body->applyCentralForce(force);
}
}
void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
{
btVector3 angvel(ang_velX,ang_velY,ang_velZ);
- if (m_body && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+ if (m_object && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
- }
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ } else
{
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
if (local)
{
angvel = xform.getBasis()*angvel;
}
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ body->setAngularVelocity(angvel);
+
}
- m_body->setAngularVelocity(angvel);
}
}
@@ -490,39 +999,53 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa
{
btVector3 linVel(lin_velX,lin_velY,lin_velZ);
- if (m_body && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+ if (m_object/* && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)*/)
{
- m_body->activate(true);
- if (m_body->isStaticObject())
+ m_object->activate(true);
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ return;
}
-
+
+ btSoftBody* soft = GetSoftBody();
+ if (soft)
+ {
+ if (local)
+ {
+ linVel = m_softbodyStartTrans.getBasis()*linVel;
+ }
+ soft->setVelocity(linVel);
+ } else
{
- btTransform xform = m_body->getCenterOfMassTransform();
+ btTransform xform = m_object->getWorldTransform();
if (local)
{
linVel = xform.getBasis()*linVel;
}
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ body->setLinearVelocity(linVel);
}
- m_body->setLinearVelocity(linVel);
}
}
void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
{
btVector3 impulse(impulseX,impulseY,impulseZ);
- if (m_body && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
+ if (m_object && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
{
- m_body->activate();
- if (m_body->isStaticObject())
+ m_object->activate();
+ if (m_object->isStaticObject())
{
- m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+ m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
}
btVector3 pos(attachX,attachY,attachZ);
-
- m_body->applyImpulse(impulse,pos);
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ body->applyImpulse(impulse,pos);
+
}
}
@@ -532,29 +1055,55 @@ void CcdPhysicsController::SetActive(bool active)
// reading out information from physics
void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
{
- const btVector3& linvel = this->m_body->getLinearVelocity();
- linvX = linvel.x();
- linvY = linvel.y();
- linvZ = linvel.z();
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ const btVector3& linvel = body->getLinearVelocity();
+ linvX = linvel.x();
+ linvY = linvel.y();
+ linvZ = linvel.z();
+ } else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+ }
}
void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ)
{
- const btVector3& angvel= m_body->getAngularVelocity();
- angVelX = angvel.x();
- angVelY = angvel.y();
- angVelZ = angvel.z();
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ const btVector3& angvel= body->getAngularVelocity();
+ angVelX = angvel.x();
+ angVelY = angvel.y();
+ angVelZ = angvel.z();
+ } else
+ {
+ angVelX = 0.f;
+ angVelY = 0.f;
+ angVelZ = 0.f;
+ }
}
void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
{
btVector3 pos(posX,posY,posZ);
- btVector3 rel_pos = pos-m_body->getCenterOfMassPosition();
- btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos);
- linvX = linvel.x();
- linvY = linvel.y();
- linvZ = linvel.z();
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ btVector3 linvel = body->getVelocityInLocalPoint(pos);
+ linvX = linvel.x();
+ linvY = linvel.y();
+ linvZ = linvel.z();
+ } else
+ {
+ linvX = 0.f;
+ linvY = 0.f;
+ linvZ = 0.f;
+ }
}
void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
{
@@ -565,11 +1114,15 @@ void CcdPhysicsController::setRigidBody(bool rigid)
{
if (!rigid)
{
- //fake it for now
- btVector3 inertia = m_body->getInvInertiaDiagLocal();
- inertia[1] = 0.f;
- m_body->setInvInertiaDiagLocal(inertia);
- m_body->updateInertiaTensor();
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ //fake it for now
+ btVector3 inertia = body->getInvInertiaDiagLocal();
+ inertia[1] = 0.f;
+ body->setInvInertiaDiagLocal(inertia);
+ body->updateInertiaTensor();
+ }
}
}
@@ -586,40 +1139,52 @@ void CcdPhysicsController::setNewClientInfo(void* clientinfo)
void CcdPhysicsController::UpdateDeactivation(float timeStep)
{
- m_body->updateDeactivation( timeStep);
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ body->updateDeactivation( timeStep);
+ }
}
bool CcdPhysicsController::wantsSleeping()
{
-
- return m_body->wantsSleeping();
+ btRigidBody* body = GetRigidBody();
+ if (body)
+ {
+ return body->wantsSleeping();
+ }
+ //check it out
+ return true;
}
PHY_IPhysicsController* CcdPhysicsController::GetReplica()
{
- //very experimental, shape sharing is not implemented yet.
- //just support btSphereShape/ConeShape for now
-
+ // This is used only to replicate Near and Radar sensor controllers
+ // The replication of object physics controller is done in KX_BulletPhysicsController::GetReplica()
CcdConstructionInfo cinfo = m_cci;
- if (cinfo.m_collisionShape)
+ if (m_shapeInfo)
+ {
+ // This situation does not normally happen
+ cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape();
+ }
+ else if (m_collisionShape)
{
- switch (cinfo.m_collisionShape->getShapeType())
+ switch (m_collisionShape->getShapeType())
{
case SPHERE_SHAPE_PROXYTYPE:
{
- btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
+ btSphereShape* orgShape = (btSphereShape*)m_collisionShape;
cinfo.m_collisionShape = new btSphereShape(*orgShape);
break;
}
- case CONE_SHAPE_PROXYTYPE:
+ case CONE_SHAPE_PROXYTYPE:
{
- btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
+ btConeShape* orgShape = (btConeShape*)m_collisionShape;
cinfo.m_collisionShape = new btConeShape(*orgShape);
break;
}
-
default:
{
return 0;
@@ -628,6 +1193,7 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplica()
}
cinfo.m_MotionState = new DefaultMotionState();
+ cinfo.m_shapeInfo = m_shapeInfo;
CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
return replica;
@@ -689,3 +1255,273 @@ void DefaultMotionState::calculateWorldTransformations()
}
+// Shape constructor
+std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> CcdShapeConstructionInfo::m_meshShapeMap;
+
+CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, bool polytope)
+{
+ if (polytope)
+ // not yet supported
+ return NULL;
+
+ std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::const_iterator mit = m_meshShapeMap.find(mesh);
+ if (mit != m_meshShapeMap.end())
+ return mit->second;
+ return NULL;
+}
+
+bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact)
+{
+ m_useGimpact = useGimpact;
+
+ // assume no shape information
+ // no support for dynamic change of shape yet
+ assert(m_meshObject == NULL);
+ m_shapeType = PHY_SHAPE_NONE;
+ m_vertexArray.clear();
+ m_polygonIndexArray.clear();
+ m_meshObject = NULL;
+
+ if (!meshobj)
+ return false;
+
+ // Mesh has no polygons!
+ int numpolys = meshobj->NumPolygons();
+ if (!numpolys)
+ {
+ return false;
+ }
+
+ // check that we have at least one colliding polygon
+ int numvalidpolys = 0;
+
+ for (int p=0; p<numpolys; p++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ numvalidpolys++;
+ break;
+ }
+ }
+
+ // No collision polygons
+ if (numvalidpolys < 1)
+ return false;
+
+ m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH;
+
+ numvalidpolys = 0;
+
+ for (int p2=0; p2<numpolys; p2++)
+ {
+ RAS_Polygon* poly = meshobj->GetPolygon(p2);
+
+ // only add polygons that have the collisionflag set
+ if (poly->IsCollider())
+ {
+ //Bullet can raycast any shape, so
+ if (polytope)
+ {
+ for (int i=0;i<poly->VertexCount();i++)
+ {
+ const float* vtx = poly->GetVertex(i)->getXYZ();
+ btPoint3 point(vtx[0],vtx[1],vtx[2]);
+ //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare)
+ bool found = false;
+ for (int j=0;j<m_vertexArray.size();j++)
+ {
+ if (m_vertexArray[j]==point)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ m_vertexArray.push_back(point);
+
+ numvalidpolys++;
+ }
+ } else
+ {
+ {
+ const float* vtx = poly->GetVertex(2)->getXYZ();
+ btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+
+ vtx = poly->GetVertex(1)->getXYZ();
+ btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+
+ vtx = poly->GetVertex(0)->getXYZ();
+ btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+
+ m_vertexArray.push_back(vertex0);
+ m_vertexArray.push_back(vertex1);
+ m_vertexArray.push_back(vertex2);
+ m_polygonIndexArray.push_back(p2);
+ numvalidpolys++;
+ }
+ if (poly->VertexCount() == 4)
+ {
+ const float* vtx = poly->GetVertex(3)->getXYZ();
+ btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
+
+ vtx = poly->GetVertex(2)->getXYZ();
+ btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
+
+ vtx = poly->GetVertex(0)->getXYZ();
+ btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
+
+ m_vertexArray.push_back(vertex0);
+ m_vertexArray.push_back(vertex1);
+ m_vertexArray.push_back(vertex2);
+ m_polygonIndexArray.push_back(p2);
+ numvalidpolys++;
+ }
+ }
+ }
+ }
+
+ if (!numvalidpolys)
+ {
+ // should not happen
+ m_shapeType = PHY_SHAPE_NONE;
+ return false;
+ }
+ m_meshObject = meshobj;
+ if (!polytope)
+ {
+ // triangle shape can be shared, store the mesh object in the map
+ m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this));
+ }
+ return true;
+}
+
+btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape()
+{
+ btCollisionShape* collisionShape = 0;
+ btTriangleMeshShape* concaveShape = 0;
+ btTriangleMesh* collisionMeshData = 0;
+ btCompoundShape* compoundShape = 0;
+ CcdShapeConstructionInfo* nextShapeInfo;
+
+ switch (m_shapeType)
+ {
+ case PHY_SHAPE_NONE:
+ break;
+
+ case PHY_SHAPE_BOX:
+ collisionShape = new btBoxShape(m_halfExtend);
+ break;
+
+ case PHY_SHAPE_SPHERE:
+ collisionShape = new btSphereShape(m_radius);
+ break;
+
+ case PHY_SHAPE_CYLINDER:
+ collisionShape = new btCylinderShapeZ(m_halfExtend);
+ break;
+
+ case PHY_SHAPE_CONE:
+ collisionShape = new btConeShapeZ(m_radius, m_height);
+ break;
+
+ case PHY_SHAPE_POLYTOPE:
+ collisionShape = new btConvexHullShape(&m_vertexArray.begin()->getX(), m_vertexArray.size());
+ break;
+
+ case PHY_SHAPE_MESH:
+ // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of
+ // triangle mesh information between duplicates => drastic performance increase when
+ // duplicating complex mesh objects.
+ // BUT it causes a small performance decrease when sharing is not required:
+ // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering
+ // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1
+ // and btScaledBvhTriangleMeshShape otherwise.
+ if (m_useGimpact)
+ {
+ collisionMeshData = new btTriangleMesh();
+
+
+ // m_vertexArray is necessarily a multiple of 3
+ for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); )
+ {
+ collisionMeshData->addTriangle(*it++,*it++,*it++);
+ }
+ btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData);
+
+ collisionShape = gimpactShape;
+ gimpactShape->updateBound();
+
+ } else
+ {
+ if (!m_unscaledShape)
+ {
+ collisionMeshData = new btTriangleMesh(true,false);
+ collisionMeshData->m_weldingThreshold = m_weldingThreshold;
+
+ // m_vertexArray is necessarily a multiple of 3
+ for (std::vector<btPoint3>::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); )
+ {
+ collisionMeshData->addTriangle(*it++,*it++,*it++);
+ }
+ // this shape will be shared and not deleted until shapeInfo is deleted
+ m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true );
+ m_unscaledShape->recalcLocalAabb();
+ }
+ collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f));
+ }
+ break;
+
+ case PHY_SHAPE_COMPOUND:
+ if (m_shapeArray.size() > 0)
+ {
+ compoundShape = new btCompoundShape();
+ for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin();
+ sit != m_shapeArray.end();
+ sit++)
+ {
+ collisionShape = (*sit)->CreateBulletShape();
+ if (collisionShape)
+ {
+ collisionShape->setLocalScaling((*sit)->m_childScale);
+ compoundShape->addChildShape((*sit)->m_childTrans, collisionShape);
+ }
+ }
+ collisionShape = compoundShape;
+ }
+ }
+ return collisionShape;
+}
+
+void CcdShapeConstructionInfo::AddShape(CcdShapeConstructionInfo* shapeInfo)
+{
+ m_shapeArray.push_back(shapeInfo);
+}
+
+CcdShapeConstructionInfo::~CcdShapeConstructionInfo()
+{
+ for (std::vector<CcdShapeConstructionInfo*>::iterator sit = m_shapeArray.begin();
+ sit != m_shapeArray.end();
+ sit++)
+ {
+ (*sit)->Release();
+ }
+ m_shapeArray.clear();
+ if (m_unscaledShape)
+ {
+ DeleteBulletShape(m_unscaledShape);
+ }
+ m_vertexArray.clear();
+ if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL)
+ {
+ std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject);
+ if (mit != m_meshShapeMap.end() && mit->second == this)
+ {
+ m_meshShapeMap.erase(mit);
+ }
+ }
+}
+
+
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
index 448e5622eff..054ec91122a 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h
@@ -17,11 +17,15 @@ subject to the following restrictions:
#ifndef BULLET2_PHYSICSCONTROLLER_H
#define BULLET2_PHYSICSCONTROLLER_H
+#include <vector>
+#include <map>
+
#include "PHY_IPhysicsController.h"
/// PHY_IPhysicsController is the abstract simplified Interface to a physical object.
/// It contains the IMotionState and IDeformableMesh Interfaces.
#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btTransform.h"
#include "PHY_IMotionState.h"
@@ -31,8 +35,119 @@ extern float gAngularSleepingTreshold;
extern bool gDisableDeactivation;
class CcdPhysicsEnvironment;
class btMotionState;
+class RAS_MeshObject;
+class btCollisionShape;
+
+
+#define CCD_BSB_SHAPE_MATCHING 2
+#define CCD_BSB_BENDING_CONSTRAINTS 8
+#define CCD_BSB_AERO_VPOINT 16 /* aero model, Vertex normals are oriented toward velocity*/
+#define CCD_BSB_AERO_VTWOSIDE 32 /* aero model, Vertex normals are flipped to match velocity */
+
+/* BulletSoftBody.collisionflags */
+#define CCD_BSB_COL_SDF_RS 2 /* SDF based rigid vs soft */
+#define CCD_BSB_COL_CL_RS 4 /* Cluster based rigid vs soft */
+#define CCD_BSB_COL_CL_SS 8 /* Cluster based soft vs soft */
+#define CCD_BSB_COL_VF_SS 16 /* Vertex/Face based soft vs soft */
+
+
+
+// Shape contructor
+// It contains all the information needed to create a simple bullet shape at runtime
+class CcdShapeConstructionInfo
+{
+public:
+
+
+ static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope);
+
+ CcdShapeConstructionInfo() :
+ m_shapeType(PHY_SHAPE_NONE),
+ m_radius(1.0),
+ m_height(1.0),
+ m_halfExtend(0.f,0.f,0.f),
+ m_childScale(1.0f,1.0f,1.0f),
+ m_refCount(1),
+ m_meshObject(NULL),
+ m_unscaledShape(NULL),
+ m_useGimpact(false),
+ m_weldingThreshold(0.f)
+ {
+ m_childTrans.setIdentity();
+ }
+
+ ~CcdShapeConstructionInfo();
+
+ CcdShapeConstructionInfo* AddRef()
+ {
+ m_refCount++;
+ return this;
+ }
+
+ int Release()
+ {
+ if (--m_refCount > 0)
+ return m_refCount;
+ delete this;
+ return 0;
+ }
+
+ void AddShape(CcdShapeConstructionInfo* shapeInfo);
+
+ btTriangleMeshShape* GetMeshShape(void)
+ {
+ return m_unscaledShape;
+ }
+ CcdShapeConstructionInfo* GetChildShape(int i)
+ {
+ if (i < 0 || i >= m_shapeArray.size())
+ return NULL;
+
+ return m_shapeArray.at(i);
+ }
+ bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact);
+ RAS_MeshObject* GetMesh(void)
+ {
+ return m_meshObject;
+ }
+
+ btCollisionShape* CreateBulletShape();
+
+ // member variables
+ PHY_ShapeType m_shapeType;
+ btScalar m_radius;
+ btScalar m_height;
+ btVector3 m_halfExtend;
+ btTransform m_childTrans;
+ btVector3 m_childScale;
+ std::vector<btPoint3> m_vertexArray; // Contains both vertex array for polytope shape and
+ // triangle array for concave mesh shape.
+ // In this case a triangle is made of 3 consecutive points
+ std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the
+ // original mesh that correspond to shape triangles.
+ // only set for concave mesh shape.
+
+ void setVertexWeldingThreshold(float threshold)
+ {
+ m_weldingThreshold = threshold;
+ }
+ float getVertexWeldingThreshold() const
+ {
+ return m_weldingThreshold;
+ }
+protected:
+ static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap;
+ int m_refCount; // this class is shared between replicas
+ // keep track of users so that we can release it
+ RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh
+ btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape,
+ // the actual shape is of type btScaledBvhTriangleMeshShape
+ std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes
+ bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection
+ float m_weldingThreshold; //welding closeby vertices together can improve softbody stability etc.
+};
struct CcdConstructionInfo
{
@@ -52,21 +167,28 @@ struct CcdConstructionInfo
CcdConstructionInfo()
- : m_gravity(0,0,0),
+ : m_localInertiaTensor(1.f, 1.f, 1.f),
+ m_gravity(0,0,0),
m_scaling(1.f,1.f,1.f),
m_mass(0.f),
m_restitution(0.1f),
m_friction(0.5f),
m_linearDamping(0.1f),
m_angularDamping(0.1f),
+ m_margin(0.06f),
+ m_gamesoftFlag(0),
m_collisionFlags(0),
m_bRigid(false),
+ m_bSoft(false),
m_collisionFilterGroup(DefaultFilter),
m_collisionFilterMask(AllFilter),
m_collisionShape(0),
m_MotionState(0),
+ m_shapeInfo(0),
m_physicsEnv(0),
- m_inertiaFactor(1.f)
+ m_inertiaFactor(1.f),
+ m_do_anisotropic(false),
+ m_anisotropicFriction(1.f,1.f,1.f)
{
}
@@ -78,8 +200,50 @@ struct CcdConstructionInfo
btScalar m_friction;
btScalar m_linearDamping;
btScalar m_angularDamping;
+ btScalar m_margin;
+
+ ////////////////////
+ int m_gamesoftFlag;
+ float m_soft_linStiff; /* linear stiffness 0..1 */
+ float m_soft_angStiff; /* angular stiffness 0..1 */
+ float m_soft_volume; /* volume preservation 0..1 */
+
+ int m_soft_viterations; /* Velocities solver iterations */
+ int m_soft_piterations; /* Positions solver iterations */
+ int m_soft_diterations; /* Drift solver iterations */
+ int m_soft_citerations; /* Cluster solver iterations */
+
+ float m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
+ float m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
+ float m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
+ float m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+
+ float m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ float m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
+ float m_soft_kVCF; /* Velocities correction factor (Baumgarte) */
+ float m_soft_kDP; /* Damping coefficient [0,1] */
+
+ float m_soft_kDG; /* Drag coefficient [0,+inf] */
+ float m_soft_kLF; /* Lift coefficient [0,+inf] */
+ float m_soft_kPR; /* Pressure coefficient [-inf,+inf] */
+ float m_soft_kVC; /* Volume conversation coefficient [0,+inf] */
+
+ float m_soft_kDF; /* Dynamic friction coefficient [0,1] */
+ float m_soft_kMT; /* Pose matching coefficient [0,1] */
+ float m_soft_kCHR; /* Rigid contacts hardness [0,1] */
+ float m_soft_kKHR; /* Kinetic contacts hardness [0,1] */
+
+ float m_soft_kSHR; /* Soft contacts hardness [0,1] */
+ float m_soft_kAHR; /* Anchors hardness [0,1] */
+ int m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
+ int m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/
+///////////////////
+
+
+
int m_collisionFlags;
bool m_bRigid;
+ bool m_bSoft;
///optional use of collision group/mask:
///only collision with object goups that match the collision mask.
@@ -89,29 +253,59 @@ struct CcdConstructionInfo
short int m_collisionFilterGroup;
short int m_collisionFilterMask;
+ ///these pointers are used as argument passing for the CcdPhysicsController constructor
+ ///and not anymore after that
class btCollisionShape* m_collisionShape;
class PHY_IMotionState* m_MotionState;
+ class CcdShapeConstructionInfo* m_shapeInfo;
CcdPhysicsEnvironment* m_physicsEnv; //needed for self-replication
float m_inertiaFactor;//tweak the inertia (hooked up to Blender 'formfactor'
+ bool m_do_anisotropic;
+ btVector3 m_anisotropicFriction;
+
+ bool m_do_fh; ///< Should the object have a linear Fh spring?
+ bool m_do_rot_fh; ///< Should the object have an angular Fh spring?
+ btScalar m_fh_spring; ///< Spring constant (both linear and angular)
+ btScalar m_fh_damping; ///< Damping factor (linear and angular) in range [0, 1]
+ btScalar m_fh_distance; ///< The range above the surface where Fh is active.
+ bool m_fh_normal; ///< Should the object slide off slopes?
+ float m_radius;//for fh backwards compatibility
+
};
class btRigidBody;
-
+class btCollisionObject;
+class btSoftBody;
///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution.
class CcdPhysicsController : public PHY_IPhysicsController
{
- btRigidBody* m_body;
+
+ btCollisionObject* m_object;
+
+
class PHY_IMotionState* m_MotionState;
btMotionState* m_bulletMotionState;
+ class btCollisionShape* m_collisionShape;
+ class CcdShapeConstructionInfo* m_shapeInfo;
+
friend class CcdPhysicsEnvironment; // needed when updating the controller
+ //some book keeping for replication
+ bool m_softbodyMappingDone;
+ bool m_softBodyTransformInitialized;
+ bool m_prototypeTransformInitialized;
+ btTransform m_softbodyStartTrans;
+
void* m_newClientInfo;
int m_registerCount; // needed when multiple sensors use the same controller
CcdConstructionInfo m_cci;//needed for replication
+
+ CcdPhysicsController* m_parentCtrl;
+
void GetWorldOrientation(btMatrix3x3& mat);
void CreateRigidbody();
@@ -135,11 +329,24 @@ class CcdPhysicsController : public PHY_IPhysicsController
virtual ~CcdPhysicsController();
+ CcdConstructionInfo& getConstructionInfo()
+ {
+ return m_cci;
+ }
+ const CcdConstructionInfo& getConstructionInfo() const
+ {
+ return m_cci;
+ }
+
+
+ btRigidBody* GetRigidBody();
+ btCollisionObject* GetCollisionObject();
+ btSoftBody* GetSoftBody();
- btRigidBody* GetRigidBody() { return m_body;}
+ CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; }
btCollisionShape* GetCollisionShape() {
- return m_body->getCollisionShape();
+ return m_object->getCollisionShape();
}
////////////////////////////////////
// PHY_IPhysicsController interface
@@ -206,14 +413,37 @@ class CcdPhysicsController : public PHY_IPhysicsController
}
virtual void calcXform() {} ;
- virtual void SetMargin(float margin) {};
- virtual float GetMargin() const {return 0.f;};
+ virtual void SetMargin(float margin)
+ {
+ if (m_collisionShape)
+ m_collisionShape->setMargin(btScalar(margin));
+ }
+ virtual float GetMargin() const
+ {
+ return (m_collisionShape) ? m_collisionShape->getMargin() : 0.f;
+ }
+ virtual float GetRadius() const
+ {
+ // this is not the actual shape radius, it's only used for Fh support
+ return m_cci.m_radius;
+ }
+ virtual void SetRadius(float margin)
+ {
+ if (m_collisionShape && m_collisionShape->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
+ {
+ btSphereShape* sphereShape = static_cast<btSphereShape*>(m_collisionShape);
+ sphereShape->setUnscaledRadius(margin);
+ }
+ m_cci.m_radius = margin;
+ }
bool wantsSleeping();
void UpdateDeactivation(float timeStep);
+ void SetCenterOfMassTransform(btTransform& xform);
+
static btTransform GetTransformFromMotionState(PHY_IMotionState* motionState);
void setAabb(const btVector3& aabbMin,const btVector3& aabbMax);
@@ -233,6 +463,23 @@ class CcdPhysicsController : public PHY_IPhysicsController
{
return m_cci.m_physicsEnv;
}
+
+ void setParentCtrl(CcdPhysicsController* parentCtrl)
+ {
+ m_parentCtrl = parentCtrl;
+ }
+
+ CcdPhysicsController* getParentCtrl()
+ {
+ return m_parentCtrl;
+ }
+
+ const CcdPhysicsController* getParentCtrl() const
+ {
+ return m_parentCtrl;
+ }
+
+
};
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
index dfbcf115fd7..91655e96101 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp
@@ -23,6 +23,9 @@ subject to the following restrictions:
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
+#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
+#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h"
//profiling/timings
#include "LinearMath/btQuickprof.h"
@@ -53,6 +56,7 @@ void DrawRasterizerLine(const float* from,const float* to,int color);
#include <stdio.h>
+#include <string.h> // for memset
#ifdef NEW_BULLET_VEHICLE_SUPPORT
class WrapperVehicle : public PHY_IVehicle
@@ -329,30 +333,29 @@ m_filterCallback(NULL)
{
m_triggerCallbacks[i] = 0;
}
+
+// m_collisionConfiguration = new btDefaultCollisionConfiguration();
+ m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
+
if (!dispatcher)
{
- dispatcher = new btCollisionDispatcher();
+ btCollisionDispatcher* disp = new btCollisionDispatcher(m_collisionConfiguration);
+ dispatcher = disp;
+ btGImpactCollisionAlgorithm::registerAlgorithm(disp);
m_ownDispatcher = dispatcher;
}
- if(!pairCache)
- {
-
- //todo: calculate/let user specify this world sizes
- btVector3 worldMin(-10000,-10000,-10000);
- btVector3 worldMax(10000,10000,10000);
-
- pairCache = new btAxisSweep3(worldMin,worldMax);
- // remember that this was allocated by us so that we can release it
- m_ownPairCache = pairCache;
- //broadphase = new btSimpleBroadphase();
- }
+ //m_broadphase = new btAxisSweep3(btVector3(-1000,-1000,-1000),btVector3(1000,1000,1000));
+ //m_broadphase = new btSimpleBroadphase();
+ m_broadphase = new btDbvtBroadphase();
m_filterCallback = new CcdOverlapFilterCallBack(this);
- pairCache->setOverlapFilterCallback(m_filterCallback);
+ m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback);
setSolverType(1);//issues with quickstep and memory allocations
- m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,m_solver);
+// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+ m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
+
m_debugDrawer = 0;
m_gravity = btVector3(0.f,-10.f,0.f);
m_dynamicsWorld->setGravity(m_gravity);
@@ -363,24 +366,42 @@ m_filterCallback(NULL)
void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
{
btRigidBody* body = ctrl->GetRigidBody();
+ btCollisionObject* obj = ctrl->GetCollisionObject();
//this m_userPointer is just used for triggers, see CallbackTriggers
- body->setUserPointer(ctrl);
+ obj->setUserPointer(ctrl);
+ if (body)
+ body->setGravity( m_gravity );
- body->setGravity( m_gravity );
m_controllers.insert(ctrl);
- //use explicit group/filter for finer control over collision in bullet => near/radar sensor
- m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
- if (body->isStaticOrKinematicObject())
+ if (body)
+ {
+ //use explicit group/filter for finer control over collision in bullet => near/radar sensor
+ m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
+ } else
+ {
+ if (ctrl->GetSoftBody())
+ {
+ btSoftBody* softBody = ctrl->GetSoftBody();
+ m_dynamicsWorld->addSoftBody(softBody);
+ } else
+ {
+ if (obj->getCollisionShape())
+ {
+ m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
+ }
+ }
+ }
+ if (obj->isStaticOrKinematicObject())
{
- body->setActivationState(ISLAND_SLEEPING);
+ obj->setActivationState(ISLAND_SLEEPING);
}
//CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask());
- assert(body->getBroadphaseHandle());
+ assert(obj->getBroadphaseHandle());
btBroadphaseInterface* scene = getBroadphase();
@@ -389,7 +410,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
assert(shapeinterface);
- const btTransform& t = ctrl->GetRigidBody()->getCenterOfMassTransform();
+ const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform();
btPoint3 minAabb,maxAabb;
@@ -401,42 +422,59 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl)
//extent it with the motion
- btVector3 linMotion = body->getLinearVelocity()*timeStep;
-
- float maxAabbx = maxAabb.getX();
- float maxAabby = maxAabb.getY();
- float maxAabbz = maxAabb.getZ();
- float minAabbx = minAabb.getX();
- float minAabby = minAabb.getY();
- float minAabbz = minAabb.getZ();
-
- if (linMotion.x() > 0.f)
- maxAabbx += linMotion.x();
- else
- minAabbx += linMotion.x();
- if (linMotion.y() > 0.f)
- maxAabby += linMotion.y();
- else
- minAabby += linMotion.y();
- if (linMotion.z() > 0.f)
- maxAabbz += linMotion.z();
- else
- minAabbz += linMotion.z();
-
-
- minAabb = btVector3(minAabbx,minAabby,minAabbz);
- maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz);
-
+ if (body)
+ {
+ btVector3 linMotion = body->getLinearVelocity()*timeStep;
+
+ float maxAabbx = maxAabb.getX();
+ float maxAabby = maxAabb.getY();
+ float maxAabbz = maxAabb.getZ();
+ float minAabbx = minAabb.getX();
+ float minAabby = minAabb.getY();
+ float minAabbz = minAabb.getZ();
+
+ if (linMotion.x() > 0.f)
+ maxAabbx += linMotion.x();
+ else
+ minAabbx += linMotion.x();
+ if (linMotion.y() > 0.f)
+ maxAabby += linMotion.y();
+ else
+ minAabby += linMotion.y();
+ if (linMotion.z() > 0.f)
+ maxAabbz += linMotion.z();
+ else
+ minAabbz += linMotion.z();
+
+
+ minAabb = btVector3(minAabbx,minAabby,minAabbz);
+ maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz);
+ }
}
+
+
void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl)
{
//also remove constraint
-
- m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
+ btRigidBody* body = ctrl->GetRigidBody();
+ if (body)
+ {
+ m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
+ } else
+ {
+ //if a softbody
+ if (ctrl->GetSoftBody())
+ {
+ m_dynamicsWorld->removeSoftBody(ctrl->GetSoftBody());
+ } else
+ {
+ m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject());
+ }
+ }
m_controllers.erase(ctrl);
if (ctrl->m_registerCount != 0)
@@ -451,13 +489,20 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr
// this function is used when the collisionning group of a controller is changed
// remove and add the collistioning object
btRigidBody* body = ctrl->GetRigidBody();
- btVector3 inertia;
-
- m_dynamicsWorld->removeCollisionObject(body);
- body->setCollisionFlags(newCollisionFlags);
- body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
- body->setMassProps(newMass, inertia);
- m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask);
+ btCollisionObject* obj = ctrl->GetCollisionObject();
+ if (obj)
+ {
+ btVector3 inertia(0.0,0.0,0.0);
+ m_dynamicsWorld->removeCollisionObject(obj);
+ obj->setCollisionFlags(newCollisionFlags);
+ if (body)
+ {
+ if (newMass)
+ body->getCollisionShape()->calculateLocalInertia(newMass, inertia);
+ body->setMassProps(newMass, inertia);
+ }
+ m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask);
+ }
// to avoid nasty interaction, we must update the property of the controller as well
ctrl->m_cci.m_mass = newMass;
ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup;
@@ -469,9 +514,9 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr
{
if (m_controllers.insert(ctrl).second)
{
- btRigidBody* body = ctrl->GetRigidBody();
- body->setUserPointer(ctrl);
- m_dynamicsWorld->addCollisionObject(body,
+ btCollisionObject* obj = ctrl->GetCollisionObject();
+ obj->setUserPointer(ctrl);
+ m_dynamicsWorld->addCollisionObject(obj,
ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask());
}
}
@@ -480,7 +525,19 @@ void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ct
{
if (m_controllers.erase(ctrl))
{
- m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody());
+ btRigidBody* body = ctrl->GetRigidBody();
+ if (body)
+ {
+ m_dynamicsWorld->removeRigidBody(body);
+ } else
+ {
+ if (ctrl->GetSoftBody())
+ {
+ } else
+ {
+ m_dynamicsWorld->removeCollisionObject(body);
+ }
+ }
}
}
@@ -501,10 +558,18 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
(*it)->SynchronizeMotionStates(timeStep);
}
+ processFhSprings(curTime,timeStep);
+
float subStep = timeStep / float(m_numTimeSubSteps);
for (i=0;i<m_numTimeSubSteps;i++)
{
- m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step
+// m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step
+ m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step
+ }
+
+ for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
+ {
+ (*it)->SynchronizeMotionStates(timeStep);
}
for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
@@ -518,11 +583,181 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep)
veh->SyncWheels();
}
+ if (m_dynamicsWorld->getDebugDrawer() && m_dynamicsWorld->getDebugDrawer()->getDebugMode() >0)
+ m_dynamicsWorld->debugDrawWorld();
+
+
CallbackTriggers();
return true;
}
+class ClosestRayResultCallbackNotMe : public btCollisionWorld::ClosestRayResultCallback
+{
+ btCollisionObject* m_owner;
+ btCollisionObject* m_parent;
+
+public:
+ ClosestRayResultCallbackNotMe(const btVector3& rayFromWorld,const btVector3& rayToWorld,btCollisionObject* owner,btCollisionObject* parent)
+ :btCollisionWorld::ClosestRayResultCallback(rayFromWorld,rayToWorld),
+ m_owner(owner)
+ {
+
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ //don't collide with self
+ if (proxy0->m_clientObject == m_owner)
+ return false;
+
+ if (proxy0->m_clientObject == m_parent)
+ return false;
+
+ return btCollisionWorld::ClosestRayResultCallback::needsCollision(proxy0);
+ }
+
+};
+
+void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep)
+{
+ std::set<CcdPhysicsController*>::iterator it;
+
+ for (it=m_controllers.begin(); it!=m_controllers.end(); it++)
+ {
+ CcdPhysicsController* ctrl = (*it);
+ btRigidBody* body = ctrl->GetRigidBody();
+
+ if (body && (ctrl->getConstructionInfo().m_do_fh || ctrl->getConstructionInfo().m_do_rot_fh))
+ {
+ //printf("has Fh or RotFh\n");
+ //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo()
+ //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates
+
+
+ CcdPhysicsController* parentCtrl = ctrl->getParentCtrl();
+ btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0;
+ btRigidBody* cl_object = parentBody ? parentBody : body;
+
+ if (body->isStaticOrKinematicObject())
+ continue;
+
+ btVector3 rayDirLocal(0,0,-10);
+
+ //m_dynamicsWorld
+ //ctrl->GetRigidBody();
+ btVector3 rayFromWorld = body->getCenterOfMassPosition();
+ //btVector3 rayToWorld = rayFromWorld + body->getCenterOfMassTransform().getBasis() * rayDirLocal;
+ //ray always points down the z axis in world space...
+ btVector3 rayToWorld = rayFromWorld + rayDirLocal;
+
+ ClosestRayResultCallbackNotMe resultCallback(rayFromWorld,rayToWorld,body,parentBody);
+
+ m_dynamicsWorld->rayTest(rayFromWorld,rayToWorld,resultCallback);
+ if (resultCallback.hasHit())
+ {
+ //we hit this one: resultCallback.m_collisionObject;
+ CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(resultCallback.m_collisionObject->getUserPointer());
+
+ if (controller)
+ {
+ if (controller->getConstructionInfo().m_fh_distance < SIMD_EPSILON)
+ continue;
+
+ btRigidBody* hit_object = controller->GetRigidBody();
+ if (!hit_object)
+ continue;
+
+ CcdConstructionInfo& hitObjShapeProps = controller->getConstructionInfo();
+
+ float distance = resultCallback.m_closestHitFraction*rayDirLocal.length()-ctrl->getConstructionInfo().m_radius;
+ if (distance >= hitObjShapeProps.m_fh_distance)
+ continue;
+
+
+
+ //btVector3 ray_dir = cl_object->getCenterOfMassTransform().getBasis()* rayDirLocal.normalized();
+ btVector3 ray_dir = rayDirLocal.normalized();
+ btVector3 normal = resultCallback.m_hitNormalWorld;
+ normal.normalize();
+
+
+ if (ctrl->getConstructionInfo().m_do_fh)
+ {
+ btVector3 lspot = cl_object->getCenterOfMassPosition()
+ + rayDirLocal * resultCallback.m_closestHitFraction;
+
+
+
+
+ lspot -= hit_object->getCenterOfMassPosition();
+ btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot);
+ btScalar rel_vel_ray = ray_dir.dot(rel_vel);
+ btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance;
+
+ btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring;
+ btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping;
+
+ cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir));
+ if (hitObjShapeProps.m_fh_normal)
+ {
+ cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir));
+ }
+
+ btVector3 lateral = rel_vel - rel_vel_ray * ray_dir;
+
+
+ if (ctrl->getConstructionInfo().m_do_anisotropic) {
+ //Bullet basis contains no scaling/shear etc.
+ const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis();
+ btVector3 loc_lateral = lateral * lcs;
+ const btVector3& friction_scaling = cl_object->getAnisotropicFriction();
+ loc_lateral *= friction_scaling;
+ lateral = lcs * loc_lateral;
+ }
+
+ btScalar rel_vel_lateral = lateral.length();
+
+ if (rel_vel_lateral > SIMD_EPSILON) {
+ btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction();
+
+ btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring);
+
+ btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass();
+
+ btVector3 friction = (rel_mom_lateral > max_friction) ?
+ -lateral * (max_friction / rel_vel_lateral) :
+ -lateral;
+
+ cl_object->applyCentralImpulse(friction);
+ }
+ }
+
+
+ if (ctrl->getConstructionInfo().m_do_rot_fh) {
+ btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2);
+
+ btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring;
+ btVector3 ang_vel = cl_object->getAngularVelocity();
+
+ // only rotations that tilt relative to the normal are damped
+ ang_vel -= ang_vel.dot(normal) * normal;
+
+ btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping;
+
+ cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp));
+ }
+
+ }
+
+
+ }
+
+
+ }
+ }
+
+}
void CcdPhysicsEnvironment::setDebugMode(int debugMode)
{
@@ -578,7 +813,7 @@ void CcdPhysicsEnvironment::setSolverDamping(float damping)
void CcdPhysicsEnvironment::setLinearAirDamping(float damping)
{
- gLinearAirDamping = damping;
+ //gLinearAirDamping = damping;
}
void CcdPhysicsEnvironment::setUseEpa(bool epa)
@@ -597,7 +832,7 @@ void CcdPhysicsEnvironment::setSolverType(int solverType)
{
m_solver = new btSequentialImpulseConstraintSolver();
- ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
+// ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
break;
}
}
@@ -618,7 +853,13 @@ void CcdPhysicsEnvironment::setSolverType(int solverType)
-
+void CcdPhysicsEnvironment::getGravity(PHY__Vector3& grav)
+{
+ const btVector3& gravity = m_dynamicsWorld->getGravity();
+ grav[0] = gravity.getX();
+ grav[1] = gravity.getY();
+ grav[2] = gravity.getZ();
+}
void CcdPhysicsEnvironment::setGravity(float x,float y,float z)
@@ -659,9 +900,10 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint(
{
+ bool useReferenceFrameA = true;
genericConstraint = new btGeneric6DofConstraint(
*rb0,*rb1,
- frameInA,frameInB);
+ frameInA,frameInB,useReferenceFrameA);
genericConstraint->setLinearLowerLimit(linearMinLimits);
genericConstraint->setLinearUpperLimit(linearMaxLimits);
genericConstraint->setAngularLowerLimit(angularMinLimits);
@@ -709,35 +951,54 @@ void CcdPhysicsEnvironment::removeConstraint(int constraintId)
struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
- PHY_IPhysicsController* m_ignoreClient;
+ PHY_IRayCastFilterCallback& m_phyRayFilter;
+ const btCollisionShape* m_hitTriangleShape;
+ int m_hitTriangleIndex;
- FilterClosestRayResultCallback (PHY_IPhysicsController* ignoreClient,const btVector3& rayFrom,const btVector3& rayTo)
+ FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo)
: btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo),
- m_ignoreClient(ignoreClient)
+ m_phyRayFilter(phyRayFilter),
+ m_hitTriangleShape(NULL),
+ m_hitTriangleIndex(0)
{
-
}
virtual ~FilterClosestRayResultCallback()
{
}
- virtual float AddSingleResult( btCollisionWorld::LocalRayResult& rayResult)
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask))
+ return false;
+ if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask))
+ return false;
+ btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject;
+ CcdPhysicsController* phyCtrl = static_cast<CcdPhysicsController*>(object->getUserPointer());
+ if (phyCtrl == m_phyRayFilter.m_ignoreController)
+ return false;
+ return m_phyRayFilter.needBroadphaseRayCast(phyCtrl);
+ }
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
{
CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer());
- //ignore client...
- if (curHit != m_ignoreClient)
- {
- //if valid
- return ClosestRayResultCallback::AddSingleResult(rayResult);
+ // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it
+ if (rayResult.m_localShapeInfo)
+ {
+ m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape();
+ m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex;
+ } else
+ {
+ m_hitTriangleShape = NULL;
+ m_hitTriangleIndex = 0;
}
- return m_closestHitFraction;
+ return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace);
}
};
-PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
+PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
{
@@ -751,19 +1012,101 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i
//Either Ray Cast with or without filtering
//btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo);
- FilterClosestRayResultCallback rayCallback(ignoreClient,rayFrom,rayTo);
+ FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo);
+
+ PHY_RayCastResult result;
+ memset(&result, 0, sizeof(result));
- PHY_IPhysicsController* nearestHit = 0;
// don't collision with sensor object
- m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback, CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter);
- if (rayCallback.HasHit())
+ rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter;
+ //, ,filterCallback.m_faceNormal);
+
+ m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback);
+ if (rayCallback.hasHit())
{
- nearestHit = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
- hitX = rayCallback.m_hitPointWorld.getX();
- hitY = rayCallback.m_hitPointWorld.getY();
- hitZ = rayCallback.m_hitPointWorld.getZ();
+ CcdPhysicsController* controller = static_cast<CcdPhysicsController*>(rayCallback.m_collisionObject->getUserPointer());
+ result.m_controller = controller;
+ result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX();
+ result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY();
+ result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ();
+
+ if (rayCallback.m_hitTriangleShape != NULL)
+ {
+ // identify the mesh polygon
+ CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo;
+ if (shapeInfo)
+ {
+ btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape();
+ if (shape->isCompound())
+ {
+ btCompoundShape* compoundShape = (btCompoundShape*)shape;
+ CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo;
+ // need to search which sub-shape has been hit
+ for (int i=0; i<compoundShape->getNumChildShapes(); i++)
+ {
+ shapeInfo = compoundShapeInfo->GetChildShape(i);
+ shape=compoundShape->getChildShape(i);
+ if (shape == rayCallback.m_hitTriangleShape)
+ break;
+ }
+ }
+ if (shape == rayCallback.m_hitTriangleShape &&
+ rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size())
+ {
+ result.m_meshObject = shapeInfo->GetMesh();
+ result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex);
+ // Bullet returns the normal from "outside".
+ // If the user requests the real normal, compute it now
+ if (filterCallback.m_faceNormal)
+ {
+ // mesh shapes are shared and stored in the shapeInfo
+ btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape();
+ if (triangleShape)
+ {
+ // this code is copied from Bullet
+ btVector3 triangle[3];
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+ btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface();
+
+ meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ 0);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride);
+ const btVector3& meshScaling = shape->getLocalScaling();
+ for (int j=2;j>=0;j--)
+ {
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+ btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
+
+ triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ }
+ meshInterface->unLockReadOnlyVertexBase(0);
+ btVector3 triangleNormal;
+ triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
+ rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal;
+ }
+ }
+ }
+ }
+ }
if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON))
{
rayCallback.m_hitNormalWorld.normalize();
@@ -771,14 +1114,14 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i
{
rayCallback.m_hitNormalWorld.setValue(1,0,0);
}
- normalX = rayCallback.m_hitNormalWorld.getX();
- normalY = rayCallback.m_hitNormalWorld.getY();
- normalZ = rayCallback.m_hitNormalWorld.getZ();
-
+ result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX();
+ result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY();
+ result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ();
+ filterCallback.reportHit(&result);
}
- return nearestHit;
+ return result.m_controller;
}
@@ -801,6 +1144,13 @@ btBroadphaseInterface* CcdPhysicsEnvironment::getBroadphase()
return m_dynamicsWorld->getBroadphase();
}
+btDispatcher* CcdPhysicsEnvironment::getDispatcher()
+{
+ return m_dynamicsWorld->getDispatcher();
+}
+
+
+
@@ -833,6 +1183,12 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment()
if (NULL != m_filterCallback)
delete m_filterCallback;
+
+ if (NULL != m_collisionConfiguration)
+ delete m_collisionConfiguration;
+
+ if (NULL != m_broadphase)
+ delete m_broadphase;
}
@@ -845,7 +1201,7 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float
{
//param = 1..12, min0,max0,min1,max1...min6,max6
btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint;
- genCons->SetLimit(param,value0,value1);
+ genCons->setLimit(param,value0,value1);
break;
};
default:
@@ -1108,6 +1464,26 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi
return sphereController;
}
+int findClosestNode(btSoftBody* sb,const btVector3& worldPoint);
+int findClosestNode(btSoftBody* sb,const btVector3& worldPoint)
+{
+ int node = -1;
+
+ btSoftBody::tNodeArray& nodes(sb->m_nodes);
+ float maxDistSqr = 1e30f;
+
+ for (int n=0;n<nodes.size();n++)
+ {
+ btScalar distSqr = (nodes[n].m_x - worldPoint).length2();
+ if (distSqr<maxDistSqr)
+ {
+ maxDistSqr = distSqr;
+ node = n;
+ }
+ }
+ return node;
+}
+
int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl0,class PHY_IPhysicsController* ctrl1,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
float axisX,float axisY,float axisZ,
@@ -1123,14 +1499,166 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
btRigidBody* rb0 = c0 ? c0->GetRigidBody() : 0;
btRigidBody* rb1 = c1 ? c1->GetRigidBody() : 0;
+
+
+
bool rb0static = rb0 ? rb0->isStaticOrKinematicObject() : true;
bool rb1static = rb1 ? rb1->isStaticOrKinematicObject() : true;
+
+ btCollisionObject* colObj0 = c0->GetCollisionObject();
+ if (!colObj0)
+ {
+ return 0;
+ }
+
+ btVector3 pivotInA(pivotX,pivotY,pivotZ);
+
+ //it might be a soft body, let's try
+ btSoftBody* sb0 = c0 ? c0->GetSoftBody() : 0;
+ btSoftBody* sb1 = c1 ? c1->GetSoftBody() : 0;
+ if (sb0 && sb1)
+ {
+ //not between two soft bodies?
+ return 0;
+ }
+
+ if (sb0)
+ {
+ //either cluster or node attach, let's find closest node first
+ //the soft body doesn't have a 'real' world transform, so get its initial world transform for now
+ btVector3 pivotPointSoftWorld = sb0->m_initialWorldTransform(pivotInA);
+ int node=findClosestNode(sb0,pivotPointSoftWorld);
+ if (node >=0)
+ {
+ bool clusterconstaint = false;
+/*
+ switch (type)
+ {
+ case PHY_LINEHINGE_CONSTRAINT:
+ {
+ if (sb0->clusterCount() && rb1)
+ {
+ btSoftBody::LJoint::Specs ls;
+ ls.erp=0.5f;
+ ls.position=sb0->clusterCom(0);
+ sb0->appendLinearJoint(ls,rb1);
+ clusterconstaint = true;
+ break;
+ }
+ }
+ case PHY_GENERIC_6DOF_CONSTRAINT:
+ {
+ if (sb0->clusterCount() && rb1)
+ {
+ btSoftBody::AJoint::Specs as;
+ as.erp = 1;
+ as.cfm = 1;
+ as.axis.setValue(axisX,axisY,axisZ);
+ sb0->appendAngularJoint(as,rb1);
+ clusterconstaint = true;
+ break;
+ }
+
+ break;
+ }
+ default:
+ {
+
+ }
+ };
+ */
+
+ if (!clusterconstaint)
+ {
+ if (rb1)
+ {
+ sb0->appendAnchor(node,rb1);
+ } else
+ {
+ sb0->setMass(node,0.f);
+ }
+ }
+
+
+ }
+ return 0;//can't remove soft body anchors yet
+ }
+
+ if (sb1)
+ {
+ btVector3 pivotPointAWorld = colObj0->getWorldTransform()(pivotInA);
+ int node=findClosestNode(sb1,pivotPointAWorld);
+ if (node >=0)
+ {
+ bool clusterconstaint = false;
+
+ /*
+ switch (type)
+ {
+ case PHY_LINEHINGE_CONSTRAINT:
+ {
+ if (sb1->clusterCount() && rb0)
+ {
+ btSoftBody::LJoint::Specs ls;
+ ls.erp=0.5f;
+ ls.position=sb1->clusterCom(0);
+ sb1->appendLinearJoint(ls,rb0);
+ clusterconstaint = true;
+ break;
+ }
+ }
+ case PHY_GENERIC_6DOF_CONSTRAINT:
+ {
+ if (sb1->clusterCount() && rb0)
+ {
+ btSoftBody::AJoint::Specs as;
+ as.erp = 1;
+ as.cfm = 1;
+ as.axis.setValue(axisX,axisY,axisZ);
+ sb1->appendAngularJoint(as,rb0);
+ clusterconstaint = true;
+ break;
+ }
+
+ break;
+ }
+ default:
+ {
+
+
+ }
+ };*/
+
+
+ if (!clusterconstaint)
+ {
+ if (rb0)
+ {
+ sb1->appendAnchor(node,rb0);
+ } else
+ {
+ sb1->setMass(node,0.f);
+ }
+ }
+
+
+ }
+ return 0;//can't remove soft body anchors yet
+ }
+
if (rb0static && rb1static)
+ {
+
return 0;
+ }
+
- btVector3 pivotInA(pivotX,pivotY,pivotZ);
+ if (!rb0)
+ return 0;
+
+
btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) :
rb0->getCenterOfMassTransform() * pivotInA;
btVector3 axisInA(axisX,axisY,axisZ);
@@ -1191,10 +1719,11 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA;
frameInB = inv * globalFrameA;
-
+ bool useReferenceFrameA = true;
+
genericConstraint = new btGeneric6DofConstraint(
*rb0,*rb1,
- frameInA,frameInB);
+ frameInA,frameInB,useReferenceFrameA);
} else
@@ -1215,9 +1744,10 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
///frameInB in worldspace
frameInB = rb0->getCenterOfMassTransform() * frameInA;
+ bool useReferenceFrameA = true;
genericConstraint = new btGeneric6DofConstraint(
*rb0,s_fixedObject2,
- frameInA,frameInB);
+ frameInA,frameInB,useReferenceFrameA);
}
if (genericConstraint)
@@ -1370,8 +1900,9 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl
PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float coneradius,float coneheight)
{
CcdConstructionInfo cinfo;
- //This is a memory leak: Bullet does not delete the shape and it cannot be added to
- //the KX_Scene.m_shapes list -- too bad but that's not a lot of data
+
+ // we don't need a CcdShapeConstructionInfo for this shape:
+ // it is simple enough for the standard copy constructor (see CcdPhysicsController::GetReplica)
cinfo.m_collisionShape = new btConeShape(coneradius,coneheight);
cinfo.m_MotionState = 0;
cinfo.m_physicsEnv = this;
diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
index 825a5e525f2..3d9d5442b8f 100644
--- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h
@@ -56,6 +56,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment
protected:
btIDebugDraw* m_debugDrawer;
+
+ class btDefaultCollisionConfiguration* m_collisionConfiguration;
+ class btBroadphaseInterface* m_broadphase;
+
//solver iterations
int m_numIterations;
@@ -70,6 +74,7 @@ protected:
btContactSolverInfo m_solverInfo;
+ void processFhSprings(double curTime,float timeStep);
public:
CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0);
@@ -115,6 +120,8 @@ protected:
virtual void setDebugMode(int debugMode);
virtual void setGravity(float x,float y,float z);
+ virtual void getGravity(PHY__Vector3& grav);
+
virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type,
float pivotX,float pivotY,float pivotZ,
@@ -157,8 +164,7 @@ protected:
btTypedConstraint* getConstraintById(int constraintId);
- virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
//Methods for gamelogic collision/physics callbacks
@@ -192,8 +198,7 @@ protected:
btBroadphaseInterface* getBroadphase();
-
-
+ btDispatcher* getDispatcher();
bool IsSatCollisionDetectionEnabled() const
@@ -212,7 +217,10 @@ protected:
void SyncMotionStates(float timeStep);
-
+ class btSoftRigidDynamicsWorld* getDynamicsWorld()
+ {
+ return m_dynamicsWorld;
+ }
class btConstraintSolver* GetConstraintSolver();
@@ -230,13 +238,13 @@ protected:
std::vector<WrapperVehicle*> m_wrapperVehicles;
- //use explicit btDiscreteDynamicsWorld* so that we have access to
+ //use explicit btSoftRigidDynamicsWorld/btDiscreteDynamicsWorld* so that we have access to
//btDiscreteDynamicsWorld::addRigidBody(body,filter,group)
//so that we can set the body collision filter/group at the time of creation
//and not afterwards (breaks the collision system for radar/near sensor)
//Ideally we would like to have access to this function from the btDynamicsWorld interface
//class btDynamicsWorld* m_dynamicsWorld;
- class btDiscreteDynamicsWorld* m_dynamicsWorld;
+ class btSoftRigidDynamicsWorld* m_dynamicsWorld;
class btConstraintSolver* m_solver;
diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile
index 49259d0a67c..d5570e75833 100644
--- a/source/gameengine/Physics/Bullet/Makefile
+++ b/source/gameengine/Physics/Bullet/Makefile
@@ -37,5 +37,10 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += -I$(NAN_BULLET2)/include
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_STRING)/include
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I../../../kernel/gen_system
CPPFLAGS += -I../../Physics/common
CPPFLAGS += -I../../Physics/Dummy
+CPPFLAGS += -I../../Rasterizer
+
diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript
index dd6eab0f018..0936d45197a 100644
--- a/source/gameengine/Physics/Bullet/SConscript
+++ b/source/gameengine/Physics/Bullet/SConscript
@@ -3,7 +3,7 @@ Import ('env')
sources = 'CcdPhysicsEnvironment.cpp CcdPhysicsController.cpp'
-incs = '. ../common'
+incs = '. ../common #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer'
incs += ' ' + env['BF_BULLET_INC']
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
index f512d44c9f2..d78958b746c 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp
@@ -109,8 +109,7 @@ void DummyPhysicsEnvironment::removeConstraint(int constraintid)
}
}
-PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)
+PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ)
{
//collision detection / raytesting
return NULL;
diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
index b5a61f72e4a..975be84f2a7 100644
--- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h
@@ -69,8 +69,7 @@ public:
return 0;
}
- virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
//gamelogic callbacks
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
index 95f01b45f2b..d8ee54935d7 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsController.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h
@@ -120,6 +120,7 @@ public:
virtual void SetMargin(float margin) ;
virtual float GetMargin() const;
virtual float GetRadius() const ;
+ virtual void SetRadius(float margin) { SetMargin(margin); }
// clientinfo for raycasts for example
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
index 65018d2523e..80e4dc4044e 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp
@@ -26,6 +26,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+#include <string.h> // memset
#include "SumoPhysicsEnvironment.h"
#include "PHY_IMotionState.h"
#include "SumoPhysicsController.h"
@@ -125,37 +126,35 @@ void SumoPhysicsEnvironment::removeConstraint(int constraintid)
}
}
-PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClientCtrl,
+PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,
float fromX,float fromY,float fromZ,
- float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,
- float& normalX,float& normalY,float& normalZ)
+ float toX,float toY,float toZ)
{
- SumoPhysicsController* ignoreCtr = static_cast<SumoPhysicsController*> (ignoreClientCtrl);
+ SumoPhysicsController* ignoreCtr = static_cast<SumoPhysicsController*> (filterCallback.m_ignoreController);
//collision detection / raytesting
MT_Point3 hit, normal;
- PHY_IPhysicsController *ret = 0;
+ PHY_RayCastResult result;
SM_Object* sm_ignore = 0;
if (ignoreCtr)
sm_ignore = ignoreCtr->GetSumoObject();
+ memset(&result, 0, sizeof(result));
SM_Object* smOb = m_sumoScene->rayTest(sm_ignore,MT_Point3(fromX, fromY, fromZ),MT_Point3(toX, toY, toZ), hit, normal);
if (smOb)
{
- ret = (PHY_IPhysicsController *) smOb->getPhysicsClientObject();
+ result.m_controller = (PHY_IPhysicsController *) smOb->getPhysicsClientObject();
+ result.m_hitPoint[0] = hit[0];
+ result.m_hitPoint[1] = hit[1];
+ result.m_hitPoint[2] = hit[2];
+ result.m_hitNormal[0] = normal[0];
+ result.m_hitNormal[1] = normal[1];
+ result.m_hitNormal[2] = normal[2];
+ filterCallback.reportHit(&result);
}
- hitX = hit[0];
- hitY = hit[1];
- hitZ = hit[2];
-
- normalX = normal[0];
- normalY = normal[1];
- normalZ = normal[2];
-
- return ret;
+ return result.m_controller;
}
//gamelogic callbacks
void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl)
diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
index 8b9fb463034..100adf969d5 100644
--- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
+++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h
@@ -75,8 +75,7 @@ public:
return 0;
}
- virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ);
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ);
//gamelogic callbacks
diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h
index c289b9d8bcb..3b3e42c38d2 100644
--- a/source/gameengine/Physics/common/PHY_DynamicTypes.h
+++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h
@@ -87,6 +87,18 @@ typedef enum PHY_ConstraintType {
} PHY_ConstraintType;
+typedef enum PHY_ShapeType {
+ PHY_SHAPE_NONE,
+ PHY_SHAPE_BOX,
+ PHY_SHAPE_SPHERE,
+ PHY_SHAPE_CYLINDER,
+ PHY_SHAPE_CONE,
+ PHY_SHAPE_MESH,
+ PHY_SHAPE_POLYTOPE,
+ PHY_SHAPE_COMPOUND
+} PHY_ShapeType;
+
+
typedef float PHY_Vector3[3];
#endif //__PHY_DYNAMIC_TYPES
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h
index ca8edea114a..884e14cfb5a 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsController.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h
@@ -90,7 +90,8 @@ class PHY_IPhysicsController
virtual void calcXform() =0;
virtual void SetMargin(float margin) =0;
virtual float GetMargin() const=0;
- virtual float GetRadius() const { return 0.f;}
+ virtual float GetRadius() const=0;
+ virtual void SetRadius(float margin) = 0;
PHY__Vector3 GetWorldPosition(PHY__Vector3& localpos);
};
diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
index 5b275066665..98496fb7f9e 100644
--- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
+++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h
@@ -33,6 +33,50 @@
#include <vector>
#include "PHY_DynamicTypes.h"
class PHY_IVehicle;
+class RAS_MeshObject;
+class PHY_IPhysicsController;
+
+/**
+ * pass back information from rayTest
+ */
+struct PHY_RayCastResult
+{
+ PHY_IPhysicsController* m_controller;
+ PHY__Vector3 m_hitPoint;
+ PHY__Vector3 m_hitNormal;
+ const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers)
+ int m_polygon; // index of the polygon hit by the ray,
+ // only if m_meshObject != NULL
+};
+
+/**
+ * This class replaces the ignoreController parameter of rayTest function.
+ * It allows more sophisticated filtering on the physics controller before computing the ray intersection to save CPU.
+ * It is only used to its full extend by the Ccd physics environement (Bullet).
+ */
+class PHY_IRayCastFilterCallback
+{
+public:
+ PHY_IPhysicsController* m_ignoreController;
+ bool m_faceNormal;
+
+ virtual ~PHY_IRayCastFilterCallback()
+ {
+ }
+
+ virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller)
+ {
+ return true;
+ }
+
+ virtual void reportHit(PHY_RayCastResult* result) = 0;
+
+ PHY_IRayCastFilterCallback(PHY_IPhysicsController* ignoreController, bool faceNormal=false)
+ :m_ignoreController(ignoreController),
+ m_faceNormal(faceNormal)
+ {
+ }
+};
/**
* Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.)
@@ -94,8 +138,7 @@ class PHY_IPhysicsEnvironment
//complex constraint for vehicles
virtual PHY_IVehicle* getVehicleConstraint(int constraintId) =0;
- virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ,
- float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0;
+ virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0;
//Methods for gamelogic collision/physics callbacks
diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py
index d56888cde80..b68d3014115 100644
--- a/source/gameengine/PyDoc/BL_ActionActuator.py
+++ b/source/gameengine/PyDoc/BL_ActionActuator.py
@@ -164,5 +164,14 @@ class BL_ActionActuator(SCA_IActuator):
@param mode: True for armature/world space, False for bone space
@type mode: boolean
"""
-
-
+ def setFrameProperty(prop):
+ """
+ @param prop: A string specifying the property of the object that will be updated with the action frame number.
+ @type prop: string
+ """
+ def getFrameProperty():
+ """
+ Returns the name of the property that is set to the current frame number.
+
+ @rtype: string
+ """
diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
index 63cce253fa4..a26b276a2da 100644
--- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py
+++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py
@@ -154,5 +154,14 @@ class BL_ShapeActionActuator(SCA_IActuator):
@rtype: string
"""
-
-
+ def setFrameProperty(prop):
+ """
+ @param prop: A string specifying the property of the object that will be updated with the action frame number.
+ @type prop: string
+ """
+ def getFrameProperty():
+ """
+ Returns the name of the property that is set to the current frame number.
+
+ @rtype: string
+ """
diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py
index 268fb9cc172..1a0a737718e 100644
--- a/source/gameengine/PyDoc/GameKeys.py
+++ b/source/gameengine/PyDoc/GameKeys.py
@@ -164,3 +164,12 @@ Example::
# Activate Right!
"""
+
+def EventToString(event):
+ """
+ Return the string name of a key event. Will raise a ValueError error if its invalid.
+
+ @type event: int
+ @param event: key event from GameKeys or the keyboard sensor.
+ @rtype: string
+ """
diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py
index 965c0522bd7..af3d2810553 100644
--- a/source/gameengine/PyDoc/GameLogic.py
+++ b/source/gameengine/PyDoc/GameLogic.py
@@ -14,8 +14,7 @@ Documentation for the GameLogic Module.
Examples::
# To get a controller:
- import GameLogic
- co = GameLogic.getCurrentController()
+ co = GameLogic.getCurrentController() # GameLogic is automatically imported
# To get the game object associated with this controller:
obj = co.getOwner()
@@ -42,6 +41,7 @@ Documentation for the GameLogic Module.
- L{SCA_MouseSensor}
- L{SCA_PropertySensor}
- L{SCA_RandomSensor}
+ - L{SCA_DelaySensor}
You can also access actuators linked to the controller::
# To get an actuator attached to the controller:
@@ -220,6 +220,13 @@ def setPhysicsTicRate(ticrate):
@param ticrate: The new update frequency (in Hz).
@type ticrate: float
"""
+def getAverageFrameRate():
+ """
+ Gets the estimated average framerate
+
+ @return: The estimed average framerate in frames per second
+ @rtype: float
+ """
def expandPath(path):
"""
@@ -236,3 +243,13 @@ def expandPath(path):
@return: The converted string
@rtype: string
"""
+
+def getBlendFileList(path = "//"):
+ """
+ Returns a list of blend files in the same directory as the open blend file, or from using the option argument.
+
+ @param path: Optional directory argument, will be expanded (like expandPath) into the full path.
+ @type path: string
+ @return: A list of filenames, with no directory prefix
+ @rtype: list
+ """
diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py
index a5ba5b1d634..ff9b4ffc95b 100644
--- a/source/gameengine/PyDoc/KX_GameObject.py
+++ b/source/gameengine/PyDoc/KX_GameObject.py
@@ -30,11 +30,11 @@ class KX_GameObject:
Delete this object, can be used inpace of the EndObject Actuator.
The actual removal of the object from the scene is delayed.
"""
- def getVisible(visible):
+ def getVisible():
"""
Gets the game object's visible flag.
- @type visible: boolean
+ @rtype: boolean
"""
def setVisible(visible):
"""
@@ -49,16 +49,25 @@ class KX_GameObject:
@rtype: int
@return: the objects state.
"""
- def setState():
+ def setState(state):
"""
- Sets the game object's visible flag.
+ Sets the game object's state flag.
The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29)
- @type visible: boolean
+ @type state: integer
"""
def setPosition(pos):
"""
- Sets the game object's position.
+ Sets the game object's position.
+ Global coordinates for root object, local for child objects.
+
+
+ @type pos: [x, y, z]
+ @param pos: the new position, in local coordinates.
+ """
+ def setWorldPosition(pos):
+ """
+ Sets the game object's position in world coordinates regardless if the object is root or child.
@type pos: [x, y, z]
@param pos: the new position, in world coordinates.
@@ -135,6 +144,26 @@ class KX_GameObject:
@param local: - False: you get the "global" velocity ie: relative to world orientation (default).
- True: you get the "local" velocity ie: relative to object orientation.
"""
+ def getAngularVelocity(local = 0):
+ """
+ Gets the game object's angular velocity.
+
+ @type local: boolean
+ @param local: - False: you get the "global" velocity ie: relative to world orientation (default).
+ - True: you get the "local" velocity ie: relative to object orientation.
+ @rtype: list [vx, vy, vz]
+ @return: the object's angular velocity.
+ """
+ def setAngularVelocity(velocity, local = 0):
+ """
+ Sets the game object's angular velocity.
+
+ @type velocity: 3d vector.
+ @param velocity: angular velocity vector.
+ @type local: boolean
+ @param local: - False: you get the "global" velocity ie: relative to world orientation (default).
+ - True: you get the "local" velocity ie: relative to object orientation.
+ """
def getVelocity(point):
"""
Gets the game object's velocity at the specified point.
@@ -280,11 +309,13 @@ class KX_GameObject:
@rtype: L{KX_GameObject}
@return: the first object hit or None if no object or object does not match prop
"""
- def rayCast(to,from,dist,prop):
+ def rayCast(objto,objfrom,dist,prop,face,xray,poly):
"""
Look from a point/object to another point/object and find first object hit within dist that matches prop.
- Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit.
- Ex:
+ if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit.
+ if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element.
+
+ Ex::
# shoot along the axis gun-gunAim (gunAim should be collision-free)
ob,point,normal = gun.rayCast(gunAim,None,50)
if ob:
@@ -292,21 +323,42 @@ class KX_GameObject:
Notes:
The ray ignores the object on which the method is called.
- If is casted from/to object center or explicit [x,y,z] points.
- The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray
- If a property was specified and the first object hit does not have that property, there is no hit
- The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects.
+ It is casted from/to object center or explicit [x,y,z] points.
+
+ The face paremeter determines the orientation of the normal::
+ 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside)
+ 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect)
+
+ The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray.
+ The prop and xray parameters interact as follow::
+ prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray.
+ prop off, xray on : idem.
+ prop on, xray off: return closest hit if it matches prop, no hit otherwise.
+ prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray.
+ The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray.
+ If there is no hit or the hit object is not a static mesh, None is returned as 4th element.
+
+ The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects.
- @param to: [x,y,z] or object to which the ray is casted
- @type to: L{KX_GameObject} or 3-tuple
- @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center
- @type from: L{KX_GameObject} or 3-tuple or None
+ @param objto: [x,y,z] or object to which the ray is casted
+ @type objto: L{KX_GameObject} or 3-tuple
+ @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center
+ @type objfrom: L{KX_GameObject} or 3-tuple or None
@param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to
@type dist: float
@param prop: property name that object must have; can be omitted => detect any object
@type prop: string
- @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz))
- @return: (object,hitpoint,hitnormal) or (None,None,None)
+ @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin
+ @type face: int
+ @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object
+ @type xray: int
+ @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy}
+ @type poly: int
+ @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz))
+ or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy})
+ @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon)
+ If no hit, returns (None,None,None) or (None,None,None,None)
+ If the object hit is not a static mesh, polygon is None
"""
diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py
index e43fa3598f0..03bc36b6ac1 100644
--- a/source/gameengine/PyDoc/KX_MeshProxy.py
+++ b/source/gameengine/PyDoc/KX_MeshProxy.py
@@ -95,6 +95,21 @@ class KX_MeshProxy:
@rtype: L{KX_VertexProxy}
@return: a vertex object.
"""
+ def getNumPolygons():
+ """
+ Returns the number of polygon in the mesh.
+
+ @rtype: integer
+ """
+ def getPolygon(index):
+ """
+ Gets the specified polygon from the mesh.
+
+ @type index: integer
+ @param index: polygon number
+ @rtype: L{KX_PolyProxy}
+ @return: a polygon object.
+ """
def reinstancePhysicsMesh():
"""
Updates the physics system with the changed mesh.
diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py
index db577d21e6f..b7b76473292 100644
--- a/source/gameengine/PyDoc/KX_ObjectActuator.py
+++ b/source/gameengine/PyDoc/KX_ObjectActuator.py
@@ -111,9 +111,7 @@ class KX_ObjectActuator(SCA_IActuator):
For the servo control actuator, this is the target speed.
@rtype: list [vx, vy, vz, local]
- @return: A four item list, containing the vector velocity, and whether
- the velocity is applied in local coordinates (True) or world
- coordinates (False)
+ @return: A four item list, containing the vector velocity, and whether the velocity is applied in local coordinates (True) or world coordinates (False)
"""
def setLinearVelocity(vx, vy, vz, local):
"""
diff --git a/source/gameengine/PyDoc/KX_PolyProxy.py b/source/gameengine/PyDoc/KX_PolyProxy.py
new file mode 100644
index 00000000000..bcd42c2ac2e
--- /dev/null
+++ b/source/gameengine/PyDoc/KX_PolyProxy.py
@@ -0,0 +1,100 @@
+# $Id$
+# Documentation for the polygon proxy class
+
+class KX_PolyProxy:
+ """
+ A polygon holds the index of the vertex forming the poylgon.
+
+ Note:
+ The polygon attributes are read-only, you need to retrieve the vertex proxy if you want
+ to change the vertex settings.
+
+ @ivar matname: The name of polygon material, empty if no material.
+ @type matname: string
+ @ivar material: The material of the polygon
+ @type material: L{KX_PolygonMaterial} or KX_BlenderMaterial
+ @ivar texture: The texture name of the polygon.
+ @type texture: string
+ @ivar matid: The material index of the polygon, use this to retrieve vertex proxy from mesh proxy
+ @type matid: integer
+ @ivar v1: vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy
+ @type v1: integer
+ @ivar v2: vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy
+ @type v2: integer
+ @ivar v3: vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy
+ @type v3: integer
+ @ivar v4: vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex
+ use this to retrieve vertex proxy from mesh proxy
+ @type v4: integer
+ @ivar visible: visible state of the polygon: 1=visible, 0=invisible
+ @type visible: integer
+ @ivar collide: collide state of the polygon: 1=receives collision, 0=collision free.
+ @type collide: integer
+ """
+
+ def getMaterialName():
+ """
+ Returns the polygon material name with MA prefix
+
+ @rtype: string
+ @return: material name
+ """
+ def getMaterial():
+ """
+ Returns the polygon material
+
+ @rtype: L{KX_PolygonMaterial} or KX_BlenderMaterial
+ """
+ def getTextureName():
+ """
+ Returns the polygon texture name
+
+ @rtype: string
+ @return: texture name
+ """
+ def getMaterialIndex():
+ """
+ Returns the material bucket index of the polygon.
+ This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}.
+
+ @rtype: integer
+ @return: the material index in the mesh
+ """
+ def getNumVertex():
+ """
+ Returns the number of vertex of the polygon.
+
+ @rtype: integer
+ @return: number of vertex, 3 or 4.
+ """
+ def isVisible():
+ """
+ Returns whether the polygon is visible or not
+
+ @rtype: integer
+ @return: 0=invisible, 1=visible
+ """
+ def isCollider():
+ """
+ Returns whether the polygon is receives collision or not
+
+ @rtype: integer
+ @return: 0=collision free, 1=receives collision
+ """
+ def getVertexIndex(vertex):
+ """
+ Returns the mesh vertex index of a polygon vertex
+ This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}.
+
+ @type vertex: integer
+ @param vertex: index of the vertex in the polygon: 0->3
+ @rtype: integer
+ @return: mesh vertex index
+ """
+ def getMesh():
+ """
+ Returns a mesh proxy
+
+ @rtype: L{KX_MeshProxy}
+ @return: mesh proxy
+ """
diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
index 4f2bf85bff3..c3b2e947ddb 100644
--- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
+++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py
@@ -66,6 +66,23 @@ class KX_SCA_AddObjectActuator(SCA_IActuator):
@rtype: list [vx, vy, vz]
"""
+ def setAngularVelocity(vx, vy, vz):
+ """
+ Sets the initial angular velocity of added objects.
+
+ @type vx: float
+ @param vx: the x component of the initial angular velocity.
+ @type vy: float
+ @param vy: the y component of the initial angular velocity.
+ @type vz: float
+ @param vz: the z component of the initial angular velocity.
+ """
+ def getAngularVelocity():
+ """
+ Returns the initial angular velocity of added objects.
+
+ @rtype: list [vx, vy, vz]
+ """
def getLastCreatedObject():
"""
Returns the last object created by this actuator.
diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
index eb00a91a4ce..498f6072e23 100644
--- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
+++ b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py
@@ -59,8 +59,9 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
def setMesh(name):
"""
Sets the name of the mesh that will replace the current one.
+ When the name is None it will unset the mesh value so no action is taken.
- @type name: string
+ @type name: string or None
"""
def getMesh():
"""
@@ -68,6 +69,6 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator):
Returns None if no mesh has been scheduled to be added.
- @rtype: string
+ @rtype: string or None
"""
diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py
index 2ecd94f38ae..948302991b7 100644
--- a/source/gameengine/PyDoc/KX_TrackToActuator.py
+++ b/source/gameengine/PyDoc/KX_TrackToActuator.py
@@ -21,7 +21,7 @@ class KX_TrackToActuator(SCA_IActuator):
@type object: L{KX_GameObject}, string or None
@param object: Either a reference to a game object or the name of the object to track.
"""
- def getObject():
+ def getObject(name_only):
"""
Returns the name of the object to track.
diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py
index f0e48b6ed43..cdda87fcb49 100644
--- a/source/gameengine/PyDoc/Rasterizer.py
+++ b/source/gameengine/PyDoc/Rasterizer.py
@@ -37,6 +37,10 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M
# Centre the mouse
Rasterizer.setMousePosition(Rasterizer.getWindowWidth()/2, Rasterizer.getWindowHeight()/2)
+@group Material Types: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL
+@var KX_TEXFACE_MATERIAL: Materials as defined by the texture face settings.
+@var KX_BLENDER_MULTITEX_MATERIAL: Materials approximating blender materials with multitexturing.
+@var KX_BLENDER_BLENDER_MATERIAL: Materials approximating blender materials with GLSL.
"""
@@ -84,7 +88,8 @@ def setMousePosition(x, y):
"""
Sets the mouse cursor position.
- @type x, y: integer
+ @type x: integer
+ @type y: integer
"""
def setBackgroundColor(rgba):
@@ -145,3 +150,46 @@ def getFocalLength():
@rtype: float
"""
+
+def setMaterialMode(mode):
+ """
+ Set the material mode to use for OpenGL rendering.
+
+ @type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL
+ @note: Changes will only affect newly created scenes.
+ """
+
+def getMaterialMode(mode):
+ """
+ Get the material mode to use for OpenGL rendering.
+
+ @rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL
+ """
+
+def setGLSLMaterialSetting(setting, enable):
+ """
+ Enables or disables a GLSL material setting.
+
+ @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures)
+ @type enable: boolean
+ """
+
+def getGLSLMaterialSetting(setting, enable):
+ """
+ Get the state of a GLSL material setting.
+
+ @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures)
+ @rtype: boolean
+ """
+def drawLine(from,to,color):
+ """
+ Draw a line in the 3D scene.
+
+ @param from: the origin of the line
+ @type from: list [x, y, z]
+ @param to: the end of the line
+ @type to: list [x, y, z]
+ @param color: the color of the line
+ @type color: list [r, g, b]
+ """
+
diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py
new file mode 100644
index 00000000000..19df589ea7b
--- /dev/null
+++ b/source/gameengine/PyDoc/SCA_DelaySensor.py
@@ -0,0 +1,56 @@
+# $Id$
+# Documentation for SCA_DelaySensor
+from SCA_ISensor import *
+
+class SCA_DelaySensor(SCA_ISensor):
+ """
+ The Delay sensor generates positive and negative triggers at precise time,
+ expressed in number of frames. The delay parameter defines the length
+ of the initial OFF period. A positive trigger is generated at the end of this period.
+ The duration parameter defines the length of the ON period following the OFF period.
+ There is a negative trigger at the end of the ON period. If duration is 0, the sensor
+ stays ON and there is no negative trigger.
+ The sensor runs the OFF-ON cycle once unless the repeat option is set: the
+ OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0).
+ Use SCA_ISensor::reset() at any time to restart sensor.
+ """
+ def setDelay(delay):
+ """
+ Set the initial delay before the positive trigger.
+
+ @param delay: length of the initial OFF period as number of frame, 0 for immediate trigger
+ @type delay: integer
+ """
+ def setDuration(duration):
+ """
+ Set the duration of the ON pulse after initial delay and the generation of the positive trigger.
+ If duration is greater than 0, a negative trigger is sent at the end of the ON pulse.
+
+ @param duration: length of the ON period in number of frame after the initial OFF period
+ @type duration: integer
+ """
+ def setRepeat(repeat):
+ """
+ Set if the sensor repeat mode.
+
+ @param repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once.
+ @type repeat: integer
+ """
+ def getDelay():
+ """
+ Return the delay parameter value.
+
+ @rtype: integer
+ """
+ def getDuration():
+ """
+ Return the duration parameter value
+
+ @rtype: integer
+ """
+ def getRepeat():
+ """
+ Return the repeat parameter value
+
+ @rtype: KX_TRUE or KX_FALSE
+ """
diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py
index 0ebc2debb31..14858505e24 100644
--- a/source/gameengine/PyDoc/SCA_ISensor.py
+++ b/source/gameengine/PyDoc/SCA_ISensor.py
@@ -9,7 +9,12 @@ class SCA_ISensor(SCA_ILogicBrick):
def isPositive():
"""
- True if this sensor brick has been activated.
+ True if this sensor brick is in a positive state.
+ """
+
+ def isTriggered():
+ """
+ True if this sensor brick has triggered the current controller.
"""
def getUsePosPulseMode():
@@ -77,4 +82,10 @@ class SCA_ISensor(SCA_ILogicBrick):
@param level: Detect level instead of edge? (KX_TRUE, KX_FALSE)
@type level: boolean
"""
+ def reset():
+ """
+ Reset sensor internal state, effect depends on the type of sensor and settings.
+
+ The sensor is put in its initial state as if it was just activated.
+ """
diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile
index e3b1f274ee5..917f70c7108 100644
--- a/source/gameengine/Rasterizer/Makefile
+++ b/source/gameengine/Rasterizer/Makefile
@@ -49,10 +49,6 @@ ifeq ($(OS),darwin)
CPPFLAGS += -fpascal-strings
endif
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
-
###############
SOURCEDIR = source/gameengine/Rasterizer
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
index ef206332057..6e5553d4781 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp
@@ -85,7 +85,7 @@ RAS_2DFilterManager::~RAS_2DFilterManager()
FreeTextures();
}
-unsigned int RAS_2DFilterManager::CreateShaderProgram(char* shadersource)
+unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource)
{
GLuint program = 0;
GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.h b/source/gameengine/Rasterizer/RAS_2DFilterManager.h
index f5998e1f093..c16bd41dd0e 100644
--- a/source/gameengine/Rasterizer/RAS_2DFilterManager.h
+++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.h
@@ -33,7 +33,7 @@
class RAS_2DFilterManager
{
private:
- unsigned int CreateShaderProgram(char* shadersource);
+ unsigned int CreateShaderProgram(const char* shadersource);
unsigned int CreateShaderProgram(int filtermode);
void AnalyseShader(int passindex, vector<STR_String>& propNames);
void StartShaderProgram(int passindex);
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
index 82bdce44519..f7938bb62e6 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp
@@ -26,10 +26,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef WIN32
// don't show these anoying STL warnings
#pragma warning (disable:4786)
@@ -39,168 +35,234 @@
#include "RAS_MaterialBucket.h"
#include "STR_HashedString.h"
#include "RAS_MeshObject.h"
-#define KX_NUM_MATERIALBUCKETS 100
#include "RAS_IRasterizer.h"
#include "RAS_IRenderTools.h"
#include "RAS_BucketManager.h"
+#include <algorithm>
#include <set>
-RAS_BucketManager::RAS_BucketManager()
+/* sorting */
+
+struct RAS_BucketManager::sortedmeshslot
{
+public:
+ MT_Scalar m_z; /* depth */
+ RAS_MeshSlot *m_ms; /* mesh slot */
+ RAS_MaterialBucket *m_bucket; /* buck mesh slot came from */
-}
+ sortedmeshslot() {}
-RAS_BucketManager::~RAS_BucketManager()
-{
- RAS_BucketManagerClearAll();
-}
+ void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm)
+ {
+ // would be good to use the actual bounding box center instead
+ MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]);
-/**
- * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.)
- */
-struct RAS_BucketManager::alphamesh
-{
-public:
- MT_Scalar m_z;
- RAS_MaterialBucket::T_MeshSlotList::iterator m_ms;
- RAS_MaterialBucket *m_bucket;
- alphamesh(MT_Scalar z, RAS_MaterialBucket::T_MeshSlotList::iterator &ms, RAS_MaterialBucket *bucket) :
- m_z(z),
- m_ms(ms),
- m_bucket(bucket)
- {}
+ m_z = MT_dot(pnorm, pos);
+ m_ms = ms;
+ m_bucket = bucket;
+ }
};
struct RAS_BucketManager::backtofront
{
- bool operator()(const alphamesh &a, const alphamesh &b)
+ bool operator()(const sortedmeshslot &a, const sortedmeshslot &b)
{
- return a.m_z < b.m_z;
+ return (a.m_z < b.m_z) || (a.m_z == b.m_z && a.m_ms < b.m_ms);
}
};
+
+struct RAS_BucketManager::fronttoback
+{
+ bool operator()(const sortedmeshslot &a, const sortedmeshslot &b)
+ {
+ return (a.m_z > b.m_z) || (a.m_z == b.m_z && a.m_ms > b.m_ms);
+ }
+};
+
+/* bucket manager */
+
+RAS_BucketManager::RAS_BucketManager()
+{
+
+}
+
+RAS_BucketManager::~RAS_BucketManager()
+{
+ BucketList::iterator it;
+
+ for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++)
+ delete (*it);
+
+ for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++)
+ delete(*it);
+ m_SolidBuckets.clear();
+ m_AlphaBuckets.clear();
+}
+
+void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha)
+{
+ BucketList::iterator bit;
+ list<RAS_MeshSlot>::iterator mit;
+ size_t size = 0, i = 0;
+
+ /* Camera's near plane equation: pnorm.dot(point) + pval,
+ * but we leave out pval since it's constant anyway */
+ const MT_Vector3 pnorm(cameratrans.getBasis()[2]);
+
+ for (bit = buckets.begin(); bit != buckets.end(); ++bit)
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit)
+ if (!mit->IsCulled())
+ size++;
+
+ slots.resize(size);
+
+ for (bit = buckets.begin(); bit != buckets.end(); ++bit)
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit)
+ if (!mit->IsCulled())
+ slots[i++].set(&*mit, *bit, pnorm);
+
+ if(alpha)
+ sort(slots.begin(), slots.end(), backtofront());
+ else
+ sort(slots.begin(), slots.end(), fronttoback());
+}
void RAS_BucketManager::RenderAlphaBuckets(
const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
{
- BucketList::iterator bit;
- std::multiset<alphamesh, backtofront> alphameshset;
- RAS_MaterialBucket::T_MeshSlotList::iterator mit;
+ vector<sortedmeshslot> slots;
+ vector<sortedmeshslot>::iterator sit;
+
+ // Having depth masks disabled/enabled gives different artifacts in
+ // case no sorting is done or is done inexact. For compatibility, we
+ // disable it.
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
+
+ OrderBuckets(cameratrans, m_AlphaBuckets, slots, true);
- /* Camera's near plane equation: cam_norm.dot(point) + cam_origin */
- const MT_Vector3 cam_norm(cameratrans.getBasis()[2]);
- const MT_Scalar cam_origin = cameratrans.getOrigin()[2];
- for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit)
- {
- for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit)
- {
- if ((*mit).m_bVisible)
- {
- MT_Point3 pos((*mit).m_OpenGLMatrix[12], (*mit).m_OpenGLMatrix[13], (*mit).m_OpenGLMatrix[14]);
- alphameshset.insert(alphamesh(MT_dot(cam_norm, pos) + cam_origin, mit, *bit));
- }
+ for(sit=slots.begin(); sit!=slots.end(); ++sit) {
+ rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj);
+
+ while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
+ sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
+ }
+
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+}
+
+void RAS_BucketManager::RenderSolidBuckets(
+ const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
+{
+ BucketList::iterator bit;
+ list<RAS_MeshSlot>::iterator mit;
+
+ rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+
+ for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+ if (mit->IsCulled())
+ continue;
+
+ rendertools->SetClientObject(rasty, mit->m_clientObj);
+
+ while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools))
+ (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit);
}
}
- // It shouldn't be strictly necessary to disable depth writes; but
- // it is needed for compatibility.
- rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED);
+ /* this code draws meshes order front-to-back instead to reduce overdraw.
+ * it turned out slower due to much material state switching, a more clever
+ * algorithm might do better. */
+#if 0
+ vector<sortedmeshslot> slots;
+ vector<sortedmeshslot>::iterator sit;
- RAS_IRasterizer::DrawMode drawingmode;
- std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin();
- for (; msit != alphameshset.end(); ++msit)
- {
- rendertools->SetClientObject((*(*msit).m_ms).m_clientObj);
- while ((*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools, drawingmode))
- (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, drawingmode);
+ OrderBuckets(cameratrans, m_SolidBuckets, slots, false);
+
+ for(sit=slots.begin(); sit!=slots.end(); ++sit) {
+ rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj);
+
+ while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
+ sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
}
-
- rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
+#endif
}
void RAS_BucketManager::Renderbuckets(
const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
{
- BucketList::iterator bucket;
-
- rasty->EnableTextures(false);
- rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);
-
- // beginning each frame, clear (texture/material) caching information
+ /* beginning each frame, clear (texture/material) caching information */
rasty->ClearCachingInfo();
- RAS_MaterialBucket::StartFrame();
-
- for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket)
- (*bucket)->Render(cameratrans,rasty,rendertools);
-
+ RenderSolidBuckets(cameratrans, rasty, rendertools);
RenderAlphaBuckets(cameratrans, rasty, rendertools);
- RAS_MaterialBucket::EndFrame();
+
+ rendertools->SetClientObject(rasty, NULL);
}
RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated)
{
- bucketCreated = false;
BucketList::iterator it;
- for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++)
- {
+
+ bucketCreated = false;
+
+ for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++)
if (*(*it)->GetPolyMaterial() == *material)
return *it;
- }
for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++)
- {
if (*(*it)->GetPolyMaterial() == *material)
return *it;
- }
RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material);
bucketCreated = true;
+
if (bucket->IsAlpha())
m_AlphaBuckets.push_back(bucket);
else
- m_MaterialBuckets.push_back(bucket);
+ m_SolidBuckets.push_back(bucket);
return bucket;
}
-void RAS_BucketManager::RAS_BucketManagerClearAll()
+void RAS_BucketManager::OptimizeBuckets(MT_Scalar distance)
{
- BucketList::iterator it;
- for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++)
- {
- delete (*it);
- }
- for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++)
- {
- delete(*it);
- }
+ BucketList::iterator bit;
- m_MaterialBuckets.clear();
- m_AlphaBuckets.clear();
+ distance = 10.0;
+
+ for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit)
+ (*bit)->Optimize(distance);
+ for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit)
+ (*bit)->Optimize(distance);
}
-void RAS_BucketManager::ReleaseDisplayLists()
+void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat)
{
BucketList::iterator bit;
- RAS_MaterialBucket::T_MeshSlotList::iterator mit;
+ list<RAS_MeshSlot>::iterator mit;
- for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) {
- for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
- if(mit->m_DisplayList) {
- mit->m_DisplayList->Release();
- mit->m_DisplayList = NULL;
+ for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
+ if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+ if(mit->m_DisplayList) {
+ mit->m_DisplayList->Release();
+ mit->m_DisplayList = NULL;
+ }
}
}
}
for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) {
- for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
- if(mit->m_DisplayList) {
- mit->m_DisplayList->Release();
- mit->m_DisplayList = NULL;
+ if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) {
+ for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
+ if(mit->m_DisplayList) {
+ mit->m_DisplayList->Release();
+ mit->m_DisplayList = NULL;
+ }
}
}
}
diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h
index 08b67ed022f..74526f365a0 100644
--- a/source/gameengine/Rasterizer/RAS_BucketManager.h
+++ b/source/gameengine/Rasterizer/RAS_BucketManager.h
@@ -39,32 +39,33 @@
class RAS_BucketManager
{
- //GEN_Map<class RAS_IPolyMaterial,class RAS_MaterialBucket*> m_MaterialBuckets;
-
typedef std::vector<class RAS_MaterialBucket*> BucketList;
- BucketList m_MaterialBuckets;
+ BucketList m_SolidBuckets;
BucketList m_AlphaBuckets;
- struct alphamesh;
+ struct sortedmeshslot;
struct backtofront;
+ struct fronttoback;
public:
RAS_BucketManager();
virtual ~RAS_BucketManager();
- void RenderAlphaBuckets(const MT_Transform& cameratrans,
- RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
void Renderbuckets(const MT_Transform & cameratrans,
- RAS_IRasterizer* rasty,
- class RAS_IRenderTools* rendertools);
+ RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated);
+ void OptimizeBuckets(MT_Scalar distance);
- void ReleaseDisplayLists();
+ void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL);
private:
- void RAS_BucketManagerClearAll();
+ void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha);
+ void RenderSolidBuckets(const MT_Transform& cameratrans,
+ RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
+ void RenderAlphaBuckets(const MT_Transform& cameratrans,
+ RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools);
};
#endif //__RAS_BUCKETMANAGER
diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h
index 4e8484ab880..3332ac4c0a7 100644
--- a/source/gameengine/Rasterizer/RAS_Deformer.h
+++ b/source/gameengine/Rasterizer/RAS_Deformer.h
@@ -44,7 +44,11 @@ public:
virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)=0;
virtual bool Apply(class RAS_IPolyMaterial *polymat)=0;
virtual bool Update(void)=0;
- virtual RAS_Deformer *GetReplica()=0;
+ virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)=0;
+ virtual bool SkipVertexTransform()
+ {
+ return false;
+ }
protected:
class RAS_MeshObject *m_pMesh;
};
diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h
index dcb48c1c2a0..9cb59f300f7 100644
--- a/source/gameengine/Rasterizer/RAS_FramingManager.h
+++ b/source/gameengine/Rasterizer/RAS_FramingManager.h
@@ -108,6 +108,13 @@ public :
) const {
return m_frame_type;
};
+
+ void
+ SetFrameType(
+ RAS_FrameType type
+ ) {
+ m_frame_type = type;
+ };
float
BarRed(
@@ -140,14 +147,6 @@ public :
};
private :
-
- /**
- * private to force use of public constructor
- */
-
- RAS_FrameSettings(
- const RAS_FrameSettings &
- );
RAS_FrameType m_frame_type;
float m_bar_r;
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
index 4ee06d96603..fb3607f89f4 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
@@ -42,11 +42,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
int transp,
bool alpha,
bool zsort,
- int lightlayer,
- bool bIsTriangle,
- void* clientobject=NULL) :
-
- m_texturename(texname),
+ int lightlayer)
+ : m_texturename(texname),
m_materialname(matname),
m_tile(tile),
m_tilexrep(tilexrep),
@@ -56,7 +53,6 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
m_alpha(alpha),
m_zsort(zsort),
m_lightlayer(lightlayer),
- m_bIsTriangle(bIsTriangle),
m_polymatid(m_newpolymatid++),
m_flag(0),
m_multimode(0)
@@ -72,15 +68,16 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const
{
if(m_flag &RAS_BLENDERMAT)
{
- return (
+ bool test = (
this->m_multimode == lhs.m_multimode &&
this->m_flag == lhs.m_flag &&
this->m_drawingmode == lhs.m_drawingmode &&
this->m_transp == lhs.m_transp &&
- this->m_lightlayer == lhs.m_lightlayer &&
this->m_texturename.hash() == lhs.m_texturename.hash() &&
this->m_materialname.hash() == lhs.m_materialname.hash()
);
+
+ return test;
}
else
{
@@ -92,8 +89,6 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const
this->m_alpha == lhs.m_alpha &&
this->m_zsort == lhs.m_zsort &&
this->m_drawingmode == lhs.m_drawingmode &&
- this->m_bIsTriangle == lhs.m_bIsTriangle &&
- this->m_lightlayer == lhs.m_lightlayer &&
this->m_texturename.hash() == lhs.m_texturename.hash() &&
this->m_materialname.hash() == lhs.m_materialname.hash()
);
@@ -123,11 +118,6 @@ bool RAS_IPolyMaterial::IsZSort() const
return m_zsort;
}
-bool RAS_IPolyMaterial::UsesTriangles() const
-{
- return m_bIsTriangle;
-}
-
unsigned int RAS_IPolyMaterial::hash() const
{
return m_texturename.hash();
@@ -172,5 +162,10 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const
return dolights;
}
+bool RAS_IPolyMaterial::UsesObjectColor() const
+{
+ return !(m_flag & RAS_BLENDERGLSL);
+}
+
unsigned int RAS_IPolyMaterial::m_newpolymatid = 0;
diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
index 8fc53e6b038..218dd91cb30 100644
--- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
+++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
@@ -71,7 +71,6 @@ protected:
bool m_alpha;
bool m_zsort;
int m_lightlayer;
- bool m_bIsTriangle;
unsigned int m_polymatid;
static unsigned int m_newpolymatid;
@@ -106,9 +105,7 @@ public:
int transp,
bool alpha,
bool zsort,
- int lightlayer,
- bool bIsTriangle,
- void* clientobject);
+ int lightlayer);
virtual ~RAS_IPolyMaterial() {};
/**
@@ -129,14 +126,13 @@ public:
{
return false;
}
- virtual void ActivateMeshSlot(const class KX_MeshSlot & ms, RAS_IRasterizer* rasty) const {}
+ virtual void ActivateMeshSlot(const class RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const {}
virtual bool Equals(const RAS_IPolyMaterial& lhs) const;
bool Less(const RAS_IPolyMaterial& rhs) const;
int GetLightLayer() const;
bool IsAlpha() const;
bool IsZSort() const;
- bool UsesTriangles() const;
unsigned int hash() const;
int GetDrawingMode() const;
const STR_String& GetMaterialName() const;
@@ -145,6 +141,7 @@ public:
const unsigned int GetFlag() const;
virtual bool UsesLighting(RAS_IRasterizer *rasty) const;
+ virtual bool UsesObjectColor() const;
/*
* PreCalculate texture gen
diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h
index 9e03212283e..411b28fa3b7 100644
--- a/source/gameengine/Rasterizer/RAS_IRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h
@@ -169,6 +169,10 @@ public:
*/
virtual bool BeginFrame(int drawingmode, double time)=0;
/**
+ * ClearColorBuffer clears the color buffer.
+ */
+ virtual void ClearColorBuffer()=0;
+ /**
* ClearDepthBuffer clears the depth buffer.
*/
virtual void ClearDepthBuffer()=0;
@@ -181,7 +185,8 @@ public:
*/
virtual void EndFrame()=0;
/**
- * SetRenderArea sets the render area from the 2d canvas
+ * SetRenderArea sets the render area from the 2d canvas.
+ * Returns true if only of subset of the canvas is used.
*/
virtual void SetRenderArea()=0;
@@ -195,6 +200,7 @@ public:
* @return true if stereo mode is enabled.
*/
virtual bool Stereo()=0;
+ virtual bool InterlacedStereo()=0;
/**
* Sets which eye buffer subsequent primitives will be rendered to.
*/
@@ -217,39 +223,18 @@ public:
// Drawing Functions
/**
- * IndexPrimitives: Renders primitives.
- * @param vertexarrays is an array of vertex arrays
- * @param indexarrays is an array of index arrays
- * @param mode determines the type of primitive stored in the vertex/index arrays
- * @param useObjectColor will render the object using @param rgbacolor instead of
- * vertex colors.
- */
- virtual void IndexPrimitives( const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)=0;
-
- virtual void IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)=0;
+ * IndexPrimitives: Renders primitives from mesh slot.
+ */
+ virtual void IndexPrimitives(class RAS_MeshSlot& ms)=0;
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0;
/**
* IndexPrimitives_3DText will render text into the polygons.
* The text to be rendered is from @param rendertools client object's text property.
*/
- virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
+ virtual void IndexPrimitives_3DText(class RAS_MeshSlot& ms,
class RAS_IPolyMaterial* polymat,
- class RAS_IRenderTools* rendertools,
- bool useObjectColor,
- const MT_Vector4& rgbacolor)=0;
+ class RAS_IRenderTools* rendertools)=0;
virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0;
/* This one should become our final version, methinks. */
@@ -271,9 +256,6 @@ public:
virtual const MT_Point3& GetCameraPosition()=0;
/**
*/
- virtual void LoadViewMatrix()=0;
- /**
- */
virtual void SetFog(float start,
float dist,
float r,
@@ -309,9 +291,6 @@ public:
*/
virtual int GetDrawingMode()=0;
/**
- */
- virtual void EnableTextures(bool enable)=0;
- /**
* Sets face culling
*/
virtual void SetCullFace(bool enable)=0;
@@ -385,7 +364,9 @@ public:
virtual void SetAttribNum(int num) = 0;
virtual void SetTexCoord(TexCoGen coords, int unit) = 0;
virtual void SetAttrib(TexCoGen coords, int unit) = 0;
- virtual void GetViewMatrix(MT_Matrix4x4 &mat) const = 0;
+
+ virtual const MT_Matrix4x4& GetViewMatrix() const = 0;
+ virtual const MT_Matrix4x4& GetViewInvMatrix() const = 0;
virtual bool QueryLists(){return false;}
virtual bool QueryArrays(){return false;}
@@ -398,6 +379,7 @@ public:
virtual void SetMotionBlurState(int newstate)=0;
virtual void SetBlendingMode(int blendmode)=0;
+ virtual void SetFrontFace(bool ccw)=0;
};
#endif //__RAS_IRASTERIZER
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp
index 2be9bb75ebf..555a3520bb4 100644
--- a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp
@@ -28,42 +28,22 @@
#include "RAS_IRenderTools.h"
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-void RAS_IRenderTools::SetViewMat(const MT_Transform& trans)
-{
- trans.getValue(m_viewmat);
-}
-
-
-
-void RAS_IRenderTools::SetClientObject(void* obj)
+void RAS_IRenderTools::SetClientObject(RAS_IRasterizer* rasty, void *obj)
{
if (m_clientobject != obj)
- {
m_clientobject = obj;
- m_modified = true;
- }
}
-
-
void RAS_IRenderTools::SetAuxilaryClientInfo(void* inf)
{
m_auxilaryClientInfo = inf;
}
-
-
void RAS_IRenderTools::AddLight(struct RAS_LightObject* lightobject)
{
m_lights.push_back(lightobject);
}
-
-
void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject)
{
std::vector<struct RAS_LightObject*>::iterator lit =
@@ -71,5 +51,5 @@ void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject)
if (!(lit==m_lights.end()))
m_lights.erase(lit);
-
}
+
diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h
index 54a663ba111..57f331e64cb 100644
--- a/source/gameengine/Rasterizer/RAS_IRenderTools.h
+++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h
@@ -44,12 +44,9 @@ class RAS_IRenderTools
{
protected:
- float m_viewmat[16];
void* m_clientobject;
void* m_auxilaryClientInfo;
- bool m_modified;
-
std::vector<struct RAS_LightObject*> m_lights;
RAS_2DFilterManager m_filtermanager;
@@ -68,8 +65,7 @@ public:
RAS_IRenderTools(
) :
- m_clientobject(NULL),
- m_modified(true)
+ m_clientobject(NULL)
{
};
@@ -131,24 +127,21 @@ public:
float v1[3],
float v2[3],
float v3[3],
- float v4[3]
+ float v4[3],
+ int glattrib
)=0;
virtual
- void
- SetViewMat(
- const MT_Transform& trans
- );
-
- virtual
- int
+ void
ProcessLighting(
- int layer
+ int layer,
+ const MT_Transform& trans
)=0;
virtual
void
SetClientObject(
+ RAS_IRasterizer* rasty,
void* obj
);
@@ -190,24 +183,6 @@ public:
virtual
void
Render2DFilters(RAS_ICanvas* canvas)=0;
-
- virtual
- class RAS_IPolyMaterial*
- CreateBlenderPolyMaterial(
- const STR_String &texname,
- bool ba,
- const STR_String& matname,
- int tile,
- int tilexrep,
- int tileyrep,
- int mode,
- bool transparant,
- bool zsort,
- int lightlayer,
- bool bIsTriangle,
- void* clientobject,
- void* tface
- )=0;
};
#endif //__RAS_IRENDERTOOLS
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
index 0015b6a251f..ad8d7ebd5b0 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
@@ -28,10 +28,6 @@
#include "RAS_MaterialBucket.h"
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef WIN32
#pragma warning (disable:4786)
#include <windows.h>
@@ -44,79 +40,423 @@
#include "RAS_MeshObject.h"
#include "RAS_Deformer.h" // __NLA
+/* mesh slot */
+
+RAS_MeshSlot::RAS_MeshSlot()
+{
+ m_clientObj = NULL;
+ m_pDeformer = NULL;
+ m_OpenGLMatrix = NULL;
+ m_mesh = NULL;
+ m_bucket = NULL;
+ m_bVisible = false;
+ m_bCulled = true;
+ m_bObjectColor = false;
+ m_RGBAcolor = MT_Vector4(0.0, 0.0, 0.0, 0.0);
+ m_DisplayList = NULL;
+ m_bDisplayList = true;
+ m_joinSlot = NULL;
+}
+
+RAS_MeshSlot::~RAS_MeshSlot()
+{
+ vector<RAS_DisplayArray*>::iterator it;
+
+ Split(true);
+
+ while(m_joinedSlots.size())
+ m_joinedSlots.front()->Split(true);
+ for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+ (*it)->m_users--;
+ if((*it)->m_users == 0)
+ delete *it;
+ }
+
+ if (m_DisplayList) {
+ m_DisplayList->Release();
+ m_DisplayList = NULL;
+ }
+}
-KX_VertexIndex::KX_VertexIndex(int size)
+RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot)
{
- m_size = size;
+ vector<RAS_DisplayArray*>::iterator it;
+
+ m_clientObj = NULL;
+ m_pDeformer = NULL;
+ m_OpenGLMatrix = NULL;
+ m_mesh = slot.m_mesh;
+ m_bucket = slot.m_bucket;
+ m_bVisible = slot.m_bVisible;
+ m_bCulled = slot.m_bCulled;
+ m_bObjectColor = slot.m_bObjectColor;
+ m_RGBAcolor = slot.m_RGBAcolor;
+ m_DisplayList = NULL;
+ m_bDisplayList = slot.m_bDisplayList;
+ m_joinSlot = NULL;
+ m_currentArray = slot.m_currentArray;
+ m_displayArrays = slot.m_displayArrays;
+ m_joinedSlots = slot.m_joinedSlots;
+
+ m_startarray = slot.m_startarray;
+ m_startvertex = slot.m_startvertex;
+ m_startindex = slot.m_startindex;
+ m_endarray = slot.m_endarray;
+ m_endvertex = slot.m_endvertex;
+ m_endindex = slot.m_endindex;
+
+ for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+ // don't copy display arrays for now because it breaks python
+ // access to vertices, but we'll need a solution if we want to
+ // join display arrays for reducing draw calls.
+ //*it = new RAS_DisplayArray(**it);
+ //(*it)->m_users = 1;
+
+ (*it)->m_users++;
+ }
}
+void RAS_MeshSlot::init(RAS_MaterialBucket *bucket, int numverts)
+{
+ m_bucket = bucket;
+
+ SetDisplayArray(numverts);
+ m_startarray = 0;
+ m_startvertex = 0;
+ m_startindex = 0;
+ m_endarray = 0;
+ m_endvertex = 0;
+ m_endindex = 0;
+}
-void KX_VertexIndex::SetIndex(short loc,unsigned int index)
+void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it)
{
- m_indexarray[loc]=index;
+ int startvertex, endvertex;
+ int startindex, endindex;
+
+ it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL;
+
+ if(it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) {
+ it.array = NULL;
+ it.vertex = NULL;
+ it.index = NULL;
+ it.startvertex = 0;
+ it.endvertex = 0;
+ it.totindex = 0;
+ }
+ else {
+ startvertex = m_startvertex;
+ endvertex = (m_startarray == m_endarray)? m_endvertex: it.array->m_vertex.size();
+ startindex = m_startindex;
+ endindex = (m_startarray == m_endarray)? m_endindex: it.array->m_index.size();
+
+ it.vertex = &it.array->m_vertex[0];
+ it.index = &it.array->m_index[startindex];
+ it.startvertex = startvertex;
+ it.endvertex = endvertex;
+ it.totindex = endindex-startindex;
+ it.arraynum = m_startarray;
+ }
}
-bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const
+void RAS_MeshSlot::next(RAS_MeshSlot::iterator& it)
{
- bool result = ((m_mesh < lhs.m_mesh ) ||
- ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix)));
-
- return result;
+ int startvertex, endvertex;
+ int startindex, endindex;
+
+ if(it.arraynum == (size_t)m_endarray) {
+ it.array = NULL;
+ it.vertex = NULL;
+ it.index = NULL;
+ it.startvertex = 0;
+ it.endvertex = 0;
+ it.totindex = 0;
+ }
+ else {
+ it.arraynum++;
+ it.array = m_displayArrays[it.arraynum];
+
+ startindex = 0;
+ endindex = (it.arraynum == (size_t)m_endarray)? m_endindex: it.array->m_index.size();
+ startvertex = 0;
+ endvertex = (it.arraynum == (size_t)m_endarray)? m_endvertex: it.array->m_vertex.size();
+
+ it.vertex = &it.array->m_vertex[0];
+ it.index = &it.array->m_index[startindex];
+ it.startvertex = startvertex;
+ it.endvertex = endvertex;
+ it.totindex = endindex-startindex;
+ }
}
-KX_MeshSlot::~KX_MeshSlot()
+bool RAS_MeshSlot::end(RAS_MeshSlot::iterator& it)
{
- if (m_DisplayList)
- m_DisplayList->Release();
+ return (it.array == NULL);
}
+RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray()
+{
+ return m_currentArray;
+}
-RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat)
- :m_bModified(true)
+void RAS_MeshSlot::SetDisplayArray(int numverts)
{
- m_material = mat;
+ vector<RAS_DisplayArray*>::iterator it;
+ RAS_DisplayArray *darray = NULL;
+
+ for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+ darray = *it;
+
+ if(darray->m_type == numverts) {
+ if(darray->m_index.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_INDEX)
+ darray = NULL;
+ else if(darray->m_vertex.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_VERTEX)
+ darray = NULL;
+ else
+ break;
+ }
+ else
+ darray = NULL;
+ }
+
+ if(!darray) {
+ darray = new RAS_DisplayArray();
+ darray->m_users = 1;
+
+ if(numverts == 2) darray->m_type = RAS_DisplayArray::LINE;
+ else if(numverts == 3) darray->m_type = RAS_DisplayArray::TRIANGLE;
+ else darray->m_type = RAS_DisplayArray::QUAD;
+
+ m_displayArrays.push_back(darray);
+
+ if(numverts == 2)
+ darray->m_type = RAS_DisplayArray::LINE;
+ else if(numverts == 3)
+ darray->m_type = RAS_DisplayArray::TRIANGLE;
+ else if(numverts == 4)
+ darray->m_type = RAS_DisplayArray::QUAD;
+
+ m_endarray = m_displayArrays.size()-1;
+ m_endvertex = 0;
+ m_endindex = 0;
+ }
+
+ m_currentArray = darray;
}
+void RAS_MeshSlot::AddPolygon(int numverts)
+{
+ SetDisplayArray(numverts);
+}
+int RAS_MeshSlot::AddVertex(const RAS_TexVert& tv)
+{
+ RAS_DisplayArray *darray;
+ int offset;
+
+ darray = m_currentArray;
+ darray->m_vertex.push_back(tv);
+ offset = darray->m_vertex.size()-1;
-RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const
-{
- return m_material;
+ if(darray == m_displayArrays[m_endarray])
+ m_endvertex++;
+
+ return offset;
}
+void RAS_MeshSlot::AddPolygonVertex(int offset)
+{
+ RAS_DisplayArray *darray;
+
+ darray = m_currentArray;
+ darray->m_index.push_back(offset);
+
+ if(darray == m_displayArrays[m_endarray])
+ m_endindex++;
+}
+bool RAS_MeshSlot::Equals(RAS_MeshSlot *target)
+{
+ if(!m_OpenGLMatrix || !target->m_OpenGLMatrix)
+ return false;
+ if(m_pDeformer || target->m_pDeformer)
+ return false;
+ if(m_bVisible != target->m_bVisible)
+ return false;
+ if(m_bObjectColor != target->m_bObjectColor)
+ return false;
+ if(m_bObjectColor && !(m_RGBAcolor == target->m_RGBAcolor))
+ return false;
-void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms)
+ return true;
+}
+
+bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance)
{
- m_meshSlots.insert(ms);
+ vector<RAS_DisplayArray*>::iterator it;
+ iterator mit;
+ size_t i;
+
+ // verify if we can join
+ if(m_joinSlot || m_joinedSlots.size() || target->m_joinSlot)
+ return false;
+
+ if(!Equals(target))
+ return false;
+
+ MT_Vector3 co(&m_OpenGLMatrix[12]);
+ MT_Vector3 targetco(&target->m_OpenGLMatrix[12]);
+
+ if((co - targetco).length() > distance)
+ return false;
+
+ MT_Matrix4x4 mat(m_OpenGLMatrix);
+ MT_Matrix4x4 targetmat(target->m_OpenGLMatrix);
+ targetmat.invert();
+
+ MT_Matrix4x4 transform = targetmat*mat;
+
+ // m_mesh, clientobj
+ m_joinSlot = target;
+ m_joinInvTransform = transform;
+ m_joinInvTransform.invert();
+ target->m_joinedSlots.push_back(this);
+
+ MT_Matrix4x4 ntransform = m_joinInvTransform.transposed();
+ ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f;
+
+ for(begin(mit); !end(mit); next(mit))
+ for(i=mit.startvertex; i<mit.endvertex; i++)
+ mit.vertex[i].Transform(transform, ntransform);
+
+ for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+ target->m_displayArrays.push_back(*it);
+ target->m_endarray++;
+ target->m_endvertex = target->m_displayArrays.back()->m_vertex.size();
+ target->m_endindex = target->m_displayArrays.back()->m_index.size();
+ }
+
+ if (m_DisplayList) {
+ m_DisplayList->Release();
+ m_DisplayList = NULL;
+ }
+ if (target->m_DisplayList) {
+ target->m_DisplayList->Release();
+ target->m_DisplayList = NULL;
+ }
+
+ return true;
+#if 0
+ return false;
+#endif
}
+bool RAS_MeshSlot::Split(bool force)
+{
+ list<RAS_MeshSlot*>::iterator jit;
+ RAS_MeshSlot *target = m_joinSlot;
+ vector<RAS_DisplayArray*>::iterator it, jt;
+ iterator mit;
+ size_t i, found0 = 0, found1 = 0;
+
+ if(target && (force || !Equals(target))) {
+ m_joinSlot = NULL;
+
+ for(jit=target->m_joinedSlots.begin(); jit!=target->m_joinedSlots.end(); jit++) {
+ if(*jit == this) {
+ target->m_joinedSlots.erase(jit);
+ found0 = 1;
+ break;
+ }
+ }
+
+ if(!found0)
+ abort();
+
+ for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
+ found1 = 0;
+ for(jt=target->m_displayArrays.begin(); jt!=target->m_displayArrays.end(); jt++) {
+ if(*jt == *it) {
+ target->m_displayArrays.erase(jt);
+ target->m_endarray--;
+ found1 = 1;
+ break;
+ }
+ }
+
+ if(!found1)
+ abort();
+ }
+
+ if(target->m_displayArrays.size()) {
+ target->m_endvertex = target->m_displayArrays.back()->m_vertex.size();
+ target->m_endindex = target->m_displayArrays.back()->m_index.size();
+ }
+ else {
+ target->m_endvertex = 0;
+ target->m_endindex = 0;
+ }
+
+ MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed();
+ ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f;
+
+ for(begin(mit); !end(mit); next(mit))
+ for(i=mit.startvertex; i<mit.endvertex; i++)
+ mit.vertex[i].Transform(m_joinInvTransform, ntransform);
+
+ if (target->m_DisplayList) {
+ target->m_DisplayList->Release();
+ target->m_DisplayList = NULL;
+ }
+
+ return true;
+ }
+ return false;
+}
-void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms)
+bool RAS_MeshSlot::IsCulled()
{
- T_MeshSlotList::iterator it = m_meshSlots.find(ms);
+ list<RAS_MeshSlot*>::iterator it;
- if (!(it == m_meshSlots.end()))
- m_meshSlots.erase(it);
-
+ if(m_joinSlot)
+ return true;
+ if(!m_bCulled)
+ return false;
+
+ for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++)
+ if(!(*it)->m_bCulled)
+ return false;
+
+ return true;
}
+/* material bucket sorting */
+
+struct RAS_MaterialBucket::less
+{
+ bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const
+ {
+ return *x->GetPolyMaterial() < *y->GetPolyMaterial();
+ }
+};
+
+/* material bucket */
+RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat)
+{
+ m_material = mat;
+}
-void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms,
- bool visible,
- bool color,
- const MT_Vector4& rgbavec)
+RAS_MaterialBucket::~RAS_MaterialBucket()
{
- T_MeshSlotList::iterator it = m_meshSlots.find(ms);
-
- assert (!(it == m_meshSlots.end()));
- (*it).m_bVisible = visible;
- (*it).m_bObjectColor = color;
- (*it).m_RGBAcolor= rgbavec;
+}
+
+RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const
+{
+ return m_material;
}
bool RAS_MaterialBucket::IsAlpha() const
@@ -129,162 +469,132 @@ bool RAS_MaterialBucket::IsZSort() const
return (m_material->IsZSort());
}
-
-
-void RAS_MaterialBucket::StartFrame()
+RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts)
{
-}
+ RAS_MeshSlot *ms;
+ m_meshSlots.push_back(RAS_MeshSlot());
+
+ ms = &m_meshSlots.back();
+ ms->init(this, numverts);
+ return ms;
+}
-void RAS_MaterialBucket::EndFrame()
+RAS_MeshSlot* RAS_MaterialBucket::CopyMesh(RAS_MeshSlot *ms)
{
+ m_meshSlots.push_back(RAS_MeshSlot(*ms));
+
+ return &m_meshSlots.back();
}
-unsigned int RAS_MaterialBucket::NumMeshSlots()
+void RAS_MaterialBucket::RemoveMesh(RAS_MeshSlot* ms)
{
- return m_meshSlots.size();
+ list<RAS_MeshSlot>::iterator it;
+
+ for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) {
+ if(&*it == ms) {
+ m_meshSlots.erase(it);
+ return;
+ }
+ }
}
-RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin()
+list<RAS_MeshSlot>::iterator RAS_MaterialBucket::msBegin()
{
return m_meshSlots.begin();
}
-RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd()
+list<RAS_MeshSlot>::iterator RAS_MaterialBucket::msEnd()
{
return m_meshSlots.end();
}
bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
- RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode &drawmode)
+ RAS_IRenderTools *rendertools)
{
- rendertools->SetViewMat(cameratrans);
-
if (!rasty->SetMaterial(*m_material))
return false;
if (m_material->UsesLighting(rasty))
- rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/);
+ rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans);
else
- rendertools->ProcessLighting(-1);
-
- if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID)
- drawmode = RAS_IRasterizer::KX_MODE_LINES;
- else if(m_material->UsesTriangles())
- drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES;
- else
- drawmode = RAS_IRasterizer::KX_MODE_QUADS;
+ rendertools->ProcessLighting(-1, cameratrans);
return true;
}
void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
- RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode)
+ RAS_IRenderTools* rendertools, RAS_MeshSlot &ms)
{
- if (!ms.m_bVisible)
- return;
-
m_material->ActivateMeshSlot(ms, rasty);
- /* __NLA Do the deformation */
if (ms.m_pDeformer)
{
ms.m_pDeformer->Apply(m_material);
// KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_)
}
- /* End __NLA */
- if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
- ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix));
+ if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
+ ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix));
rendertools->PushMatrix();
- rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode());
+ if (!ms.m_pDeformer || !ms.m_pDeformer->SkipVertexTransform())
+ {
+ rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode());
+ }
if(rasty->QueryLists())
- {
if(ms.m_DisplayList)
ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified());
- }
// verify if we can use display list, not for deformed object, and
// also don't create a new display list when drawing shadow buffers,
- // then it won't have texture coordinates for actual drawing
- KX_ListSlot **displaylist;
+ // then it won't have texture coordinates for actual drawing. also
+ // for zsort we can't make a display list, since the polygon order
+ // changes all the time.
if(ms.m_pDeformer)
- displaylist = 0;
+ ms.m_bDisplayList = false;
else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW)
- displaylist = 0;
+ ms.m_bDisplayList = false;
+ else if (IsZSort())
+ ms.m_bDisplayList = false;
+ else if(m_material->UsesObjectColor() && ms.m_bObjectColor)
+ ms.m_bDisplayList = false;
else
- displaylist = &ms.m_DisplayList;
+ ms.m_bDisplayList = true;
- // Use the text-specific IndexPrimitives for text faces
+ // for text drawing using faces
if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT)
- {
- rasty->IndexPrimitives_3DText(
- ms.m_mesh->GetVertexCache(m_material),
- ms.m_mesh->GetIndexCache(m_material),
- drawmode,
- m_material,
- rendertools, // needed for textprinting on polys
- ms.m_bObjectColor,
- ms.m_RGBAcolor);
- }
-
- // for using glMultiTexCoord
- else if((m_material->GetFlag() & RAS_MULTITEX))
- {
- rasty->IndexPrimitivesMulti(
- ms.m_mesh->GetVertexCache(m_material),
- ms.m_mesh->GetIndexCache(m_material),
- drawmode,
- ms.m_bObjectColor,
- ms.m_RGBAcolor,
- displaylist);
- }
-
- // Use the normal IndexPrimitives
+ rasty->IndexPrimitives_3DText(ms, m_material, rendertools);
+ // for multitexturing
+ else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL)))
+ rasty->IndexPrimitivesMulti(ms);
+ // use normal IndexPrimitives
else
- {
- rasty->IndexPrimitives(
- ms.m_mesh->GetVertexCache(m_material),
- ms.m_mesh->GetIndexCache(m_material),
- drawmode,
- ms.m_bObjectColor,
- ms.m_RGBAcolor,
- displaylist);
- }
+ rasty->IndexPrimitives(ms);
- if(rasty->QueryLists()) {
+ if(rasty->QueryLists())
if(ms.m_DisplayList)
ms.m_mesh->SetMeshModified(false);
- }
rendertools->PopMatrix();
}
-void RAS_MaterialBucket::Render(const MT_Transform& cameratrans,
- RAS_IRasterizer* rasty,
- RAS_IRenderTools* rendertools)
+void RAS_MaterialBucket::Optimize(MT_Scalar distance)
{
- if (m_meshSlots.begin()== m_meshSlots.end())
- return;
-
- //rendertools->SetViewMat(cameratrans);
-
- //rasty->SetMaterial(*m_material);
+ /* TODO: still have to check before this works correct:
+ * - lightlayer, frontface, text, billboard
+ * - make it work with physics */
- RAS_IRasterizer::DrawMode drawmode;
- for (T_MeshSlotList::const_iterator it = m_meshSlots.begin();
- ! (it == m_meshSlots.end()); ++it)
- {
- rendertools->SetClientObject((*it).m_clientObj);
- while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) {
- RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode);
- }
- }
- // to reset the eventual GL_CW mode
- rendertools->SetClientObject(NULL);
+#if 0
+ list<RAS_MeshSlot>::iterator it;
+ list<RAS_MeshSlot>::iterator jt;
+
+ // greed joining on all following buckets
+ for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++)
+ for(jt=it, jt++; jt!=m_meshSlots.end(); jt++)
+ jt->Join(&*it, distance);
+#endif
}
-
diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
index 4eef889c533..475f01d549a 100644
--- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h
+++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h
@@ -36,30 +36,15 @@
#include "MT_Transform.h"
#include "RAS_IPolygonMaterial.h"
#include "RAS_IRasterizer.h"
-#include "RAS_Deformer.h" // __NLA
+#include "RAS_Deformer.h"
+
#include <vector>
-#include <map>
#include <set>
+#include <list>
using namespace std;
-/**
- * KX_VertexIndex
- */
-struct KX_VertexIndex {
-public:
- KX_VertexIndex(int size);
- void SetIndex(short loc,unsigned int index);
-
- // The vertex array
- short m_vtxarray;
- // An index into the vertex array for up to 4 verticies
- unsigned short m_indexarray[4];
- short m_size;
-};
+/* Display List Slot */
-/**
- * KX_ListSlot.
- */
class KX_ListSlot
{
protected:
@@ -80,91 +65,149 @@ public:
virtual void SetModified(bool mod)=0;
};
-/**
- * KX_MeshSlot.
- */
-class KX_MeshSlot
+class RAS_DisplayArray;
+class RAS_MeshSlot;
+class RAS_MeshMaterial;
+class RAS_MaterialBucket;
+
+/* An array with data used for OpenGL drawing */
+
+class RAS_DisplayArray
{
public:
- void* m_clientObj;
- RAS_Deformer* m_pDeformer; // __NLA
- double* m_OpenGLMatrix;
- class RAS_MeshObject* m_mesh;
- mutable bool m_bVisible; // for visibility
- mutable bool m_bObjectColor;
- mutable MT_Vector4 m_RGBAcolor;
- mutable KX_ListSlot* m_DisplayList; // for lists
- KX_MeshSlot() :
- m_pDeformer(NULL),
- m_bVisible(true),
- m_DisplayList(0)
- {
- }
- ~KX_MeshSlot();
- bool Less(const KX_MeshSlot& lhs) const;
+ vector<RAS_TexVert> m_vertex;
+ vector<unsigned short> m_index;
+ enum { LINE = 2, TRIANGLE = 3, QUAD = 4 } m_type;
+ //RAS_MeshSlot *m_origSlot;
+ int m_users;
+
+ enum { BUCKET_MAX_INDEX = 65535 };
+ enum { BUCKET_MAX_VERTEX = 65535 };
};
+/* Entry of a RAS_MeshObject into RAS_MaterialBucket */
-inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs)
+class RAS_MeshSlot
{
- return ( rhs.Less(lhs));
-}
+private:
+ // indices into display arrays
+ int m_startarray;
+ int m_endarray;
+ int m_startindex;
+ int m_endindex;
+ int m_startvertex;
+ int m_endvertex;
+ vector<RAS_DisplayArray*> m_displayArrays;
+
+ // for construction only
+ RAS_DisplayArray* m_currentArray;
+
+public:
+ // for rendering
+ RAS_MaterialBucket* m_bucket;
+ RAS_MeshObject* m_mesh;
+ void* m_clientObj;
+ RAS_Deformer* m_pDeformer;
+ double* m_OpenGLMatrix;
+ // visibility
+ bool m_bVisible;
+ bool m_bCulled;
+ // object color
+ bool m_bObjectColor;
+ MT_Vector4 m_RGBAcolor;
+ // display lists
+ KX_ListSlot* m_DisplayList;
+ bool m_bDisplayList;
+ // joined mesh slots
+ RAS_MeshSlot* m_joinSlot;
+ MT_Matrix4x4 m_joinInvTransform;
+ list<RAS_MeshSlot*> m_joinedSlots;
+
+ RAS_MeshSlot();
+ RAS_MeshSlot(const RAS_MeshSlot& slot);
+ virtual ~RAS_MeshSlot();
+
+ void init(RAS_MaterialBucket *bucket, int numverts);
+
+ struct iterator {
+ RAS_DisplayArray *array;
+ RAS_TexVert *vertex;
+ unsigned short *index;
+ size_t startvertex;
+ size_t endvertex;
+ size_t totindex;
+ size_t arraynum;
+ };
+
+ void begin(iterator& it);
+ void next(iterator& it);
+ bool end(iterator& it);
+
+ /* used during construction */
+ void SetDisplayArray(int numverts);
+ RAS_DisplayArray *CurrentDisplayArray();
+
+ void AddPolygon(int numverts);
+ int AddVertex(const RAS_TexVert& tv);
+ void AddPolygonVertex(int offset);
+
+ /* optimization */
+ bool Split(bool force=false);
+ bool Join(RAS_MeshSlot *target, MT_Scalar distance);
+ bool Equals(RAS_MeshSlot *target);
+ bool IsCulled();
+};
+
+/* Used by RAS_MeshObject, to point to it's slots in a bucket */
+
+class RAS_MeshMaterial
+{
+public:
+ RAS_MeshSlot *m_baseslot;
+ class RAS_MaterialBucket *m_bucket;
+
+ GEN_Map<GEN_HashedPtr,RAS_MeshSlot*> m_slots;
+};
+
+/* Contains a list of display arrays with the same material,
+ * and a mesh slot for each mesh that uses display arrays in
+ * this bucket */
-/**
- * Contains a list of meshs with the same material properties.
- */
class RAS_MaterialBucket
{
public:
- typedef std::set<KX_MeshSlot> T_MeshSlotList;
-
RAS_MaterialBucket(RAS_IPolyMaterial* mat);
- virtual ~RAS_MaterialBucket() {}
-
- void Render(const MT_Transform& cameratrans,
- class RAS_IRasterizer* rasty,
- class RAS_IRenderTools* rendertools);
+ virtual ~RAS_MaterialBucket();
+ /* Bucket Sorting */
+ struct less;
+ typedef set<RAS_MaterialBucket*, less> Set;
+
+ /* Material Properties */
RAS_IPolyMaterial* GetPolyMaterial() const;
- bool IsAlpha() const;
- bool IsZSort() const;
+ bool IsAlpha() const;
+ bool IsZSort() const;
- static void StartFrame();
- static void EndFrame();
-
- void SetMeshSlot(KX_MeshSlot& ms);
- void RemoveMeshSlot(KX_MeshSlot& ms);
- void MarkVisibleMeshSlot(KX_MeshSlot& ms,
- bool visible,
- bool color,
- const MT_Vector4& rgbavec);
-
- void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
- RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode);
+ /* Rendering */
bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
- RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode& drawmode);
-
- unsigned int NumMeshSlots();
- T_MeshSlotList::iterator msBegin();
- T_MeshSlotList::iterator msEnd();
-
- struct less
- {
- bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const
- {
- return *x->GetPolyMaterial() < *y->GetPolyMaterial();
- }
- };
+ RAS_IRenderTools *rendertools);
+ void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty,
+ RAS_IRenderTools* rendertools, RAS_MeshSlot &ms);
- typedef set<RAS_MaterialBucket*, less> Set;
+ /* Mesh Slot Access */
+ list<RAS_MeshSlot>::iterator msBegin();
+ list<RAS_MeshSlot>::iterator msEnd();
+
+ class RAS_MeshSlot* AddMesh(int numverts);
+ class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms);
+ void RemoveMesh(class RAS_MeshSlot* ms);
+ void Optimize(MT_Scalar distance);
+
private:
-
- T_MeshSlotList m_meshSlots;
- bool m_bModified;
+ list<RAS_MeshSlot> m_meshSlots;
RAS_IPolyMaterial* m_material;
- double* m_pOGLMatrix;
};
-#endif //__KX_BUCKET
+#endif //__RAS_MATERIAL_BUCKET
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
index af5228e4c35..a907994bf57 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp
@@ -26,10 +26,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
#include "MT_MinMax.h"
@@ -37,62 +33,84 @@
#include <algorithm>
+/* polygon sorting */
-STR_String RAS_MeshObject::s_emptyname = "";
+struct RAS_MeshObject::polygonSlot
+{
+ float m_z;
+ int m_index[4];
+
+ polygonSlot() {}
+ /* pnorm is the normal from the plane equation that the distance from is
+ * used to sort again. */
+ void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray,
+ int offset, int nvert, const MT_Vector3& pnorm)
+ {
+ MT_Vector3 center(0, 0, 0);
+ int i;
+ for(i=0; i<nvert; i++) {
+ m_index[i] = indexarray[offset+i];
+ center += vertexarray[m_index[i]].getXYZ();
+ }
-KX_ArrayOptimizer::~KX_ArrayOptimizer()
-{
- for (vector<KX_VertexArray*>::iterator itv = m_VertexArrayCache1.begin();
- !(itv == m_VertexArrayCache1.end());++itv)
- {
- delete (*itv);
+ /* note we don't divide center by the number of vertices, since all
+ * polygons have the same number of vertices, and that we leave out
+ * the 4-th component of the plane equation since it is constant. */
+ m_z = MT_dot(pnorm, center);
}
- for (vector<KX_IndexArray*>::iterator iti = m_IndexArrayCache1.begin();
- !(iti == m_IndexArrayCache1.end());++iti)
+ void set(unsigned short *indexarray, int offset, int nvert)
{
- delete (*iti);
+ int i;
+
+ for(i=0; i<nvert; i++)
+ indexarray[offset+i] = m_index[i];
}
+};
- m_TriangleArrayCount.clear();
- m_VertexArrayCache1.clear();
- m_IndexArrayCache1.clear();
-
+struct RAS_MeshObject::backtofront
+{
+ bool operator()(const polygonSlot &a, const polygonSlot &b) const
+ {
+ return a.m_z < b.m_z;
+ }
+};
-}
+struct RAS_MeshObject::fronttoback
+{
+ bool operator()(const polygonSlot &a, const polygonSlot &b) const
+ {
+ return a.m_z > b.m_z;
+ }
+};
+/* mesh object */
+STR_String RAS_MeshObject::s_emptyname = "";
RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer)
- : m_bModified(true),
- m_lightlayer(lightlayer),
- m_zsort(false),
- m_MeshMod(true),
+ : m_lightlayer(lightlayer),
+ m_bModified(true),
+ m_bMeshModified(true),
m_mesh(mesh),
- m_class(0)
+ m_bDeformed(false)
{
}
-
-bool RAS_MeshObject::MeshModified()
-{
- return m_MeshMod;
-}
-
-
RAS_MeshObject::~RAS_MeshObject()
{
- for (vector<RAS_Polygon*>::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++)
- {
- delete (*it);
- }
+ vector<RAS_Polygon*>::iterator it;
- ClearArrayData();
+ for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++)
+ delete (*it);
}
-
+bool RAS_MeshObject::MeshModified()
+{
+ return m_bMeshModified;
+}
unsigned int RAS_MeshObject::GetLightLayer()
{
@@ -108,18 +126,21 @@ int RAS_MeshObject::NumMaterials()
const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid)
{
- RAS_MaterialBucket* bucket = GetMaterialBucket(matid);
+ RAS_MeshMaterial* mmat = GetMeshMaterial(matid);
+
+ if(mmat)
+ return mmat->m_bucket->GetPolyMaterial()->GetMaterialName();
- return bucket?bucket->GetPolyMaterial()->GetMaterialName():s_emptyname;
+ return s_emptyname;
}
-RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(unsigned int matid)
+RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid)
{
if (m_materials.size() > 0 && (matid < m_materials.size()))
{
- RAS_MaterialBucket::Set::const_iterator it = m_materials.begin();
+ list<RAS_MeshMaterial>::iterator it = m_materials.begin();
while (matid--) ++it;
- return *it;
+ return &*it;
}
return NULL;
@@ -134,21 +155,24 @@ int RAS_MeshObject::NumPolygons()
-RAS_Polygon* RAS_MeshObject::GetPolygon(int num)
+RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const
{
return m_Polygons[num];
}
-RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetFirstMaterial()
+
+ list<RAS_MeshMaterial>::iterator GetFirstMaterial();
+ list<RAS_MeshMaterial>::iterator GetLastMaterial();
+list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetFirstMaterial()
{
return m_materials.begin();
}
-RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetLastMaterial()
+list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial()
{
return m_materials.end();
}
@@ -171,377 +195,238 @@ const STR_String& RAS_MeshObject::GetName()
const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid)
{
- RAS_MaterialBucket* bucket = GetMaterialBucket(matid);
+ RAS_MeshMaterial* mmat = GetMeshMaterial(matid);
- return bucket?bucket->GetPolyMaterial()->GetTextureName():s_emptyname;
+ if(mmat)
+ return mmat->m_bucket->GetPolyMaterial()->GetTextureName();
+
+ return s_emptyname;
}
+RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat)
+{
+ list<RAS_MeshMaterial>::iterator mit;
+ /* find a mesh material */
+ for(mit = m_materials.begin(); mit != m_materials.end(); mit++)
+ if(mit->m_bucket->GetPolyMaterial() == mat)
+ return &*mit;
-void RAS_MeshObject::AddPolygon(RAS_Polygon* poly)
-{
- m_Polygons.push_back(poly);
+ return NULL;
}
+RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts)
+{
+ RAS_MeshMaterial *mmat;
+ RAS_Polygon *poly;
+ RAS_MeshSlot *slot;
+ /* find a mesh material */
+ mmat = GetMeshMaterial(bucket->GetPolyMaterial());
+
+ /* none found, create a new one */
+ if(!mmat) {
+ RAS_MeshMaterial meshmat;
+ meshmat.m_bucket = bucket;
+ meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts);
+ m_materials.push_back(meshmat);
+ mmat = &m_materials.back();
+ }
+
+ /* add it to the bucket, this also adds new display arrays */
+ slot = mmat->m_baseslot;
+ slot->AddPolygon(numverts);
+
+ /* create a new polygon */
+ RAS_DisplayArray *darray = slot->CurrentDisplayArray();
+ poly = new RAS_Polygon(bucket, darray, numverts);
+ m_Polygons.push_back(poly);
+
+ return poly;
+}
void RAS_MeshObject::DebugColor(unsigned int abgr)
{
-/*
- int numpolys = NumPolygons();
- for (int i=0;i<numpolys;i++)
- {
+ /*int numpolys = NumPolygons();
+
+ for (int i=0;i<numpolys;i++) {
RAS_Polygon* poly = m_polygons[i];
for (int v=0;v<poly->VertexCount();v++)
- {
- RAS_TexVert* vtx = poly->GetVertex(v);
- vtx->setDebugRGBA(abgr);
- }
+ RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr);
}
*/
- m_debugcolor = abgr;
+ /* m_debugcolor = abgr; */
}
void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
{
- const vecVertexArray & vertexvec = GetVertexCache(mat);
-
- for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it)
- {
- KX_VertexArray::iterator vit;
- for (vit=(*it)->begin(); vit != (*it)->end(); vit++)
- {
- vit->SetRGBA(rgba);
- }
- }
-}
-
-void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx,
- int numverts,
- RAS_IPolyMaterial* mat)
-{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]);
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]);
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]);
-
- if (!mat->UsesTriangles())
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]);
-}
+ RAS_MeshMaterial *mmat = GetMeshMaterial(mat);
+ RAS_MeshSlot *slot = mmat->m_baseslot;
+ RAS_MeshSlot::iterator it;
+ size_t i;
+
+ for(slot->begin(it); !slot->end(it); slot->next(it))
+ for(i=it.startvertex; i<it.endvertex; i++)
+ it.vertex[i].SetRGBA(rgba);
+}
+
+void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
+ const MT_Point3& xyz,
+ const MT_Point2& uv,
+ const MT_Point2& uv2,
+ const MT_Vector4& tangent,
+ const unsigned int rgba,
+ const MT_Vector3& normal,
+ bool flat,
+ int origindex)
+{
+ RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex);
+ RAS_MeshMaterial *mmat;
+ RAS_DisplayArray *darray;
+ RAS_MeshSlot *slot;
+ int offset;
+
+ mmat = GetMeshMaterial(poly->GetMaterial()->GetPolyMaterial());
+ slot = mmat->m_baseslot;
+ darray = slot->CurrentDisplayArray();
+ if(!flat) {
+ /* find vertices shared between faces, with the restriction
+ * that they exist in the same display array, and have the
+ * same uv coordinate etc */
+ vector<SharedVertex>& sharedmap = m_sharedvertex_map[origindex];
+ vector<SharedVertex>::iterator it;
-void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx,
- int numverts,
- int edgecode,
- RAS_IPolyMaterial* mat)
-{
- //int indexpos = m_IndexArrayCount[idx.m_vtxarray];
- int edgetrace = 1<<(numverts-1);
- bool drawedge = (edgecode & edgetrace)!=0;
- edgetrace = 1;
- int prevvert = idx.m_indexarray[numverts-1];
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- for (int v = 0; v < numverts; v++)
- {
- unsigned int curvert = idx.m_indexarray[v];
- if (drawedge)
+ for(it = sharedmap.begin(); it != sharedmap.end(); it++)
{
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert);
- ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert);
+ if(it->m_darray != darray)
+ continue;
+ if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert))
+ continue;
+
+ /* found one, add it and we're done */
+ if(poly->IsVisible())
+ slot->AddPolygonVertex(it->m_offset);
+ poly->SetVertexOffset(i, it->m_offset);
+ return;
}
- prevvert = curvert;
- drawedge = (edgecode & edgetrace)!=0;
- edgetrace*=2;
}
- //m_IndexArrayCount[idx.m_vtxarray] = indexpos;
-}
-int RAS_MeshObject::FindOrAddVertex(int vtxarray,
- const MT_Point3& xyz,
- const MT_Point2& uv,
- const MT_Point2& uv2,
- const MT_Vector4& tangent,
- const unsigned int rgbacolor,
- const MT_Vector3& normal,
- bool flat,
- RAS_IPolyMaterial* mat,
- int origindex)
-{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray];
- RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex);
+ /* no shared vertex found, add a new one */
+ offset = slot->AddVertex(texvert);
+ if(poly->IsVisible())
+ slot->AddPolygonVertex(offset);
+ poly->SetVertexOffset(i, offset);
-#define KX_FIND_SHARED_VERTICES
-#ifdef KX_FIND_SHARED_VERTICES
if(!flat) {
- for (std::vector<RAS_MatArrayIndex>::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin();
- it != m_xyz_index_to_vertex_index_mapping[origindex].end();
- it++)
- {
- if ((*it).m_arrayindex1 == ao->m_index1 &&
- (*it).m_array == vtxarray &&
- *(*it).m_matid == *mat &&
- (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert)
- )
- {
- return (*it).m_index;
- }
- }
+ SharedVertex shared;
+ shared.m_darray = darray;
+ shared.m_offset = offset;
+ m_sharedvertex_map[origindex].push_back(shared);
}
-#endif // KX_FIND_SHARED_VERTICES
-
- // no vertex found, add one
- ao->m_VertexArrayCache1[vtxarray]->push_back(newvert);
- // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]);
- RAS_MatArrayIndex idx;
- idx.m_arrayindex1 = ao->m_index1;
- idx.m_array = vtxarray;
- idx.m_index = numverts;
- idx.m_matid = mat;
- m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx);
-
- return numverts;
}
-vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat)
+int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat)
{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- return ao->m_VertexArrayCache1;
-}
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ RAS_MeshSlot::iterator it;
+ size_t len = 0;
-int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat)
-{
- int len = 0;
-
- const vecVertexArray & vertexvec = GetVertexCache(mat);
- vector<KX_VertexArray*>::const_iterator it = vertexvec.begin();
+ mmat = GetMeshMaterial(mat);
+ slot = mmat->m_baseslot;
+ for(slot->begin(it); !slot->end(it); slot->next(it))
+ len += it.endvertex - it.startvertex;
- for (; it != vertexvec.end(); ++it)
- {
- len += (*it)->size();
- }
-
return len;
}
-
RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
unsigned int index)
{
- RAS_TexVert* vertex = NULL;
-
- RAS_MaterialBucket* bucket = GetMaterialBucket(matid);
- if (bucket)
- {
- RAS_IPolyMaterial* mat = bucket->GetPolyMaterial();
- if (mat)
- {
- const vecVertexArray & vertexvec = GetVertexCache(mat);
- vector<KX_VertexArray*>::const_iterator it = vertexvec.begin();
-
- for (unsigned int len = 0; it != vertexvec.end(); ++it)
- {
- if (index < len + (*it)->size())
- {
- vertex = &(*(*it))[index-len];
- break;
- }
- else
- {
- len += (*it)->size();
- }
- }
- }
- }
-
- return vertex;
-}
-
-
+ RAS_MeshMaterial *mmat;
+ RAS_MeshSlot *slot;
+ RAS_MeshSlot::iterator it;
+ size_t len;
-const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat)
-{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- return ao->m_IndexArrayCache1;
-}
+ mmat = GetMeshMaterial(matid);
-
-
-KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat)
-{
- KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat];
-
- if(aop)
- return *aop;
+ if(!mmat)
+ return NULL;
- // didn't find array, but an array might already exist
- // for a material equal to this one
- for(int i=0;i<m_matVertexArrayS.size();i++) {
- RAS_IPolyMaterial *mat = (RAS_IPolyMaterial*)(m_matVertexArrayS.getKey(i)->getValue());
- if(*mat == *polymat) {
- m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i));
- return *m_matVertexArrayS.at(i);
- }
+ slot = mmat->m_baseslot;
+ len = 0;
+ for(slot->begin(it); !slot->end(it); slot->next(it)) {
+ if(index >= len + it.endvertex - it.startvertex)
+ len += it.endvertex - it.startvertex;
+ else
+ return &it.vertex[index - len];
}
-
- // create new array
- int numelements = m_matVertexArrayS.size();
- m_sortedMaterials.push_back(polymat);
-
- KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements);
- m_matVertexArrayS.insert(polymat, ao);
- return ao;
+ return NULL;
}
-
-
-void RAS_MeshObject::Bucketize(double* oglmatrix,
- void* clientobj,
- bool useObjectColor,
- const MT_Vector4& rgbavec)
+void RAS_MeshObject::AddMeshUser(void *clientobj)
{
- KX_MeshSlot ms;
- ms.m_clientObj = clientobj;
- ms.m_mesh = this;
- ms.m_OpenGLMatrix = oglmatrix;
- ms.m_bObjectColor = useObjectColor;
- ms.m_RGBAcolor = rgbavec;
-
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- {
- RAS_MaterialBucket* bucket = *it;
-// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial());
- bucket->SetMeshSlot(ms);
- }
+ list<RAS_MeshMaterial>::iterator it;
-}
-
-
-
-void RAS_MeshObject::MarkVisible(double* oglmatrix,
- void* clientobj,
- bool visible,
- bool useObjectColor,
- const MT_Vector4& rgbavec)
-{
- KX_MeshSlot ms;
- ms.m_clientObj = clientobj;
- ms.m_mesh = this;
- ms.m_OpenGLMatrix = oglmatrix;
- ms.m_RGBAcolor = rgbavec;
- ms.m_bObjectColor= useObjectColor;
-
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- {
- RAS_MaterialBucket* bucket = *it;
-// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial());
- bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec);
+ for(it = m_materials.begin();it!=m_materials.end();++it) {
+ /* always copy from the base slot, which is never removed
+ * since new objects can be created with the same mesh data */
+ RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot);
+ ms->m_clientObj = clientobj;
+ it->m_slots.insert(clientobj, ms);
}
}
-
-void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix,
- void* clientobj)
+void RAS_MeshObject::UpdateBuckets(void* clientobj,
+ double* oglmatrix,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec,
+ bool visible,
+ bool culled)
{
- KX_MeshSlot ms;
- ms.m_clientObj = clientobj;
- ms.m_mesh = this;
- ms.m_OpenGLMatrix = oglmatrix;
-
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- {
- RAS_MaterialBucket* bucket = *it;
-// RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial();
- //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat);
- bucket->RemoveMeshSlot(ms);
- }
-
-}
-
-
+ list<RAS_MeshMaterial>::iterator it;
-/*
- * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool
- * it is the clients responsibility to make sure the array and index are valid
- */
-RAS_TexVert* RAS_MeshObject::GetVertex(short array,
- unsigned int index,
- RAS_IPolyMaterial* polymat)
-{
- KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);
- return &((*(ao->m_VertexArrayCache1)[array])[index]);
-}
+ for(it = m_materials.begin();it!=m_materials.end();++it) {
+ RAS_MeshSlot **msp = it->m_slots[clientobj];
+ if(!msp)
+ continue;
+ RAS_MeshSlot *ms = *msp;
-void RAS_MeshObject::ClearArrayData()
-{
- for (int i=0;i<m_matVertexArrayS.size();i++) {
- KX_ArrayOptimizer** ao = m_matVertexArrayS.at(i);
-
- // we have duplicate entries, only free once
- for(int j=i+1;j<m_matVertexArrayS.size();j++) {
- if(ao == m_matVertexArrayS.at(j)) {
- ao = NULL;
- break;
- }
- }
+ ms->m_mesh = this;
+ ms->m_OpenGLMatrix = oglmatrix;
+ ms->m_bObjectColor = useObjectColor;
+ ms->m_RGBAcolor = rgbavec;
+ ms->m_bVisible = visible;
+ ms->m_bCulled = culled || !visible;
- if (ao)
- delete *ao;
+ /* split if necessary */
+ ms->Split();
}
}
-
-
-/**
- * RAS_MeshObject::CreateNewVertices creates vertices within sorted pools of vertices that share same material
-*/
-int RAS_MeshObject::FindVertexArray(int numverts,
- RAS_IPolyMaterial* polymat)
+void RAS_MeshObject::RemoveFromBuckets(void *clientobj)
{
-// bool found=false;
- int array=-1;
+ list<RAS_MeshMaterial>::iterator it;
- KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat);
+ for(it = m_materials.begin();it!=m_materials.end();++it) {
+ RAS_MeshSlot **msp = it->m_slots[clientobj];
- for (unsigned int i=0;i<ao->m_VertexArrayCache1.size();i++)
- {
- if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES)
- {
- if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES))
- {
- array = i;
- ao->m_TriangleArrayCount[array]+=numverts-2;
- break;
- }
- }
- }
+ if(!msp)
+ continue;
- if (array == -1)
- {
- array = ao->m_VertexArrayCache1.size();
- vector<RAS_TexVert>* va = new vector<RAS_TexVert>;
- ao->m_VertexArrayCache1.push_back(va);
- KX_IndexArray *ia = new KX_IndexArray();
- ao->m_IndexArrayCache1.push_back(ia);
- ao->m_TriangleArrayCount.push_back(numverts-2);
- }
+ RAS_MeshSlot *ms = *msp;
- return array;
+ it->m_bucket->RemoveMesh(ms);
+ it->m_slots.remove(clientobj);
+ }
}
-
-
-
//void RAS_MeshObject::Transform(const MT_Transform& trans)
//{
//m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans);
@@ -563,71 +448,7 @@ void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec)
}
*/
-
-
-void RAS_MeshObject::UpdateMaterialList()
-{
- m_materials.clear();
- unsigned int numpolys = m_Polygons.size();
- // for all polygons, find out which material they use, and add it to the set of materials
- for (unsigned int i=0;i<numpolys;i++)
- {
- m_materials.insert(m_Polygons[i]->GetMaterial());
- }
-}
-
-struct RAS_MeshObject::polygonSlot
-{
- float m_z;
- int m_index[4];
-
- polygonSlot() {}
-
- /* pnorm is the normal from the plane equation that the distance from is
- * used to sort again. */
- void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray,
- int offset, int nvert, const MT_Vector3& pnorm)
- {
- MT_Vector3 center(0, 0, 0);
- int i;
-
- for(i=0; i<nvert; i++) {
- m_index[i] = indexarray[offset+i];
- center += vertexarray[m_index[i]].getLocalXYZ();
- }
-
- /* note we don't divide center by the number of vertices, since all
- * polygons have the same number of vertices, and that we leave out
- * the 4-th component of the plane equation since it is constant. */
- m_z = MT_dot(pnorm, center);
- }
-
- void set(KX_IndexArray& indexarray, int offset, int nvert)
- {
- int i;
-
- for(i=0; i<nvert; i++)
- indexarray[offset+i] = m_index[i];
- }
-};
-
-struct RAS_MeshObject::backtofront
-{
- bool operator()(const polygonSlot &a, const polygonSlot &b) const
- {
- return a.m_z < b.m_z;
- }
-};
-
-struct RAS_MeshObject::fronttoback
-{
- bool operator()(const polygonSlot &a, const polygonSlot &b) const
- {
- return a.m_z > b.m_z;
- }
-};
-
-void RAS_MeshObject::SortPolygons(const MT_Transform &transform)
+void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform)
{
// Limitations: sorting is quite simple, and handles many
// cases wrong, partially due to polygons being sorted per
@@ -645,43 +466,34 @@ void RAS_MeshObject::SortPolygons(const MT_Transform &transform)
// to avoid excessive state changes while drawing. e) would
// require splitting polygons.
- if (!m_zsort)
- return;
+ RAS_MeshSlot::iterator it;
+ size_t j;
- // Extract camera Z plane...
- const MT_Vector3 pnorm(transform.getBasis()[2]);
- // unneeded: const MT_Scalar pval = transform.getOrigin()[2];
+ for(ms.begin(it); !ms.end(it); ms.next(it)) {
+ unsigned int nvert = (int)it.array->m_type;
+ unsigned int totpoly = it.totindex/nvert;
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- {
- if(!(*it)->IsZSort())
+ if(totpoly <= 1)
+ continue;
+ if(it.array->m_type == RAS_DisplayArray::LINE)
continue;
- RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial();
- KX_ArrayOptimizer* ao = GetArrayOptimizer(mat);
-
- vecIndexArrays& indexarrays = ao->m_IndexArrayCache1;
- vecVertexArray& vertexarrays = ao->m_VertexArrayCache1;
- unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4;
-
- for(i=0; i<indexarrays.size(); i++) {
- KX_IndexArray& indexarray = *indexarrays[i];
- KX_VertexArray& vertexarray = *vertexarrays[i];
+ // Extract camera Z plane...
+ const MT_Vector3 pnorm(transform.getBasis()[2]);
+ // unneeded: const MT_Scalar pval = transform.getOrigin()[2];
- unsigned int totpoly = indexarray.size()/nvert;
- vector<polygonSlot> slots(totpoly);
+ vector<polygonSlot> slots(totpoly);
- /* get indices and z into temporary array */
- for(j=0; j<totpoly; j++)
- slots[j].get(vertexarray, indexarray, j*nvert, nvert, pnorm);
+ /* get indices and z into temporary array */
+ for(j=0; j<totpoly; j++)
+ slots[j].get(it.vertex, it.index, j*nvert, nvert, pnorm);
- /* sort (stable_sort might be better, if flickering happens?) */
- std::sort(slots.begin(), slots.end(), backtofront());
+ /* sort (stable_sort might be better, if flickering happens?) */
+ std::sort(slots.begin(), slots.end(), backtofront());
- /* get indices from temporary array again */
- for(j=0; j<totpoly; j++)
- slots[j].set(indexarray, j*nvert, nvert);
- }
+ /* get indices from temporary array again */
+ for(j=0; j<totpoly; j++)
+ slots[j].set(it.index, j*nvert, nvert);
}
}
@@ -690,37 +502,8 @@ void RAS_MeshObject::SchedulePolygons(int drawingmode)
{
if (m_bModified)
{
- int i, numpolys = m_Polygons.size();
-
- for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it)
- if ((*it)->IsZSort())
- m_zsort = true;
-
- if (drawingmode == RAS_IRasterizer::KX_WIREFRAME)
- {
- for (i=0;i<numpolys;i++)
- {
- RAS_Polygon* poly = m_Polygons[i];
- if (poly->IsVisible())
- ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(),
- poly->GetMaterial()->GetPolyMaterial());
-
- }
- m_zsort = false;
- }
- else
- {
- for (i=0;i<numpolys;i++)
- {
- RAS_Polygon* poly = m_Polygons[i];
- if (poly->IsVisible())
- SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),
- poly->GetMaterial()->GetPolyMaterial());
- }
- }
-
m_bModified = false;
- m_MeshMod = true;
+ m_bMeshModified = true;
}
}
diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h
index 99806666fa6..0d35a2f402b 100644
--- a/source/gameengine/Rasterizer/RAS_MeshObject.h
+++ b/source/gameengine/Rasterizer/RAS_MeshObject.h
@@ -36,6 +36,7 @@
#include <vector>
#include <set>
+#include <list>
#include "RAS_Polygon.h"
#include "RAS_MaterialBucket.h"
@@ -44,194 +45,71 @@
#include "GEN_HashedPtr.h"
struct Mesh;
-/**
- * This class holds an array of vertices and indicies.
- */
-class KX_ArrayOptimizer
-{
-public:
- KX_ArrayOptimizer(int index)
- : m_index1(index)
- {};
- virtual ~KX_ArrayOptimizer();
-
- vector<KX_VertexArray*> m_VertexArrayCache1;
- vector<int> m_TriangleArrayCount;
- vector<KX_IndexArray*> m_IndexArrayCache1;
-
- /**
- order in which they are stored into the mesh
- */
- int m_index1;
-};
-
-/**
- * This struct holds a triangle.
- */
-struct RAS_TriangleIndex
-{
-public:
- int m_index[3];
- int m_array;
- RAS_IPolyMaterial* m_matid;
- bool m_collider;
-};
-
-/**
- * This class looks horribly broken. Only m_matid is used, and
- * m_matid is a (int) RAS_IPolyMaterial*.
- * --> m_matid == lhs.m_matid should be *m_matid == *lhs.m_matid
- */
-class RAS_MatArrayIndex
-{
-public:
- int m_arrayindex1;
- RAS_IPolyMaterial* m_matid;
- int m_array;
- int m_index;
-
-/*
- inline bool Less(const RAS_MatArrayIndex& lhs) const {
- bool result =
- ( (m_matid < lhs.m_matid) ||
- ((m_matid == lhs.m_matid)&&(m_array < lhs.m_array)) ||
- ((m_matid == lhs.m_matid) && (m_array == lhs.m_array) &&
- (m_index < lhs.m_index))
-
- );
- return result;
-
- }
-*/
-
-};
-/*
-inline bool operator <( const RAS_MatArrayIndex& rhs,const RAS_MatArrayIndex& lhs)
-{
- return ( rhs.Less(lhs));
-}*/
+/* RAS_MeshObject is a mesh used for rendering. It stores polygons,
+ * but the actual vertices and index arrays are stored in material
+ * buckets, referenced by the list of RAS_MeshMaterials. */
-/**
- * RAS_MeshObject stores mesh data for the renderer.
- */
class RAS_MeshObject
{
-
- // GEN_Map<class RAS_IPolyMaterial,KX_ArrayOptimizer*> m_matVertexArrayS;
- //vector<class RAS_IPolyMaterial*,KX_ArrayOptimizer> m_vertexArrays;
- virtual KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat);
- //vector<RAS_Polygon*> m_polygons;
-
+private:
unsigned int m_debugcolor;
- bool m_bModified;
int m_lightlayer;
-
- vector<class RAS_Polygon*> m_Polygons;
+
+ bool m_bModified;
+ bool m_bMeshModified;
+
STR_String m_name;
static STR_String s_emptyname;
- bool m_zsort;
- bool m_MeshMod;
+ vector<class RAS_Polygon*> m_Polygons;
+
+ /* polygon sorting */
struct polygonSlot;
struct backtofront;
struct fronttoback;
- void SchedulePoly(
- const KX_VertexIndex& idx,
- int numverts,
- RAS_IPolyMaterial* mat
- );
-
- void ScheduleWireframePoly(
- const KX_VertexIndex& idx,
- int numverts,
- int edgecode,
- RAS_IPolyMaterial* mat
- );
-
protected:
- enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192};
- enum { BUCKET_MAX_TRIANGLES = 65535 };
-
- GEN_Map<GEN_HashedPtr,KX_ArrayOptimizer*> m_matVertexArrayS;
-
- RAS_MaterialBucket::Set m_materials;
+ list<RAS_MeshMaterial> m_materials;
Mesh* m_mesh;
+ bool m_bDeformed;
+
public:
// for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime)
RAS_MeshObject(Mesh* mesh, int lightlayer);
virtual ~RAS_MeshObject();
- vector<RAS_IPolyMaterial*> m_sortedMaterials;
- vector<vector<RAS_MatArrayIndex> > m_xyz_index_to_vertex_index_mapping;
- vector<RAS_TriangleIndex > m_triangle_indices;
-
- int m_class;
- unsigned int GetLightLayer();
+ bool IsDeformed() { return m_bDeformed; }
+
+ /* materials */
int NumMaterials();
const STR_String& GetMaterialName(unsigned int matid);
- RAS_MaterialBucket* GetMaterialBucket(unsigned int matid);
const STR_String& GetTextureName(unsigned int matid);
- virtual void AddPolygon(RAS_Polygon* poly);
- void UpdateMaterialList();
-
- int NumPolygons();
- RAS_Polygon* GetPolygon(int num);
-
- virtual void Bucketize(
- double* oglmatrix,
- void* clientobj,
- bool useObjectColor,
- const MT_Vector4& rgbavec
- );
- void RemoveFromBuckets(
- double* oglmatrix,
- void* clientobj
- );
+ RAS_MeshMaterial* GetMeshMaterial(unsigned int matid);
+ RAS_MeshMaterial* GetMeshMaterial(RAS_IPolyMaterial *mat);
- void MarkVisible(
- double* oglmatrix,
- void* clientobj,
- bool visible,
- bool useObjectColor,
- const MT_Vector4& rgbavec
- );
+ list<RAS_MeshMaterial>::iterator GetFirstMaterial();
+ list<RAS_MeshMaterial>::iterator GetLastMaterial();
- void DebugColor(unsigned int abgr);
- void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba);
-
- /**
- * Sorts the polygons by their transformed z values.
- */
- void SortPolygons(const MT_Transform &transform);
+ unsigned int GetLightLayer();
- void SchedulePolygons(int drawingmode);
+ /* name */
+ void SetName(STR_String name);
+ const STR_String& GetName();
- void ClearArrayData();
-
- RAS_MaterialBucket::Set::iterator GetFirstMaterial();
- RAS_MaterialBucket::Set::iterator GetLastMaterial();
-
- virtual RAS_TexVert* GetVertex(
- short array,
- unsigned int index,
- RAS_IPolyMaterial* polymat
- );
-
- virtual int FindVertexArray(
- int numverts,
- RAS_IPolyMaterial* polymat
- );
+ /* modification state */
+ bool MeshModified();
+ void SetMeshModified(bool v){m_bMeshModified = v;}
+ /* original blender mesh */
+ Mesh* GetMesh() { return m_mesh; }
+
+ /* mesh construction */
- // find (and share) or add vertices
- // for some speedup, only the last 20 added vertices are searched for equality
-
- virtual int FindOrAddVertex(
- int vtxarray,
+ virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts);
+ virtual void AddVertex(RAS_Polygon *poly, int i,
const MT_Point3& xyz,
const MT_Point2& uv,
const MT_Point2& uv2,
@@ -239,27 +117,43 @@ public:
const unsigned int rgbacolor,
const MT_Vector3& normal,
bool flat,
- RAS_IPolyMaterial* mat,
- int origindex
- );
-
- vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat);
+ int origindex);
+
+ void SchedulePolygons(int drawingmode);
+
+ /* vertex and polygon acces */
+ int NumVertices(RAS_IPolyMaterial* mat);
+ RAS_TexVert* GetVertex(unsigned int matid, unsigned int index);
+
+ int NumPolygons();
+ RAS_Polygon* GetPolygon(int num) const;
- int GetVertexArrayLength(RAS_IPolyMaterial* mat);
+ /* buckets */
+ virtual void AddMeshUser(void *clientobj);
+ virtual void UpdateBuckets(
+ void* clientobj,
+ double* oglmatrix,
+ bool useObjectColor,
+ const MT_Vector4& rgbavec,
+ bool visible,
+ bool culled);
- RAS_TexVert* GetVertex(
- unsigned int matid,
- unsigned int index
- );
+ void RemoveFromBuckets(void *clientobj);
- const vecIndexArrays& GetIndexCache (RAS_IPolyMaterial* mat);
- void SetName(STR_String name);
- const STR_String& GetName();
+ /* colors */
+ void DebugColor(unsigned int abgr);
+ void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba);
+
+ /* polygon sorting by Z for alpha */
+ void SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform);
- bool MeshModified();
- void SetMeshModified(bool v){m_MeshMod = v;}
- Mesh* GetMesh() { return m_mesh; }
+ /* for construction to find shared vertices */
+ struct SharedVertex {
+ RAS_DisplayArray *m_darray;
+ int m_offset;
+ };
+ vector<vector<SharedVertex> > m_sharedvertex_map;
};
#endif //__RAS_MESHOBJECT
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Blur2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Blur2DFilter.h
index 33c4b3faab0..81821639489 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Blur2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Blur2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_BLUR2DFILTER
#define __RAS_BLUR2DFILTER
-char * BlurFragmentShader=STRINGIFY(
+const char * BlurFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Dilation2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Dilation2DFilter.h
index c41e5ac06af..2ee75396f42 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Dilation2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Dilation2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_DILATION2DFILTER
#define __RAS_DILATION2DFILTER
-char * DilationFragmentShader=STRINGIFY(
+const char * DilationFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h
index 2bb357c958a..d3ce829bab0 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_EROSION2DFILTER
#define __RAS_EROSION2DFILTER
-char * ErosionFragmentShader=STRINGIFY(
+const char * ErosionFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_GrayScale2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_GrayScale2DFilter.h
index 7324edd4e92..ae51308e9a4 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_GrayScale2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_GrayScale2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_GRAYSCALE2DFILTER
#define __RAS_GRAYSCALE2DFILTER
-char * GrayScaleFragmentShader=STRINGIFY(
+const char * GrayScaleFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
void main(void)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Invert2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Invert2DFilter.h
index 5d90fe3475b..f723f619f68 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Invert2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Invert2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_INVERT2DFILTER
#define __RAS_INVERT2DFILTER
-char * InvertFragmentShader=STRINGIFY(
+const char * InvertFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
void main(void)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Laplacian2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Laplacian2DFilter.h
index cbe926976df..bfbb40b2fc9 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Laplacian2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Laplacian2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_LAPLACION2DFILTER
#define __RAS_LAPLACION2DFILTER
-char * LaplacionFragmentShader=STRINGIFY(
+const char * LaplacionFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Prewitt2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Prewitt2DFilter.h
index 7cd1082e5e3..0cbf8a7a802 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Prewitt2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Prewitt2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_PREWITT2DFILTER
#define __RAS_PREWITT2DFILTER
-char * PrewittFragmentShader=STRINGIFY(
+const char * PrewittFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sepia2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sepia2DFilter.h
index d1c16f39823..ca431af4cd7 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sepia2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sepia2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_SEPIA2DFILTER
#define __RAS_SEPIA2DFILTER
-char * SepiaFragmentShader=STRINGIFY(
+const char * SepiaFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
void main(void)
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sharpen2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sharpen2DFilter.h
index 14e0be6df9d..5a9661e2617 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sharpen2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sharpen2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_SHARPEN2DFILTER
#define __RAS_SHARPEN2DFILTER
-char * SharpenFragmentShader=STRINGIFY(
+const char * SharpenFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sobel2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sobel2DFilter.h
index 40c17c285ce..142e4f0e3d4 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sobel2DFilter.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Sobel2DFilter.h
@@ -28,7 +28,7 @@
#ifndef __RAS_SOBEL2DFILTER
#define __RAS_SOBEL2DFILTER
-char * SobelFragmentShader=STRINGIFY(
+const char * SobelFragmentShader=STRINGIFY(
uniform sampler2D bgl_RenderedTexture;
uniform vec2 bgl_TextureCoordinateOffset[9];
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
index 2a6d64ecc73..e4403ace69f 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt
@@ -32,6 +32,7 @@ SET(INC
../../../../intern/moto/include
../../../../source/gameengine/Rasterizer
../../../../extern/glew/include
+ ../../../../source/blender/gpu
)
BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}")
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
index f01978b8eb1..aee485a22be 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile
@@ -41,12 +41,11 @@ CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
CPPFLAGS += -I../../../kernel/gen_system
+CPPFLAGS += -I../../../blender/gpu
CPPFLAGS += -I../../BlenderRoutines
CPPFLAGS += -I..
+
ifeq ($(OS),darwin)
CPPFLAGS += -fpascal-strings
endif
-ifeq ($(WITH_BF_GLEXT),true)
- CPPFLAGS += -DWITH_GLEXT
-endif
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
index c2687319717..2c4b55ff964 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp
@@ -9,6 +9,7 @@
#include "GL/glew.h"
+#include "RAS_MaterialBucket.h"
#include "RAS_TexVert.h"
#include "MT_assert.h"
@@ -125,20 +126,20 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list)
}
}
-RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot)
+RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms)
{
/*
Keep a copy of constant lists submitted for rendering,
this guards against (replicated)new...delete every frame,
and we can reuse lists!
- :: sorted by vertex array
+ :: sorted by mesh slot
*/
- RAS_ListSlot* localSlot = (RAS_ListSlot*)*slot;
+ RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList;
if(!localSlot) {
- RAS_Lists::iterator it = mLists.find(vertexarrays);
+ RAS_Lists::iterator it = mLists.find(&ms);
if(it == mLists.end()) {
localSlot = new RAS_ListSlot(this);
- mLists.insert(std::pair<vecVertexArray, RAS_ListSlot*>(vertexarrays, localSlot));
+ mLists.insert(std::pair<RAS_MeshSlot*, RAS_ListSlot*>(&ms, localSlot));
} else {
localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef());
}
@@ -157,69 +158,45 @@ void RAS_ListRasterizer::ReleaseAlloc()
mLists.clear();
}
-
-void RAS_ListRasterizer::IndexPrimitives(
- const vecVertexArray & vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)
+void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
{
RAS_ListSlot* localSlot =0;
- // useObjectColor(are we updating every frame?)
- if(!useObjectColor && slot) {
- localSlot = FindOrAdd(vertexarrays, slot);
+ if(ms.m_bDisplayList) {
+ localSlot = FindOrAdd(ms);
localSlot->DrawList();
if(localSlot->End()) {
// save slot here too, needed for replicas and object using same mesh
// => they have the same vertexarray but different mesh slot
- *slot = localSlot;
+ ms.m_DisplayList = localSlot;
return;
}
}
- if (mUseVertexArrays) {
- RAS_VAOpenGLRasterizer::IndexPrimitives(
- vertexarrays, indexarrays,
- mode, useObjectColor,
- rgbacolor,slot
- );
- } else {
- RAS_OpenGLRasterizer::IndexPrimitives(
- vertexarrays, indexarrays,
- mode, useObjectColor,
- rgbacolor,slot
- );
- }
+ if (mUseVertexArrays)
+ RAS_VAOpenGLRasterizer::IndexPrimitives(ms);
+ else
+ RAS_OpenGLRasterizer::IndexPrimitives(ms);
- if(!useObjectColor && slot) {
+ if(ms.m_bDisplayList) {
localSlot->EndList();
- *slot = localSlot;
+ ms.m_DisplayList = localSlot;
}
}
-void RAS_ListRasterizer::IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)
+void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
{
RAS_ListSlot* localSlot =0;
- // useObjectColor(are we updating every frame?)
- if(!useObjectColor && slot) {
- localSlot = FindOrAdd(vertexarrays, slot);
+ if(ms.m_bDisplayList) {
+ localSlot = FindOrAdd(ms);
localSlot->DrawList();
if(localSlot->End()) {
// save slot here too, needed for replicas and object using same mesh
// => they have the same vertexarray but different mesh slot
- *slot = localSlot;
+ ms.m_DisplayList = localSlot;
return;
}
}
@@ -227,23 +204,14 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(
// workaround: note how we do not use vertex arrays for making display
// lists, since glVertexAttribPointerARB doesn't seem to work correct
// in display lists on ATI? either a bug in the driver or in Blender ..
- if (mUseVertexArrays && !localSlot) {
- RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(
- vertexarrays, indexarrays,
- mode, useObjectColor,
- rgbacolor,slot
- );
- } else {
- RAS_OpenGLRasterizer::IndexPrimitivesMulti(
- vertexarrays, indexarrays,
- mode, useObjectColor,
- rgbacolor,slot
- );
- }
+ if (mUseVertexArrays && !localSlot)
+ RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms);
+ else
+ RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms);
- if(!useObjectColor && slot) {
+ if(ms.m_bDisplayList) {
localSlot->EndList();
- *slot = localSlot;
+ ms.m_DisplayList = localSlot;
}
}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
index b1b19144c12..96d6d2a995d 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h
@@ -4,6 +4,7 @@
#include "RAS_MaterialBucket.h"
#include "RAS_VAOpenGLRasterizer.h"
#include <vector>
+#include <map>
class RAS_ListRasterizer;
class RAS_ListSlot : public KX_ListSlot
@@ -34,14 +35,14 @@ enum RAS_ListSlotFlags {
LIST_REGEN =64
};
-typedef std::map<const vecVertexArray, RAS_ListSlot*> RAS_Lists;
+typedef std::map<class RAS_MeshSlot*, RAS_ListSlot*> RAS_Lists;
class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer
{
bool mUseVertexArrays;
RAS_Lists mLists;
- RAS_ListSlot* FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot);
+ RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms);
void ReleaseAlloc();
public:
@@ -49,23 +50,8 @@ public:
RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false);
virtual ~RAS_ListRasterizer();
- virtual void IndexPrimitives(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot
- );
-
- virtual void IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot
- );
+ virtual void IndexPrimitives(class RAS_MeshSlot& ms);
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
virtual bool Init();
virtual void Exit();
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
index 1dcc6e70934..87a0a1d8b9e 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp
@@ -38,6 +38,9 @@
#include "MT_CmMatrix4x4.h"
#include "RAS_IRenderTools.h" // rendering text
+#include "GPU_draw.h"
+#include "GPU_material.h"
+
/**
* 32x32 bit masks for vinterlace stereo mode
*/
@@ -67,10 +70,12 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
m_motionblurvalue(-1.0),
m_texco_num(0),
m_attrib_num(0),
- m_last_blendmode(0),
+ m_last_blendmode(GPU_BLEND_SOLID),
+ m_last_frontface(true),
m_materialCachingInfo(0)
{
- m_viewmatrix.Identity();
+ m_viewmatrix.setIdentity();
+ m_viewinvmatrix.setIdentity();
for (int i = 0; i < 32; i++)
{
@@ -87,81 +92,9 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer()
{
}
-
-
-static void Myinit_gl_stuff(void)
-{
- float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
- float mat_shininess[] = { 35.0 };
-/* float one= 1.0; */
- int a, x, y;
- GLubyte pat[32*32];
- const GLubyte *patc= pat;
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
-
-
-#if defined(__FreeBSD) || defined(__linux__)
- glDisable(GL_DITHER); /* op sgi/sun hardware && 12 bits */
-#endif
-
- /* no local viewer, looks ugly in ortho mode */
- /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
-
- glDepthFunc(GL_LEQUAL);
- /* scaling matrices */
- glEnable(GL_NORMALIZE);
-
- glShadeModel(GL_FLAT);
-
- glDisable(GL_ALPHA_TEST);
- glDisable(GL_BLEND);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_FOG);
- glDisable(GL_LIGHTING);
- glDisable(GL_LOGIC_OP);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_TEXTURE_1D);
- glDisable(GL_TEXTURE_2D);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
-
- glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
- glPixelTransferi(GL_RED_SCALE, 1);
- glPixelTransferi(GL_RED_BIAS, 0);
- glPixelTransferi(GL_GREEN_SCALE, 1);
- glPixelTransferi(GL_GREEN_BIAS, 0);
- glPixelTransferi(GL_BLUE_SCALE, 1);
- glPixelTransferi(GL_BLUE_BIAS, 0);
- glPixelTransferi(GL_ALPHA_SCALE, 1);
- glPixelTransferi(GL_ALPHA_BIAS, 0);
-
- a = 0;
- for(x=0; x<32; x++)
- {
- for(y=0; y<4; y++)
- {
- if( (x) & 1) pat[a++]= 0x88;
- else pat[a++]= 0x22;
- }
- }
-
- glPolygonStipple(patc);
-
- glFrontFace(GL_CCW);
- glCullFace(GL_BACK);
- glEnable(GL_CULL_FACE);
-}
-
-
-
bool RAS_OpenGLRasterizer::Init()
{
-
- Myinit_gl_stuff();
+ GPU_state_init();
m_redback = 0.4375;
m_greenback = 0.4375;
@@ -172,7 +105,12 @@ bool RAS_OpenGLRasterizer::Init()
m_ambg = 0.0f;
m_ambb = 0.0f;
- SetBlendingMode(0);
+ glDisable(GL_BLEND);
+ glDisable(GL_ALPHA_TEST);
+ m_last_blendmode = GPU_BLEND_SOLID;
+
+ glFrontFace(GL_CCW);
+ m_last_frontface = true;
glClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@@ -316,21 +254,10 @@ void RAS_OpenGLRasterizer::Exit()
EndFrame();
}
-bool RAS_OpenGLRasterizer::InterlacedStereo() const
-{
- return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
-}
-
bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
{
m_time = time;
m_drawingmode = drawingmode;
-
- if (!InterlacedStereo() || m_curreye == RAS_STEREO_LEFTEYE)
- {
- m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
- m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
- }
// Blender camera routine destroys the settings
if (m_drawingmode < KX_SOLID)
@@ -344,7 +271,12 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time)
glEnable (GL_CULL_FACE);
}
- SetBlendingMode(0);
+ glDisable(GL_BLEND);
+ glDisable(GL_ALPHA_TEST);
+ m_last_blendmode = GPU_BLEND_SOLID;
+
+ glFrontFace(GL_CCW);
+ m_last_frontface = true;
glShadeModel(GL_SMOOTH);
@@ -359,34 +291,28 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode)
{
m_drawingmode = drawingmode;
- switch (m_drawingmode)
- {
- case KX_WIREFRAME:
- {
- glDisable (GL_CULL_FACE);
- break;
- }
- default:
- {
- }
- }
+ if(m_drawingmode == KX_WIREFRAME)
+ glDisable(GL_CULL_FACE);
}
-
-
int RAS_OpenGLRasterizer::GetDrawingMode()
{
return m_drawingmode;
}
-
void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask)
{
glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE);
}
+void RAS_OpenGLRasterizer::ClearColorBuffer()
+{
+ m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback);
+ m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER);
+}
+
void RAS_OpenGLRasterizer::ClearDepthBuffer()
{
@@ -497,6 +423,10 @@ bool RAS_OpenGLRasterizer::Stereo()
return true;
}
+bool RAS_OpenGLRasterizer::InterlacedStereo()
+{
+ return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED;
+}
void RAS_OpenGLRasterizer::SetEye(const StereoEye eye)
{
@@ -573,294 +503,84 @@ void RAS_OpenGLRasterizer::SwapBuffers()
-void RAS_OpenGLRasterizer::GetViewMatrix(MT_Matrix4x4 &mat) const
+const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const
{
- float viewmat[16];
- glGetFloatv(GL_MODELVIEW_MATRIX, viewmat);
- mat.setValue(viewmat);
+ return m_viewmatrix;
}
-
-
-void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot
- )
-{
- const RAS_TexVert* vertexarray;
- unsigned int numindices, vt;
-
- for (vt=0;vt<vertexarrays.size();vt++)
- {
- vertexarray = &((*vertexarrays[vt]) [0]);
- const KX_IndexArray & indexarray = (*indexarrays[vt]);
- numindices = indexarray.size();
-
- if (!numindices)
- break;
-
- int vindex=0;
- switch (mode)
- {
- case KX_MODE_LINES:
- {
- glBegin(GL_LINES);
- vindex=0;
- for (unsigned int i=0;i<numindices;i+=2)
- {
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- }
- glEnd();
- }
- break;
- case KX_MODE_QUADS:
- {
- glBegin(GL_QUADS);
- vindex=0;
- if (useObjectColor)
- {
- for (unsigned int i=0;i<numindices;i+=4)
- {
-
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- else
- {
- for (unsigned int i=0;i<numindices;i+=4)
- {
- // This looks curiously endian unsafe to me.
- // However it depends on the way the colors are packed into
- // the m_rgba field of RAS_TexVert
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- glEnd();
- break;
- }
- case KX_MODE_TRIANGLES:
- {
- glBegin(GL_TRIANGLES);
- vindex=0;
- if (useObjectColor)
- {
- for (unsigned int i=0;i<numindices;i+=3)
- {
-
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- else
- {
- for (unsigned int i=0;i<numindices;i+=3)
- {
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- glTexCoord2fv(vertexarray[(indexarray[vindex])].getUV1());
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- glEnd();
- break;
- }
- default:
- {
- }
-
- } // switch
- } // for each vertexarray
-
+const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const
+{
+ return m_viewinvmatrix;
}
-void RAS_OpenGLRasterizer::IndexPrimitives_3DText(const vecVertexArray & vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
+void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
class RAS_IPolyMaterial* polymat,
- class RAS_IRenderTools* rendertools,
- bool useObjectColor,
- const MT_Vector4& rgbacolor
- )
+ class RAS_IRenderTools* rendertools)
{
- const RAS_TexVert* vertexarray;
- unsigned int numindices, vt;
-
- if (useObjectColor)
- {
+ bool obcolor = ms.m_bObjectColor;
+ MT_Vector4& rgba = ms.m_RGBAcolor;
+ RAS_MeshSlot::iterator it;
+
+ // handle object color
+ if (obcolor) {
glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
}
else
- {
glEnableClientState(GL_COLOR_ARRAY);
- }
-
- for (vt=0;vt<vertexarrays.size();vt++)
- {
- vertexarray = &((*vertexarrays[vt]) [0]);
- const KX_IndexArray & indexarray = (*indexarrays[vt]);
- numindices = indexarray.size();
-
- if (!numindices)
- break;
+
+ for(ms.begin(it); !ms.end(it); ms.next(it)) {
+ RAS_TexVert *vertex;
+ size_t i, j, numvert;
- int vindex=0;
- switch (mode)
- {
- case KX_MODE_LINES:
- {
- glBegin(GL_LINES);
- vindex=0;
- for (unsigned int i=0;i<numindices;i+=2)
- {
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- }
- glEnd();
- }
- break;
- case KX_MODE_QUADS:
+ numvert = it.array->m_type;
+
+ if(it.array->m_type == RAS_DisplayArray::LINE) {
+ // line drawing, no text
+ glBegin(GL_LINES);
+
+ for(i=0; i<it.totindex; i+=2)
{
- vindex=0;
- for (unsigned int i=0;i<numindices;i+=4)
- {
- float v1[3],v2[3],v3[3],v4[3];
-
- v1[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v1[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v1[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- v2[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v2[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v2[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- v3[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v3[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v3[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- v4[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v4[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v4[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
-
- vindex++;
-
- rendertools->RenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,v4);
- ClearCachingInfo();
- }
- break;
+ vertex = &it.vertex[it.index[i]];
+ glVertex3fv(vertex->getXYZ());
+
+ vertex = &it.vertex[it.index[i+1]];
+ glVertex3fv(vertex->getXYZ());
}
- case KX_MODE_TRIANGLES:
+
+ glEnd();
+ }
+ else {
+ // triangle and quad text drawing
+ for(i=0; i<it.totindex; i+=numvert)
{
- glBegin(GL_TRIANGLES);
- vindex=0;
- for (unsigned int i=0;i<numindices;i+=3)
- {
- float v1[3],v2[3],v3[3];
-
- v1[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v1[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v1[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- v2[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v2[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v2[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- v3[0] = vertexarray[(indexarray[vindex])].getLocalXYZ()[0];
- v3[1] = vertexarray[(indexarray[vindex])].getLocalXYZ()[1];
- v3[2] = vertexarray[(indexarray[vindex])].getLocalXYZ()[2];
- vindex++;
-
- rendertools->RenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,NULL);
- ClearCachingInfo();
+ float v[4][3];
+ int glattrib, unit;
+
+ for(j=0; j<numvert; j++) {
+ vertex = &it.vertex[it.index[i+j]];
+
+ v[j][0] = vertex->getXYZ()[0];
+ v[j][1] = vertex->getXYZ()[1];
+ v[j][2] = vertex->getXYZ()[2];
}
- glEnd();
- break;
- }
- default:
- {
+
+ // find the right opengl attribute
+ glattrib = -1;
+ if(GLEW_ARB_vertex_program)
+ for(unit=0; unit<m_attrib_num; unit++)
+ if(m_attrib[unit] == RAS_TEXCO_UV1)
+ glattrib = unit;
+
+ rendertools->RenderText(polymat->GetDrawingMode(), polymat,
+ v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib);
+
+ ClearCachingInfo();
}
- } //switch
- } //for each vertexarray
+ }
+ }
+
+ glDisableClientState(GL_COLOR_ARRAY);
}
void RAS_OpenGLRasterizer::SetTexCoordNum(int num)
@@ -897,14 +617,14 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
if(GLEW_ARB_multitexture) {
for(unit=0; unit<m_texco_num; unit++) {
- if(tv.getFlag() & TV_2NDUV && (int)tv.getUnit() == unit) {
+ if(tv.getFlag() & RAS_TexVert::SECOND_UV && (int)tv.getUnit() == unit) {
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2());
continue;
}
switch(m_texco[unit]) {
case RAS_TEXCO_ORCO:
case RAS_TEXCO_GLOB:
- glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getLocalXYZ());
+ glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ());
break;
case RAS_TEXCO_UV1:
glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1());
@@ -929,7 +649,7 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
switch(m_attrib[unit]) {
case RAS_TEXCO_ORCO:
case RAS_TEXCO_GLOB:
- glVertexAttrib3fvARB(unit, tv.getLocalXYZ());
+ glVertexAttrib3fvARB(unit, tv.getXYZ());
break;
case RAS_TEXCO_UV1:
glVertexAttrib2fvARB(unit, tv.getUV1());
@@ -953,211 +673,80 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv)
}
}
-void RAS_OpenGLRasterizer::Tangent( const RAS_TexVert& v1,
- const RAS_TexVert& v2,
- const RAS_TexVert& v3,
- const MT_Vector3 &no)
+
+void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
{
- // TODO: set for deformer...
- MT_Vector3 x1(v1.getLocalXYZ()), x2(v2.getLocalXYZ()), x3(v3.getLocalXYZ());
- MT_Vector2 uv1(v1.getUV1()), uv2(v2.getUV1()), uv3(v3.getUV1());
- MT_Vector3 dx1(x2 - x1), dx2(x3 - x1);
- MT_Vector2 duv1(uv2 - uv1), duv2(uv3 - uv1);
-
- MT_Scalar r = 1.0 / (duv1.x() * duv2.y() - duv2.x() * duv1.y());
- duv1 *= r;
- duv2 *= r;
- MT_Vector3 sdir(duv2.y() * dx1 - duv1.y() * dx2);
- MT_Vector3 tdir(duv1.x() * dx2 - duv2.x() * dx1);
-
- // Gram-Schmidt orthogonalize
- MT_Vector3 t(sdir - no.cross(no.cross(sdir)));
- if (!MT_fuzzyZero(t)) t /= t.length();
-
- float tangent[4];
- t.getValue(tangent);
- // Calculate handedness
- tangent[3] = no.dot(sdir.cross(tdir)) < 0.0 ? -1.0 : 1.0;
+ IndexPrimitivesInternal(ms, false);
}
+void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
+{
+ IndexPrimitivesInternal(ms, true);
+}
-void RAS_OpenGLRasterizer::IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot
- )
+void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
{
+ bool obcolor = ms.m_bObjectColor;
+ bool wireframe = m_drawingmode <= KX_WIREFRAME;
+ MT_Vector4& rgba = ms.m_RGBAcolor;
+ RAS_MeshSlot::iterator it;
+
+ // iterate over display arrays, each containing an index + vertex array
+ for(ms.begin(it); !ms.end(it); ms.next(it)) {
+ RAS_TexVert *vertex;
+ size_t i, j, numvert;
+
+ numvert = it.array->m_type;
- const RAS_TexVert* vertexarray;
- unsigned int numindices,vt;
-
- for (vt=0;vt<vertexarrays.size();vt++)
- {
- vertexarray = &((*vertexarrays[vt]) [0]);
- const KX_IndexArray & indexarray = (*indexarrays[vt]);
- numindices = indexarray.size();
-
- if (!numindices)
- break;
+ if(it.array->m_type == RAS_DisplayArray::LINE) {
+ // line drawing
+ glBegin(GL_LINES);
- int vindex=0;
- switch (mode)
- {
- case KX_MODE_LINES:
+ for(i=0; i<it.totindex; i+=2)
{
- glBegin(GL_LINES);
- vindex=0;
- for (unsigned int i=0;i<numindices;i+=2)
- {
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- glVertex3fv(vertexarray[(indexarray[vindex++])].getLocalXYZ());
- }
- glEnd();
+ vertex = &it.vertex[it.index[i]];
+ glVertex3fv(vertex->getXYZ());
+
+ vertex = &it.vertex[it.index[i+1]];
+ glVertex3fv(vertex->getXYZ());
}
- break;
- case KX_MODE_QUADS:
- {
+
+ glEnd();
+ }
+ else {
+ // triangle and quad drawing
+ if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ glBegin(GL_TRIANGLES);
+ else
glBegin(GL_QUADS);
- vindex=0;
- if (useObjectColor)
- {
- for (unsigned int i=0;i<numindices;i+=4)
- {
-
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- else
- {
- for (unsigned int i=0;i<numindices;i+=4)
- {
- // This looks curiously endian unsafe to me.
- // However it depends on the way the colors are packed into
- // the m_rgba field of RAS_TexVert
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
-
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- glEnd();
- break;
- }
- case KX_MODE_TRIANGLES:
+
+ for(i=0; i<it.totindex; i+=numvert)
{
- glBegin(GL_TRIANGLES);
- vindex=0;
- if (useObjectColor)
- {
- for (unsigned int i=0;i<numindices;i+=3)
- {
-
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
- }
- }
- else
- {
- for (unsigned int i=0;i<numindices;i+=3)
- {
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
-
- //
- glColor4ubv((const GLubyte *)(vertexarray[(indexarray[vindex])].getRGBA()));
- glNormal3fv(vertexarray[(indexarray[vindex])].getNormal());
- TexCoord(vertexarray[(indexarray[vindex])]);
- glVertex3fv(vertexarray[(indexarray[vindex])].getLocalXYZ());
- vindex++;
+ if(obcolor)
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+
+ for(j=0; j<numvert; j++) {
+ vertex = &it.vertex[it.index[i+j]];
+
+ if(!wireframe) {
+ if(!obcolor)
+ glColor4ubv((const GLubyte *)(vertex->getRGBA()));
+
+ glNormal3fv(vertex->getNormal());
+
+ if(multi)
+ TexCoord(*vertex);
+ else
+ glTexCoord2fv(vertex->getUV1());
}
+
+ glVertex3fv(vertex->getXYZ());
}
- glEnd();
- break;
}
- default:
- {
- }
- } // switch
- } // for each vertexarray
+
+ glEnd();
+ }
+ }
}
void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
@@ -1232,7 +821,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos,
const MT_Point3 &, const MT_Quaternion &camOrientQuat)
{
- MT_Matrix4x4 viewMat = mat;
+ m_viewmatrix = mat;
// correction for stereo
if(m_stereomode != RAS_STEREO_NOSTEREO)
@@ -1259,7 +848,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto
MT_Transform transform;
transform.setIdentity();
transform.translate(-(eyeline * m_eyeseparation / 2.0));
- viewMat *= transform;
+ m_viewmatrix *= transform;
}
break;
case RAS_STEREO_RIGHTEYE:
@@ -1268,20 +857,21 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto
MT_Transform transform;
transform.setIdentity();
transform.translate(eyeline * m_eyeseparation / 2.0);
- viewMat *= transform;
+ m_viewmatrix *= transform;
}
break;
}
}
- // convert row major matrix 'viewMat' to column major for OpenGL
- MT_Scalar cammat[16];
- viewMat.getValue(cammat);
- MT_CmMatrix4x4 viewCmmat = cammat;
+ m_viewinvmatrix = m_viewmatrix;
+ m_viewinvmatrix.invert();
+
+ // note: getValue gives back column major as needed by OpenGL
+ MT_Scalar glviewmat[16];
+ m_viewmatrix.getValue(glviewmat);
glMatrixMode(GL_MODELVIEW);
- m_viewmatrix = viewCmmat;
- glLoadMatrixd(&m_viewmatrix(0,0));
+ glLoadMatrixd(glviewmat);
m_campos = campos;
}
@@ -1292,20 +882,6 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
}
-
-void RAS_OpenGLRasterizer::LoadViewMatrix()
-{
- glLoadMatrixd(&m_viewmatrix(0,0));
-}
-
-
-
-void RAS_OpenGLRasterizer::EnableTextures(bool enable)
-{
-}
-
-
-
void RAS_OpenGLRasterizer::SetCullFace(bool enable)
{
if (enable)
@@ -1373,7 +949,10 @@ void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add)
void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue)
{
- m_motionblur = 1;
+ /* don't just set m_motionblur to 1, but check if it is 0 so
+ * we don't reset a motion blur that is already enabled */
+ if(m_motionblur == 0)
+ m_motionblur = 1;
m_motionblurvalue = motionblurvalue;
}
@@ -1388,23 +967,23 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode)
if(blendmode == m_last_blendmode)
return;
- if(blendmode == 0) {
+ if(blendmode == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- else if(blendmode == 1) {
+ else if(blendmode == GPU_BLEND_ADD) {
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
}
- else if(blendmode == 2) {
+ else if(blendmode == GPU_BLEND_ALPHA) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
- else if(blendmode == 4) {
+ else if(blendmode == GPU_BLEND_CLIP) {
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
@@ -1413,3 +992,16 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode)
m_last_blendmode = blendmode;
}
+void RAS_OpenGLRasterizer::SetFrontFace(bool ccw)
+{
+ if(m_last_frontface == ccw)
+ return;
+
+ if(ccw)
+ glFrontFace(GL_CCW);
+ else
+ glFrontFace(GL_CW);
+
+ m_last_frontface = ccw;
+}
+
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
index 02056cce446..0717cce0ce8 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
@@ -41,7 +41,7 @@ using namespace std;
#include "RAS_MaterialBucket.h"
#include "RAS_ICanvas.h"
-#define RAS_MAX_TEXCO 3 // match in BL_Material
+#define RAS_MAX_TEXCO 8 // match in BL_Material
#define RAS_MAX_ATTRIB 16 // match in BL_BlenderShader
struct OglDebugLine
@@ -77,7 +77,8 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
float m_ambb;
double m_time;
- MT_CmMatrix4x4 m_viewmatrix;
+ MT_Matrix4x4 m_viewmatrix;
+ MT_Matrix4x4 m_viewinvmatrix;
MT_Point3 m_campos;
StereoMode m_stereomode;
@@ -87,7 +88,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
float m_focallength;
bool m_setfocallength;
int m_noOfScanlines;
- bool InterlacedStereo() const;
//motion blur
int m_motionblur;
@@ -100,6 +100,7 @@ protected:
int m_texco_num;
int m_attrib_num;
int m_last_blendmode;
+ bool m_last_frontface;
/** Stores the caching information for the last material activated. */
RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo;
@@ -129,6 +130,7 @@ public:
virtual bool Init();
virtual void Exit();
virtual bool BeginFrame(int drawingmode, double time);
+ virtual void ClearColorBuffer();
virtual void ClearDepthBuffer();
virtual void ClearCachingInfo(void);
virtual void EndFrame();
@@ -136,6 +138,7 @@ public:
virtual void SetStereoMode(const StereoMode stereomode);
virtual bool Stereo();
+ virtual bool InterlacedStereo();
virtual void SetEye(const StereoEye eye);
virtual StereoEye GetEye();
virtual void SetEyeSeparation(const float eyeseparation);
@@ -144,33 +147,15 @@ public:
virtual float GetFocalLength();
virtual void SwapBuffers();
- virtual void IndexPrimitives(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot
- );
+ virtual void IndexPrimitives(class RAS_MeshSlot& ms);
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
virtual void IndexPrimitives_3DText(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
+ class RAS_MeshSlot& ms,
class RAS_IPolyMaterial* polymat,
- class RAS_IRenderTools* rendertools,
- bool useObjectColor,
- const MT_Vector4& rgbacolor
- );
-
- virtual void IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot);
+ class RAS_IRenderTools* rendertools);
+ void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi);
virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat);
virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat);
@@ -182,7 +167,6 @@ public:
);
virtual const MT_Point3& GetCameraPosition();
- virtual void LoadViewMatrix();
virtual void SetFog(
float start,
@@ -214,7 +198,6 @@ public:
virtual void SetDrawingMode(int drawingmode);
virtual int GetDrawingMode();
- virtual void EnableTextures(bool enable);
virtual void SetCullFace(bool enable);
virtual void SetLines(bool enable);
@@ -270,13 +253,10 @@ public:
virtual void SetTexCoord(TexCoGen coords, int unit);
virtual void SetAttrib(TexCoGen coords, int unit);
- void TexCoord(const RAS_TexVert &tv);
- virtual void GetViewMatrix(MT_Matrix4x4 &mat) const;
+ void TexCoord(const RAS_TexVert &tv);
- void Tangent(const RAS_TexVert& v1,
- const RAS_TexVert& v2,
- const RAS_TexVert& v3,
- const MT_Vector3 &no);
+ const MT_Matrix4x4& GetViewMatrix() const;
+ const MT_Matrix4x4& GetViewInvMatrix() const;
virtual void EnableMotionBlur(float motionblurvalue);
virtual void DisableMotionBlur();
@@ -293,6 +273,7 @@ public:
};
virtual void SetBlendingMode(int blendmode);
+ virtual void SetFrontFace(bool ccw);
};
#endif //__RAS_OPENGLRASTERIZER
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
index c78a97ad7be..2cb3b52adfb 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include "GL/glew.h"
+#include "GPU_extensions.h"
#include "STR_String.h"
#include "RAS_TexVert.h"
@@ -77,16 +78,16 @@ void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode)
{
case KX_BOUNDINGBOX:
case KX_WIREFRAME:
- glDisableClientState(GL_COLOR_ARRAY);
- glDisable(GL_CULL_FACE);
+ //glDisableClientState(GL_COLOR_ARRAY);
+ //glDisable(GL_CULL_FACE);
break;
case KX_SOLID:
- glDisableClientState(GL_COLOR_ARRAY);
+ //glDisableClientState(GL_COLOR_ARRAY);
break;
case KX_TEXTURED:
case KX_SHADED:
case KX_SHADOW:
- glEnableClientState(GL_COLOR_ARRAY);
+ //glEnableClientState(GL_COLOR_ARRAY);
default:
break;
}
@@ -98,141 +99,121 @@ void RAS_VAOpenGLRasterizer::Exit()
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
- EnableTextures(false);
RAS_OpenGLRasterizer::Exit();
}
-void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)
+void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms)
{
- static const GLsizei vtxstride = sizeof(RAS_TexVert);
+ static const GLsizei stride = sizeof(RAS_TexVert);
+ bool wireframe = m_drawingmode <= KX_WIREFRAME;
+ RAS_MeshSlot::iterator it;
GLenum drawmode;
- if(mode == KX_MODE_TRIANGLES)
- drawmode = GL_TRIANGLES;
- else if(mode == KX_MODE_QUADS)
- drawmode = GL_QUADS;
- else
- drawmode = GL_LINES;
- const RAS_TexVert* vertexarray;
- unsigned int numindices, vt;
-
- if (drawmode != GL_LINES)
- {
- if (useObjectColor)
- {
- glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
- } else
- {
- glColor4d(0,0,0,1.0);
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- else
- {
- glColor3d(0,0,0);
- }
-
- EnableTextures(false);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ if(!wireframe)
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// use glDrawElements to draw each vertexarray
- for (vt=0;vt<vertexarrays.size();vt++)
- {
- vertexarray = &((*vertexarrays[vt]) [0]);
- const KX_IndexArray & indexarray = (*indexarrays[vt]);
- numindices = indexarray.size();
-
- if (!numindices)
+ for(ms.begin(it); !ms.end(it); ms.next(it)) {
+ if(it.totindex == 0)
continue;
-
- glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
- glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
- glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1());
- if(glIsEnabled(GL_COLOR_ARRAY))
- glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
- //if(m_Lock)
- // local->Begin(vertexarrays[vt]->size());
+ // drawing mode
+ if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ drawmode = GL_TRIANGLES;
+ else if(it.array->m_type == RAS_DisplayArray::QUAD)
+ drawmode = GL_QUADS;
+ else
+ drawmode = GL_LINES;
+
+ // colors
+ if (drawmode != GL_LINES && !wireframe) {
+ if (ms.m_bObjectColor) {
+ const MT_Vector4& rgba = ms.m_RGBAcolor;
- // here the actual drawing takes places
- glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ }
+ else {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ }
+ else
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
+ glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
+ if(!wireframe) {
+ glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1());
+ if(glIsEnabled(GL_COLOR_ARRAY))
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
+ }
- //if(m_Lock)
- // local->End();
+ // here the actual drawing takes places
+ glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
}
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ if(!wireframe) {
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
}
-void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot)
+void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
{
- static const GLsizei vtxstride = sizeof(RAS_TexVert);
-
+ static const GLsizei stride = sizeof(RAS_TexVert);
+ bool wireframe = m_drawingmode <= KX_WIREFRAME;
+ RAS_MeshSlot::iterator it;
GLenum drawmode;
- if(mode == KX_MODE_TRIANGLES)
- drawmode = GL_TRIANGLES;
- else if(mode == KX_MODE_QUADS)
- drawmode = GL_QUADS;
- else
- drawmode = GL_LINES;
- const RAS_TexVert* vertexarray;
- unsigned int numindices, vt;
-
- if (drawmode != GL_LINES)
- {
- if (useObjectColor)
- {
- glDisableClientState(GL_COLOR_ARRAY);
- glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]);
- }
- else
- {
- glColor4d(0,0,0,1.0);
- glEnableClientState(GL_COLOR_ARRAY);
- }
- }
- else
- {
- glColor3d(0,0,0);
- }
+ if(!wireframe)
+ EnableTextures(true);
// use glDrawElements to draw each vertexarray
- for (vt=0;vt<vertexarrays.size();vt++)
- {
- vertexarray = &((*vertexarrays[vt]) [0]);
- const KX_IndexArray & indexarray = (*indexarrays[vt]);
- numindices = indexarray.size();
-
- if (!numindices)
+ for(ms.begin(it); !ms.end(it); ms.next(it)) {
+ if(it.totindex == 0)
continue;
- glVertexPointer(3,GL_FLOAT,vtxstride,vertexarray->getLocalXYZ());
- glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal());
- TexCoordPtr(vertexarray);
- if(glIsEnabled(GL_COLOR_ARRAY))
- glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA());
+ // drawing mode
+ if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
+ drawmode = GL_TRIANGLES;
+ else if(it.array->m_type == RAS_DisplayArray::QUAD)
+ drawmode = GL_QUADS;
+ else
+ drawmode = GL_LINES;
+
+ // colors
+ if (drawmode != GL_LINES && !wireframe) {
+ if (ms.m_bObjectColor) {
+ const MT_Vector4& rgba = ms.m_RGBAcolor;
- //if(m_Lock)
- // local->Begin(vertexarrays[vt]->size());
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+ }
+ else {
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ }
+ else
+ glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
+
+ glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
+ glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
+ if(!wireframe) {
+ TexCoordPtr(it.vertex);
+ if(glIsEnabled(GL_COLOR_ARRAY))
+ glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
+ }
// here the actual drawing takes places
- glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0]));
-
- //if(m_Lock)
- // local->End();
+ glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
+ }
+
+ if(!wireframe) {
+ glDisableClientState(GL_COLOR_ARRAY);
+ EnableTextures(false);
}
}
@@ -248,7 +229,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
for(unit=0; unit<m_texco_num; unit++)
{
glClientActiveTextureARB(GL_TEXTURE0_ARB+unit);
- if(tv->getFlag() & TV_2NDUV && (int)tv->getUnit() == unit) {
+ if(tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2());
continue;
@@ -257,7 +238,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
{
case RAS_TEXCO_ORCO:
case RAS_TEXCO_GLOB:
- glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ());
+ glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ());
break;
case RAS_TEXCO_UV1:
glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1());
@@ -284,7 +265,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv)
switch(m_attrib[unit]) {
case RAS_TEXCO_ORCO:
case RAS_TEXCO_GLOB:
- glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ());
+ glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ());
break;
case RAS_TEXCO_UV1:
glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1());
@@ -313,11 +294,6 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable)
TexCoGen *texco, *attrib;
int unit, texco_num, attrib_num;
- /* disable previously enabled texture coordinates and attributes. ideally
- * this shouldn't be necessary .. */
- if(enable)
- EnableTextures(false);
-
/* we cache last texcoords and attribs to ensure we disable the ones that
* were actually last set */
if(enable) {
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
index e4cc4ace0e8..766bbfbed0e 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h
@@ -50,22 +50,10 @@ public:
virtual void SetDrawingMode(int drawingmode);
- virtual void IndexPrimitives( const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot);
-
- virtual void IndexPrimitivesMulti(
- const vecVertexArray& vertexarrays,
- const vecIndexArrays & indexarrays,
- DrawMode mode,
- bool useObjectColor,
- const MT_Vector4& rgbacolor,
- class KX_ListSlot** slot);
-
+ virtual void IndexPrimitives(class RAS_MeshSlot& ms);
+ virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms);
+private:
virtual void EnableTextures(bool enable);
//virtual bool QueryArrays(){return true;}
//virtual bool QueryLists(){return m_Lock;}
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
index 0cf9c326370..8d46528f7f0 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript
@@ -1,12 +1,9 @@
#!/usr/bin/python
Import ('env')
-if env['WITH_BF_GLEXT'] == 1:
- env['CPPFLAGS'].append('-DWITH_GLEXT')
-
sources = env.Glob('*.cpp')
incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines '
-incs += ' #extern/glew/include ' + env['BF_OPENGL_INC']
+incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC']
env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] )
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp
index b74cb9cfcac..50331d7a664 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.cpp
+++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp
@@ -26,99 +26,82 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifdef WIN32
-
#pragma warning (disable:4786)
#endif
#include "RAS_Polygon.h"
-RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket,
- bool visible,
- int numverts,
- int vtxarrayindex)
- :m_bucket(bucket),
- m_vertexindexbase(numverts),
- m_numverts(numverts),
- m_edgecode(65535)
+RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray *darray, int numvert)
{
- m_vertexindexbase.m_vtxarray = vtxarrayindex ;//m_bucket->FindVertexArray(numverts);
- m_polyFlags.Visible = visible;
-}
-
+ m_bucket = bucket;
+ m_darray = darray;
+ m_offset[0]= m_offset[1]= m_offset[2]= m_offset[3]= 0;
+ m_numvert = numvert;
+ m_edgecode = 255;
+ m_polyflags = 0;
+}
int RAS_Polygon::VertexCount()
{
- return m_numverts;
+ return m_numvert;
}
-
-
-void RAS_Polygon::SetVertex(int i,
- unsigned int vertexindex ) //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal)
+void RAS_Polygon::SetVertexOffset(int i, unsigned short offset)
{
- m_vertexindexbase.SetIndex(i,vertexindex); //m_bucket->FindOrAddVertex(m_vertexindexbase.m_vtxarray,
- //xyz,uv,rgbacolor,normal));
+ m_offset[i] = offset;
}
-
-
-const KX_VertexIndex& RAS_Polygon::GetIndexBase()
+RAS_TexVert *RAS_Polygon::GetVertex(int i)
{
- return m_vertexindexbase;
+ return &m_darray->m_vertex[m_offset[i]];
}
-
-
-void RAS_Polygon::SetVisibleWireframeEdges(int edgecode)
+int RAS_Polygon::GetVertexOffset(int i)
{
- m_edgecode = edgecode;
+ return m_offset[i];
}
-
-
-// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc.
int RAS_Polygon::GetEdgeCode()
{
return m_edgecode;
}
+void RAS_Polygon::SetEdgeCode(int edgecode)
+{
+ m_edgecode = edgecode;
+}
bool RAS_Polygon::IsVisible()
{
- return m_polyFlags.Visible;
+ return (m_polyflags & VISIBLE) != 0;
}
-
+void RAS_Polygon::SetVisible(bool visible)
+{
+ if(visible) m_polyflags |= VISIBLE;
+ else m_polyflags &= ~VISIBLE;
+}
bool RAS_Polygon::IsCollider()
{
- return m_polyFlags.Collider;
+ return (m_polyflags & COLLIDER) != 0;
}
-
-
-void RAS_Polygon::SetCollider(bool col)
+void RAS_Polygon::SetCollider(bool visible)
{
- m_polyFlags.Collider = col;
+ if(visible) m_polyflags |= COLLIDER;
+ else m_polyflags &= ~COLLIDER;
}
-
-
-KX_VertexIndex& RAS_Polygon::GetVertexIndexBase()
+RAS_MaterialBucket* RAS_Polygon::GetMaterial()
{
- return m_vertexindexbase;
+ return m_bucket;
}
-
-
-RAS_MaterialBucket* RAS_Polygon::GetMaterial()
+RAS_DisplayArray* RAS_Polygon::GetDisplayArray()
{
- return m_bucket;
+ return m_darray;
}
diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h
index 7ce7926a816..18526ba45f7 100644
--- a/source/gameengine/Rasterizer/RAS_Polygon.h
+++ b/source/gameengine/Rasterizer/RAS_Polygon.h
@@ -35,55 +35,47 @@
#include <vector>
using namespace std;
-
-//
-// Bitfield that stores the flags for each CValue derived class
-//
-struct PolygonFlags {
- PolygonFlags() :
- Visible(true),
- Collider(true)
- {
- }
- unsigned char Visible : 1;
- unsigned char Collider : 1;
- //int Visible : 1;
- //int Collider : 1;
-};
+/* polygon flags */
class RAS_Polygon
{
+ /* location */
RAS_MaterialBucket* m_bucket;
- KX_VertexIndex m_vertexindexbase;
- int m_numverts;
- int m_edgecode;
- PolygonFlags m_polyFlags;
-
+ RAS_DisplayArray* m_darray;
+ unsigned short m_offset[4];
+ unsigned short m_numvert;
+
+ /* flags */
+ unsigned char m_edgecode;
+ unsigned char m_polyflags;
public:
- RAS_Polygon(RAS_MaterialBucket* bucket,
- bool visible,
- int numverts,
- int vtxarrayindex) ;
+ enum {
+ VISIBLE = 1,
+ COLLIDER = 2
+ };
+
+ RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray* darray, int numvert);
virtual ~RAS_Polygon() {};
-// RAS_TexVert* GetVertex(int index);
int VertexCount();
- void SetVertex(int i, unsigned int vertexindex); //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal)
-
- const KX_VertexIndex& GetIndexBase();
+ RAS_TexVert* GetVertex(int i);
- void SetVisibleWireframeEdges(int edgecode);
+ void SetVertexOffset(int i, unsigned short offset);
+ int GetVertexOffset(int i);
+
// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc.
int GetEdgeCode();
+ void SetEdgeCode(int edgecode);
bool IsVisible();
+ void SetVisible(bool visible);
+
bool IsCollider();
- void SetCollider(bool col);
+ void SetCollider(bool collider);
- KX_VertexIndex& GetVertexIndexBase();
RAS_MaterialBucket* GetMaterial();
-
+ RAS_DisplayArray* GetDisplayArray();
};
#endif
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp
index 935633dc636..b92965ed1cc 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.cpp
+++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp
@@ -27,12 +27,7 @@
*/
#include "RAS_TexVert.h"
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define SHORT(x) short(x*32767.0)
+#include "MT_Matrix4x4.h"
RAS_TexVert::RAS_TexVert(const MT_Point3& xyz,
const MT_Point2& uv,
@@ -40,7 +35,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz,
const MT_Vector4& tangent,
const unsigned int rgba,
const MT_Vector3& normal,
- const short flag,
+ const bool flat,
const unsigned int origindex)
{
xyz.getValue(m_localxyz);
@@ -49,9 +44,10 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz,
SetRGBA(rgba);
SetNormal(normal);
tangent.getValue(m_tangent);
- m_flag = flag;
+ m_flag = (flat)? FLAT: 0;
m_origindex = origindex;
m_unit = 2;
+ m_softBodyIndex = -1;
}
const MT_Point3& RAS_TexVert::xyz()
@@ -101,7 +97,7 @@ void RAS_TexVert::SetFlag(const short flag)
void RAS_TexVert::SetUnit(const unsigned int u)
{
- m_unit = u<=TV_MAX?u:TV_MAX;
+ m_unit = u<=MAX_UNIT?u:MAX_UNIT;
}
void RAS_TexVert::SetNormal(const MT_Vector3& normal)
@@ -109,12 +105,18 @@ void RAS_TexVert::SetNormal(const MT_Vector3& normal)
normal.getValue(m_normal);
}
+void RAS_TexVert::SetTangent(const MT_Vector3& tangent)
+{
+ tangent.getValue(m_tangent);
+}
+
// compare two vertices, and return TRUE if both are almost identical (they can be shared)
bool RAS_TexVert::closeTo(const RAS_TexVert* other)
{
return (m_flag == other->m_flag &&
m_rgba == other->m_rgba &&
MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) &&
+ MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) &&
MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) &&
MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) && // p --
MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))) ;
@@ -131,11 +133,10 @@ unsigned int RAS_TexVert::getUnit() const
return m_unit;
}
-
-void RAS_TexVert::getOffsets(void* &xyz, void* &uv1, void* &rgba, void* &normal) const
+void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat)
{
- xyz = (void *) m_localxyz;
- uv1 = (void *) m_uv1;
- rgba = (void *) &m_rgba;
- normal = (void *) m_normal;
+ SetXYZ((mat*MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue());
+ SetNormal((nmat*MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue());
+ SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue());
}
+
diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h
index bf092b4b230..54da109cbf1 100644
--- a/source/gameengine/Rasterizer/RAS_TexVert.h
+++ b/source/gameengine/Rasterizer/RAS_TexVert.h
@@ -37,11 +37,6 @@
static MT_Point3 g_pt3;
static MT_Point2 g_pt2;
-#define TV_CALCFACENORMAL 0x0001
-#define TV_2NDUV 0x0002
-
-#define TV_MAX 3//match Def in BL_Material.h
-
class RAS_TexVert
{
@@ -49,16 +44,23 @@ class RAS_TexVert
float m_uv1[2]; // 2*4 = 8
float m_uv2[2]; // 2*4 = 8
unsigned int m_rgba; // 4
- float m_tangent[4]; // 4*2 = 8
- float m_normal[3]; // 3*2 = 6
+ float m_tangent[4]; // 4*4 = 16
+ float m_normal[3]; // 3*4 = 12
short m_flag; // 2
+ short m_softBodyIndex; //2
unsigned int m_unit; // 4
- unsigned int m_origindex; // 4
+ unsigned int m_origindex; // 4
//---------
- // 56
+ // 56+6+8+2=72
// 32 bytes total size, fits nice = 56 = not fit nice.
- // We'll go for 64 bytes total size - 24 bytes left.
+
public:
+ enum {
+ FLAT = 1,
+ SECOND_UV = 2,
+ MAX_UNIT = 8
+ };
+
short getFlag() const;
unsigned int getUnit() const;
@@ -70,7 +72,7 @@ public:
const MT_Vector4& tangent,
const unsigned int rgba,
const MT_Vector3& normal,
- const short flag,
+ const bool flat,
const unsigned int origindex);
~RAS_TexVert() {};
@@ -82,7 +84,7 @@ public:
return m_uv2;
};
- const float* getLocalXYZ() const {
+ const float* getXYZ() const {
return m_localxyz;
};
@@ -90,6 +92,16 @@ public:
return m_normal;
}
+ short int getSoftBodyIndex() const
+ {
+ return m_softBodyIndex;
+ }
+
+ void setSoftBodyIndex(short int sbIndex)
+ {
+ m_softBodyIndex = sbIndex;
+ }
+
const float* getTangent() const {
return m_tangent;
}
@@ -108,20 +120,19 @@ public:
void SetRGBA(const unsigned int rgba);
void SetNormal(const MT_Vector3& normal);
+ void SetTangent(const MT_Vector3& tangent);
void SetFlag(const short flag);
void SetUnit(const unsigned u);
void SetRGBA(const MT_Vector4& rgba);
const MT_Point3& xyz();
- // compare two vertices, and return TRUE if both are almost identical (they can be shared)
- bool closeTo(const RAS_TexVert* other);
+ void Transform(const class MT_Matrix4x4& mat,
+ const class MT_Matrix4x4& nmat);
- bool closeTo(const MT_Point3& otherxyz,
- const MT_Point2& otheruv,
- const unsigned int otherrgba,
- short othernormal[3]) const;
- void getOffsets(void*&xyz, void *&uv1, void *&rgba, void *&normal) const;
+ // compare two vertices, to test if they can be shared, used for
+ // splitting up based on uv's, colors, etc
+ bool closeTo(const RAS_TexVert* other);
};
#endif //__RAS_TEXVERT
diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript
index e6bc657ed6d..a024f7e0ee6 100644
--- a/source/gameengine/Rasterizer/SConscript
+++ b/source/gameengine/Rasterizer/SConscript
@@ -3,11 +3,8 @@ Import ('env')
sources = env.Glob('*.cpp')
-if env['WITH_BF_GLEXT'] == 1:
- env['CPPFLAGS'].append('-DWITH_GLEXT')
-
-incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions'
+incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna'
incs += ' ' + env['BF_PYTHON_INC']
if env['OURPLATFORM']=='win32-vc':