Compare commits

...

85 Commits

Author SHA1 Message Date
c860152f9b Using threads more 2026-01-30 01:04:23 +03:00
da4c1fee0e Threads and tasks 2026-01-29 15:28:50 +03:00
4cf0ea5321 Added json.lua 2026-01-23 21:31:15 +03:00
8320b14358 Started working on dialogue 2026-01-23 21:28:25 +03:00
1d358d206e Much better narration/dialogue/action handling (and for lua too) 2026-01-23 02:42:29 +03:00
cd91174f5d Better narration processing 2026-01-22 17:15:19 +03:00
4b24d85123 Action nodes support and lots of other updates 2026-01-19 00:07:03 +03:00
f86e7fd96c Furniture placement 2026-01-09 22:29:26 +03:00
272e202774 Now can create roofs from lua script 2026-01-08 00:16:46 +03:00
80fba23cd2 Can create roofs now 2026-01-07 01:35:08 +03:00
c031056e17 house generation almost complete 2026-01-02 18:08:20 +03:00
49fc547295 Building interior walls created with editor 2026-01-02 01:41:58 +03:00
d6d61229f8 Started town procedural generation code 2025-12-28 06:23:29 +03:00
5bb529bc31 Refactoring: split items 2025-12-27 16:05:32 +03:00
d3c93c5c18 Consistent startup 2025-12-19 06:09:07 +03:00
9bb9e2c09b Generating path from shore to pier 2025-12-15 01:41:44 +03:00
3f99099919 Creating pier 2025-12-14 06:59:12 +03:00
81a78990ce Maintain item list 2025-12-08 03:37:14 +03:00
33fc237793 Made cursor work 2025-12-07 20:09:41 +03:00
44896ed0d9 Heightmap editor + saving 2025-12-07 01:31:25 +03:00
e0db570581 Started implementing deficated editor GUI 2025-12-04 15:51:56 +03:00
6eed5063e6 Fixes in modules 2025-12-02 14:30:05 +03:00
5b014dcb65 Better boat handling 2025-11-30 18:28:26 +03:00
cd82fb0eed converted to Jolt physics 2025-11-23 02:00:31 +03:00
3f0484e87c Updated lots of things 2025-10-22 16:39:19 +03:00
9c4bea5983 Base character for morph targets 2025-10-08 07:11:39 +03:00
3645557520 Working on morph targets 2025-10-07 23:14:15 +03:00
19a1275a8a Now root motion works much better; raft/boat climbing 2025-10-04 04:10:21 +03:00
25280a9cbe Support proper actuator animation 2025-09-27 01:23:16 +03:00
7e06da700a New models; using raft 2025-09-25 04:11:31 +03:00
9e5d08bfc6 Animation tree implemented 2025-09-22 20:34:12 +03:00
a62d781aa0 Updates 2025-09-21 00:05:28 +03:00
fea7c71788 Updates 2025-09-20 23:14:17 +03:00
e967844558 Converting vehicle and building workflow to blender2ogre 2025-09-20 05:52:24 +03:00
62e14cf075 Lots of updates - lua, narrator, logic, models 2025-09-19 04:35:20 +03:00
4249a0238b Adding complete copy 2025-09-18 17:49:15 +03:00
cfd9ed8708 Lua works; narrator works 2025-09-17 18:08:26 +03:00
1977a12d8b Added lpeg for narrator 2025-09-16 22:31:16 +03:00
190318e5c4 Updates 2025-09-16 20:38:29 +03:00
1aa002d8ba Animation fixes + fonts 2025-09-15 23:55:31 +03:00
1bc0f298fc Added treading water animation 2025-09-15 03:18:46 +03:00
e6463fc264 Added female; added swimming animation 2025-09-15 03:11:41 +03:00
7621607152 rename swimming 2025-09-15 02:08:45 +03:00
82ac145e87 Swimming animation 2025-09-15 02:08:15 +03:00
ff780c34b3 Add swimming animation 2025-09-15 02:07:18 +03:00
5c03f0cd2c Water works! 2025-09-15 01:51:38 +03:00
4d0fb8f60f Let physics run for a while to prevent bugs 2025-09-08 11:40:53 +03:00
3f59a384e4 Water: distortions 2025-09-08 09:46:16 +03:00
d42cf2854a Watergit push! 2025-09-07 21:15:00 +03:00
92ec3e9497 Updates 2025-09-05 22:56:48 +03:00
25816c5658 Tweaked water physics 2025-09-04 01:14:10 +03:00
1c56387c35 Fixed water body presence physics 2025-09-03 22:16:53 +03:00
aca04ff621 Water is in ECS; water material is created in code 2025-09-03 05:31:13 +03:00
847aab6ed0 Converted to ECS, physics fix 2025-09-02 16:07:03 +03:00
b434e516f0 Removed separate controller class 2025-09-01 12:32:34 +03:00
e0045ffeb1 Almost moved character to flecs 2025-09-01 03:19:03 +03:00
6ec256195b Staticc linking to libstdc++/libgcc 2025-08-30 23:13:59 +03:00
228eafb7d8 Proper cache variable setting 2025-08-30 22:11:58 +03:00
338ffe2661 Proper blender use 2025-08-30 21:13:04 +03:00
657107b4ae Rearrangements; Audio support 2025-08-30 21:06:56 +03:00
503db60c60 Fixed build system 2025-08-28 02:32:43 +03:00
c730ca5222 updates 2025-08-26 08:13:21 +03:00
2349bbc77e Handling on-floor target 2025-08-21 15:03:07 +03:00
d3b2ae30d5 Making this work 2025-08-21 10:58:22 +03:00
52de5b16a8 Making this work 2025-08-21 10:58:17 +03:00
5c05f6b8e0 proper blender path 2025-08-19 14:18:18 +03:00
9ef3194cde Fixed physics 2025-07-11 09:52:13 +03:00
0c27405da7 Blender import improvement 2025-07-11 02:20:48 +03:00
51c25ac6a6 Update gitignore 2025-07-10 06:52:56 +03:00
db46a3a7a7 Add edited male 2025-07-10 06:30:11 +03:00
f7db2130a8 Remove unneeded code 2025-07-09 15:19:34 +03:00
99b711f42f Added missing files 2025-07-09 15:01:16 +03:00
912f3e5368 Update 2025-07-09 13:17:20 +03:00
cb4229905d Ignore characters dir 2025-07-07 08:56:21 +03:00
4a3315e104 Added mixamo 2025-07-07 08:31:41 +03:00
79d27bd7ab Added vroid assets 2025-07-07 08:26:16 +03:00
f67d0c9ccb Add textures 2025-07-07 08:18:51 +03:00
7fa48cab21 Added blender scripts 2025-07-07 07:50:40 +03:00
8d1345a532 Adding buildings to LFS 2025-07-07 07:43:18 +03:00
8d95fcc97e Adding blend files to git-lfs 2025-07-07 07:29:58 +03:00
4c9990b4da Convert to git-lfs 2025-07-07 07:26:04 +03:00
4a790a060a Better water 2025-07-07 00:16:48 +03:00
c72b1cf35e Added separate game file 2025-07-05 06:19:03 +03:00
52d6d31241 Fixed render targets; renamed GuiTest to Editor 2025-07-05 06:03:16 +03:00
b2e010bdb4 Render target water 2025-07-04 01:10:08 +03:00
648 changed files with 170656 additions and 1518 deletions

7
.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
*.blend filter=lfs diff=lfs merge=lfs -text
*.kra filter=lfs diff=lfs merge=lfs -text
*.vrm filter=lfs diff=lfs merge=lfs -text
*.vroid filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text

5
.gitignore vendored
View File

