Convert models during CMake build

No generation of dynamic model lists yet
This commit is contained in:
Matt Penny 2024-10-05 01:54:55 -04:00
parent 1e8a4f5458
commit e1e6a53aa6
7 changed files with 221 additions and 16 deletions

View file

@ -15,6 +15,16 @@ if(NOT EXISTS ${VALVE_INTRO_VIDEO})
endif() endif()
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(materials)
add_subdirectory(models)
add_subdirectory(sound) add_subdirectory(sound)
add_subdirectory(test_chambers) add_subdirectory(test_chambers)

View file

@ -225,6 +225,11 @@ function(_add_texture_transform_command TEXTURE_SCRIPT OUTPUT_LIST)
set(INPUT_FILE "${PAK_MATERIALS_DIR}/${TEXTURE_NAME}.png") set(INPUT_FILE "${PAK_MATERIALS_DIR}/${TEXTURE_NAME}.png")
set(OUTPUT_FILE "${PAK_MODIFIED_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}) set(DEPENDENCY_FILES ${INPUT_FILE} ${TEXTURE_SCRIPT})
_get_texture_script_file_list(${TEXTURE_SCRIPT} ADDITIONAL_DEPS ${PAK_MATERIALS_DIR} DEPENDENCY_FILES) _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
${OUTPUT_FILES} ${OUTPUT_FILES}
COMMAND COMMAND
${PYTHON3} ${CONVERT_ASSET} ${CMAKE_COMMAND} -E make_directory ${OUTPUT_DIR}
COMMAND
${Python3_EXECUTABLE} ${CONVERT_ASSET}
${IMAGEMAGICK_CONVERT} ${INPUT_FILE} ${TEXTURE_SCRIPT} ${OUTPUT_FILE} ${IMAGEMAGICK_CONVERT} ${INPUT_FILE} ${TEXTURE_SCRIPT} ${OUTPUT_FILE}
WORKING_DIRECTORY WORKING_DIRECTORY
# TODO: Change this to PAK_MODIFIED_MATERIALS_DIR and update .ims files with relative path # TODO: Change this to PAK_MODIFIED_MATERIALS_DIR and update .ims files with relative path

View file

@ -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 $<PATH:RELATIVE_PATH,${INPUT_FILE},${PROJECT_SOURCE_DIR}>"
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}
)

View file

@ -238,13 +238,20 @@ function(_add_sound_transform_command SOUND_SCRIPT OUTPUT_LIST)
endfunction() endfunction()
function(_add_sound_transform_command_sox SOUND_SCRIPT INPUT_FILE OUTPUT_FILE) function(_add_sound_transform_command_sox SOUND_SCRIPT INPUT_FILE OUTPUT_FILE)
cmake_path(
GET OUTPUT_FILE PARENT_PATH
OUTPUT_DIR
)
add_custom_command( add_custom_command(
DEPENDS DEPENDS
extract_vpks ${CONVERT_ASSET} ${INPUT_FILE} ${SOUND_SCRIPT} extract_vpks ${CONVERT_ASSET} ${INPUT_FILE} ${SOUND_SCRIPT}
OUTPUT OUTPUT
${OUTPUT_FILE} ${OUTPUT_FILE}
COMMAND 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 COMMENT
"Transforming $<PATH:RELATIVE_PATH,${INPUT_FILE},${PROJECT_SOURCE_DIR}>" "Transforming $<PATH:RELATIVE_PATH,${INPUT_FILE},${PROJECT_SOURCE_DIR}>"
VERBATIM VERBATIM

View file

@ -8,9 +8,6 @@ cmake_path(
## Level export ## ## Level export ##
################## ##################
set(SCENE_SCALE 128)
set(MODEL_SCALE 0.01)
set(LEVELS set(LEVELS
test_chamber_00 test_chamber_00
test_chamber_01 test_chamber_01
@ -31,6 +28,7 @@ set(LEVEL_MATERIALS
set(EXPORT_LEVEL ${PROJECT_SOURCE_DIR}/tools/level_scripts/export_level.lua) set(EXPORT_LEVEL ${PROJECT_SOURCE_DIR}/tools/level_scripts/export_level.lua)
set(EXPORT_SCRIPTS set(EXPORT_SCRIPTS
${EXPORT_LEVEL}
${PROJECT_SOURCE_DIR}/tools/level_scripts/animation.lua ${PROJECT_SOURCE_DIR}/tools/level_scripts/animation.lua
${PROJECT_SOURCE_DIR}/tools/level_scripts/collision_export.lua ${PROJECT_SOURCE_DIR}/tools/level_scripts/collision_export.lua
${PROJECT_SOURCE_DIR}/tools/level_scripts/dynamic_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( add_custom_command(
DEPENDS DEPENDS
${EXPORT_LEVEL} ${LEVEL_FBX} ${LEVEL_YAML} ${LEVEL_MATERIALS} ${EXPORT_SCRIPTS} ${LEVEL_FBX} ${LEVEL_YAML} ${LEVEL_MATERIALS}
OUTPUT OUTPUT
${OUTPUT_FILE_H} ${OUTPUT_FILE_GEO_C} ${OUTPUT_FILE_ANIM_C} ${OUTPUT_FILE_H} ${OUTPUT_FILE_GEO_C} ${OUTPUT_FILE_ANIM_C}
COMMAND COMMAND
@ -146,7 +144,7 @@ set(LEVEL_LIST "${LEVEL_LIST_OUT_DIR}/level_list.h")
add_custom_command( add_custom_command(
DEPENDS DEPENDS
${GENERATE_LEVEL_LIST} ${LEVEL_GENERATED_HEADERS} ${GEN_LEVEL_LIST} ${LEVEL_GENERATED_HEADERS}
OUTPUT OUTPUT
${LEVEL_LIST} ${LEVEL_LIST}
COMMAND COMMAND

View file

@ -11,8 +11,9 @@ add_dependencies(portal
materials materials
sound_tables sound_tables
# TODO: rework when including chambers in compilation # TODO: rework when including models in compilation
level_list level_list
models
) )
############### ###############

View file

@ -11,18 +11,14 @@ import sys
# such files in a cross-platform way. # such files in a cross-platform way.
if __name__ == "__main__": 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("Runs a specified command with the given input and output file paths")
print("The command's arguments are read from a file") print("The command's arguments are read from a file")
print() 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) sys.exit(1)
command, input_file, args_file, output_file = sys.argv[1:] command, input_file, args_file, *additional_args = sys.argv[1:]
output_parent_dir = os.path.dirname(output_file)
if output_parent_dir:
os.makedirs(output_parent_dir, exist_ok=True)
with open(args_file) as f: with open(args_file) as f:
args = shlex.split(f.read().strip()) args = shlex.split(f.read().strip())
@ -31,6 +27,6 @@ if __name__ == "__main__":
command, command,
input_file, input_file,
*args, *args,
output_file *additional_args
]) ])
sys.exit(rc.returncode) sys.exit(rc.returncode)