From e1e6a53aa613490d5284059ea9939496d23849ad Mon Sep 17 00:00:00 2001 From: Matt Penny Date: Sat, 5 Oct 2024 01:54:55 -0400 Subject: [PATCH] Convert models during CMake build No generation of dynamic model lists yet --- assets/CMakeLists.txt | 10 ++ assets/materials/CMakeLists.txt | 9 +- assets/models/CMakeLists.txt | 186 ++++++++++++++++++++++++++++ assets/sound/CMakeLists.txt | 9 +- assets/test_chambers/CMakeLists.txt | 8 +- src/CMakeLists.txt | 3 +- tools/convert_asset.py | 12 +- 7 files changed, 221 insertions(+), 16 deletions(-) create mode 100644 assets/models/CMakeLists.txt diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index 28e6b46..9d7a262 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -15,6 +15,16 @@ if(NOT EXISTS ${VALVE_INTRO_VIDEO}) endif() endif() +# Scaling factor when converting 3D assets +# +# Blender files use meters, exported FBX files use centimeters, so +# this is used to convert back to the original design-time units +set(MODEL_SCALE 0.01) + +# Scaling factor for render space +set(SCENE_SCALE 128) + add_subdirectory(materials) +add_subdirectory(models) add_subdirectory(sound) add_subdirectory(test_chambers) diff --git a/assets/materials/CMakeLists.txt b/assets/materials/CMakeLists.txt index e0661e7..efbb538 100644 --- a/assets/materials/CMakeLists.txt +++ b/assets/materials/CMakeLists.txt @@ -225,6 +225,11 @@ function(_add_texture_transform_command TEXTURE_SCRIPT OUTPUT_LIST) set(INPUT_FILE "${PAK_MATERIALS_DIR}/${TEXTURE_NAME}.png") set(OUTPUT_FILE "${PAK_MODIFIED_MATERIALS_DIR}/${TEXTURE_NAME}.png") + cmake_path( + GET OUTPUT_FILE PARENT_PATH + OUTPUT_DIR + ) + set(DEPENDENCY_FILES ${INPUT_FILE} ${TEXTURE_SCRIPT}) _get_texture_script_file_list(${TEXTURE_SCRIPT} ADDITIONAL_DEPS ${PAK_MATERIALS_DIR} DEPENDENCY_FILES) @@ -237,7 +242,9 @@ function(_add_texture_transform_command TEXTURE_SCRIPT OUTPUT_LIST) OUTPUT ${OUTPUT_FILES} COMMAND - ${PYTHON3} ${CONVERT_ASSET} + ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR} + COMMAND + ${Python3_EXECUTABLE} ${CONVERT_ASSET} ${IMAGEMAGICK_CONVERT} ${INPUT_FILE} ${TEXTURE_SCRIPT} ${OUTPUT_FILE} WORKING_DIRECTORY # TODO: Change this to PAK_MODIFIED_MATERIALS_DIR and update .ims files with relative path diff --git a/assets/models/CMakeLists.txt b/assets/models/CMakeLists.txt new file mode 100644 index 0000000..7ab0b4a --- /dev/null +++ b/assets/models/CMakeLists.txt @@ -0,0 +1,186 @@ +################## +## Model export ## +################## + +# TODO: dynamic and animated models + +set(MODELS + cube/cube + fleck_ash2 + grav_flare + pedestal + player/chell + portal_gun/ball_trail + portal_gun/v_portalgun + portal_gun/w_portalgun + portal/portal_blue + portal/portal_blue_face + portal/portal_blue_filled + portal/portal_collider + portal/portal_collider_vertical + portal/portal_orange + portal/portal_orange_face + portal/portal_orange_filled + props/autoportal_frame/autoportal_frame + props/box_dropper + props/box_dropper_glass + props/button + props/combine_ball_catcher + props/combine_ball_launcher + props/cylinder_test + props/door_01 + props/door_02 + props/lab_chair + props/lab_desk/lab_desk01 + props/lab_desk/lab_desk02 + props/lab_desk/lab_desk03 + props/lab_desk/lab_desk04 + props/lab_monitor + props/light_rail_endcap + props/portal_cleanser + props/radio + props/round_elevator + props/round_elevator_collision + props/round_elevator_interior + props/security_camera + props/signage + props/switch001 + signage/clock + signage/clock_digits +) + +# Most models depend on both of these. Some only depend on one or the other, +# but use both for simplicity. Otherwise there would be many special cases. +set(MODEL_DEFAULT_MATERIALS + ${ASSETS_DIR}/materials/static.skm.yaml + ${ASSETS_DIR}/materials/objects.skm.yaml +) + +function(_add_model_export_command MODEL_NAME OUTPUT_VARIABLE) + cmake_path( + RELATIVE_PATH CMAKE_CURRENT_SOURCE_DIR + BASE_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE RELATIVE_CURRENT_DIR + ) + + set(INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}.blend") + set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/${RELATIVE_CURRENT_DIR}/${MODEL_NAME}.fbx") + + cmake_path( + GET OUTPUT_FILE PARENT_PATH + OUTPUT_DIR + ) + + add_custom_command( + DEPENDS + ${EXPORT_FBX} ${INPUT_FILE} + OUTPUT + ${OUTPUT_FILE} + COMMAND + ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR} + COMMAND + ${BLENDER_3_6} ${INPUT_FILE} --background --python ${EXPORT_FBX} -- ${OUTPUT_FILE} + COMMENT + "Exporting $" + VERBATIM + ) + + set(${OUTPUT_VARIABLE} ${OUTPUT_FILE}) + return(PROPAGATE ${OUTPUT_VARIABLE}) +endfunction() + +function(_add_model_generate_command MODEL_NAME MODEL_FBX OUTPUT_LIST) + set(MODEL_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}.flags") + set(MODEL_MATERIALS ${MODEL_DEFAULT_MATERIALS}) + + get_source_file_property(FILE_MATERIALS ${MODEL_FLAGS} ADDITIONAL_MATERIALS) + if (FILE_MATERIALS) + list(APPEND MODEL_MATERIALS ${FILE_MATERIALS}) + endif() + + cmake_path( + REMOVE_EXTENSION MODEL_FBX + OUTPUT_VARIABLE OUTPUT_FILE_NO_EXTENSION + ) + cmake_path( + GET OUTPUT_FILE_NO_EXTENSION PARENT_PATH + OUTPUT_DIR + ) + + set(OUTPUT_FILE_H "${OUTPUT_FILE_NO_EXTENSION}.h") + set(OUTPUT_FILE_GEO_C "${OUTPUT_FILE_NO_EXTENSION}_geo.c") + + # TODO: not all models have animations + # set(OUTPUT_FILE_ANIM_C "${OUTPUT_FILE_NO_EXTENSION}_anim.c") + + add_custom_command( + DEPENDS + ${CONVERT_ASSET} ${MODEL_FBX} ${MODEL_FLAGS} ${MODEL_MATERIALS} + OUTPUT + ${OUTPUT_FILE_H} ${OUTPUT_FILE_GEO_C} ${OUTPUT_FILE_ANIM_C} + COMMAND + ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR} + COMMAND + ${CONVERT_ASSET} + ${SKELETOOL64} + ${MODEL_FBX} + ${MODEL_FLAGS} + --fixed-point-scale ${SCENE_SCALE} + --model-scale ${MODEL_SCALE} + --name ${MODEL_NAME} + --output ${OUTPUT_FILE_H} + WORKING_DIRECTORY + ${PROJECT_SOURCE_DIR} + COMMENT + "Generating model ${MODEL_NAME}" + VERBATIM + ) + + list(APPEND ${OUTPUT_LIST} + ${OUTPUT_FILE_H} + ${OUTPUT_FILE_GEO_C} + ${OUTPUT_FILE_ANIM_C} + ) + return(PROPAGATE ${OUTPUT_LIST}) +endfunction() + + +# Add commands for exporting model files +# There are some special cases for models which use non-default materials + +set_property(SOURCE player/chell.flags + PROPERTY ADDITIONAL_MATERIALS + ${ASSETS_DIR}/materials/chell.skm.yaml +) + +set_property(SOURCE props/combine_ball_launcher.flags + PROPERTY ADDITIONAL_MATERIALS + ${ASSETS_DIR}/materials/ball_catcher.skm.yaml +) + +set_property(SOURCE props/combine_ball_catcher.flags + PROPERTY ADDITIONAL_MATERIALS + ${ASSETS_DIR}/materials/ball_catcher.skm.yaml +) + +set_property(SOURCE props/round_elevator.flags + PROPERTY ADDITIONAL_MATERIALS + ${ASSETS_DIR}/materials/elevator.skm.yaml +) + +set_property(SOURCE props/round_elevator_interior.flags + PROPERTY ADDITIONAL_MATERIALS + ${ASSETS_DIR}/materials/elevator.skm.yaml +) + +set(MODEL_GENERATED_FILES "") + +foreach(MODEL ${MODELS}) + _add_model_export_command(${MODEL} MODEL_FBX) + _add_model_generate_command(${MODEL} ${MODEL_FBX} MODEL_GENERATED_FILES) +endforeach() + +add_custom_target( + models + DEPENDS ${MODEL_GENERATED_FILES} +) diff --git a/assets/sound/CMakeLists.txt b/assets/sound/CMakeLists.txt index aacf45b..c98f67a 100644 --- a/assets/sound/CMakeLists.txt +++ b/assets/sound/CMakeLists.txt @@ -238,13 +238,20 @@ function(_add_sound_transform_command SOUND_SCRIPT OUTPUT_LIST) endfunction() function(_add_sound_transform_command_sox SOUND_SCRIPT INPUT_FILE OUTPUT_FILE) + cmake_path( + GET OUTPUT_FILE PARENT_PATH + OUTPUT_DIR + ) + add_custom_command( DEPENDS extract_vpks ${CONVERT_ASSET} ${INPUT_FILE} ${SOUND_SCRIPT} OUTPUT ${OUTPUT_FILE} COMMAND - ${PYTHON3} ${CONVERT_ASSET} ${SOX} ${INPUT_FILE} ${SOUND_SCRIPT} ${OUTPUT_FILE} + ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR} + COMMAND + ${Python3_EXECUTABLE} ${CONVERT_ASSET} ${SOX} ${INPUT_FILE} ${SOUND_SCRIPT} ${OUTPUT_FILE} COMMENT "Transforming $" VERBATIM diff --git a/assets/test_chambers/CMakeLists.txt b/assets/test_chambers/CMakeLists.txt index 64c779e..bf5bdfb 100644 --- a/assets/test_chambers/CMakeLists.txt +++ b/assets/test_chambers/CMakeLists.txt @@ -8,9 +8,6 @@ cmake_path( ## Level export ## ################## -set(SCENE_SCALE 128) -set(MODEL_SCALE 0.01) - set(LEVELS test_chamber_00 test_chamber_01 @@ -31,6 +28,7 @@ set(LEVEL_MATERIALS set(EXPORT_LEVEL ${PROJECT_SOURCE_DIR}/tools/level_scripts/export_level.lua) set(EXPORT_SCRIPTS + ${EXPORT_LEVEL} ${PROJECT_SOURCE_DIR}/tools/level_scripts/animation.lua ${PROJECT_SOURCE_DIR}/tools/level_scripts/collision_export.lua ${PROJECT_SOURCE_DIR}/tools/level_scripts/dynamic_collision_export.lua @@ -95,7 +93,7 @@ function(_add_level_generate_command LEVEL_NAME LEVEL_FBX OUTPUT_LIST) add_custom_command( DEPENDS - ${EXPORT_LEVEL} ${LEVEL_FBX} ${LEVEL_YAML} ${LEVEL_MATERIALS} + ${EXPORT_SCRIPTS} ${LEVEL_FBX} ${LEVEL_YAML} ${LEVEL_MATERIALS} OUTPUT ${OUTPUT_FILE_H} ${OUTPUT_FILE_GEO_C} ${OUTPUT_FILE_ANIM_C} COMMAND @@ -146,7 +144,7 @@ set(LEVEL_LIST "${LEVEL_LIST_OUT_DIR}/level_list.h") add_custom_command( DEPENDS - ${GENERATE_LEVEL_LIST} ${LEVEL_GENERATED_HEADERS} + ${GEN_LEVEL_LIST} ${LEVEL_GENERATED_HEADERS} OUTPUT ${LEVEL_LIST} COMMAND diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ce20e8..1df51ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,8 +11,9 @@ add_dependencies(portal materials sound_tables - # TODO: rework when including chambers in compilation + # TODO: rework when including models in compilation level_list + models ) ############### diff --git a/tools/convert_asset.py b/tools/convert_asset.py index 620aef6..00f2273 100644 --- a/tools/convert_asset.py +++ b/tools/convert_asset.py @@ -11,18 +11,14 @@ import sys # such files in a cross-platform way. if __name__ == "__main__": - if len(sys.argv) != 5: + if len(sys.argv) < 4: print("Runs a specified command with the given input and output file paths") print("The command's arguments are read from a file") print() - print(f"Usage: {sys.argv[0]} COMMAND INPUT_FILE ARGS_FILE OUTPUT_FILE") + print(f"Usage: {sys.argv[0]} COMMAND INPUT_FILE ARGS_FILE [ARG]...") sys.exit(1) - command, input_file, args_file, output_file = sys.argv[1:] - - output_parent_dir = os.path.dirname(output_file) - if output_parent_dir: - os.makedirs(output_parent_dir, exist_ok=True) + command, input_file, args_file, *additional_args = sys.argv[1:] with open(args_file) as f: args = shlex.split(f.read().strip()) @@ -31,6 +27,6 @@ if __name__ == "__main__": command, input_file, *args, - output_file + *additional_args ]) sys.exit(rc.returncode)