@@ -1,4 +1,9 @@
*~
build/*
build-vscode/*
characters/*
resources/buildings/*
assets/blender/scripts/*.blend
__pycache__/
*.blend[1-9]
./characters/

73
.vscode/settings.json vendored
View File

@@ -1,7 +1,76 @@
{
"cmake.generator": "Unix Makefiles",
"cmake.configureSettings": {
"CMAKE_PREFIX_PATH": "/media/slapin/library/ogre/ogre-sdk"
"CMAKE_PREFIX_PATH": "/media/slapin/library/ogre3/ogre-sdk",
"CMAKE_VERBOSE_MAKEFILE": "ON"
},
"cmake.buildDirectory": "${workspaceFolder}/build-vscode"
"cmake.buildDirectory": "${workspaceFolder}/build-vscode",
"files.associations": {
"istream": "cpp",
"variant": "cpp",
"tuple": "cpp",
"iostream": "cpp",
"string_view": "cpp",
"atomic": "cpp",
"memory_resource": "cpp",
"stop_token": "cpp",
"random": "cpp",
"future": "cpp",
"array": "cpp",
"deque": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"initializer_list": "cpp",
"span": "cpp",
"chrono": "cpp",
"format": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"bit": "cpp",
"bitset": "cpp",
"charconv": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"map": "cpp",
"set": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"optional": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"typeinfo": "cpp"
}
}

18
.vscode/tasks.json vendored
View File

@@ -13,7 +13,8 @@
"label": "CMake: clean rebuild",
"command": "build",
"targets": [
"GuiTest",
"Editor",
"Game",
"0_Bootstrap",
"TerrainTest",
"Procedural"
@@ -27,7 +28,8 @@
"label": "CMake: clean rebuild",
"command": "cleanRebuild",
"targets": [
"GuiTest",
"Editor",
"Game",
"0_Bootstrap",
"TerrainTest",
"Procedural"
@@ -57,6 +59,18 @@
"group": "build",
"problemMatcher": [],
"detail": "CMake clean rebuild task"
},
{
"type": "cmake",
"label": "CMake: build",
"command": "build",
"targets": [
"Editor",
"Game"
],
"group": "build",
"problemMatcher": [],
"detail": "CMake build task"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,46 @@
project(world2)
cmake_minimum_required(VERSION 3.13.0)
project(world2)
set(CMAKE_CXX_STANDARD 14)
set(BLENDER /home/slapin/blender-3.6.20-linux-x64/blender)
set(CMAKE_CXX_STANDARD 17)
set(BLENDER "${CMAKE_SOURCE_DIR}/../../blender-bin/bin/blender" CACHE STRING "Blender path")
set(CREATE_DIRECTORIES
${CMAKE_SOURCE_DIR}/assets/blender/shapes/male
${CMAKE_SOURCE_DIR}/assets/blender/shapes/female
${CMAKE_SOURCE_DIR}/characters/shapes/male/chibi
${CMAKE_SOURCE_DIR}/characters/shapes/female/chibi
${CMAKE_SOURCE_DIR}/characters/male
${CMAKE_SOURCE_DIR}/characters/female)
set(CREATE_SCENES
${CMAKE_SOURCE_DIR}/characters/female/vroid-normal-female.scene
${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
)
${CMAKE_BINARY_DIR}/assets/blender/shapes/male
${CMAKE_BINARY_DIR}/assets/blender/shapes/female
${CMAKE_BINARY_DIR}/assets/blender/scripts
${CMAKE_BINARY_DIR}/characters/shapes/male/chibi
${CMAKE_BINARY_DIR}/characters/shapes/female/chibi
${CMAKE_BINARY_DIR}/characters/male
${CMAKE_BINARY_DIR}/characters/female)
#set(CREATE_SCENES
# ${CMAKE_SOURCE_DIR}/characters/female/vroid-normal-female.scene
# ${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
# )
# workaround horribly broken assimp cmake, fixed with assimp 5.1
add_library(fix::assimp INTERFACE IMPORTED)
set_target_properties(fix::assimp PROPERTIES
INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml"
INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
)
file(GLOB TERRAIN_SRC ${CMAKE_SOURCE_DIR}/src/terrain/*.cpp)
#add_library(assimp INTERFACE IMPORTED)
#set_target_properties(assimp PROPERTIES
# INTERFACE_LINK_LIBRARIES "assimp;pugixml"
# # INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
# INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
#)
file(GLOB WATER_SRC ${CMAKE_SOURCE_DIR}/water/*.cpp)
# The COMPONENTS part checks that OGRE was built the way we need it
# The CONFIG flag makes sure we get OGRE instead of OGRE-next
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging CONFIG)
find_package(OGRE REQUIRED COMPONENTS Bites Paging Terrain CONFIG)
find_package(ZLIB)
find_package(SDL2)
find_package(assimp)
find_package(Bullet)
find_package(assimp REQUIRED CONFIG)
find_package(OgreProcedural REQUIRED CONFIG)
find_package(pugixml REQUIRED CONFIG)
find_package(flecs REQUIRED CONFIG)
add_library(fix::assimp INTERFACE IMPORTED)
set_target_properties(fix::assimp PROPERTIES
INTERFACE_LINK_LIBRARIES "${ASSIMP_LIBRARIES};pugixml"
INTERFACE_LINK_DIRECTORIES "${ASSIMP_LIBRARY_DIRS}"
# INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
add_library(fix::OgreProcedural INTERFACE IMPORTED)
set_target_properties(fix::OgreProcedural PROPERTIES
@@ -40,27 +48,74 @@ set_target_properties(fix::OgreProcedural PROPERTIES
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
if(OGRE_STATIC)
add_library(OgreGLSupportStatic INTERFACE IMPORTED)
set_target_properties(OgreGLSupportStatic PROPERTIES
INTERFACE_LINK_LIBRARIES "OgreGLSupportStatic"
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
endif()
add_library(fix::pugixml INTERFACE IMPORTED)
set_target_properties(fix::pugixml PROPERTIES
INTERFACE_LINK_LIBRARIES "pugixml"
INTERFACE_LINK_DIRECTORIES "${CMAKE_PREFIX_PATH}/lib"
)
add_subdirectory(src/lua)
add_subdirectory(src/gamedata)
add_subdirectory(src/miniaudio)
add_subdirectory(src/sound)
add_subdirectory(src/sceneloader)
add_subdirectory(audio/gui)
add_subdirectory(lua-scripts)
add_subdirectory(morph)
add_subdirectory(src/world)
add_subdirectory(src/tests)
add_subdirectory(src/physics)
add_subdirectory(src/editor)
add_subdirectory(assets/blender/buildings/parts)
add_subdirectory(resources)
# add the source files as usual
add_executable(0_Bootstrap Bootstrap.cpp)
# this also sets the includes and pulls third party dependencies
target_link_libraries(0_Bootstrap OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(0_Bootstrap PUBLIC OgreBites OgrePaging OgreBullet)
add_dependencies(0_Bootstrap stage_files)
add_executable(Game Game.cpp ${WATER_SRC})
target_include_directories(Game PRIVATE src/gamedata)
target_link_libraries(Game OgreBites OgrePaging OgreTerrain OgreMeshLodGenerator
OgreProcedural::OgreProcedural
GameData
sound
sceneloader physics
flecs::flecs_static
-Wl,--as-needed
)
if(OGRE_STATIC)
target_link_options(Game PRIVATE -static-libstdc++ -static-libgcc)
endif()
add_dependencies(Game stage_files import_buildings import_water_stuff import_vehicles import_vrm audio_data_gui)
add_executable(GuiTest GuiTest.cpp ${TERRAIN_SRC} ${WATER_SRC})
target_link_libraries(GuiTest OgreBites OgreBullet OgrePaging OgreTerrain OgreMeshLodGenerator ${OgreProcedural_LIBRARIES} ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(GuiTest PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreMeshLodGenerator ${OgreProcedural_INCLUDE_DIRS})
add_dependencies(GuiTest stage_files import_buildings)
add_executable(Procedural Procedural.cpp ${TERRAIN_SRC})
target_link_libraries(Procedural OgreBites OgreBullet OgrePaging OgreTerrain OgreProcedural::OgreProcedural ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(Procedural PUBLIC OgreBites OgrePaging OgreBullet OgreTerrain OgreProcedural::OgreProcedural ${CMAKE_PREFIX_PATH}/include/OgreProcedural)
add_executable(Procedural Procedural.cpp)
target_link_libraries(Procedural OgreBites OgrePaging OgreTerrain
OgreProcedural::OgreProcedural
-Wl,--as-needed
)
if(OGRE_STATIC)
target_link_options(Procedural PRIVATE -static-libstdc++ -static-libgcc)
endif()
add_dependencies(Procedural stage_files import_buildings)
file(GLOB FONTS_SRC ${CMAKE_SOURCE_DIR}/assets/fonts/*.ttf)
set(FONT_OUTPUT_FILES)
foreach(FONT_FILE ${FONTS_SRC})
get_filename_component(FILE_NAME ${FONT_FILE} NAME_WE)
set(FONT_OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/fonts/${FILE_NAME}.ttf)
add_custom_command(
OUTPUT ${FONT_OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/resources/fonts
COMMAND ${CMAKE_COMMAND} -E copy ${FONT_FILE} ${FONT_OUTPUT_FILE}
DEPENDS ${FONT_FILE})
list(APPEND FONT_OUTPUT_FILES ${FONT_OUTPUT_FILE})
endforeach()
add_custom_target(fonts ALL DEPENDS ${FONT_OUTPUT_FILES})
file(GLOB BUILDINGS_SRC ${CMAKE_SOURCE_DIR}/assets/blender/buildings/*.blend)
set(BUILDING_OUTPUT_FILES)
foreach(BUILDING_FILE ${BUILDINGS_SRC})
@@ -79,56 +134,78 @@ foreach(BUILDING_FILE ${BUILDINGS_SRC})
endforeach()
add_custom_target(import_buildings ALL DEPENDS ${BUILDING_OUTPUT_FILES})
add_executable(TerrainTest terrain.cpp ${TERRAIN_SRC})
target_link_libraries(TerrainTest OgreBites OgreBullet OgrePaging OgreTerrain lua ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY})
target_include_directories(TerrainTest PUBLIC OgreBites OgrePaging OgreTerrain OgreBullet PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
file(GLOB LUA_SCRIPTS_SRC ${CMAKE_SOURCE_DIR}/lua-scripts/*.lua)
set(LUA_SCRIPTS_OUTPUT)
foreach(LUA_SCRIPT_FILE ${LUA_SCRIPTS_SRC})
get_filename_component(FILE_NAME ${LUA_SCRIPT_FILE} NAME_WE)
set(LUA_SCRIPT_OUTPUT_FILE ${CMAKE_BINARY_DIR}/lua-scripts/${FILE_NAME}.lua)
add_custom_command(OUTPUT ${LUA_SCRIPT_OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E copy ${LUA_SCRIPT_FILE} ${LUA_SCRIPT_OUTPUT_FILE}
DEPENDS ${LUA_SCRIPT_FILE})
list(APPEND LUA_SCRIPTS_OUTPUT ${LUA_SCRIPT_OUTPUT_FILE})
file(GLOB VEHICLES_SRC ${CMAKE_SOURCE_DIR}/assets/blender/vehicles/*.blend)
set(VEHICLE_OUTPUT_FILES)
foreach(VEHICLE_FILE ${VEHICLES_SRC})
get_filename_component(FILE_NAME ${VEHICLE_FILE} NAME_WE)
set(VEHICLE_OUTPUT_FILE ${CMAKE_BINARY_DIR}/resources/vehicles/${FILE_NAME}.glb)
add_custom_command(
OUTPUT ${VEHICLE_OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/resources/vehicles
COMMAND ${BLENDER} ${VEHICLE_FILE}
-b -Y -P
${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_buildings.py
-- ${VEHICLE_OUTPUT_FILE}
COMMAND touch ${VEHICLE_OUTPUT_FILE}
DEPENDS ${VEHICLE_FILE})
list(APPEND VEHICLE_OUTPUT_FILES ${VEHICLE_OUTPUT_FILE})
endforeach()
add_custom_target(stage_lua_scripts ALL DEPENDS ${LUA_SCRIPTS_OUTPUT})
add_custom_target(import_vehicles ALL DEPENDS ${VEHICLE_OUTPUT_FILES})
set(CHARACTER_SHAPES_SRC edited-normal-male-base.blend edited-shape-test-male.blend)
set(CHARACTER_SHAPES_OUTPUT_FILES)
foreach(CHARACTER_SHAPE_FILE ${CHARACTER_SHAPES_SRC})
get_filename_component(FILE_NAME ${CHARACTER_SHAPE_FILE} NAME_WE)
set(CHARACTER_SHAPE_OUTPUT_FILE ${CMAKE_BINARY_DIR}/characters/shapes/male/${FILE_NAME}/${FILE_NAME}.scene)
add_custom_command(
OUTPUT ${CHARACTER_SHAPE_OUTPUT_FILE}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/assets/blender
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/characters/shapes/male/${FILE_NAME}
COMMAND ${BLENDER} ${CMAKE_SOURCE_DIR}/assets/blender/${CHARACTER_SHAPE_FILE}
-b -Y -P
${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_characters_ogre.py
-- ${CHARACTER_SHAPE_OUTPUT_FILE}
COMMAND touch ${CHARACTER_SHAPE_OUTPUT_FILE}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/${CHARACTER_SHAPE_FILE})
list(APPEND CHARACTER_SHAPES_OUTPUT_FILES ${CHARACTER_SHAPE_OUTPUT_FILE})
endforeach()
add_custom_target(import_character_shapes ALL DEPENDS ${CHARACTER_SHAPES_OUTPUT_FILES})
set(WATER_STUFF)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/water/sea.glb
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/water
COMMAND ${BLENDER} ${CMAKE_SOURCE_DIR}/assets/blender/sea.blend
-b -Y -P
${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_buildings.py
-- ${CMAKE_BINARY_DIR}/water/sea.glb
COMMAND touch ${CMAKE_BINARY_DIR}/water/sea.glb
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/sea.blend)
list(APPEND WATER_STUFF ${CMAKE_BINARY_DIR}/water/sea.glb)
add_custom_target(import_water_stuff ALL DEPENDS ${WATER_STUFF})
add_executable(TerrainTest terrain.cpp)
target_link_libraries(TerrainTest OgreBites OgrePaging OgreTerrain lua
-Wl,--as-needed
)
target_include_directories(TerrainTest PRIVATE . src/terrain src/lua src/lua/lua-5.4.8/src)
if(OGRE_STATIC)
target_link_libraries(TerrainTest fix::assimp pugixml)
target_link_options(TerrainTest PRIVATE -static-libstdc++ -static-libgcc)
target_link_libraries(Procedural fix::assimp pugixml)
endif()
add_dependencies(TerrainTest stage_lua_scripts stage_files)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/stories
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/lua-scripts/stories ${CMAKE_BINARY_DIR}/stories
DEPENDS ${CMAKE_BINARY_DIR}/lua-scripts/stories
)
add_custom_target(stage_stories ALL DEPENDS stage_lua_scripts ${CMAKE_BINARY_DIR}/stories)
add_custom_command(
OUTPUT ${CMAKE_BINARY_DIR}/resources.cfg
COMMAND cp ${CMAKE_SOURCE_DIR}/resources.cfg ${CMAKE_BINARY_DIR}/resources.cfg
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/main
${CMAKE_BINARY_DIR}/resources/main
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/shaderlib
${CMAKE_BINARY_DIR}/resources/shaderlib
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/terrain
${CMAKE_BINARY_DIR}/resources/terrain
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/characters
${CMAKE_BINARY_DIR}/characters
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/lua-scripts
# ${CMAKE_BINARY_DIR}/lua-scripts
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/skybox
# ${CMAKE_BINARY_DIR}/skybox
# COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources/debug
# ${CMAKE_BINARY_DIR}/resources/debug
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/resources.cfg ${CMAKE_BINARY_DIR}/resources.cfg
DEPENDS ${CMAKE_SOURCE_DIR}/resources.cfg)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
COMMAND unzip -o ${CMAKE_SOURCE_DIR}/world_map.kra mergedimage.png -d ${CMAKE_BINARY_DIR}/world_map
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_BINARY_DIR}/world_map/mergedimage.png
${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/world_map
DEPENDS ${CMAKE_SOURCE_DIR}/world_map.kra)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/resources/terrain/brushes.png
COMMAND unzip -o ${CMAKE_SOURCE_DIR}/brushes.kra mergedimage.png -d ${CMAKE_BINARY_DIR}/brushes
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_BINARY_DIR}/brushes/mergedimage.png
${CMAKE_BINARY_DIR}/resources/terrain/brushes.png
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/brushes
DEPENDS ${CMAKE_SOURCE_DIR}/brushes.kra)
set(SKYBOX_SRC
early_morning_bk.jpg
@@ -150,6 +227,8 @@ set(WATER_SRC
water.program
water.frag
water.vert
depth.frag
depth.vert
water.compositor
waves2.png
)
@@ -176,28 +255,93 @@ foreach(MATERIAL_FILE ${MATERIAL_FILES})
list(APPEND MATERIALS_OUTPUT ${OUTPUT_FILE})
endforeach()
file(GLOB VRM_FILES RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/assets/vroid/*.vrm)
file(GLOB MIXAMO_FILES RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/assets/blender/mixamo/**/*.fbx)
set(VRM_SOURCE)
foreach(VRM_FILE ${VRM_FILES} ${MIXAMO_FILES})
set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${VRM_FILE}")
set(INPUT_FILE "${CMAKE_SOURCE_DIR}/${VRM_FILE}")
add_custom_command(OUTPUT "${OUTPUT_FILE}"
COMMAND ${CMAKE_COMMAND} -E copy "${INPUT_FILE}" "${OUTPUT_FILE}"
DEPENDS "${INPUT_FILE}" VERBATIM)
list(APPEND VRM_SOURCE "${OUTPUT_FILE}")
endforeach()
set(VRM_IMPORTED_BLENDS
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-female.blend
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-male.blend
${CMAKE_BINARY_DIR}/assets/blender/shapes/male/vrm-vroid-normal-male-chibi.blend
)
add_custom_command(OUTPUT ${VRM_IMPORTED_BLENDS}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm.py
COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${VRM_IMPORTED_BLENDS}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm.py
${VRM_SOURCE}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set(EDITED_BLENDS_LIST
male
female
)
set(EDITED_BLEND_TARGETS)
set(CHARACTER_GLBS)
foreach(EDITED_BLEND ${EDITED_BLENDS_LIST})
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/characters/female/vroid-normal-female.scene
${CMAKE_SOURCE_DIR}/characters/male/vroid-normal-male.scene
${CMAKE_SOURCE_DIR}/assets/blender/vrm-vroid-normal-female.blend
${CMAKE_SOURCE_DIR}/assets/blender/vrm-vroid-normal-male.blend
${CMAKE_SOURCE_DIR}/assets/blender/shapes/male/vrm-vroid-normal-male-chibi.blend
COMMAND mkdir -p ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm.py
OUTPUT ${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-${EDITED_BLEND}.blend
COMMAND ${CMAKE_COMMAND}
-E copy ${CMAKE_SOURCE_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend
${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend
COMMAND ${BLENDER} -b -Y
${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend
-P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/copy_animations.py --
${CMAKE_BINARY_DIR}/assets/blender/vrm-vroid-normal-${EDITED_BLEND}.blend ${EDITED_BLEND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
list(APPEND EDITED_BLEND_TARGETS ${CMAKE_BINARY_DIR}/assets/blender/edited-normal-${EDITED_BLEND}.blend)
list(APPEND CHARACTER_GLBS ${CMAKE_BINARY_DIR}/characters/${EDITED_BLEND}/normal-${EDITED_BLEND}.glb)
endforeach()
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/characters/shapes/male/chibi/vroid-normal-male-chibi.glb
DEPENDS ${CMAKE_BINARY_DIR}/assets/blender/characters/shapes/male/chibi/vroid-normal-male-chibi.glb
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/assets/blender/characters/shapes/male/chibi/vroid-normal-male-chibi.glb
${CMAKE_BINARY_DIR}/characters/shapes/male/chibi/vroid-normal-male-chibi.glb)
add_custom_target(morph ALL DEPENDS MorphTargetsResearch ${CMAKE_BINARY_DIR}/characters/shapes/male/chibi/vroid-normal-male-chibi.glb)
set(COPY_BLENDS edited-shape-test-male.blend edited-normal-male-base.blend)
foreach (COPY_BLEND_FILE ${COPY_BLENDS})
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/assets/blender/${COPY_BLEND_FILE}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/${COPY_BLEND_FILE}
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_SOURCE_DIR}/assets/blender/${COPY_BLEND_FILE}
${CMAKE_BINARY_DIR}/assets/blender/${COPY_BLEND_FILE}
)
list(APPEND EDITED_BLEND_TARGETS ${CMAKE_BINARY_DIR}/assets/blender/${COPY_BLEND_FILE})
endforeach()
add_custom_target(edited-blends ALL DEPENDS ${EDITED_BLEND_TARGETS})
add_custom_command(
OUTPUT ${CHARACTER_GLBS}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CREATE_DIRECTORIES}
COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py
# COMMAND ${BLENDER} -b -Y -P ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_ogre_scene.py
COMMAND echo rm -Rf ${CMAKE_SOURCE_DIR}/characters/male/*.material ${CMAKE_SOURCE_DIR}/characters/female/*.material
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${CMAKE_SOURCE_DIR}/assets/blender/scripts/import_vrm.py
${CMAKE_SOURCE_DIR}/assets/vroid/buch1.vrm
${CMAKE_SOURCE_DIR}/assets/vroid/buch1-chibi.vrm
${CMAKE_SOURCE_DIR}/assets/vroid/jane2-dress.vrm
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
COMMAND ${CMAKE_COMMAND} -E touch ${CHARACTER_GLBS}
DEPENDS ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_models.py ${VRM_IMPORTED_BLENDS} ${EDITED_BLEND_TARGETS}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_target(stage_files ALL DEPENDS ${CMAKE_BINARY_DIR}/resources.cfg ${MATERIALS_OUTPUT}
${CMAKE_BINARY_DIR}/resources/terrain/world_map.png
${CMAKE_BINARY_DIR}/resources/terrain/brushes.png)
${CMAKE_BINARY_DIR}/resources/terrain/brushes.png
edited-blends stage_resources)
add_custom_target(remove_scenes COMMAND rm -f ${CREATE_SCENES})
add_custom_target(remove_scenes COMMAND rm -f ${VRM_SOURCE} ${VRM_IMPORTED_BLENDS} ${CHARACTER_GLBS})
add_custom_target(import_vrm DEPENDS ${CREATE_SCENES})
add_custom_target(import_vrm DEPENDS ${CHARACTER_GLBS})
target_compile_definitions(Game PRIVATE FLECS_CPP_NO_AUTO_REGISTRATION)
install(TARGETS Game DESTINATION bin)
install(TARGETS Editor DESTINATION bin)

View File

@@ -9,8 +9,8 @@
#include <OgreTrays.h>
#include <OgreTimer.h>
#include <OgreMeshLodGenerator.h>
#include <OgreTerrain.h>
#include "src/terrain/terrain.h"
#include "water/water.h"
class App;
class SkyRenderer : public Ogre::SceneManager::Listener {
@@ -244,16 +244,12 @@ public:
void initGui();
};
class App : public OgreBites::ApplicationContext {
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal;
Ogre::Camera *mCamera;
Ogre::Real mPivotPitch;
Ogre::SceneManager *mScnMgr;
OgreBites::InputListenerChain mInput;
Ogre::Viewport *mViewport;
EditUI m_edit_ui;
TerrainSetup m_terrain;
Ogre::Light *mSun;
SkyBoxRenderer *sky;
Water m_water;
@@ -285,6 +281,8 @@ class App : public OgreBites::ApplicationContext {
// Ogre::Root::getSingleton().queueEndRendering();
mApp->setWindowGrab(false);
}
if (evt.keysym.sym == OgreBites::SDLK_SPACE)
mApp->dump_water();
if (evt.keysym.sym == 'w')
motion.z = -1.0f;
if (evt.keysym.sym == 's')
@@ -364,6 +362,7 @@ class App : public OgreBites::ApplicationContext {
mApp->updateCamera(evt.timeSinceLastFrame);
mApp->updateSun(evt.timeSinceLastFrame);
mApp->updateTerrain(evt.timeSinceLastFrame);
mApp->updateWater(evt.timeSinceLastFrame);
}
}
};
@@ -371,12 +370,9 @@ class App : public OgreBites::ApplicationContext {
public:
App()
: OgreBites::ApplicationContext("GuiTest")
: OgreBites::ApplicationContext("ChoroEditor")
, mKbd(this)
, m_edit_ui(this)
, mDynWorld(new Ogre::Bullet::DynamicsWorld(
Ogre::Vector3(0, -9.8, 0)))
, m_terrain(mDynWorld->getBtWorld())
{
}
virtual ~App()
@@ -392,13 +388,18 @@ public:
mScnMgr->addRenderQueueListener(pOverlaySystem);
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
// getRenderWindow());
mDbgDraw.reset(new Ogre::Bullet::DebugDrawer(
mScnMgr->getRootSceneNode(), mDynWorld->getBtWorld()));
}
void locateResources()
void locateResources() override
{
OgreBites::ApplicationContext::locateResources();
}
void loadResources() override
{
}
void dump_water()
{
m_water.dump_textures();
}
void initCamera()
{
@@ -429,8 +430,40 @@ public:
// our model is quite small, so reduce the clipping planes
mCamera->setNearClipDistance(0.1f);
mCamera->setFarClipDistance(800);
mPivotPitch = 0;
}
void configure()
{
std::cout << "Startup" << "\n";
initApp();
std::cout << "Set up RTSS" << "\n";
Ogre::Root *root = getRoot();
Ogre::SceneManager *scnMgr = getSceneManager();
// register our scene with the RTSS
Ogre::RTShader::ShaderGenerator *shadergen =
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(scnMgr);
setWindowGrab(true);
std::cout << "Init camera" << "\n";
initCamera();
std::cout << "Set up water" << "\n";
#if 0
m_water.createWater(getRenderWindow(), mCamera,
mDynWorld.get());
#endif
std::cout << "Set up cursor" << "\n";
Ogre::ResourceGroupManager::getSingleton()
.initialiseAllResourceGroups();
// OgreBites::ApplicationContext::loadResources();
setupCursor();
std::cout << "Create content" << "\n";
createContent();
std::cout << "Setup terrain" << "\n";
m_water.init();
}
void setupCursor()
{
// mKeyDirection = Ogre::Vector3::ZERO;
// mVerticalVelocity = 0;
Ogre::ManualObject *mobj =
@@ -473,6 +506,7 @@ public:
}
void updateMotion(float delta)
{
#if 0
if (delta == 0.0f)
return;
Ogre::Vector3 move(mCameraNode->getOrientation().zAxis() *
@@ -495,6 +529,7 @@ public:
// mKbd.motion = Ogre::Vector3(0, 0, 0);
// if (move.squaredLength() > 0)
// std::cout << move << "\n";
#endif
}
void updateCamera(Ogre::Real delta)
{
@@ -541,10 +576,12 @@ public:
mCameraGoal->translate(0, 0, distChange,
Ogre::Node::TS_LOCAL);
Ogre::Vector3 mh = mCameraGoal->_getDerivedPosition();
#if 0
float h = m_terrain.get_height(mh);
if (h + 10 > mh.y)
mCameraGoal->translate(0, 10.0f * deltaZoom, distChange,
Ogre::Node::TS_LOCAL);
#endif
}
Ogre::SceneNode *mSunGoal;
Ogre::SceneNode *mSunNode;
@@ -600,7 +637,7 @@ public:
Ogre::Timer mTerrainUpd;
void updateTerrain(float delta)
{
mDbgDraw->update();
// mDbgDraw->update();
#if 0
if (mTerrainUpd.getMilliseconds() > 1000) {
m_terrain.create_colliders();
@@ -608,15 +645,16 @@ public:
}
#endif
}
void updateWater(float delta)
{
m_water.updateWater(delta);
}
void createContent()
{
int i;
m_edit_ui.init_glb_list();
m_edit_ui.initGui();
createSun();
mInput = OgreBites::InputListenerChain(
{ getImGuiInputListener(), &mKbd });
addInputListener(&mInput);
getRoot()->addFrameListener(&mKbd);
// mTrayMgr->showCursor();
@@ -641,8 +679,6 @@ public:
"Skybox/Dynamic", "General");
OgreAssert(m, "Sky box material not found.");
m->load();
m_water.createWater(mCamera);
getRoot()->addFrameListener(&m_water);
#endif
}
void create_entity_node(const Ogre::String &name, int key)
@@ -674,11 +710,6 @@ public:
{
return mCamera;
}
void setupTerrain()
{
m_terrain.setupTerrain(mCamera, mSun, mDynWorld.get(),
mDbgDraw.get());
}
};
void EditUI::buildings_editor()
@@ -845,20 +876,9 @@ void EditUI::initGui()
int main()
{
App ctx;
ctx.initApp();
ctx.configure();
// ctx.runRenderingSettingsDialog();
// get a pointer to the already created root
Ogre::Root *root = ctx.getRoot();
Ogre::SceneManager *scnMgr = ctx.getSceneManager();
// register our scene with the RTSS
Ogre::RTShader::ShaderGenerator *shadergen =
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(scnMgr);
ctx.setWindowGrab(true);
ctx.initCamera();
ctx.createContent();
ctx.setupTerrain();
// register for input events
// KeyHandler keyHandler;
// ctx.addInputListener(&keyHandler);

855
Game.cpp Normal file
View File

@@ -0,0 +1,855 @@
#include <iostream>
#include <Ogre.h>
#include <OgreApplicationContext.h>
#include <OgreOverlaySystem.h>
#include <OgreOverlayManager.h>
#include <OgreImGuiOverlay.h>
#include <OgreImGuiInputListener.h>
#include <OgreTrays.h>
#include <OgreTimer.h>
#include <OgreMeshLodGenerator.h>
// #include "water/water.h"
#include "GameData.h"
#include "Components.h"
#include "CharacterModule.h"
#include "TerrainModule.h"
#include "GUIModuleCommon.h"
#include "AppModule.h"
#include "sound.h"
class App;
class SkyRenderer : public Ogre::SceneManager::Listener {
protected:
Ogre::SceneManager *mSceneManager;
virtual void _updateRenderQueue(Ogre::RenderQueue *queue) = 0;
public:
enum BoxPlane {
BP_FRONT = 0,
BP_BACK = 1,
BP_LEFT = 2,
BP_RIGHT = 3,
BP_UP = 4,
BP_DOWN = 5
};
SkyRenderer(Ogre::SceneManager *owner)
: mSceneManager(owner)
, mSceneNode(0)
, mEnabled(false)
{
}
virtual ~SkyRenderer()
{
setEnabled(false);
if (mSceneNode)
mSceneManager->destroySceneNode(mSceneNode);
}
Ogre::SceneNode *mSceneNode;
bool mEnabled;
void setEnabled(bool enable)
{
if (enable == mEnabled)
return;
mEnabled = enable;
enable ? mSceneManager->addListener(this) :
mSceneManager->removeListener(this);
}
void
postFindVisibleObjects(Ogre::SceneManager *source,
Ogre::SceneManager::IlluminationRenderStage irs,
Ogre::Viewport *vp) override
{
// Queue skies, if viewport seems it
if (!vp->getSkiesEnabled() ||
irs == Ogre::SceneManager::IRS_RENDER_TO_TEXTURE)
return;
if (!mEnabled || !mSceneNode)
return;
// Update nodes
// Translate the box by the camera position (constant distance)
mSceneNode->setPosition(vp->getCamera()->getDerivedPosition());
_updateRenderQueue(source->getRenderQueue());
}
};
class SkyBoxRenderer : public SkyRenderer {
std::unique_ptr<Ogre::ManualObject> mSkyBoxObj;
Ogre::Quaternion mSkyBoxOrientation;
void _updateRenderQueue(Ogre::RenderQueue *queue) override
{
if (mSkyBoxObj->isVisible()) {
mSkyBoxObj->_updateRenderQueue(queue);
}
}
public:
SkyBoxRenderer(Ogre::SceneManager *owner)
: SkyRenderer(owner)
{
}
Ogre::SceneManager::SkyBoxGenParameters mSkyBoxGenParameters;
void create(const Ogre::String &materialName, Ogre::Real distance,
uint8_t renderQueue, const Ogre::Quaternion &orientation,
const Ogre::String &groupName)
{
Ogre::MaterialPtr m =
Ogre::MaterialManager::getSingleton().getByName(
materialName, groupName);
OgreAssert(m, "Sky box material '" + materialName +
"' not found.");
// Ensure loaded
m->load();
bool valid = m->getBestTechnique() &&
m->getBestTechnique()->getNumPasses();
#if 0
if (valid) {
Pass *pass = m->getBestTechnique()->getPass(0);
valid = valid && pass->getNumTextureUnitStates() &&
pass->getTextureUnitState(0)->getTextureType() ==
TEX_TYPE_CUBE_MAP;
}
if (!valid) {
LogManager::getSingleton().logWarning(
"skybox material " + materialName +
" is not supported, defaulting");
m = MaterialManager::getSingleton().getDefaultSettings();
}
#endif
OgreAssert(valid, "Bad material" + materialName);
// Create node
mSceneNode = mSceneManager->createSceneNode();
// Create object
mSkyBoxObj = std::make_unique<Ogre::ManualObject>("SkyBox");
mSkyBoxObj->setCastShadows(false);
mSceneNode->attachObject(mSkyBoxObj.get());
mSkyBoxObj->setRenderQueueGroup(renderQueue);
mSkyBoxObj->begin(materialName,
Ogre::RenderOperation::OT_TRIANGLE_STRIP,
groupName);
// rendering cube, only using 14 vertices
const Ogre::Vector3 cube_strip[14] = {
{ -1.f, 1.f, 1.f }, // Front-top-left
{ 1.f, 1.f, 1.f }, // Front-top-right
{ -1.f, -1.f, 1.f }, // Front-bottom-left
{ 1.f, -1.f, 1.f }, // Front-bottom-right
{ 1.f, -1.f, -1.f }, // Back-bottom-right
{ 1.f, 1.f, 1.f }, // Front-top-right
{ 1.f, 1.f, -1.f }, // Back-top-right
{ -1.f, 1.f, 1.f }, // Front-top-left
{ -1.f, 1.f, -1.f }, // Back-top-left
{ -1.f, -1.f, 1.f }, // Front-bottom-left
{ -1.f, -1.f, -1.f }, // Back-bottom-left
{ 1.f, -1.f, -1.f }, // Back-bottom-right
{ -1.f, 1.f, -1.f }, // Back-top-left
{ 1.f, 1.f, -1.f } // Back-top-right
};
for (const auto &vtx : cube_strip) {
mSkyBoxObj->position(orientation * (vtx * distance));
// Note UVs mirrored front/back
mSkyBoxObj->textureCoord(vtx.normalisedCopy() *
Ogre::Vector3(1, 1, -1));
}
mSkyBoxObj->end();
mSkyBoxGenParameters.skyBoxDistance = distance;
}
};
class App;
class KeyboardListener : public OgreBites::InputListener {
App *mApp;
uint32_t control;
ECS::Vector2 mouse;
ECS::Vector2 mouse_abs;
float wheel_y;
bool mouse_moved, wheel_moved;
float mInitDelay;
public:
Ogre::Timer fps_timer;
bool fast;
KeyboardListener(App *app)
: OgreBites::InputListener()
, mApp(app)
, fast(false)
, control(0)
, mouse({ 0, 0 })
, mouse_abs({ 0, 0 })
, wheel_y(0.0f)
, mouse_moved(false)
, wheel_moved(false)
, mInitDelay(1.0)
{
}
bool isGuiEnabled()
{
if (!ECS::get().has<ECS::GUI>())
return false;
return (ECS::get().get<ECS::GUI>().enabled);
}
void setGuiEnabled(bool value)
{
if (!ECS::get().has<ECS::GUI>())
return;
ECS::get().get_mut<ECS::GUI>().enabled = value;
ECS::get().modified<ECS::GUI>();
}
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
{
bool updated = false;
if (isGuiEnabled())
return false;
if (evt.keysym.sym == OgreBites::SDLK_ESCAPE) {
OgreAssert(ECS::get().has<ECS::GUI>(), "");
setGuiEnabled(true);
if (ECS::get().has<ECS::GUI>())
ECS::get<ECS::GUI>().setWindowGrab(false);
return true;
}
OgreBites::Keycode key = evt.keysym.sym;
if (key == 'w')
control |= 1;
else if (key == 'a')
control |= 2;
else if (key == 's')
control |= 4;
else if (key == 'd')
control |= 8;
else if (key == OgreBites::SDLK_LSHIFT)
control |= 16;
else if (key == 'e')
control |= 32;
else if (key == 'f')
control |= 64;
if (key == 'w' || key == 'a' || key == 's' || key == 'd' ||
key == 'e' || key == OgreBites::SDLK_LSHIFT || key == 'e' ||
key == 'f')
return true;
return false;
}
bool keyReleased(const OgreBites::KeyboardEvent &evt) override
{
OgreBites::Keycode key = evt.keysym.sym;
if (key == 'w')
control &= ~1;
else if (key == 'a')
control &= ~2;
else if (key == 's')
control &= ~4;
else if (key == 'd')
control &= ~8;
else if (key == OgreBites::SDLK_LSHIFT)
control &= ~16;
else if (key == 'e')
control &= ~32;
else if (key == 'f')
control &= ~64;
if (isGuiEnabled())
return false;
if (key == 'w' || key == 'a' || key == 's' || key == 'd' ||
key == OgreBites::SDLK_LSHIFT || key == 'e' || key == 'f')
return true;
return false;
}
bool mouseMoved(const OgreBites::MouseMotionEvent &evt) override
{
if (isGuiEnabled())
return false;
mouse.x = evt.xrel;
mouse.y = evt.yrel;
mouse_abs.x = evt.x;
mouse_abs.y = evt.y;
mouse_moved = true;
/* no special mouse handling */
return true;
}
bool mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) override
{
if (isGuiEnabled())
return false;
/* no special mouse wheel handling */
wheel_y = evt.y;
wheel_moved = true;
return true;
}
bool mousePressed(const OgreBites::MouseButtonEvent &evt) override
{
std::cout << "Mouse press " << (int)evt.button << " "
<< (int)evt.clicks << "\n";
if ((int)evt.button == 1)
control |= 256;
else
control &= ~256;
return false;
}
void frameRendered(const Ogre::FrameEvent &evt) override;
};
class App : public OgreBites::ApplicationContext {
Ogre::SceneNode *mCameraNode, *mCameraPivot, *mCameraGoal;
Ogre::Camera *mCamera, *mCameraInterior, *mCameraInventory;
Ogre::Real mPivotPitch;
Ogre::SceneManager *mScnMgr, *mScnMgrInterior, *mScnMgrInventory;
Ogre::Viewport *mViewport;
SkyBoxRenderer *sky;
bool mGrab;
KeyboardListener mKbd;
public:
App()
: OgreBites::ApplicationContext("ChoroGame")
, mKbd(this)
, mGrab(false)
{
}
virtual ~App()
{
}
void setup() override
{
OgreBites::ApplicationContext::setup();
Ogre::Root *root = getRoot();
Ogre::SceneManager *scnMgr = root->createSceneManager();
mScnMgr = scnMgr;
mScnMgrInterior = root->createSceneManager();
mScnMgrInventory = root->createSceneManager();
Ogre::OverlaySystem *pOverlaySystem = getOverlaySystem();
mScnMgr->addRenderQueueListener(pOverlaySystem);
mScnMgrInterior->addRenderQueueListener(pOverlaySystem);
mScnMgrInventory->addRenderQueueListener(pOverlaySystem);
// mTrayMgr = new OgreBites::TrayManager("AppTrays",
// getRenderWindow());
}
bool isWindowGrab()
{
return mGrab;
}
void locateResources() override
{
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
"Water", true);
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
"LuaScripts", false);
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
"./lua-scripts", "FileSystem", "LuaScripts", true,
true);
OgreBites::ApplicationContext::locateResources();
}
void loadResources() override
{
}
void setWindowGrab(bool grab = true)
{
mGrab = grab;
ApplicationContextBase::setWindowGrab(grab);
}
void initInteriorCamera()
{
Ogre::SceneNode *cameraNode =
mScnMgrInterior->getRootSceneNode()
->createChildSceneNode("InteriorCameraNode");
cameraNode->setPosition(0, 2, 3);
cameraNode->lookAt(Ogre::Vector3(0, 1, -1),
Ogre::Node::TS_PARENT);
mCameraInterior = mScnMgr->createCamera("interior_camera");
mCameraInterior->setNearClipDistance(0.05f);
mCameraInterior->setAutoAspectRatio(true);
cameraNode->attachObject(mCameraInterior);
}
void initInventoryCamera()
{
Ogre::SceneNode *cameraNode =
mScnMgrInventory->getRootSceneNode()
->createChildSceneNode("InteriorCameraNode");
cameraNode->setPosition(0, 2, 3);
cameraNode->lookAt(Ogre::Vector3(0, 1, -1),
Ogre::Node::TS_PARENT);
mCameraInventory = mScnMgr->createCamera("inventory_camera");
mCameraInventory->setNearClipDistance(0.05f);
mCameraInventory->setAutoAspectRatio(true);
cameraNode->attachObject(mCameraInventory);
}
void initCamera()
{
mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode(
"CameraNode");
mCameraNode->setPosition(0, 2, 3);
mCameraNode->lookAt(Ogre::Vector3(0, 1, -1),
Ogre::Node::TS_PARENT);
// create the camera
mCamera = mScnMgr->createCamera("fps_camera");
mCamera->setNearClipDistance(0.05f);
mCamera->setAutoAspectRatio(true);
mCameraNode->attachObject(mCamera);
// and tell it to render into the main window
mViewport = getRenderWindow()->addViewport(mCamera);
mCameraPivot =
mScnMgr->getRootSceneNode()->createChildSceneNode(
"FPSCameraPivot");
mCameraGoal = mCameraPivot->createChildSceneNode(
"FPSCameraGoal", Ogre::Vector3(0, 2, 3));
mCameraNode->setPosition(mCameraPivot->getPosition() +
mCameraGoal->getPosition());
mCameraPivot->setFixedYawAxis(true);
mCameraGoal->setFixedYawAxis(true);
mCameraNode->setFixedYawAxis(true);
// our model is quite small, so reduce the clipping planes
mCamera->setNearClipDistance(0.1f);
mCamera->setFarClipDistance(800);
mPivotPitch = 0;
initInteriorCamera();
initInventoryCamera();
}
void configure()
{
std::cout << "Startup"
<< "\n";
initApp();
std::cout << "Set up RTSS"
<< "\n";
Ogre::Root *root = getRoot();
Ogre::SceneManager *scnMgr = getSceneManager();
// register our scene with the RTSS
Ogre::RTShader::ShaderGenerator *shadergen =
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
shadergen->addSceneManager(scnMgr);
setWindowGrab(true);
std::cout << "Init camera"
<< "\n";
initCamera();
std::cout << "Set up water"
<< "\n";
std::cout << "Set up cursor"
<< "\n";
Ogre::ResourceGroupManager::getSingleton()
.initialiseAllResourceGroups();
// OgreBites::ApplicationContext::loadResources();
// setupCursor();
std::cout << "Setup input"
<< "\n";
setupInput();
std::cout << "Create content"
<< "\n";
createContent();
std::cout << "Setup done"
<< "\n";
#if 0
mDbgDraw->setDebugMode(mDbgDraw->getDebugMode() |
btIDebugDraw::DBG_DrawContactPoints);
#endif
Ogre::LogManager::getSingleton().setMinLogLevel(
Ogre::LML_CRITICAL);
}
Ogre::SceneManager *getSceneManager()
{
return mScnMgr;
}
Ogre::Timer mTerrainUpd;
bool isTerrainReady()
{
if (ECS::get().has<ECS::Terrain>())
return ECS::get().get<ECS::Terrain>().mTerrainReady;
return false;
}
// TODO: implement rough water level calculation
float getWaterLevel(const Ogre::Vector3 &position)
{
Ogre::Vector3::UNIT_Y;
float etime =
Ogre::ControllerManager::getSingleton().getElapsedTime();
return 0.0f;
}
void updateWorld(float delta)
{
#if 0
mDynWorld->getBtWorld()->stepSimulation(delta, 3);
#endif
if (!ECS::get().has<ECS::GUI>())
goto end;
{
/* Update window grab */
ECS::GUI &gui = ECS::get().get_mut<ECS::GUI>();
if (gui.grabChanged) {
setWindowGrab(gui.grab);
gui.grabChanged = false;
ECS::get().modified<ECS::GUI>();
std::cout << "updateWorld " << gui.grabChanged
<< " " << gui.grab << std::endl;
}
}
end:
ECS::update(delta);
#if 0
if (ECS::get<ECS::EngineData>().enableDbgDraw)
mDbgDraw->update();
#endif
}
class InputListenerChainFlexible : public OgreBites::InputListener {
protected:
std::vector<OgreBites::InputListener *> mListenerChain;
public:
InputListenerChainFlexible()
{
}
InputListenerChainFlexible(std::vector<InputListener *> chain)
: mListenerChain(chain)
{
}
void add(OgreBites::InputListener *listener)
{
mListenerChain.push_back(listener);
}
void erase(OgreBites::InputListener *listener)
{
mListenerChain.erase(std::find(mListenerChain.begin(),
mListenerChain.end(),
listener));
}
bool empty() const
{
return mListenerChain.empty();
}
InputListenerChainFlexible &
operator=(const InputListenerChainFlexible &o)
{
mListenerChain = o.mListenerChain;
return *this;
}
void frameRendered(const Ogre::FrameEvent &evt) override
{
for (auto listener : mListenerChain)
listener->frameRendered(evt);
}
bool keyPressed(const OgreBites::KeyboardEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->keyPressed(evt))
return true;
}
return false;
}
bool keyReleased(const OgreBites::KeyboardEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->keyReleased(evt))
return true;
}
return false;
}
bool touchMoved(const OgreBites::TouchFingerEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->touchMoved(evt))
return true;
}
return false;
}
bool
touchPressed(const OgreBites::TouchFingerEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->touchPressed(evt))
return true;
}
return false;
}
bool
touchReleased(const OgreBites::TouchFingerEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->touchReleased(evt))
return true;
}
return false;
}
bool mouseMoved(const OgreBites::MouseMotionEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->mouseMoved(evt))
return true;
}
return false;
}
bool
mouseWheelRolled(const OgreBites::MouseWheelEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->mouseWheelRolled(evt))
return true;
}
return false;
}
bool
mousePressed(const OgreBites::MouseButtonEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->mousePressed(evt))
return true;
}
return false;
}
bool
mouseReleased(const OgreBites::MouseButtonEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->mouseReleased(evt))
return true;
}
return false;
}
bool textInput(const OgreBites::TextInputEvent &evt) override
{
for (auto listner : mListenerChain) {
if (listner->textInput(evt))
return true;
}
return false;
}
};
flecs::entity input_update;
flecs::entity find_wait_gui;
void setupInput()
{
}
void createContent()
{
int i;
sky = new SkyBoxRenderer(getSceneManager());
bool drawFirst = true;
uint8_t renderQueue = drawFirst ?
Ogre::RENDER_QUEUE_SKIES_EARLY :
Ogre::RENDER_QUEUE_SKIES_LATE;
sky->create("Skybox/Dynamic", 450, renderQueue,
Ogre::Quaternion::IDENTITY,
Ogre::ResourceGroupManager::
AUTODETECT_RESOURCE_GROUP_NAME);
sky->setEnabled(true);
Ogre::MaterialPtr m =
Ogre::MaterialManager::getSingleton().getByName(
"Skybox/Dynamic", "General");
OgreAssert(m, "Sky box material not found.");
m->load();
ECS::setupExteriorScene(mScnMgr,
/*mDynWorld.get(), */ mCameraNode,
mCamera, getRenderWindow());
ECS::get().set<ECS::RenderWindow>(
{ getRenderWindow(), getDisplayDPI() });
ECS::get()
.observer<ECS::GUI>("UpdateGrab")
.event(flecs::OnSet)
.each([this](ECS::GUI &gui) {
if (gui.grabChanged)
setWindowGrab(gui.grab);
std::cout << "grab: " << gui.grab << "\n";
std::cout << "GUI enabled: " << gui.enabled
<< "\n";
});
ECS::get()
.observer<ECS::App>("UpdateInputListener")
.event(flecs::OnSet)
.each([this](ECS::App &app) {
if (app.mInput)
removeInputListener(app.mInput);
delete app.mInput;
app.mInput =
OGRE_NEW OgreBites::InputListenerChain(
app.listeners);
addInputListener(app.mInput);
});
#if 0
ECS::get()
.observer<ECS::GUI, ECS::App>("SetInputListener2")
.event(flecs::OnSet)
.each([this](ECS::GUI &gui, ECS::App &app) {
if (gui.mGuiInpitListener &&
app.listeners.size() == 1) {
app.listeners.clear();
app.listeners.push_back(
gui.mGuiInpitListener);
app.listeners.push_back(&mKbd);
ECS::modified<ECS::App>();
}
});
#endif
#if 0
input_update =
ECS::get()
.system<ECS::GUI, ECS::App>("SetInputListener")
.kind(flecs::OnUpdate)
.each([this](ECS::GUI &gui, ECS::App &app) {
if (app.listeners.size() < 2 &&
gui.mGuiInpitListener) {
OgreBites::InputListener *guiListener =
gui.mGuiInpitListener;
if (guiListener) {
app.listeners.clear();
app.listeners.push_back(
guiListener);
app.listeners.push_back(
&mKbd);
std::cout
<< "input update complete\n";
gui.mGuiInpitListener =
guiListener;
if (app.mInput)
removeInputListener(
app.mInput);
delete app.mInput;
app.mInput = new OgreBites::
InputListenerChain(
app.listeners);
addInputListener(
app.mInput);
std::cout
<< "update listeners: "
<< app.listeners
.size()
<< "\n";
if (app.listeners
.size() ==
2)
OgreAssert(
app.listeners.size() ==
2,
"");
input_update.disable();
OgreAssert(false, "");
} else {
app.listeners.clear();
app.listeners.push_back(
&mKbd);
}
} else
input_update.disable();
std::cout << "input update "
<< app.listeners.size()
<< "\n";
});
#endif
ECS::get().set<ECS::App>(
{ initialiseImGui(),
nullptr,
{ getImGuiInputListener(), &mKbd } });
Sound::setup();
Sound::ding();
}
void create_entity_node(const Ogre::String &name, int key)
{
Ogre::Entity *ent = mScnMgr->createEntity(name);
Ogre::SceneNode *pnode =
mScnMgr->getRootSceneNode()->createChildSceneNode(
"ent:" + name +
Ogre::StringConverter::toString(key),
mCameraPivot->getPosition(),
mCameraPivot->getOrientation());
pnode->attachObject(ent);
Ogre::Quaternion q = pnode->getOrientation();
Ogre::Radian yaw = q.getYaw();
Ogre::Quaternion nq(yaw, Ogre::Vector3(0, 1, 0));
pnode->setOrientation(nq);
set_gui_active(false);
ECS::get<ECS::GUI>().setWindowGrab(true);
}
bool get_gui_active()
{
return ECS::get().get<ECS::GUI>().enabled;
}
void set_gui_active(bool active)
{
ECS::get().get_mut<ECS::GUI>().enabled = active;
ECS::get().modified<ECS::GUI>();
}
Ogre::Camera *getCamera()
{
return mCamera;
}
flecs::entity getPlayer() const
{
return ECS::player;
}
void enableDbgDraw(bool enable)
{
ECS::get_mut<ECS::EngineData>().enableDbgDraw = enable;
ECS::modified<ECS::EngineData>();
}
bool isEnabledDbgDraw() const
{
return ECS::get<ECS::EngineData>().enableDbgDraw;
}
};
void KeyboardListener::frameRendered(const Ogre::FrameEvent &evt)
{
if (fps_timer.getMilliseconds() > 1000.0f) {
std::cout << "FPS: "
<< mApp->getRenderWindow()->getStatistics().lastFPS
<< " ";
std::cout << "Draw calls: "
<< mApp->getRenderWindow()->getStatistics().batchCount
<< " ";
fps_timer.reset();
std::cout << "Drops: "
<< mApp->getRenderWindow()
->getStatistics()
.vBlankMissCount
<< "\n";
fps_timer.reset();
}
if (!isGuiEnabled() ||
(isGuiEnabled() && ECS::get<ECS::GUI>().narrationBox)) {
mApp->updateWorld(evt.timeSinceLastFrame);
if (mInitDelay >= 0.0f)
mInitDelay -= evt.timeSinceLastFrame;
}
if (!isGuiEnabled() && ECS::get().has<ECS::Input>()) {
ECS::Input &input = ECS::get().get_mut<ECS::Input>();
input.control = control;
input.mouse = mouse;
input.mouse_abs = mouse_abs;
mouse.x = 0;
mouse.y = 0;
input.wheel_y = wheel_y;
wheel_y = 0;
input.mouse_moved = mouse_moved;
input.wheel_moved = wheel_moved;
}
}
int main()
{
App ctx;
ctx.configure();
// ctx.runRenderingSettingsDialog();
// get a pointer to the already created root
// register for input events
// KeyHandler keyHandler;
// ctx.addInputListener(&keyHandler);
ctx.enableDbgDraw(false);
ctx.getRoot()->startRendering();
ctx.setWindowGrab(false);
ctx.closeApp();
return 0;
}

