diff --git a/.gitignore b/.gitignore index 68f7aa533..0a865079f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,9 @@ CMakeLists.txt.user* *.suo *.user +#-- vs & vscode +.vs* + *.lnk #-- binaries StuntRally*.* diff --git a/CMakeLists.txt b/CMakeLists.txt index dc7dfa109..716c12aa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -project(StuntRally CXX C) -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.16) +project(StuntRally) # Allows disabling building of components option(BUILD_GAME "Build the game binary." ON) @@ -34,13 +34,13 @@ if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() - - # Include path for additional CMake library finding scripts set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") # We want the binaries to be easily accessible -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # Data installation path @@ -113,7 +113,7 @@ if(BUILD_GAME OR BUILD_EDITOR) link_directories(${SDL2_LIBRARY_DIRS}) list(APPEND LIBS ${SDL2_LIBRARY}) - find_package(MyGUI REQUIRED QUIET) + find_package(MyGUI REQUIRED) include_directories(${MYGUI_INCLUDE_DIRS}) include_directories(${MYGUI_PLATFORM_INCLUDE_DIRS}) link_directories(${MYGUI_LIB_DIR}) diff --git a/cmake/FindBullet.cmake b/cmake/FindBullet.cmake deleted file mode 100644 index 8c9ae3c0d..000000000 --- a/cmake/FindBullet.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# - Try to find the Bullet physics engine -# -# This module defines the following variables -# -# BULLET_FOUND - Was bullet found -# BULLET_INCLUDE_DIRS - the Bullet include directories -# BULLET_LIBRARIES - Link to this, by default it includes bullet components -# -# This module accepts the following variables -# -# BULLET_ROOT - Can be set to bullet install path or Windows build path -# - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# Copyright 2009 Philip Lowman -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) - -macro(_FIND_BULLET_LIBRARY _var) - find_library(${_var} - NAMES - ${ARGN} - HINTS - ${BULLET_ROOT} - ${BULLET_ROOT}/out/release8/libs - ${BULLET_ROOT}/out/debug8/libs - PATH_SUFFIXES lib - ) - mark_as_advanced(${_var}) -endmacro() - -macro(_BULLET_APPEND_LIBRARIES _list _release) - set(_debug ${_release}_DEBUG) - if(${_debug}) - set(${_list} ${${_list}} optimized ${${_release}} debug ${${_debug}}) - else() - set(${_list} ${${_list}} ${${_release}}) - endif() -endmacro() - -find_path(BULLET_INCLUDE_DIR NAMES btBulletCollisionCommon.h - HINTS - ${BULLET_ROOT}/include - ${BULLET_ROOT}/src - PATH_SUFFIXES bullet -) - -# Find the libraries - -_FIND_BULLET_LIBRARY(BULLET_DYNAMICS_LIBRARY BulletDynamics) -_FIND_BULLET_LIBRARY(BULLET_DYNAMICS_LIBRARY_DEBUG BulletDynamics_Debug BulletDynamics_d) -_FIND_BULLET_LIBRARY(BULLET_COLLISION_LIBRARY BulletCollision) -_FIND_BULLET_LIBRARY(BULLET_COLLISION_LIBRARY_DEBUG BulletCollision_Debug BulletCollision_d) -_FIND_BULLET_LIBRARY(BULLET_MATH_LIBRARY BulletMath LinearMath) -_FIND_BULLET_LIBRARY(BULLET_MATH_LIBRARY_DEBUG BulletMath_Debug BulletMath_d LinearMath_d) -_FIND_BULLET_LIBRARY(BULLET_FILELOADER_LIBRARY BulletFileLoader) -_FIND_BULLET_LIBRARY(BULLET_FILELOADER_LIBRARY_DEBUG BulletFileLoader_Debug BulletFileLoader_d) -_FIND_BULLET_LIBRARY(BULLET_WORLDIMPORTER_LIBRARY BulletWorldImporter) -_FIND_BULLET_LIBRARY(BULLET_WORLDIMPORTER_LIBRARY_DEBUG BulletWorldImporter_Debug BulletWorldImporter_d) - -# handle the QUIETLY and REQUIRED arguments and set BULLET_FOUND to TRUE if -# all listed variables are TRUE -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Bullet DEFAULT_MSG - BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY - BULLET_FILELOADER_LIBRARY BULLET_WORLDIMPORTER_LIBRARY BULLET_INCLUDE_DIR) - -set(BULLET_INCLUDE_DIRS ${BULLET_INCLUDE_DIR}) - -# we only need dynamics, collision, math and worldimporter - -if(BULLET_FOUND) - _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_FILELOADER_LIBRARY) - _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_WORLDIMPORTER_LIBRARY) - _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_DYNAMICS_LIBRARY) - _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_COLLISION_LIBRARY) - _BULLET_APPEND_LIBRARIES(BULLET_LIBRARIES BULLET_MATH_LIBRARY) -endif() diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index 339f494dd..bc62c4074 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -79,6 +79,31 @@ IF (WIN32) #Windows SET(MYGUI_LIB_DIR ${OGRESOURCE}/lib) SET(MYGUI_LIBRARIES debug Debug/MyGUIEngine_d optimized Release/MyGUIEngine) ENDIF (OGRESOURCE) + IF (VCPKG_TOOLCHAIN) + # The MyGUIConfig.cmake file isn't installed by vcpkg and + # find_path() has trouble finding MyGUI.h for some reason, so + # manually specify the required paths here. This doesn't do + # much detection, so if MyGUI was not installed, configuration + # might proceed as normal, but the build will fail. + message(STATUS "Using MyGUI from vcpkg") + add_library(MyGUIStaticLinkage INTERFACE) + target_compile_definitions(MyGUIStaticLinkage INTERFACE MYGUI_STATIC) + find_package(Freetype REQUIRED QUIET) + target_link_libraries(MyGUIStaticLinkage INTERFACE Freetype::Freetype) + find_library(MYGUI_LIBRARIES_REL NAMES MyGUIEngineStatic) + if(MYGUI_LIBRARIES_REL) + set(MYGUI_LIBRARIES_REL optimized ${MYGUI_LIBRARIES_REL}) + endif() + find_library(MYGUI_LIBRARIES_DBG NAMES MyGUIEngineStatic_d) + if(MYGUI_LIBRARIES_DBG) + set(MYGUI_LIBRARIES_DBG debug ${MYGUI_LIBRARIES_DBG}) + endif() + target_link_libraries(MyGUIStaticLinkage INTERFACE ${MYGUI_LIBRARIES_REL} ${MYGUI_LIBRARIES_DBG}) + set(MYGUI_INCLUDE_DIRS "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/MYGUI") + # MYGUI_LIB_DIR is handled by above library, so just put anything here + set(MYGUI_LIB_DIR ${CMAKE_BINARY_DIR}) + set(MYGUI_LIBRARIES MyGUIStaticLinkage) + ENDIF (VCPKG_TOOLCHAIN) ELSE (WIN32) #Unix CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR) FIND_PACKAGE(PkgConfig) @@ -97,7 +122,9 @@ ELSE (WIN32) #Unix ENDIF (WIN32) #Do some preparation -SEPARATE_ARGUMENTS(MYGUI_INCLUDE_DIRS) +IF (NOT VCPKG_TOOLCHAIN) + SEPARATE_ARGUMENTS(MYGUI_INCLUDE_DIRS) +ENDIF (NOT VCPKG_TOOLCHAIN) SEPARATE_ARGUMENTS(MYGUI_LIBRARIES) SEPARATE_ARGUMENTS(MYGUI_PLATFORM_LIBRARIES) diff --git a/data/gui/MyGUI_Ogre_FP.glsl b/data/gui/MyGUI_Ogre_FP.glsl new file mode 100644 index 000000000..4f748c411 --- /dev/null +++ b/data/gui/MyGUI_Ogre_FP.glsl @@ -0,0 +1,17 @@ +#version 130 + +precision highp int; +precision highp float; + +uniform sampler2D sampleTexture; + +in vec4 outUV0; +in vec4 outColor; + +out vec4 fragColor; + +// Texturing fragment program for GLSL +void main() +{ + fragColor = outColor * texture(sampleTexture, outUV0.xy); +} \ No newline at end of file diff --git a/data/gui/MyGUI_Ogre_FP.glsles b/data/gui/MyGUI_Ogre_FP.glsles new file mode 100644 index 000000000..22d6d319e --- /dev/null +++ b/data/gui/MyGUI_Ogre_FP.glsles @@ -0,0 +1,15 @@ +#version 100 + +precision highp int; +precision highp float; + +uniform sampler2D sampleTexture; + +varying vec4 outUV0; +varying vec4 outColor; + +// Texturing fragment program for GLSL ES +void main() +{ + gl_FragColor = outColor * texture2D(sampleTexture, outUV0.xy); +} \ No newline at end of file diff --git a/data/gui/MyGUI_Ogre_FP.hlsl b/data/gui/MyGUI_Ogre_FP.hlsl new file mode 100644 index 000000000..b9549aff1 --- /dev/null +++ b/data/gui/MyGUI_Ogre_FP.hlsl @@ -0,0 +1,9 @@ +void main( + uniform sampler2D sampleTexture : register(s0), + in float4 inPosition : POSITION, + in float4 inColor : TEXCOORD0, + in float2 inTexcoord : TEXCOORD1, + out float4 Out : COLOR ) +{ + Out = tex2D(sampleTexture, inTexcoord) * inColor; +} \ No newline at end of file diff --git a/data/gui/MyGUI_Ogre_VP.glsl b/data/gui/MyGUI_Ogre_VP.glsl new file mode 100644 index 000000000..5d3a2f11b --- /dev/null +++ b/data/gui/MyGUI_Ogre_VP.glsl @@ -0,0 +1,20 @@ +#version 130 + +precision highp int; +precision highp float; + +in vec4 position; +in vec4 uv0; +in vec4 colour; +uniform mat4 worldViewProj; + +out vec4 outUV0; +out vec4 outColor; + +// Texturing vertex program for GLSL +void main() +{ + gl_Position = worldViewProj * position; + outUV0 = uv0; + outColor = colour; +} \ No newline at end of file diff --git a/data/gui/MyGUI_Ogre_VP.glsles b/data/gui/MyGUI_Ogre_VP.glsles new file mode 100644 index 000000000..272f14bd1 --- /dev/null +++ b/data/gui/MyGUI_Ogre_VP.glsles @@ -0,0 +1,20 @@ +#version 100 + +precision highp int; +precision highp float; + +attribute vec4 position; +attribute vec4 uv0; +attribute vec4 colour; +uniform mat4 worldViewProj; + +varying vec4 outUV0; +varying vec4 outColor; + +// Texturing vertex program for GLSL ES +void main() +{ + gl_Position = worldViewProj * position; + outUV0 = uv0; + outColor = colour; +} \ No newline at end of file diff --git a/data/gui/MyGUI_Ogre_VP.hlsl b/data/gui/MyGUI_Ogre_VP.hlsl new file mode 100644 index 000000000..eb8e984c6 --- /dev/null +++ b/data/gui/MyGUI_Ogre_VP.hlsl @@ -0,0 +1,13 @@ +void main( + in float4 inPosition : POSITION0, + in float4 inColor : COLOR0, + in float2 inTexcoord : TEXCOORD0, + uniform float4x4 worldViewProj, + out float4 outPosition : SV_POSITION, + out float4 outColor : TEXCOORD0, + out float2 outTexcoord : TEXCOORD1 ) +{ + outPosition = mul(worldViewProj, inPosition); + outColor = inColor; + outTexcoord = inTexcoord; +} \ No newline at end of file diff --git a/source/BulletFileLoader/CMakeLists.txt b/source/BulletFileLoader/CMakeLists.txt new file mode 100644 index 000000000..180434e64 --- /dev/null +++ b/source/BulletFileLoader/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(BulletFileLoader STATIC + bChunk.cpp + bChunk.h + bCommon.h + bDefines.h + bDNA.cpp + bDNA.h + bFile.cpp + bFile.h + btBulletFile.cpp + btBulletFile.h) + +target_include_directories(BulletFileLoader PRIVATE ${BULLET_INCLUDE_DIRS}) +target_link_libraries(BulletFileLoader PRIVATE ${BULLET_LIBRARIES}) +target_include_directories(BulletFileLoader PUBLIC ./) diff --git a/source/BulletFileLoader/bChunk.cpp b/source/BulletFileLoader/bChunk.cpp new file mode 100644 index 000000000..564e5507e --- /dev/null +++ b/source/BulletFileLoader/bChunk.cpp @@ -0,0 +1,75 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "bChunk.h" +#include "bDefines.h" +#include "bFile.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + +using namespace bParse; + + +// ----------------------------------------------------- // +short ChunkUtils::swapShort(short sht) +{ + SWITCH_SHORT(sht); + return sht; +} + +// ----------------------------------------------------- // +int ChunkUtils::swapInt(int inte) +{ + SWITCH_INT(inte); + return inte; +} + +// ----------------------------------------------------- // +long64 ChunkUtils::swapLong64(long64 lng) +{ + SWITCH_LONGINT(lng); + return lng; +} + +// ----------------------------------------------------- // +int ChunkUtils::getOffset(int flags) +{ + // if the file is saved in a + // different format, get the + // file's chunk size + int res = CHUNK_HEADER_LEN; + + if (VOID_IS_8) + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr4); + } + else + { + if (flags &FD_BITS_VARIES) + res = sizeof(bChunkPtr8); + } + return res; +} + + + + + +//eof diff --git a/source/BulletFileLoader/bChunk.h b/source/BulletFileLoader/bChunk.h new file mode 100644 index 000000000..77039bcf9 --- /dev/null +++ b/source/BulletFileLoader/bChunk.h @@ -0,0 +1,92 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BCHUNK_H__ +#define __BCHUNK_H__ + +#if defined (_WIN32) && ! defined (__MINGW32__) + #define long64 __int64 +#elif defined (__MINGW32__) + #include + #define long64 int64_t +#else + #define long64 long long +#endif + + +namespace bParse { + + + // ----------------------------------------------------- // + class bChunkPtr4 + { + public: + bChunkPtr4(){} + int code; + int len; + union + { + int m_uniqueInt; + }; + int dna_nr; + int nr; + }; + + // ----------------------------------------------------- // + class bChunkPtr8 + { + public: + bChunkPtr8(){} + int code, len; + union + { + long64 oldPrev; + int m_uniqueInts[2]; + }; + int dna_nr, nr; + }; + + // ----------------------------------------------------- // + class bChunkInd + { + public: + bChunkInd(){} + int code, len; + void *oldPtr; + int dna_nr, nr; + }; + + + // ----------------------------------------------------- // + class ChunkUtils + { + public: + + // file chunk offset + static int getOffset(int flags); + + // endian utils + static short swapShort(short sht); + static int swapInt(int inte); + static long64 swapLong64(long64 lng); + + }; + + + const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd))); + const bool VOID_IS_8 = ((sizeof(void*)==8)); +} + +#endif//__BCHUNK_H__ diff --git a/source/BulletFileLoader/bCommon.h b/source/BulletFileLoader/bCommon.h new file mode 100644 index 000000000..b01d2b899 --- /dev/null +++ b/source/BulletFileLoader/bCommon.h @@ -0,0 +1,39 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BCOMMON_H__ +#define __BCOMMON_H__ + + +#include +//#include "bLog.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btHashMap.h" + +namespace bParse { + + class bMain; + class bFileData; + class bFile; + class bDNA; + + // delete void* undefined + typedef struct bStructHandle {int unused;}bStructHandle; + typedef btAlignedObjectArray bListBasePtr; + typedef btHashMap bPtrMap; +} + + +#endif//__BCOMMON_H__ diff --git a/source/BulletFileLoader/bDNA.cpp b/source/BulletFileLoader/bDNA.cpp new file mode 100644 index 000000000..7b42062b3 --- /dev/null +++ b/source/BulletFileLoader/bDNA.cpp @@ -0,0 +1,629 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include + +#include "bDNA.h" +#include "bChunk.h" +#include +#include +#include + +//this define will force traversal of structures, to check backward (and forward) compatibility +//#define TEST_BACKWARD_FORWARD_COMPATIBILITY + + +using namespace bParse; + + +// ----------------------------------------------------- // +bDNA::bDNA() + : mPtrLen(0) +{ + // -- +} + +// ----------------------------------------------------- // +bDNA::~bDNA() +{ + // -- +} + +// ----------------------------------------------------- // +bool bDNA::lessThan(bDNA *file) +{ + return ( m_Names.size() < file->m_Names.size()); +} + +// ----------------------------------------------------- // +char *bDNA::getName(int ind) +{ + assert(ind <= (int)m_Names.size()); + return m_Names[ind].m_name; +} + + +// ----------------------------------------------------- // +char *bDNA::getType(int ind) +{ + assert(ind<= (int)mTypes.size()); + return mTypes[ind]; +} + + +// ----------------------------------------------------- // +short *bDNA::getStruct(int ind) +{ + assert(ind <= (int)mStructs.size()); + return mStructs[ind]; +} + + +// ----------------------------------------------------- // +short bDNA::getLength(int ind) +{ + assert(ind <= (int)mTlens.size()); + return mTlens[ind]; +} + + +// ----------------------------------------------------- // +int bDNA::getReverseType(short type) +{ + + int* intPtr = mStructReverse.find(type); + if (intPtr) + return *intPtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getReverseType(const char *type) +{ + + btHashString key(type); + int* valuePtr = mTypeLookup.find(key); + if (valuePtr) + return *valuePtr; + + return -1; +} + +// ----------------------------------------------------- // +int bDNA::getNumStructs() +{ + return (int)mStructs.size(); +} + +// ----------------------------------------------------- // +bool bDNA::flagNotEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagEqual(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + int flag = mCMPFlags[dna_nr]; + return flag == FDF_STRUCT_EQU; +} + +// ----------------------------------------------------- // +bool bDNA::flagNone(int dna_nr) +{ + assert(dna_nr <= (int)mCMPFlags.size()); + return mCMPFlags[dna_nr] == FDF_NONE; +} + +// ----------------------------------------------------- // +int bDNA::getPointerSize() +{ + return mPtrLen; +} + +// ----------------------------------------------------- // +void bDNA::initRecurseCmpFlags(int iter) +{ + // iter is FDF_STRUCT_NEQU + + short *oldStrc = mStructs[iter]; + short type = oldStrc[0]; + + for (int i=0; i<(int)mStructs.size(); i++) + { + if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU ) + { + short *curStruct = mStructs[i]; + int eleLen = curStruct[1]; + curStruct+=2; + + for (int j=0; jgetReverseType(typeName); + if (newLookup == -1) + { + mCMPFlags[i] = FDF_NONE; + continue; + } + short *curStruct = memDNA->mStructs[newLookup]; +#else + // memory for file + + if (oldLookup < memDNA->mStructs.size()) + { + short *curStruct = memDNA->mStructs[oldLookup]; +#endif + + + + // rebuild... + mCMPFlags[i] = FDF_STRUCT_NEQU; + +#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY + + if (curStruct[1] == oldStruct[1]) + { + // type len same ... + if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]]) + { + bool isSame = true; + int elementLength = oldStruct[1]; + + + curStruct+=2; + oldStruct+=2; + + + for (int j=0; jmTypes[curStruct[0]])!=0) + { + isSame=false; + break; + } + + // name the same + if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0) + { + isSame=false; + break; + } + } + // flag valid == + if (isSame) + mCMPFlags[i] = FDF_STRUCT_EQU; + } + } +#endif + } + } + + + + + + // recurse in + for ( i=0; i<(int)mStructs.size(); i++) + { + if (mCMPFlags[i] == FDF_STRUCT_NEQU) + initRecurseCmpFlags(i); + } +} + + + + +static int name_is_array(char* name, int* dim1, int* dim2) { + int len = strlen(name); + /*fprintf(stderr,"[%s]",name);*/ + /*if (len >= 1) { + if (name[len-1] != ']') + return 1; + } + return 0;*/ + char *bp; + int num; + if (dim1) { + *dim1 = 1; + } + if (dim2) { + *dim2 = 1; + } + bp = strchr(name, '['); + if (!bp) { + return 0; + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array parse error.\n"); + return 0; + } + } + if (dim2) { + *dim2 = num; + } + + /* find second dim, if any. */ + bp = strchr(bp, '['); + if (!bp) { + return 1; /* at least we got the first dim. */ + } + num = 0; + while (++bp < name+len-1) { + const char c = *bp; + if (c == ']') { + break; + } + if (c <= '9' && c >= '0') { + num *= 10; + num += (c - '0'); + } else { + printf("array2 parse error.\n"); + return 1; + } + } + if (dim1) { + if (dim2) { + *dim1 = *dim2; + *dim2 = num; + } else { + *dim1 = num; + } + } + + return 1; +} + + +// ----------------------------------------------------- // +void bDNA::init(char *data, int len, bool swap) +{ + int *intPtr=0;short *shtPtr=0; + char *cp = 0;int dataLen =0; + //long nr=0; + intPtr = (int*)data; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp(data, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; intPtr++; + } + + + + // Parse names + if (swap) + { + *intPtr = ChunkUtils::swapInt(*intPtr); + } + dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (swap) + { + *intPtr = ChunkUtils::swapInt(*intPtr); + } + dataLen = *intPtr; + intPtr++; + + cp = (char*)intPtr; + for ( i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + dataLen = (int)mTypes.size(); + + shtPtr = (short*)intPtr; + for ( i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + assert(strncmp(cp, "STRC", 4)==0); intPtr++; + + if (swap) + { + *intPtr = ChunkUtils::swapInt(*intPtr); + } + dataLen = *intPtr; + intPtr++; + + + shtPtr = (short*)intPtr; + for ( i=0; itypes_count; ++i) { + /* if (!bf->types[i].is_struct)*/ + { + printf("%3d: sizeof(%s%s)=%d", + i, + bf->types[i].is_struct ? "struct " : "atomic ", + bf->types[i].name, bf->types[i].size); + if (bf->types[i].is_struct) { + int j; + printf(", %d fields: { ", bf->types[i].fieldtypes_count); + for (j=0; jtypes[i].fieldtypes_count; ++j) { + printf("%s %s", + bf->types[bf->types[i].fieldtypes[j]].name, + bf->names[bf->types[i].fieldnames[j]]); + if (j == bf->types[i].fieldtypes_count-1) { + printf(";}"); + } else { + printf("; "); + } + } + } + printf("\n\n"); + + } + } +#endif + +} + + + + +//eof + + diff --git a/source/BulletFileLoader/bDNA.h b/source/BulletFileLoader/bDNA.h new file mode 100644 index 000000000..691080bf5 --- /dev/null +++ b/source/BulletFileLoader/bDNA.h @@ -0,0 +1,110 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BDNA_H__ +#define __BDNA_H__ + + +#include "bCommon.h" + +namespace bParse { + + struct bNameInfo + { + char* m_name; + bool m_isPointer; + int m_dim0; + int m_dim1; + }; + + class bDNA + { + public: + bDNA(); + ~bDNA(); + + void init(char *data, int len, bool swap=false); + + int getArraySize(char* str); + int getArraySizeNew(short name) + { + const bNameInfo& nameInfo = m_Names[name]; + return nameInfo.m_dim0*nameInfo.m_dim1; + } + int getElementSize(short type, short name) + { + const bNameInfo& nameInfo = m_Names[name]; + int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1; + return size; + } + + int getNumNames() const + { + return m_Names.size(); + } + + char *getName(int ind); + char *getType(int ind); + short *getStruct(int ind); + short getLength(int ind); + int getReverseType(short type); + int getReverseType(const char *type); + + + int getNumStructs(); + + // + bool lessThan(bDNA* other); + + void initCmpFlags(bDNA *memDNA); + bool flagNotEqual(int dna_nr); + bool flagEqual(int dna_nr); + bool flagNone(int dna_nr); + + + int getPointerSize(); + + void dumpTypeDefinitions(); + + + private: + enum FileDNAFlags + { + FDF_NONE=0, + FDF_STRUCT_NEQU, + FDF_STRUCT_EQU + }; + + void initRecurseCmpFlags(int i); + + btAlignedObjectArray mCMPFlags; + + btAlignedObjectArray m_Names; + btAlignedObjectArray mTypes; + btAlignedObjectArray mStructs; + btAlignedObjectArray mTlens; + btHashMap mStructReverse; + btHashMap mTypeLookup; + + int mPtrLen; + + + + + }; +} + + +#endif//__BDNA_H__ diff --git a/source/BulletFileLoader/bDefines.h b/source/BulletFileLoader/bDefines.h new file mode 100644 index 000000000..3a9e2c987 --- /dev/null +++ b/source/BulletFileLoader/bDefines.h @@ -0,0 +1,139 @@ +/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* 3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef __B_DEFINES_H__ +#define __B_DEFINES_H__ + + +// MISC defines, see BKE_global.h, BKE_utildefines.h +#define SIZEOFBLENDERHEADER 12 + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else +# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + + +// ------------------------------------------------------------ +#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +# define MAKE_ID2(c, d) ( (c)<<8 | (d) ) +# define MOST_SIG_BYTE 0 +# define BBIG_ENDIAN +#else +# define MAKE_ID2(c, d) ( (d)<<8 | (c) ) +# define MOST_SIG_BYTE 1 +# define BLITTLE_ENDIAN +#endif + +// ------------------------------------------------------------ +#define ID_SCE MAKE_ID2('S', 'C') +#define ID_LI MAKE_ID2('L', 'I') +#define ID_OB MAKE_ID2('O', 'B') +#define ID_ME MAKE_ID2('M', 'E') +#define ID_CU MAKE_ID2('C', 'U') +#define ID_MB MAKE_ID2('M', 'B') +#define ID_MA MAKE_ID2('M', 'A') +#define ID_TE MAKE_ID2('T', 'E') +#define ID_IM MAKE_ID2('I', 'M') +#define ID_IK MAKE_ID2('I', 'K') +#define ID_WV MAKE_ID2('W', 'V') +#define ID_LT MAKE_ID2('L', 'T') +#define ID_SE MAKE_ID2('S', 'E') +#define ID_LF MAKE_ID2('L', 'F') +#define ID_LA MAKE_ID2('L', 'A') +#define ID_CA MAKE_ID2('C', 'A') +#define ID_IP MAKE_ID2('I', 'P') +#define ID_KE MAKE_ID2('K', 'E') +#define ID_WO MAKE_ID2('W', 'O') +#define ID_SCR MAKE_ID2('S', 'R') +#define ID_VF MAKE_ID2('V', 'F') +#define ID_TXT MAKE_ID2('T', 'X') +#define ID_SO MAKE_ID2('S', 'O') +#define ID_SAMPLE MAKE_ID2('S', 'A') +#define ID_GR MAKE_ID2('G', 'R') +#define ID_ID MAKE_ID2('I', 'D') +#define ID_AR MAKE_ID2('A', 'R') +#define ID_AC MAKE_ID2('A', 'C') +#define ID_SCRIPT MAKE_ID2('P', 'Y') +#define ID_FLUIDSIM MAKE_ID2('F', 'S') +#define ID_NT MAKE_ID2('N', 'T') +#define ID_BR MAKE_ID2('B', 'R') + + +#define ID_SEQ MAKE_ID2('S', 'Q') +#define ID_CO MAKE_ID2('C', 'O') +#define ID_PO MAKE_ID2('A', 'C') +#define ID_NLA MAKE_ID2('N', 'L') + +#define ID_VS MAKE_ID2('V', 'S') +#define ID_VN MAKE_ID2('V', 'N') + + +// ------------------------------------------------------------ +#define FORM MAKE_ID('F','O','R','M') +#define DDG1 MAKE_ID('3','D','G','1') +#define DDG2 MAKE_ID('3','D','G','2') +#define DDG3 MAKE_ID('3','D','G','3') +#define DDG4 MAKE_ID('3','D','G','4') +#define GOUR MAKE_ID('G','O','U','R') +#define BLEN MAKE_ID('B','L','E','N') +#define DER_ MAKE_ID('D','E','R','_') +#define V100 MAKE_ID('V','1','0','0') +#define DATA MAKE_ID('D','A','T','A') +#define GLOB MAKE_ID('G','L','O','B') +#define IMAG MAKE_ID('I','M','A','G') +#define USER MAKE_ID('U','S','E','R') + + +// ------------------------------------------------------------ +#define DNA1 MAKE_ID('D','N','A','1') +#define REND MAKE_ID('R','E','N','D') +#define ENDB MAKE_ID('E','N','D','B') +#define NAME MAKE_ID('N','A','M','E') +#define SDNA MAKE_ID('S','D','N','A') +#define TYPE MAKE_ID('T','Y','P','E') +#define TLEN MAKE_ID('T','L','E','N') +#define STRC MAKE_ID('S','T','R','C') + + +// ------------------------------------------------------------ +#define SWITCH_INT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_SHORT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; } + +// ------------------------------------------------------------ +#define SWITCH_LONGINT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ + s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ + s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; } + +#endif//__B_DEFINES_H__ diff --git a/source/BulletFileLoader/bFile.cpp b/source/BulletFileLoader/bFile.cpp new file mode 100644 index 000000000..69a503e79 --- /dev/null +++ b/source/BulletFileLoader/bFile.cpp @@ -0,0 +1,1773 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include "bFile.h" +#include "bCommon.h" +#include "bChunk.h" +#include "bDNA.h" +#include +#include +#include +#include "bDefines.h" +#include "LinearMath/btSerializer.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btMinMax.h" + +#define SIZEOFBLENDERHEADER 12 +#define MAX_ARRAY_LENGTH 512 +using namespace bParse; +#define MAX_STRLEN 1024 + +const char* getCleanName(const char* memName, char* buffer) +{ + int slen = strlen(memName); + assert(sleninit will convert part of DNA file endianness to current CPU endianness if necessary + mFileDNA->init((char*)dnaBuffer, dnaLen, (mFlags & FD_ENDIAN_SWAP)!=0); + + if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS) + mFileDNA->dumpTypeDefinitions(); +} + +// ----------------------------------------------------- // +void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength) +{ + if ( (mFlags &FD_OK) ==0) + return; + + if (mFlags & FD_FILEDNA_IS_MEMDNA) + { + setFileDNA(verboseMode,memDna,memDnaLength); + } + + if (mFileDNA==0) + { + char *blenderData = mFileBuffer; + bChunkInd dna; + dna.oldPtr = 0; + + char *tempBuffer = blenderData; + for (int i=0; i 0) + { + if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0) + dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags)); + else dna.oldPtr = 0; + } + else dna.oldPtr = 0; + } + // Some Bullet files are missing the DNA1 block + // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME + // In Bullet tests its SDNA + NAME + else if (strncmp(tempBuffer, "SDNANAME", 8) ==0) + { + dna.oldPtr = blenderData + i; + dna.len = mFileLen-i; + + // Also no REND block, so exit now. + if (mVersion==276) break; + } + + if (mDataStart && dna.oldPtr) break; + tempBuffer++; + } + if (!dna.oldPtr || !dna.len) + { + //printf("Failed to find DNA1+SDNA pair\n"); + mFlags &= ~FD_OK; + return; + } + + + mFileDNA = new bDNA(); + + + ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary + mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0); + + + if (mVersion==276) + { + int i; + for (i=0;igetNumNames();i++) + { + if (strcmp(mFileDNA->getName(i),"int")==0) + { + mFlags |= FD_BROKEN_DNA; + } + } + if ((mFlags&FD_BROKEN_DNA)!=0) + { + //printf("warning: fixing some broken DNA version\n"); + } + } + + + + if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS) + mFileDNA->dumpTypeDefinitions(); + } + mMemoryDNA = new bDNA(); + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + mMemoryDNA->init(memDna,memDnaLength,littleEndian==0); + + + + + ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files + if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames()) + { + mFlags |= FD_VERSION_VARIES; + //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform"); + } + + // as long as it kept up to date it will be ok!! + if (mMemoryDNA->lessThan(mFileDNA)) + { + //printf ("Warning, file DNA is newer than built in."); + } + + + mFileDNA->initCmpFlags(mMemoryDNA); + + parseData(); + + resolvePointers(verboseMode); + + updateOldPointers(); + + +} + + + +// ----------------------------------------------------- // +void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag) +{ + char *data = head; + short *strc = mFileDNA->getStruct(dataChunk.dna_nr); + + + + const char s[] = "SoftBodyMaterialData"; + int szs = sizeof(s); + if (strncmp((char*)&dataChunk.code,"ARAY",4)==0) + { + short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr); + char *oldType = mFileDNA->getType(oldStruct[0]); + if (strncmp(oldType,s,szs)==0) + { + return; + } + } + + + int len = mFileDNA->getLength(strc[0]); + + for (int i=0; icode & 0xFFFF)==0) + c->code >>=16; + SWITCH_INT(c->len); + SWITCH_INT(c->dna_nr); + SWITCH_INT(c->nr); + } else + { + bChunkPtr8* c = (bChunkPtr8*) dataPtr; + if ((c->code & 0xFFFF)==0) + c->code >>=16; + SWITCH_INT(c->len); + SWITCH_INT(c->dna_nr); + SWITCH_INT(c->nr); + + } + } else + { + if (mFlags &FD_BITS_VARIES) + { + bChunkPtr8*c = (bChunkPtr8*) dataPtr; + if ((c->code & 0xFFFF)==0) + c->code >>=16; + SWITCH_INT(c->len); + SWITCH_INT(c->dna_nr); + SWITCH_INT(c->nr); + + } else + { + bChunkPtr4* c = (bChunkPtr4*) dataPtr; + if ((c->code & 0xFFFF)==0) + c->code >>=16; + SWITCH_INT(c->len); + + SWITCH_INT(c->dna_nr); + SWITCH_INT(c->nr); + + } + } + +} + + +void bFile::swapDNA(char* ptr) +{ + bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0); + + int offset = (mFlags & FD_FILE_64)? 24 : 20; + char* data = &ptr[offset]; + +// void bDNA::init(char *data, int len, bool swap) + int *intPtr=0;short *shtPtr=0; + char *cp = 0;int dataLen =0; + intPtr = (int*)data; + + /* + SDNA (4 bytes) (magic number) + NAME (4 bytes) + (4 bytes) amount of names (int) + + + */ + + if (strncmp(data, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; + intPtr++; + } else + { + + if (strncmp(data+4, "SDNA", 4)==0) + { + // skip ++ NAME + intPtr++; + intPtr++; + intPtr++; + } + } + + + + + // Parse names + if (swap) + dataLen = ChunkUtils::swapInt(*intPtr); + else + dataLen = *intPtr; + + *intPtr = ChunkUtils::swapInt(*intPtr); + intPtr++; + + cp = (char*)intPtr; + int i; + for ( i=0; i amount of types (int) + + + */ + + intPtr = (int*)cp; + assert(strncmp(cp, "TYPE", 4)==0); intPtr++; + + if (swap) + dataLen = ChunkUtils::swapInt(*intPtr); + else + dataLen = *intPtr; + + *intPtr = ChunkUtils::swapInt(*intPtr); + + intPtr++; + + cp = (char*)intPtr; + for ( i=0; i (short) the lengths of types + + */ + + // Parse type lens + intPtr = (int*)cp; + assert(strncmp(cp, "TLEN", 4)==0); intPtr++; + + + shtPtr = (short*)intPtr; + for ( i=0; i amount of structs (int) + + + + + + + */ + + intPtr = (int*)shtPtr; + cp = (char*)intPtr; + assert(strncmp(cp, "STRC", 4)==0); + intPtr++; + + if (swap) + dataLen = ChunkUtils::swapInt(*intPtr); + else + dataLen = *intPtr; + + *intPtr = ChunkUtils::swapInt(*intPtr); + + intPtr++; + + + shtPtr = (short*)intPtr; + for ( i=0; i=0) + { + swap(dataPtrHead, dataChunk,ignoreEndianFlag); + } else + { + //printf("unknown chunk\n"); + } + } + + // next please! + dataPtr += seek; + + seek = getNextBlock(&dataChunk, dataPtr, mFlags); + if (seek < 0) + break; + } + + if (mFlags & FD_ENDIAN_SWAP) + { + mFlags &= ~FD_ENDIAN_SWAP; + } else + { + mFlags |= FD_ENDIAN_SWAP; + } + + + +} + + +// ----------------------------------------------------- // +char* bFile::readStruct(char *head, bChunkInd& dataChunk) +{ + bool ignoreEndianFlag = false; + + if (mFlags & FD_ENDIAN_SWAP) + swap(head, dataChunk, ignoreEndianFlag); + + + + if (!mFileDNA->flagEqual(dataChunk.dna_nr)) + { + // Ouch! need to rebuild the struct + short *oldStruct,*curStruct; + char *oldType, *newType; + int oldLen, curLen, reverseOld; + + + oldStruct = mFileDNA->getStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + + oldLen = mFileDNA->getLength(oldStruct[0]); + + if ((mFlags&FD_BROKEN_DNA)!=0) + { + if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20) + { + return 0; + } + if ((strcmp(oldType,"btShortIntIndexData")==0)) + { + int allocLen = 2; + char *dataAlloc = new char[(dataChunk.nr*allocLen)+1]; + memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1); + short* dest = (short*) dataAlloc; + const short* src = (short*) head; + for (int i=0;igetReverseType(oldType); + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + curLen = mMemoryDNA->getLength(curStruct[0]); + + + + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + numallocs++; + // numBlocks * length + + int allocLen = (curLen); + char *dataAlloc = new char[(dataChunk.nr*allocLen)+1]; + memset(dataAlloc, 0, (dataChunk.nr*allocLen)); + + // track allocated + addDataBlock(dataAlloc); + + char *cur = dataAlloc; + char *old = head; + for (int block=0; blockgetStruct(dataChunk.dna_nr); + oldType = mFileDNA->getType(oldStruct[0]); + printf("%s equal structure, just memcpy\n",oldType); +#endif // + } + + + char *dataAlloc = new char[(dataChunk.len)+1]; + memset(dataAlloc, 0, dataChunk.len+1); + + + // track allocated + addDataBlock(dataAlloc); + + memcpy(dataAlloc, head, dataChunk.len); + return dataAlloc; + +} + + +// ----------------------------------------------------- // +void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers) +{ + if (old_dna == -1) return; + if (new_dna == -1) return; + + //disable this, because we need to fixup pointers/ListBase + if (0)//mFileDNA->flagEqual(old_dna)) + { + short *strc = mFileDNA->getStruct(old_dna); + int len = mFileDNA->getLength(strc[0]); + + memcpy(strcPtr, dtPtr, len); + return; + } + + // Ok, now build the struct + char *memType, *memName, *cpc, *cpo; + short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct; + int elementLength, size, revType, old_nr, new_nr, fpLen; + short firstStructType; + + + // File to memory lookup + memoryStruct = mMemoryDNA->getStruct(new_dna); + fileStruct = mFileDNA->getStruct(old_dna); + firstStruct = fileStruct; + + + filePtrOld = fileStruct; + firstStructType = mMemoryDNA->getStruct(0)[0]; + + // Get number of elements + elementLength = memoryStruct[1]; + memoryStruct+=2; + + cpc = strcPtr; cpo = 0; + for (int ele=0; elegetType(memoryStruct[0]); + memName = mMemoryDNA->getName(memoryStruct[1]); + + + size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]); + revType = mMemoryDNA->getReverseType(memoryStruct[0]); + + if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*') + { + cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld); + if (cpo) + { + int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]); + old_nr = mFileDNA->getReverseType(memType); + new_nr = revType; + fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]); + if (arrayLen==1) + { + parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers); + } else + { + char* tmpCpc = cpc; + char* tmpCpo = cpo; + + for (int i=0;i3 && type <8) + { + char c; + char *cp = data; + for (int i=0; igetPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + + if (!src && !dst) + return; + + + if (ptrFile == ptrMem) + { + memcpy(dst, src, ptrMem); + } + else if (ptrMem==4 && ptrFile==8) + { + btPointerUid* oldPtr = (btPointerUid*)src; + btPointerUid* newPtr = (btPointerUid*)dst; + + if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1]) + { + //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers + //so it can be used to distinguish between .blend and .bullet + newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0]; + } else + { + //deal with pointers the Blender .blend style way, see + //readfile.c in the Blender source tree + long64 longValue = *((long64*)src); + //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros + if (mFlags & FD_ENDIAN_SWAP) + SWITCH_LONGINT(longValue); + *((int*)dst) = (int)(longValue>>3); + } + + } + else if (ptrMem==8 && ptrFile==4) + { + btPointerUid* oldPtr = (btPointerUid*)src; + btPointerUid* newPtr = (btPointerUid*)dst; + if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1]) + { + newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0]; + newPtr->m_uniqueIds[1] = 0; + } else + { + *((long64*)dst)= *((int*)src); + } + } + else + { + printf ("%d %d\n", ptrFile,ptrMem); + assert(0 && "Invalid pointer len"); + } + + +} + + +// ----------------------------------------------------- // +void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers) +{ + // find the matching memory dna data + // to the file being loaded. Fill the + // memory with the file data... + + int len = dna_addr[1]; + dna_addr+=2; + + for (int i=0; igetType(dna_addr[0]); + const char* name = mFileDNA->getName(dna_addr[1]); + + + + int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]); + + if ((mFlags&FD_BROKEN_DNA)!=0) + { + if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0)) + { + eleLen = 0; + } + } + + if (strcmp(lookupName, name)==0) + { + //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str()); + int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]); + //assert(arrayLenold == arrayLen); + + if (name[0] == '*') + { + // cast pointers + int ptrFile = mFileDNA->getPointerSize(); + int ptrMem = mMemoryDNA->getPointerSize(); + safeSwapPtr(strcData,data); + + if (fixupPointers) + { + if (arrayLen > 1) + { + //void **sarray = (void**)strcData; + //void **darray = (void**)data; + + char *cpc, *cpo; + cpc = (char*)strcData; + cpo = (char*)data; + + for (int a=0; agetStruct(old_nr); + int elementLength = old[1]; + old+=2; + + for (int i=0; igetType(old[0]); + char* name = mFileDNA->getName(old[1]); + int len = mFileDNA->getElementSize(old[0], old[1]); + + if (strcmp(lookupName, name)==0) + { + if (strcmp(type, lookupType)==0) + { + if (foundPos) + *foundPos = old; + return data; + } + return 0; + } + data+=len; + } + return 0; +} + + +// ----------------------------------------------------- // +void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag) +{ + if (dna_nr == -1) return; + + short *strc = mFileDNA->getStruct(dna_nr); + //short *firstStrc = strc; + + int elementLen= strc[1]; + strc+=2; + + short first = mFileDNA->getStruct(0)[0]; + + char *buf = data; + for (int i=0; igetType(strc[0]); + char *name = mFileDNA->getName(strc[1]); + + int size = mFileDNA->getElementSize(strc[0], strc[1]); + if (strc[0] >= first && name[0]!='*') + { + int old_nr = mFileDNA->getReverseType(type); + int arrayLen = mFileDNA->getArraySizeNew(strc[1]); + if (arrayLen==1) + { + swapStruct(old_nr,buf,ignoreEndianFlag); + } else + { + char* tmpBuf = buf; + for (int i=0;igetArraySize(name); + int arrayLen = mFileDNA->getArraySizeNew(strc[1]); + //assert(arrayLenOld == arrayLen); + swapData(buf, strc[0], arrayLen,ignoreEndianFlag); + } + buf+=size; + } +} + +void bFile::resolvePointersMismatch() +{ +// printf("resolvePointersStructMismatch\n"); + + int i; + + for (i=0;i< m_pointerFixupArray.size();i++) + { + char* cur = m_pointerFixupArray.at(i); + void** ptrptr = (void**) cur; + void* ptr = *ptrptr; + ptr = findLibPointer(ptr); + if (ptr) + { + //printf("Fixup pointer!\n"); + *(ptrptr) = ptr; + } else + { +// printf("pointer not found: %x\n",cur); + } + } + + + for (i=0; igetPointerSize(); + int ptrFile = mFileDNA->getPointerSize(); + + + int blockLen = block->len / ptrFile; + + void *onptr = findLibPointer(*ptrptr); + if (onptr) + { + char *newPtr = new char[blockLen * ptrMem]; + addDataBlock(newPtr); + memset(newPtr, 0, blockLen * ptrMem); + + void **onarray = (void**)onptr; + char *oldPtr = (char*)onarray; + + int p = 0; + while (blockLen-- > 0) + { + btPointerUid dp = {{0}}; + safeSwapPtr((char*)dp.m_uniqueIds, oldPtr); + + void **tptr = (void**)(newPtr + p * ptrMem); + *tptr = findLibPointer(dp.m_ptr); + + oldPtr += ptrFile; + ++p; + } + + *ptrptr = newPtr; + } + } + } +} + + +///this loop only works fine if the Blender DNA structure of the file matches the headerfiles +void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + short oldLen = fileDna->getLength(oldStruct[0]); + //char* structType = fileDna->getType(oldStruct[0]); + + char* cur = (char*)findLibPointer(dataChunk.oldPtr); + for (int block=0; blockgetStruct(0)[0]; + + + char* elemPtr= strcPtr; + + short int* oldStruct = fileDna->getStruct(dna_nr); + + int elementLength = oldStruct[1]; + oldStruct+=2; + + int totalSize = 0; + + for (int ele=0; elegetType(oldStruct[0]); + memName = fileDna->getName(oldStruct[1]); + + + + int arrayLen = fileDna->getArraySizeNew(oldStruct[1]); + if (memName[0] == '*') + { + if (arrayLen > 1) + { + void **array= (void**)elemPtr; + for (int a=0; a ",&memName[1]); + printf("%p ", array[a]); + printf("\n",&memName[1]); + } + + array[a] = findLibPointer(array[a]); + } + } + else + { + void** ptrptr = (void**) elemPtr; + void* ptr = *ptrptr; + if (verboseMode & FD_VERBOSE_EXPORT_XML) + { + for (int i=0;i ",&memName[1]); + printf("%p ", ptr); + printf("\n",&memName[1]); + } + ptr = findLibPointer(ptr); + + if (ptr) + { + // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr); + *(ptrptr) = ptr; + if (memName[1] == '*' && ptrptr && *ptrptr) + { + // This will only work if the given **array is continuous + void **array= (void**)*(ptrptr); + void *np= array[0]; + int n=0; + while (np) + { + np= findLibPointer(array[n]); + if (np) array[n]= np; + n++; + } + } + } else + { + // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr); + } + } + } else + { + int revType = fileDna->getReverseType(oldStruct[0]); + if (oldStruct[0]>=firstStructType) //revType != -1 && + { + char cleanName[MAX_STRLEN]; + getCleanName(memName,cleanName); + + int arrayLen = fileDna->getArraySizeNew(oldStruct[1]); + int byteOffset = 0; + + if (verboseMode & FD_VERBOSE_EXPORT_XML) + { + for (int i=0;i1) + { + printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen); + } else + { + printf("<%s type=\"%s\">\n",cleanName,memType); + } + } + + for (int i=0;i\n",cleanName); + } + } else + { + //export a simple type + if (verboseMode & FD_VERBOSE_EXPORT_XML) + { + + if (arrayLen>MAX_ARRAY_LENGTH) + { + printf("too long\n"); + } else + { + //printf("%s %s\n",memType,memName); + + bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0); + + if (isIntegerType) + { + const char* newtype="int"; + int dbarray[MAX_ARRAY_LENGTH]; + int* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + char cleanName[MAX_STRLEN]; + getCleanName(memName,cleanName); + + int i; + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (i=0;i",cleanName,memType); + else + printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen); + for (i=0;i\n",cleanName); + } + } else + { + const char* newtype="double"; + double dbarray[MAX_ARRAY_LENGTH]; + double* dbPtr = 0; + char* tmp = elemPtr; + dbPtr = &dbarray[0]; + if (dbPtr) + { + int i; + getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr); + for (i=0;i",memName,memType); + } + else + { + printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen); + } + for (i=0;i\n",cleanName); + } + } + } + + } + } + } + + int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]); + totalSize += size; + elemPtr+=size; + + } + + return totalSize; +} + + +///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures +void bFile::resolvePointers(int verboseMode) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + //char *dataPtr = mFileBuffer+mDataStart; + + if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES)) + { + resolvePointersMismatch(); + } + + { + + if (verboseMode & FD_VERBOSE_EXPORT_XML) + { + printf("\n"); + int numitems = m_chunks.size(); + printf("\n", btGetVersion(), numitems); + } + for (int i=0;iflagEqual(dataChunk.dna_nr)) + { + //dataChunk.len + short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr); + char* oldType = fileDna->getType(oldStruct[0]); + + if (verboseMode & FD_VERBOSE_EXPORT_XML) + printf(" <%s pointer=%p>\n",oldType,dataChunk.oldPtr); + + resolvePointersChunk(dataChunk, verboseMode); + + if (verboseMode & FD_VERBOSE_EXPORT_XML) + printf(" \n",oldType); + } else + { + //printf("skipping mStruct\n"); + } + } + if (verboseMode & FD_VERBOSE_EXPORT_XML) + { + printf("\n"); + } + } + + +} + + +// ----------------------------------------------------- // +void* bFile::findLibPointer(void *ptr) +{ + + bStructHandle** ptrptr = getLibPointers().find(ptr); + if (ptrptr) + return *ptrptr; + return 0; +} + + +void bFile::updateOldPointers() +{ + int i; + + for (i=0;igetStruct(dataChunk.dna_nr); + char* typeName = dna->getType(newStruct[0]); + printf("%3d: %s ",i,typeName); + + printf("code=%s ",codestr); + + printf("ptr=%p ",dataChunk.oldPtr); + printf("len=%d ",dataChunk.len); + printf("nr=%d ",dataChunk.nr); + if (dataChunk.nr!=1) + { + printf("not 1\n"); + } + printf("\n"); + + + + + } + +#if 0 + IDFinderData ifd; + ifd.success = 0; + ifd.IDname = NULL; + ifd.just_print_it = 1; + for (i=0; im_blocks.size(); ++i) + { + BlendBlock* bb = bf->m_blocks[i]; + printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size()); + block_ID_finder(bb, bf, &ifd); + printf("\n"); + } +#endif + +} + + +void bFile::writeChunks(FILE* fp, bool fixupPointers) +{ + bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA; + + for (int i=0;igetStruct(dataChunk.dna_nr); + oldType = fileDna->getType(oldStruct[0]); + //int oldLen = fileDna->getLength(oldStruct[0]); + ///don't try to convert Link block data, just memcpy it. Other data can be converted. + reverseOld = mMemoryDNA->getReverseType(oldType); + + + if ((reverseOld!=-1)) + { + // make sure it's here + //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!"); + // + curStruct = mMemoryDNA->getStruct(reverseOld); + newType = mMemoryDNA->getType(curStruct[0]); + // make sure it's the same + assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!"); + + + curLen = mMemoryDNA->getLength(curStruct[0]); + dataChunk.dna_nr = reverseOld; + if (strcmp("Link",oldType)!=0) + { + dataChunk.len = curLen * dataChunk.nr; + } else + { +// printf("keep length of link = %d\n",dataChunk.len); + } + + //write the structure header + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + + + + short int* curStruct1; + curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr); + assert(curStruct1 == curStruct); + + char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr; + + //write the actual contents of the structure(s) + fwrite(cur,dataChunk.len,1,fp); + } else + { + printf("serious error, struct mismatch: don't write\n"); + } + } + +} + + +// ----------------------------------------------------- // +int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags) +{ + bool swap = false; + bool varies = false; + + if (flags &FD_ENDIAN_SWAP) + swap = true; + if (flags &FD_BITS_VARIES) + varies = true; + + if (VOID_IS_8) + { + if (varies) + { + bChunkPtr4 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr4)); + + + bChunkPtr8 chunk; + + chunk.code = head.code; + chunk.len = head.len; + chunk.m_uniqueInts[0] = head.m_uniqueInt; + chunk.m_uniqueInts[1] = 0; + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr8 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr8)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + else + { + if (varies) + { + bChunkPtr8 head; + memcpy(&head, dataPtr, sizeof(bChunkPtr8)); + + + bChunkPtr4 chunk; + chunk.code = head.code; + chunk.len = head.len; + + if (head.m_uniqueInts[0]==head.m_uniqueInts[1]) + { + chunk.m_uniqueInt = head.m_uniqueInts[0]; + } else + { + long64 oldPtr =0; + memcpy(&oldPtr, &head.m_uniqueInts[0], 8); + if (swap) + SWITCH_LONGINT(oldPtr); + chunk.m_uniqueInt = (int)(oldPtr >> 3); + } + + + chunk.dna_nr = head.dna_nr; + chunk.nr = head.nr; + + if (swap) + { + if ((chunk.code & 0xFFFF)==0) + chunk.code >>=16; + + SWITCH_INT(chunk.len); + SWITCH_INT(chunk.dna_nr); + SWITCH_INT(chunk.nr); + } + + memcpy(dataChunk, &chunk, sizeof(bChunkInd)); + } + else + { + bChunkPtr4 c; + memcpy(&c, dataPtr, sizeof(bChunkPtr4)); + + if (swap) + { + if ((c.code & 0xFFFF)==0) + c.code >>=16; + + SWITCH_INT(c.len); + SWITCH_INT(c.dna_nr); + SWITCH_INT(c.nr); + } + memcpy(dataChunk, &c, sizeof(bChunkInd)); + } + } + + if (dataChunk->len < 0) + return -1; + +#if 0 + print ("----------"); + print (dataChunk->code); + print (dataChunk->len); + print (dataChunk->old); + print (dataChunk->dna_nr); + print (dataChunk->nr); +#endif + return (dataChunk->len+ChunkUtils::getOffset(flags)); +} + + + +//eof diff --git a/source/BulletFileLoader/bFile.h b/source/BulletFileLoader/bFile.h new file mode 100644 index 000000000..e3523febb --- /dev/null +++ b/source/BulletFileLoader/bFile.h @@ -0,0 +1,175 @@ +/* +bParse +Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __BFILE_H__ +#define __BFILE_H__ + +#include "bCommon.h" +#include "bChunk.h" +#include + +namespace bParse { + + // ----------------------------------------------------- // + enum bFileFlags + { + FD_INVALID =0, + FD_OK =1, + FD_VOID_IS_8 =2, + FD_ENDIAN_SWAP =4, + FD_FILE_64 =8, + FD_BITS_VARIES =16, + FD_VERSION_VARIES = 32, + FD_DOUBLE_PRECISION =64, + FD_BROKEN_DNA = 128, + FD_FILEDNA_IS_MEMDNA = 256 + }; + + enum bFileVerboseMode + { + FD_VERBOSE_EXPORT_XML = 1, + FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2, + FD_VERBOSE_DUMP_CHUNKS = 4, + FD_VERBOSE_DUMP_FILE_INFO=8, + }; + // ----------------------------------------------------- // + class bFile + { + protected: + + char m_headerString[7]; + + bool mOwnsBuffer; + char* mFileBuffer; + int mFileLen; + int mVersion; + + + bPtrMap mLibPointers; + + int mDataStart; + bDNA* mFileDNA; + bDNA* mMemoryDNA; + + btAlignedObjectArray m_pointerFixupArray; + btAlignedObjectArray m_pointerPtrFixupArray; + + btAlignedObjectArray m_chunks; + btHashMap m_chunkPtrPtrMap; + + // + + bPtrMap mDataPointers; + + + int mFlags; + + // //////////////////////////////////////////////////////////////////////////// + + // buffer offset util + int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags); + void safeSwapPtr(char *dst, const char *src); + + virtual void parseHeader(); + + virtual void parseData() = 0; + + void resolvePointersMismatch(); + void resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode); + + int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion); + //void swapPtr(char *dst, char *src); + + void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers); + void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers); + char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos); + + + void swap(char *head, class bChunkInd& ch, bool ignoreEndianFlag); + void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag); + void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag); + void swapLen(char *dataPtr); + void swapDNA(char* ptr); + + + char* readStruct(char *head, class bChunkInd& chunk); + char *getAsString(int code); + + virtual void parseInternal(int verboseMode, char* memDna,int memDnaLength); + + public: + bFile(const char *filename, const char headerString[7]); + + //todo: make memoryBuffer const char + //bFile( const char *memoryBuffer, int len); + bFile( char *memoryBuffer, int len, const char headerString[7]); + virtual ~bFile(); + + bDNA* getFileDNA() + { + return mFileDNA; + } + + virtual void addDataBlock(char* dataBlock) = 0; + + int getFlags() const + { + return mFlags; + } + + void setFileDNAisMemoryDNA() + { + mFlags |= FD_FILEDNA_IS_MEMDNA; + } + + bPtrMap& getLibPointers() + { + return mLibPointers; + } + + void* findLibPointer(void *ptr); + + bool ok(); + + virtual void parse(int verboseMode) = 0; + + virtual int write(const char* fileName, bool fixupPointers=false) = 0; + + virtual void writeChunks(FILE* fp, bool fixupPointers ); + + virtual void writeDNA(FILE* fp) = 0; + + void updateOldPointers(); + void resolvePointers(int verboseMode); + + void dumpChunks(bDNA* dna); + + virtual void setFileDNA(int verboseMode, char* buffer, int len); + + int getVersion() const + { + return mVersion; + } + //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped + void preSwap(); + void writeFile(const char* fileName); + + + + }; +} + + +#endif//__BFILE_H__ diff --git a/source/BulletFileLoader/btBulletFile.cpp b/source/BulletFileLoader/btBulletFile.cpp new file mode 100644 index 000000000..aa1c383fd --- /dev/null +++ b/source/BulletFileLoader/btBulletFile.cpp @@ -0,0 +1,439 @@ +/* +bParse +Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBulletFile.h" +#include "bDefines.h" +#include "bDNA.h" + +#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__) +#include +#endif +#include + + +// 32 && 64 bit versions +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +#ifdef _WIN64 +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; +#else +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; +#endif //_WIN64 +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + +extern char sBulletDNAstr64[]; +extern int sBulletDNAlen64; +extern char sBulletDNAstr[]; +extern int sBulletDNAlen; + +#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + +using namespace bParse; + +btBulletFile::btBulletFile() +:bFile("", "BULLET ") +{ + mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it" + + m_DnaCopy = 0; + + +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +#ifdef _WIN64 + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); +#else//_WIN64 + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); +#endif//_WIN64 +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + m_DnaCopy = (char*) btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64); + } + else + { + m_DnaCopy =(char*) btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + mMemoryDNA->init(m_DnaCopy,sBulletDNAlen); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +} + + + +btBulletFile::btBulletFile(const char* fileName) +:bFile(fileName, "BULLET ") +{ + m_DnaCopy = 0; +} + + + +btBulletFile::btBulletFile(char *memoryBuffer, int len) +:bFile(memoryBuffer,len, "BULLET ") +{ + m_DnaCopy = 0; +} + + +btBulletFile::~btBulletFile() +{ + if (m_DnaCopy) + btAlignedFree(m_DnaCopy); + + + while (m_dataBlocks.size()) + { + char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1]; + delete[] dataBlock; + m_dataBlocks.pop_back(); + } + +} + + + +// ----------------------------------------------------- // +void btBulletFile::parseData() +{ +// printf ("Building datablocks"); +// printf ("Chunk size = %d",CHUNK_HEADER_LEN); +// printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags)); + + const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0; + + //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0; + + + int remain = mFileLen; + + mDataStart = 12; + remain-=12; + + //invalid/empty file? + if (remain < sizeof(bChunkInd)) + return; + + char *dataPtr = mFileBuffer+mDataStart; + + bChunkInd dataChunk; + dataChunk.code = 0; + + + //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags); + int seek = getNextBlock(&dataChunk, dataPtr, mFlags); + + + if (mFlags &FD_ENDIAN_SWAP) + swapLen(dataPtr); + + //dataPtr += ChunkUtils::getOffset(mFlags); + char *dataPtrHead = 0; + + while (dataChunk.code != DNA1) + { + if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) ) + { + + // one behind + if (dataChunk.code == SDNA) break; + //if (dataChunk.code == DNA1) break; + + // same as (BHEAD+DATA dependency) + dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags); + if (dataChunk.dna_nr>=0) + { + char *id = readStruct(dataPtrHead, dataChunk); + + // lookup maps + if (id) + { + m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk); + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id); + + m_chunks.push_back(dataChunk); + // block it + //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code); + //if (listID) + // listID->push_back((bStructHandle*)id); + } + + if (dataChunk.code == BT_MULTIBODY_CODE) + { + m_multiBodies.push_back((bStructHandle*)id); + } + + if (dataChunk.code == BT_SOFTBODY_CODE) + { + m_softBodies.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_RIGIDBODY_CODE) + { + m_rigidBodies.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_DYNAMICSWORLD_CODE) + { + m_dynamicsWorldInfo.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_CONSTRAINT_CODE) + { + m_constraints.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_QUANTIZED_BVH_CODE) + { + m_bvhs.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_TRIANLGE_INFO_MAP) + { + m_triangleInfoMaps.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_COLLISIONOBJECT_CODE) + { + m_collisionObjects.push_back((bStructHandle*) id); + } + + if (dataChunk.code == BT_SHAPE_CODE) + { + m_collisionShapes.push_back((bStructHandle*) id); + } + + // if (dataChunk.code == GLOB) + // { + // m_glob = (bStructHandle*) id; + // } + } else + { + //printf("unknown chunk\n"); + + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead); + } + } else + { + printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n"); + } + + + dataPtr += seek; + remain-=seek; + if (remain<=0) + break; + + seek = getNextBlock(&dataChunk, dataPtr, mFlags); + if (mFlags &FD_ENDIAN_SWAP) + swapLen(dataPtr); + + if (seek < 0) + break; + } + +} + +void btBulletFile::addDataBlock(char* dataBlock) +{ + m_dataBlocks.push_back(dataBlock); + +} + + + + +void btBulletFile::writeDNA(FILE* fp) +{ + + bChunkInd dataChunk; + dataChunk.code = DNA1; + dataChunk.dna_nr = 0; + dataChunk.nr = 1; +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { +#ifdef _WIN64 + dataChunk.len = sBulletDNAlen64; + dataChunk.oldPtr = sBulletDNAstr64; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); +#else + btAssert(0); +#endif + } + else + { +#ifndef _WIN64 + dataChunk.len = sBulletDNAlen; + dataChunk.oldPtr = sBulletDNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); +#else//_WIN64 + btAssert(0); +#endif//_WIN64 + } +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + dataChunk.len = sBulletDNAlen64; + dataChunk.oldPtr = sBulletDNAstr64; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp); + } + else + { + dataChunk.len = sBulletDNAlen; + dataChunk.oldPtr = sBulletDNAstr; + fwrite(&dataChunk,sizeof(bChunkInd),1,fp); + fwrite(sBulletDNAstr, sBulletDNAlen,1,fp); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES +} + + +void btBulletFile::parse(int verboseMode) +{ +#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { +#ifdef _WIN64 + + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + parseInternal(verboseMode,(char*)sBulletDNAstr64,sBulletDNAlen64); +#else + btAssert(0); +#endif + } + else + { +#ifndef _WIN64 + + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen); +#else + btAssert(0); +#endif + } +#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + if (VOID_IS_8) + { + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16); + memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64); + parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen64); + } + else + { + if (m_DnaCopy) + delete m_DnaCopy; + m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16); + memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen); + parseInternal(verboseMode,m_DnaCopy,sBulletDNAlen); + } +#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES + + //the parsing will convert to cpu endian + mFlags &=~FD_ENDIAN_SWAP; + + int littleEndian= 1; + littleEndian= ((char*)&littleEndian)[0]; + + mFileBuffer[8] = littleEndian?'v':'V'; + +} + +// experimental +int btBulletFile::write(const char* fileName, bool fixupPointers) +{ + FILE *fp = fopen(fileName, "wb"); + if (fp) + { + char header[SIZEOFBLENDERHEADER] ; + memcpy(header, m_headerString, 7); + int endian= 1; + endian= ((char*)&endian)[0]; + + if (endian) + { + header[7] = '_'; + } else + { + header[7] = '-'; + } + if (VOID_IS_8) + { + header[8]='V'; + } else + { + header[8]='v'; + } + + header[9] = '2'; + header[10] = '7'; + header[11] = '5'; + + fwrite(header,SIZEOFBLENDERHEADER,1,fp); + + writeChunks(fp, fixupPointers); + + writeDNA(fp); + + fclose(fp); + + } else + { + printf("Error: cannot open file %s for writing\n",fileName); + return 0; + } + return 1; +} + + + +void btBulletFile::addStruct(const char* structType,void* data, int len, void* oldPtr, int code) +{ + + bParse::bChunkInd dataChunk; + dataChunk.code = code; + dataChunk.nr = 1; + dataChunk.len = len; + dataChunk.dna_nr = mMemoryDNA->getReverseType(structType); + dataChunk.oldPtr = oldPtr; + + ///Perform structure size validation + short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr); + int elemBytes; + elemBytes= mMemoryDNA->getLength(structInfo[0]); +// int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]); + assert(len==elemBytes); + + mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data); + m_chunks.push_back(dataChunk); +} + diff --git a/source/BulletFileLoader/btBulletFile.h b/source/BulletFileLoader/btBulletFile.h new file mode 100644 index 000000000..2296400a3 --- /dev/null +++ b/source/BulletFileLoader/btBulletFile.h @@ -0,0 +1,86 @@ +/* +bParse +Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_BULLET_FILE_H +#define BT_BULLET_FILE_H + + +#include "bFile.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "bDefines.h" + + +#include "LinearMath/btSerializer.h" + + + +namespace bParse { + + // ----------------------------------------------------- // + class btBulletFile : public bFile + { + + + protected: + + char* m_DnaCopy; + + public: + + btAlignedObjectArray m_multiBodies; + + btAlignedObjectArray m_softBodies; + + btAlignedObjectArray m_rigidBodies; + + btAlignedObjectArray m_collisionObjects; + + btAlignedObjectArray m_collisionShapes; + + btAlignedObjectArray m_constraints; + + btAlignedObjectArray m_bvhs; + + btAlignedObjectArray m_triangleInfoMaps; + + btAlignedObjectArray m_dynamicsWorldInfo; + + btAlignedObjectArray m_dataBlocks; + btBulletFile(); + + btBulletFile(const char* fileName); + + btBulletFile(char *memoryBuffer, int len); + + virtual ~btBulletFile(); + + virtual void addDataBlock(char* dataBlock); + + + // experimental + virtual int write(const char* fileName, bool fixupPointers=false); + + virtual void parse(int verboseMode); + + virtual void parseData(); + + virtual void writeDNA(FILE* fp); + + void addStruct(const char* structType,void* data, int len, void* oldPtr, int code); + + }; +}; + +#endif //BT_BULLET_FILE_H diff --git a/source/BulletWorldImporter/CMakeLists.txt b/source/BulletWorldImporter/CMakeLists.txt new file mode 100644 index 000000000..13b43dd8f --- /dev/null +++ b/source/BulletWorldImporter/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(BulletWorldImporter STATIC + btBulletWorldImporter.cpp + btBulletWorldImporter.h + btWorldImporter.cpp + btWorldImporter.h) + +target_include_directories(BulletWorldImporter PRIVATE ${BULLET_INCLUDE_DIRS}) +target_link_libraries(BulletWorldImporter PRIVATE BulletFileLoader ${BULLET_LIBRARIES}) +target_include_directories(BulletWorldImporter PUBLIC ./) diff --git a/source/BulletWorldImporter/btBulletWorldImporter.cpp b/source/BulletWorldImporter/btBulletWorldImporter.cpp new file mode 100644 index 000000000..6c8e2f8cd --- /dev/null +++ b/source/BulletWorldImporter/btBulletWorldImporter.cpp @@ -0,0 +1,337 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBulletWorldImporter.h" +#include "../BulletFileLoader/btBulletFile.h" + +#include "btBulletDynamicsCommon.h" +#ifndef USE_GIMPACT +#include "BulletCollision/Gimpact/btGImpactShape.h" +#endif + +//#define USE_INTERNAL_EDGE_UTILITY +#ifdef USE_INTERNAL_EDGE_UTILITY +#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h" +#endif //USE_INTERNAL_EDGE_UTILITY + +btBulletWorldImporter::btBulletWorldImporter(btDynamicsWorld* world) + : btWorldImporter(world) +{ +} + +btBulletWorldImporter::~btBulletWorldImporter() +{ +} + +bool btBulletWorldImporter::loadFile(const char* fileName, const char* preSwapFilenameOut) +{ + bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName); + + bool result = loadFileFromMemory(bulletFile2); + //now you could save the file in 'native' format using + //bulletFile2->writeFile("native.bullet"); + if (result) + { + if (preSwapFilenameOut) + { + bulletFile2->preSwap(); + bulletFile2->writeFile(preSwapFilenameOut); + } + } + delete bulletFile2; + + return result; +} + +bool btBulletWorldImporter::loadFileFromMemory(char* memoryBuffer, int len) +{ + bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(memoryBuffer, len); + + bool result = loadFileFromMemory(bulletFile2); + + delete bulletFile2; + + return result; +} + +bool btBulletWorldImporter::loadFileFromMemory(bParse::btBulletFile* bulletFile2) +{ + bool ok = (bulletFile2->getFlags() & bParse::FD_OK) != 0; + + if (ok) + bulletFile2->parse(m_verboseMode); + else + return false; + + if (m_verboseMode & bParse::FD_VERBOSE_DUMP_CHUNKS) + { + bulletFile2->dumpChunks(bulletFile2->getFileDNA()); + } + + return convertAllObjects(bulletFile2); +} + +bool btBulletWorldImporter::convertAllObjects(bParse::btBulletFile* bulletFile2) +{ + m_shapeMap.clear(); + m_bodyMap.clear(); + + int i; + + for (i = 0; i < bulletFile2->m_bvhs.size(); i++) + { + btOptimizedBvh* bvh = createOptimizedBvh(); + + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i]; + bvh->deSerializeDouble(*bvhData); + } + else + { + btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i]; + bvh->deSerializeFloat(*bvhData); + } + m_bvhMap.insert(bulletFile2->m_bvhs[i], bvh); + } + + for (i = 0; i < bulletFile2->m_collisionShapes.size(); i++) + { + btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i]; + btCollisionShape* shape = convertCollisionShape(shapeData); + if (shape) + { + // printf("shapeMap.insert(%x,%x)\n",shapeData,shape); + m_shapeMap.insert(shapeData, shape); + } + + if (shape && shapeData->m_name) + { + char* newname = duplicateName(shapeData->m_name); + m_objectNameMap.insert(shape, newname); + m_nameShapeMap.insert(newname, shape); + } + } + + for (int i = 0; i < bulletFile2->m_dynamicsWorldInfo.size(); i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btDynamicsWorldDoubleData* solverInfoData = (btDynamicsWorldDoubleData*)bulletFile2->m_dynamicsWorldInfo[i]; + btContactSolverInfo solverInfo; + + btVector3 gravity; + gravity.deSerializeDouble(solverInfoData->m_gravity); + + solverInfo.m_tau = btScalar(solverInfoData->m_solverInfo.m_tau); + solverInfo.m_damping = btScalar(solverInfoData->m_solverInfo.m_damping); + solverInfo.m_friction = btScalar(solverInfoData->m_solverInfo.m_friction); + solverInfo.m_timeStep = btScalar(solverInfoData->m_solverInfo.m_timeStep); + + solverInfo.m_restitution = btScalar(solverInfoData->m_solverInfo.m_restitution); + solverInfo.m_maxErrorReduction = btScalar(solverInfoData->m_solverInfo.m_maxErrorReduction); + solverInfo.m_sor = btScalar(solverInfoData->m_solverInfo.m_sor); + solverInfo.m_erp = btScalar(solverInfoData->m_solverInfo.m_erp); + + solverInfo.m_erp2 = btScalar(solverInfoData->m_solverInfo.m_erp2); + solverInfo.m_globalCfm = btScalar(solverInfoData->m_solverInfo.m_globalCfm); + solverInfo.m_splitImpulsePenetrationThreshold = btScalar(solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold); + solverInfo.m_splitImpulseTurnErp = btScalar(solverInfoData->m_solverInfo.m_splitImpulseTurnErp); + + solverInfo.m_linearSlop = btScalar(solverInfoData->m_solverInfo.m_linearSlop); + solverInfo.m_warmstartingFactor = btScalar(solverInfoData->m_solverInfo.m_warmstartingFactor); + solverInfo.m_maxGyroscopicForce = btScalar(solverInfoData->m_solverInfo.m_maxGyroscopicForce); + solverInfo.m_singleAxisRollingFrictionThreshold = btScalar(solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold); + + solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations; + solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode; + solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold; + solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize; + + solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse; + + setDynamicsWorldInfo(gravity, solverInfo); + } + else + { + btDynamicsWorldFloatData* solverInfoData = (btDynamicsWorldFloatData*)bulletFile2->m_dynamicsWorldInfo[i]; + btContactSolverInfo solverInfo; + + btVector3 gravity; + gravity.deSerializeFloat(solverInfoData->m_gravity); + + solverInfo.m_tau = solverInfoData->m_solverInfo.m_tau; + solverInfo.m_damping = solverInfoData->m_solverInfo.m_damping; + solverInfo.m_friction = solverInfoData->m_solverInfo.m_friction; + solverInfo.m_timeStep = solverInfoData->m_solverInfo.m_timeStep; + + solverInfo.m_restitution = solverInfoData->m_solverInfo.m_restitution; + solverInfo.m_maxErrorReduction = solverInfoData->m_solverInfo.m_maxErrorReduction; + solverInfo.m_sor = solverInfoData->m_solverInfo.m_sor; + solverInfo.m_erp = solverInfoData->m_solverInfo.m_erp; + + solverInfo.m_erp2 = solverInfoData->m_solverInfo.m_erp2; + solverInfo.m_globalCfm = solverInfoData->m_solverInfo.m_globalCfm; + solverInfo.m_splitImpulsePenetrationThreshold = solverInfoData->m_solverInfo.m_splitImpulsePenetrationThreshold; + solverInfo.m_splitImpulseTurnErp = solverInfoData->m_solverInfo.m_splitImpulseTurnErp; + + solverInfo.m_linearSlop = solverInfoData->m_solverInfo.m_linearSlop; + solverInfo.m_warmstartingFactor = solverInfoData->m_solverInfo.m_warmstartingFactor; + solverInfo.m_maxGyroscopicForce = solverInfoData->m_solverInfo.m_maxGyroscopicForce; + solverInfo.m_singleAxisRollingFrictionThreshold = solverInfoData->m_solverInfo.m_singleAxisRollingFrictionThreshold; + + solverInfo.m_numIterations = solverInfoData->m_solverInfo.m_numIterations; + solverInfo.m_solverMode = solverInfoData->m_solverInfo.m_solverMode; + solverInfo.m_restingContactRestitutionThreshold = solverInfoData->m_solverInfo.m_restingContactRestitutionThreshold; + solverInfo.m_minimumSolverBatchSize = solverInfoData->m_solverInfo.m_minimumSolverBatchSize; + + solverInfo.m_splitImpulse = solverInfoData->m_solverInfo.m_splitImpulse; + + setDynamicsWorldInfo(gravity, solverInfo); + } + } + + for (i = 0; i < bulletFile2->m_rigidBodies.size(); i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i]; + convertRigidBodyDouble(colObjData); + } + else + { + btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i]; + convertRigidBodyFloat(colObjData); + } + } + + for (i = 0; i < bulletFile2->m_collisionObjects.size(); i++) + { + if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) + { + btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i]; + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f; + startTransform.deSerializeDouble(colObjData->m_worldTransform); + + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name); + body->setFriction(btScalar(colObjData->m_friction)); + body->setRestitution(btScalar(colObjData->m_restitution)); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData, body); + } + else + { + printf("error: no shape found\n"); + } + } + else + { + btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i]; + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f; + startTransform.deSerializeFloat(colObjData->m_worldTransform); + + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData, body); + } + else + { + printf("error: no shape found\n"); + } + } + } + + for (i = 0; i < bulletFile2->m_constraints.size(); i++) + { + btTypedConstraintData2* constraintData = (btTypedConstraintData2*)bulletFile2->m_constraints[i]; + + btCollisionObject** colAptr = m_bodyMap.find(constraintData->m_rbA); + btCollisionObject** colBptr = m_bodyMap.find(constraintData->m_rbB); + + btRigidBody* rbA = 0; + btRigidBody* rbB = 0; + + if (colAptr) + { + rbA = btRigidBody::upcast(*colAptr); + if (!rbA) + rbA = &getFixedBody(); + } + if (colBptr) + { + rbB = btRigidBody::upcast(*colBptr); + if (!rbB) + rbB = &getFixedBody(); + } + if (!rbA && !rbB) + continue; + + bool isDoublePrecisionData = (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION) != 0; + + if (isDoublePrecisionData) + { + if (bulletFile2->getVersion() >= 282) + { + btTypedConstraintDoubleData* dc = (btTypedConstraintDoubleData*)constraintData; + convertConstraintDouble(dc, rbA, rbB, bulletFile2->getVersion()); + } + else + { + //double-precision constraints were messed up until 2.82, try to recover data... + + btTypedConstraintData* oldData = (btTypedConstraintData*)constraintData; + + convertConstraintBackwardsCompatible281(oldData, rbA, rbB, bulletFile2->getVersion()); + } + } + else + { + btTypedConstraintFloatData* dc = (btTypedConstraintFloatData*)constraintData; + convertConstraintFloat(dc, rbA, rbB, bulletFile2->getVersion()); + } + } + + return true; +} diff --git a/source/BulletWorldImporter/btBulletWorldImporter.h b/source/BulletWorldImporter/btBulletWorldImporter.h new file mode 100644 index 000000000..dbcf55f03 --- /dev/null +++ b/source/BulletWorldImporter/btBulletWorldImporter.h @@ -0,0 +1,52 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BULLET_WORLD_IMPORTER_H +#define BULLET_WORLD_IMPORTER_H + +#include "btWorldImporter.h" + +class btBulletFile; + +namespace bParse +{ +class btBulletFile; + +}; + +///The btBulletWorldImporter is a starting point to import .bullet files. +///note that not all data is converted yet. You are expected to override or modify this class. +///See Bullet/Demos/SerializeDemo for a derived class that extract btSoftBody objects too. +class btBulletWorldImporter : public btWorldImporter +{ +public: + btBulletWorldImporter(btDynamicsWorld* world = 0); + + virtual ~btBulletWorldImporter(); + + ///if you pass a valid preSwapFilenameOut, it will save a new file with a different endianness + ///this pre-swapped file can be loaded without swapping on a target platform of different endianness + bool loadFile(const char* fileName, const char* preSwapFilenameOut = 0); + + ///the memoryBuffer might be modified (for example if endian swaps are necessary) + bool loadFileFromMemory(char* memoryBuffer, int len); + + bool loadFileFromMemory(bParse::btBulletFile* file); + + //call make sure bulletFile2 has been parsed, either using btBulletFile::parse or btBulletWorldImporter::loadFileFromMemory + virtual bool convertAllObjects(bParse::btBulletFile* file); +}; + +#endif //BULLET_WORLD_IMPORTER_H \ No newline at end of file diff --git a/source/BulletWorldImporter/btWorldImporter.cpp b/source/BulletWorldImporter/btWorldImporter.cpp new file mode 100644 index 000000000..eb7a0c502 --- /dev/null +++ b/source/BulletWorldImporter/btWorldImporter.cpp @@ -0,0 +1,2084 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btWorldImporter.h" +#include "btBulletDynamicsCommon.h" +#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" +#ifdef USE_GIMPACT +#include "BulletCollision/Gimpact/btGImpactShape.h" +#endif +btWorldImporter::btWorldImporter(btDynamicsWorld* world) + : m_dynamicsWorld(world), + m_verboseMode(0), + m_importerFlags(0) +{ +} + +btWorldImporter::~btWorldImporter() +{ +} + +void btWorldImporter::deleteAllData() +{ + int i; + for (i = 0; i < m_allocatedConstraints.size(); i++) + { + if (m_dynamicsWorld) + m_dynamicsWorld->removeConstraint(m_allocatedConstraints[i]); + delete m_allocatedConstraints[i]; + } + m_allocatedConstraints.clear(); + + for (i = 0; i < m_allocatedRigidBodies.size(); i++) + { + if (m_dynamicsWorld) + m_dynamicsWorld->removeRigidBody(btRigidBody::upcast(m_allocatedRigidBodies[i])); + delete m_allocatedRigidBodies[i]; + } + + m_allocatedRigidBodies.clear(); + + for (i = 0; i < m_allocatedCollisionShapes.size(); i++) + { + delete m_allocatedCollisionShapes[i]; + } + m_allocatedCollisionShapes.clear(); + + for (i = 0; i < m_allocatedBvhs.size(); i++) + { + delete m_allocatedBvhs[i]; + } + m_allocatedBvhs.clear(); + + for (i = 0; i < m_allocatedTriangleInfoMaps.size(); i++) + { + delete m_allocatedTriangleInfoMaps[i]; + } + m_allocatedTriangleInfoMaps.clear(); + for (i = 0; i < m_allocatedTriangleIndexArrays.size(); i++) + { + delete m_allocatedTriangleIndexArrays[i]; + } + m_allocatedTriangleIndexArrays.clear(); + for (i = 0; i < m_allocatedNames.size(); i++) + { + delete[] m_allocatedNames[i]; + } + m_allocatedNames.clear(); + + for (i = 0; i < m_allocatedbtStridingMeshInterfaceDatas.size(); i++) + { + btStridingMeshInterfaceData* curData = m_allocatedbtStridingMeshInterfaceDatas[i]; + + for (int a = 0; a < curData->m_numMeshParts; a++) + { + btMeshPartData* curPart = &curData->m_meshPartsPtr[a]; + if (curPart->m_vertices3f) + delete[] curPart->m_vertices3f; + + if (curPart->m_vertices3d) + delete[] curPart->m_vertices3d; + + if (curPart->m_indices32) + delete[] curPart->m_indices32; + + if (curPart->m_3indices16) + delete[] curPart->m_3indices16; + + if (curPart->m_indices16) + delete[] curPart->m_indices16; + + if (curPart->m_3indices8) + delete[] curPart->m_3indices8; + } + delete[] curData->m_meshPartsPtr; + delete curData; + } + m_allocatedbtStridingMeshInterfaceDatas.clear(); + + for (i = 0; i < m_indexArrays.size(); i++) + { + btAlignedFree(m_indexArrays[i]); + } + m_indexArrays.clear(); + + for (i = 0; i < m_shortIndexArrays.size(); i++) + { + btAlignedFree(m_shortIndexArrays[i]); + } + m_shortIndexArrays.clear(); + + for (i = 0; i < m_charIndexArrays.size(); i++) + { + btAlignedFree(m_charIndexArrays[i]); + } + m_charIndexArrays.clear(); + + for (i = 0; i < m_floatVertexArrays.size(); i++) + { + btAlignedFree(m_floatVertexArrays[i]); + } + m_floatVertexArrays.clear(); + + for (i = 0; i < m_doubleVertexArrays.size(); i++) + { + btAlignedFree(m_doubleVertexArrays[i]); + } + m_doubleVertexArrays.clear(); +} + +btCollisionShape* btWorldImporter::convertCollisionShape(btCollisionShapeData* shapeData) +{ + btCollisionShape* shape = 0; + + switch (shapeData->m_shapeType) + { + case STATIC_PLANE_PROXYTYPE: + { + btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData; + btVector3 planeNormal, localScaling; + planeNormal.deSerializeFloat(planeData->m_planeNormal); + localScaling.deSerializeFloat(planeData->m_localScaling); + shape = createPlaneShape(planeNormal, planeData->m_planeConstant); + shape->setLocalScaling(localScaling); + + break; + } + case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*)shapeData; + btCollisionShapeData* colShapeData = (btCollisionShapeData*)&scaledMesh->m_trimeshShapeData; + colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE; + btCollisionShape* childShape = convertCollisionShape(colShapeData); + btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape; + btVector3 localScaling; + localScaling.deSerializeFloat(scaledMesh->m_localScaling); + + shape = createScaledTrangleMeshShape(meshShape, localScaling); + break; + } + case GIMPACT_SHAPE_PROXYTYPE: + { +#ifdef USE_GIMPACT + btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*)shapeData; + if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE) + { + btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface); + btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData); + + btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface); + btVector3 localScaling; + localScaling.deSerializeFloat(gimpactData->m_localScaling); + gimpactShape->setLocalScaling(localScaling); + gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin)); + gimpactShape->updateBound(); + shape = gimpactShape; + } + else + { + printf("unsupported gimpact sub type\n"); + } +#endif //USE_GIMPACT + break; + } + //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API + //so deal with this + case CAPSULE_SHAPE_PROXYTYPE: + { + btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData; + + switch (capData->m_upAxis) + { + case 0: + { + shape = createCapsuleShapeX(1, 1); + break; + } + case 1: + { + shape = createCapsuleShapeY(1, 1); + break; + } + case 2: + { + shape = createCapsuleShapeZ(1, 1); + break; + } + default: + { + printf("error: wrong up axis for btCapsuleShape\n"); + } + }; + if (shape) + { + btCapsuleShape* cap = (btCapsuleShape*)shape; + cap->deSerializeFloat(capData); + } + break; + } + case CYLINDER_SHAPE_PROXYTYPE: + case CONE_SHAPE_PROXYTYPE: + case BOX_SHAPE_PROXYTYPE: + case SPHERE_SHAPE_PROXYTYPE: + case MULTI_SPHERE_SHAPE_PROXYTYPE: + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData; + btVector3 implicitShapeDimensions; + implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions); + btVector3 localScaling; + localScaling.deSerializeFloat(bsd->m_localScaling); + btVector3 margin(bsd->m_collisionMargin, bsd->m_collisionMargin, bsd->m_collisionMargin); + switch (shapeData->m_shapeType) + { + case BOX_SHAPE_PROXYTYPE: + { + btBoxShape* box = (btBoxShape*)createBoxShape(implicitShapeDimensions / localScaling + margin); + //box->initializePolyhedralFeatures(); + shape = box; + + break; + } + case SPHERE_SHAPE_PROXYTYPE: + { + shape = createSphereShape(implicitShapeDimensions.getX()); + break; + } + + case CYLINDER_SHAPE_PROXYTYPE: + { + btCylinderShapeData* cylData = (btCylinderShapeData*)shapeData; + btVector3 halfExtents = implicitShapeDimensions + margin; + switch (cylData->m_upAxis) + { + case 0: + { + shape = createCylinderShapeX(halfExtents.getY(), halfExtents.getX()); + break; + } + case 1: + { + shape = createCylinderShapeY(halfExtents.getX(), halfExtents.getY()); + break; + } + case 2: + { + shape = createCylinderShapeZ(halfExtents.getX(), halfExtents.getZ()); + break; + } + default: + { + printf("unknown Cylinder up axis\n"); + } + }; + + break; + } + case CONE_SHAPE_PROXYTYPE: + { + btConeShapeData* conData = (btConeShapeData*)shapeData; + btVector3 halfExtents = implicitShapeDimensions; //+margin; + switch (conData->m_upIndex) + { + case 0: + { + shape = createConeShapeX(halfExtents.getY(), halfExtents.getX()); + break; + } + case 1: + { + shape = createConeShapeY(halfExtents.getX(), halfExtents.getY()); + break; + } + case 2: + { + shape = createConeShapeZ(halfExtents.getX(), halfExtents.getZ()); + break; + } + default: + { + printf("unknown Cone up axis\n"); + } + }; + + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd; + int numSpheres = mss->m_localPositionArraySize; + + btAlignedObjectArray tmpPos; + btAlignedObjectArray radii; + radii.resize(numSpheres); + tmpPos.resize(numSpheres); + int i; + for (i = 0; i < numSpheres; i++) + { + tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos); + radii[i] = mss->m_localPositionArrayPtr[i].m_radius; + } + shape = createMultiSphereShape(&tmpPos[0], &radii[0], numSpheres); + break; + } + case CONVEX_HULL_SHAPE_PROXYTYPE: + { + // int sz = sizeof(btConvexHullShapeData); + // int sz2 = sizeof(btConvexInternalShapeData); + // int sz3 = sizeof(btCollisionShapeData); + btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd; + int numPoints = convexData->m_numUnscaledPoints; + + btAlignedObjectArray tmpPoints; + tmpPoints.resize(numPoints); + int i; + for (i = 0; i < numPoints; i++) + { +#ifdef BT_USE_DOUBLE_PRECISION + if (convexData->m_unscaledPointsDoublePtr) + tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]); + if (convexData->m_unscaledPointsFloatPtr) + tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]); +#else + if (convexData->m_unscaledPointsFloatPtr) + tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]); + if (convexData->m_unscaledPointsDoublePtr) + tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]); +#endif //BT_USE_DOUBLE_PRECISION + } + btConvexHullShape* hullShape = createConvexHullShape(); + for (i = 0; i < numPoints; i++) + { + hullShape->addPoint(tmpPoints[i]); + } + hullShape->setMargin(bsd->m_collisionMargin); + //hullShape->initializePolyhedralFeatures(); + shape = hullShape; + break; + } + default: + { + printf("error: cannot create shape type (%d)\n", shapeData->m_shapeType); + } + } + + if (shape) + { + shape->setMargin(bsd->m_collisionMargin); + + btVector3 localScaling; + localScaling.deSerializeFloat(bsd->m_localScaling); + shape->setLocalScaling(localScaling); + } + break; + } + case TRIANGLE_MESH_SHAPE_PROXYTYPE: + { + btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData; + btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&trimesh->m_meshInterface); + btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData); + if (!meshInterface->getNumSubParts()) + { + return 0; + } + + btVector3 scaling; + scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling); + meshInterface->setScaling(scaling); + + btOptimizedBvh* bvh = 0; +#if 1 + if (trimesh->m_quantizedFloatBvh) + { + btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh); + if (bvhPtr && *bvhPtr) + { + bvh = *bvhPtr; + } + else + { + bvh = createOptimizedBvh(); + bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh); + } + } + if (trimesh->m_quantizedDoubleBvh) + { + btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh); + if (bvhPtr && *bvhPtr) + { + bvh = *bvhPtr; + } + else + { + bvh = createOptimizedBvh(); + bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh); + } + } +#endif + + btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface, bvh); + trimeshShape->setMargin(trimesh->m_collisionMargin); + shape = trimeshShape; + + if (trimesh->m_triangleInfoMap) + { + btTriangleInfoMap* map = createTriangleInfoMap(); + map->deSerialize(*trimesh->m_triangleInfoMap); + trimeshShape->setTriangleInfoMap(map); + +#ifdef USE_INTERNAL_EDGE_UTILITY + gContactAddedCallback = btAdjustInternalEdgeContactsCallback; +#endif //USE_INTERNAL_EDGE_UTILITY + } + + //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin); + break; + } + case COMPOUND_SHAPE_PROXYTYPE: + { + btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData; + btCompoundShape* compoundShape = createCompoundShape(); + + btAlignedObjectArray childShapes; + for (int i = 0; i < compoundData->m_numChildShapes; i++) + { + btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape; + + btCollisionShape* childShape = convertCollisionShape(cd); + if (childShape) + { + btTransform localTransform; + localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform); + compoundShape->addChildShape(localTransform, childShape); + } + else + { +#ifdef _DEBUG + printf("error: couldn't create childShape for compoundShape\n"); +#endif + } + } + shape = compoundShape; + + break; + } + case SOFTBODY_SHAPE_PROXYTYPE: + { + return 0; + } + default: + { +#ifdef _DEBUG + printf("unsupported shape type (%d)\n", shapeData->m_shapeType); +#endif + } + } + + return shape; +} + +char* btWorldImporter::duplicateName(const char* name) +{ + if (name) + { + int l = (int)strlen(name); + char* newName = new char[l + 1]; + memcpy(newName, name, l); + newName[l] = 0; + m_allocatedNames.push_back(newName); + return newName; + } + return 0; +} + +void btWorldImporter::convertConstraintBackwardsCompatible281(btTypedConstraintData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion) +{ + btTypedConstraint* constraint = 0; + + switch (constraintData->m_objectType) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraintDoubleData* p2pData = (btPoint2PointConstraintDoubleData*)constraintData; + if (rbA && rbB) + { + btVector3 pivotInA, pivotInB; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + pivotInB.deSerializeDouble(p2pData->m_pivotInB); + constraint = createPoint2PointConstraint(*rbA, *rbB, pivotInA, pivotInB); + } + else + { + btVector3 pivotInA; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + constraint = createPoint2PointConstraint(*rbA, pivotInA); + } + break; + } + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* hinge = 0; + + btHingeConstraintDoubleData* hingeData = (btHingeConstraintDoubleData*)constraintData; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + rbBFrame.deSerializeDouble(hingeData->m_rbBFrame); + hinge = createHingeConstraint(*rbA, *rbB, rbAFrame, rbBFrame, hingeData->m_useReferenceFrameA != 0); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + hinge = createHingeConstraint(*rbA, rbAFrame, hingeData->m_useReferenceFrameA != 0); + } + if (hingeData->m_enableAngularMotor) + { + hinge->enableAngularMotor(true, (btScalar)hingeData->m_motorTargetVelocity, (btScalar)hingeData->m_maxMotorImpulse); + } + hinge->setAngularOnly(hingeData->m_angularOnly != 0); + hinge->setLimit(btScalar(hingeData->m_lowerLimit), btScalar(hingeData->m_upperLimit), btScalar(hingeData->m_limitSoftness), btScalar(hingeData->m_biasFactor), btScalar(hingeData->m_relaxationFactor)); + + constraint = hinge; + break; + } + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData; + btConeTwistConstraint* coneTwist = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + rbBFrame.deSerializeFloat(coneData->m_rbBFrame); + coneTwist = createConeTwistConstraint(*rbA, *rbB, rbAFrame, rbBFrame); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + coneTwist = createConeTwistConstraint(*rbA, rbAFrame); + } + coneTwist->setLimit((btScalar)coneData->m_swingSpan1, (btScalar)coneData->m_swingSpan2, (btScalar)coneData->m_twistSpan, (btScalar)coneData->m_limitSoftness, + (btScalar)coneData->m_biasFactor, (btScalar)coneData->m_relaxationFactor); + coneTwist->setDamping((btScalar)coneData->m_damping); + + constraint = coneTwist; + break; + } + + case D6_SPRING_CONSTRAINT_TYPE: + { + btGeneric6DofSpringConstraintData* dofData = (btGeneric6DofSpringConstraintData*)constraintData; + // int sz = sizeof(btGeneric6DofSpringConstraintData); + btGeneric6DofSpringConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_6dofData.m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_6dofData.m_rbBFrame); + dof = createGeneric6DofSpringConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_6dofData.m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpringConstraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_6dofData.m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_6dofData.m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_6dofData.m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_6dofData.m_linearUpperLimit); + + angLowerLimit.setW(0.f); + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + if (fileVersion > 280) + { + for (i = 0; i < 6; i++) + { + dof->setStiffness(i, (btScalar)dofData->m_springStiffness[i]); + dof->setEquilibriumPoint(i, (btScalar)dofData->m_equilibriumPoint[i]); + dof->enableSpring(i, dofData->m_springEnabled[i] != 0); + dof->setDamping(i, (btScalar)dofData->m_springDamping[i]); + } + } + } + + constraint = dof; + break; + } + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData; + btGeneric6DofConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + if (rbB) + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbB, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n"); + } + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit); + + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + } + + constraint = dof; + break; + } + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData; + btSliderConstraint* slider = 0; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(sliderData->m_rbAFrame); + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbA, *rbB, rbAFrame, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + else + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbB, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + slider->setLowerLinLimit((btScalar)sliderData->m_linearLowerLimit); + slider->setUpperLinLimit((btScalar)sliderData->m_linearUpperLimit); + slider->setLowerAngLimit((btScalar)sliderData->m_angularLowerLimit); + slider->setUpperAngLimit((btScalar)sliderData->m_angularUpperLimit); + slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame != 0); + constraint = slider; + break; + } + + default: + { + printf("unknown constraint type\n"); + } + }; + + if (constraint) + { + constraint->setDbgDrawSize((btScalar)constraintData->m_dbgDrawSize); + ///those fields didn't exist and set to zero for pre-280 versions, so do a check here + if (fileVersion >= 280) + { + constraint->setBreakingImpulseThreshold((btScalar)constraintData->m_breakingImpulseThreshold); + constraint->setEnabled(constraintData->m_isEnabled != 0); + constraint->setOverrideNumSolverIterations(constraintData->m_overrideNumSolverIterations); + } + + if (constraintData->m_name) + { + char* newname = duplicateName(constraintData->m_name); + m_nameConstraintMap.insert(newname, constraint); + m_objectNameMap.insert(constraint, newname); + } + if (m_dynamicsWorld) + m_dynamicsWorld->addConstraint(constraint, constraintData->m_disableCollisionsBetweenLinkedBodies != 0); + } +} + +void btWorldImporter::convertConstraintFloat(btTypedConstraintFloatData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion) +{ + btTypedConstraint* constraint = 0; + + switch (constraintData->m_objectType) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraintFloatData* p2pData = (btPoint2PointConstraintFloatData*)constraintData; + if (rbA && rbB) + { + btVector3 pivotInA, pivotInB; + pivotInA.deSerializeFloat(p2pData->m_pivotInA); + pivotInB.deSerializeFloat(p2pData->m_pivotInB); + constraint = createPoint2PointConstraint(*rbA, *rbB, pivotInA, pivotInB); + } + else + { + btVector3 pivotInA; + pivotInA.deSerializeFloat(p2pData->m_pivotInA); + constraint = createPoint2PointConstraint(*rbA, pivotInA); + } + break; + } + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* hinge = 0; + btHingeConstraintFloatData* hingeData = (btHingeConstraintFloatData*)constraintData; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(hingeData->m_rbAFrame); + rbBFrame.deSerializeFloat(hingeData->m_rbBFrame); + hinge = createHingeConstraint(*rbA, *rbB, rbAFrame, rbBFrame, hingeData->m_useReferenceFrameA != 0); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeFloat(hingeData->m_rbAFrame); + hinge = createHingeConstraint(*rbA, rbAFrame, hingeData->m_useReferenceFrameA != 0); + } + if (hingeData->m_enableAngularMotor) + { + hinge->enableAngularMotor(true, hingeData->m_motorTargetVelocity, hingeData->m_maxMotorImpulse); + } + hinge->setAngularOnly(hingeData->m_angularOnly != 0); + hinge->setLimit(btScalar(hingeData->m_lowerLimit), btScalar(hingeData->m_upperLimit), btScalar(hingeData->m_limitSoftness), btScalar(hingeData->m_biasFactor), btScalar(hingeData->m_relaxationFactor)); + + constraint = hinge; + break; + } + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData; + btConeTwistConstraint* coneTwist = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + rbBFrame.deSerializeFloat(coneData->m_rbBFrame); + coneTwist = createConeTwistConstraint(*rbA, *rbB, rbAFrame, rbBFrame); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeFloat(coneData->m_rbAFrame); + coneTwist = createConeTwistConstraint(*rbA, rbAFrame); + } + coneTwist->setLimit(coneData->m_swingSpan1, coneData->m_swingSpan2, coneData->m_twistSpan, coneData->m_limitSoftness, coneData->m_biasFactor, coneData->m_relaxationFactor); + coneTwist->setDamping(coneData->m_damping); + + constraint = coneTwist; + break; + } + + case D6_SPRING_CONSTRAINT_TYPE: + { + btGeneric6DofSpringConstraintData* dofData = (btGeneric6DofSpringConstraintData*)constraintData; + // int sz = sizeof(btGeneric6DofSpringConstraintData); + btGeneric6DofSpringConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_6dofData.m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_6dofData.m_rbBFrame); + dof = createGeneric6DofSpringConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_6dofData.m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpringConstraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_6dofData.m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_6dofData.m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_6dofData.m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_6dofData.m_linearUpperLimit); + + angLowerLimit.setW(0.f); + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + if (fileVersion > 280) + { + for (i = 0; i < 6; i++) + { + dof->setStiffness(i, dofData->m_springStiffness[i]); + dof->setEquilibriumPoint(i, dofData->m_equilibriumPoint[i]); + dof->enableSpring(i, dofData->m_springEnabled[i] != 0); + dof->setDamping(i, dofData->m_springDamping[i]); + } + } + } + + constraint = dof; + break; + } + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData; + btGeneric6DofConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + if (rbB) + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbB, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n"); + } + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit); + + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + } + + constraint = dof; + break; + } + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData; + btSliderConstraint* slider = 0; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(sliderData->m_rbAFrame); + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbA, *rbB, rbAFrame, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + else + { + btTransform rbBFrame; + rbBFrame.deSerializeFloat(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbB, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + slider->setLowerLinLimit(sliderData->m_linearLowerLimit); + slider->setUpperLinLimit(sliderData->m_linearUpperLimit); + slider->setLowerAngLimit(sliderData->m_angularLowerLimit); + slider->setUpperAngLimit(sliderData->m_angularUpperLimit); + slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame != 0); + constraint = slider; + break; + } + case GEAR_CONSTRAINT_TYPE: + { + btGearConstraintFloatData* gearData = (btGearConstraintFloatData*)constraintData; + btGearConstraint* gear = 0; + if (rbA && rbB) + { + btVector3 axisInA, axisInB; + axisInA.deSerializeFloat(gearData->m_axisInA); + axisInB.deSerializeFloat(gearData->m_axisInB); + gear = createGearConstraint(*rbA, *rbB, axisInA, axisInB, gearData->m_ratio); + } + else + { + btAssert(0); + //perhaps a gear against a 'fixed' body, while the 'fixed' body is not serialized? + //btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f); + } + constraint = gear; + break; + } + case D6_SPRING_2_CONSTRAINT_TYPE: + { + btGeneric6DofSpring2ConstraintData* dofData = (btGeneric6DofSpring2ConstraintData*)constraintData; + + btGeneric6DofSpring2Constraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeFloat(dofData->m_rbAFrame); + rbBFrame.deSerializeFloat(dofData->m_rbBFrame); + dof = createGeneric6DofSpring2Constraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_rotateOrder); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpring2Constraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit); + + angLowerLimit.setW(0.f); + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + if (fileVersion > 280) + { + //6-dof: 3 linear followed by 3 angular + for (i = 0; i < 3; i++) + { + dof->setStiffness(i, dofData->m_linearSpringStiffness.m_floats[i], dofData->m_linearSpringStiffnessLimited[i] != 0); + dof->setEquilibriumPoint(i, dofData->m_linearEquilibriumPoint.m_floats[i]); + dof->enableSpring(i, dofData->m_linearEnableSpring[i] != 0); + dof->setDamping(i, dofData->m_linearSpringDamping.m_floats[i], (dofData->m_linearSpringDampingLimited[i] != 0)); + } + for (i = 0; i < 3; i++) + { + dof->setStiffness(i + 3, dofData->m_angularSpringStiffness.m_floats[i], (dofData->m_angularSpringStiffnessLimited[i] != 0)); + dof->setEquilibriumPoint(i + 3, dofData->m_angularEquilibriumPoint.m_floats[i]); + dof->enableSpring(i + 3, dofData->m_angularEnableSpring[i] != 0); + dof->setDamping(i + 3, dofData->m_angularSpringDamping.m_floats[i], dofData->m_angularSpringDampingLimited[i]); + } + } + } + + constraint = dof; + break; + } + case FIXED_CONSTRAINT_TYPE: + { + btGeneric6DofSpring2Constraint* dof = 0; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + //compute a shared world frame, and compute frameInA, frameInB relative to this + btTransform sharedFrame; + sharedFrame.setIdentity(); + btVector3 centerPos = btScalar(0.5) * (rbA->getWorldTransform().getOrigin() + + rbB->getWorldTransform().getOrigin()); + sharedFrame.setOrigin(centerPos); + rbAFrame = rbA->getWorldTransform().inverse() * sharedFrame; + rbBFrame = rbB->getWorldTransform().inverse() * sharedFrame; + + dof = createGeneric6DofSpring2Constraint(*rbA, *rbB, rbAFrame, rbBFrame, RO_XYZ); + dof->setLinearUpperLimit(btVector3(0, 0, 0)); + dof->setLinearLowerLimit(btVector3(0, 0, 0)); + dof->setAngularUpperLimit(btVector3(0, 0, 0)); + dof->setAngularLowerLimit(btVector3(0, 0, 0)); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpring2Constraint: requires rbA && rbB\n"); + } + + constraint = dof; + break; + } + default: + { + printf("unknown constraint type\n"); + } + }; + + if (constraint) + { + constraint->setDbgDrawSize(constraintData->m_dbgDrawSize); + ///those fields didn't exist and set to zero for pre-280 versions, so do a check here + if (fileVersion >= 280) + { + constraint->setBreakingImpulseThreshold(constraintData->m_breakingImpulseThreshold); + constraint->setEnabled(constraintData->m_isEnabled != 0); + constraint->setOverrideNumSolverIterations(constraintData->m_overrideNumSolverIterations); + } + + if (constraintData->m_name) + { + char* newname = duplicateName(constraintData->m_name); + m_nameConstraintMap.insert(newname, constraint); + m_objectNameMap.insert(constraint, newname); + } + if (m_dynamicsWorld) + m_dynamicsWorld->addConstraint(constraint, constraintData->m_disableCollisionsBetweenLinkedBodies != 0); + } +} + +void btWorldImporter::convertConstraintDouble(btTypedConstraintDoubleData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion) +{ + btTypedConstraint* constraint = 0; + + switch (constraintData->m_objectType) + { + case POINT2POINT_CONSTRAINT_TYPE: + { + btPoint2PointConstraintDoubleData2* p2pData = (btPoint2PointConstraintDoubleData2*)constraintData; + if (rbA && rbB) + { + btVector3 pivotInA, pivotInB; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + pivotInB.deSerializeDouble(p2pData->m_pivotInB); + constraint = createPoint2PointConstraint(*rbA, *rbB, pivotInA, pivotInB); + } + else + { + btVector3 pivotInA; + pivotInA.deSerializeDouble(p2pData->m_pivotInA); + constraint = createPoint2PointConstraint(*rbA, pivotInA); + } + break; + } + case HINGE_CONSTRAINT_TYPE: + { + btHingeConstraint* hinge = 0; + + btHingeConstraintDoubleData2* hingeData = (btHingeConstraintDoubleData2*)constraintData; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + rbBFrame.deSerializeDouble(hingeData->m_rbBFrame); + hinge = createHingeConstraint(*rbA, *rbB, rbAFrame, rbBFrame, hingeData->m_useReferenceFrameA != 0); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeDouble(hingeData->m_rbAFrame); + hinge = createHingeConstraint(*rbA, rbAFrame, hingeData->m_useReferenceFrameA != 0); + } + if (hingeData->m_enableAngularMotor) + { + hinge->enableAngularMotor(true, (btScalar)hingeData->m_motorTargetVelocity, (btScalar)hingeData->m_maxMotorImpulse); + } + hinge->setAngularOnly(hingeData->m_angularOnly != 0); + hinge->setLimit(btScalar(hingeData->m_lowerLimit), btScalar(hingeData->m_upperLimit), btScalar(hingeData->m_limitSoftness), btScalar(hingeData->m_biasFactor), btScalar(hingeData->m_relaxationFactor)); + + constraint = hinge; + break; + } + case CONETWIST_CONSTRAINT_TYPE: + { + btConeTwistConstraintDoubleData* coneData = (btConeTwistConstraintDoubleData*)constraintData; + btConeTwistConstraint* coneTwist = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(coneData->m_rbAFrame); + rbBFrame.deSerializeDouble(coneData->m_rbBFrame); + coneTwist = createConeTwistConstraint(*rbA, *rbB, rbAFrame, rbBFrame); + } + else + { + btTransform rbAFrame; + rbAFrame.deSerializeDouble(coneData->m_rbAFrame); + coneTwist = createConeTwistConstraint(*rbA, rbAFrame); + } + coneTwist->setLimit((btScalar)coneData->m_swingSpan1, (btScalar)coneData->m_swingSpan2, (btScalar)coneData->m_twistSpan, (btScalar)coneData->m_limitSoftness, + (btScalar)coneData->m_biasFactor, (btScalar)coneData->m_relaxationFactor); + coneTwist->setDamping((btScalar)coneData->m_damping); + + constraint = coneTwist; + break; + } + + case D6_SPRING_CONSTRAINT_TYPE: + { + btGeneric6DofSpringConstraintDoubleData2* dofData = (btGeneric6DofSpringConstraintDoubleData2*)constraintData; + // int sz = sizeof(btGeneric6DofSpringConstraintData); + btGeneric6DofSpringConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(dofData->m_6dofData.m_rbAFrame); + rbBFrame.deSerializeDouble(dofData->m_6dofData.m_rbBFrame); + dof = createGeneric6DofSpringConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_6dofData.m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpringConstraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeDouble(dofData->m_6dofData.m_angularLowerLimit); + angUpperLimit.deSerializeDouble(dofData->m_6dofData.m_angularUpperLimit); + linLowerLimit.deSerializeDouble(dofData->m_6dofData.m_linearLowerLimit); + linUpperlimit.deSerializeDouble(dofData->m_6dofData.m_linearUpperLimit); + + angLowerLimit.setW(0.f); + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + if (fileVersion > 280) + { + for (i = 0; i < 6; i++) + { + dof->setStiffness(i, (btScalar)dofData->m_springStiffness[i]); + dof->setEquilibriumPoint(i, (btScalar)dofData->m_equilibriumPoint[i]); + dof->enableSpring(i, dofData->m_springEnabled[i] != 0); + dof->setDamping(i, (btScalar)dofData->m_springDamping[i]); + } + } + } + + constraint = dof; + break; + } + case D6_CONSTRAINT_TYPE: + { + btGeneric6DofConstraintDoubleData2* dofData = (btGeneric6DofConstraintDoubleData2*)constraintData; + btGeneric6DofConstraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(dofData->m_rbAFrame); + rbBFrame.deSerializeDouble(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + if (rbB) + { + btTransform rbBFrame; + rbBFrame.deSerializeDouble(dofData->m_rbBFrame); + dof = createGeneric6DofConstraint(*rbB, rbBFrame, dofData->m_useLinearReferenceFrameA != 0); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n"); + } + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeDouble(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeDouble(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeDouble(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeDouble(dofData->m_linearUpperLimit); + + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + } + + constraint = dof; + break; + } + case SLIDER_CONSTRAINT_TYPE: + { + btSliderConstraintDoubleData* sliderData = (btSliderConstraintDoubleData*)constraintData; + btSliderConstraint* slider = 0; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(sliderData->m_rbAFrame); + rbBFrame.deSerializeDouble(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbA, *rbB, rbAFrame, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + else + { + btTransform rbBFrame; + rbBFrame.deSerializeDouble(sliderData->m_rbBFrame); + slider = createSliderConstraint(*rbB, rbBFrame, sliderData->m_useLinearReferenceFrameA != 0); + } + slider->setLowerLinLimit((btScalar)sliderData->m_linearLowerLimit); + slider->setUpperLinLimit((btScalar)sliderData->m_linearUpperLimit); + slider->setLowerAngLimit((btScalar)sliderData->m_angularLowerLimit); + slider->setUpperAngLimit((btScalar)sliderData->m_angularUpperLimit); + slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame != 0); + constraint = slider; + break; + } + case GEAR_CONSTRAINT_TYPE: + { + btGearConstraintDoubleData* gearData = (btGearConstraintDoubleData*)constraintData; + btGearConstraint* gear = 0; + if (rbA && rbB) + { + btVector3 axisInA, axisInB; + axisInA.deSerializeDouble(gearData->m_axisInA); + axisInB.deSerializeDouble(gearData->m_axisInB); + gear = createGearConstraint(*rbA, *rbB, axisInA, axisInB, gearData->m_ratio); + } + else + { + btAssert(0); + //perhaps a gear against a 'fixed' body, while the 'fixed' body is not serialized? + //btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA,const btVector3& axisInB, btScalar ratio=1.f); + } + constraint = gear; + break; + } + + case D6_SPRING_2_CONSTRAINT_TYPE: + { + btGeneric6DofSpring2ConstraintDoubleData2* dofData = (btGeneric6DofSpring2ConstraintDoubleData2*)constraintData; + + btGeneric6DofSpring2Constraint* dof = 0; + + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + rbAFrame.deSerializeDouble(dofData->m_rbAFrame); + rbBFrame.deSerializeDouble(dofData->m_rbBFrame); + dof = createGeneric6DofSpring2Constraint(*rbA, *rbB, rbAFrame, rbBFrame, dofData->m_rotateOrder); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpring2Constraint: requires rbA && rbB\n"); + } + + if (dof) + { + btVector3 angLowerLimit, angUpperLimit, linLowerLimit, linUpperlimit; + angLowerLimit.deSerializeDouble(dofData->m_angularLowerLimit); + angUpperLimit.deSerializeDouble(dofData->m_angularUpperLimit); + linLowerLimit.deSerializeDouble(dofData->m_linearLowerLimit); + linUpperlimit.deSerializeDouble(dofData->m_linearUpperLimit); + + angLowerLimit.setW(0.f); + dof->setAngularLowerLimit(angLowerLimit); + dof->setAngularUpperLimit(angUpperLimit); + dof->setLinearLowerLimit(linLowerLimit); + dof->setLinearUpperLimit(linUpperlimit); + + int i; + if (fileVersion > 280) + { + //6-dof: 3 linear followed by 3 angular + for (i = 0; i < 3; i++) + { + dof->setStiffness(i, dofData->m_linearSpringStiffness.m_floats[i], dofData->m_linearSpringStiffnessLimited[i]); + dof->setEquilibriumPoint(i, dofData->m_linearEquilibriumPoint.m_floats[i]); + dof->enableSpring(i, dofData->m_linearEnableSpring[i] != 0); + dof->setDamping(i, dofData->m_linearSpringDamping.m_floats[i], (dofData->m_linearSpringDampingLimited[i] != 0)); + } + for (i = 0; i < 3; i++) + { + dof->setStiffness(i + 3, dofData->m_angularSpringStiffness.m_floats[i], (dofData->m_angularSpringStiffnessLimited[i] != 0)); + dof->setEquilibriumPoint(i + 3, dofData->m_angularEquilibriumPoint.m_floats[i]); + dof->enableSpring(i + 3, dofData->m_angularEnableSpring[i] != 0); + dof->setDamping(i + 3, dofData->m_angularSpringDamping.m_floats[i], (dofData->m_angularSpringDampingLimited[i] != 0)); + } + } + } + + constraint = dof; + break; + } + case FIXED_CONSTRAINT_TYPE: + { + btGeneric6DofSpring2Constraint* dof = 0; + if (rbA && rbB) + { + btTransform rbAFrame, rbBFrame; + //compute a shared world frame, and compute frameInA, frameInB relative to this + btTransform sharedFrame; + sharedFrame.setIdentity(); + btVector3 centerPos = btScalar(0.5) * (rbA->getWorldTransform().getOrigin() + + rbB->getWorldTransform().getOrigin()); + sharedFrame.setOrigin(centerPos); + rbAFrame = rbA->getWorldTransform().inverse() * sharedFrame; + rbBFrame = rbB->getWorldTransform().inverse() * sharedFrame; + + dof = createGeneric6DofSpring2Constraint(*rbA, *rbB, rbAFrame, rbBFrame, RO_XYZ); + dof->setLinearUpperLimit(btVector3(0, 0, 0)); + dof->setLinearLowerLimit(btVector3(0, 0, 0)); + dof->setAngularUpperLimit(btVector3(0, 0, 0)); + dof->setAngularLowerLimit(btVector3(0, 0, 0)); + } + else + { + printf("Error in btWorldImporter::createGeneric6DofSpring2Constraint: requires rbA && rbB\n"); + } + + constraint = dof; + break; + } + + default: + { + printf("unknown constraint type\n"); + } + }; + + if (constraint) + { + constraint->setDbgDrawSize((btScalar)constraintData->m_dbgDrawSize); + ///those fields didn't exist and set to zero for pre-280 versions, so do a check here + if (fileVersion >= 280) + { + constraint->setBreakingImpulseThreshold((btScalar)constraintData->m_breakingImpulseThreshold); + constraint->setEnabled(constraintData->m_isEnabled != 0); + constraint->setOverrideNumSolverIterations(constraintData->m_overrideNumSolverIterations); + } + + if (constraintData->m_name) + { + char* newname = duplicateName(constraintData->m_name); + m_nameConstraintMap.insert(newname, constraint); + m_objectNameMap.insert(constraint, newname); + } + if (m_dynamicsWorld) + m_dynamicsWorld->addConstraint(constraint, constraintData->m_disableCollisionsBetweenLinkedBodies != 0); + } +} + +btTriangleIndexVertexArray* btWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData) +{ + btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer(); + + for (int i = 0; i < meshData.m_numMeshParts; i++) + { + btIndexedMesh meshPart; + meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles; + meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices; + + if (meshData.m_meshPartsPtr[i].m_indices32) + { + meshPart.m_indexType = PHY_INTEGER; + meshPart.m_triangleIndexStride = 3 * sizeof(int); + int* indexArray = (int*)btAlignedAlloc(sizeof(int) * 3 * meshPart.m_numTriangles, 16); + m_indexArrays.push_back(indexArray); + for (int j = 0; j < 3 * meshPart.m_numTriangles; j++) + { + indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value; + } + meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; + } + else + { + if (meshData.m_meshPartsPtr[i].m_3indices16) + { + meshPart.m_indexType = PHY_SHORT; + meshPart.m_triangleIndexStride = sizeof(short int) * 3; //sizeof(btShortIntIndexTripletData); + + short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16); + m_shortIndexArrays.push_back(indexArray); + + for (int j = 0; j < meshPart.m_numTriangles; j++) + { + indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0]; + indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1]; + indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2]; + } + + meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; + } + if (meshData.m_meshPartsPtr[i].m_indices16) + { + meshPart.m_indexType = PHY_SHORT; + meshPart.m_triangleIndexStride = 3 * sizeof(short int); + short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16); + m_shortIndexArrays.push_back(indexArray); + for (int j = 0; j < 3 * meshPart.m_numTriangles; j++) + { + indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value; + } + + meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; + } + + if (meshData.m_meshPartsPtr[i].m_3indices8) + { + meshPart.m_indexType = PHY_UCHAR; + meshPart.m_triangleIndexStride = sizeof(unsigned char) * 3; + + unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char) * 3 * meshPart.m_numTriangles, 16); + m_charIndexArrays.push_back(indexArray); + + for (int j = 0; j < meshPart.m_numTriangles; j++) + { + indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0]; + indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1]; + indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2]; + } + + meshPart.m_triangleIndexBase = (const unsigned char*)indexArray; + } + } + + if (meshData.m_meshPartsPtr[i].m_vertices3f) + { + meshPart.m_vertexType = PHY_FLOAT; + meshPart.m_vertexStride = sizeof(btVector3FloatData); + btVector3FloatData* vertices = (btVector3FloatData*)btAlignedAlloc(sizeof(btVector3FloatData) * meshPart.m_numVertices, 16); + m_floatVertexArrays.push_back(vertices); + + for (int j = 0; j < meshPart.m_numVertices; j++) + { + vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0]; + vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1]; + vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2]; + vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3]; + } + meshPart.m_vertexBase = (const unsigned char*)vertices; + } + else + { + meshPart.m_vertexType = PHY_DOUBLE; + meshPart.m_vertexStride = sizeof(btVector3DoubleData); + + btVector3DoubleData* vertices = (btVector3DoubleData*)btAlignedAlloc(sizeof(btVector3DoubleData) * meshPart.m_numVertices, 16); + m_doubleVertexArrays.push_back(vertices); + + for (int j = 0; j < meshPart.m_numVertices; j++) + { + vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0]; + vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1]; + vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2]; + vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3]; + } + meshPart.m_vertexBase = (const unsigned char*)vertices; + } + + if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase) + { + meshInterface->addIndexedMesh(meshPart, meshPart.m_indexType); + } + } + + return meshInterface; +} + +btStridingMeshInterfaceData* btWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData) +{ + //create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter + btStridingMeshInterfaceData* newData = new btStridingMeshInterfaceData; + + newData->m_scaling = interfaceData->m_scaling; + newData->m_numMeshParts = interfaceData->m_numMeshParts; + newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts]; + + for (int i = 0; i < newData->m_numMeshParts; i++) + { + btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i]; + btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i]; + + curNewPart->m_numTriangles = curPart->m_numTriangles; + curNewPart->m_numVertices = curPart->m_numVertices; + + if (curPart->m_vertices3f) + { + curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices]; + memcpy(curNewPart->m_vertices3f, curPart->m_vertices3f, sizeof(btVector3FloatData) * curNewPart->m_numVertices); + } + else + curNewPart->m_vertices3f = NULL; + + if (curPart->m_vertices3d) + { + curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices]; + memcpy(curNewPart->m_vertices3d, curPart->m_vertices3d, sizeof(btVector3DoubleData) * curNewPart->m_numVertices); + } + else + curNewPart->m_vertices3d = NULL; + + int numIndices = curNewPart->m_numTriangles * 3; + ///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time + ///we catch it by only dealing with m_3indices8 if none of the other indices are initialized + bool uninitialized3indices8Workaround = false; + + if (curPart->m_indices32) + { + uninitialized3indices8Workaround = true; + curNewPart->m_indices32 = new btIntIndexData[numIndices]; + memcpy(curNewPart->m_indices32, curPart->m_indices32, sizeof(btIntIndexData) * numIndices); + } + else + curNewPart->m_indices32 = NULL; + + if (curPart->m_3indices16) + { + uninitialized3indices8Workaround = true; + curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles]; + memcpy(curNewPart->m_3indices16, curPart->m_3indices16, sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles); + } + else + curNewPart->m_3indices16 = NULL; + + if (curPart->m_indices16) + { + uninitialized3indices8Workaround = true; + curNewPart->m_indices16 = new btShortIntIndexData[numIndices]; + memcpy(curNewPart->m_indices16, curPart->m_indices16, sizeof(btShortIntIndexData) * numIndices); + } + else + curNewPart->m_indices16 = NULL; + + if (!uninitialized3indices8Workaround && curPart->m_3indices8) + { + curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles]; + memcpy(curNewPart->m_3indices8, curPart->m_3indices8, sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles); + } + else + curNewPart->m_3indices8 = NULL; + } + + m_allocatedbtStridingMeshInterfaceDatas.push_back(newData); + + return (newData); +} + +#ifdef USE_INTERNAL_EDGE_UTILITY +extern ContactAddedCallback gContactAddedCallback; + +static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0, int index0, const btCollisionObject* colObj1, int partId1, int index1) +{ + btAdjustInternalEdgeContacts(cp, colObj1, colObj0, partId1, index1); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE); + //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED); + return true; +} +#endif //USE_INTERNAL_EDGE_UTILITY + +btCollisionObject* btWorldImporter::createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName) +{ + return createRigidBody(false, 0, startTransform, shape, bodyName); +} + +void btWorldImporter::setDynamicsWorldInfo(const btVector3& gravity, const btContactSolverInfo& solverInfo) +{ + if (m_dynamicsWorld) + { + m_dynamicsWorld->setGravity(gravity); + m_dynamicsWorld->getSolverInfo() = solverInfo; + } +} + +btRigidBody* btWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform, btCollisionShape* shape, const char* bodyName) +{ + btVector3 localInertia; + localInertia.setZero(); + + if (mass) + shape->calculateLocalInertia(mass, localInertia); + + btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia); + body->setWorldTransform(startTransform); + + if (m_dynamicsWorld) + m_dynamicsWorld->addRigidBody(body); + + if (bodyName) + { + char* newname = duplicateName(bodyName); + m_objectNameMap.insert(body, newname); + m_nameBodyMap.insert(newname, body); + } + m_allocatedRigidBodies.push_back(body); + return body; +} + +btCollisionShape* btWorldImporter::createPlaneShape(const btVector3& planeNormal, btScalar planeConstant) +{ + btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal, planeConstant); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} +btCollisionShape* btWorldImporter::createBoxShape(const btVector3& halfExtents) +{ + btBoxShape* shape = new btBoxShape(halfExtents); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} +btCollisionShape* btWorldImporter::createSphereShape(btScalar radius) +{ + btSphereShape* shape = new btSphereShape(radius); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height) +{ + btCapsuleShapeX* shape = new btCapsuleShapeX(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height) +{ + btCapsuleShape* shape = new btCapsuleShape(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height) +{ + btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCylinderShapeX(btScalar radius, btScalar height) +{ + btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height, radius, radius)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCylinderShapeY(btScalar radius, btScalar height) +{ + btCylinderShape* shape = new btCylinderShape(btVector3(radius, height, radius)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createCylinderShapeZ(btScalar radius, btScalar height) +{ + btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius, radius, height)); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createConeShapeX(btScalar radius, btScalar height) +{ + btConeShapeX* shape = new btConeShapeX(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createConeShapeY(btScalar radius, btScalar height) +{ + btConeShape* shape = new btConeShape(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCollisionShape* btWorldImporter::createConeShapeZ(btScalar radius, btScalar height) +{ + btConeShapeZ* shape = new btConeShapeZ(radius, height); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btTriangleIndexVertexArray* btWorldImporter::createTriangleMeshContainer() +{ + btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray(); + m_allocatedTriangleIndexArrays.push_back(in); + return in; +} + +btOptimizedBvh* btWorldImporter::createOptimizedBvh() +{ + btOptimizedBvh* bvh = new btOptimizedBvh(); + m_allocatedBvhs.push_back(bvh); + return bvh; +} + +btTriangleInfoMap* btWorldImporter::createTriangleInfoMap() +{ + btTriangleInfoMap* tim = new btTriangleInfoMap(); + m_allocatedTriangleInfoMaps.push_back(tim); + return tim; +} + +btBvhTriangleMeshShape* btWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh) +{ + if (bvh) + { + btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh, bvh->isQuantized(), false); + bvhTriMesh->setOptimizedBvh(bvh); + m_allocatedCollisionShapes.push_back(bvhTriMesh); + return bvhTriMesh; + } + + btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh, true); + m_allocatedCollisionShapes.push_back(ts); + return ts; +} +btCollisionShape* btWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh) +{ + return 0; +} +btGImpactMeshShape* btWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh) +{ +#ifdef USE_GIMPACT + btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh); + m_allocatedCollisionShapes.push_back(shape); + return shape; +#else + return 0; +#endif +} +btConvexHullShape* btWorldImporter::createConvexHullShape() +{ + btConvexHullShape* shape = new btConvexHullShape(); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btCompoundShape* btWorldImporter::createCompoundShape() +{ + btCompoundShape* shape = new btCompoundShape(); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btScaledBvhTriangleMeshShape* btWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScaling) +{ + btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape, localScaling); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btMultiSphereShape* btWorldImporter::createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres) +{ + btMultiSphereShape* shape = new btMultiSphereShape(positions, radi, numSpheres); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +class btHeightfieldTerrainShape* btWorldImporter::createHeightfieldShape(int heightStickWidth, int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, + int upAxis, int heightDataType, + bool flipQuadEdges) +{ + + btHeightfieldTerrainShape* shape = new btHeightfieldTerrainShape(heightStickWidth, heightStickLength, + heightfieldData, heightScale, minHeight, maxHeight, upAxis, PHY_ScalarType(heightDataType), flipQuadEdges); + m_allocatedCollisionShapes.push_back(shape); + return shape; +} + +btRigidBody& btWorldImporter::getFixedBody() +{ + static btRigidBody s_fixed(0, 0, 0); + s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.))); + return s_fixed; +} + +btPoint2PointConstraint* btWorldImporter::createPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB) +{ + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA, rbB, pivotInA, pivotInB); + m_allocatedConstraints.push_back(p2p); + return p2p; +} + +btPoint2PointConstraint* btWorldImporter::createPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA) +{ + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA, pivotInA); + m_allocatedConstraints.push_back(p2p); + return p2p; +} + +btHingeConstraint* btWorldImporter::createHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA) +{ + btHingeConstraint* hinge = new btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA); + m_allocatedConstraints.push_back(hinge); + return hinge; +} + +btHingeConstraint* btWorldImporter::createHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA) +{ + btHingeConstraint* hinge = new btHingeConstraint(rbA, rbAFrame, useReferenceFrameA); + m_allocatedConstraints.push_back(hinge); + return hinge; +} + +btConeTwistConstraint* btWorldImporter::createConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame) +{ + btConeTwistConstraint* cone = new btConeTwistConstraint(rbA, rbB, rbAFrame, rbBFrame); + m_allocatedConstraints.push_back(cone); + return cone; +} + +btConeTwistConstraint* btWorldImporter::createConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame) +{ + btConeTwistConstraint* cone = new btConeTwistConstraint(rbA, rbAFrame); + m_allocatedConstraints.push_back(cone); + return cone; +} + +btGeneric6DofConstraint* btWorldImporter::createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) +{ + btGeneric6DofConstraint* dof = new btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btGeneric6DofConstraint* btWorldImporter::createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB) +{ + btGeneric6DofConstraint* dof = new btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btGeneric6DofSpring2Constraint* btWorldImporter::createGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, int rotateOrder) +{ + btGeneric6DofSpring2Constraint* dof = new btGeneric6DofSpring2Constraint(rbA, rbB, frameInA, frameInB, (RotateOrder)rotateOrder); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btGeneric6DofSpringConstraint* btWorldImporter::createGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) +{ + btGeneric6DofSpringConstraint* dof = new btGeneric6DofSpringConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA); + m_allocatedConstraints.push_back(dof); + return dof; +} + +btSliderConstraint* btWorldImporter::createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) +{ + btSliderConstraint* slider = new btSliderConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA); + m_allocatedConstraints.push_back(slider); + return slider; +} + +btSliderConstraint* btWorldImporter::createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA) +{ + btSliderConstraint* slider = new btSliderConstraint(rbB, frameInB, useLinearReferenceFrameA); + m_allocatedConstraints.push_back(slider); + return slider; +} + +btGearConstraint* btWorldImporter::createGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio) +{ + btGearConstraint* gear = new btGearConstraint(rbA, rbB, axisInA, axisInB, ratio); + m_allocatedConstraints.push_back(gear); + return gear; +} + +// query for data +int btWorldImporter::getNumCollisionShapes() const +{ + return m_allocatedCollisionShapes.size(); +} + +btCollisionShape* btWorldImporter::getCollisionShapeByIndex(int index) +{ + return m_allocatedCollisionShapes[index]; +} + +btCollisionShape* btWorldImporter::getCollisionShapeByName(const char* name) +{ + btCollisionShape** shapePtr = m_nameShapeMap.find(name); + if (shapePtr && *shapePtr) + { + return *shapePtr; + } + return 0; +} + +btRigidBody* btWorldImporter::getRigidBodyByName(const char* name) +{ + btRigidBody** bodyPtr = m_nameBodyMap.find(name); + if (bodyPtr && *bodyPtr) + { + return *bodyPtr; + } + return 0; +} + +btTypedConstraint* btWorldImporter::getConstraintByName(const char* name) +{ + btTypedConstraint** constraintPtr = m_nameConstraintMap.find(name); + if (constraintPtr && *constraintPtr) + { + return *constraintPtr; + } + return 0; +} + +const char* btWorldImporter::getNameForPointer(const void* ptr) const +{ + const char* const* namePtr = m_objectNameMap.find(ptr); + if (namePtr && *namePtr) + return *namePtr; + return 0; +} + +int btWorldImporter::getNumRigidBodies() const +{ + return m_allocatedRigidBodies.size(); +} + +btCollisionObject* btWorldImporter::getRigidBodyByIndex(int index) const +{ + return m_allocatedRigidBodies[index]; +} +int btWorldImporter::getNumConstraints() const +{ + return m_allocatedConstraints.size(); +} + +btTypedConstraint* btWorldImporter::getConstraintByIndex(int index) const +{ + return m_allocatedConstraints[index]; +} + +int btWorldImporter::getNumBvhs() const +{ + return m_allocatedBvhs.size(); +} +btOptimizedBvh* btWorldImporter::getBvhByIndex(int index) const +{ + return m_allocatedBvhs[index]; +} + +int btWorldImporter::getNumTriangleInfoMaps() const +{ + return m_allocatedTriangleInfoMaps.size(); +} + +btTriangleInfoMap* btWorldImporter::getTriangleInfoMapByIndex(int index) const +{ + return m_allocatedTriangleInfoMaps[index]; +} + +void btWorldImporter::convertRigidBodyFloat(btRigidBodyFloatData* colObjData) +{ + btScalar mass = btScalar(colObjData->m_inverseMass ? 1.f / colObjData->m_inverseMass : 0.f); + btVector3 localInertia; + localInertia.setZero(); + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + colObjData->m_collisionObjectData.m_worldTransform.m_origin.m_floats[3] = 0.f; + startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform); + + // startTransform.setBasis(btMatrix3x3::getIdentity()); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + if (shape->isNonMoving()) + { + mass = 0.f; + } + if (mass) + { + shape->calculateLocalInertia(mass, localInertia); + } + bool isDynamic = mass != 0.f; + btRigidBody* body = createRigidBody(isDynamic, mass, startTransform, shape, colObjData->m_collisionObjectData.m_name); + body->setFriction(colObjData->m_collisionObjectData.m_friction); + body->setRestitution(colObjData->m_collisionObjectData.m_restitution); + btVector3 linearFactor, angularFactor; + linearFactor.deSerializeFloat(colObjData->m_linearFactor); + angularFactor.deSerializeFloat(colObjData->m_angularFactor); + body->setLinearFactor(linearFactor); + body->setAngularFactor(angularFactor); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData, body); + } + else + { + printf("error: no shape found\n"); + } +} + +void btWorldImporter::convertRigidBodyDouble(btRigidBodyDoubleData* colObjData) +{ + btScalar mass = btScalar(colObjData->m_inverseMass ? 1.f / colObjData->m_inverseMass : 0.f); + btVector3 localInertia; + localInertia.setZero(); + btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape); + if (shapePtr && *shapePtr) + { + btTransform startTransform; + colObjData->m_collisionObjectData.m_worldTransform.m_origin.m_floats[3] = 0.f; + startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform); + + // startTransform.setBasis(btMatrix3x3::getIdentity()); + btCollisionShape* shape = (btCollisionShape*)*shapePtr; + if (shape->isNonMoving()) + { + mass = 0.f; + } + if (mass) + { + shape->calculateLocalInertia(mass, localInertia); + } + bool isDynamic = mass != 0.f; + btRigidBody* body = createRigidBody(isDynamic, mass, startTransform, shape, colObjData->m_collisionObjectData.m_name); + body->setFriction(btScalar(colObjData->m_collisionObjectData.m_friction)); + body->setRestitution(btScalar(colObjData->m_collisionObjectData.m_restitution)); + btVector3 linearFactor, angularFactor; + linearFactor.deSerializeDouble(colObjData->m_linearFactor); + angularFactor.deSerializeDouble(colObjData->m_angularFactor); + body->setLinearFactor(linearFactor); + body->setAngularFactor(angularFactor); + +#ifdef USE_INTERNAL_EDGE_UTILITY + if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape; + if (trimesh->getTriangleInfoMap()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); + } + } +#endif //USE_INTERNAL_EDGE_UTILITY + m_bodyMap.insert(colObjData, body); + } + else + { + printf("error: no shape found\n"); + } +} \ No newline at end of file diff --git a/source/BulletWorldImporter/btWorldImporter.h b/source/BulletWorldImporter/btWorldImporter.h new file mode 100644 index 000000000..2d2ddd22f --- /dev/null +++ b/source/BulletWorldImporter/btWorldImporter.h @@ -0,0 +1,227 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_WORLD_IMPORTER_H +#define BT_WORLD_IMPORTER_H + +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btHashMap.h" + +class btCollisionShape; +class btCollisionObject; +class btRigidBody; +class btTypedConstraint; +class btDynamicsWorld; +struct ConstraintInput; +class btRigidBodyColladaInfo; +struct btCollisionShapeData; +class btTriangleIndexVertexArray; +class btStridingMeshInterface; +struct btStridingMeshInterfaceData; +class btGImpactMeshShape; +class btOptimizedBvh; +struct btTriangleInfoMap; +class btBvhTriangleMeshShape; +class btPoint2PointConstraint; +class btHingeConstraint; +class btConeTwistConstraint; +class btGeneric6DofConstraint; +class btGeneric6DofSpringConstraint; +class btGeneric6DofSpring2Constraint; +class btSliderConstraint; +class btGearConstraint; +struct btContactSolverInfo; +struct btTypedConstraintData; +struct btTypedConstraintFloatData; +struct btTypedConstraintDoubleData; + +struct btRigidBodyDoubleData; +struct btRigidBodyFloatData; + +#ifdef BT_USE_DOUBLE_PRECISION +#define btRigidBodyData btRigidBodyDoubleData +#else +#define btRigidBodyData btRigidBodyFloatData +#endif //BT_USE_DOUBLE_PRECISION + +enum btWorldImporterFlags +{ + eRESTORE_EXISTING_OBJECTS = 1, //don't create new objects +}; + +class btWorldImporter +{ +protected: + btDynamicsWorld* m_dynamicsWorld; + + int m_verboseMode; + int m_importerFlags; + + btAlignedObjectArray m_allocatedCollisionShapes; + btAlignedObjectArray m_allocatedRigidBodies; + btAlignedObjectArray m_allocatedConstraints; + btAlignedObjectArray m_allocatedBvhs; + btAlignedObjectArray m_allocatedTriangleInfoMaps; + btAlignedObjectArray m_allocatedTriangleIndexArrays; + btAlignedObjectArray m_allocatedbtStridingMeshInterfaceDatas; + + btAlignedObjectArray m_allocatedNames; + + btAlignedObjectArray m_indexArrays; + btAlignedObjectArray m_shortIndexArrays; + btAlignedObjectArray m_charIndexArrays; + + btAlignedObjectArray m_floatVertexArrays; + btAlignedObjectArray m_doubleVertexArrays; + + btHashMap m_bvhMap; + btHashMap m_timMap; + + btHashMap m_nameShapeMap; + btHashMap m_nameBodyMap; + btHashMap m_nameConstraintMap; + btHashMap m_objectNameMap; + + btHashMap m_shapeMap; + btHashMap m_bodyMap; + + //methods + + static btRigidBody& getFixedBody(); + + char* duplicateName(const char* name); + + btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData); + + void convertConstraintBackwardsCompatible281(btTypedConstraintData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion); + void convertConstraintFloat(btTypedConstraintFloatData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion); + void convertConstraintDouble(btTypedConstraintDoubleData* constraintData, btRigidBody* rbA, btRigidBody* rbB, int fileVersion); + void convertRigidBodyFloat(btRigidBodyFloatData* colObjData); + void convertRigidBodyDouble(btRigidBodyDoubleData* colObjData); + +public: + btWorldImporter(btDynamicsWorld* world); + + virtual ~btWorldImporter(); + + ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load. + ///make sure you don't use the dynamics world containing objects after you call this method + virtual void deleteAllData(); + + void setVerboseMode(int verboseMode) + { + m_verboseMode = verboseMode; + } + + int getVerboseMode() const + { + return m_verboseMode; + } + + void setImporterFlags(int importerFlags) + { + m_importerFlags = importerFlags; + } + + int getImporterFlags() const + { + return m_importerFlags; + } + + // query for data + int getNumCollisionShapes() const; + btCollisionShape* getCollisionShapeByIndex(int index); + int getNumRigidBodies() const; + btCollisionObject* getRigidBodyByIndex(int index) const; + int getNumConstraints() const; + btTypedConstraint* getConstraintByIndex(int index) const; + int getNumBvhs() const; + btOptimizedBvh* getBvhByIndex(int index) const; + int getNumTriangleInfoMaps() const; + btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const; + + // queris involving named objects + btCollisionShape* getCollisionShapeByName(const char* name); + btRigidBody* getRigidBodyByName(const char* name); + btTypedConstraint* getConstraintByName(const char* name); + const char* getNameForPointer(const void* ptr) const; + + ///those virtuals are called by load and can be overridden by the user + + virtual void setDynamicsWorldInfo(const btVector3& gravity, const btContactSolverInfo& solverInfo); + + //bodies + virtual btRigidBody* createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform, btCollisionShape* shape, const char* bodyName); + virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName); + + ///shapes + + virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant); + virtual btCollisionShape* createBoxShape(const btVector3& halfExtents); + virtual btCollisionShape* createSphereShape(btScalar radius); + virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height); + virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height); + virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height); + + virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height); + virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height); + virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height); + virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height); + virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height); + virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height); + virtual class btTriangleIndexVertexArray* createTriangleMeshContainer(); + virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh); + virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh); + virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh); + virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData); + + virtual class btConvexHullShape* createConvexHullShape(); + virtual class btCompoundShape* createCompoundShape(); + virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape); + + virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres); + + virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData); + + virtual class btHeightfieldTerrainShape* createHeightfieldShape(int heightStickWidth, int heightStickLength, + const void* heightfieldData, btScalar heightScale, + btScalar minHeight, btScalar maxHeight, + int upAxis, int heightDataType, + bool flipQuadEdges); + + ///acceleration and connectivity structures + virtual btOptimizedBvh* createOptimizedBvh(); + virtual btTriangleInfoMap* createTriangleInfoMap(); + + ///constraints + virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB); + virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA); + virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false); + virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false); + virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame); + virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB); + virtual btGeneric6DofSpringConstraint* createGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + virtual btGeneric6DofSpring2Constraint* createGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, int rotateOrder); + + virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA); + virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA); + virtual btGearConstraint* createGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio); +}; + +#endif //BT_WORLD_IMPORTER_H \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index d564e1087..7fb06fa2a 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 2.8) - # Linux prefers lower-case exe names if (WIN32 OR APPLE) set(GAME_EXE StuntRally) @@ -14,13 +12,19 @@ else() endif() # Search include files from all source sub directories -include_directories(btOgre ogre ogre/common paged-geom road tinyxml sound vdrift) +include_directories(./ btOgre ogre ogre/common paged-geom road tinyxml sound vdrift) # Compile our libraries ------ if (BUILD_GAME OR BUILD_EDITOR) - - foreach(ourlib oics tinyxml paged-geom btOgre) + if(VCPKG_TOOLCHAIN) + add_subdirectory(mygui-ogre) + include_directories(mygui-ogre) + list(APPEND OURLIBS MyGUI_OgrePlatform_Local) + include_directories("${OGRE_INCLUDE_DIRS}/Bites" "${OGRE_INCLUDE_DIRS}/Overlay" "${OGRE_INCLUDE_DIRS}/Paging" "${OGRE_INCLUDE_DIRS}/Terrain") + endif() + + foreach(ourlib oics tinyxml paged-geom btOgre BulletFileLoader BulletWorldImporter) add_subdirectory(${ourlib}) list(APPEND OURLIBS ${ourlib}) endforeach() @@ -135,7 +139,7 @@ if (BUILD_TRANSL_TOOL) file(GLOB TRANSL_SOURCES transl/main.cpp) # Glob .cpp files needed for the translations tool add_executable(${TRANSL_EXE} ${TRANSL_SOURCES}) #target_link_libraries(${TRANSL_EXE} ${TRANSL_LIBS}) - target_link_libraries(${TRANSL_EXE} "boost_filesystem" "boost_system") + target_link_libraries(${TRANSL_EXE} Boost::filesystem Boost::system) install(TARGETS ${TRANSL_EXE} DESTINATION bin) endif() diff --git a/source/editor/BaseApp.h b/source/editor/BaseApp.h index 8b12c488d..2ba3fcec9 100644 --- a/source/editor/BaseApp.h +++ b/source/editor/BaseApp.h @@ -114,12 +114,9 @@ class BaseApp : public BGui, bool bGuiFocus; // gui shown MyGUI::Gui* mGui; void baseInitGui(); - - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - MyGUI::OgreD3D11Platform* mPlatform; - #else + MyGUI::OgrePlatform* mPlatform; - #endif + Wnd mWndBrush, mWndCam, mWndStart, // tool windows mWndRoadCur, mWndRoadStats, mWndFluids, mWndObjects, diff --git a/source/editor/BaseApp_Create.cpp b/source/editor/BaseApp_Create.cpp index c50a7bff3..5cd63396b 100644 --- a/source/editor/BaseApp_Create.cpp +++ b/source/editor/BaseApp_Create.cpp @@ -16,7 +16,8 @@ #include #include #include -#include "../ogre/common/MyGUI_D3D11.h" +#include +#include #include "../sdl4ogre/sdlinputwrapper.hpp" #include "../sdl4ogre/sdlcursormanager.hpp" #include "../sdl4ogre/sdlwindowhelper.hpp" @@ -27,6 +28,7 @@ #include #include #include +#include #include namespace @@ -474,11 +476,7 @@ void BaseApp::baseInitGui() { using namespace MyGUI; // Gui - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - mPlatform = new OgreD3D11Platform(); - #else mPlatform = new OgrePlatform(); - #endif mPlatform->initialise(mWindow, mSceneMgr, "General", PATHMANAGER::UserConfigDir() + "/MyGUI.log"); mGui = new Gui(); diff --git a/source/editor/main.cpp b/source/editor/main.cpp index f291bdc8d..1b04947c9 100644 --- a/source/editor/main.cpp +++ b/source/editor/main.cpp @@ -20,10 +20,10 @@ void LoadDefaultSet(SETTINGS* settings, string setFile) // . . . . . . . . . . MAIN . . . . . . . . . . -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR lpCmdLine, int nCmdShow) -#else +#if defined(main) || OGRE_PLATFORM != OGRE_PLATFORM_WIN32 int main(int argc, char* argv[]) +#else + int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR lpCmdLine, int nCmdShow) #endif { setlocale(LC_NUMERIC, "C"); @@ -77,10 +77,10 @@ void LoadDefaultSet(SETTINGS* settings, string setFile) try { - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - pApp->Run( settings->ogre_dialog || lpCmdLine[0]!=0 ); - #else + #if defined(main) || OGRE_PLATFORM != OGRE_PLATFORM_WIN32 pApp->Run( settings->ogre_dialog ); + #else + pApp->Run( settings->ogre_dialog || lpCmdLine[0]!=0 ); #endif } catch (Ogre::Exception& e) diff --git a/source/editor/pch.h b/source/editor/pch.h index f929afa34..b0df52670 100644 --- a/source/editor/pch.h +++ b/source/editor/pch.h @@ -4,6 +4,15 @@ #ifdef _MSC_VER // include file for project specific include files that are used frequently, but are changed infrequently +/// win +#define WINVER 0x0510 +#define _WIN32_WINNT 0x0510 +#define _WIN32_WINDOWS 0x0410 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include + /// std #include #include @@ -26,17 +35,6 @@ #include #include -/// win -#include -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - #define WINVER 0x0510 - #define _WIN32_WINNT 0x0510 - #define _WIN32_WINDOWS 0x0410 - #define WIN32_LEAN_AND_MEAN - #include - #include -#endif - #include "tinyxml.h" #include "tinyxml2.h" diff --git a/source/mygui-ogre/CMakeLists.txt b/source/mygui-ogre/CMakeLists.txt new file mode 100644 index 000000000..749e8758d --- /dev/null +++ b/source/mygui-ogre/CMakeLists.txt @@ -0,0 +1,19 @@ +add_library(MyGUI_OgrePlatform_Local STATIC + MyGUI_OgreDataManager.h + MyGUI_OgreDataStream.h + MyGUI_OgreDiagnostic.h + MyGUI_OgrePlatform.h + MyGUI_OgreRTTexture.h + MyGUI_OgreRenderManager.h + MyGUI_OgreTexture.h + MyGUI_OgreVertexBuffer.h + MyGUI_OgreDataManager.cpp + MyGUI_OgreDataStream.cpp + MyGUI_OgreRTTexture.cpp + MyGUI_OgreRenderManager.cpp + MyGUI_OgreTexture.cpp + MyGUI_OgreVertexBuffer.cpp) + +target_include_directories(MyGUI_OgrePlatform_Local PRIVATE ./include ${OGRE_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}) +target_include_directories(MyGUI_OgrePlatform_Local PUBLIC ./include) +target_link_libraries(MyGUI_OgrePlatform_Local PRIVATE ${OGRE_LIBRARIES} ${MYGUI_LIBRARIES}) diff --git a/source/mygui-ogre/MyGUI_OgreDataManager.cpp b/source/mygui-ogre/MyGUI_OgreDataManager.cpp new file mode 100644 index 000000000..fd2b96a0f --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreDataManager.cpp @@ -0,0 +1,167 @@ +/*! + @file + @author Albert Semenov + @date 05/2008 +*/ + +#include "MyGUI_OgreDataManager.h" +#include "MyGUI_OgreDiagnostic.h" +#include "MyGUI_OgreDataStream.h" + +#include + +namespace MyGUI +{ + + OgreDataManager::OgreDataManager() : + mAllGroups(false), + mIsInitialise(false) + { + } + + void OgreDataManager::initialise(const std::string& _group) + { + MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice"); + MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName()); + + mGroup = _group; + if (mGroup == Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME) + mAllGroups = true; + else + mAllGroups = false; + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized"); + mIsInitialise = true; + } + + void OgreDataManager::shutdown() + { + MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised"); + MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName()); + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown"); + mIsInitialise = false; + } + + IDataStream* OgreDataManager::getData(const std::string& _name) const + { + try + { + Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(_name, mGroup); + OgreDataStream* data = new OgreDataStream(stream); + + return data; + } + catch (const Ogre::FileNotFoundException& _e) + { + MYGUI_PLATFORM_LOG(Warning, _e.getDescription()); + } + + return nullptr; + } + + void OgreDataManager::freeData(IDataStream* _data) + { + delete _data; + } + + bool OgreDataManager::isDataExist(const std::string& _name) const + { + if (mAllGroups) + return Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(_name); + else + return Ogre::ResourceGroupManager::getSingleton().resourceExists(mGroup, _name); + } + + const VectorString& OgreDataManager::getDataListNames(const std::string& _pattern) const + { + return getDataListNames(_pattern, false); + } + + const VectorString& OgreDataManager::getDataListNames(const std::string& _pattern, bool _fullpath) const + { + static VectorString result; + result.clear(); + + VectorString search; + if (mAllGroups) + { + Ogre::StringVector sp = Ogre::ResourceGroupManager::getSingleton().getResourceGroups(); + search.reserve(sp.size()); + for (size_t i = 0; i < sp.size(); i++) + search.push_back(sp[i]); + } + else + search.push_back(mGroup); + + std::vector pFileInfos; + + int resultSize = 0; + for (size_t i = 0; i < search.size(); i++) + { + Ogre::FileInfoListPtr pFileInfo = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo(search[i], _pattern); + resultSize += pFileInfo->size(); + if (!pFileInfo->empty()) + pFileInfos.push_back(pFileInfo); + else + pFileInfo.reset(); + } + + result.reserve(resultSize); + + for (size_t i = 0; i < pFileInfos.size(); i++) + { + Ogre::FileInfoListPtr pFileInfo = pFileInfos[i]; + for (Ogre::FileInfoList::iterator fi = pFileInfo->begin(); fi != pFileInfo->end(); ++fi) + { + if (fi->path.empty()) + { + bool found = false; + for (VectorString::iterator iter = result.begin(); iter != result.end(); ++iter) + { + if (*iter == fi->filename) + { + found = true; + break; + } + } + if (!found) + { + result.push_back(_fullpath ? fi->archive->getName() + "/" + fi->filename : fi->filename); + } + } + } + + pFileInfo.reset(); + } + + return result; + } + + const std::string& OgreDataManager::getDataPath(const std::string& _name) const + { + static std::string result; + result.clear(); + + const VectorString& files = getDataListNames(_name, true); + if (!files.empty()) + { + result = files[0]; + if (files.size() > 1) + { + MYGUI_PLATFORM_LOG(Warning, "There are several files with name '" << _name << "'. '" << result << "' was used."); + MYGUI_PLATFORM_LOG(Warning, "Other candidates are:"); + for (size_t index = 1; index < files.size(); index++) + MYGUI_PLATFORM_LOG(Warning, " - '" << files[index] << "'"); + } + } + + return result; + } + + void OgreDataManager::addResourceLocation(const std::string& _name, bool _recursive) + { + Ogre::ResourceGroupManager::getSingleton().addResourceLocation(_name, "FileSystem", mGroup, _recursive); + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreDataManager.h b/source/mygui-ogre/MyGUI_OgreDataManager.h new file mode 100644 index 000000000..5b26ce745 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreDataManager.h @@ -0,0 +1,69 @@ +/*! + @file + @author Albert Semenov + @date 05/2008 +*/ + +#ifndef MYGUI_OGRE_DATA_MANAGER_H_ +#define MYGUI_OGRE_DATA_MANAGER_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_DataManager.h" + +namespace MyGUI +{ + + class OgreDataManager : + public DataManager + { + public: + OgreDataManager(); + + void initialise(const std::string& _group); + void shutdown(); + + static OgreDataManager& getInstance() + { + return *getInstancePtr(); + } + static OgreDataManager* getInstancePtr() + { + return static_cast(DataManager::getInstancePtr()); + } + + const std::string& getGroup() const + { + return mGroup; + } + + /** @see DataManager::getData */ + IDataStream* getData(const std::string& _name) const override; + + /** @see DataManager::freeData */ + void freeData(IDataStream* _data) override; + + /** @see DataManager::isDataExist */ + bool isDataExist(const std::string& _name) const override; + + /** @see DataManager::getDataListNames */ + const VectorString& getDataListNames(const std::string& _pattern) const override; + + /** @see DataManager::getDataPath */ + const std::string& getDataPath(const std::string& _name) const override; + + /*internal:*/ + void addResourceLocation(const std::string& _name, bool _recursive); + + private: + const VectorString& getDataListNames(const std::string& _pattern, bool _fullpath) const; + + private: + std::string mGroup; + bool mAllGroups; + + bool mIsInitialise; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_DATA_MANAGER_H_ diff --git a/source/mygui-ogre/MyGUI_OgreDataStream.cpp b/source/mygui-ogre/MyGUI_OgreDataStream.cpp new file mode 100644 index 000000000..af432b7de --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreDataStream.cpp @@ -0,0 +1,48 @@ +/*! + @file + @author Albert Semenov + @date 08/2009 +*/ + +#include "MyGUI_OgreDataStream.h" + +namespace MyGUI +{ + + OgreDataStream::OgreDataStream(Ogre::DataStreamPtr _stream) : + mStream(_stream) + { + } + + OgreDataStream::~OgreDataStream() + { + mStream.reset(); + } + + bool OgreDataStream::eof() + { + return !mStream ? true : mStream->eof(); + } + + size_t OgreDataStream::size() + { + return !mStream ? 0 : mStream->size(); + } + + void OgreDataStream::readline(std::string& _source, Char _delim) + { + if (!mStream) + { + _source.clear(); + return; + } + _source = mStream->getLine(false); + } + + size_t OgreDataStream::read(void* _buf, size_t _count) + { + if (!mStream) return 0; + return mStream->read(_buf, _count); + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreDataStream.h b/source/mygui-ogre/MyGUI_OgreDataStream.h new file mode 100644 index 000000000..802da7ad6 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreDataStream.h @@ -0,0 +1,36 @@ +/*! + @file + @author Albert Semenov + @date 08/2009 +*/ + +#ifndef MYGUI_OGRE_DATA_STREAM_H_ +#define MYGUI_OGRE_DATA_STREAM_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_IDataStream.h" + +#include + +namespace MyGUI +{ + + class OgreDataStream : + public IDataStream + { + public: + OgreDataStream(Ogre::DataStreamPtr _stream); + ~OgreDataStream() override; + + bool eof() override; + size_t size() override; + void readline(std::string& _source, Char _delim) override; + size_t read(void* _buf, size_t _count) override; + + private: + Ogre::DataStreamPtr mStream; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_DATA_STREAM_H_ diff --git a/source/mygui-ogre/MyGUI_OgreDiagnostic.h b/source/mygui-ogre/MyGUI_OgreDiagnostic.h new file mode 100644 index 000000000..e83ab7b35 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreDiagnostic.h @@ -0,0 +1,35 @@ +/*! + @file + @author Albert Semenov + @date 06/2009 +*/ + +#ifndef MYGUI_OGRE_DIAGNOSTIC_H_ +#define MYGUI_OGRE_DIAGNOSTIC_H_ + +#include "MyGUI_Prerequest.h" + +#define MYGUI_PLATFORM_LOG_SECTION "Platform" +#define MYGUI_PLATFORM_LOG_FILENAME "MyGUI.log" +#define MYGUI_PLATFORM_LOG(level, text) MYGUI_LOGGING(MYGUI_PLATFORM_LOG_SECTION, level, text) + +#define MYGUI_PLATFORM_EXCEPT(dest) \ +do { \ + MYGUI_PLATFORM_LOG(Critical, dest); \ + std::ostringstream stream; \ + stream << dest << "\n"; \ + MYGUI_BASE_EXCEPT(stream.str().c_str(), "MyGUI"); \ +} while (false) + +#define MYGUI_PLATFORM_ASSERT(exp, dest) \ +do { \ + if ( ! (exp) ) \ + { \ + MYGUI_PLATFORM_LOG(Critical, dest); \ + std::ostringstream stream; \ + stream << dest << "\n"; \ + MYGUI_BASE_EXCEPT(stream.str().c_str(), "MyGUI"); \ + } \ +} while (false) + +#endif // MYGUI_OGRE_DIAGNOSTIC_H_ diff --git a/source/mygui-ogre/MyGUI_OgrePlatform.h b/source/mygui-ogre/MyGUI_OgrePlatform.h new file mode 100644 index 000000000..e37f09072 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgrePlatform.h @@ -0,0 +1,86 @@ +/*! + @file + @author Albert Semenov + @date 04/2009 +*/ + +#ifndef MYGUI_OGRE_PLATFORM_H_ +#define MYGUI_OGRE_PLATFORM_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_OgreTexture.h" +#include "MyGUI_OgreVertexBuffer.h" +#include "MyGUI_OgreRenderManager.h" +#include "MyGUI_OgreDataManager.h" +#include "MyGUI_OgreDiagnostic.h" +#include "MyGUI_OgreTexture.h" +#include "MyGUI_LogManager.h" +#include + +namespace MyGUI +{ + + class OgrePlatform + { + public: + OgrePlatform() : + mIsInitialise(false) + { + mLogManager = new LogManager(); + mDataManager = new OgreDataManager(); + mRenderManager = new OgreRenderManager(); + } + + ~OgrePlatform() + { + assert(!mIsInitialise); + delete mRenderManager; + delete mDataManager; + delete mLogManager; + } + + void initialise( + Ogre::RenderWindow* _window, + Ogre::SceneManager* _scene, + const std::string& _group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + const std::string& _logName = MYGUI_PLATFORM_LOG_FILENAME) + { + assert(!mIsInitialise); + mIsInitialise = true; + + if (!_logName.empty()) + LogManager::getInstance().createDefaultSource(_logName); + + mDataManager->initialise(_group); + mRenderManager->initialise(_window, _scene); + } + + void shutdown() + { + assert(mIsInitialise); + mIsInitialise = false; + + mRenderManager->shutdown(); + mDataManager->shutdown(); + } + + OgreRenderManager* getRenderManagerPtr() + { + return mRenderManager; + } + + OgreDataManager* getDataManagerPtr() + { + return mDataManager; + } + + private: + bool mIsInitialise; + OgreRenderManager* mRenderManager; + OgreDataManager* mDataManager; + LogManager* mLogManager; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_PLATFORM_H_ diff --git a/source/mygui-ogre/MyGUI_OgreRTTexture.cpp b/source/mygui-ogre/MyGUI_OgreRTTexture.cpp new file mode 100644 index 000000000..8dabaae36 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreRTTexture.cpp @@ -0,0 +1,72 @@ +/*! + @file + @author Albert Semenov + @date 10/2009 +*/ + +#include +#include "MyGUI_OgreRTTexture.h" +#include "MyGUI_OgreRenderManager.h" + +#include + +namespace MyGUI +{ + + OgreRTTexture::OgreRTTexture(Ogre::TexturePtr _texture) : + mViewport(nullptr), + mSaveViewport(nullptr), + mTexture(_texture) + { + Ogre::Root* root = Ogre::Root::getSingletonPtr(); + if (root != nullptr) + { + Ogre::RenderSystem* system = root->getRenderSystem(); + if (system != nullptr) + { + size_t width = mTexture->getWidth(); + size_t height = mTexture->getHeight(); + + mRenderTargetInfo.maximumDepth = system->getMaximumDepthInputValue(); + mRenderTargetInfo.hOffset = system->getHorizontalTexelOffset() / float(width); + mRenderTargetInfo.vOffset = system->getVerticalTexelOffset() / float(height); + mRenderTargetInfo.aspectCoef = float(height) / float(width); + mRenderTargetInfo.pixScaleX = 1.0f / float(width); + mRenderTargetInfo.pixScaleY = 1.0f / float(height); + } + } + } + + void OgreRTTexture::begin() + { + Ogre::RenderTexture* rtt = mTexture->getBuffer()->getRenderTarget(); + + if (mViewport == nullptr) + { + mViewport = rtt->addViewport(nullptr); + mViewport->setClearEveryFrame(false); + mViewport->setOverlaysEnabled(false); + } + + Ogre::RenderSystem* system = Ogre::Root::getSingleton().getRenderSystem(); + mSaveViewport = system->_getViewport(); + system->_setViewport(mViewport); + system->clearFrameBuffer(Ogre::FBT_COLOUR, Ogre::ColourValue::ZERO); + + OgreRenderManager::getInstance().beginRttRender(mTexture->getBuffer()->getRenderTarget()->requiresTextureFlipping()); + } + + void OgreRTTexture::end() + { + Ogre::RenderSystem* system = Ogre::Root::getSingleton().getRenderSystem(); + system->_setViewport(mSaveViewport); + + OgreRenderManager::getInstance().endRttRender(); + } + + void OgreRTTexture::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) + { + OgreRenderManager::getInstance().doRenderRtt(_buffer, _texture, _count, mTexture->getBuffer()->getRenderTarget()); + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreRTTexture.h b/source/mygui-ogre/MyGUI_OgreRTTexture.h new file mode 100644 index 000000000..7f8649764 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreRTTexture.h @@ -0,0 +1,44 @@ +/*! + @file + @author Albert Semenov + @date 10/2009 +*/ + +#ifndef MYGUI_OGRE_RTTEXTURE_H_ +#define MYGUI_OGRE_RTTEXTURE_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_IRenderTarget.h" + +#include +#include + +namespace MyGUI +{ + + class OgreRTTexture : + public IRenderTarget + { + public: + OgreRTTexture(Ogre::TexturePtr _texture); + + void begin() override; + void end() override; + + void doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) override; + + const RenderTargetInfo& getInfo() const override + { + return mRenderTargetInfo; + } + + private: + RenderTargetInfo mRenderTargetInfo; + Ogre::Viewport* mViewport; + Ogre::Viewport* mSaveViewport; + Ogre::TexturePtr mTexture; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_RTTEXTURE_H_ diff --git a/source/mygui-ogre/MyGUI_OgreRenderManager.cpp b/source/mygui-ogre/MyGUI_OgreRenderManager.cpp new file mode 100644 index 000000000..7f8755882 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreRenderManager.cpp @@ -0,0 +1,583 @@ +/*! + @file + @author Albert Semenov + @date 04/2008 +*/ + +#include "MyGUI_OgreDataManager.h" +#include "MyGUI_OgreRenderManager.h" +#include "MyGUI_OgreTexture.h" +#include "MyGUI_OgreVertexBuffer.h" +#include "MyGUI_LogManager.h" +#include "MyGUI_OgreDiagnostic.h" +#include "MyGUI_Timer.h" +#include "MyGUI_Gui.h" + +#include + +namespace MyGUI +{ + + OgreRenderManager& OgreRenderManager::getInstance() + { + return *getInstancePtr(); + } + OgreRenderManager* OgreRenderManager::getInstancePtr() + { + return static_cast(RenderManager::getInstancePtr()); + } + + OgreRenderManager::OgreRenderManager() : + mUpdate(false), + mSceneManager(nullptr), + mWindow(nullptr), + mActiveViewport(0), + mRenderSystem(nullptr), + mIsInitialise(false), + mManualRender(false), + mCountBatch(0) + { + } + + void OgreRenderManager::initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene) + { + MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice"); + MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName()); + + mSceneManager = nullptr; + mWindow = nullptr; + mUpdate = false; + mRenderSystem = nullptr; + mActiveViewport = 0; + + Ogre::Root* root = Ogre::Root::getSingletonPtr(); + if (root != nullptr) + setRenderSystem(root->getRenderSystem()); + setRenderWindow(_window); + setSceneManager(_scene); + + mMaterial = Ogre::MaterialManager::getSingleton().create("MyGUI/Default", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + mPass = mMaterial->getTechnique(0)->getPass(0); + mPass->setLightingEnabled(false); + mPass->setCullingMode(Ogre::CULL_NONE); + mPass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); + mPass->setDepthCheckEnabled(false); + mPass->setDepthWriteEnabled(false); + mPass->setVertexColourTracking(Ogre::TVC_DIFFUSE); + auto tu = mPass->createTextureUnitState(); + tu->setTextureAddressingMode(Ogre::TAM_CLAMP); + tu->setTextureFiltering(Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); + mMaterial->touch(); + + registerShader("Default", "MyGUI_Ogre_VP." + getShaderExtension(), "MyGUI_Ogre_FP." + getShaderExtension()); + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized"); + mIsInitialise = true; + } + + void OgreRenderManager::shutdown() + { + MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised"); + MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName()); + + destroyAllResources(); + + setSceneManager(nullptr); + setRenderWindow(nullptr); + setRenderSystem(nullptr); + + MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown"); + mIsInitialise = false; + } + + void OgreRenderManager::setRenderSystem(Ogre::RenderSystem* _render) + { + // отписываемся + if (mRenderSystem != nullptr) + { + mRenderSystem->removeListener(this); + mRenderSystem = nullptr; + } + + mRenderSystem = _render; + + // подписываемся на рендер евент + if (mRenderSystem != nullptr) + { + mRenderSystem->addListener(this); + + // формат цвета в вершинах + Ogre::VertexElementType vertex_type = mRenderSystem->getColourVertexElementType(); + if (vertex_type == Ogre::VET_COLOUR_ARGB) + mVertexFormat = VertexColourType::ColourARGB; + else if (vertex_type == Ogre::VET_COLOUR_ABGR) + mVertexFormat = VertexColourType::ColourABGR; + + updateRenderInfo(); + } + } + + Ogre::RenderSystem* OgreRenderManager::getRenderSystem() const + { + return mRenderSystem; + } + + void OgreRenderManager::setRenderWindow(Ogre::RenderWindow* _window) + { + mWindow = _window; + + if (mWindow != nullptr) + { + if (mWindow->getNumViewports() <= mActiveViewport && + !mWindow->getViewport(mActiveViewport)->getOverlaysEnabled()) + { + MYGUI_PLATFORM_LOG(Warning, "Overlays are disabled. MyGUI won't render in selected viewport."); + } + + windowResized(mWindow); + } + } + + void OgreRenderManager::setSceneManager(Ogre::SceneManager* _scene) + { + if (nullptr != mSceneManager) + { + mSceneManager->removeRenderQueueListener(this); + mSceneManager = nullptr; + } + + mSceneManager = _scene; + + if (nullptr != mSceneManager) + { + mSceneManager->addRenderQueueListener(this); + } + } + + void OgreRenderManager::setActiveViewport(unsigned short _num) + { + mActiveViewport = _num; + + if (mWindow != nullptr) + { + if (mWindow->getNumViewports() <= mActiveViewport) + { + MYGUI_PLATFORM_LOG(Error, "Invalid active viewport index selected. There is no viewport with given index."); + } + + // рассылка обновлений + windowResized(mWindow); + } + } + + void OgreRenderManager::renderQueueStarted( + Ogre::uint8 queueGroupId, + const Ogre::String& invocation, + bool& skipThisInvocation) + { + Gui* gui = Gui::getInstancePtr(); + if (gui == nullptr) + return; + + if (Ogre::RENDER_QUEUE_OVERLAY != queueGroupId) + return; + + Ogre::Viewport* viewport = mSceneManager->getCurrentViewport(); + if (nullptr == viewport + || !viewport->getOverlaysEnabled()) + return; + + if (mWindow->getNumViewports() <= mActiveViewport + || viewport != mWindow->getViewport(mActiveViewport)) + return; + + mCountBatch = 0; + + static Timer timer; + static unsigned long last_time = timer.getMilliseconds(); + unsigned long now_time = timer.getMilliseconds(); + unsigned long time = now_time - last_time; + + onFrameEvent(time / 1000.0f); + + last_time = now_time; + + begin(); + onRenderToTarget(this, mUpdate); + end(); + + // сбрасываем флаг + mUpdate = false; + } + + void OgreRenderManager::renderQueueEnded( + Ogre::uint8 queueGroupId, + const Ogre::String& invocation, + bool& repeatThisInvocation) + { + } + + void OgreRenderManager::eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters) + { + if (eventName == "DeviceLost") + { + } + else if (eventName == "DeviceRestored") + { + // обновить всех + mUpdate = true; + } + } + + IVertexBuffer* OgreRenderManager::createVertexBuffer() + { + return new OgreVertexBuffer(); + } + + void OgreRenderManager::destroyVertexBuffer(IVertexBuffer* _buffer) + { + delete _buffer; + } + + void OgreRenderManager::windowResized(Ogre::RenderWindow* _window) + { + if (_window->getNumViewports() > mActiveViewport) + { + Ogre::Viewport* port = _window->getViewport(mActiveViewport); +#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0 + Ogre::OrientationMode orient = port->getOrientationMode(); + if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270) + setViewSize(port->getActualHeight(), port->getActualWidth()); + else + setViewSize(port->getActualWidth(), port->getActualHeight()); +#else + setViewSize(port->getActualWidth(), port->getActualHeight()); +#endif + } + } + + void OgreRenderManager::updateRenderInfo() + { + if (mRenderSystem != nullptr) + { + if (mRenderSystem->getName() == "Direct3D11 Rendering Subsystem" || + mRenderSystem->getName() == "Direct3D9 Rendering Subsystem") // special case, it's not working with the value returned by the rendersystem + { + mInfo.maximumDepth = 0.0f; + } + else + { + mInfo.maximumDepth = mRenderSystem->getMaximumDepthInputValue(); + } + mInfo.hOffset = mRenderSystem->getHorizontalTexelOffset() / float(mViewSize.width); + mInfo.vOffset = mRenderSystem->getVerticalTexelOffset() / float(mViewSize.height); + mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width); + mInfo.pixScaleX = 1.0f / float(mViewSize.width); + mInfo.pixScaleY = 1.0f / float(mViewSize.height); + } + } + + void OgreRenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) + { + MYGUI_ASSERT(_texture != nullptr, "Rendering without texture is not supported"); + + OgreTexture* texture = static_cast(_texture); + + // If there is a shader set in the OgreTexture and it is different from the default one then use that shader for this render pass + OgreShaderInfo* shaderInfo = texture->getShaderInfo(); + if(shaderInfo != nullptr && (shaderInfo->vertexProgram != mDefaultShader->vertexProgram || shaderInfo->fragmentProgram != mDefaultShader->fragmentProgram)) + { + mRenderSystem->bindGpuProgram(texture->getShaderInfo()->vertexProgram->_getBindingDelegate()); + mRenderSystem->bindGpuProgram(texture->getShaderInfo()->fragmentProgram->_getBindingDelegate()); + + auto params = texture->getShaderInfo()->vertexProgram->getDefaultParameters(); + params->copyConstantsFrom(*mDefaultShader->vertexProgram->getDefaultParameters()); + mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, params, Ogre::GPV_ALL); + } + + OgreVertexBuffer* buffer = static_cast(_buffer); + auto renderOperation = buffer->getRenderOperation(); + renderOperation->vertexData->vertexCount = _count; + + mRenderSystem->_setTexture(0, true, texture->getOgreTexture()); + mRenderSystem->_render(*renderOperation); + + // Restore the default shader if it was changed previously + if (shaderInfo != nullptr && (shaderInfo->vertexProgram != mDefaultShader->vertexProgram || shaderInfo->fragmentProgram != mDefaultShader->fragmentProgram)) + { + mRenderSystem->bindGpuProgram(mDefaultShader->vertexProgram->_getBindingDelegate()); + mRenderSystem->bindGpuProgram(mDefaultShader->fragmentProgram->_getBindingDelegate()); + } + + ++mCountBatch; + } + + void OgreRenderManager::begin() + { + mSceneManager->_setPass(mPass); + + setShaderProjectionMatrix(false); + } + + void OgreRenderManager::end() + { + } + + ITexture* OgreRenderManager::createTexture(const std::string& _name) + { + MapTexture::const_iterator item = mTextures.find(_name); + MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist"); + + OgreTexture* texture = new OgreTexture(_name, OgreDataManager::getInstance().getGroup()); + mTextures[_name] = texture; + return texture; + } + + void OgreRenderManager::destroyTexture(ITexture* _texture) + { + if (_texture == nullptr) return; + + MapTexture::iterator item = mTextures.find(_texture->getName()); + MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found"); + + mTextures.erase(item); + delete _texture; + } + + ITexture* OgreRenderManager::getTexture(const std::string& _name) + { + if (_name.empty()) + return nullptr; + MapTexture::const_iterator item = mTextures.find(_name); + if (item == mTextures.end()) + { + Ogre::TexturePtr texture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName( + _name, + OgreDataManager::getInstance().getGroup()); + if (texture) + { + ITexture* result = createTexture(_name); + static_cast(result)->setOgreTexture(texture); + return result; + } + return nullptr; + } + return item->second; + } + + bool OgreRenderManager::isFormatSupported(PixelFormat _format, TextureUsage _usage) + { + return Ogre::TextureManager::getSingleton().isFormatSupported( + Ogre::TEX_TYPE_2D, + OgreTexture::convertFormat(_format), + OgreTexture::convertUsage(_usage)); + } + + void OgreRenderManager::destroyAllResources() + { + for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) + { + delete item->second; + } + mTextures.clear(); + + for (auto& shaderInfo : mRegisteredShaders) + { + delete shaderInfo.second; + } + mRegisteredShaders.clear(); + } + +#if MYGUI_DEBUG_MODE == 1 + bool OgreRenderManager::checkTexture(ITexture* _texture) + { + for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) + { + if (item->second == _texture) + return true; + } + return false; + } +#endif + + const IntSize& OgreRenderManager::getViewSize() const + { + return mViewSize; + } + + VertexColourType OgreRenderManager::getVertexFormat() const + { + return mVertexFormat; + } + + const RenderTargetInfo& OgreRenderManager::getInfo() const + { + return mInfo; + } + + size_t OgreRenderManager::getActiveViewport() const + { + return mActiveViewport; + } + + Ogre::RenderWindow* OgreRenderManager::getRenderWindow() const + { + return mWindow; + } + + bool OgreRenderManager::getManualRender() const + { + return mManualRender; + } + + void OgreRenderManager::setManualRender(bool _value) + { + mManualRender = _value; + } + + size_t OgreRenderManager::getBatchCount() const + { + return mCountBatch; + } + + void OgreRenderManager::setViewSize(int _width, int _height) + { + mViewSize.set(_width, _height); + mUpdate = true; + updateRenderInfo(); + onResizeView(mViewSize); + } + + void OgreRenderManager::registerShader( + const std::string& _shaderName, + const std::string& _vertexProgramFile, + const std::string& _fragmentProgramFile) + { + MYGUI_PLATFORM_LOG(Info, "* OgreRenderManager::registerShader(): " << _shaderName); + auto iter = mRegisteredShaders.find(_shaderName); + if (iter != mRegisteredShaders.end()) + { + delete iter->second; + } + mRegisteredShaders[_shaderName] = createShader(_shaderName, _vertexProgramFile, _fragmentProgramFile); + if (_shaderName == "Default") + { + mDefaultShader = mRegisteredShaders[_shaderName]; + + // Set the default shader + mPass->setVertexProgram(mDefaultShader->vertexProgram->getName()); + mPass->setFragmentProgram(mDefaultShader->fragmentProgram->getName()); + } + } + + std::string OgreRenderManager::getShaderExtension() const + { + std::string shaderLanguage; + if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsl")) + return "glsl"; + else if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("glsles")) + return "glsles"; + else if (Ogre::HighLevelGpuProgramManager::getSingleton().isLanguageSupported("hlsl")) + return "hlsl"; + MYGUI_EXCEPT("No supported shader was found. Only glsl, glsles and hlsl are implemented so far."); + } + + void OgreRenderManager::beginRttRender(bool isFlippedTexture) + { + mSceneManager->_setPass(mPass); // required only by DirectX11 render system + setShaderProjectionMatrix(isFlippedTexture); + } + + void OgreRenderManager::endRttRender() + { + setShaderProjectionMatrix(false); + mSceneManager->_setPass(mPass); // required only by DirectX11 render system + } + + void OgreRenderManager::doRenderRtt(IVertexBuffer* _buffer, ITexture* _texture, size_t _count, Ogre::RenderTexture* rtt) + { + doRender(_buffer, _texture, _count); + } + + OgreShaderInfo* OgreRenderManager::getShaderInfo(const std::string& _shaderName) const + { + auto iter = mRegisteredShaders.find(_shaderName); + if (iter != mRegisteredShaders.end()) + return iter->second; + MYGUI_PLATFORM_LOG(Error, "Failed to get shader info for shader '" << _shaderName << "'. Did you forgot to register shader?"); + return nullptr; + } + + OgreShaderInfo* OgreRenderManager::createShader( + const std::string& _shaderName, + const std::string& _vertexProgramFile, + const std::string& _fragmentProgramFile) + { + OgreShaderInfo* shaderInfo = new OgreShaderInfo(); + + std::string shaderLanguage = getShaderExtension(); + + shaderInfo->vertexProgram = Ogre::HighLevelGpuProgramManager::getSingleton().getByName( + _vertexProgramFile, + OgreDataManager::getInstance().getGroup()); + if (!shaderInfo->vertexProgram) + { + MYGUI_ASSERT(DataManager::getInstance().isDataExist(_vertexProgramFile), "Shader file '" << _vertexProgramFile << "' is missing."); + shaderInfo->vertexProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( + _vertexProgramFile, + OgreDataManager::getInstance().getGroup(), + shaderLanguage, + Ogre::GPT_VERTEX_PROGRAM); + shaderInfo->vertexProgram->setSourceFile(_vertexProgramFile); + if (shaderLanguage == "hlsl") + { + shaderInfo->vertexProgram->setParameter("target", "vs_3_0"); + shaderInfo->vertexProgram->setParameter("entry_point", "main"); + } + + shaderInfo->vertexProgram->load(); + } + + shaderInfo->fragmentProgram = Ogre::HighLevelGpuProgramManager::getSingleton().getByName( + _fragmentProgramFile, + OgreDataManager::getInstance().getGroup()); + if (!shaderInfo->fragmentProgram) + { + MYGUI_ASSERT(DataManager::getInstance().isDataExist(_fragmentProgramFile), "Shader file '" << _vertexProgramFile << "' is missing."); + shaderInfo->fragmentProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram( + _fragmentProgramFile, + OgreDataManager::getInstance().getGroup(), + shaderLanguage, + Ogre::GPT_FRAGMENT_PROGRAM); + shaderInfo->fragmentProgram->setSourceFile(_fragmentProgramFile); + if (shaderLanguage == "hlsl") + { + shaderInfo->fragmentProgram->setParameter("target", "ps_3_0"); + shaderInfo->fragmentProgram->setParameter("entry_point", "main"); + } + + shaderInfo->fragmentProgram->load(); + } + + return shaderInfo; + } + + void OgreRenderManager::setShaderProjectionMatrix(bool isFlipped) + { + Ogre::Matrix4 projectionMatrix; + mRenderSystem->_convertProjectionMatrix(Ogre::Matrix4::IDENTITY, projectionMatrix, true); + + if (isFlipped) + { + projectionMatrix[1][0] = -projectionMatrix[1][0]; + projectionMatrix[1][1] = -projectionMatrix[1][1]; + projectionMatrix[1][2] = -projectionMatrix[1][2]; + projectionMatrix[1][3] = -projectionMatrix[1][3]; + } + + Ogre::GpuProgramParametersSharedPtr params = mDefaultShader->vertexProgram->getDefaultParameters(); + params->setNamedConstant("worldViewProj", projectionMatrix * Ogre::Affine3::IDENTITY); + mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, params, Ogre::GPV_ALL); + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreRenderManager.h b/source/mygui-ogre/MyGUI_OgreRenderManager.h new file mode 100644 index 000000000..df57b9ac5 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreRenderManager.h @@ -0,0 +1,177 @@ +/*! + @file + @author Albert Semenov + @date 04/2008 +*/ + +#ifndef MYGUI_OGRE_RENDER_MANAGER_H_ +#define MYGUI_OGRE_RENDER_MANAGER_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_RenderFormat.h" +#include "MyGUI_IVertexBuffer.h" +#include "MyGUI_RenderManager.h" + +#include +#include +#include + +namespace MyGUI +{ + + struct OgreShaderInfo + { + Ogre::HighLevelGpuProgramPtr vertexProgram; + Ogre::HighLevelGpuProgramPtr fragmentProgram; + }; + + class OgreRenderManager : + public RenderManager, + public IRenderTarget, + public Ogre::RenderQueueListener, + public Ogre::RenderSystem::Listener + { + public: + OgreRenderManager(); + + void initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene); + void shutdown(); + + static OgreRenderManager& getInstance(); + static OgreRenderManager* getInstancePtr(); + + /** @see RenderManager::getViewSize */ + const IntSize& getViewSize() const override; + + /** @see RenderManager::getVertexFormat */ + VertexColourType getVertexFormat() const override; + + /** @see RenderManager::createVertexBuffer */ + IVertexBuffer* createVertexBuffer() override; + /** @see RenderManager::destroyVertexBuffer */ + void destroyVertexBuffer(IVertexBuffer* _buffer) override; + + /** @see RenderManager::createTexture */ + ITexture* createTexture(const std::string& _name) override; + /** @see RenderManager::destroyTexture */ + void destroyTexture(ITexture* _texture) override; + /** @see RenderManager::getTexture */ + ITexture* getTexture(const std::string& _name) override; + + /** @see RenderManager::isFormatSupported */ + bool isFormatSupported(PixelFormat _format, TextureUsage _usage) override; + + /** @see IRenderTarget::begin */ + void begin() override; + /** @see IRenderTarget::end */ + void end() override; + + /** @see IRenderTarget::doRender */ + void doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) override; + + /** @see IRenderTarget::getInfo */ + const RenderTargetInfo& getInfo() const override; + + void setRenderSystem(Ogre::RenderSystem* _render); + Ogre::RenderSystem* getRenderSystem() const; + + void setRenderWindow(Ogre::RenderWindow* _window); + + /** Set scene manager where MyGUI will be rendered */ + void setSceneManager(Ogre::SceneManager* _scene); + + /** Get GUI viewport index */ + size_t getActiveViewport() const; + + /** Set GUI viewport index */ + void setActiveViewport(unsigned short _num); + + Ogre::RenderWindow* getRenderWindow() const; + + bool getManualRender() const; + void setManualRender(bool _value); + + size_t getBatchCount() const; + + /** @see RenderManager::setViewSize */ + void setViewSize(int _width, int _height) override; + + /** @see RenderManager::registerShader */ + void registerShader( + const std::string& _shaderName, + const std::string& _vertexProgramFile, + const std::string& _fragmentProgramFile) override; + +#if MYGUI_DEBUG_MODE == 1 + virtual bool checkTexture(ITexture* _texture); +#endif + + std::string getShaderExtension() const; + + /*internal:*/ + /* for use with RTT */ + void beginRttRender(bool isFlippedTexture); + void endRttRender(); + void doRenderRtt(IVertexBuffer* _buffer, ITexture* _texture, size_t _count, Ogre::RenderTexture* rtt); + OgreShaderInfo* getShaderInfo(const std::string& _shaderName) const; + + private: + void renderQueueStarted( + Ogre::uint8 queueGroupId, + const Ogre::String& invocation, + bool& skipThisInvocation) override; + void renderQueueEnded( + Ogre::uint8 queueGroupId, + const Ogre::String& invocation, + bool& repeatThisInvocation) override; + virtual void windowResized(Ogre::RenderWindow* _window); + + // restore buffers + void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters) override; + + void destroyAllResources(); + void updateRenderInfo(); + + OgreShaderInfo* createShader( + const std::string& _shaderName, + const std::string& _vertexProgramFile, + const std::string& _fragmentProgramFile); + + void setShaderProjectionMatrix(bool isFlipped); + + private: + // флаг для обновления всех и вся + bool mUpdate; + + IntSize mViewSize; + + Ogre::SceneManager* mSceneManager; + + VertexColourType mVertexFormat; + + // окно, на которое мы подписываемся для изменения размеров + Ogre::RenderWindow* mWindow; + + // вьюпорт, с которым работает система + unsigned short mActiveViewport; + + Ogre::RenderSystem* mRenderSystem; + RenderTargetInfo mInfo; + + typedef std::map MapTexture; + MapTexture mTextures; + + bool mIsInitialise; + bool mManualRender; + size_t mCountBatch; + + OgreShaderInfo* mDefaultShader = nullptr; + std::map mRegisteredShaders; + + Ogre::MaterialPtr mMaterial; + Ogre::Pass* mPass; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_RENDER_MANAGER_H_ diff --git a/source/mygui-ogre/MyGUI_OgreTexture.cpp b/source/mygui-ogre/MyGUI_OgreTexture.cpp new file mode 100644 index 000000000..55bacebe0 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreTexture.cpp @@ -0,0 +1,307 @@ +/*! + @file + @author Albert Semenov + @date 04/2009 +*/ + +#include +#include "MyGUI_OgreTexture.h" +#include "MyGUI_DataManager.h" +#include "MyGUI_OgreRenderManager.h" +#include "MyGUI_OgreDiagnostic.h" +#include "MyGUI_OgreRTTexture.h" +#include "MyGUI_OgreDataManager.h" +#include + +namespace MyGUI +{ + + OgreTexture::OgreTexture(const std::string& _name, const std::string& _group) : + mName(_name), + mGroup(_group), + mNumElemBytes(0), + mPixelFormat(Ogre::PF_UNKNOWN), + mUsage(Ogre::TU_DEFAULT), + mListener(nullptr), + mRenderTarget(nullptr) + { + mTmpData.data = nullptr; + } + + OgreTexture::~OgreTexture() + { + destroy(); + } + + const std::string& OgreTexture::getName() const + { + return mName; + } + + void OgreTexture::saveToFile(const std::string& _filename) + { + Ogre::uchar* readrefdata = static_cast(lock(TextureUsage::Read)); + + Ogre::Image img; + img = img.loadDynamicImage(readrefdata, mTexture->getWidth(), mTexture->getHeight(), mTexture->getFormat()); + img.save(_filename); + + unlock(); + } + + void OgreTexture::setShader(const std::string& _shaderName) + { + mShaderInfo = OgreRenderManager::getInstance().getShaderInfo(_shaderName); + } + + void OgreTexture::setInvalidateListener(ITextureInvalidateListener* _listener) + { + mListener = _listener; + } + + void OgreTexture::destroy() + { + if (mTmpData.data != nullptr) + { + delete[] (uint8*)mTmpData.data; + mTmpData.data = nullptr; + } + + if (mRenderTarget != nullptr) + { + delete mRenderTarget; + mRenderTarget = nullptr; + } + + if (mTexture) + { + Ogre::TextureManager::getSingleton().remove(mTexture->getHandle()); + mTexture.reset(); + } + } + + int OgreTexture::getWidth() const + { + return (int)mTexture->getWidth(); + } + + int OgreTexture::getHeight() const + { + return (int)mTexture->getHeight(); + } + + void* OgreTexture::lock(TextureUsage _access) + { + if (_access == TextureUsage::Write) + { + return mTexture->getBuffer()->lock(Ogre::HardwareBuffer::HBL_WRITE_ONLY); + } + + // здесь проверить режим создания, и возможно так залочить без пиксель бокса + + // для чтения копируем в пиксель бокс + if (mTmpData.data != nullptr) + { + delete[] (uint8*)mTmpData.data; + mTmpData.data = nullptr; + } + + mTmpData = Ogre::PixelBox( + mTexture->getWidth(), + mTexture->getHeight(), + mTexture->getDepth(), + mTexture->getFormat()); + mTmpData.data = new uint8[mTexture->getBuffer()->getSizeInBytes()]; + + mTexture->getBuffer()->blitToMemory(mTmpData); + + return mTmpData.data; + } + + void OgreTexture::unlock() + { + if (mTexture->getBuffer()->isLocked()) + { + mTexture->getBuffer()->unlock(); + } + else if (mTmpData.data != nullptr) + { + delete[] (uint8*)mTmpData.data; + mTmpData.data = nullptr; + } + } + + bool OgreTexture::isLocked() const + { + return mTexture->getBuffer()->isLocked(); + } + + Ogre::TextureUsage OgreTexture::convertUsage(TextureUsage _usage) + { + if (_usage == TextureUsage::Default) + { + return Ogre::TU_STATIC_WRITE_ONLY; + } + else if (_usage == TextureUsage::RenderTarget) + { + return Ogre::TU_RENDERTARGET; + } + else if (_usage.isValue(TextureUsage::Static)) + { + if (_usage.isValue(TextureUsage::Write)) + { + return Ogre::TU_STATIC_WRITE_ONLY; + } + else + { + return Ogre::TU_STATIC; + } + } + else if (_usage.isValue(TextureUsage::Dynamic)) + { + if (_usage.isValue(TextureUsage::Write)) + { + return Ogre::TU_DYNAMIC_WRITE_ONLY; + } + else + { + return Ogre::TU_DYNAMIC; + } + } + else if (_usage.isValue(TextureUsage::Stream)) + { + if (_usage.isValue(TextureUsage::Write)) + { + return Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE; + } + else + { + return Ogre::TU_DYNAMIC; + } + } + return Ogre::TU_DEFAULT; + } + + Ogre::PixelFormat OgreTexture::convertFormat(PixelFormat _format) + { + if (_format == PixelFormat::L8) return Ogre::PF_BYTE_L; + else if (_format == PixelFormat::L8A8) return Ogre::PF_BYTE_LA; + else if (_format == PixelFormat::R8G8B8) return Ogre::PF_R8G8B8; + else if (_format == PixelFormat::R8G8B8A8) return Ogre::PF_A8R8G8B8; + + return Ogre::PF_UNKNOWN; + } + + void OgreTexture::setFormat(PixelFormat _format) + { + mOriginalFormat = _format; + mPixelFormat = convertFormat(_format); + mNumElemBytes = _format.getBytesPerPixel(); + } + + void OgreTexture::setUsage(TextureUsage _usage) + { + mOriginalUsage = _usage; + mUsage = convertUsage(_usage); + } + + void OgreTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format) + { + setFormat(_format); + setUsage(_usage); + + mTexture = Ogre::TextureManager::getSingleton().createManual( + mName, + mGroup, + Ogre::TEX_TYPE_2D, + _width, + _height, + 0, + mPixelFormat, + mUsage, + this); + + mTexture->load(); + + } + + void OgreTexture::loadFromFile(const std::string& _filename) + { + setUsage(TextureUsage::Default); + + auto createResult = Ogre::TextureManager::getSingleton().createOrRetrieve( + _filename, + OgreDataManager::getInstance().getGroup(), + false, + nullptr, + nullptr, + Ogre::TEX_TYPE_2D, + 0); + if (!createResult.second) + { + MYGUI_PLATFORM_LOG(Error, "Texture '" + _filename + "' not found, set default texture"); + } + else + { + mTexture = std::static_pointer_cast(createResult.first); + if (!mTexture->isLoaded()) + mTexture->load(); + } + + setFormatByOgreTexture(); + } + + void OgreTexture::setFormatByOgreTexture() + { + mOriginalFormat = PixelFormat::Unknow; + mPixelFormat = Ogre::PF_UNKNOWN; + mNumElemBytes = 0; + + if (mTexture) + { + mPixelFormat = mTexture->getFormat(); + + if (mPixelFormat == Ogre::PF_BYTE_L) + { + mOriginalFormat = PixelFormat::L8; + mNumElemBytes = 1; + } + else if (mPixelFormat == Ogre::PF_BYTE_LA) + { + mOriginalFormat = PixelFormat::L8A8; + mNumElemBytes = 2; + } + else if (mPixelFormat == Ogre::PF_R8G8B8) + { + mOriginalFormat = PixelFormat::R8G8B8; + mNumElemBytes = 3; + } + else if (mPixelFormat == Ogre::PF_A8R8G8B8) + { + mOriginalFormat = PixelFormat::R8G8B8A8; + mNumElemBytes = 4; + } + else + { + mOriginalFormat = PixelFormat::Unknow; + mNumElemBytes = Ogre::PixelUtil::getNumElemBytes(mPixelFormat); + } + + } + } + + void OgreTexture::loadResource(Ogre::Resource* resource) + { + if (mListener) + mListener->textureInvalidate(this); + } + + IRenderTarget* OgreTexture::getRenderTarget() + { + if (mRenderTarget == nullptr) + mRenderTarget = new OgreRTTexture(mTexture); + + return mRenderTarget; + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreTexture.h b/source/mygui-ogre/MyGUI_OgreTexture.h new file mode 100644 index 000000000..062987f6b --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreTexture.h @@ -0,0 +1,106 @@ +/*! + @file + @author Albert Semenov + @date 04/2009 +*/ + +#ifndef MYGUI_OGRE_TEXTURE_H_ +#define MYGUI_OGRE_TEXTURE_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_ITexture.h" +#include "MyGUI_RenderFormat.h" + +#include +#include + +namespace MyGUI +{ + + struct OgreShaderInfo; + + class OgreTexture : + public ITexture, + public Ogre::ManualResourceLoader + { + public: + OgreTexture(const std::string& _name, const std::string& _group); + ~OgreTexture() override; + + const std::string& getName() const override; + + void createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format) override; + void loadFromFile(const std::string& _filename) override; + void saveToFile(const std::string& _filename) override; + void setShader(const std::string& _shaderName) override; + + void setInvalidateListener(ITextureInvalidateListener* _listener) override; + + void destroy() override; + + void* lock(TextureUsage _access) override; + void unlock() override; + bool isLocked() const override; + + int getWidth() const override; + int getHeight() const override; + + PixelFormat getFormat() const override + { + return mOriginalFormat; + } + TextureUsage getUsage() const override + { + return mOriginalUsage; + } + size_t getNumElemBytes() const override + { + return mNumElemBytes; + } + + IRenderTarget* getRenderTarget() override; + + static Ogre::TextureUsage convertUsage(TextureUsage _usage); + static Ogre::PixelFormat convertFormat(PixelFormat _format); + /*internal:*/ + Ogre::TexturePtr getOgreTexture() + { + return mTexture; + } + void setOgreTexture(Ogre::TexturePtr _value) + { + mTexture = _value; + } + OgreShaderInfo* getShaderInfo() const + { + return mShaderInfo; + } + + private: + void setUsage(TextureUsage _usage); + void setFormat(PixelFormat _format); + void setFormatByOgreTexture(); + + void loadResource(Ogre::Resource* resource) override; + + private: + Ogre::TexturePtr mTexture; + OgreShaderInfo* mShaderInfo = nullptr; + std::string mName; + std::string mGroup; + + TextureUsage mOriginalUsage; + PixelFormat mOriginalFormat; + size_t mNumElemBytes; + + Ogre::PixelFormat mPixelFormat; + Ogre::TextureUsage mUsage; + + ITextureInvalidateListener* mListener; + IRenderTarget* mRenderTarget; + Ogre::PixelBox mTmpData; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_TEXTURE_H_ diff --git a/source/mygui-ogre/MyGUI_OgreVertexBuffer.cpp b/source/mygui-ogre/MyGUI_OgreVertexBuffer.cpp new file mode 100644 index 000000000..440895439 --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreVertexBuffer.cpp @@ -0,0 +1,91 @@ +/*! + @file + @author Albert Semenov + @date 04/2009 +*/ + +#include "MyGUI_OgreVertexBuffer.h" + +#include + +namespace MyGUI +{ + + const size_t VERTEX_BUFFER_REALLOCK_STEP = 5 * VertexQuad::VertexCount; + + OgreVertexBuffer::OgreVertexBuffer() : + mVertexCount(0), + mNeedVertexCount(0) + { + } + + OgreVertexBuffer::~OgreVertexBuffer() + { + destroy(); + } + + void OgreVertexBuffer::create() + { + mRenderOperation.vertexData = new Ogre::VertexData(); + mRenderOperation.vertexData->vertexStart = 0; + + Ogre::VertexDeclaration* vd = mRenderOperation.vertexData->vertexDeclaration; + vd->addElement(0, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); + vd->addElement(0, Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); + vd->addElement( + 0, + Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3) + Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), + Ogre::VET_FLOAT2, + Ogre::VES_TEXTURE_COORDINATES); + + // Create the Vertex Buffer, using the Vertex Structure we previously declared in _declareVertexStructure. + mVertexBuffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( + mRenderOperation.vertexData->vertexDeclaration->getVertexSize(0), // declared Vertex used + mVertexCount, + Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, + false); + + // Bind the created buffer to the renderOperation object. Now we can manipulate the buffer, and the RenderOp keeps the changes. + mRenderOperation.vertexData->vertexBufferBinding->setBinding(0, mVertexBuffer); + mRenderOperation.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; + mRenderOperation.useIndexes = false; + } + + void OgreVertexBuffer::destroy() + { + delete mRenderOperation.vertexData; + mRenderOperation.vertexData = nullptr; + mVertexBuffer.reset(); + } + + void OgreVertexBuffer::resize() + { + mVertexCount = mNeedVertexCount + VERTEX_BUFFER_REALLOCK_STEP; + destroy(); + create(); + } + + void OgreVertexBuffer::setVertexCount(size_t _count) + { + mNeedVertexCount = _count; + } + + size_t OgreVertexBuffer::getVertexCount() const + { + return mNeedVertexCount; + } + + Vertex* OgreVertexBuffer::lock() + { + if (mNeedVertexCount > mVertexCount || mVertexCount == 0) + resize(); + + return reinterpret_cast(mVertexBuffer->lock(Ogre::HardwareVertexBuffer::HBL_DISCARD)); + } + + void OgreVertexBuffer::unlock() + { + mVertexBuffer->unlock(); + } + +} // namespace MyGUI diff --git a/source/mygui-ogre/MyGUI_OgreVertexBuffer.h b/source/mygui-ogre/MyGUI_OgreVertexBuffer.h new file mode 100644 index 000000000..2d3a93aed --- /dev/null +++ b/source/mygui-ogre/MyGUI_OgreVertexBuffer.h @@ -0,0 +1,53 @@ +/*! + @file + @author Albert Semenov + @date 04/2009 +*/ + +#ifndef MYGUI_OGRE_VERTEX_BUFFER_H_ +#define MYGUI_OGRE_VERTEX_BUFFER_H_ + +#include "MyGUI_Prerequest.h" +#include "MyGUI_IVertexBuffer.h" + +#include +#include +#include + +namespace MyGUI +{ + + class OgreVertexBuffer : + public IVertexBuffer + { + public: + OgreVertexBuffer(); + ~OgreVertexBuffer() override; + + void setVertexCount(size_t _count) override; + size_t getVertexCount() const override; + + Vertex* lock() override; + void unlock() override; + + Ogre::RenderOperation* getRenderOperation() + { + return &mRenderOperation; + } + + private: + void create(); + void destroy(); + void resize(); + + private: + size_t mVertexCount; + size_t mNeedVertexCount; + + Ogre::RenderOperation mRenderOperation; + Ogre::HardwareVertexBufferSharedPtr mVertexBuffer; + }; + +} // namespace MyGUI + +#endif // MYGUI_OGRE_VERTEX_BUFFER_H_ diff --git a/source/ogre/BaseApp.h b/source/ogre/BaseApp.h index fa380dab1..c7ddd5b38 100644 --- a/source/ogre/BaseApp.h +++ b/source/ogre/BaseApp.h @@ -149,13 +149,8 @@ class BaseApp : public BGui, Img bckLoad, bckLoadBar, barLoad, imgLoad; Txt txLoadBig, txLoad; int barSizeX, barSizeY; - - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - MyGUI::OgreD3D11Platform* mPlatform; - #else MyGUI::OgrePlatform* mPlatform; - #endif /// main menu // pSet->inMenu WP mWndMainPanels[ciMainBtns]; diff --git a/source/ogre/BaseApp_Create.cpp b/source/ogre/BaseApp_Create.cpp index 03e40cf85..f290c8056 100644 --- a/source/ogre/BaseApp_Create.cpp +++ b/source/ogre/BaseApp_Create.cpp @@ -24,7 +24,6 @@ #include #include -#include "common/MyGUI_D3D11.h" #include #include @@ -680,11 +679,7 @@ void BaseApp::windowClosed() void BaseApp::baseInitGui() { using namespace MyGUI; - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - mPlatform = new MyGUI::OgreD3D11Platform(); - #else mPlatform = new MyGUI::OgrePlatform(); - #endif mPlatform->initialise(mWindow, mSceneMgr, "General", PATHMANAGER::UserConfigDir() + "/MyGUI.log"); mGui = new MyGUI::Gui(); diff --git a/source/ogre/SceneInit.cpp b/source/ogre/SceneInit.cpp index cf7241e63..2b3b1dc2d 100644 --- a/source/ogre/SceneInit.cpp +++ b/source/ogre/SceneInit.cpp @@ -22,7 +22,6 @@ #include "../shiny/Main/Factory.hpp" #include #include -#include "common/MyGUI_D3D11.h" #include #include #include diff --git a/source/ogre/common/Gui_Popup.cpp b/source/ogre/common/Gui_Popup.cpp index 33398f461..c38cc98fa 100644 --- a/source/ogre/common/Gui_Popup.cpp +++ b/source/ogre/common/Gui_Popup.cpp @@ -5,7 +5,6 @@ #include #include -#include "MyGUI_D3D11.h" #include #include #include diff --git a/source/ogre/common/Gui_Popup.h b/source/ogre/common/Gui_Popup.h index b52f7d997..e96d672cb 100644 --- a/source/ogre/common/Gui_Popup.h +++ b/source/ogre/common/Gui_Popup.h @@ -45,12 +45,8 @@ class GuiPopup GuiPopup(); MyGUI::Gui* mGui; - - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - MyGUI::OgreD3D11Platform* mPlatform; - #else + MyGUI::OgrePlatform* mPlatform; - #endif protected: void ButtonClick(MyGUI::Widget*); diff --git a/source/ogre/common/MyGUI_D3D11.cpp b/source/ogre/common/MyGUI_D3D11.cpp deleted file mode 100644 index db13cda12..000000000 --- a/source/ogre/common/MyGUI_D3D11.cpp +++ /dev/null @@ -1,584 +0,0 @@ -#include "pch.h" -#include "MyGUI_Prerequest.h" -#include "MyGUI_OgreDataManager.h" -#include "MyGUI_OgreRenderManager.h" -#include "MyGUI_OgreTexture.h" -#include "MyGUI_OgreVertexBuffer.h" -#include "MyGUI_LogManager.h" -#include "MyGUI_OgreDiagnostic.h" -#include "MyGUI_Timer.h" -#include "MyGUI_Gui.h" -#include "MyGUI_D3D11.h" - -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - -namespace MyGUI -{ - OgreD3D11RenderManager& OgreD3D11RenderManager::getInstance() - { - return *getInstancePtr(); - } - OgreD3D11RenderManager* OgreD3D11RenderManager::getInstancePtr() - { - return static_cast(RenderManager::getInstancePtr()); - } - - OgreD3D11RenderManager::OgreD3D11RenderManager() : - mUpdate(false), - mSceneManager(nullptr), - mWindow(nullptr), - mActiveViewport(0), - mRenderSystem(nullptr), - mIsInitialise(false), - mManualRender(false), - mCountBatch(0), - bUseShaders(false) - { - } - - OgreD3D11RenderManager::~OgreD3D11RenderManager() - { - - } - - void OgreD3D11RenderManager::initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene) - { - MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice"); - MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName()); - - mColorBlendMode.blendType = Ogre::LBT_COLOUR; - mColorBlendMode.source1 = Ogre::LBS_TEXTURE; - mColorBlendMode.source2 = Ogre::LBS_DIFFUSE; - mColorBlendMode.operation = Ogre::LBX_MODULATE; - - mAlphaBlendMode.blendType = Ogre::LBT_ALPHA; - mAlphaBlendMode.source1 = Ogre::LBS_TEXTURE; - mAlphaBlendMode.source2 = Ogre::LBS_DIFFUSE; - mAlphaBlendMode.operation = Ogre::LBX_MODULATE; - - mTextureAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP; - mTextureAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP; - mTextureAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP; - - mSceneManager = nullptr; - mWindow = nullptr; - mUpdate = false; - mRenderSystem = nullptr; - mActiveViewport = 0; - - mDefaultVertexProgram = createDefaultVertexProgram(); - mDefaultFragmentProgram = createDefaultFragmentProgram(); - mDefaultFragmentProgramWith1Texture = createDefaultFragmentProgramWith1Texture(); - if(mDefaultVertexProgram != 0 && mDefaultFragmentProgram != 0 && mDefaultFragmentProgramWith1Texture != 0) - { - bUseShaders = true; - } - - Ogre::Root* root = Ogre::Root::getSingletonPtr(); - if (root != nullptr) - setRenderSystem(root->getRenderSystem()); - setRenderWindow(_window); - setSceneManager(_scene); - - MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized"); - mIsInitialise = true; - } - - void OgreD3D11RenderManager::shutdown() - { - MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised"); - MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName()); - - destroyAllResources(); - - setSceneManager(nullptr); - setRenderWindow(nullptr); - setRenderSystem(nullptr); - - MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown"); - mIsInitialise = false; - } - - void OgreD3D11RenderManager::setRenderSystem(Ogre::RenderSystem* _render) - { - // отписываемся - if (mRenderSystem != nullptr) - { - mRenderSystem->removeListener(this); - mRenderSystem = nullptr; - } - - mRenderSystem = _render; - - // подписываемся на рендер евент - if (mRenderSystem != nullptr) - { - mRenderSystem->addListener(this); - - // формат цвета в вершинах - Ogre::VertexElementType vertex_type = mRenderSystem->getColourVertexElementType(); - if (vertex_type == Ogre::VET_COLOUR_ARGB) - mVertexFormat = VertexColourType::ColourARGB; - else if (vertex_type == Ogre::VET_COLOUR_ABGR) - mVertexFormat = VertexColourType::ColourABGR; - - updateRenderInfo(); - } - } - - Ogre::RenderSystem* OgreD3D11RenderManager::getRenderSystem() - { - return mRenderSystem; - } - - void OgreD3D11RenderManager::setRenderWindow(Ogre::RenderWindow* _window) - { - // отписываемся - if (mWindow != nullptr) - { - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this); - mWindow = nullptr; - } - - mWindow = _window; - - if (mWindow != nullptr) - { - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this); - windowResized(mWindow); - } - } - - void OgreD3D11RenderManager::setSceneManager(Ogre::SceneManager* _scene) - { - if (nullptr != mSceneManager) - { - mSceneManager->removeRenderQueueListener(this); - mSceneManager = nullptr; - } - - mSceneManager = _scene; - - if (nullptr != mSceneManager) - { - mSceneManager->addRenderQueueListener(this); - } - } - - void OgreD3D11RenderManager::setActiveViewport(unsigned short _num) - { - mActiveViewport = _num; - - if (mWindow != nullptr) - { - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this); - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this); - - // рассылка обновлений - windowResized(mWindow); - } - } - - void OgreD3D11RenderManager::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation) - { - Gui* gui = Gui::getInstancePtr(); - if (gui == nullptr) - return; - - if (Ogre::RENDER_QUEUE_OVERLAY != queueGroupId) - return; - - Ogre::Viewport* viewport = mSceneManager->getCurrentViewport(); - if (nullptr == viewport - || !viewport->getOverlaysEnabled()) - return; - - if (mWindow->getNumViewports() <= mActiveViewport - || viewport != mWindow->getViewport(mActiveViewport)) - return; - - mCountBatch = 0; - - static Timer timer; - static unsigned long last_time = timer.getMilliseconds(); - unsigned long now_time = timer.getMilliseconds(); - unsigned long time = now_time - last_time; - - onFrameEvent((float)((double)(time) / (double)1000)); - - last_time = now_time; - - //begin(); - setManualRender(true); - onRenderToTarget(this, mUpdate); - //end(); - - // сбрасываем флаг - mUpdate = false; - } - - void OgreD3D11RenderManager::renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation) - { - } - - void OgreD3D11RenderManager::eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters) - { - if (eventName == "DeviceLost") - { - } - else if (eventName == "DeviceRestored") - { - // обновить всех - mUpdate = true; - } - } - - IVertexBuffer* OgreD3D11RenderManager::createVertexBuffer() - { - return new OgreVertexBuffer(); - } - - void OgreD3D11RenderManager::destroyVertexBuffer(IVertexBuffer* _buffer) - { - delete _buffer; - } - - // для оповещений об изменении окна рендера - void OgreD3D11RenderManager::windowResized(Ogre::RenderWindow* _window) - { - if (_window->getNumViewports() > mActiveViewport) - { - Ogre::Viewport* port = _window->getViewport(mActiveViewport); -#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0 - Ogre::OrientationMode orient = port->getOrientationMode(); - if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270) - mViewSize.set(port->getActualHeight(), port->getActualWidth()); - else - mViewSize.set(port->getActualWidth(), port->getActualHeight()); -#else - mViewSize.set(port->getActualWidth(), port->getActualHeight()); -#endif - - // обновить всех - mUpdate = true; - - updateRenderInfo(); - - onResizeView(mViewSize); - } - } - - void OgreD3D11RenderManager::updateRenderInfo() - { - if (mRenderSystem != nullptr) - { - mInfo.maximumDepth = mRenderSystem->getMaximumDepthInputValue(); - mInfo.hOffset = mRenderSystem->getHorizontalTexelOffset() / float(mViewSize.width); - mInfo.vOffset = mRenderSystem->getVerticalTexelOffset() / float(mViewSize.height); - mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width); - mInfo.pixScaleX = 1.0f / float(mViewSize.width); - mInfo.pixScaleY = 1.0f / float(mViewSize.height); - } - } - - void OgreD3D11RenderManager::doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count) - { - if (getManualRender()) - { - begin(); - setManualRender(false); - } - - if (_texture) - { - if(bUseShaders) - { - mRenderSystem->bindGpuProgram(mDefaultFragmentProgramWith1Texture); - } - OgreTexture* texture = static_cast(_texture); - Ogre::TexturePtr texture_ptr = texture->getOgreTexture(); - if (!texture_ptr.isNull()) - { - mRenderSystem->_setTexture(0, true, texture_ptr); - mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); - } - } - else - { - if(bUseShaders) - { - mRenderSystem->bindGpuProgram(mDefaultFragmentProgram); - } - } - - OgreVertexBuffer* buffer = static_cast(_buffer); - Ogre::RenderOperation* operation = buffer->getRenderOperation(); - operation->vertexData->vertexCount = _count; - - mRenderSystem->_render(*operation); - - ++ mCountBatch; - } - - void OgreD3D11RenderManager::begin() - { - // set-up matrices - mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY); - mRenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY); - -#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0 - Ogre::OrientationMode orient = mWindow->getViewport(mActiveViewport)->getOrientationMode(); - mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY * Ogre::Quaternion(Ogre::Degree(orient * 90.f), Ogre::Vector3::UNIT_Z)); -#else - mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY); -#endif - - // initialise render settings - mRenderSystem->setLightingEnabled(false); - mRenderSystem->_setDepthBufferParams(false, false); - mRenderSystem->_setDepthBias(0, 0); - mRenderSystem->_setCullingMode(Ogre::CULL_NONE); - mRenderSystem->_setFog(Ogre::FOG_NONE); - mRenderSystem->_setColourBufferWriteEnabled(true, true, true, true); - mRenderSystem->unbindGpuProgram(Ogre::GPT_FRAGMENT_PROGRAM); - mRenderSystem->unbindGpuProgram(Ogre::GPT_VERTEX_PROGRAM); - mRenderSystem->setShadingType(Ogre::SO_GOURAUD); - - // initialise texture settings - mRenderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE); - mRenderSystem->_setTextureCoordSet(0, 0); - mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE); - mRenderSystem->_setTextureAddressingMode(0, mTextureAddressMode); - mRenderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY); -#if OGRE_VERSION < MYGUI_DEFINE_VERSION(1, 6, 0) - mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0); -#else - mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false); -#endif - mRenderSystem->_setTextureBlendMode(0, mColorBlendMode); - mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode); - mRenderSystem->_disableTextureUnitsFrom(1); - - // enable alpha blending - mRenderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA); - - // always use wireframe - // TODO: add option to enable wireframe mode in platform - mRenderSystem->_setPolygonMode(Ogre::PM_SOLID); - - if(bUseShaders) - { - mRenderSystem->bindGpuProgram(mDefaultVertexProgram); - } - - } - - void OgreD3D11RenderManager::end() - { - } - - ITexture* OgreD3D11RenderManager::createTexture(const std::string& _name) - { - MapTexture::const_iterator item = mTextures.find(_name); - MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist"); - - OgreTexture* texture = new OgreTexture(_name, OgreDataManager::getInstance().getGroup()); - mTextures[_name] = texture; - return texture; - } - - void OgreD3D11RenderManager::destroyTexture(ITexture* _texture) - { - if (_texture == nullptr) return; - - MapTexture::iterator item = mTextures.find(_texture->getName()); - MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found"); - - mTextures.erase(item); - delete _texture; - } - - ITexture* OgreD3D11RenderManager::getTexture(const std::string& _name) - { - MapTexture::const_iterator item = mTextures.find(_name); - if (item == mTextures.end()) - { - Ogre::TexturePtr texture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName(_name); - if (!texture.isNull()) - { - ITexture* result = createTexture(_name); - static_cast(result)->setOgreTexture(texture); - return result; - } - return nullptr; - } - return item->second; - } - - bool OgreD3D11RenderManager::isFormatSupported(PixelFormat _format, TextureUsage _usage) - { - return Ogre::TextureManager::getSingleton().isFormatSupported( - Ogre::TEX_TYPE_2D, - OgreTexture::convertFormat(_format), - OgreTexture::convertUsage(_usage)); - } - - void OgreD3D11RenderManager::destroyAllResources() - { - for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) - { - delete item->second; - } - mTextures.clear(); - } - -#if MYGUI_DEBUG_MODE == 1 - bool OgreD3D11RenderManager::checkTexture(ITexture* _texture) - { - for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item) - { - if (item->second == _texture) - return true; - } - return false; - } -#endif - - const IntSize& OgreD3D11RenderManager::getViewSize() const - { - return mViewSize; - } - - VertexColourType OgreD3D11RenderManager::getVertexFormat() - { - return mVertexFormat; - } - - const RenderTargetInfo& OgreD3D11RenderManager::getInfo() - { - return mInfo; - } - - size_t OgreD3D11RenderManager::getActiveViewport() - { - return mActiveViewport; - } - - Ogre::RenderWindow* OgreD3D11RenderManager::getRenderWindow() - { - return mWindow; - } - - bool OgreD3D11RenderManager::getManualRender() - { - return mManualRender; - } - - void OgreD3D11RenderManager::setManualRender(bool _value) - { - mManualRender = _value; - } - - size_t OgreD3D11RenderManager::getBatchCount() const - { - return mCountBatch; - } - - Ogre::GpuProgram* OgreD3D11RenderManager::createDefaultVertexProgram() - { - Ogre::HighLevelGpuProgramManager* mgr = Ogre::HighLevelGpuProgramManager::getSingletonPtr(); - std::string progName ="mygui_default_VP"; - - Ogre::HighLevelGpuProgramPtr ret = mgr->createProgram(progName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", Ogre::GPT_VERTEX_PROGRAM); - - ret->setParameter("profiles", "vs_4_0"); - ret->setParameter("entry_point", "main_vp"); - - std::stringstream sourceStr; - - sourceStr << - "void main_vp( \n" - " in float4 position : POSITION, \n" - " in float4 diffuse : DIFFUSE, \n" - " in float2 uv :TEXCOORD0, \n" - " out float4 oPos : POSITION, \n" - " out float4 oDiffuse : TEXCOORD0, \n" - " out float2 oUV : TEXCOORD1) \n" - "{ \n" - " oPos = position;" - " oDiffuse = diffuse; \n" - " oUV = uv; \n" - "} \n"; - - ret->setSource(sourceStr.str()); - ret->load(); - - return ret->_getBindingDelegate(); - } - - //---------------------------------------------------------------------------------------- - - Ogre::GpuProgram* OgreD3D11RenderManager::createDefaultFragmentProgram() - { - Ogre::HighLevelGpuProgramManager* mgr = Ogre::HighLevelGpuProgramManager::getSingletonPtr(); - std::string progName = "mygui_default_FP"; - - Ogre::HighLevelGpuProgramPtr ret = mgr->createProgram(progName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", Ogre::GPT_FRAGMENT_PROGRAM); - - ret->setParameter("profiles", "ps_4_0"); - ret->setParameter("entry_point", "main_fp"); - - std::stringstream sourceStr; - - sourceStr << - "float4 main_fp(in float4 iPos : POSITION, \n" - "in float4 diffuse : TEXCOORD0, \n" - "in float2 uv : TEXCOORD1 \n" - "): COLOR0 \n" - "{ \n" - " return diffuse; \n" - "} \n"; - - ret->setSource(sourceStr.str()); - ret->load(); - - return ret->_getBindingDelegate(); - } - - Ogre::GpuProgram* OgreD3D11RenderManager::createDefaultFragmentProgramWith1Texture() - { - Ogre::HighLevelGpuProgramManager* mgr = Ogre::HighLevelGpuProgramManager::getSingletonPtr(); - std::string progName = "mygui_default_FP"; - - Ogre::HighLevelGpuProgramPtr ret = mgr->createProgram(progName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - "cg", Ogre::GPT_FRAGMENT_PROGRAM); - - ret->setParameter("profiles", "ps_4_0"); - ret->setParameter("entry_point", "main_fp"); - - std::stringstream sourceStr; - - sourceStr << - "float4 main_fp(in float4 iPos : POSITION, \n" - "in float4 diffuse : TEXCOORD0, \n" - "in float2 uv : TEXCOORD1, \n" - "uniform sampler2D diffuseMap : TEXUNIT0): COLOR0 \n" - "{ \n" - " float4 diffuseTex = tex2D(diffuseMap, uv); \n" - " diffuseTex = diffuseTex * diffuse ; \n" - " return diffuseTex ; \n" - "} \n"; - - ret->setSource(sourceStr.str()); - ret->load(); - - return ret->_getBindingDelegate(); - } - -} - -#endif diff --git a/source/ogre/common/MyGUI_D3D11.h b/source/ogre/common/MyGUI_D3D11.h deleted file mode 100644 index f82d7b565..000000000 --- a/source/ogre/common/MyGUI_D3D11.h +++ /dev/null @@ -1,203 +0,0 @@ -#pragma once -#include "MyGUI_OgreTexture.h" -#include "MyGUI_OgreVertexBuffer.h" -#include "MyGUI_OgreRenderManager.h" -#include "MyGUI_OgreDataManager.h" -#include "MyGUI_OgreDiagnostic.h" -#include "MyGUI_OgreTexture.h" -#include "MyGUI_LogManager.h" -#include "MyGUI_OgrePlatform.h" -#include "MyGUI_LastHeader.h" - -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - -namespace MyGUI -{ - - class OgreD3D11RenderManager : public RenderManager, - public IRenderTarget, - public Ogre::WindowEventListener, - public Ogre::RenderQueueListener, - public Ogre::RenderSystem::Listener - - { - //changes - public: - Ogre::GpuProgram* createDefaultVertexProgram(); - Ogre::GpuProgram* createDefaultFragmentProgram(); - Ogre::GpuProgram* createDefaultFragmentProgramWith1Texture(); - Ogre::GpuProgram *mDefaultVertexProgram,*mDefaultFragmentProgram,*mDefaultFragmentProgramWith1Texture; - bool bUseShaders; - public: - OgreD3D11RenderManager(); - virtual ~OgreD3D11RenderManager(); - - void initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene); - void shutdown(); - - static OgreD3D11RenderManager& getInstance(); - static OgreD3D11RenderManager* getInstancePtr(); - - /** @see RenderManager::getViewSize */ - virtual const IntSize& getViewSize() const; - - /** @see RenderManager::getVertexFormat */ - virtual VertexColourType getVertexFormat(); - - /** @see RenderManager::createVertexBuffer */ - virtual IVertexBuffer* createVertexBuffer(); - /** @see RenderManager::destroyVertexBuffer */ - virtual void destroyVertexBuffer(IVertexBuffer* _buffer); - - /** @see RenderManager::createTexture */ - virtual ITexture* createTexture(const std::string& _name); - /** @see RenderManager::destroyTexture */ - virtual void destroyTexture(ITexture* _texture); - /** @see RenderManager::getTexture */ - virtual ITexture* getTexture(const std::string& _name); - - /** @see RenderManager::isFormatSupported */ - virtual bool isFormatSupported(PixelFormat _format, TextureUsage _usage); - - /** @see IRenderTarget::begin */ - virtual void begin(); - /** @see IRenderTarget::end */ - virtual void end(); - - /** @see IRenderTarget::doRender */ - virtual void doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count); - - /** @see IRenderTarget::getInfo */ - virtual const RenderTargetInfo& getInfo(); - - void setRenderSystem(Ogre::RenderSystem* _render); - Ogre::RenderSystem* getRenderSystem(); - - void setRenderWindow(Ogre::RenderWindow* _window); - - /** Set scene manager where MyGUI will be rendered */ - void setSceneManager(Ogre::SceneManager* _scene); - - /** Get GUI viewport index */ - size_t getActiveViewport(); - - /** Set GUI viewport index */ - void setActiveViewport(unsigned short _num); - - Ogre::RenderWindow* getRenderWindow(); - - bool getManualRender(); - void setManualRender(bool _value); - - size_t getBatchCount() const; - -#if MYGUI_DEBUG_MODE == 1 - virtual bool checkTexture(ITexture* _texture); -#endif - - private: - virtual void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation); - virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation); - virtual void windowResized(Ogre::RenderWindow* _window); - - // восстанавливаем буферы - virtual void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters); - - void destroyAllResources(); - void updateRenderInfo(); - - - private: - // флаг для обновления всех и вся - bool mUpdate; - - IntSize mViewSize; - - Ogre::SceneManager* mSceneManager; - - VertexColourType mVertexFormat; - - // окно, на которое мы подписываемся для изменения размеров - Ogre::RenderWindow* mWindow; - - // вьюпорт, с которым работает система - unsigned short mActiveViewport; - - Ogre::RenderSystem* mRenderSystem; - Ogre::TextureUnitState::UVWAddressingMode mTextureAddressMode; - Ogre::LayerBlendModeEx mColorBlendMode, mAlphaBlendMode; - - RenderTargetInfo mInfo; - - typedef std::map MapTexture; - MapTexture mTextures; - - bool mIsInitialise; - bool mManualRender; - size_t mCountBatch; - }; - - class OgreD3D11Platform - { - public: - OgreD3D11Platform() : - mIsInitialise(false) - { - mLogManager = new LogManager(); - mRenderManager = new OgreD3D11RenderManager(); - mDataManager = new OgreDataManager(); - } - - ~OgreD3D11Platform() - { - assert(!mIsInitialise); - delete mRenderManager; - delete mDataManager; - delete mLogManager; - } - - void initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene, const std::string& _group = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, const std::string& _logName = MYGUI_PLATFORM_LOG_FILENAME) - { - assert(!mIsInitialise); - mIsInitialise = true; - - if (!_logName.empty()) - LogManager::getInstance().createDefaultSource(_logName); - - mRenderManager->initialise(_window, _scene); - mDataManager->initialise(_group); - } - - void shutdown() - { - assert(mIsInitialise); - mIsInitialise = false; - - mRenderManager->shutdown(); - mDataManager->shutdown(); - } - - OgreD3D11RenderManager* getRenderManagerPtr() - { - assert(mIsInitialise); - return mRenderManager; - } - - OgreDataManager* getDataManagerPtr() - { - assert(mIsInitialise); - return mDataManager; - } - - private: - bool mIsInitialise; - OgreD3D11RenderManager* mRenderManager; - OgreDataManager* mDataManager; - LogManager* mLogManager; - }; - -} - -#endif diff --git a/source/ogre/main.cpp b/source/ogre/main.cpp index 029aab35a..5dbb6135c 100644 --- a/source/ogre/main.cpp +++ b/source/ogre/main.cpp @@ -30,10 +30,10 @@ void LoadDefaultSet(SETTINGS* settings, string setFile) // . . . . . . . . . . MAIN . . . . . . . . . . -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR lpCmdLine, int nCmdShow) -#else +#if defined(main) || OGRE_PLATFORM != OGRE_PLATFORM_WIN32 int main(int argc, char* argv[]) +#else + int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR lpCmdLine, int nCmdShow) #endif { Ogre::Timer ti; @@ -80,12 +80,12 @@ void LoadDefaultSet(SETTINGS* settings, string setFile) // Helper for testing networked games on 1 computer // use number > 0 in command parameter, adds it to nick, port and own ogre.log int num = -1; - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - if (lpCmdLine) - num = Ogre::StringConverter::parseInt(lpCmdLine); - #else + #if defined(main) || OGRE_PLATFORM != OGRE_PLATFORM_WIN32 if (argc > 1) num = Ogre::StringConverter::parseInt(argv[1]); + #else + if (lpCmdLine) + num = Ogre::StringConverter::parseInt(lpCmdLine); #endif if (num > 0) { @@ -126,10 +126,10 @@ void LoadDefaultSet(SETTINGS* settings, string setFile) try { - #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - pApp->Run( settings->ogre_dialog || lpCmdLine[0]!=0 ); //Release change- + #if defined(main) || OGRE_PLATFORM != OGRE_PLATFORM_WIN32 + pApp->Run( settings->ogre_dialog ); #else - pApp->Run( settings->ogre_dialog); + pApp->Run( settings->ogre_dialog || lpCmdLine[0]!=0 ); //Release change- #endif } catch (Ogre::Exception& e) diff --git a/source/ogre/pch.h b/source/ogre/pch.h index 95e159b0a..8d5b7eba8 100644 --- a/source/ogre/pch.h +++ b/source/ogre/pch.h @@ -5,6 +5,15 @@ #ifdef _MSC_VER // include file for project specific include files that are used frequently, but are changed infrequently +/// win +#define WINVER 0x0510 +#define _WIN32_WINNT 0x0510 +#define _WIN32_WINDOWS 0x0410 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include + /// std #include #include @@ -27,17 +36,6 @@ #include #include -/// win -#include -#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 - #define WINVER 0x0510 - #define _WIN32_WINNT 0x0510 - #define _WIN32_WINDOWS 0x0410 - #define WIN32_LEAN_AND_MEAN - #include - #include -#endif - #include "tinyxml.h" #include "tinyxml2.h" #include "half.hpp" diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 000000000..ae76c62b1 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,22 @@ +{ + "name": "stuntrally", + "version": "2.6.2", + "description": "Racing game with track editor based on VDrift and OGRE", + "dependencies": [ + "boost-system", + "boost-filesystem", + "boost-wave", + "bullet3", + "enet", + "freetype", + "libogg", + "libvorbis", + "mygui", + { + "name": "ogre", + "features": ["d3d9"] + }, + "openal-soft" + ], + "builtin-baseline": "2ac61f87f69f0484b8044f95ab274038fbaf7bdd" +}