View File

@@ -7,10 +7,6 @@
#include "Ogre.h"
#include "OgreApplicationContext.h"
#include "Bullet/OgreBullet.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "btKinematicCharacterController.h"
#include "LinearMath/btTransform.h"
#include "OgrePageManager.h"
#include "Procedural.h"
@@ -23,11 +19,8 @@ using Real = Ogre::Real;
using Math = Ogre::Math;
class WorldData {
std::unique_ptr<Ogre::Bullet::DynamicsWorld> mDynWorld;
std::unique_ptr<Ogre::Bullet::DebugDrawer> mDbgDraw;
std::unique_ptr<Ogre::Root> mRoot;
std::unique_ptr<Ogre::SceneManager> mScnMgr;
std::unique_ptr<btDynamicsWorld> mbtWorld;
std::unique_ptr<Ogre::PageManager> mPageManager;
Ogre::PagedWorld *mPagedWorld;
@@ -63,13 +56,8 @@ private:
DummyPageProvider mDummyPageProvider;
WorldData(Ogre::Root *root, Ogre::SceneManager *scnMgr)
: mDynWorld(new Ogre::Bullet::DynamicsWorld(
Ogre::Vector3(0, -9.8, 0)))
, mDbgDraw(new Ogre::Bullet::DebugDrawer(
scnMgr->getRootSceneNode(), mDynWorld->getBtWorld()))
, mRoot(root)
: mRoot(root)
, mScnMgr(scnMgr)
, mbtWorld(mDynWorld->getBtWorld())
, mPageManager(nullptr)
, mPagedWorld(nullptr)
{
@@ -101,94 +89,8 @@ public:
void createTrimesh(Ogre::Entity *entity)
{
}
btPairCachingGhostObject *addGhostObject(Ogre::Entity *ent,
btCollisionShape *shape,
int group = 1,
int mask = 0xFFFF)
{
btDynamicsWorld *world = mDynWorld->getBtWorld();
Ogre::SceneNode *node = ent->getParentSceneNode();
btPairCachingGhostObject *ghost =
new btPairCachingGhostObject();
ghost->setCollisionShape(shape);
ghost->setCollisionFlags(
ghost->getCollisionFlags() |
btCollisionObject::CF_NO_CONTACT_RESPONSE |
btCollisionObject::CF_CHARACTER_OBJECT);
getWorld()->attachCollisionObject(ghost, ent, group, mask);
#if 0
getBtWorld()
->getBroadphase()->getOverlappingPairCache()
->setInternalGhostPairCallback(new btGhostPairCallback());
ghost->setUserPointer(new EntityCollisionListener{ent, nullptr});
#endif
return ghost;
}
btRigidBody *addRigidBody(float mass, Ogre::Entity *ent,
Ogre::Bullet::ColliderType ct, int group = 1,
int mask = 0xFFFF)
{
btDynamicsWorld *world = mDynWorld->getBtWorld();
Ogre::SceneNode *node = ent->getParentSceneNode();
Ogre::Bullet::RigidBodyState *state =
new Ogre::Bullet::RigidBodyState(node);
btCollisionShape *cs;
btCollisionShape *shape;
btVector3 inertia(0, 0, 0);
switch (ct) {
case Ogre::Bullet::CT_TRIMESH: {
cs = Ogre::Bullet::createTrimeshCollider(ent);
if (mass != 0)
cs->calculateLocalInertia(mass, inertia);
} break;
case Ogre::Bullet::CT_CAPSULE: {
cs = new btCompoundShape();
btScalar height = 1.0f;
btScalar radius = 0.3f;
shape = new btCapsuleShape(radius,
2 * height - 2 * radius);
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(0, 1, 0));
static_cast<btCompoundShape *>(cs)->addChildShape(
transform, shape);
btScalar masses[1] = { mass };
btTransform principal;
static_cast<btCompoundShape *>(cs)
->calculatePrincipalAxisTransform(
masses, principal, inertia);
} break;
default:
assert(false);
break;
}
btRigidBody *body = new btRigidBody(mass, state, cs, inertia);
getWorld()->attachRigidBody(body, ent, nullptr, group, mask);
#if 0
body->setUserPointer(new EntityCollisionListener{ent, nullptr});
// btRigidBody *body = mDynWorld->addRigidBody(0, ent, Ogre::Bullet::CT_TRIMESH);
#endif
return body;
}
btRigidBody *addKinematicRigidBody(float mass, Ogre::Entity *ent,
Ogre::Bullet::ColliderType ct,
int group = 1, int mask = 0xFFFF)
{
return mDynWorld->addKinematicRigidBody(ent, ct, group, mask);
}
btDynamicsWorld *getBtWorld()
{
return mDynWorld->getBtWorld();
}
Ogre::Bullet::DynamicsWorld *getWorld()
{
return mDynWorld.get();
}
void update(float delta)
{
WorldData::get_singleton()->getBtWorld()->stepSimulation(delta,
10);
mDbgDraw->update();
}
void initPagedWorld(Ogre::Camera *camera)
{
@@ -202,8 +104,6 @@ public:
WorldData *WorldData::singleton = nullptr;
class MainWorld : public Ogre::FrameListener {
btRigidBody *mFloorBody;
public:
void setup()
{
@@ -221,13 +121,6 @@ public:
WorldData::get_singleton()->getSceneManager();
Ogre::Entity *floor = scnMgr->createEntity("Floor", "floor");
scnMgr->getRootSceneNode()->attachObject(floor);
mFloorBody = WorldData::get_singleton()->addRigidBody(
0, floor, Ogre::Bullet::CT_TRIMESH);
}
btRigidBody *addCharacter(Ogre::Entity *ent, float mass)
{
return WorldData::get_singleton()->addKinematicRigidBody(
mass, ent, Ogre::Bullet::CT_COMPOUND);
}
bool frameStarted(const Ogre::FrameEvent &evt) override;
};
@@ -267,9 +160,6 @@ class CharacterController : public OgreBites::InputListener,
Ogre::Vector3 rootMotion;
Ogre::Quaternion rootRotation;
// btRigidBody *mRigidBody;
btCompoundShape *mCollisionShape;
btPairCachingGhostObject *mGhostObject;
btKinematicCharacterController *mController;
public:
CharacterController(Ogre::SceneNode *camNode, Ogre::Camera *cam,
@@ -318,35 +208,6 @@ private:
recoverResult *recover_result,
const std::set<btCollisionObject *> &exclude);
#endif
inline btQuaternion convert(const Ogre::Quaternion &q)
{
return btQuaternion(q.x, q.y, q.z, q.w);
}
inline btVector3 convert(const Ogre::Vector3 &v)
{
return btVector3(v.x, v.y, v.z);
}
inline btTransform convert(const Ogre::Quaternion &q,
const Ogre::Vector3 &v)
{
btQuaternion mq = convert(q);
btVector3 mv = convert(v);
return btTransform(mq, mv);
}
inline Ogre::Quaternion convert(const btQuaternion &q)
{
return Ogre::Quaternion(q.w(), q.x(), q.y(), q.z());
}
inline Ogre::Vector3 convert(const btVector3 &v)
{
return Ogre::Vector3(v.x(), v.y(), v.z());
}
inline void convert(const btTransform &from, Ogre::Quaternion &q,
Ogre::Vector3 &v)
{
q = convert(from.getRotation());
v = convert(from.getOrigin());
}
};
CharacterController::CharacterController(Ogre::SceneNode *camNode,
Ogre::Camera *cam,
@@ -360,9 +221,6 @@ CharacterController::CharacterController(Ogre::SceneNode *camNode,
, mAnimID(ANIM_NONE)
, mRunning(false)
, world(world)
, mCollisionShape(nullptr)
, mGhostObject(nullptr)
, mController(nullptr)
{
setupBody();
setupCamera();
@@ -377,72 +235,6 @@ void CharacterController::setupBody()
mBodyNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
mBodyNode->attachObject(mBodyEnt);
mSkeleton = mBodyEnt->getSkeleton();
// mRigidBody = world->addCharacter(mBodyEnt, 0);
// mCollisionShape = static_cast<btCompoundShape *>(mRigidBody->getCollisionShape());
mGhostObject = new btPairCachingGhostObject();
mCollisionShape = new btCompoundShape;
mGhostObject->setCollisionShape(mCollisionShape);
{
btVector3 inertia(0, 0, 0);
// mCollisionShape = new btCompoundShape();
btScalar height = 1.0f;
btScalar radius = 0.3f;
btCapsuleShape *shape =
new btCapsuleShape(radius, 2 * height - 2 * radius);
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(0, 1, 0));
static_cast<btCompoundShape *>(mCollisionShape)
->addChildShape(transform, shape);
btScalar masses[1] = { 0 };
btTransform principal;
static_cast<btCompoundShape *>(mCollisionShape)
->calculatePrincipalAxisTransform(masses, principal,
inertia);
}
mGhostObject->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT |
btCollisionObject::CF_NO_CONTACT_RESPONSE);
mGhostObject->setActivationState(DISABLE_DEACTIVATION);
Ogre::Bullet::KinematicMotionSimple *controller =
new Ogre::Bullet::KinematicMotionSimple(mGhostObject,
mBodyNode);
WorldData::get_singleton()->getWorld()->attachCollisionObject(
mGhostObject, mBodyEnt, btBroadphaseProxy::AllFilter,
btBroadphaseProxy::AllFilter);
WorldData::get_singleton()->getBtWorld()->addAction(controller);
assert(mCollisionShape);
#if 0
if (mRigidBody->getMass() == 0) {
#if 0
mRigidBody->setCollisionFlags(mRigidBody->getCollisionFlags()
| btCollisionObject::CF_KINEMATIC_OBJECT
| btCollisionObject::CF_NO_CONTACT_RESPONSE
);
#endif
#if 0
mGhostObject->setWorldTransform(mRigidBody->getWorldTransform());
WorldData::get_singleton()->getBtWorld()
->getBroadphase()->getOverlappingPairCache()
->setInternalGhostPairCallback(new btGhostPairCallback());
#endif
}
#endif
#if 0
mRigidBody->setActivationState(DISABLE_DEACTIVATION);
#endif
#if 0
{
Ogre::Entity *e2 = mScnMgr->createEntity("normal-male.glb");
Ogre::SceneNode *e2node = mScnMgr->getRootSceneNode()->createChildSceneNode();
e2node->attachObject(e2);
mGhostObject = WorldData::get_singleton()->addGhostObject(e2, mCollisionShape);
mController = new btKinematicCharacterController(mGhostObject, mCollisionShape, 0.5f);
WorldData::get_singleton()->getBtWorld()->addAction(mController);
}
#endif
assert(mSkeleton->hasBone("Root"));
mRootBone = mSkeleton->getBone("Root");
assert(mRootBone);
@@ -743,8 +535,6 @@ void CharacterController::updateRootMotion(Real delta)
Ogre::Vector3 velocity = rot * boneMotion / delta;
velocity += gravity * delta;
Ogre::Vector3 rotMotion = velocity * delta;
btTransform from(convert(mBodyNode->getOrientation()),
convert(mBodyNode->getPosition()));
mBodyNode->setPosition(mBodyNode->getPosition() + rotMotion);
// WorldData::get_singleton()->getWorld()->testBodyMotion(mRigidBody, from, Ogre::Bullet::convert(rotMotion), true,
// nullptr, false, std::set<btCollisionObject *>());

BIN
assets/blender/altar.blend LFS Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,31 @@
project(building-parts)
set(PARTS_FILES pier.blend)
set(FURNITURE_FILES furniture.blend furniture-sofa.blend)
set(PARTS_OUTPUT_DIRS)
foreach(PARTS_FILE ${PARTS_FILES})
get_filename_component(FILE_NAME ${PARTS_FILE} NAME_WE)
set(PARTS_OUTPUT_DIR ${CMAKE_BINARY_DIR}/resources/buildings/parts/${FILE_NAME})
add_custom_command(
OUTPUT ${PARTS_OUTPUT_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PARTS_OUTPUT_DIR}
COMMAND ${BLENDER} ${CMAKE_CURRENT_SOURCE_DIR}/${PARTS_FILE}
-b -Y -P
${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_building_parts.py
-- ${PARTS_OUTPUT_DIR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PARTS_FILE} ${CMAKE_SOURCE_DIR}/assets/blender/scripts/export_building_parts.py)
list(APPEND PARTS_OUTPUT_DIRS ${PARTS_OUTPUT_DIR})
endforeach()
foreach(FURNITURE_FILE ${FURNITURE_FILES})
get_filename_component(FILE_NAME ${FURNITURE_FILE} NAME_WE)
set(PARTS_OUTPUT_DIR ${CMAKE_BINARY_DIR}/resources/buildings/parts/${FILE_NAME})
add_custom_command(
OUTPUT ${PARTS_OUTPUT_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${PARTS_OUTPUT_DIR}
COMMAND ${BLENDER} ${CMAKE_CURRENT_SOURCE_DIR}/${FURNITURE_FILE}
-b -Y -P
${CMAKE_CURRENT_SOURCE_DIR}/export_furniture_parts.py
-- ${PARTS_OUTPUT_DIR}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PARTS_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/export_furniture_parts.py)
list(APPEND PARTS_OUTPUT_DIRS ${PARTS_OUTPUT_DIR})
endforeach()
add_custom_target(import_building_parts ALL DEPENDS ${PARTS_OUTPUT_DIRS})

View File

@@ -0,0 +1,182 @@
import bpy
import os, sys, time
import json
from mathutils import Matrix, Quaternion
argv = sys.argv
argv = argv[argv.index("--") + 1:]
incpath = os.path.dirname(__file__)
sys.path.insert(0, incpath)
outdir = argv[0]
basis_change = Matrix((
(1, 0, 0, 0),
(0, 0, 1, 0),
(0, -1, 0, 0),
(0, 0, 0, 1)
))
def export_root_objects_to_gltf(output_dir):
# Ensure the output directory exists
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Deselect all objects
bpy.ops.object.select_all(action='DESELECT')
# Iterate through all objects in the scene
for obj in bpy.context.scene.objects:
# Check if the object has no parent and has children
# The original request specifies "objects having no parent with children".
# This condition captures those that are explicitly root objects of a hierarchy.
if obj.parent is None:
# Select the root object and all its children
print(obj.name)
if not obj.name.startswith("furniture-"):
continue
desc = {}
desc["name"] = obj.name.replace("furniture-","")
desc["mesh"] = obj.name + ".glb"
if "furniture_tags" in obj:
mtags = obj["furniture_tags"]
if "," in mtags:
atags = [m.strip() for m in mtags.split(",")]
desc["tags"] = atags
else:
desc["tags"] = [mtags]
else:
desc["tags"] = []
desc["sensors"] = []
desc["actions"] = []
desc["positions"] = []
for child in obj.children:
if child.name.startswith("action-"):
if not "action" in child:
continue
if not "height" in child:
continue
if not "radius" in child:
continue
local_matrix = child.matrix_local
ogre_local_matrix = basis_change @ local_matrix @ basis_change.inverted()
local_pos_d = ogre_local_matrix.to_translation()
local_rot_d = ogre_local_matrix.to_quaternion()
local_pos = [round(x, 4) for x in local_pos_d]
local_rot = [round(x, 4) for x in local_rot_d]
action = {}
action["position_x"] = local_pos[0]
action["position_y"] = local_pos[1]
action["position_z"] = local_pos[2]
action["rotation_w"] = local_rot[0]
action["rotation_x"] = local_rot[1]
action["rotation_y"] = local_rot[2]
action["rotation_z"] = local_rot[3]
action["height"] = child["height"]
action["radius"] = child["radius"]
action["action"] = child["action"]
if "action_text" in child:
action["action_text"] = child["action_text"]
else:
action["action_text"] = child["action"].capitalize()
if "name" in child:
action["name"] = child["name"]
else:
action["name"] = desc["name"] + "_" + str(len(desc["actions"]))
action["furniture"] = {}
action["furniture"]["name"] = desc["name"]
action["furniture"]["tags"] = desc["tags"]
action["positions"] = []
for schild in child.children:
if schild.name.startswith("position-"):
local_matrix = schild.matrix_local
ogre_local_matrix = basis_change @ local_matrix @ basis_change.inverted()
local_pos_d = ogre_local_matrix.to_translation()
local_rot_d = ogre_local_matrix.to_quaternion()
local_pos = [round(x, 4) for x in local_pos_d]
local_rot = [round(x, 4) for x in local_rot_d]
position = {}
if "name" in schild:
position["name"] = schild["name"]
if "type" in schild:
position["type"] = schild["type"]
position["position_x"] = local_pos[0]
position["position_y"] = local_pos[2]
position["position_z"] = local_pos[1]
position["rotation_w"] = local_rot[0]
position["rotation_x"] = local_rot[1]
position["rotation_y"] = local_rot[2]
position["rotation_z"] = local_rot[3]
action["positions"].append(position)
desc["actions"].append(action)
if child.name.startswith("position-"):
local_matrix = child.matrix_local
ogre_local_matrix = basis_change @ local_matrix @ basis_change.inverted()
local_pos_d = ogre_local_matrix.to_translation()
local_rot_d = ogre_local_matrix.to_quaternion()
local_pos = [round(x, 4) for x in local_pos_d]
local_rot = [round(x, 4) for x in local_rot_d]
position = {}
if "name" in child:
position["name"] = child["name"]
if "type" in child:
position["type"] = child["type"]
position["position_x"] = local_pos[0]
position["position_y"] = local_pos[2]
position["position_z"] = local_pos[1]
position["rotation_w"] = local_rot[0]
position["rotation_x"] = local_rot[1]
position["rotation_y"] = local_rot[2]
position["rotation_z"] = local_rot[3]
desc["positions"].append(position)
obj.select_set(True)
for child in obj.children_recursive:
child.select_set(True)
obj.location = (0.0, 0.0, 0.0)
# Set the root object as the active object for the export operator
bpy.context.view_layer.objects.active = obj
# Define the output file path
file_path = os.path.join(output_dir, f"{obj.name}.glb")
# Export the selected objects to a glTF file
bpy.ops.export_scene.gltf(filepath=file_path,
use_selection=True,
check_existing=False,
export_format='GLB',
export_texture_dir='textures', export_texcoords=True,
export_normals=True,
export_tangents=True,
export_materials='EXPORT',
export_colors=True,
use_mesh_edges=False,
use_mesh_vertices=False,
export_cameras=False,
use_visible=False,
use_renderable=False,
export_yup=True,
export_apply=True,
export_animations=True,
export_force_sampling=True,
export_def_bones=False,
export_current_frame=False,
export_morph=True,
export_morph_animation=False,
export_morph_normal=True,
export_morph_tangent=True,
export_lights=False,
export_skins=True)
# Deselect all objects for the next iteration
bpy.ops.object.select_all(action='DESELECT')
print(f"Exported {obj.name} and its children to {file_path}")
with open(file_path + ".json", "w") as json_data:
json.dump(desc, json_data)
export_root_objects_to_gltf(outdir)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More