From b8569121b6f46c77c26123eb100f665d4f7b0569 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Thu, 30 Dec 2021 00:14:36 +0300 Subject: [PATCH] Temp commit. Will delete later --- extern/src/cimgui.h | 567 +- extern/src/cimgui_impl.h | 8 +- extern/src/libdeflate.h | 4 +- extern/src/x264.h | 1019 --- extern/src/x264_config.h | 8 - src/CLOUD/Classes/glitter_editor.h | 22 - src/CLOUD/classes.c | 214 +- src/CLOUD/classes.h | 52 +- src/CLOUD/classes/data_player.c | 201 - src/CLOUD/classes/data_player.h | 21 - src/CLOUD/classes/data_test.c | 87 +- src/CLOUD/classes/data_test.h | 9 +- src/CLOUD/classes/data_test/auth_3d_test.c | 588 ++ src/CLOUD/classes/data_test/auth_3d_test.h | 17 + src/CLOUD/classes/data_test/glitter_test.c | 409 +- src/CLOUD/classes/data_test/glitter_test.h | 14 +- src/CLOUD/classes/data_test/stage_test.c | 471 ++ src/CLOUD/classes/data_test/stage_test.h | 17 + src/CLOUD/classes/data_view.c | 55 + src/CLOUD/classes/data_view.h | 16 + src/CLOUD/classes/data_view/auth_3d.c | 998 +++ src/CLOUD/classes/data_view/auth_3d.h | 15 + src/CLOUD/classes/data_view/draw_task.c | 247 + src/CLOUD/classes/data_view/draw_task.h | 15 + .../{Classes => classes}/glitter_editor.c | 3596 ++++++---- src/CLOUD/classes/glitter_editor.h | 19 + src/CLOUD/classes/graphics.c | 122 +- src/CLOUD/classes/graphics.h | 3 +- src/CLOUD/classes/graphics/background_color.c | 88 +- src/CLOUD/classes/graphics/background_color.h | 14 +- src/CLOUD/classes/graphics/glitter.c | 97 + src/CLOUD/classes/graphics/glitter.h | 15 + src/CLOUD/classes/graphics/glitter_counter.c | 122 - src/CLOUD/classes/graphics/glitter_counter.h | 16 - src/CLOUD/classes/graphics/post_process.c | 251 +- src/CLOUD/classes/graphics/post_process.h | 13 +- src/CLOUD/classes/graphics/render_settings.c | 120 +- src/CLOUD/classes/graphics/render_settings.h | 13 +- src/CLOUD/classes/imgui_helper.c | 767 ++- src/CLOUD/classes/imgui_helper.h | 40 +- src/CLOUD/classes/information.c | 32 + src/CLOUD/classes/information.h | 15 + src/CLOUD/classes/information/frame_speed.c | 70 + src/CLOUD/classes/information/frame_speed.h | 15 + src/CLOUD/control.c | 44 - src/CLOUD/input.c | 28 +- src/CLOUD/main.c | 218 +- src/CLOUD/main.h | 2 - src/CLOUD/render.c | 1188 ++-- src/CLOUD/shared.c | 161 +- src/CLOUD/shared.h | 7 +- src/CLOUD/sound.c | 9 +- src/CLOUD/unedat.h | 2 +- src/CLOUD/video.c | 53 - src/CRE/Glitter/curve.c | 10 +- src/CRE/Glitter/curve_get_value.c | 2 +- src/CRE/Glitter/diva_resource.c | 4 +- src/CRE/Glitter/diva_resource.h | 2 +- src/CRE/Glitter/effect.c | 31 +- src/CRE/Glitter/effect_group.c | 104 +- src/CRE/Glitter/effect_group.h | 9 +- src/CRE/Glitter/effect_inst.c | 245 +- src/CRE/Glitter/effect_inst.h | 4 +- src/CRE/Glitter/emitter_inst.c | 2 +- src/CRE/Glitter/file_reader.c | 26 +- src/CRE/Glitter/file_reader.h | 2 +- src/CRE/Glitter/glitter.c | 9 +- src/CRE/Glitter/glitter.h | 55 +- src/CRE/Glitter/list.c | 2 +- src/CRE/Glitter/locus_history.c | 2 +- src/CRE/Glitter/particle.c | 37 +- src/CRE/Glitter/particle_inst.c | 4 +- src/CRE/Glitter/particle_manager.c | 24 +- src/CRE/Glitter/particle_manager.h | 4 +- src/CRE/Glitter/random.c | 12 +- src/CRE/Glitter/render_element.c | 2 +- src/CRE/Glitter/render_group.c | 325 +- src/CRE/Glitter/render_scene.c | 2 +- src/CRE/Glitter/render_scene.h | 2 +- src/CRE/Glitter/scene.c | 4 +- src/CRE/Glitter/shared.c | 40 +- src/CRE/Glitter/shared.h | 8 +- src/CRE/Glitter/texture.c | 71 +- src/CRE/Glitter/texture.h | 4 +- src/CRE/GlitterX/effect_inst_x.c | 65 +- src/CRE/GlitterX/effect_inst_x.h | 2 +- src/CRE/GlitterX/emitter_inst_x.c | 21 +- src/CRE/GlitterX/locus_history_x.c | 2 +- src/CRE/GlitterX/render_element_x.c | 4 +- src/CRE/GlitterX/render_group_x.c | 361 +- src/CRE/GlitterX/render_scene_x.c | 2 +- src/CRE/GlitterX/render_scene_x.h | 2 +- src/CRE/auth_3d.c | 3481 ++++++++++ src/CRE/auth_3d.h | 653 ++ src/CRE/camera.c | 145 +- src/CRE/camera.h | 25 +- src/CRE/data.c | 777 +++ src/CRE/data.h | 120 + src/CRE/dof.c | 74 - src/CRE/dof.h | 46 - src/CRE/draw_object.c | 1722 +++++ src/CRE/draw_object.h | 35 + src/CRE/draw_pass.c | 1288 +++- src/CRE/draw_pass.h | 34 +- src/CRE/draw_primitive.c | 6 + src/CRE/draw_primitive.h | 12 + src/CRE/draw_task.c | 966 +++ src/CRE/draw_task.h | 47 + src/CRE/fbo.c | 11 + src/CRE/fbo.h | 3 + src/CRE/fbo_hdr.c | 82 - src/CRE/fbo_hdr.h | 32 - src/CRE/fbo_helper.c | 40 - src/CRE/fbo_helper.h | 18 - src/CRE/fbo_pp.c | 424 -- src/CRE/fbo_pp.h | 39 - src/CRE/fbo_render.c | 77 - src/CRE/fbo_render.h | 28 - src/CRE/gl_state.c | 115 +- src/CRE/gl_state.h | 48 + src/CRE/hash.c | 2 +- .../moti.c => CRE/interpolation/motion.c} | 45 +- src/CRE/interpolation/motion.h | 38 + src/CRE/light_param.c | 369 + src/CRE/light_param.h | 55 + src/CRE/light_param/face.c | 45 + src/CRE/light_param/face.h | 28 + src/CRE/light_param/fog.c | 105 + src/CRE/light_param/fog.h | 35 + src/CRE/light_param/light.c | 450 ++ src/CRE/light_param/light.h | 83 + src/CRE/light_param/wind.c | 103 + src/CRE/light_param/wind.h | 46 + src/CRE/lock.c | 30 + src/CRE/lock.h | 17 +- src/CRE/object.c | 1533 +++++ src/CRE/object.h | 625 ++ src/CRE/post_process.c | 785 +-- src/CRE/post_process.h | 146 +- src/CRE/post_process/aa.c | 268 + src/CRE/post_process/aa.h | 24 + src/CRE/post_process/blur.c | 338 + src/CRE/post_process/blur.h | 42 + src/CRE/post_process/dof.c | 227 +- src/CRE/post_process/dof.h | 58 +- src/CRE/post_process/exposure.c | 67 + src/CRE/post_process/exposure.h | 22 + src/CRE/post_process/tone_map.c | 435 ++ src/CRE/post_process/tone_map.h | 101 + src/CRE/render_context.c | 1172 ++++ src/CRE/render_context.h | 527 ++ src/CRE/render_texture.c | 193 +- src/CRE/render_texture.h | 21 +- src/CRE/rob.c | 5963 +++++++++++++++++ src/CRE/rob.h | 1105 +++ src/CRE/shader.c | 1056 ++- src/CRE/shader.h | 238 +- src/CRE/shader_aft.h | 77 - src/CRE/{shader_aft.c => shader_ft.c} | 709 +- src/CRE/shader_ft.h | 79 + src/CRE/shader_glsl.c | 46 +- src/CRE/stage.c | 287 + src/CRE/stage.h | 39 + src/CRE/static_var.c | 89 +- src/CRE/static_var.h | 45 +- src/CRE/texture.c | 125 +- src/CRE/texture.h | 29 +- src/CRE/time.c | 20 +- src/CRE/time.h | 4 +- src/CRE/timer.c | 65 +- src/CRE/timer.h | 15 +- src/CRE/vertex.c | 341 - src/CRE/vertex.h | 65 - src/CRE/video_x264.c | 962 --- src/CRE/video_x264.h | 136 - src/DivaGL/DivaGL.rc | 46 + src/DivaGL/DivaGL.vcxproj | 402 ++ src/DivaGL/DivaGL.vcxproj.user | 39 + src/DivaGL/bone_data.c | 3274 +++++++++ src/DivaGL/bone_data.h | 3717 ++++++++++ src/DivaGL/dllmain.c | 36 + src/DivaGL/gl.c | 60 + src/DivaGL/gl.h | 39 + src/DivaGL/inject.c | 122 + src/DivaGL/inject.h | 16 + src/DivaGL/print.c | 22 + src/DivaGL/print.h | 11 + src/DivaGL/shader_table.c | 213 + src/DivaGL/shader_table.h | 212 + src/KKdLib/a3da.c | 3594 ++++++++++ src/KKdLib/a3da.h | 488 ++ src/KKdLib/a3da_data.c | 38 - src/KKdLib/a3da_data.h | 28 - src/KKdLib/a3dai.c | 287 - src/KKdLib/a3dai.h | 37 - src/KKdLib/aet.c | 15 + src/KKdLib/aet.h | 115 +- src/KKdLib/auth_3d.h | 106 - src/KKdLib/{auth_3d.c => database/aet.c} | 2 +- .../control.h => KKdLib/database/aet.h} | 4 +- src/KKdLib/database/auth_3d.c | 466 ++ src/KKdLib/database/auth_3d.h | 78 + src/KKdLib/database/bone.c | 1479 ++++ src/KKdLib/database/bone.h | 103 + src/KKdLib/database/motion.c | 519 ++ src/KKdLib/database/motion.h | 59 + src/KKdLib/database/object.c | 906 +++ src/KKdLib/database/object.h | 80 + src/KKdLib/database/sprite.c | 6 + .../video.h => KKdLib/database/sprite.h} | 6 +- src/KKdLib/database/stage.c | 525 ++ src/KKdLib/database/stage.h | 163 + src/KKdLib/database/string_array.c | 6 + src/KKdLib/database/string_array.h | 8 + src/KKdLib/database/texture.c | 516 ++ src/KKdLib/database/texture.h | 44 + src/KKdLib/dds.c | 4 +- src/KKdLib/default.c | 3 + src/KKdLib/default.h | 24 +- src/KKdLib/{io_deflate.c => deflate.c} | 2 +- src/KKdLib/{io_deflate.h => deflate.h} | 0 src/KKdLib/divafile.c | 75 +- src/KKdLib/divafile.h | 4 + src/KKdLib/dsc.c | 1604 +++-- src/KKdLib/dsc.h | 59 +- src/KKdLib/{f2_enrs.c => f2/enrs.c} | 75 +- src/KKdLib/{f2_enrs.h => f2/enrs.h} | 6 +- src/KKdLib/{f2_header.c => f2/header.c} | 2 +- src/KKdLib/{f2_header.h => f2/header.h} | 4 +- src/KKdLib/{f2_pof.c => f2/pof.c} | 18 +- src/KKdLib/{f2_pof.h => f2/pof.h} | 12 +- src/KKdLib/{f2_struct.c => f2/struct.c} | 51 +- src/KKdLib/{f2_struct.h => f2/struct.h} | 12 +- src/KKdLib/farc.c | 164 +- src/KKdLib/farc.h | 23 +- src/KKdLib/half_t.c | 5 + src/KKdLib/half_t.h | 4 + src/KKdLib/hash.c | 55 +- src/KKdLib/hash.h | 17 +- src/KKdLib/{io_json.c => io/json.c} | 30 +- src/KKdLib/{io_json.h => io/json.h} | 6 +- src/KKdLib/{io_msgpack.c => io/msgpack.c} | 29 +- src/KKdLib/{io_msgpack.h => io/msgpack.h} | 6 +- src/KKdLib/io/path.c | 544 ++ src/KKdLib/io/path.h | 27 + src/KKdLib/{io_stream.c => io/stream.c} | 72 +- src/KKdLib/{io_stream.h => io/stream.h} | 15 +- src/KKdLib/io_path.c | 145 - src/KKdLib/io_path.h | 19 - src/KKdLib/key_val.c | 495 ++ src/KKdLib/key_val.h | 56 + src/KKdLib/kf.c | 13 +- src/KKdLib/kf.h | 10 + src/KKdLib/kkc.c | 52 +- src/KKdLib/kkc.h | 2 +- src/KKdLib/kkfs.c | 14 +- src/KKdLib/kkfs.h | 14 +- src/KKdLib/light_param/face.c | 214 + src/KKdLib/light_param/face.h | 28 + src/KKdLib/light_param/fog.c | 270 + src/KKdLib/light_param/fog.h | 51 + src/KKdLib/light_param/glow.c | 340 + src/KKdLib/light_param/glow.h | 54 + src/KKdLib/light_param/ibl.c | 445 ++ src/KKdLib/light_param/ibl.h | 39 + src/KKdLib/light_param/light.c | 436 ++ src/KKdLib/light_param/light.h | 78 + src/KKdLib/light_param/wind.c | 240 + src/KKdLib/light_param/wind.h | 40 + src/KKdLib/mat.c | 703 +- src/KKdLib/mat.h | 45 +- src/KKdLib/mot.c | 1565 +++-- src/KKdLib/mot.h | 66 +- src/KKdLib/moti.h | 36 - src/KKdLib/msgpack.c | 59 +- src/KKdLib/msgpack.h | 2 +- src/KKdLib/obj.c | 4301 ++++++------ src/KKdLib/obj.h | 382 +- src/KKdLib/pv_db.h | 843 +-- src/KKdLib/quat.c | 37 +- src/KKdLib/sort.c | 292 +- src/KKdLib/sort.h | 12 +- src/KKdLib/{sound_diva.c => sound/diva.c} | 8 +- src/KKdLib/{sound_diva.h => sound/diva.h} | 2 +- src/KKdLib/{sound_vag.c => sound/vag.c} | 30 +- src/KKdLib/{sound_vag.h => sound/vag.h} | 2 +- src/KKdLib/{sound_wav.c => sound/wav.c} | 4 +- src/KKdLib/{sound_wav.h => sound/wav.h} | 2 +- src/KKdLib/str_utils.c | 306 + src/KKdLib/str_utils.h | 17 + src/KKdLib/string.c | 268 +- src/KKdLib/string.h | 37 +- src/KKdLib/txp.c | 151 +- src/KKdLib/txp.h | 16 +- src/KKdLib/types.h | 1 + src/KKdLib/vec.c | 24 + src/KKdLib/vec.h | 66 +- src/KKdLib/vector.c | 22 - src/KKdLib/vector.h | 215 +- thirdparty.txt | 344 - 300 files changed, 61488 insertions(+), 15863 deletions(-) delete mode 100644 extern/src/x264.h delete mode 100644 extern/src/x264_config.h delete mode 100644 src/CLOUD/Classes/glitter_editor.h delete mode 100644 src/CLOUD/classes/data_player.c delete mode 100644 src/CLOUD/classes/data_player.h create mode 100644 src/CLOUD/classes/data_test/auth_3d_test.c create mode 100644 src/CLOUD/classes/data_test/auth_3d_test.h create mode 100644 src/CLOUD/classes/data_test/stage_test.c create mode 100644 src/CLOUD/classes/data_test/stage_test.h create mode 100644 src/CLOUD/classes/data_view.c create mode 100644 src/CLOUD/classes/data_view.h create mode 100644 src/CLOUD/classes/data_view/auth_3d.c create mode 100644 src/CLOUD/classes/data_view/auth_3d.h create mode 100644 src/CLOUD/classes/data_view/draw_task.c create mode 100644 src/CLOUD/classes/data_view/draw_task.h rename src/CLOUD/{Classes => classes}/glitter_editor.c (63%) create mode 100644 src/CLOUD/classes/glitter_editor.h create mode 100644 src/CLOUD/classes/graphics/glitter.c create mode 100644 src/CLOUD/classes/graphics/glitter.h delete mode 100644 src/CLOUD/classes/graphics/glitter_counter.c delete mode 100644 src/CLOUD/classes/graphics/glitter_counter.h create mode 100644 src/CLOUD/classes/information.c create mode 100644 src/CLOUD/classes/information.h create mode 100644 src/CLOUD/classes/information/frame_speed.c create mode 100644 src/CLOUD/classes/information/frame_speed.h delete mode 100644 src/CLOUD/control.c delete mode 100644 src/CLOUD/video.c create mode 100644 src/CRE/auth_3d.c create mode 100644 src/CRE/auth_3d.h create mode 100644 src/CRE/data.c create mode 100644 src/CRE/data.h delete mode 100644 src/CRE/dof.c delete mode 100644 src/CRE/dof.h create mode 100644 src/CRE/draw_object.c create mode 100644 src/CRE/draw_object.h create mode 100644 src/CRE/draw_primitive.c create mode 100644 src/CRE/draw_primitive.h create mode 100644 src/CRE/draw_task.c create mode 100644 src/CRE/draw_task.h delete mode 100644 src/CRE/fbo_hdr.c delete mode 100644 src/CRE/fbo_hdr.h delete mode 100644 src/CRE/fbo_helper.c delete mode 100644 src/CRE/fbo_helper.h delete mode 100644 src/CRE/fbo_pp.c delete mode 100644 src/CRE/fbo_pp.h delete mode 100644 src/CRE/fbo_render.c delete mode 100644 src/CRE/fbo_render.h rename src/{KKdLib/moti.c => CRE/interpolation/motion.c} (67%) create mode 100644 src/CRE/interpolation/motion.h create mode 100644 src/CRE/light_param.c create mode 100644 src/CRE/light_param.h create mode 100644 src/CRE/light_param/face.c create mode 100644 src/CRE/light_param/face.h create mode 100644 src/CRE/light_param/fog.c create mode 100644 src/CRE/light_param/fog.h create mode 100644 src/CRE/light_param/light.c create mode 100644 src/CRE/light_param/light.h create mode 100644 src/CRE/light_param/wind.c create mode 100644 src/CRE/light_param/wind.h create mode 100644 src/CRE/object.c create mode 100644 src/CRE/object.h create mode 100644 src/CRE/post_process/aa.c create mode 100644 src/CRE/post_process/aa.h create mode 100644 src/CRE/post_process/blur.c create mode 100644 src/CRE/post_process/blur.h create mode 100644 src/CRE/post_process/exposure.c create mode 100644 src/CRE/post_process/exposure.h create mode 100644 src/CRE/post_process/tone_map.c create mode 100644 src/CRE/post_process/tone_map.h create mode 100644 src/CRE/render_context.c create mode 100644 src/CRE/render_context.h create mode 100644 src/CRE/rob.c create mode 100644 src/CRE/rob.h delete mode 100644 src/CRE/shader_aft.h rename src/CRE/{shader_aft.c => shader_ft.c} (69%) create mode 100644 src/CRE/shader_ft.h create mode 100644 src/CRE/stage.c create mode 100644 src/CRE/stage.h delete mode 100644 src/CRE/vertex.c delete mode 100644 src/CRE/vertex.h delete mode 100644 src/CRE/video_x264.c delete mode 100644 src/CRE/video_x264.h create mode 100644 src/DivaGL/DivaGL.rc create mode 100644 src/DivaGL/DivaGL.vcxproj create mode 100644 src/DivaGL/DivaGL.vcxproj.user create mode 100644 src/DivaGL/bone_data.c create mode 100644 src/DivaGL/bone_data.h create mode 100644 src/DivaGL/dllmain.c create mode 100644 src/DivaGL/gl.c create mode 100644 src/DivaGL/gl.h create mode 100644 src/DivaGL/inject.c create mode 100644 src/DivaGL/inject.h create mode 100644 src/DivaGL/print.c create mode 100644 src/DivaGL/print.h create mode 100644 src/DivaGL/shader_table.c create mode 100644 src/DivaGL/shader_table.h create mode 100644 src/KKdLib/a3da.c create mode 100644 src/KKdLib/a3da.h delete mode 100644 src/KKdLib/a3da_data.c delete mode 100644 src/KKdLib/a3da_data.h delete mode 100644 src/KKdLib/a3dai.c delete mode 100644 src/KKdLib/a3dai.h create mode 100644 src/KKdLib/aet.c delete mode 100644 src/KKdLib/auth_3d.h rename src/KKdLib/{auth_3d.c => database/aet.c} (73%) rename src/{CLOUD/control.h => KKdLib/database/aet.h} (53%) create mode 100644 src/KKdLib/database/auth_3d.c create mode 100644 src/KKdLib/database/auth_3d.h create mode 100644 src/KKdLib/database/bone.c create mode 100644 src/KKdLib/database/bone.h create mode 100644 src/KKdLib/database/motion.c create mode 100644 src/KKdLib/database/motion.h create mode 100644 src/KKdLib/database/object.c create mode 100644 src/KKdLib/database/object.h create mode 100644 src/KKdLib/database/sprite.c rename src/{CLOUD/video.h => KKdLib/database/sprite.h} (53%) create mode 100644 src/KKdLib/database/stage.c create mode 100644 src/KKdLib/database/stage.h create mode 100644 src/KKdLib/database/string_array.c create mode 100644 src/KKdLib/database/string_array.h create mode 100644 src/KKdLib/database/texture.c create mode 100644 src/KKdLib/database/texture.h rename src/KKdLib/{io_deflate.c => deflate.c} (99%) rename src/KKdLib/{io_deflate.h => deflate.h} (100%) rename src/KKdLib/{f2_enrs.c => f2/enrs.c} (95%) rename src/KKdLib/{f2_enrs.h => f2/enrs.h} (91%) rename src/KKdLib/{f2_header.c => f2/header.c} (98%) rename src/KKdLib/{f2_header.h => f2/header.h} (95%) rename src/KKdLib/{f2_pof.c => f2/pof.c} (92%) rename src/KKdLib/{f2_pof.h => f2/pof.h} (63%) rename src/KKdLib/{f2_struct.c => f2/struct.c} (92%) rename src/KKdLib/{f2_struct.h => f2/struct.h} (85%) rename src/KKdLib/{io_json.c => io/json.c} (96%) rename src/KKdLib/{io_json.h => io/json.h} (72%) rename src/KKdLib/{io_msgpack.c => io/msgpack.c} (96%) rename src/KKdLib/{io_msgpack.h => io/msgpack.h} (72%) create mode 100644 src/KKdLib/io/path.c create mode 100644 src/KKdLib/io/path.h rename src/KKdLib/{io_stream.c => io/stream.c} (90%) rename src/KKdLib/{io_stream.h => io/stream.h} (93%) delete mode 100644 src/KKdLib/io_path.c delete mode 100644 src/KKdLib/io_path.h create mode 100644 src/KKdLib/key_val.c create mode 100644 src/KKdLib/key_val.h create mode 100644 src/KKdLib/light_param/face.c create mode 100644 src/KKdLib/light_param/face.h create mode 100644 src/KKdLib/light_param/fog.c create mode 100644 src/KKdLib/light_param/fog.h create mode 100644 src/KKdLib/light_param/glow.c create mode 100644 src/KKdLib/light_param/glow.h create mode 100644 src/KKdLib/light_param/ibl.c create mode 100644 src/KKdLib/light_param/ibl.h create mode 100644 src/KKdLib/light_param/light.c create mode 100644 src/KKdLib/light_param/light.h create mode 100644 src/KKdLib/light_param/wind.c create mode 100644 src/KKdLib/light_param/wind.h delete mode 100644 src/KKdLib/moti.h rename src/KKdLib/{sound_diva.c => sound/diva.c} (98%) rename src/KKdLib/{sound_diva.h => sound/diva.h} (95%) rename src/KKdLib/{sound_vag.c => sound/vag.c} (98%) rename src/KKdLib/{sound_vag.h => sound/vag.h} (96%) rename src/KKdLib/{sound_wav.c => sound/wav.c} (99%) rename src/KKdLib/{sound_wav.h => sound/wav.h} (96%) diff --git a/extern/src/cimgui.h b/extern/src/cimgui.h index 7865352e..d44c8bc4 100644 --- a/extern/src/cimgui.h +++ b/extern/src/cimgui.h @@ -1,8 +1,5 @@ -//This file is automatically generated by generator.lua from https://github.com/cimgui/cimgui -//based on imgui.h file version "1.82" from Dear ImGui https://github.com/ocornut/imgui -//with imgui_internal.h api -#ifndef CIMGUI_INCLUDED -#define CIMGUI_INCLUDED +#pragma once + #include #include #if defined _WIN32 || defined __CYGWIN__ @@ -41,9 +38,13 @@ typedef unsigned __int64 ImU64; #ifdef CIMGUI_DEFINE_ENUMS_AND_STRUCTS typedef struct ImGuiTableColumnSettings ImGuiTableColumnSettings; typedef struct ImGuiTableCellData ImGuiTableCellData; +typedef struct ImGuiStackTool ImGuiStackTool; +typedef struct ImGuiStackLevelInfo ImGuiStackLevelInfo; typedef struct ImGuiViewportP ImGuiViewportP; typedef struct ImGuiPtrOrIndex ImGuiPtrOrIndex; typedef struct ImGuiShrinkWidthItem ImGuiShrinkWidthItem; +typedef struct ImGuiWindowStackData ImGuiWindowStackData; +typedef struct ImGuiComboPreviewData ImGuiComboPreviewData; typedef struct ImGuiDataTypeTempStorage ImGuiDataTypeTempStorage; typedef struct ImVec2ih ImVec2ih; typedef struct ImVec1 ImVec1; @@ -56,6 +57,7 @@ typedef struct ImGuiWindowTempData ImGuiWindowTempData; typedef struct ImGuiWindow ImGuiWindow; typedef struct ImGuiTableColumnsSettings ImGuiTableColumnsSettings; typedef struct ImGuiTableSettings ImGuiTableSettings; +typedef struct ImGuiTableTempData ImGuiTableTempData; typedef struct ImGuiTableColumn ImGuiTableColumn; typedef struct ImGuiTable ImGuiTable; typedef struct ImGuiTabItem ImGuiTabItem; @@ -69,9 +71,9 @@ typedef struct ImGuiOldColumnData ImGuiOldColumnData; typedef struct ImGuiNextItemData ImGuiNextItemData; typedef struct ImGuiNextWindowData ImGuiNextWindowData; typedef struct ImGuiMetricsConfig ImGuiMetricsConfig; -typedef struct ImGuiNavMoveResult ImGuiNavMoveResult; +typedef struct ImGuiNavItemData ImGuiNavItemData; typedef struct ImGuiMenuColumns ImGuiMenuColumns; -typedef struct ImGuiLastItemDataBackup ImGuiLastItemDataBackup; +typedef struct ImGuiLastItemData ImGuiLastItemData; typedef struct ImGuiInputTextState ImGuiInputTextState; typedef struct ImGuiGroupData ImGuiGroupData; typedef struct ImGuiDataTypeInfo ImGuiDataTypeInfo; @@ -179,14 +181,8 @@ typedef int ImGuiTreeNodeFlags; typedef int ImGuiViewportFlags; typedef int ImGuiWindowFlags; typedef void* ImTextureID; +typedef unsigned short ImDrawIdx; typedef unsigned int ImGuiID; -typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); -typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); -typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); -typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); -typedef unsigned short ImWchar16; -typedef unsigned int ImWchar32; -typedef ImWchar16 ImWchar; typedef signed char ImS8; typedef unsigned char ImU8; typedef signed short ImS16; @@ -195,8 +191,14 @@ typedef signed int ImS32; typedef unsigned int ImU32; typedef int64_t ImS64; typedef uint64_t ImU64; +typedef unsigned short ImWchar16; +typedef unsigned int ImWchar32; +typedef ImWchar16 ImWchar; +typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); +typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); +typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); +typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); -typedef unsigned short ImDrawIdx; struct ImBitVector; struct ImRect; struct ImDrawDataBuilder; @@ -207,9 +209,9 @@ struct ImGuiContextHook; struct ImGuiDataTypeInfo; struct ImGuiGroupData; struct ImGuiInputTextState; -struct ImGuiLastItemDataBackup; +struct ImGuiLastItemData; struct ImGuiMenuColumns; -struct ImGuiNavMoveResult; +struct ImGuiNavItemData; struct ImGuiMetricsConfig; struct ImGuiNextWindowData; struct ImGuiNextItemData; @@ -223,12 +225,14 @@ struct ImGuiTabBar; struct ImGuiTabItem; struct ImGuiTable; struct ImGuiTableColumn; +struct ImGuiTableTempData; struct ImGuiTableSettings; struct ImGuiTableColumnsSettings; struct ImGuiWindow; struct ImGuiWindowTempData; struct ImGuiWindowSettings; typedef int ImGuiLayoutType; +typedef int ImGuiActivateFlags; typedef int ImGuiItemFlags; typedef int ImGuiItemStatusFlags; typedef int ImGuiOldColumnFlags; @@ -237,6 +241,7 @@ typedef int ImGuiNavDirSourceFlags; typedef int ImGuiNavMoveFlags; typedef int ImGuiNextItemDataFlags; typedef int ImGuiNextWindowDataFlags; +typedef int ImGuiScrollFlags; typedef int ImGuiSeparatorFlags; typedef int ImGuiTextFlags; typedef int ImGuiTooltipFlags; @@ -275,13 +280,16 @@ typedef struct ImVector_ImGuiPopupData {int Size;int Capacity;ImGuiPopupData* Da typedef struct ImVector_ImGuiPtrOrIndex {int Size;int Capacity;ImGuiPtrOrIndex* Data;} ImVector_ImGuiPtrOrIndex; typedef struct ImVector_ImGuiSettingsHandler {int Size;int Capacity;ImGuiSettingsHandler* Data;} ImVector_ImGuiSettingsHandler; typedef struct ImVector_ImGuiShrinkWidthItem {int Size;int Capacity;ImGuiShrinkWidthItem* Data;} ImVector_ImGuiShrinkWidthItem; +typedef struct ImVector_ImGuiStackLevelInfo {int Size;int Capacity;ImGuiStackLevelInfo* Data;} ImVector_ImGuiStackLevelInfo; typedef struct ImVector_ImGuiStoragePair {int Size;int Capacity;ImGuiStoragePair* Data;} ImVector_ImGuiStoragePair; typedef struct ImVector_ImGuiStyleMod {int Size;int Capacity;ImGuiStyleMod* Data;} ImVector_ImGuiStyleMod; typedef struct ImVector_ImGuiTabItem {int Size;int Capacity;ImGuiTabItem* Data;} ImVector_ImGuiTabItem; typedef struct ImVector_ImGuiTableColumnSortSpecs {int Size;int Capacity;ImGuiTableColumnSortSpecs* Data;} ImVector_ImGuiTableColumnSortSpecs; +typedef struct ImVector_ImGuiTableTempData {int Size;int Capacity;ImGuiTableTempData* Data;} ImVector_ImGuiTableTempData; typedef struct ImVector_ImGuiTextRange {int Size;int Capacity;ImGuiTextRange* Data;} ImVector_ImGuiTextRange; typedef struct ImVector_ImGuiViewportPPtr {int Size;int Capacity;ImGuiViewportP** Data;} ImVector_ImGuiViewportPPtr; typedef struct ImVector_ImGuiWindowPtr {int Size;int Capacity;ImGuiWindow** Data;} ImVector_ImGuiWindowPtr; +typedef struct ImVector_ImGuiWindowStackData {int Size;int Capacity;ImGuiWindowStackData* Data;} ImVector_ImGuiWindowStackData; typedef struct ImVector_ImTextureID {int Size;int Capacity;ImTextureID* Data;} ImVector_ImTextureID; typedef struct ImVector_ImU32 {int Size;int Capacity;ImU32* Data;} ImVector_ImU32; typedef struct ImVector_ImVec2 {int Size;int Capacity;ImVec2* Data;} ImVector_ImVec2; @@ -352,9 +360,7 @@ typedef enum { ImGuiInputTextFlags_NoUndoRedo = 1 << 16, ImGuiInputTextFlags_CharsScientific = 1 << 17, ImGuiInputTextFlags_CallbackResize = 1 << 18, - ImGuiInputTextFlags_CallbackEdit = 1 << 19, - ImGuiInputTextFlags_Multiline = 1 << 20, - ImGuiInputTextFlags_NoMarkEdited = 1 << 21 + ImGuiInputTextFlags_CallbackEdit = 1 << 19 }ImGuiInputTextFlags_; typedef enum { ImGuiTreeNodeFlags_None = 0, @@ -470,26 +476,28 @@ typedef enum { }ImGuiTableFlags_; typedef enum { ImGuiTableColumnFlags_None = 0, - ImGuiTableColumnFlags_DefaultHide = 1 << 0, - ImGuiTableColumnFlags_DefaultSort = 1 << 1, - ImGuiTableColumnFlags_WidthStretch = 1 << 2, - ImGuiTableColumnFlags_WidthFixed = 1 << 3, - ImGuiTableColumnFlags_NoResize = 1 << 4, - ImGuiTableColumnFlags_NoReorder = 1 << 5, - ImGuiTableColumnFlags_NoHide = 1 << 6, - ImGuiTableColumnFlags_NoClip = 1 << 7, - ImGuiTableColumnFlags_NoSort = 1 << 8, - ImGuiTableColumnFlags_NoSortAscending = 1 << 9, - ImGuiTableColumnFlags_NoSortDescending = 1 << 10, - ImGuiTableColumnFlags_NoHeaderWidth = 1 << 11, - ImGuiTableColumnFlags_PreferSortAscending = 1 << 12, - ImGuiTableColumnFlags_PreferSortDescending = 1 << 13, - ImGuiTableColumnFlags_IndentEnable = 1 << 14, - ImGuiTableColumnFlags_IndentDisable = 1 << 15, - ImGuiTableColumnFlags_IsEnabled = 1 << 20, - ImGuiTableColumnFlags_IsVisible = 1 << 21, - ImGuiTableColumnFlags_IsSorted = 1 << 22, - ImGuiTableColumnFlags_IsHovered = 1 << 23, + ImGuiTableColumnFlags_Disabled = 1 << 0, + ImGuiTableColumnFlags_DefaultHide = 1 << 1, + ImGuiTableColumnFlags_DefaultSort = 1 << 2, + ImGuiTableColumnFlags_WidthStretch = 1 << 3, + ImGuiTableColumnFlags_WidthFixed = 1 << 4, + ImGuiTableColumnFlags_NoResize = 1 << 5, + ImGuiTableColumnFlags_NoReorder = 1 << 6, + ImGuiTableColumnFlags_NoHide = 1 << 7, + ImGuiTableColumnFlags_NoClip = 1 << 8, + ImGuiTableColumnFlags_NoSort = 1 << 9, + ImGuiTableColumnFlags_NoSortAscending = 1 << 10, + ImGuiTableColumnFlags_NoSortDescending = 1 << 11, + ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, + ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, + ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, + ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, + ImGuiTableColumnFlags_IndentEnable = 1 << 16, + ImGuiTableColumnFlags_IndentDisable = 1 << 17, + ImGuiTableColumnFlags_IsEnabled = 1 << 24, + ImGuiTableColumnFlags_IsVisible = 1 << 25, + ImGuiTableColumnFlags_IsSorted = 1 << 26, + ImGuiTableColumnFlags_IsHovered = 1 << 27, ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, @@ -510,6 +518,7 @@ typedef enum { ImGuiFocusedFlags_ChildWindows = 1 << 0, ImGuiFocusedFlags_RootWindow = 1 << 1, ImGuiFocusedFlags_AnyWindow = 1 << 2, + ImGuiFocusedFlags_NoPopupHierarchy = 1 << 3, ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows }ImGuiFocusedFlags_; typedef enum { @@ -517,10 +526,11 @@ typedef enum { ImGuiHoveredFlags_ChildWindows = 1 << 0, ImGuiHoveredFlags_RootWindow = 1 << 1, ImGuiHoveredFlags_AnyWindow = 1 << 2, - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, - ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, + ImGuiHoveredFlags_NoPopupHierarchy = 1 << 3, + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 5, + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, + ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows }ImGuiHoveredFlags_; @@ -612,13 +622,12 @@ typedef enum { ImGuiNavInput_FocusNext, ImGuiNavInput_TweakSlow, ImGuiNavInput_TweakFast, - ImGuiNavInput_KeyMenu_, ImGuiNavInput_KeyLeft_, ImGuiNavInput_KeyRight_, ImGuiNavInput_KeyUp_, ImGuiNavInput_KeyDown_, ImGuiNavInput_COUNT, - ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ + ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyLeft_ }ImGuiNavInput_; typedef enum { ImGuiConfigFlags_None = 0, @@ -696,6 +705,7 @@ typedef enum { }ImGuiCol_; typedef enum { ImGuiStyleVar_Alpha, + ImGuiStyleVar_DisabledAlpha, ImGuiStyleVar_WindowPadding, ImGuiStyleVar_WindowRounding, ImGuiStyleVar_WindowBorderSize, @@ -754,11 +764,11 @@ typedef enum { ImGuiColorEditFlags_PickerHueWheel = 1 << 26, ImGuiColorEditFlags_InputRGB = 1 << 27, ImGuiColorEditFlags_InputHSV = 1 << 28, - ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, - ImGuiColorEditFlags__DisplayMask = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, - ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, - ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, - ImGuiColorEditFlags__InputMask = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV + ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, + ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, + ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, + ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, + ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV }ImGuiColorEditFlags_; typedef enum { ImGuiSliderFlags_None = 0, @@ -797,6 +807,7 @@ typedef enum { struct ImGuiStyle { float Alpha; + float DisabledAlpha; ImVec2 WindowPadding; float WindowRounding; float WindowBorderSize; @@ -899,7 +910,9 @@ struct ImGuiIO int MetricsActiveWindows; int MetricsActiveAllocations; ImVec2 MouseDelta; + bool WantCaptureMouseUnlessPopupClose; ImGuiKeyModFlags KeyMods; + ImGuiKeyModFlags KeyModsPrev; ImVec2 MousePosPrev; ImVec2 MouseClickedPos[5]; double MouseClickedTime[5]; @@ -907,6 +920,7 @@ struct ImGuiIO bool MouseDoubleClicked[5]; bool MouseReleased[5]; bool MouseDownOwned[5]; + bool MouseDownOwnedUnlessPopupClose[5]; bool MouseDownWasDoubleClick[5]; float MouseDownDuration[5]; float MouseDownDurationPrev[5]; @@ -917,6 +931,7 @@ struct ImGuiIO float NavInputsDownDuration[ImGuiNavInput_COUNT]; float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; float PenPressure; + bool AppFocusLost; ImWchar16 InputQueueSurrogate; ImVector_ImWchar InputQueueCharacters; }; @@ -1154,6 +1169,7 @@ struct ImFontAtlas int TexDesiredWidth; int TexGlyphPadding; bool Locked; + bool TexReady; bool TexPixelsUseColors; unsigned char* TexPixelsAlpha8; unsigned int* TexPixelsRGBA32; @@ -1183,6 +1199,7 @@ struct ImFont short ConfigDataCount; ImWchar FallbackChar; ImWchar EllipsisChar; + ImWchar DotChar; bool DirtyLookupTables; float Scale; float Ascent, Descent; @@ -1284,7 +1301,7 @@ typedef enum { ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, ImGuiItemFlags_MixedValue = 1 << 6, ImGuiItemFlags_ReadOnly = 1 << 7, - ImGuiItemFlags_Default_ = 0 + ImGuiItemFlags_Inputable = 1 << 8 }ImGuiItemFlags_; typedef enum { ImGuiItemStatusFlags_None = 0, @@ -1295,8 +1312,14 @@ typedef enum { ImGuiItemStatusFlags_ToggledOpen = 1 << 4, ImGuiItemStatusFlags_HasDeactivated = 1 << 5, ImGuiItemStatusFlags_Deactivated = 1 << 6, - ImGuiItemStatusFlags_HoveredWindow = 1 << 7 + ImGuiItemStatusFlags_HoveredWindow = 1 << 7, + ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8 }ImGuiItemStatusFlags_; +typedef enum { + ImGuiInputTextFlags_Multiline = 1 << 26, + ImGuiInputTextFlags_NoMarkEdited = 1 << 27, + ImGuiInputTextFlags_MergedItem = 1 << 28 +}ImGuiInputTextFlagsPrivate_; typedef enum { ImGuiButtonFlags_PressedOnClick = 1 << 4, ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, @@ -1308,7 +1331,6 @@ typedef enum { ImGuiButtonFlags_FlattenChildren = 1 << 11, ImGuiButtonFlags_AllowItemOverlap = 1 << 12, ImGuiButtonFlags_DontClosePopups = 1 << 13, - ImGuiButtonFlags_Disabled = 1 << 14, ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, ImGuiButtonFlags_NoKeyModifiers = 1 << 16, ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, @@ -1317,18 +1339,22 @@ typedef enum { ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold, ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease }ImGuiButtonFlagsPrivate_; +typedef enum { + ImGuiComboFlags_CustomPreview = 1 << 20 +}ImGuiComboFlagsPrivate_; typedef enum { ImGuiSliderFlags_Vertical = 1 << 20, ImGuiSliderFlags_ReadOnly = 1 << 21 }ImGuiSliderFlagsPrivate_; typedef enum { ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, - ImGuiSelectableFlags_SelectOnClick = 1 << 21, - ImGuiSelectableFlags_SelectOnRelease = 1 << 22, - ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, - ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 24, - ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, - ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26 + ImGuiSelectableFlags_SelectOnNav = 1 << 21, + ImGuiSelectableFlags_SelectOnClick = 1 << 22, + ImGuiSelectableFlags_SelectOnRelease = 1 << 23, + ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, + ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 25, + ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26, + ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 27 }ImGuiSelectableFlagsPrivate_; typedef enum { ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20 @@ -1373,6 +1399,7 @@ typedef enum { ImGuiInputSource_Keyboard, ImGuiInputSource_Gamepad, ImGuiInputSource_Nav, + ImGuiInputSource_Clipboard, ImGuiInputSource_COUNT }ImGuiInputSource; typedef enum { @@ -1383,39 +1410,6 @@ typedef enum { ImGuiInputReadMode_RepeatSlow, ImGuiInputReadMode_RepeatFast }ImGuiInputReadMode; -typedef enum { - ImGuiNavHighlightFlags_None = 0, - ImGuiNavHighlightFlags_TypeDefault = 1 << 0, - ImGuiNavHighlightFlags_TypeThin = 1 << 1, - ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, - ImGuiNavHighlightFlags_NoRounding = 1 << 3 -}ImGuiNavHighlightFlags_; -typedef enum { - ImGuiNavDirSourceFlags_None = 0, - ImGuiNavDirSourceFlags_Keyboard = 1 << 0, - ImGuiNavDirSourceFlags_PadDPad = 1 << 1, - ImGuiNavDirSourceFlags_PadLStick = 1 << 2 -}ImGuiNavDirSourceFlags_; -typedef enum { - ImGuiNavMoveFlags_None = 0, - ImGuiNavMoveFlags_LoopX = 1 << 0, - ImGuiNavMoveFlags_LoopY = 1 << 1, - ImGuiNavMoveFlags_WrapX = 1 << 2, - ImGuiNavMoveFlags_WrapY = 1 << 3, - ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, - ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, - ImGuiNavMoveFlags_ScrollToEdge = 1 << 6 -}ImGuiNavMoveFlags_; -typedef enum { - ImGuiNavForward_None, - ImGuiNavForward_ForwardQueued, - ImGuiNavForward_ForwardActive -}ImGuiNavForward; -typedef enum { - ImGuiNavLayer_Main = 0, - ImGuiNavLayer_Menu = 1, - ImGuiNavLayer_COUNT -}ImGuiNavLayer; typedef enum { ImGuiPopupPositionPolicy_Default, ImGuiPopupPositionPolicy_ComboBox, @@ -1447,6 +1441,15 @@ struct ImGuiStyleMod ImGuiStyleVar VarIdx; union { int BackupInt[2]; float BackupFloat[2]; }; }; +struct ImGuiComboPreviewData +{ + ImRect PreviewRect; + ImVec2 BackupCursorPos; + ImVec2 BackupCursorMaxPos; + ImVec2 BackupCursorPosPrevLine; + float BackupPrevLineTextBaseOffset; + ImGuiLayoutType BackupLayout; +}; struct ImGuiGroupData { ImGuiID WindowID; @@ -1463,9 +1466,14 @@ struct ImGuiGroupData }; struct ImGuiMenuColumns { - float Spacing; - float Width, NextWidth; - float Pos[3], NextWidths[3]; + ImU32 TotalWidth; + ImU32 NextTotalWidth; + ImU16 Spacing; + ImU16 OffsetIcon; + ImU16 OffsetLabel; + ImU16 OffsetShortcut; + ImU16 OffsetMark; + ImU16 Widths[4]; }; struct ImGuiInputTextState { @@ -1482,7 +1490,7 @@ struct ImGuiInputTextState bool CursorFollow; bool SelectedAllMouseLock; bool Edited; - ImGuiInputTextFlags UserFlags; + ImGuiInputTextFlags Flags; ImGuiInputTextCallback UserCallback; void* UserCallbackData; }; @@ -1496,16 +1504,6 @@ struct ImGuiPopupData ImVec2 OpenPopupPos; ImVec2 OpenMousePos; }; -struct ImGuiNavMoveResult -{ - ImGuiWindow* Window; - ImGuiID ID; - ImGuiID FocusScopeId; - float DistBox; - float DistCenter; - float DistAxial; - ImRect RectRel; -}; typedef enum { ImGuiNextWindowDataFlags_None = 0, ImGuiNextWindowDataFlags_HasPos = 1 << 0, @@ -1548,6 +1546,33 @@ struct ImGuiNextItemData ImGuiCond OpenCond; bool OpenVal; }; +struct ImGuiLastItemData +{ + ImGuiID ID; + ImGuiItemFlags InFlags; + ImGuiItemStatusFlags StatusFlags; + ImRect Rect; + ImRect NavRect; + ImRect DisplayRect; +}; +struct ImGuiStackSizes +{ + short SizeOfIDStack; + short SizeOfColorStack; + short SizeOfStyleVarStack; + short SizeOfFontStack; + short SizeOfFocusScopeStack; + short SizeOfGroupStack; + short SizeOfItemFlagsStack; + short SizeOfBeginPopupStack; + short SizeOfDisabledStack; +}; +struct ImGuiWindowStackData +{ + ImGuiWindow* Window; + ImGuiLastItemData ParentLastItemDataBackup; + ImGuiStackSizes StackSizesOnBegin; +}; struct ImGuiShrinkWidthItem { int Index; @@ -1558,6 +1583,68 @@ struct ImGuiPtrOrIndex void* Ptr; int Index; }; +typedef enum { + ImGuiActivateFlags_None = 0, + ImGuiActivateFlags_PreferInput = 1 << 0, + ImGuiActivateFlags_PreferTweak = 1 << 1, + ImGuiActivateFlags_TryToPreserveState = 1 << 2 +}ImGuiActivateFlags_; +typedef enum { + ImGuiScrollFlags_None = 0, + ImGuiScrollFlags_KeepVisibleEdgeX = 1 << 0, + ImGuiScrollFlags_KeepVisibleEdgeY = 1 << 1, + ImGuiScrollFlags_KeepVisibleCenterX = 1 << 2, + ImGuiScrollFlags_KeepVisibleCenterY = 1 << 3, + ImGuiScrollFlags_AlwaysCenterX = 1 << 4, + ImGuiScrollFlags_AlwaysCenterY = 1 << 5, + ImGuiScrollFlags_NoScrollParent = 1 << 6, + ImGuiScrollFlags_MaskX_ = ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleCenterX | ImGuiScrollFlags_AlwaysCenterX, + ImGuiScrollFlags_MaskY_ = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY +}ImGuiScrollFlags_; +typedef enum { + ImGuiNavHighlightFlags_None = 0, + ImGuiNavHighlightFlags_TypeDefault = 1 << 0, + ImGuiNavHighlightFlags_TypeThin = 1 << 1, + ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, + ImGuiNavHighlightFlags_NoRounding = 1 << 3 +}ImGuiNavHighlightFlags_; +typedef enum { + ImGuiNavDirSourceFlags_None = 0, + ImGuiNavDirSourceFlags_Keyboard = 1 << 0, + ImGuiNavDirSourceFlags_PadDPad = 1 << 1, + ImGuiNavDirSourceFlags_PadLStick = 1 << 2 +}ImGuiNavDirSourceFlags_; +typedef enum { + ImGuiNavMoveFlags_None = 0, + ImGuiNavMoveFlags_LoopX = 1 << 0, + ImGuiNavMoveFlags_LoopY = 1 << 1, + ImGuiNavMoveFlags_WrapX = 1 << 2, + ImGuiNavMoveFlags_WrapY = 1 << 3, + ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, + ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, + ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, + ImGuiNavMoveFlags_Forwarded = 1 << 7, + ImGuiNavMoveFlags_DebugNoResult = 1 << 8, + ImGuiNavMoveFlags_Tabbing = 1 << 9, + ImGuiNavMoveFlags_Activate = 1 << 10, + ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 11 +}ImGuiNavMoveFlags_; +typedef enum { + ImGuiNavLayer_Main = 0, + ImGuiNavLayer_Menu = 1, + ImGuiNavLayer_COUNT +}ImGuiNavLayer; +struct ImGuiNavItemData +{ + ImGuiWindow* Window; + ImGuiID ID; + ImGuiID FocusScopeId; + ImRect RectRel; + ImGuiItemFlags InFlags; + float DistBox; + float DistCenter; + float DistAxial; +}; typedef enum { ImGuiOldColumnFlags_None = 0, ImGuiOldColumnFlags_NoBorder = 1 << 0, @@ -1600,8 +1687,8 @@ struct ImGuiViewportP ImDrawDataBuilder DrawDataBuilder; ImVec2 WorkOffsetMin; ImVec2 WorkOffsetMax; - ImVec2 CurrWorkOffsetMin; - ImVec2 CurrWorkOffsetMax; + ImVec2 BuildWorkOffsetMin; + ImVec2 BuildWorkOffsetMax; }; struct ImGuiWindowSettings { @@ -1625,6 +1712,7 @@ struct ImGuiSettingsHandler }; struct ImGuiMetricsConfig { + bool ShowStackTool; bool ShowWindowsRects; bool ShowWindowsBeginOrder; bool ShowTablesRects; @@ -1633,15 +1721,19 @@ struct ImGuiMetricsConfig int ShowWindowsRectsType; int ShowTablesRectsType; }; -struct ImGuiStackSizes +struct ImGuiStackLevelInfo { - short SizeOfIDStack; - short SizeOfColorStack; - short SizeOfStyleVarStack; - short SizeOfFontStack; - short SizeOfFocusScopeStack; - short SizeOfGroupStack; - short SizeOfBeginPopupStack; + ImGuiID ID; + ImS8 QueryFrameCount; + bool QuerySuccess; + char Desc[58]; +}; +struct ImGuiStackTool +{ + int LastActiveFrame; + int StackLevel; + ImGuiID QueryId; + ImVector_ImGuiStackLevelInfo Results; }; typedef enum { ImGuiContextHookType_NewFramePre, ImGuiContextHookType_NewFramePost, ImGuiContextHookType_EndFramePre, ImGuiContextHookType_EndFramePost, ImGuiContextHookType_RenderPre, ImGuiContextHookType_RenderPost, ImGuiContextHookType_Shutdown, ImGuiContextHookType_PendingRemoval_ }ImGuiContextHookType; struct ImGuiContextHook @@ -1671,14 +1763,14 @@ struct ImGuiContext bool WithinEndChild; bool GcCompactAll; bool TestEngineHookItems; - ImGuiID TestEngineHookIdInfo; void* TestEngine; ImVector_ImGuiWindowPtr Windows; ImVector_ImGuiWindowPtr WindowsFocusOrder; ImVector_ImGuiWindowPtr WindowsTempSortBuffer; - ImVector_ImGuiWindowPtr CurrentWindowStack; + ImVector_ImGuiWindowStackData CurrentWindowStack; ImGuiStorage WindowsById; int WindowsActiveCount; + ImVec2 WindowsHoverPadding; ImGuiWindow* CurrentWindow; ImGuiWindow* HoveredWindow; ImGuiWindow* HoveredWindowUnderMovingWindow; @@ -1686,6 +1778,7 @@ struct ImGuiContext ImGuiWindow* WheelingWindow; ImVec2 WheelingWindowRefMousePos; float WheelingWindowTimer; + ImGuiID DebugHookIdInfo; ImGuiID HoveredId; ImGuiID HoveredIdPreviousFrame; bool HoveredIdAllowOverlap; @@ -1717,8 +1810,10 @@ struct ImGuiContext ImGuiWindow* ActiveIdPreviousFrameWindow; ImGuiID LastActiveId; float LastActiveIdTimer; - ImGuiNextWindowData NextWindowData; + ImGuiItemFlags CurrentItemFlags; ImGuiNextItemData NextItemData; + ImGuiLastItemData LastItemData; + ImGuiNextWindowData NextWindowData; ImVector_ImGuiColorMod ColorStack; ImVector_ImGuiStyleMod StyleVarStack; ImVector_ImFontPtr FontStack; @@ -1734,15 +1829,15 @@ struct ImGuiContext ImGuiID NavActivateId; ImGuiID NavActivateDownId; ImGuiID NavActivatePressedId; - ImGuiID NavInputId; + ImGuiID NavActivateInputId; + ImGuiActivateFlags NavActivateFlags; ImGuiID NavJustTabbedId; ImGuiID NavJustMovedToId; ImGuiID NavJustMovedToFocusScopeId; ImGuiKeyModFlags NavJustMovedToKeyMods; ImGuiID NavNextActivateId; + ImGuiActivateFlags NavNextActivateFlags; ImGuiInputSource NavInputSource; - ImRect NavScoringRect; - int NavScoringCount; ImGuiNavLayer NavLayer; int NavIdTabCounter; bool NavIdIsAlive; @@ -1754,17 +1849,21 @@ struct ImGuiContext bool NavInitRequestFromMove; ImGuiID NavInitResultId; ImRect NavInitResultRectRel; - bool NavMoveRequest; - ImGuiNavMoveFlags NavMoveRequestFlags; - ImGuiNavForward NavMoveRequestForward; - ImGuiKeyModFlags NavMoveRequestKeyMods; - ImGuiDir NavMoveDir, NavMoveDirLast; + bool NavMoveSubmitted; + bool NavMoveScoringItems; + bool NavMoveForwardToNextFrame; + ImGuiNavMoveFlags NavMoveFlags; + ImGuiScrollFlags NavMoveScrollFlags; + ImGuiKeyModFlags NavMoveKeyMods; + ImGuiDir NavMoveDir; + ImGuiDir NavMoveDirForDebug; ImGuiDir NavMoveClipDir; - ImGuiNavMoveResult NavMoveResultLocal; - ImGuiNavMoveResult NavMoveResultLocalVisibleSet; - ImGuiNavMoveResult NavMoveResultOther; - ImGuiWindow* NavWrapRequestWindow; - ImGuiNavMoveFlags NavWrapRequestFlags; + ImRect NavScoringRect; + int NavScoringDebugCount; + int NavTabbingInputableRemaining; + ImGuiNavItemData NavMoveResultLocal; + ImGuiNavItemData NavMoveResultLocalVisible; + ImGuiNavItemData NavMoveResultOther; ImGuiWindow* NavWindowingTarget; ImGuiWindow* NavWindowingTargetAnim; ImGuiWindow* NavWindowingListWindow; @@ -1773,9 +1872,7 @@ struct ImGuiContext bool NavWindowingToggleLayer; ImGuiWindow* TabFocusRequestCurrWindow; ImGuiWindow* TabFocusRequestNextWindow; - int TabFocusRequestCurrCounterRegular; int TabFocusRequestCurrCounterTabStop; - int TabFocusRequestNextCounterRegular; int TabFocusRequestNextCounterTabStop; bool TabFocusPressed; float DimBgRatio; @@ -1798,30 +1895,34 @@ struct ImGuiContext ImVector_unsigned_char DragDropPayloadBufHeap; unsigned char DragDropPayloadBufLocal[16]; ImGuiTable* CurrentTable; + int CurrentTableStackIdx; ImPool_ImGuiTable Tables; - ImVector_ImGuiPtrOrIndex CurrentTableStack; + ImVector_ImGuiTableTempData TablesTempDataStack; ImVector_float TablesLastTimeActive; ImVector_ImDrawChannel DrawChannelsTempMergeBuffer; ImGuiTabBar* CurrentTabBar; ImPool_ImGuiTabBar TabBars; ImVector_ImGuiPtrOrIndex CurrentTabBarStack; ImVector_ImGuiShrinkWidthItem ShrinkWidthBuffer; - ImVec2 LastValidMousePos; + ImVec2 MouseLastValidPos; ImGuiInputTextState InputTextState; ImFont InputTextPasswordFont; ImGuiID TempInputId; ImGuiColorEditFlags ColorEditOptions; float ColorEditLastHue; float ColorEditLastSat; - float ColorEditLastColor[3]; + ImU32 ColorEditLastColor; ImVec4 ColorPickerRef; + ImGuiComboPreviewData ComboPreviewData; float SliderCurrentAccum; bool SliderCurrentAccumDirty; bool DragCurrentAccumDirty; float DragCurrentAccum; float DragSpeedDefaultRatio; float ScrollbarClickDeltaToGrabCenter; - int TooltipOverrideCount; + float DisabledAlphaBackup; + short DisabledStackSize; + short TooltipOverrideCount; float TooltipSlowDelay; ImVector_char ClipboardHandlerData; ImVector_ImGuiID MenusIdSubmittedThisFrame; @@ -1850,8 +1951,10 @@ struct ImGuiContext bool DebugItemPickerActive; ImGuiID DebugItemPickerBreakId; ImGuiMetricsConfig DebugMetricsConfig; + ImGuiStackTool DebugStackTool; float FramerateSecPerFrame[120]; int FramerateSecPerFrameIdx; + int FramerateSecPerFrameCount; float FramerateSecPerFrameAccum; int WantCaptureMouseNextFrame; int WantCaptureKeyboardNextFrame; @@ -1872,13 +1975,9 @@ struct ImGuiWindowTempData ImVec1 Indent; ImVec1 ColumnsOffset; ImVec1 GroupOffset; - ImGuiID LastItemId; - ImGuiItemStatusFlags LastItemStatusFlags; - ImRect LastItemRect; - ImRect LastItemDisplayRect; ImGuiNavLayer NavLayerCurrent; - int NavLayerActiveMask; - int NavLayerActiveMaskNext; + short NavLayersActiveMask; + short NavLayersActiveMaskNext; ImGuiID NavFocusScopeIdCurrent; bool NavHideHighlightOneFrame; bool NavHasScroll; @@ -1893,14 +1992,11 @@ struct ImGuiWindowTempData int CurrentTableIdx; ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; - int FocusCounterRegular; int FocusCounterTabStop; - ImGuiItemFlags ItemFlags; float ItemWidth; float TextWrapPos; ImVector_float ItemWidthStack; ImVector_float TextWrapPosStack; - ImGuiStackSizes StackSizesOnBegin; }; struct ImGuiWindow { @@ -1940,6 +2036,7 @@ struct ImGuiWindow short BeginCount; short BeginOrderWithinParent; short BeginOrderWithinContext; + short FocusOrder; ImGuiID PopupId; ImS8 AutoFitFramesX, AutoFitFramesY; ImS8 AutoFitChildAxises; @@ -1948,6 +2045,7 @@ struct ImGuiWindow ImS8 HiddenFramesCanSkipItems; ImS8 HiddenFramesCannotSkipItems; ImS8 HiddenFramesForRenderOnly; + ImS8 DisableInputsFrames; ImGuiCond SetWindowPosAllowFlags : 8; ImGuiCond SetWindowSizeAllowFlags : 8; ImGuiCond SetWindowCollapsedAllowFlags : 8; @@ -1975,6 +2073,7 @@ struct ImGuiWindow ImDrawList DrawListInst; ImGuiWindow* ParentWindow; ImGuiWindow* RootWindow; + ImGuiWindow* RootWindowPopupTree; ImGuiWindow* RootWindowForTitleBarHighlight; ImGuiWindow* RootWindowForNav; ImGuiWindow* NavLastChildNavWindow; @@ -1984,19 +2083,13 @@ struct ImGuiWindow int MemoryDrawListVtxCapacity; bool MemoryCompacted; }; -struct ImGuiLastItemDataBackup -{ - ImGuiID LastItemId; - ImGuiItemStatusFlags LastItemStatusFlags; - ImRect LastItemRect; - ImRect LastItemDisplayRect; -}; typedef enum { ImGuiTabBarFlags_DockNode = 1 << 20, ImGuiTabBarFlags_IsFocused = 1 << 21, ImGuiTabBarFlags_SaveSettings = 1 << 22 }ImGuiTabBarFlagsPrivate_; typedef enum { + ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing, ImGuiTabItemFlags_NoCloseButton = 1 << 20, ImGuiTabItemFlags_Button = 1 << 21 }ImGuiTabItemFlagsPrivate_; @@ -2009,7 +2102,7 @@ struct ImGuiTabItem float Offset; float Width; float ContentWidth; - ImS16 NameOffset; + ImS32 NameOffset; ImS16 BeginOrder; ImS16 IndexDuringLayout; bool WantClose; @@ -2036,7 +2129,7 @@ struct ImGuiTabBar float ScrollingRectMinX; float ScrollingRectMaxX; ImGuiID ReorderRequestTabId; - ImS8 ReorderRequestDir; + ImS16 ReorderRequestOffset; ImS8 BeginCount; bool WantLayout; bool VisibleTabWasSubmitted; @@ -2077,7 +2170,8 @@ struct ImGuiTableColumn ImGuiTableDrawChannelIdx DrawChannelFrozen; ImGuiTableDrawChannelIdx DrawChannelUnfrozen; bool IsEnabled; - bool IsEnabledNextFrame; + bool IsUserEnabled; + bool IsUserEnabledNextFrame; bool IsVisibleX; bool IsVisibleY; bool IsRequestOutput; @@ -2101,6 +2195,7 @@ struct ImGuiTable ImGuiID ID; ImGuiTableFlags Flags; void* RawData; + ImGuiTableTempData* TempData; ImSpan_ImGuiTableColumn Columns; ImSpan_ImGuiTableColumnIdx DisplayOrderToIndex; ImSpan_ImGuiTableCellData RowCellData; @@ -2152,20 +2247,11 @@ struct ImGuiTable ImRect Bg0ClipRectForDrawCmd; ImRect Bg2ClipRectForDrawCmd; ImRect HostClipRect; - ImRect HostBackupWorkRect; - ImRect HostBackupParentWorkRect; ImRect HostBackupInnerClipRect; - ImVec2 HostBackupPrevLineSize; - ImVec2 HostBackupCurrLineSize; - ImVec2 HostBackupCursorMaxPos; - ImVec2 UserOuterSize; - ImVec1 HostBackupColumnsOffset; - float HostBackupItemWidth; - int HostBackupItemWidthStackSize; ImGuiWindow* OuterWindow; ImGuiWindow* InnerWindow; ImGuiTextBuffer ColumnsNames; - ImDrawListSplitter DrawSplitter; + ImDrawListSplitter* DrawSplitter; ImGuiTableColumnSortSpecs SortSpecsSingle; ImVector_ImGuiTableColumnSortSpecs SortSpecsMulti; ImGuiTableSortSpecs SortSpecs; @@ -2210,6 +2296,21 @@ struct ImGuiTable bool MemoryCompacted; bool HostSkipItems; }; +struct ImGuiTableTempData +{ + int TableIndex; + float LastTimeActive; + ImVec2 UserOuterSize; + ImDrawListSplitter DrawSplitter; + ImRect HostBackupWorkRect; + ImRect HostBackupParentWorkRect; + ImVec2 HostBackupPrevLineSize; + ImVec2 HostBackupCurrLineSize; + ImVec2 HostBackupCursorMaxPos; + ImVec1 HostBackupColumnsOffset; + float HostBackupItemWidth; + int HostBackupItemWidthStackSize; +}; struct ImGuiTableColumnSettings { float WidthOrWeight; @@ -2241,8 +2342,8 @@ typedef union SDL_Event SDL_Event; #endif // CIMGUI_DEFINE_ENUMS_AND_STRUCTS #ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS -typedef ImGuiStorage::ImGuiStoragePair ImGuiStoragePair; -typedef ImGuiTextFilter::ImGuiTextRange ImGuiTextRange; +typedef struct ImGuiStorage::ImGuiStoragePair ImGuiStoragePair; +typedef struct ImGuiTextFilter::ImGuiTextRange ImGuiTextRange; typedef ImStb::STB_TexteditState STB_TexteditState; typedef ImStb::StbTexteditRow StbTexteditRow; typedef ImStb::StbUndoRecord StbUndoRecord; @@ -2274,13 +2375,16 @@ typedef ImVector ImVector_ImGuiPopupData; typedef ImVector ImVector_ImGuiPtrOrIndex; typedef ImVector ImVector_ImGuiSettingsHandler; typedef ImVector ImVector_ImGuiShrinkWidthItem; +typedef ImVector ImVector_ImGuiStackLevelInfo; typedef ImVector ImVector_ImGuiStoragePair; typedef ImVector ImVector_ImGuiStyleMod; typedef ImVector ImVector_ImGuiTabItem; typedef ImVector ImVector_ImGuiTableColumnSortSpecs; +typedef ImVector ImVector_ImGuiTableTempData; typedef ImVector ImVector_ImGuiTextRange; typedef ImVector ImVector_ImGuiViewportPPtr; typedef ImVector ImVector_ImGuiWindowPtr; +typedef ImVector ImVector_ImGuiWindowStackData; typedef ImVector ImVector_ImTextureID; typedef ImVector ImVector_ImU32; typedef ImVector ImVector_ImVec2; @@ -2344,7 +2448,6 @@ CIMGUI_API void igGetContentRegionAvail(ImVec2 *pOut); CIMGUI_API void igGetContentRegionMax(ImVec2 *pOut); CIMGUI_API void igGetWindowContentRegionMin(ImVec2 *pOut); CIMGUI_API void igGetWindowContentRegionMax(ImVec2 *pOut); -CIMGUI_API float igGetWindowContentRegionWidth(void); CIMGUI_API float igGetScrollX(void); CIMGUI_API float igGetScrollY(void); CIMGUI_API void igSetScrollX_Float(float scroll_x); @@ -2534,7 +2637,8 @@ CIMGUI_API void igSetTooltipV(const char* fmt,va_list args); CIMGUI_API bool igBeginPopup(const char* str_id,ImGuiWindowFlags flags); CIMGUI_API bool igBeginPopupModal(const char* name,bool* p_open,ImGuiWindowFlags flags); CIMGUI_API void igEndPopup(void); -CIMGUI_API void igOpenPopup(const char* str_id,ImGuiPopupFlags popup_flags); +CIMGUI_API void igOpenPopup_Str(const char* str_id,ImGuiPopupFlags popup_flags); +CIMGUI_API void igOpenPopup_ID(ImGuiID id,ImGuiPopupFlags popup_flags); CIMGUI_API void igOpenPopupOnItemClick(const char* str_id,ImGuiPopupFlags popup_flags); CIMGUI_API void igCloseCurrentPopup(void); CIMGUI_API bool igBeginPopupContextItem(const char* str_id,ImGuiPopupFlags popup_flags); @@ -2556,6 +2660,7 @@ CIMGUI_API int igTableGetColumnIndex(void); CIMGUI_API int igTableGetRowIndex(void); CIMGUI_API const char* igTableGetColumnName_Int(int column_n); CIMGUI_API ImGuiTableColumnFlags igTableGetColumnFlags(int column_n); +CIMGUI_API void igTableSetColumnEnabled(int column_n,bool v); CIMGUI_API void igTableSetBgColor(ImGuiTableBgTarget target,ImU32 color,int column_n); CIMGUI_API void igColumns(int count,const char* id,bool border); CIMGUI_API void igNextColumn(void); @@ -2584,6 +2689,8 @@ CIMGUI_API bool igBeginDragDropTarget(void); CIMGUI_API const ImGuiPayload* igAcceptDragDropPayload(const char* type,ImGuiDragDropFlags flags); CIMGUI_API void igEndDragDropTarget(void); CIMGUI_API const ImGuiPayload* igGetDragDropPayload(void); +CIMGUI_API void igBeginDisabled(bool disabled); +CIMGUI_API void igEndDisabled(void); CIMGUI_API void igPushClipRect(const ImVec2 clip_rect_min,const ImVec2 clip_rect_max,bool intersect_with_current_clip_rect); CIMGUI_API void igPopClipRect(void); CIMGUI_API void igSetItemDefaultFocus(void); @@ -2662,7 +2769,9 @@ CIMGUI_API void ImGuiStyle_ScaleAllSizes(ImGuiStyle* self,float scale_factor); CIMGUI_API void ImGuiIO_AddInputCharacter(ImGuiIO* self,unsigned int c); CIMGUI_API void ImGuiIO_AddInputCharacterUTF16(ImGuiIO* self,ImWchar16 c); CIMGUI_API void ImGuiIO_AddInputCharactersUTF8(ImGuiIO* self,const char* str); +CIMGUI_API void ImGuiIO_AddFocusEvent(ImGuiIO* self,bool focused); CIMGUI_API void ImGuiIO_ClearInputCharacters(ImGuiIO* self); +CIMGUI_API void ImGuiIO_ClearInputKeys(ImGuiIO* self); CIMGUI_API ImGuiIO* ImGuiIO_ImGuiIO(void); CIMGUI_API void ImGuiIO_destroy(ImGuiIO* self); CIMGUI_API ImGuiInputTextCallbackData* ImGuiInputTextCallbackData_ImGuiInputTextCallbackData(void); @@ -2741,6 +2850,7 @@ CIMGUI_API void ImColor_SetHSV(ImColor* self,float h,float s,float v,float a); CIMGUI_API void ImColor_HSV(ImColor *pOut,float h,float s,float v,float a); CIMGUI_API ImDrawCmd* ImDrawCmd_ImDrawCmd(void); CIMGUI_API void ImDrawCmd_destroy(ImDrawCmd* self); +CIMGUI_API ImTextureID ImDrawCmd_GetTexID(ImDrawCmd* self); CIMGUI_API ImDrawListSplitter* ImDrawListSplitter_ImDrawListSplitter(void); CIMGUI_API void ImDrawListSplitter_destroy(ImDrawListSplitter* self); CIMGUI_API void ImDrawListSplitter_Clear(ImDrawListSplitter* self); @@ -2805,6 +2915,7 @@ CIMGUI_API void ImDrawList_PrimVtx(ImDrawList* self,const ImVec2 pos,const ImVec CIMGUI_API void ImDrawList__ResetForNewFrame(ImDrawList* self); CIMGUI_API void ImDrawList__ClearFreeMemory(ImDrawList* self); CIMGUI_API void ImDrawList__PopUnusedDrawCmd(ImDrawList* self); +CIMGUI_API void ImDrawList__TryMergeDrawCmds(ImDrawList* self); CIMGUI_API void ImDrawList__OnChangedClipRect(ImDrawList* self); CIMGUI_API void ImDrawList__OnChangedTextureID(ImDrawList* self); CIMGUI_API void ImDrawList__OnChangedVtxOffset(ImDrawList* self); @@ -2877,7 +2988,6 @@ CIMGUI_API void ImFont_GrowIndex(ImFont* self,int new_size); CIMGUI_API void ImFont_AddGlyph(ImFont* self,const ImFontConfig* src_cfg,ImWchar c,float x0,float y0,float x1,float y1,float u0,float v0,float u1,float v1,float advance_x); CIMGUI_API void ImFont_AddRemapChar(ImFont* self,ImWchar dst,ImWchar src,bool overwrite_dst); CIMGUI_API void ImFont_SetGlyphVisible(ImFont* self,ImWchar c,bool visible); -CIMGUI_API void ImFont_SetFallbackChar(ImFont* self,ImWchar c); CIMGUI_API bool ImFont_IsGlyphRangeUnused(ImFont* self,unsigned int c_begin,unsigned int c_last); CIMGUI_API ImGuiViewport* ImGuiViewport_ImGuiViewport(void); CIMGUI_API void ImGuiViewport_destroy(ImGuiViewport* self); @@ -2909,9 +3019,10 @@ CIMGUI_API const char* igImParseFormatTrimDecorations(const char* format,char* b CIMGUI_API int igImParseFormatPrecision(const char* format,int default_value); CIMGUI_API bool igImCharIsBlankA(char c); CIMGUI_API bool igImCharIsBlankW(unsigned int c); -CIMGUI_API int igImTextStrToUtf8(char* buf,int buf_size,const ImWchar* in_text,const ImWchar* in_text_end); +CIMGUI_API const char* igImTextCharToUtf8(char out_buf[5],unsigned int c); +CIMGUI_API int igImTextStrToUtf8(char* out_buf,int out_buf_size,const ImWchar* in_text,const ImWchar* in_text_end); CIMGUI_API int igImTextCharFromUtf8(unsigned int* out_char,const char* in_text,const char* in_text_end); -CIMGUI_API int igImTextStrFromUtf8(ImWchar* buf,int buf_size,const char* in_text,const char* in_text_end,const char** in_remaining); +CIMGUI_API int igImTextStrFromUtf8(ImWchar* out_buf,int out_buf_size,const char* in_text,const char* in_text_end,const char** in_remaining); CIMGUI_API int igImTextCountCharsFromUtf8(const char* in_text,const char* in_text_end); CIMGUI_API int igImTextCountUtf8BytesFromChar(const char* in_text,const char* in_text_end); CIMGUI_API int igImTextCountUtf8BytesFromStr(const ImWchar* in_text,const ImWchar* in_text_end); @@ -2925,10 +3036,13 @@ CIMGUI_API float igImPow_Float(float x,float y); CIMGUI_API double igImPow_double(double x,double y); CIMGUI_API float igImLog_Float(float x); CIMGUI_API double igImLog_double(double x); +CIMGUI_API int igImAbs_Int(int x); CIMGUI_API float igImAbs_Float(float x); CIMGUI_API double igImAbs_double(double x); CIMGUI_API float igImSign_Float(float x); CIMGUI_API double igImSign_double(double x); +CIMGUI_API float igImRsqrt_Float(float x); +CIMGUI_API double igImRsqrt_double(double x); CIMGUI_API void igImMin(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs); CIMGUI_API void igImMax(ImVec2 *pOut,const ImVec2 lhs,const ImVec2 rhs); CIMGUI_API void igImClamp(ImVec2 *pOut,const ImVec2 v,const ImVec2 mn,ImVec2 mx); @@ -2940,6 +3054,7 @@ CIMGUI_API float igImLengthSqr_Vec2(const ImVec2 lhs); CIMGUI_API float igImLengthSqr_Vec4(const ImVec4 lhs); CIMGUI_API float igImInvLength(const ImVec2 lhs,float fail_value); CIMGUI_API float igImFloor_Float(float f); +CIMGUI_API float igImFloorSigned(float f); CIMGUI_API void igImFloor_Vec2(ImVec2 *pOut,const ImVec2 v); CIMGUI_API int igImModPositive(int a,int b); CIMGUI_API float igImDot(const ImVec2 a,const ImVec2 b); @@ -3012,11 +3127,13 @@ CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Int(ImGuiStyleVar idx,int CIMGUI_API void ImGuiStyleMod_destroy(ImGuiStyleMod* self); CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Float(ImGuiStyleVar idx,float v); CIMGUI_API ImGuiStyleMod* ImGuiStyleMod_ImGuiStyleMod_Vec2(ImGuiStyleVar idx,ImVec2 v); +CIMGUI_API ImGuiComboPreviewData* ImGuiComboPreviewData_ImGuiComboPreviewData(void); +CIMGUI_API void ImGuiComboPreviewData_destroy(ImGuiComboPreviewData* self); CIMGUI_API ImGuiMenuColumns* ImGuiMenuColumns_ImGuiMenuColumns(void); CIMGUI_API void ImGuiMenuColumns_destroy(ImGuiMenuColumns* self); -CIMGUI_API void ImGuiMenuColumns_Update(ImGuiMenuColumns* self,int count,float spacing,bool clear); -CIMGUI_API float ImGuiMenuColumns_DeclColumns(ImGuiMenuColumns* self,float w0,float w1,float w2); -CIMGUI_API float ImGuiMenuColumns_CalcExtraSpace(ImGuiMenuColumns* self,float avail_w); +CIMGUI_API void ImGuiMenuColumns_Update(ImGuiMenuColumns* self,float spacing,bool window_reappearing); +CIMGUI_API float ImGuiMenuColumns_DeclColumns(ImGuiMenuColumns* self,float w_icon,float w_label,float w_shortcut,float w_mark); +CIMGUI_API void ImGuiMenuColumns_CalcNextTotalWidth(ImGuiMenuColumns* self,bool update_offsets); CIMGUI_API ImGuiInputTextState* ImGuiInputTextState_ImGuiInputTextState(void); CIMGUI_API void ImGuiInputTextState_destroy(ImGuiInputTextState* self); CIMGUI_API void ImGuiInputTextState_ClearText(ImGuiInputTextState* self); @@ -3028,30 +3145,42 @@ CIMGUI_API void ImGuiInputTextState_CursorAnimReset(ImGuiInputTextState* self); CIMGUI_API void ImGuiInputTextState_CursorClamp(ImGuiInputTextState* self); CIMGUI_API bool ImGuiInputTextState_HasSelection(ImGuiInputTextState* self); CIMGUI_API void ImGuiInputTextState_ClearSelection(ImGuiInputTextState* self); +CIMGUI_API int ImGuiInputTextState_GetCursorPos(ImGuiInputTextState* self); +CIMGUI_API int ImGuiInputTextState_GetSelectionStart(ImGuiInputTextState* self); +CIMGUI_API int ImGuiInputTextState_GetSelectionEnd(ImGuiInputTextState* self); CIMGUI_API void ImGuiInputTextState_SelectAll(ImGuiInputTextState* self); CIMGUI_API ImGuiPopupData* ImGuiPopupData_ImGuiPopupData(void); CIMGUI_API void ImGuiPopupData_destroy(ImGuiPopupData* self); -CIMGUI_API ImGuiNavMoveResult* ImGuiNavMoveResult_ImGuiNavMoveResult(void); -CIMGUI_API void ImGuiNavMoveResult_destroy(ImGuiNavMoveResult* self); -CIMGUI_API void ImGuiNavMoveResult_Clear(ImGuiNavMoveResult* self); CIMGUI_API ImGuiNextWindowData* ImGuiNextWindowData_ImGuiNextWindowData(void); CIMGUI_API void ImGuiNextWindowData_destroy(ImGuiNextWindowData* self); CIMGUI_API void ImGuiNextWindowData_ClearFlags(ImGuiNextWindowData* self); CIMGUI_API ImGuiNextItemData* ImGuiNextItemData_ImGuiNextItemData(void); CIMGUI_API void ImGuiNextItemData_destroy(ImGuiNextItemData* self); CIMGUI_API void ImGuiNextItemData_ClearFlags(ImGuiNextItemData* self); +CIMGUI_API ImGuiLastItemData* ImGuiLastItemData_ImGuiLastItemData(void); +CIMGUI_API void ImGuiLastItemData_destroy(ImGuiLastItemData* self); +CIMGUI_API ImGuiStackSizes* ImGuiStackSizes_ImGuiStackSizes(void); +CIMGUI_API void ImGuiStackSizes_destroy(ImGuiStackSizes* self); +CIMGUI_API void ImGuiStackSizes_SetToCurrentState(ImGuiStackSizes* self); +CIMGUI_API void ImGuiStackSizes_CompareWithCurrentState(ImGuiStackSizes* self); CIMGUI_API ImGuiPtrOrIndex* ImGuiPtrOrIndex_ImGuiPtrOrIndex_Ptr(void* ptr); CIMGUI_API void ImGuiPtrOrIndex_destroy(ImGuiPtrOrIndex* self); CIMGUI_API ImGuiPtrOrIndex* ImGuiPtrOrIndex_ImGuiPtrOrIndex_Int(int index); +CIMGUI_API ImGuiNavItemData* ImGuiNavItemData_ImGuiNavItemData(void); +CIMGUI_API void ImGuiNavItemData_destroy(ImGuiNavItemData* self); +CIMGUI_API void ImGuiNavItemData_Clear(ImGuiNavItemData* self); CIMGUI_API ImGuiOldColumnData* ImGuiOldColumnData_ImGuiOldColumnData(void); CIMGUI_API void ImGuiOldColumnData_destroy(ImGuiOldColumnData* self); CIMGUI_API ImGuiOldColumns* ImGuiOldColumns_ImGuiOldColumns(void); CIMGUI_API void ImGuiOldColumns_destroy(ImGuiOldColumns* self); CIMGUI_API ImGuiViewportP* ImGuiViewportP_ImGuiViewportP(void); CIMGUI_API void ImGuiViewportP_destroy(ImGuiViewportP* self); +CIMGUI_API void ImGuiViewportP_CalcWorkRectPos(ImVec2 *pOut,ImGuiViewportP* self,const ImVec2 off_min); +CIMGUI_API void ImGuiViewportP_CalcWorkRectSize(ImVec2 *pOut,ImGuiViewportP* self,const ImVec2 off_min,const ImVec2 off_max); +CIMGUI_API void ImGuiViewportP_UpdateWorkRect(ImGuiViewportP* self); CIMGUI_API void ImGuiViewportP_GetMainRect(ImRect *pOut,ImGuiViewportP* self); CIMGUI_API void ImGuiViewportP_GetWorkRect(ImRect *pOut,ImGuiViewportP* self); -CIMGUI_API void ImGuiViewportP_UpdateWorkRect(ImGuiViewportP* self); +CIMGUI_API void ImGuiViewportP_GetBuildWorkRect(ImRect *pOut,ImGuiViewportP* self); CIMGUI_API ImGuiWindowSettings* ImGuiWindowSettings_ImGuiWindowSettings(void); CIMGUI_API void ImGuiWindowSettings_destroy(ImGuiWindowSettings* self); CIMGUI_API char* ImGuiWindowSettings_GetName(ImGuiWindowSettings* self); @@ -3059,10 +3188,10 @@ CIMGUI_API ImGuiSettingsHandler* ImGuiSettingsHandler_ImGuiSettingsHandler(void) CIMGUI_API void ImGuiSettingsHandler_destroy(ImGuiSettingsHandler* self); CIMGUI_API ImGuiMetricsConfig* ImGuiMetricsConfig_ImGuiMetricsConfig(void); CIMGUI_API void ImGuiMetricsConfig_destroy(ImGuiMetricsConfig* self); -CIMGUI_API ImGuiStackSizes* ImGuiStackSizes_ImGuiStackSizes(void); -CIMGUI_API void ImGuiStackSizes_destroy(ImGuiStackSizes* self); -CIMGUI_API void ImGuiStackSizes_SetToCurrentState(ImGuiStackSizes* self); -CIMGUI_API void ImGuiStackSizes_CompareWithCurrentState(ImGuiStackSizes* self); +CIMGUI_API ImGuiStackLevelInfo* ImGuiStackLevelInfo_ImGuiStackLevelInfo(void); +CIMGUI_API void ImGuiStackLevelInfo_destroy(ImGuiStackLevelInfo* self); +CIMGUI_API ImGuiStackTool* ImGuiStackTool_ImGuiStackTool(void); +CIMGUI_API void ImGuiStackTool_destroy(ImGuiStackTool* self); CIMGUI_API ImGuiContextHook* ImGuiContextHook_ImGuiContextHook(void); CIMGUI_API void ImGuiContextHook_destroy(ImGuiContextHook* self); CIMGUI_API ImGuiContext* ImGuiContext_ImGuiContext(ImFontAtlas* shared_font_atlas); @@ -3082,10 +3211,6 @@ CIMGUI_API float ImGuiWindow_TitleBarHeight(ImGuiWindow* self); CIMGUI_API void ImGuiWindow_TitleBarRect(ImRect *pOut,ImGuiWindow* self); CIMGUI_API float ImGuiWindow_MenuBarHeight(ImGuiWindow* self); CIMGUI_API void ImGuiWindow_MenuBarRect(ImRect *pOut,ImGuiWindow* self); -CIMGUI_API ImGuiLastItemDataBackup* ImGuiLastItemDataBackup_ImGuiLastItemDataBackup(void); -CIMGUI_API void ImGuiLastItemDataBackup_destroy(ImGuiLastItemDataBackup* self); -CIMGUI_API void ImGuiLastItemDataBackup_Backup(ImGuiLastItemDataBackup* self); -CIMGUI_API void ImGuiLastItemDataBackup_Restore(ImGuiLastItemDataBackup* self); CIMGUI_API ImGuiTabItem* ImGuiTabItem_ImGuiTabItem(void); CIMGUI_API void ImGuiTabItem_destroy(ImGuiTabItem* self); CIMGUI_API ImGuiTabBar* ImGuiTabBar_ImGuiTabBar(void); @@ -3096,6 +3221,8 @@ CIMGUI_API ImGuiTableColumn* ImGuiTableColumn_ImGuiTableColumn(void); CIMGUI_API void ImGuiTableColumn_destroy(ImGuiTableColumn* self); CIMGUI_API ImGuiTable* ImGuiTable_ImGuiTable(void); CIMGUI_API void ImGuiTable_destroy(ImGuiTable* self); +CIMGUI_API ImGuiTableTempData* ImGuiTableTempData_ImGuiTableTempData(void); +CIMGUI_API void ImGuiTableTempData_destroy(ImGuiTableTempData* self); CIMGUI_API ImGuiTableColumnSettings* ImGuiTableColumnSettings_ImGuiTableColumnSettings(void); CIMGUI_API void ImGuiTableColumnSettings_destroy(ImGuiTableColumnSettings* self); CIMGUI_API ImGuiTableSettings* ImGuiTableSettings_ImGuiTableSettings(void); @@ -3107,10 +3234,9 @@ CIMGUI_API ImGuiWindow* igFindWindowByID(ImGuiID id); CIMGUI_API ImGuiWindow* igFindWindowByName(const char* name); CIMGUI_API void igUpdateWindowParentAndRootLinks(ImGuiWindow* window,ImGuiWindowFlags flags,ImGuiWindow* parent_window); CIMGUI_API void igCalcWindowNextAutoFitSize(ImVec2 *pOut,ImGuiWindow* window); -CIMGUI_API bool igIsWindowChildOf(ImGuiWindow* window,ImGuiWindow* potential_parent); +CIMGUI_API bool igIsWindowChildOf(ImGuiWindow* window,ImGuiWindow* potential_parent,bool popup_hierarchy); CIMGUI_API bool igIsWindowAbove(ImGuiWindow* potential_above,ImGuiWindow* potential_below); CIMGUI_API bool igIsWindowNavFocusable(ImGuiWindow* window); -CIMGUI_API void igGetWindowAllowedExtentRect(ImRect *pOut,ImGuiWindow* window); CIMGUI_API void igSetWindowPos_WindowPtr(ImGuiWindow* window,const ImVec2 pos,ImGuiCond cond); CIMGUI_API void igSetWindowSize_WindowPtr(ImGuiWindow* window,const ImVec2 size,ImGuiCond cond); CIMGUI_API void igSetWindowCollapsed_WindowPtr(ImGuiWindow* window,bool collapsed,ImGuiCond cond); @@ -3146,12 +3272,15 @@ CIMGUI_API void igSetScrollX_WindowPtr(ImGuiWindow* window,float scroll_x); CIMGUI_API void igSetScrollY_WindowPtr(ImGuiWindow* window,float scroll_y); CIMGUI_API void igSetScrollFromPosX_WindowPtr(ImGuiWindow* window,float local_x,float center_x_ratio); CIMGUI_API void igSetScrollFromPosY_WindowPtr(ImGuiWindow* window,float local_y,float center_y_ratio); -CIMGUI_API void igScrollToBringRectIntoView(ImVec2 *pOut,ImGuiWindow* window,const ImRect item_rect); +CIMGUI_API void igScrollToItem(ImGuiScrollFlags flags); +CIMGUI_API void igScrollToRect(ImGuiWindow* window,const ImRect rect,ImGuiScrollFlags flags); +CIMGUI_API void igScrollToRectEx(ImVec2 *pOut,ImGuiWindow* window,const ImRect rect,ImGuiScrollFlags flags); +CIMGUI_API void igScrollToBringRectIntoView(ImGuiWindow* window,const ImRect rect); CIMGUI_API ImGuiID igGetItemID(void); CIMGUI_API ImGuiItemStatusFlags igGetItemStatusFlags(void); +CIMGUI_API ImGuiItemFlags igGetItemFlags(void); CIMGUI_API ImGuiID igGetActiveID(void); CIMGUI_API ImGuiID igGetFocusID(void); -CIMGUI_API ImGuiItemFlags igGetItemsFlags(void); CIMGUI_API void igSetActiveID(ImGuiID id,ImGuiWindow* window); CIMGUI_API void igSetFocusID(ImGuiID id,ImGuiWindow* window); CIMGUI_API void igClearActiveID(void); @@ -3163,20 +3292,18 @@ CIMGUI_API void igPushOverrideID(ImGuiID id); CIMGUI_API ImGuiID igGetIDWithSeed(const char* str_id_begin,const char* str_id_end,ImGuiID seed); CIMGUI_API void igItemSize_Vec2(const ImVec2 size,float text_baseline_y); CIMGUI_API void igItemSize_Rect(const ImRect bb,float text_baseline_y); -CIMGUI_API bool igItemAdd(const ImRect bb,ImGuiID id,const ImRect* nav_bb); +CIMGUI_API bool igItemAdd(const ImRect bb,ImGuiID id,const ImRect* nav_bb,ImGuiItemFlags extra_flags); CIMGUI_API bool igItemHoverable(const ImRect bb,ImGuiID id); -CIMGUI_API bool igIsClippedEx(const ImRect bb,ImGuiID id,bool clip_even_when_logged); -CIMGUI_API void igSetLastItemData(ImGuiWindow* window,ImGuiID item_id,ImGuiItemStatusFlags status_flags,const ImRect item_rect); -CIMGUI_API bool igFocusableItemRegister(ImGuiWindow* window,ImGuiID id); -CIMGUI_API void igFocusableItemUnregister(ImGuiWindow* window); +CIMGUI_API void igItemInputable(ImGuiWindow* window,ImGuiID id); +CIMGUI_API bool igIsClippedEx(const ImRect bb,ImGuiID id); CIMGUI_API void igCalcItemSize(ImVec2 *pOut,ImVec2 size,float default_w,float default_h); CIMGUI_API float igCalcWrapWidthForPos(const ImVec2 pos,float wrap_pos_x); CIMGUI_API void igPushMultiItemsWidths(int components,float width_full); -CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled); -CIMGUI_API void igPopItemFlag(void); CIMGUI_API bool igIsItemToggledSelection(void); CIMGUI_API void igGetContentRegionMaxAbs(ImVec2 *pOut); CIMGUI_API void igShrinkWidths(ImGuiShrinkWidthItem* items,int count,float width_excess); +CIMGUI_API void igPushItemFlag(ImGuiItemFlags option,bool enabled); +CIMGUI_API void igPopItemFlag(void); CIMGUI_API void igLogBegin(ImGuiLogType type,int auto_open_depth); CIMGUI_API void igLogToBuffer(int auto_open_depth); CIMGUI_API void igLogRenderedText(const ImVec2* ref_pos,const char* text,const char* text_end); @@ -3185,27 +3312,40 @@ CIMGUI_API bool igBeginChildEx(const char* name,ImGuiID id,const ImVec2 size_arg CIMGUI_API void igOpenPopupEx(ImGuiID id,ImGuiPopupFlags popup_flags); CIMGUI_API void igClosePopupToLevel(int remaining,bool restore_focus_to_window_under_popup); CIMGUI_API void igClosePopupsOverWindow(ImGuiWindow* ref_window,bool restore_focus_to_window_under_popup); +CIMGUI_API void igClosePopupsExceptModals(void); CIMGUI_API bool igIsPopupOpen_ID(ImGuiID id,ImGuiPopupFlags popup_flags); CIMGUI_API bool igBeginPopupEx(ImGuiID id,ImGuiWindowFlags extra_flags); CIMGUI_API void igBeginTooltipEx(ImGuiWindowFlags extra_flags,ImGuiTooltipFlags tooltip_flags); +CIMGUI_API void igGetPopupAllowedExtentRect(ImRect *pOut,ImGuiWindow* window); CIMGUI_API ImGuiWindow* igGetTopMostPopupModal(void); CIMGUI_API void igFindBestWindowPosForPopup(ImVec2 *pOut,ImGuiWindow* window); CIMGUI_API void igFindBestWindowPosForPopupEx(ImVec2 *pOut,const ImVec2 ref_pos,const ImVec2 size,ImGuiDir* last_dir,const ImRect r_outer,const ImRect r_avoid,ImGuiPopupPositionPolicy policy); +CIMGUI_API bool igBeginViewportSideBar(const char* name,ImGuiViewport* viewport,ImGuiDir dir,float size,ImGuiWindowFlags window_flags); +CIMGUI_API bool igBeginMenuEx(const char* label,const char* icon,bool enabled); +CIMGUI_API bool igMenuItemEx(const char* label,const char* icon,const char* shortcut,bool selected,bool enabled); +CIMGUI_API bool igBeginComboPopup(ImGuiID popup_id,const ImRect bb,ImGuiComboFlags flags); +CIMGUI_API bool igBeginComboPreview(void); +CIMGUI_API void igEndComboPreview(void); CIMGUI_API void igNavInitWindow(ImGuiWindow* window,bool force_reinit); +CIMGUI_API void igNavInitRequestApplyResult(void); CIMGUI_API bool igNavMoveRequestButNoResultYet(void); +CIMGUI_API void igNavMoveRequestSubmit(ImGuiDir move_dir,ImGuiDir clip_dir,ImGuiNavMoveFlags move_flags,ImGuiScrollFlags scroll_flags); +CIMGUI_API void igNavMoveRequestForward(ImGuiDir move_dir,ImGuiDir clip_dir,ImGuiNavMoveFlags move_flags,ImGuiScrollFlags scroll_flags); +CIMGUI_API void igNavMoveRequestResolveWithLastItem(void); CIMGUI_API void igNavMoveRequestCancel(void); -CIMGUI_API void igNavMoveRequestForward(ImGuiDir move_dir,ImGuiDir clip_dir,const ImRect bb_rel,ImGuiNavMoveFlags move_flags); +CIMGUI_API void igNavMoveRequestApplyResult(void); CIMGUI_API void igNavMoveRequestTryWrapping(ImGuiWindow* window,ImGuiNavMoveFlags move_flags); CIMGUI_API float igGetNavInputAmount(ImGuiNavInput n,ImGuiInputReadMode mode); CIMGUI_API void igGetNavInputAmount2d(ImVec2 *pOut,ImGuiNavDirSourceFlags dir_sources,ImGuiInputReadMode mode,float slow_factor,float fast_factor); CIMGUI_API int igCalcTypematicRepeatAmount(float t0,float t1,float repeat_delay,float repeat_rate); CIMGUI_API void igActivateItem(ImGuiID id); -CIMGUI_API void igSetNavID(ImGuiID id,int nav_layer,ImGuiID focus_scope_id,const ImRect rect_rel); +CIMGUI_API void igSetNavID(ImGuiID id,ImGuiNavLayer nav_layer,ImGuiID focus_scope_id,const ImRect rect_rel); CIMGUI_API void igPushFocusScope(ImGuiID id); CIMGUI_API void igPopFocusScope(void); CIMGUI_API ImGuiID igGetFocusedFocusScope(void); CIMGUI_API ImGuiID igGetFocusScope(void); CIMGUI_API void igSetItemUsingMouseWheel(void); +CIMGUI_API void igSetActiveIdUsingNavAndKeys(void); CIMGUI_API bool igIsActiveIdUsingNavDir(ImGuiDir dir); CIMGUI_API bool igIsActiveIdUsingNavInput(ImGuiNavInput input); CIMGUI_API bool igIsActiveIdUsingKey(ImGuiKey key); @@ -3228,7 +3368,6 @@ CIMGUI_API ImGuiOldColumns* igFindOrCreateColumns(ImGuiWindow* window,ImGuiID id CIMGUI_API float igGetColumnOffsetFromNorm(const ImGuiOldColumns* columns,float offset_norm); CIMGUI_API float igGetColumnNormFromOffset(const ImGuiOldColumns* columns,float offset); CIMGUI_API void igTableOpenContextMenu(int column_n); -CIMGUI_API void igTableSetColumnEnabled(int column_n,bool enabled); CIMGUI_API void igTableSetColumnWidth(int column_n,float width); CIMGUI_API void igTableSetColumnSortDirection(int column_n,ImGuiSortDirection sort_direction,bool append_to_sort_specs); CIMGUI_API int igTableGetHoveredColumn(void); @@ -3263,7 +3402,8 @@ CIMGUI_API float igTableGetMaxColumnWidth(const ImGuiTable* table,int column_n); CIMGUI_API void igTableSetColumnWidthAutoSingle(ImGuiTable* table,int column_n); CIMGUI_API void igTableSetColumnWidthAutoAll(ImGuiTable* table); CIMGUI_API void igTableRemove(ImGuiTable* table); -CIMGUI_API void igTableGcCompactTransientBuffers(ImGuiTable* table); +CIMGUI_API void igTableGcCompactTransientBuffers_TablePtr(ImGuiTable* table); +CIMGUI_API void igTableGcCompactTransientBuffers_TableTempDataPtr(ImGuiTableTempData* table); CIMGUI_API void igTableGcCompactSettings(void); CIMGUI_API void igTableLoadSettings(ImGuiTable* table); CIMGUI_API void igTableSaveSettings(ImGuiTable* table); @@ -3276,7 +3416,8 @@ CIMGUI_API bool igBeginTabBarEx(ImGuiTabBar* tab_bar,const ImRect bb,ImGuiTabBar CIMGUI_API ImGuiTabItem* igTabBarFindTabByID(ImGuiTabBar* tab_bar,ImGuiID tab_id); CIMGUI_API void igTabBarRemoveTab(ImGuiTabBar* tab_bar,ImGuiID tab_id); CIMGUI_API void igTabBarCloseTab(ImGuiTabBar* tab_bar,ImGuiTabItem* tab); -CIMGUI_API void igTabBarQueueReorder(ImGuiTabBar* tab_bar,const ImGuiTabItem* tab,int dir); +CIMGUI_API void igTabBarQueueReorder(ImGuiTabBar* tab_bar,const ImGuiTabItem* tab,int offset); +CIMGUI_API void igTabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar,const ImGuiTabItem* tab,ImVec2 mouse_pos); CIMGUI_API bool igTabBarProcessReorder(ImGuiTabBar* tab_bar); CIMGUI_API bool igTabItemEx(ImGuiTabBar* tab_bar,const char* label,bool* p_open,ImGuiTabItemFlags flags); CIMGUI_API void igTabItemCalcSize(ImVec2 *pOut,const char* label,bool has_close_button); @@ -3309,7 +3450,8 @@ CIMGUI_API bool igScrollbarEx(const ImRect bb,ImGuiID id,ImGuiAxis axis,float* p CIMGUI_API bool igImageButtonEx(ImGuiID id,ImTextureID texture_id,const ImVec2 size,const ImVec2 uv0,const ImVec2 uv1,const ImVec2 padding,const ImVec4 bg_col,const ImVec4 tint_col); CIMGUI_API void igGetWindowScrollbarRect(ImRect *pOut,ImGuiWindow* window,ImGuiAxis axis); CIMGUI_API ImGuiID igGetWindowScrollbarID(ImGuiWindow* window,ImGuiAxis axis); -CIMGUI_API ImGuiID igGetWindowResizeID(ImGuiWindow* window,int n); +CIMGUI_API ImGuiID igGetWindowResizeCornerID(ImGuiWindow* window,int n); +CIMGUI_API ImGuiID igGetWindowResizeBorderID(ImGuiWindow* window,ImGuiDir dir); CIMGUI_API void igSeparatorEx(ImGuiSeparatorFlags flags); CIMGUI_API bool igCheckboxFlags_S64Ptr(const char* label,ImS64* flags,ImS64 flags_value); CIMGUI_API bool igCheckboxFlags_U64Ptr(const char* label,ImU64* flags,ImU64 flags_value); @@ -3341,11 +3483,15 @@ CIMGUI_API void igGcCompactTransientMiscBuffers(void); CIMGUI_API void igGcCompactTransientWindowBuffers(ImGuiWindow* window); CIMGUI_API void igGcAwakeTransientWindowBuffers(ImGuiWindow* window); CIMGUI_API void igErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback,void* user_data); +CIMGUI_API void igErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback,void* user_data); CIMGUI_API void igDebugDrawItemRect(ImU32 col); CIMGUI_API void igDebugStartItemPicker(void); +CIMGUI_API void igShowFontAtlas(ImFontAtlas* atlas); +CIMGUI_API void igDebugHookIdInfo(ImGuiID id,ImGuiDataType data_type,const void* data_id,const void* data_id_end); CIMGUI_API void igDebugNodeColumns(ImGuiOldColumns* columns); CIMGUI_API void igDebugNodeDrawList(ImGuiWindow* window,const ImDrawList* draw_list,const char* label); CIMGUI_API void igDebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list,const ImDrawList* draw_list,const ImDrawCmd* draw_cmd,bool show_mesh,bool show_aabb); +CIMGUI_API void igDebugNodeFont(ImFont* font); CIMGUI_API void igDebugNodeStorage(ImGuiStorage* storage,const char* label); CIMGUI_API void igDebugNodeTabBar(ImGuiTabBar* tab_bar,const char* label); CIMGUI_API void igDebugNodeTable(ImGuiTable* table); @@ -3381,10 +3527,3 @@ CIMGUI_API ImVector_ImWchar* ImVector_ImWchar_create(); CIMGUI_API void ImVector_ImWchar_destroy(ImVector_ImWchar* self); CIMGUI_API void ImVector_ImWchar_Init(ImVector_ImWchar* p); CIMGUI_API void ImVector_ImWchar_UnInit(ImVector_ImWchar* p); - - -#endif //CIMGUI_INCLUDED - - - - diff --git a/extern/src/cimgui_impl.h b/extern/src/cimgui_impl.h index 5fe456e2..287a7e20 100644 --- a/extern/src/cimgui_impl.h +++ b/extern/src/cimgui_impl.h @@ -1,7 +1,9 @@ typedef struct SDL_Window SDL_Window; +typedef struct GLFWmonitor GLFWmonitor; typedef struct GLFWwindow GLFWwindow; struct GLFWwindow; +struct GLFWmonitor; struct SDL_Window; typedef union SDL_Event SDL_Event;CIMGUI_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window,bool install_callbacks); @@ -9,10 +11,13 @@ CIMGUI_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window,bool install_cal CIMGUI_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window,bool install_callbacks); CIMGUI_API void ImGui_ImplGlfw_Shutdown(); CIMGUI_API void ImGui_ImplGlfw_NewFrame(); +CIMGUI_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window,int focused); +CIMGUI_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window,int entered); CIMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window,int button,int action,int mods); CIMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window,double xoffset,double yoffset); CIMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window,int key,int scancode,int action,int mods); CIMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window,unsigned int c); +CIMGUI_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor,int event); CIMGUI_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version); CIMGUI_API void ImGui_ImplOpenGL3_Shutdown(); CIMGUI_API void ImGui_ImplOpenGL3_NewFrame(); @@ -33,6 +38,7 @@ CIMGUI_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window,void* sdl_gl_con CIMGUI_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); CIMGUI_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); CIMGUI_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window); +CIMGUI_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window); CIMGUI_API void ImGui_ImplSDL2_Shutdown(); -CIMGUI_API void ImGui_ImplSDL2_NewFrame(SDL_Window* window); +CIMGUI_API void ImGui_ImplSDL2_NewFrame(); CIMGUI_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); diff --git a/extern/src/libdeflate.h b/extern/src/libdeflate.h index cbcda042..2f305ba2 100644 --- a/extern/src/libdeflate.h +++ b/extern/src/libdeflate.h @@ -10,8 +10,8 @@ extern "C" { #endif #define LIBDEFLATE_VERSION_MAJOR 1 -#define LIBDEFLATE_VERSION_MINOR 7 -#define LIBDEFLATE_VERSION_STRING "1.7" +#define LIBDEFLATE_VERSION_MINOR 8 +#define LIBDEFLATE_VERSION_STRING "1.8" #include #include diff --git a/extern/src/x264.h b/extern/src/x264.h deleted file mode 100644 index d685efbd..00000000 --- a/extern/src/x264.h +++ /dev/null @@ -1,1019 +0,0 @@ -/***************************************************************************** - * x264.h: x264 public header - ***************************************************************************** - * Copyright (C) 2003-2021 x264 project - * - * Authors: Laurent Aimar - * Loren Merritt - * Fiona Glaser - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. - * - * This program is also available under a commercial proprietary license. - * For more information, contact us at licensing@x264.com. - *****************************************************************************/ - -#ifndef X264_X264_H -#define X264_X264_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(_STDINT_H) && !defined(_STDINT_H_) && !defined(_STDINT_H_INCLUDED) && !defined(_STDINT) &&\ - !defined(_SYS_STDINT_H_) && !defined(_INTTYPES_H) && !defined(_INTTYPES_H_) && !defined(_INTTYPES) -# ifdef _MSC_VER -# pragma message("You must include stdint.h or inttypes.h before x264.h") -# else -# warning You must include stdint.h or inttypes.h before x264.h -# endif -#endif - -#include - -#include "x264_config.h" - -#define X264_BUILD 164 - -#ifdef _WIN32 -# define X264_DLL_IMPORT __declspec(dllimport) -# define X264_DLL_EXPORT __declspec(dllexport) -#else -# if defined(__GNUC__) && (__GNUC__ >= 4) -# define X264_DLL_IMPORT -# define X264_DLL_EXPORT __attribute__((visibility("default"))) -# else -# define X264_DLL_IMPORT -# define X264_DLL_EXPORT -# endif -#endif - -/* Application developers planning to link against a shared library version of - * libx264 from a Microsoft Visual Studio or similar development environment - * will need to define X264_API_IMPORTS before including this header. - * This clause does not apply to MinGW, similar development environments, or non - * Windows platforms. */ -#ifdef X264_API_IMPORTS -# define X264_API X264_DLL_IMPORT -#else -# ifdef X264_API_EXPORTS -# define X264_API X264_DLL_EXPORT -# else -# define X264_API -# endif -#endif - -/* x264_t: - * opaque handler for encoder */ -typedef struct x264_t x264_t; - -/**************************************************************************** - * NAL structure and functions - ****************************************************************************/ - -enum nal_unit_type_e -{ - NAL_UNKNOWN = 0, - NAL_SLICE = 1, - NAL_SLICE_DPA = 2, - NAL_SLICE_DPB = 3, - NAL_SLICE_DPC = 4, - NAL_SLICE_IDR = 5, /* ref_idc != 0 */ - NAL_SEI = 6, /* ref_idc == 0 */ - NAL_SPS = 7, - NAL_PPS = 8, - NAL_AUD = 9, - NAL_FILLER = 12, - /* ref_idc == 0 for 6,9,10,11,12 */ -}; -enum nal_priority_e -{ - NAL_PRIORITY_DISPOSABLE = 0, - NAL_PRIORITY_LOW = 1, - NAL_PRIORITY_HIGH = 2, - NAL_PRIORITY_HIGHEST = 3, -}; - -/* The data within the payload is already NAL-encapsulated; the ref_idc and type - * are merely in the struct for easy access by the calling application. - * All data returned in an x264_nal_t, including the data in p_payload, is no longer - * valid after the next call to x264_encoder_encode. Thus it must be used or copied - * before calling x264_encoder_encode or x264_encoder_headers again. */ -typedef struct x264_nal_t -{ - int i_ref_idc; /* nal_priority_e */ - int i_type; /* nal_unit_type_e */ - int b_long_startcode; - int i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */ - int i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */ - - /* Size of payload (including any padding) in bytes. */ - int i_payload; - /* If param->b_annexb is set, Annex-B bytestream with startcode. - * Otherwise, startcode is replaced with a 4-byte size. - * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */ - uint8_t *p_payload; - - /* Size of padding in bytes. */ - int i_padding; -} x264_nal_t; - -/**************************************************************************** - * Encoder parameters - ****************************************************************************/ -/* CPU flags */ - -/* x86 */ -#define X264_CPU_MMX (1U<<0) -#define X264_CPU_MMX2 (1U<<1) /* MMX2 aka MMXEXT aka ISSE */ -#define X264_CPU_MMXEXT X264_CPU_MMX2 -#define X264_CPU_SSE (1U<<2) -#define X264_CPU_SSE2 (1U<<3) -#define X264_CPU_LZCNT (1U<<4) -#define X264_CPU_SSE3 (1U<<5) -#define X264_CPU_SSSE3 (1U<<6) -#define X264_CPU_SSE4 (1U<<7) /* SSE4.1 */ -#define X264_CPU_SSE42 (1U<<8) /* SSE4.2 */ -#define X264_CPU_AVX (1U<<9) /* Requires OS support even if YMM registers aren't used */ -#define X264_CPU_XOP (1U<<10) /* AMD XOP */ -#define X264_CPU_FMA4 (1U<<11) /* AMD FMA4 */ -#define X264_CPU_FMA3 (1U<<12) -#define X264_CPU_BMI1 (1U<<13) -#define X264_CPU_BMI2 (1U<<14) -#define X264_CPU_AVX2 (1U<<15) -#define X264_CPU_AVX512 (1U<<16) /* AVX-512 {F, CD, BW, DQ, VL}, requires OS support */ -/* x86 modifiers */ -#define X264_CPU_CACHELINE_32 (1U<<17) /* avoid memory loads that span the border between two cachelines */ -#define X264_CPU_CACHELINE_64 (1U<<18) /* 32/64 is the size of a cacheline in bytes */ -#define X264_CPU_SSE2_IS_SLOW (1U<<19) /* avoid most SSE2 functions on Athlon64 */ -#define X264_CPU_SSE2_IS_FAST (1U<<20) /* a few functions are only faster on Core2 and Phenom */ -#define X264_CPU_SLOW_SHUFFLE (1U<<21) /* The Conroe has a slow shuffle unit (relative to overall SSE performance) */ -#define X264_CPU_STACK_MOD4 (1U<<22) /* if stack is only mod4 and not mod16 */ -#define X264_CPU_SLOW_ATOM (1U<<23) /* The Atom is terrible: slow SSE unaligned loads, slow - * SIMD multiplies, slow SIMD variable shifts, slow pshufb, - * cacheline split penalties -- gather everything here that - * isn't shared by other CPUs to avoid making half a dozen - * new SLOW flags. */ -#define X264_CPU_SLOW_PSHUFB (1U<<24) /* such as on the Intel Atom */ -#define X264_CPU_SLOW_PALIGNR (1U<<25) /* such as on the AMD Bobcat */ - -/* PowerPC */ -#define X264_CPU_ALTIVEC 0x0000001U - -/* ARM and AArch64 */ -#define X264_CPU_ARMV6 0x0000001U -#define X264_CPU_NEON 0x0000002U /* ARM NEON */ -#define X264_CPU_FAST_NEON_MRC 0x0000004U /* Transfer from NEON to ARM register is fast (Cortex-A9) */ -#define X264_CPU_ARMV8 0x0000008U - -/* MIPS */ -#define X264_CPU_MSA 0x0000001U /* MIPS MSA */ - -/* Analyse flags */ -#define X264_ANALYSE_I4x4 0x0001U /* Analyse i4x4 */ -#define X264_ANALYSE_I8x8 0x0002U /* Analyse i8x8 (requires 8x8 transform) */ -#define X264_ANALYSE_PSUB16x16 0x0010U /* Analyse p16x8, p8x16 and p8x8 */ -#define X264_ANALYSE_PSUB8x8 0x0020U /* Analyse p8x4, p4x8, p4x4 */ -#define X264_ANALYSE_BSUB16x16 0x0100U /* Analyse b16x8, b8x16 and b8x8 */ - -#define X264_DIRECT_PRED_NONE 0 -#define X264_DIRECT_PRED_SPATIAL 1 -#define X264_DIRECT_PRED_TEMPORAL 2 -#define X264_DIRECT_PRED_AUTO 3 -#define X264_ME_DIA 0 -#define X264_ME_HEX 1 -#define X264_ME_UMH 2 -#define X264_ME_ESA 3 -#define X264_ME_TESA 4 -#define X264_CQM_FLAT 0 -#define X264_CQM_JVT 1 -#define X264_CQM_CUSTOM 2 -#define X264_RC_CQP 0 -#define X264_RC_CRF 1 -#define X264_RC_ABR 2 -#define X264_QP_AUTO 0 -#define X264_AQ_NONE 0 -#define X264_AQ_VARIANCE 1 -#define X264_AQ_AUTOVARIANCE 2 -#define X264_AQ_AUTOVARIANCE_BIASED 3 -#define X264_B_ADAPT_NONE 0 -#define X264_B_ADAPT_FAST 1 -#define X264_B_ADAPT_TRELLIS 2 -#define X264_WEIGHTP_NONE 0 -#define X264_WEIGHTP_SIMPLE 1 -#define X264_WEIGHTP_SMART 2 -#define X264_B_PYRAMID_NONE 0 -#define X264_B_PYRAMID_STRICT 1 -#define X264_B_PYRAMID_NORMAL 2 -#define X264_KEYINT_MIN_AUTO 0 -#define X264_KEYINT_MAX_INFINITE (1<<30) - -/* AVC-Intra flavors */ -#define X264_AVCINTRA_FLAVOR_PANASONIC 0 -#define X264_AVCINTRA_FLAVOR_SONY 1 - -static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 }; -static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 }; -static const char * const x264_b_pyramid_names[] = { "none", "strict", "normal", 0 }; -static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 }; -static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 }; -static const char * const x264_fullrange_names[] = { "off", "on", 0 }; -static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020", "smpte428", - "smpte431", "smpte432", 0 }; -static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", - "iec61966-2-4", "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12", "smpte2084", "smpte428", "arib-std-b67", 0 }; -static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", "bt2020nc", "bt2020c", - "smpte2085", "chroma-derived-nc", "chroma-derived-c", "ICtCp", 0 }; -static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 }; -static const char * const x264_avcintra_flavor_names[] = { "panasonic", "sony", 0 }; - -/* Colorspace type */ -#define X264_CSP_MASK 0x00ff /* */ -#define X264_CSP_NONE 0x0000 /* Invalid mode */ -#define X264_CSP_I400 0x0001 /* monochrome 4:0:0 */ -#define X264_CSP_I420 0x0002 /* yuv 4:2:0 planar */ -#define X264_CSP_YV12 0x0003 /* yvu 4:2:0 planar */ -#define X264_CSP_NV12 0x0004 /* yuv 4:2:0, with one y plane and one packed u+v */ -#define X264_CSP_NV21 0x0005 /* yuv 4:2:0, with one y plane and one packed v+u */ -#define X264_CSP_I422 0x0006 /* yuv 4:2:2 planar */ -#define X264_CSP_YV16 0x0007 /* yvu 4:2:2 planar */ -#define X264_CSP_NV16 0x0008 /* yuv 4:2:2, with one y plane and one packed u+v */ -#define X264_CSP_YUYV 0x0009 /* yuyv 4:2:2 packed */ -#define X264_CSP_UYVY 0x000a /* uyvy 4:2:2 packed */ -#define X264_CSP_V210 0x000b /* 10-bit yuv 4:2:2 packed in 32 */ -#define X264_CSP_I444 0x000c /* yuv 4:4:4 planar */ -#define X264_CSP_YV24 0x000d /* yvu 4:4:4 planar */ -#define X264_CSP_BGR 0x000e /* packed bgr 24bits */ -#define X264_CSP_BGRA 0x000f /* packed bgr 32bits */ -#define X264_CSP_RGB 0x0010 /* packed rgb 24bits */ -#define X264_CSP_MAX 0x0011 /* end of list */ -#define X264_CSP_VFLIP 0x1000 /* the csp is vertically flipped */ -#define X264_CSP_HIGH_DEPTH 0x2000 /* the csp has a depth of 16 bits per pixel component */ - -/* Slice type */ -#define X264_TYPE_AUTO 0x0000 /* Let x264 choose the right type */ -#define X264_TYPE_IDR 0x0001 -#define X264_TYPE_I 0x0002 -#define X264_TYPE_P 0x0003 -#define X264_TYPE_BREF 0x0004 /* Non-disposable B-frame */ -#define X264_TYPE_B 0x0005 -#define X264_TYPE_KEYFRAME 0x0006 /* IDR or I depending on b_open_gop option */ -#define IS_X264_TYPE_I(x) ((x)==X264_TYPE_I || (x)==X264_TYPE_IDR || (x)==X264_TYPE_KEYFRAME) -#define IS_X264_TYPE_B(x) ((x)==X264_TYPE_B || (x)==X264_TYPE_BREF) - -/* Log level */ -#define X264_LOG_NONE (-1) -#define X264_LOG_ERROR 0 -#define X264_LOG_WARNING 1 -#define X264_LOG_INFO 2 -#define X264_LOG_DEBUG 3 - -/* Threading */ -#define X264_THREADS_AUTO 0 /* Automatically select optimal number of threads */ -#define X264_SYNC_LOOKAHEAD_AUTO (-1) /* Automatically select optimal lookahead thread buffer size */ - -/* HRD */ -#define X264_NAL_HRD_NONE 0 -#define X264_NAL_HRD_VBR 1 -#define X264_NAL_HRD_CBR 2 - -/* Zones: override ratecontrol or other options for specific sections of the video. - * See x264_encoder_reconfig() for which options can be changed. - * If zones overlap, whichever comes later in the list takes precedence. */ -typedef struct x264_zone_t -{ - int i_start, i_end; /* range of frame numbers */ - int b_force_qp; /* whether to use qp vs bitrate factor */ - int i_qp; - float f_bitrate_factor; - struct x264_param_t *param; -} x264_zone_t; - -typedef struct x264_param_t -{ - /* CPU flags */ - uint32_t cpu; - int i_threads; /* encode multiple frames in parallel */ - int i_lookahead_threads; /* multiple threads for lookahead analysis */ - int b_sliced_threads; /* Whether to use slice-based threading. */ - int b_deterministic; /* whether to allow non-deterministic optimizations when threaded */ - int b_cpu_independent; /* force canonical behavior rather than cpu-dependent optimal algorithms */ - int i_sync_lookahead; /* threaded lookahead buffer */ - - /* Video Properties */ - int i_width; - int i_height; - int i_csp; /* CSP of encoded bitstream */ - int i_bitdepth; - int i_level_idc; - int i_frame_total; /* number of frames to encode if known, else 0 */ - - /* NAL HRD - * Uses Buffering and Picture Timing SEIs to signal HRD - * The HRD in H.264 was not designed with VFR in mind. - * It is therefore not recommendeded to use NAL HRD with VFR. - * Furthermore, reconfiguring the VBV (via x264_encoder_reconfig) - * will currently generate invalid HRD. */ - int i_nal_hrd; - - struct - { - /* they will be reduced to be 0 < x <= 65535 and prime */ - int i_sar_height; - int i_sar_width; - - int i_overscan; /* 0=undef, 1=no overscan, 2=overscan */ - - /* see h264 annex E for the values of the following */ - int i_vidformat; - int b_fullrange; - int i_colorprim; - int i_transfer; - int i_colmatrix; - int i_chroma_loc; /* both top & bottom */ - } vui; - - /* Bitstream parameters */ - int i_frame_reference; /* Maximum number of reference frames */ - int i_dpb_size; /* Force a DPB size larger than that implied by B-frames and reference frames. - * Useful in combination with interactive error resilience. */ - int i_keyint_max; /* Force an IDR keyframe at this interval */ - int i_keyint_min; /* Scenecuts closer together than this are coded as I, not IDR. */ - int i_scenecut_threshold; /* how aggressively to insert extra I frames */ - int b_intra_refresh; /* Whether or not to use periodic intra refresh instead of IDR frames. */ - - int i_bframe; /* how many b-frame between 2 references pictures */ - int i_bframe_adaptive; - int i_bframe_bias; - int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */ - int b_open_gop; - int b_bluray_compat; - int i_avcintra_class; - int i_avcintra_flavor; - - int b_deblocking_filter; - int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */ - int i_deblocking_filter_beta; /* [-6, 6] idem */ - - int b_cabac; - int i_cabac_init_idc; - - int b_interlaced; - int b_constrained_intra; - - int i_cqm_preset; - char *psz_cqm_file; /* filename (in UTF-8) of CQM file, JM format */ - uint8_t cqm_4iy[16]; /* used only if i_cqm_preset == X264_CQM_CUSTOM */ - uint8_t cqm_4py[16]; - uint8_t cqm_4ic[16]; - uint8_t cqm_4pc[16]; - uint8_t cqm_8iy[64]; - uint8_t cqm_8py[64]; - uint8_t cqm_8ic[64]; - uint8_t cqm_8pc[64]; - - /* Log */ - void (*pf_log)( void *, int i_level, const char *psz, va_list ); - void *p_log_private; - int i_log_level; - int b_full_recon; /* fully reconstruct frames, even when not necessary for encoding. Implied by psz_dump_yuv */ - char *psz_dump_yuv; /* filename (in UTF-8) for reconstructed frames */ - - /* Encoder analyser parameters */ - struct - { - unsigned int intra; /* intra partitions */ - unsigned int inter; /* inter partitions */ - - int b_transform_8x8; - int i_weighted_pred; /* weighting for P-frames */ - int b_weighted_bipred; /* implicit weighting for B-frames */ - int i_direct_mv_pred; /* spatial vs temporal mv prediction */ - int i_chroma_qp_offset; - - int i_me_method; /* motion estimation algorithm to use (X264_ME_*) */ - int i_me_range; /* integer pixel motion estimation search range (from predicted mv) */ - int i_mv_range; /* maximum length of a mv (in pixels). -1 = auto, based on level */ - int i_mv_range_thread; /* minimum space between threads. -1 = auto, based on number of threads. */ - int i_subpel_refine; /* subpixel motion estimation quality */ - int b_chroma_me; /* chroma ME for subpel and mode decision in P-frames */ - int b_mixed_references; /* allow each mb partition to have its own reference number */ - int i_trellis; /* trellis RD quantization */ - int b_fast_pskip; /* early SKIP detection on P-frames */ - int b_dct_decimate; /* transform coefficient thresholding on P-frames */ - int i_noise_reduction; /* adaptive pseudo-deadzone */ - float f_psy_rd; /* Psy RD strength */ - float f_psy_trellis; /* Psy trellis strength */ - int b_psy; /* Toggle all psy optimizations */ - - int b_mb_info; /* Use input mb_info data in x264_picture_t */ - int b_mb_info_update; /* Update the values in mb_info according to the results of encoding. */ - - /* the deadzone size that will be used in luma quantization */ - int i_luma_deadzone[2]; /* {inter, intra} */ - - int b_psnr; /* compute and print PSNR stats */ - int b_ssim; /* compute and print SSIM stats */ - } analyse; - - /* Rate control parameters */ - struct - { - int i_rc_method; /* X264_RC_* */ - - int i_qp_constant; /* 0=lossless */ - int i_qp_min; /* min allowed QP value */ - int i_qp_max; /* max allowed QP value */ - int i_qp_step; /* max QP step between frames */ - - int i_bitrate; - float f_rf_constant; /* 1pass VBR, nominal QP */ - float f_rf_constant_max; /* In CRF mode, maximum CRF as caused by VBV */ - float f_rate_tolerance; - int i_vbv_max_bitrate; - int i_vbv_buffer_size; - float f_vbv_buffer_init; /* <=1: fraction of buffer_size. >1: kbit */ - float f_ip_factor; - float f_pb_factor; - - /* VBV filler: force CBR VBV and use filler bytes to ensure hard-CBR. - * Implied by NAL-HRD CBR. */ - int b_filler; - - int i_aq_mode; /* psy adaptive QP. (X264_AQ_*) */ - float f_aq_strength; - int b_mb_tree; /* Macroblock-tree ratecontrol. */ - int i_lookahead; - - /* 2pass */ - int b_stat_write; /* Enable stat writing in psz_stat_out */ - char *psz_stat_out; /* output filename (in UTF-8) of the 2pass stats file */ - int b_stat_read; /* Read stat from psz_stat_in and use it */ - char *psz_stat_in; /* input filename (in UTF-8) of the 2pass stats file */ - - /* 2pass params (same as ffmpeg ones) */ - float f_qcompress; /* 0.0 => cbr, 1.0 => constant qp */ - float f_qblur; /* temporally blur quants */ - float f_complexity_blur; /* temporally blur complexity */ - x264_zone_t *zones; /* ratecontrol overrides */ - int i_zones; /* number of zone_t's */ - char *psz_zones; /* alternate method of specifying zones */ - } rc; - - /* Cropping Rectangle parameters: added to those implicitly defined by - non-mod16 video resolutions. */ - struct - { - int i_left; - int i_top; - int i_right; - int i_bottom; - } crop_rect; - - /* frame packing arrangement flag */ - int i_frame_packing; - - /* mastering display SEI: Primary and white point chromaticity coordinates - in 0.00002 increments. Brightness units are 0.0001 cd/m^2. */ - struct - { - int b_mastering_display; /* enable writing this SEI */ - int i_green_x; - int i_green_y; - int i_blue_x; - int i_blue_y; - int i_red_x; - int i_red_y; - int i_white_x; - int i_white_y; - int64_t i_display_max; - int64_t i_display_min; - } mastering_display; - - /* content light level SEI */ - struct - { - int b_cll; /* enable writing this SEI */ - int i_max_cll; - int i_max_fall; - } content_light_level; - - /* alternative transfer SEI */ - int i_alternative_transfer; - - /* Muxing parameters */ - int b_aud; /* generate access unit delimiters */ - int b_repeat_headers; /* put SPS/PPS before each keyframe */ - int b_annexb; /* if set, place start codes (4 bytes) before NAL units, - * otherwise place size (4 bytes) before NAL units. */ - int i_sps_id; /* SPS and PPS id number */ - int b_vfr_input; /* VFR input. If 1, use timebase and timestamps for ratecontrol purposes. - * If 0, use fps only. */ - int b_pulldown; /* use explicity set timebase for CFR */ - uint32_t i_fps_num; - uint32_t i_fps_den; - uint32_t i_timebase_num; /* Timebase numerator */ - uint32_t i_timebase_den; /* Timebase denominator */ - - int b_tff; - - /* Pulldown: - * The correct pic_struct must be passed with each input frame. - * The input timebase should be the timebase corresponding to the output framerate. This should be constant. - * e.g. for 3:2 pulldown timebase should be 1001/30000 - * The PTS passed with each frame must be the PTS of the frame after pulldown is applied. - * Frame doubling and tripling require b_vfr_input set to zero (see H.264 Table D-1) - * - * Pulldown changes are not clearly defined in H.264. Therefore, it is the calling app's responsibility to manage this. - */ - - int b_pic_struct; - - /* Fake Interlaced. - * - * Used only when b_interlaced=0. Setting this flag makes it possible to flag the stream as PAFF interlaced yet - * encode all frames progessively. It is useful for encoding 25p and 30p Blu-Ray streams. - */ - - int b_fake_interlaced; - - /* Don't optimize header parameters based on video content, e.g. ensure that splitting an input video, compressing - * each part, and stitching them back together will result in identical SPS/PPS. This is necessary for stitching - * with container formats that don't allow multiple SPS/PPS. */ - int b_stitchable; - - int b_opencl; /* use OpenCL when available */ - int i_opencl_device; /* specify count of GPU devices to skip, for CLI users */ - void *opencl_device_id; /* pass explicit cl_device_id as void*, for API users */ - char *psz_clbin_file; /* filename (in UTF-8) of the compiled OpenCL kernel cache file */ - - /* Slicing parameters */ - int i_slice_max_size; /* Max size per slice in bytes; includes estimated NAL overhead. */ - int i_slice_max_mbs; /* Max number of MBs per slice; overrides i_slice_count. */ - int i_slice_min_mbs; /* Min number of MBs per slice */ - int i_slice_count; /* Number of slices per frame: forces rectangular slices. */ - int i_slice_count_max; /* Absolute cap on slices per frame; stops applying slice-max-size - * and slice-max-mbs if this is reached. */ - - /* Optional callback for freeing this x264_param_t when it is done being used. - * Only used when the x264_param_t sits in memory for an indefinite period of time, - * i.e. when an x264_param_t is passed to x264_t in an x264_picture_t or in zones. - * Not used when x264_encoder_reconfig is called directly. */ - void (*param_free)( void* ); - - /* Optional low-level callback for low-latency encoding. Called for each output NAL unit - * immediately after the NAL unit is finished encoding. This allows the calling application - * to begin processing video data (e.g. by sending packets over a network) before the frame - * is done encoding. - * - * This callback MUST do the following in order to work correctly: - * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 64. - * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer. - * After these steps, the content of nal is valid and can be used in the same way as if - * the NAL unit were output by x264_encoder_encode. - * - * This does not need to be synchronous with the encoding process: the data pointed to - * by nal (both before and after x264_nal_encode) will remain valid until the next - * x264_encoder_encode call. The callback must be re-entrant. - * - * This callback does not work with frame-based threads; threads must be disabled - * or sliced-threads enabled. This callback also does not work as one would expect - * with HRD -- since the buffering period SEI cannot be calculated until the frame - * is finished encoding, it will not be sent via this callback. - * - * Note also that the NALs are not necessarily returned in order when sliced threads is - * enabled. Accordingly, the variable i_first_mb and i_last_mb are available in - * x264_nal_t to help the calling application reorder the slices if necessary. - * - * When this callback is enabled, x264_encoder_encode does not return valid NALs; - * the calling application is expected to acquire all output NALs through the callback. - * - * It is generally sensible to combine this callback with a use of slice-max-mbs or - * slice-max-size. - * - * The opaque pointer is the opaque pointer from the input frame associated with this - * NAL unit. This helps distinguish between nalu_process calls from different sources, - * e.g. if doing multiple encodes in one process. - */ - void (*nalu_process)( x264_t *h, x264_nal_t *nal, void *opaque ); - - /* For internal use only */ - void *opaque; -} x264_param_t; - -X264_API void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal ); - -/**************************************************************************** - * H.264 level restriction information - ****************************************************************************/ - -typedef struct x264_level_t -{ - uint8_t level_idc; - int32_t mbps; /* max macroblock processing rate (macroblocks/sec) */ - int32_t frame_size; /* max frame size (macroblocks) */ - int32_t dpb; /* max decoded picture buffer (mbs) */ - int32_t bitrate; /* max bitrate (kbit/sec) */ - int32_t cpb; /* max vbv buffer (kbit) */ - uint16_t mv_range; /* max vertical mv component range (pixels) */ - uint8_t mvs_per_2mb; /* max mvs per 2 consecutive mbs. */ - uint8_t slice_rate; /* ?? */ - uint8_t mincr; /* min compression ratio */ - uint8_t bipred8x8; /* limit bipred to >=8x8 */ - uint8_t direct8x8; /* limit b_direct to >=8x8 */ - uint8_t frame_only; /* forbid interlacing */ -} x264_level_t; - -/* all of the levels defined in the standard, terminated by .level_idc=0 */ -X264_API extern const x264_level_t x264_levels[]; - -/**************************************************************************** - * Basic parameter handling functions - ****************************************************************************/ - -/* x264_param_default: - * fill x264_param_t with default values and do CPU detection */ -X264_API void x264_param_default( x264_param_t * ); - -/* x264_param_parse: - * set one parameter by name. - * returns 0 on success, or returns one of the following errors. - * note: BAD_VALUE occurs only if it can't even parse the value, - * numerical range is not checked until x264_encoder_open() or - * x264_encoder_reconfig(). - * value=NULL means "true" for boolean options, but is a BAD_VALUE for non-booleans. - * can allocate memory which should be freed by call of x264_param_cleanup. */ -#define X264_PARAM_BAD_NAME (-1) -#define X264_PARAM_BAD_VALUE (-2) -#define X264_PARAM_ALLOC_FAILED (-3) -X264_API int x264_param_parse( x264_param_t *, const char *name, const char *value ); - -/* x264_param_cleanup: - * Cleans up and frees allocated members of x264_param_t. - * This *does not* free the x264_param_t itself, as it may exist on the - * stack. It only frees any members of the struct that were allocated by - * x264 itself, in e.g. x264_param_parse(). */ -X264_API void x264_param_cleanup( x264_param_t *param ); - -/**************************************************************************** - * Advanced parameter handling functions - ****************************************************************************/ - -/* These functions expose the full power of x264's preset-tune-profile system for - * easy adjustment of large numbers of internal parameters. - * - * In order to replicate x264CLI's option handling, these functions MUST be called - * in the following order: - * 1) x264_param_default_preset - * 2) Custom user options (via param_parse or directly assigned variables) - * 3) x264_param_apply_fastfirstpass - * 4) x264_param_apply_profile - * - * Additionally, x264CLI does not apply step 3 if the preset chosen is "placebo" - * or --slow-firstpass is set. */ - -/* x264_param_default_preset: - * The same as x264_param_default, but also use the passed preset and tune - * to modify the default settings. - * (either can be NULL, which implies no preset or no tune, respectively) - * - * Currently available presets are, ordered from fastest to slowest: */ -static const char * const x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "placebo", 0 }; - -/* The presets can also be indexed numerically, as in: - * x264_param_default_preset( ¶m, "3", ... ) - * with ultrafast mapping to "0" and placebo mapping to "9". This mapping may - * of course change if new presets are added in between, but will always be - * ordered from fastest to slowest. - * - * Warning: the speed of these presets scales dramatically. Ultrafast is a full - * 100 times faster than placebo! - * - * Currently available tunings are: */ -static const char * const x264_tune_names[] = { "film", "animation", "grain", "stillimage", "psnr", "ssim", "fastdecode", "zerolatency", 0 }; - -/* Multiple tunings can be used if separated by a delimiter in ",./-+", - * however multiple psy tunings cannot be used. - * film, animation, grain, stillimage, psnr, and ssim are psy tunings. - * - * returns 0 on success, negative on failure (e.g. invalid preset/tune name). */ -X264_API int x264_param_default_preset( x264_param_t *, const char *preset, const char *tune ); - -/* x264_param_apply_fastfirstpass: - * If first-pass mode is set (rc.b_stat_read == 0, rc.b_stat_write == 1), - * modify the encoder settings to disable options generally not useful on - * the first pass. */ -X264_API void x264_param_apply_fastfirstpass( x264_param_t * ); - -/* x264_param_apply_profile: - * Applies the restrictions of the given profile. - * Currently available profiles are, from most to least restrictive: */ -static const char * const x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 }; - -/* (can be NULL, in which case the function will do nothing) - * - * Does NOT guarantee that the given profile will be used: if the restrictions - * of "High" are applied to settings that are already Baseline-compatible, the - * stream will remain baseline. In short, it does not increase settings, only - * decrease them. - * - * returns 0 on success, negative on failure (e.g. invalid profile name). */ -X264_API int x264_param_apply_profile( x264_param_t *, const char *profile ); - -/**************************************************************************** - * Picture structures and functions - ****************************************************************************/ - -/* x264_chroma_format: - * Specifies the chroma formats that x264 supports encoding. When this - * value is non-zero, then it represents a X264_CSP_* that is the only - * chroma format that x264 supports encoding. If the value is 0 then - * there are no restrictions. */ -X264_API extern const int x264_chroma_format; - -enum pic_struct_e -{ - PIC_STRUCT_AUTO = 0, // automatically decide (default) - PIC_STRUCT_PROGRESSIVE = 1, // progressive frame - // "TOP" and "BOTTOM" are not supported in x264 (PAFF only) - PIC_STRUCT_TOP_BOTTOM = 4, // top field followed by bottom - PIC_STRUCT_BOTTOM_TOP = 5, // bottom field followed by top - PIC_STRUCT_TOP_BOTTOM_TOP = 6, // top field, bottom field, top field repeated - PIC_STRUCT_BOTTOM_TOP_BOTTOM = 7, // bottom field, top field, bottom field repeated - PIC_STRUCT_DOUBLE = 8, // double frame - PIC_STRUCT_TRIPLE = 9, // triple frame -}; - -typedef struct x264_hrd_t -{ - double cpb_initial_arrival_time; - double cpb_final_arrival_time; - double cpb_removal_time; - - double dpb_output_time; -} x264_hrd_t; - -/* Arbitrary user SEI: - * Payload size is in bytes and the payload pointer must be valid. - * Payload types and syntax can be found in Annex D of the H.264 Specification. - * SEI payload alignment bits as described in Annex D must be included at the - * end of the payload if needed. - * The payload should not be NAL-encapsulated. - * Payloads are written first in order of input, apart from in the case when HRD - * is enabled where payloads are written after the Buffering Period SEI. */ - -typedef struct x264_sei_payload_t -{ - int payload_size; - int payload_type; - uint8_t *payload; -} x264_sei_payload_t; - -typedef struct x264_sei_t -{ - int num_payloads; - x264_sei_payload_t *payloads; - /* In: optional callback to free each payload AND x264_sei_payload_t when used. */ - void (*sei_free)( void* ); -} x264_sei_t; - -typedef struct x264_image_t -{ - int i_csp; /* Colorspace */ - int i_plane; /* Number of image planes */ - int i_stride[4]; /* Strides for each plane */ - uint8_t *plane[4]; /* Pointers to each plane */ -} x264_image_t; - -typedef struct x264_image_properties_t -{ - /* All arrays of data here are ordered as follows: - * each array contains one offset per macroblock, in raster scan order. In interlaced - * mode, top-field MBs and bottom-field MBs are interleaved at the row level. - * Macroblocks are 16x16 blocks of pixels (with respect to the luma plane). For the - * purposes of calculating the number of macroblocks, width and height are rounded up to - * the nearest 16. If in interlaced mode, height is rounded up to the nearest 32 instead. */ - - /* In: an array of quantizer offsets to be applied to this image during encoding. - * These are added on top of the decisions made by x264. - * Offsets can be fractional; they are added before QPs are rounded to integer. - * Adaptive quantization must be enabled to use this feature. Behavior if quant - * offsets differ between encoding passes is undefined. */ - float *quant_offsets; - /* In: optional callback to free quant_offsets when used. - * Useful if one wants to use a different quant_offset array for each frame. */ - void (*quant_offsets_free)( void* ); - - /* In: optional array of flags for each macroblock. - * Allows specifying additional information for the encoder such as which macroblocks - * remain unchanged. Usable flags are listed below. - * x264_param_t.analyse.b_mb_info must be set to use this, since x264 needs to track - * extra data internally to make full use of this information. - * - * Out: if b_mb_info_update is set, x264 will update this array as a result of encoding. - * - * For "MBINFO_CONSTANT", it will remove this flag on any macroblock whose decoded - * pixels have changed. This can be useful for e.g. noting which areas of the - * frame need to actually be blitted. Note: this intentionally ignores the effects - * of deblocking for the current frame, which should be fine unless one needs exact - * pixel-perfect accuracy. - * - * Results for MBINFO_CONSTANT are currently only set for P-frames, and are not - * guaranteed to enumerate all blocks which haven't changed. (There may be false - * negatives, but no false positives.) - */ - uint8_t *mb_info; - /* In: optional callback to free mb_info when used. */ - void (*mb_info_free)( void* ); - - /* The macroblock is constant and remains unchanged from the previous frame. */ - #define X264_MBINFO_CONSTANT (1U<<0) - /* More flags may be added in the future. */ - - /* Out: SSIM of the the frame luma (if x264_param_t.b_ssim is set) */ - double f_ssim; - /* Out: Average PSNR of the frame (if x264_param_t.b_psnr is set) */ - double f_psnr_avg; - /* Out: PSNR of Y, U, and V (if x264_param_t.b_psnr is set) */ - double f_psnr[3]; - - /* Out: Average effective CRF of the encoded frame */ - double f_crf_avg; -} x264_image_properties_t; - -typedef struct x264_picture_t -{ - /* In: force picture type (if not auto) - * If x264 encoding parameters are violated in the forcing of picture types, - * x264 will correct the input picture type and log a warning. - * Out: type of the picture encoded */ - int i_type; - /* In: force quantizer for != X264_QP_AUTO */ - int i_qpplus1; - /* In: pic_struct, for pulldown/doubling/etc...used only if b_pic_struct=1. - * use pic_struct_e for pic_struct inputs - * Out: pic_struct element associated with frame */ - int i_pic_struct; - /* Out: whether this frame is a keyframe. Important when using modes that result in - * SEI recovery points being used instead of IDR frames. */ - int b_keyframe; - /* In: user pts, Out: pts of encoded picture (user)*/ - int64_t i_pts; - /* Out: frame dts. When the pts of the first frame is close to zero, - * initial frames may have a negative dts which must be dealt with by any muxer */ - int64_t i_dts; - /* In: custom encoding parameters to be set from this frame forwards - (in coded order, not display order). If NULL, continue using - parameters from the previous frame. Some parameters, such as - aspect ratio, can only be changed per-GOP due to the limitations - of H.264 itself; in this case, the caller must force an IDR frame - if it needs the changed parameter to apply immediately. */ - x264_param_t *param; - /* In: raw image data */ - /* Out: reconstructed image data. x264 may skip part of the reconstruction process, - e.g. deblocking, in frames where it isn't necessary. To force complete - reconstruction, at a small speed cost, set b_full_recon. */ - x264_image_t img; - /* In: optional information to modify encoder decisions for this frame - * Out: information about the encoded frame */ - x264_image_properties_t prop; - /* Out: HRD timing information. Output only when i_nal_hrd is set. */ - x264_hrd_t hrd_timing; - /* In: arbitrary user SEI (e.g subtitles, AFDs) */ - x264_sei_t extra_sei; - /* private user data. copied from input to output frames. */ - void *opaque; -} x264_picture_t; - -/* x264_picture_init: - * initialize an x264_picture_t. Needs to be done if the calling application - * allocates its own x264_picture_t as opposed to using x264_picture_alloc. */ -X264_API void x264_picture_init( x264_picture_t *pic ); - -/* x264_picture_alloc: - * alloc data for a picture. You must call x264_picture_clean on it. - * returns 0 on success, or -1 on malloc failure or invalid colorspace. */ -X264_API int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height ); - -/* x264_picture_clean: - * free associated resource for a x264_picture_t allocated with - * x264_picture_alloc ONLY */ -X264_API void x264_picture_clean( x264_picture_t *pic ); - -/**************************************************************************** - * Encoder functions - ****************************************************************************/ - -/* Force a link error in the case of linking against an incompatible API version. - * Glue #defines exist to force correct macro expansion; the final output of the macro - * is x264_encoder_open_##X264_BUILD (for purposes of dlopen). */ -#define x264_encoder_glue1(x,y) x##y -#define x264_encoder_glue2(x,y) x264_encoder_glue1(x,y) -#define x264_encoder_open x264_encoder_glue2(x264_encoder_open_,X264_BUILD) - -/* x264_encoder_open: - * create a new encoder handler, all parameters from x264_param_t are copied */ -X264_API x264_t *x264_encoder_open( x264_param_t * ); - -/* x264_encoder_reconfig: - * various parameters from x264_param_t are copied. - * this takes effect immediately, on whichever frame is encoded next; - * due to delay, this may not be the next frame passed to encoder_encode. - * if the change should apply to some particular frame, use x264_picture_t->param instead. - * returns 0 on success, negative on parameter validation error. - * not all parameters can be changed; see the actual function for a detailed breakdown. - * - * since not all parameters can be changed, moving from preset to preset may not always - * fully copy all relevant parameters, but should still work usably in practice. however, - * more so than for other presets, many of the speed shortcuts used in ultrafast cannot be - * switched out of; using reconfig to switch between ultrafast and other presets is not - * recommended without a more fine-grained breakdown of parameters to take this into account. */ -X264_API int x264_encoder_reconfig( x264_t *, x264_param_t * ); -/* x264_encoder_parameters: - * copies the current internal set of parameters to the pointer provided - * by the caller. useful when the calling application needs to know - * how x264_encoder_open has changed the parameters, or the current state - * of the encoder after multiple x264_encoder_reconfig calls. - * note that the data accessible through pointers in the returned param struct - * (e.g. filenames) should not be modified by the calling application. */ -X264_API void x264_encoder_parameters( x264_t *, x264_param_t * ); -/* x264_encoder_headers: - * return the SPS and PPS that will be used for the whole stream. - * *pi_nal is the number of NAL units outputted in pp_nal. - * returns the number of bytes in the returned NALs. - * returns negative on error. - * the payloads of all output NALs are guaranteed to be sequential in memory. */ -X264_API int x264_encoder_headers( x264_t *, x264_nal_t **pp_nal, int *pi_nal ); -/* x264_encoder_encode: - * encode one picture. - * *pi_nal is the number of NAL units outputted in pp_nal. - * returns the number of bytes in the returned NALs. - * returns negative on error and zero if no NAL units returned. - * the payloads of all output NALs are guaranteed to be sequential in memory. */ -X264_API int x264_encoder_encode( x264_t *, x264_nal_t **pp_nal, int *pi_nal, x264_picture_t *pic_in, x264_picture_t *pic_out ); -/* x264_encoder_close: - * close an encoder handler */ -X264_API void x264_encoder_close( x264_t * ); -/* x264_encoder_delayed_frames: - * return the number of currently delayed (buffered) frames - * this should be used at the end of the stream, to know when you have all the encoded frames. */ -X264_API int x264_encoder_delayed_frames( x264_t * ); -/* x264_encoder_maximum_delayed_frames( x264_t * ): - * return the maximum number of delayed (buffered) frames that can occur with the current - * parameters. */ -X264_API int x264_encoder_maximum_delayed_frames( x264_t * ); -/* x264_encoder_intra_refresh: - * If an intra refresh is not in progress, begin one with the next P-frame. - * If an intra refresh is in progress, begin one as soon as the current one finishes. - * Requires that b_intra_refresh be set. - * - * Useful for interactive streaming where the client can tell the server that packet loss has - * occurred. In this case, keyint can be set to an extremely high value so that intra refreshes - * only occur when calling x264_encoder_intra_refresh. - * - * In multi-pass encoding, if x264_encoder_intra_refresh is called differently in each pass, - * behavior is undefined. - * - * Should not be called during an x264_encoder_encode. */ -X264_API void x264_encoder_intra_refresh( x264_t * ); -/* x264_encoder_invalidate_reference: - * An interactive error resilience tool, designed for use in a low-latency one-encoder-few-clients - * system. When the client has packet loss or otherwise incorrectly decodes a frame, the encoder - * can be told with this command to "forget" the frame and all frames that depend on it, referencing - * only frames that occurred before the loss. This will force a keyframe if no frames are left to - * reference after the aforementioned "forgetting". - * - * It is strongly recommended to use a large i_dpb_size in this case, which allows the encoder to - * keep around extra, older frames to fall back on in case more recent frames are all invalidated. - * Unlike increasing i_frame_reference, this does not increase the number of frames used for motion - * estimation and thus has no speed impact. It is also recommended to set a very large keyframe - * interval, so that keyframes are not used except as necessary for error recovery. - * - * x264_encoder_invalidate_reference is not currently compatible with the use of B-frames or intra - * refresh. - * - * In multi-pass encoding, if x264_encoder_invalidate_reference is called differently in each pass, - * behavior is undefined. - * - * Should not be called during an x264_encoder_encode, but multiple calls can be made simultaneously. - * - * Returns 0 on success, negative on failure. */ -X264_API int x264_encoder_invalidate_reference( x264_t *, int64_t pts ); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/extern/src/x264_config.h b/extern/src/x264_config.h deleted file mode 100644 index 19ea6ac8..00000000 --- a/extern/src/x264_config.h +++ /dev/null @@ -1,8 +0,0 @@ -#define X264_BIT_DEPTH 8 -#define X264_GPL 1 -#define X264_INTERLACED 1 -#define X264_CHROMA_FORMAT 0 -#define X264_REV 3065 -#define X264_REV_DIFF 0 -#define X264_VERSION " r3065" -#define X264_POINTVER "0.164.3065" diff --git a/src/CLOUD/Classes/glitter_editor.h b/src/CLOUD/Classes/glitter_editor.h deleted file mode 100644 index e0633617..00000000 --- a/src/CLOUD/Classes/glitter_editor.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#if defined(CLOUD_DEV) -#include "../../KKdLib/default.h" -#include "../../KKdLib/vec.h" -#include "../../CRE/Glitter/glitter.h" - -extern bool glitter_editor_enabled; - -extern void glitter_editor_dispose(); -extern void glitter_editor_init(); -extern void glitter_editor_draw(); -extern void glitter_editor_drop(size_t count, char** paths); -extern void glitter_editor_imgui(); -extern void glitter_editor_input(); -extern void glitter_editor_render(); -#endif diff --git a/src/CLOUD/classes.c b/src/CLOUD/classes.c index 52d48be8..63d5384c 100644 --- a/src/CLOUD/classes.c +++ b/src/CLOUD/classes.c @@ -5,79 +5,70 @@ #include "classes.h" -void classes_process_dispose(classes_struct* classes, const size_t classes_count) { +void classes_process_init(classes_struct* classes, const size_t classes_count, render_context* rctx) { if (!classes || !classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (classes[i].dispose) { - lock_lock(&classes[i].lock); - classes[i].dispose(); - lock_unlock(&classes[i].lock); - } - lock_free(&classes[i].lock); + classes_struct* c = &classes[i]; + lock_init(&c->data.lock); + if (lock_check_init(&c->data.lock) + && c->flags & (CLASSES_INIT_AT_STARTUP | CLASSES_SHOW_AT_STARTUP) && c->init) { + lock_lock(&c->data.lock); + if (c->init(&c->data, rctx)) + c->data.flags = CLASS_INIT; + else + c->data.flags = CLASS_DISPOSED | CLASS_HIDDEN; + c->data.imgui_focus = false; - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_dispose(classes[i].sub_classes, classes[i].sub_classes_count); + if (~c->flags & CLASSES_SHOW_AT_STARTUP) + c->data.flags |= CLASS_HIDDEN; + lock_unlock(&c->data.lock); + } + + if (lock_check_init(&c->data.lock) + && c->flags & CLASSES_SHOW_AT_STARTUP) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT && ((c->show && c->show(&c->data)) || !c->show)) + c->data.flags &= ~(CLASS_HIDE | CLASS_HIDDEN); + lock_unlock(&c->data.lock); + } + + if (c->sub_classes && c->sub_classes_count) + classes_process_init(c->sub_classes, c->sub_classes_count, rctx); } } -void classes_process_init(classes_struct* classes, const size_t classes_count) { - if (!classes || !classes_count) - return; - +void classes_process_draw(classes_struct* classes, size_t classes_count) { for (size_t i = 0; i < classes_count; i++) { - lock_init(&classes[i].lock); - if (classes[i].init && classes[i].flags & CLASSES_INIT_AT_STARTUP) { - lock_lock(&classes[i].lock); - classes[i].init(); - lock_unlock(&classes[i].lock); + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock) && c->draw) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT) + c->draw(&c->data); + lock_unlock(&c->data.lock); } - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_init(classes[i].sub_classes, classes[i].sub_classes_count); - } -} - -void classes_process_control(classes_struct* classes, const size_t classes_count) { - if (!classes || !classes_count) - return; - - for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].control) { - lock_lock(&classes[i].lock); - classes[i].control(); - lock_unlock(&classes[i].lock); - } - - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_control(classes[i].sub_classes, classes[i].sub_classes_count); - } -} - -extern void classes_process_draw(classes_struct* classes, size_t classes_count) { - for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].draw) { - lock_lock(&classes[i].lock); - classes[i].draw(); - lock_unlock(&classes[i].lock); - } - - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_draw(classes[i].sub_classes, classes[i].sub_classes_count); + if (c->sub_classes && c->sub_classes_count) + classes_process_draw(c->sub_classes, c->sub_classes_count); } } void classes_process_drop(classes_struct* classes, size_t classes_count, size_t count, char** paths) { + if (count < 1 || !paths[0]) + return; + for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].drop) { - lock_lock(&classes[i].lock); - classes[i].drop(count, paths); - lock_unlock(&classes[i].lock); + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock) && c->drop) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT) + c->drop(&c->data, count, paths); + lock_unlock(&c->data.lock); } - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_drop(classes[i].sub_classes, classes[i].sub_classes_count, count, paths); + if (c->sub_classes && c->sub_classes_count) + classes_process_drop(c->sub_classes, c->sub_classes_count, count, paths); } } @@ -86,14 +77,15 @@ void classes_process_imgui(classes_struct* classes, const size_t classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].imgui) { - lock_lock(&classes[i].lock); - classes[i].imgui(); - lock_unlock(&classes[i].lock); + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock) && c->imgui) { + lock_lock(&c->data.lock); + if (~c->data.flags & CLASS_HIDDEN) + c->imgui(&c->data); + lock_unlock(&c->data.lock); } - - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_imgui(classes[i].sub_classes, classes[i].sub_classes_count); + + classes_process_imgui(c->sub_classes, c->sub_classes_count); } } @@ -102,14 +94,15 @@ void classes_process_input(classes_struct* classes, const size_t classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].input) { - lock_lock(&classes[i].lock); - classes[i].input(); - lock_unlock(&classes[i].lock); + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock) && c->input) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT) + c->input(&c->data); + lock_unlock(&c->data.lock); } - - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_input(classes[i].sub_classes, classes[i].sub_classes_count); + + classes_process_input(c->sub_classes, c->sub_classes_count); } } @@ -118,14 +111,42 @@ void classes_process_render(classes_struct* classes, const size_t classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].render) { - lock_lock(&classes[i].lock); - classes[i].render(); - lock_unlock(&classes[i].lock); - } + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock)) { + if (c->data.flags & CLASS_HIDE) { + lock_lock(&c->data.lock); + if (~c->data.flags & CLASS_HIDDEN && ((c->hide && c->hide(&c->data)) || !c->hide)) { + c->data.flags &= ~CLASS_HIDE; + c->data.flags |= CLASS_HIDDEN; + } + lock_unlock(&c->data.lock); + } - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_render(classes[i].sub_classes, classes[i].sub_classes_count); + if ((c->data.flags & CLASS_DISPOSE || (c->data.flags & CLASS_HIDDEN + && c->flags & CLASSES_DISPOSE_AT_HIDE))) { + lock_lock(&c->data.lock); + if (~c->data.flags & CLASS_HIDDEN && ((c->hide && c->hide(&c->data)) || !c->hide)) { + c->data.flags &= ~CLASS_HIDE; + c->data.flags |= CLASS_HIDDEN; + } + + if (~c->data.flags & CLASS_DISPOSED && ((c->dispose && c->dispose(&c->data)) || !c->dispose)) { + c->data.flags &= ~CLASS_DISPOSE; + c->data.flags |= CLASS_DISPOSED; + c->data.imgui_focus = false; + } + lock_unlock(&c->data.lock); + lock_free(&c->data.lock); + } + + if (c->data.flags & CLASS_INIT && c->render) { + lock_lock(&c->data.lock); + c->render(&c->data); + lock_unlock(&c->data.lock); + } + } + + classes_process_render(c->sub_classes, c->sub_classes_count); } } @@ -134,29 +155,40 @@ void classes_process_sound(classes_struct* classes, const size_t classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].sound) { - lock_lock(&classes[i].lock); - classes[i].sound(); - lock_unlock(&classes[i].lock); + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock) && c->sound) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT) + c->sound(&c->data); + lock_unlock(&c->data.lock); } - - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_sound(classes[i].sub_classes, classes[i].sub_classes_count); + + classes_process_sound(c->sub_classes, c->sub_classes_count); } } -void classes_process_video(classes_struct* classes, const size_t classes_count) { +void classes_process_dispose(classes_struct* classes, const size_t classes_count) { if (!classes || !classes_count) return; for (size_t i = 0; i < classes_count; i++) { - if (lock_check_init(&classes[i].lock) && classes[i].video) { - lock_lock(&classes[i].lock); - classes[i].video(); - lock_unlock(&classes[i].lock); - } + classes_struct* c = &classes[i]; + if (lock_check_init(&c->data.lock)) { + lock_lock(&c->data.lock); + if (~c->data.flags & CLASS_HIDDEN && ((c->hide && c->hide(&c->data)) || !c->hide)) { + c->data.flags &= ~CLASS_HIDE; + c->data.flags |= CLASS_HIDDEN; + } - if (classes[i].sub_classes && classes[i].sub_classes_count) - classes_process_video(classes[i].sub_classes, classes[i].sub_classes_count); + if (~c->data.flags & CLASS_DISPOSED && ((c->dispose && c->dispose(&c->data)) || !c->dispose)) { + c->data.flags &= ~CLASS_DISPOSE; + c->data.flags |= CLASS_DISPOSED; + c->data.imgui_focus = false; + } + lock_unlock(&c->data.lock); + } + lock_free(&c->data.lock); + + classes_process_dispose(c->sub_classes, c->sub_classes_count); } } diff --git a/src/CLOUD/classes.h b/src/CLOUD/classes.h index 278a3bb3..b5011924 100644 --- a/src/CLOUD/classes.h +++ b/src/CLOUD/classes.h @@ -7,40 +7,58 @@ #include "../KKdLib/default.h" #include "../CRE/lock.h" +#include "../CRE/render_context.h" + +#define CLASS_DATA_NO_DATA ((void*)0) +#define CLASSES_STRUCT_NO_FUNC ((void*)0) + +typedef enum class_flags { + CLASS_INIT = 0x01, + CLASS_DISPOSE = 0x02, + CLASS_DISPOSED = 0x04, + CLASS_HIDE = 0x08, + CLASS_HIDDEN = 0x10, +} class_flags; typedef enum classes_enum { CLASSES_INIT_AT_STARTUP = 0x01, - CLASSES_IN_CONTEXT_MENU = 0x02, + CLASSES_SHOW_AT_STARTUP = 0x02, + CLASSES_DISPOSE_AT_HIDE = 0x04, + CLASSES_IN_CONTEXT_MENU = 0x08, } classes_enum; +typedef struct class_data { + lock lock; + class_flags flags; + bool imgui_focus; + void* data; +} class_data; + typedef struct classes_struct classes_struct; struct classes_struct { const char* name; const classes_enum flags; - bool* enabled; - const void(* dispose)(); - const void(* init)(); - const void(* control)(); - const void(* draw)(); - const void(* drop)(size_t count, char** paths); - const void(* imgui)(); - const void(* input)(); - const void(* render)(); - const void(* sound)(); - const void(* video)(); - lock lock; + const bool(* init)(class_data* data, render_context* rctx); + const void(* draw)(class_data* data); + const void(* drop)(class_data* data, size_t count, char** paths); + const bool(* hide)(class_data* data); + const void(* imgui)(class_data* data); + const void(* input)(class_data* data); + const void(* render)(class_data* data); + const bool(* show)(class_data* data); + const void(* sound)(class_data* data); + const bool(* dispose)(class_data* data); + class_data data; classes_struct* sub_classes; size_t sub_classes_count; }; -extern void classes_process_dispose(classes_struct* classes, size_t classes_count); -extern void classes_process_init (classes_struct* classes, size_t classes_count); -extern void classes_process_control(classes_struct* classes, size_t classes_count); +extern void classes_process_init (classes_struct* classes, size_t classes_count, render_context* rctx); extern void classes_process_draw (classes_struct* classes, size_t classes_count); extern void classes_process_drop (classes_struct* classes, size_t classes_count, size_t count, char** paths); extern void classes_process_imgui (classes_struct* classes, size_t classes_count); extern void classes_process_input (classes_struct* classes, size_t classes_count); extern void classes_process_render (classes_struct* classes, size_t classes_count); extern void classes_process_sound (classes_struct* classes, size_t classes_count); -extern void classes_process_video (classes_struct* classes, size_t classes_count); +extern void classes_process_dispose(classes_struct* classes, size_t classes_count); diff --git a/src/CLOUD/classes/data_player.c b/src/CLOUD/classes/data_player.c deleted file mode 100644 index 27493d74..00000000 --- a/src/CLOUD/classes/data_player.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#if defined(VIDEO) -#include "data_player.h" -#include "imgui_helper.h" -#include "../../CRE/fbo_hdr.h" -#include "../../CRE/gl_state.h" -#include "../../CRE/lock.h" -#include "../../CRE/static_var.h" -#include "../../CRE/timer.h" -#include "../../CRE/video_x264.h" - -typedef struct data_player_struct { - bool dispose; - bool disposed; - bool imgui_focus; - video_x264 vid; - int32_t frame; - int32_t prev_frame; - lock lock; - HANDLE timer; -} data_player_struct; - -extern int32_t width; -extern int32_t height; -extern fbo_hdr* hfbo; -extern bool input_locked; - -const char* data_player_window_title = "Data Player"; - -bool data_player_enabled = true; -static data_player_struct data_player; - -void data_player_dispose() { - if (data_player.disposed) - return; - - if (data_player.vid.error_state >= 0) { - video_x264_flush(&data_player.vid); - io_free(&data_player.vid.io); - } - video_x264_close(&data_player.vid); - lock_free(&data_player.lock); - dispose_timer(data_player.timer); - data_player_enabled = false; - data_player.imgui_focus = false; - data_player.dispose = false; - data_player.disposed = true; -} - -void data_player_draw() { - if (!data_player_enabled) - return; - - bool ret = false; - lock_lock(&data_player.lock); - ret = data_player.frame != data_player.prev_frame; - if (!data_player.vid.data) - ret = true; - lock_unlock(&data_player.lock); - - if (ret) - return; - - lock_lock(&data_player.lock); - gl_state_bind_texture_2d(hfbo->color.color_texture->texture); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_SHORT, data_player.vid.data); - data_player.vid.fmt = VIDEO_X264_PIC_FORMAT_RGBA16; - video_x264_load_image_data(&data_player.vid); - data_player.frame++; - lock_unlock(&data_player.lock); -} - -void data_player_init() { - bool dispose = false; - lock_lock(&data_player.lock); - if (data_player_enabled || data_player.dispose) - dispose = true; - lock_unlock(&data_player.lock); - - if (dispose) - data_player_dispose(); - - video_x264_init_data init; - init.width = hfbo->width; - init.height = hfbo->height; - init.fps = 60.0; - init.flip = true; - init.preset = VIDEO_X264_PRESET_MEDIUM; - init.tune = VIDEO_X264_TUNE_NONE; - init.profile = VIDEO_X264_PROFILE_HIGH; - init.color_space = VIDEO_X264_COLOR_SPACE_I444; - init.bit_depth = VIDEO_X264_BIT_DEPTH_10_BIT; - init.rate_control.method = VIDEO_X264_RATE_CONTROL_CRF; - init.rate_control.crf = 0.0f; - - video_x264_init(&data_player.vid, &init); - if (data_player.vid.error_state >= 0) - io_open(&data_player.vid.io, "test.264", "wb"); - data_player.frame = 0; - data_player.prev_frame = 0; - data_player.timer = create_timer(); - lock_init(&data_player.lock); - data_player_enabled = true; -} - -void data_player_imgui() { - bool ret = false; - lock_lock(&data_player.lock); - if (!data_player_enabled) { - if (!data_player.disposed) - data_player.dispose = true; - ret = true; - } - else if (data_player.disposed) - data_player.disposed = false; - lock_unlock(&data_player.lock); - - if (ret) - return; - - lock_lock(&data_player.lock); - float_t w = min((float_t)width / 4.0f, 360.0f); - float_t h = min((float_t)height, 100.0f); - - igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); - igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); - - ImGuiWindowFlags window_flags = 0; - window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - - data_player.imgui_focus = false; - if (!igBegin(data_player_window_title, &data_player_enabled, window_flags)) { - data_player.dispose = true; - goto End; - } - - data_player.imgui_focus |= igIsWindowFocused(0); - -End: - igEnd(); - lock_unlock(&data_player.lock); -} - -void data_player_input() { - bool ret = false; - lock_lock(&data_player.lock); - if (!data_player_enabled) - ret = true; - lock_unlock(&data_player.lock); - - if (ret) - return; - - input_locked |= data_player.imgui_focus; -} - -void data_player_render() { - bool dispose = false; - bool ret = false; - lock_lock(&data_player.lock); - if (data_player.dispose) { - dispose = true; - ret = true; - } - else if (!data_player_enabled) - ret = true; - lock_unlock(&data_player.lock); - - if (dispose) - data_player_dispose(); - - if (ret) - return; -} - -void data_player_video() { - bool ret = false; - lock_lock(&data_player.lock); - if (!data_player_enabled) - ret = true; - - if (!ret && data_player.vid.error_state < 0) - ret = true; - lock_unlock(&data_player.lock); - - if (ret) - return; - - lock_lock(&data_player.lock); - if (data_player.frame != data_player.prev_frame) { - video_x264_encode(&data_player.vid, data_player.prev_frame); - data_player.prev_frame++; - } - lock_unlock(&data_player.lock); -} -#endif diff --git a/src/CLOUD/classes/data_player.h b/src/CLOUD/classes/data_player.h deleted file mode 100644 index a2982d6d..00000000 --- a/src/CLOUD/classes/data_player.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#if defined(VIDEO) -#pragma once - -#include "../../KKdLib/default.h" -#include "../../KKdLib/vec.h" - -extern bool data_player_enabled; - -extern void data_player_dispose(); -extern void data_player_draw(); -extern void data_player_init(); -extern void data_player_imgui(); -extern void data_player_input(); -extern void data_player_render(); -extern void data_player_video(); -#endif diff --git a/src/CLOUD/classes/data_test.c b/src/CLOUD/classes/data_test.c index 895d026c..9c4681e7 100644 --- a/src/CLOUD/classes/data_test.c +++ b/src/CLOUD/classes/data_test.c @@ -4,25 +4,78 @@ */ #include "data_test.h" +#include "data_test/auth_3d_test.h" +#include "data_test/glitter_test.h" +#include "data_test/stage_test.h" -bool data_test_enabled = true; - -classes_struct data_test_classes[1] = { - { - .name = "Glitter Test", +classes_struct data_test_classes[] = { + [DATA_TEST_AUTH_3D_TEST] = { + .name = "Auth 3D Test##Data Test", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = data_test_auth_3d_test_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = data_test_auth_3d_test_hide, + .input = data_test_auth_3d_test_input, + .imgui = data_test_auth_3d_test_imgui, + .render = data_test_auth_3d_test_render, + .show = data_test_auth_3d_test_show, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = data_test_auth_3d_test_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = 0, + .sub_classes_count = 0, + }, + [DATA_TEST_GLITTER_TEST] = { + .name = "Glitter Test##Data Test", +#if defined(CLOUD_DEV) + .flags = CLASSES_DISPOSE_AT_HIDE | CLASSES_IN_CONTEXT_MENU, +#else + .flags = CLASSES_SHOW_AT_STARTUP | CLASSES_DISPOSE_AT_HIDE | CLASSES_IN_CONTEXT_MENU, +#endif + .init = data_test_glitter_test_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .input = data_test_glitter_test_input, + .imgui = data_test_glitter_test_imgui, + .render = data_test_glitter_test_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = data_test_glitter_test_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = 0, + .sub_classes_count = 0, + }, + [DATA_TEST_STAGE_TEST] = { + .name = "Stage Test##Data Test", .flags = CLASSES_INIT_AT_STARTUP | CLASSES_IN_CONTEXT_MENU, - .enabled = &glitter_test_enabled, - .dispose = (void*)glitter_test_dispose, - .init = (void*)glitter_test_init, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .input = (void*)glitter_test_input, - .imgui = (void*)glitter_test_imgui, - .render = (void*)glitter_test_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = data_test_stage_test_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = data_test_stage_test_hide, + .input = data_test_stage_test_input, + .imgui = data_test_stage_test_imgui, + .render = data_test_stage_test_render, + .show = data_test_stage_test_show, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = data_test_stage_test_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, diff --git a/src/CLOUD/classes/data_test.h b/src/CLOUD/classes/data_test.h index f2920c46..68b56d59 100644 --- a/src/CLOUD/classes/data_test.h +++ b/src/CLOUD/classes/data_test.h @@ -6,7 +6,12 @@ #pragma once #include "../classes.h" -#include "data_test/glitter_test.h" -extern bool data_test_enabled; +typedef enum data_test_classes_enum { + DATA_TEST_AUTH_3D_TEST, + DATA_TEST_GLITTER_TEST, + DATA_TEST_STAGE_TEST, + DATA_TEST_MAX, +} data_test_classes_enum; + extern classes_struct data_test_classes[]; diff --git a/src/CLOUD/classes/data_test/auth_3d_test.c b/src/CLOUD/classes/data_test/auth_3d_test.c new file mode 100644 index 00000000..5ce51c9d --- /dev/null +++ b/src/CLOUD/classes/data_test/auth_3d_test.c @@ -0,0 +1,588 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "auth_3d_test.h" +#include "../../../KKdLib/io/path.h" +#include "../../../KKdLib/sort.h" +#include "../../../KKdLib/str_utils.h" +#include "../../../KKdLib/vector.h" +#include "../../../CRE/Glitter/glitter.h" +#include "../../../CRE/Glitter/effect_group.h" +#include "../../../CRE/Glitter/file_reader.h" +#include "../../../CRE/Glitter/particle_manager.h" +#include "../../../CRE/Glitter/scene.h" +#include "../../../CRE/data.h" +#include "../../../CRE/render_context.h" +#include "../../../CRE/stage.h" +#include "../../input.h" +#include "../imgui_helper.h" + +typedef struct data_test_auth_3d_test_category { + char* name; + int32_t index; + vector_int32_t uid; +} data_test_auth_3d_test_category; + +vector(data_test_auth_3d_test_category) + +typedef struct data_test_auth_3d_test { + int32_t auth_3d_category_index; + int32_t auth_3d_index; + int32_t stage_index; + + int32_t auth_3d_id; + int32_t auth_3d_uid; + bool auth_3d_load; + bool auth_3d_uid_load; + bool stage_load; + + render_context* rctx; + + auth_3d_farc farc; + float_t trans_x; + float_t trans_z; + float_t rot_y; + vector_uint32_t obj_set_id; + + vector_ptr_char stage; + vector_data_test_auth_3d_test_category category; +} data_test_auth_3d_test; + +vector_func(data_test_auth_3d_test_category) + +extern int32_t width; +extern int32_t height; +extern bool input_locked; +extern float_t frame_speed; +extern stage stage_stgtst; +extern stage stage_test_data; + +static const char* data_test_auth_3d_test_window_title = "Auth 3D Test##Data Test"; + +static void data_test_auth_3d_test_category_free(data_test_auth_3d_test_category* cat); +static void data_test_auth_3d_test_load_auth_file(data_test_auth_3d_test* auth_3d_test); + +bool data_test_auth_3d_test_init(class_data* data, render_context* rctx) { + bool ret = false; + lock_trylock(&pv_lock); + data->data = force_malloc(sizeof(data_test_auth_3d_test)); + + data_test_auth_3d_test* auth_3d_test = data->data; + if (auth_3d_test) { + auth_3d_database* auth_3d_db = &rctx->data->data_ft.auth_3d_db; + vector_auth_3d_database_category* auth_3d_db_cat = &auth_3d_db->category; + auth_3d_database_uid* uids = auth_3d_db->uid.begin; + + auth_3d_test->category = vector_empty(data_test_auth_3d_test_category); + vector_data_test_auth_3d_test_category_reserve(&auth_3d_test->category, + auth_3d_db_cat->end - auth_3d_db_cat->begin); + for (auth_3d_database_category* i = auth_3d_db_cat->begin; + i != auth_3d_db_cat->end; i++) { + data_test_auth_3d_test_category* cat + = vector_data_test_auth_3d_test_category_reserve_back(&auth_3d_test->category); + cat->name = string_data(&i->name); + cat->index = -1; + cat->uid = vector_empty(int32_t); + + vector_int32_t_reserve(&cat->uid, i->uid.end - i->uid.begin); + for (int32_t* j = i->uid.begin; j != i->uid.end; j++) { + if (!uids[*j].enabled) + continue; + + vector_int32_t_push_back(&cat->uid, &uids[*j].org_uid); + } + + if (cat->uid.end - cat->uid.begin > 0) + cat->index = 0; + } + + auth_3d_test->rctx = rctx; + + auth_3d_test->auth_3d_category_index = -1; + auth_3d_test->auth_3d_index = -1; + auth_3d_test->stage_index = -1; + + stage* stg = rctx->stage; + if (stg && !stg->modern && stg->stage) { + stage_info* info = stg->stage; + data_struct* aft_data = rctx->data; + stage_database* aft_stage_data = &aft_data->data_ft.stage_data; + + for (stage_info* i = aft_stage_data->stage.begin; i != aft_stage_data->stage.end; i++) + if (info == i) { + auth_3d_test->stage_index = (int32_t)(i - aft_stage_data->stage.begin); + break; + } + } + + auth_3d_test->auth_3d_uid = -1; + auth_3d_test->auth_3d_load = false; + auth_3d_test->auth_3d_uid_load = false; + + if (auth_3d_test->category.end - auth_3d_test->category.begin > 0) { + data_test_auth_3d_test_category* cat = &auth_3d_test->category.begin[0]; + + if (cat->uid.end - cat->uid.begin > 0) { + auth_3d_test->auth_3d_load = true; + auth_3d_test->auth_3d_uid_load = true; + auth_3d_test->auth_3d_uid = cat->uid.begin[0]; + } + + auth_3d_test->auth_3d_category_index = 0; + auth_3d_test->auth_3d_index = cat->index; + } + + stage_database* stage_data = &rctx->data->data_ft.stage_data; + + auth_3d_test->stage = vector_ptr_empty(char); + vector_ptr_char_reserve(&auth_3d_test->stage, + stage_data->stage.end - stage_data->stage.begin); + for (stage_info* i = stage_data->stage.begin; i != stage_data->stage.end; i++) + *vector_ptr_char_reserve_back(&auth_3d_test->stage) = string_data(&i->name); + + auth_3d_test->trans_x = 0.0f; + auth_3d_test->trans_z = 0.0f; + auth_3d_test->rot_y = 0.0f; + auth_3d_test->obj_set_id = vector_empty(uint32_t); + } + ret = true; + lock_unlock(&pv_lock); + return ret; +} + +bool data_test_auth_3d_test_hide(class_data* data) { + data_test_auth_3d_test* auth_3d_test = data->data; + if (!auth_3d_test) + return true; + + lock_data_free(&stage_data_lock, data_test_auth_3d_test_hide); + + render_context* rctx = auth_3d_test->rctx; + + for (uint32_t* i = auth_3d_test->obj_set_id.begin; + i != auth_3d_test->obj_set_id.end; i++) + object_storage_delete_object_set(*i); + vector_uint32_t_free(&auth_3d_test->obj_set_id, 0); + + auth_3d_farc_free(&auth_3d_test->farc); + + auth_3d_test->auth_3d_category_index = -1; + auth_3d_test->auth_3d_index = -1; + auth_3d_test->auth_3d_uid = -1; + + data->flags &= ~CLASS_HIDE; + data->flags |= CLASS_HIDDEN; + return true; +} + +void data_test_auth_3d_test_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); + + float_t w = min((float_t)width, 280.0f); + float_t h = min((float_t)height, 316.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + ImGuiWindowFlags window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(data_test_auth_3d_test_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + data_test_auth_3d_test* auth_3d_test = data->data; + if (!auth_3d_test) + goto End; + + vector_data_test_auth_3d_test_category* auth_3d_db_cat = &auth_3d_test->category; + + render_context* rctx = auth_3d_test->rctx; + data_struct* aft_data = rctx->data; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + auth_3d_database_uid* uids = aft_auth_3d_db->uid.begin; + + int32_t auth_3d_category_index = auth_3d_test->auth_3d_category_index; + + imguiGetContentRegionAvailSetNextItemWidth(); + if (igBeginCombo("##Auth 3D Category Index", auth_3d_category_index > -1 + ? auth_3d_db_cat->begin[auth_3d_category_index].name : "", 0)) { + for (data_test_auth_3d_test_category* i = auth_3d_db_cat->begin; i != auth_3d_db_cat->end; i++) { + int32_t auth_3d_category_idx = (int32_t)(i - auth_3d_db_cat->begin); + + igPushID_Ptr(i); + if (igSelectable_Bool(i->name, + auth_3d_category_index == auth_3d_category_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && auth_3d_category_index != auth_3d_category_idx)) { + auth_3d_test->auth_3d_category_index = 0; + auth_3d_category_index = auth_3d_category_idx; + } + igPopID(); + + if (auth_3d_category_index == auth_3d_category_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= true; + igEndCombo(); + } + + if (auth_3d_category_index != auth_3d_test->auth_3d_category_index) { + data_test_auth_3d_test_category* cat = &auth_3d_db_cat->begin[auth_3d_category_index]; + + if (cat->uid.end - cat->uid.begin > 0) { + auth_3d_test->auth_3d_load = true; + auth_3d_test->auth_3d_uid_load = true; + auth_3d_test->auth_3d_uid = cat->uid.begin[cat->index]; + } + else { + auth_3d_test->auth_3d_load = false; + auth_3d_test->auth_3d_uid_load = false; + auth_3d_test->auth_3d_uid = -1; + } + auth_3d_test->auth_3d_category_index = auth_3d_category_index; + auth_3d_test->auth_3d_index = cat->index; + } + + int32_t auth_3d_index = auth_3d_test->auth_3d_index; + + igText(" ID "); + + imguiGetContentRegionAvailSetNextItemWidth(); + bool auth_3d_category_found = false; + for (data_test_auth_3d_test_category* i = auth_3d_db_cat->begin; i != auth_3d_db_cat->end; i++) { + if (auth_3d_category_index != i - auth_3d_db_cat->begin) + continue; + + if (igBeginCombo("##Auth 3D Index", auth_3d_index > -1 + ? string_data(&uids[i->uid.begin[auth_3d_index]].name) : "", 0)) { + for (int32_t* j = i->uid.begin; j != i->uid.end; j++) { + int32_t auth_3d_idx = (int32_t)(j - i->uid.begin); + + igPushID_Ptr(j); + if (igSelectable_Bool(string_data(&uids[*j].name), + auth_3d_index == auth_3d_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && auth_3d_index != auth_3d_idx)) { + auth_3d_test->auth_3d_index = -1; + auth_3d_index = auth_3d_idx; + } + igPopID(); + + if (auth_3d_index == auth_3d_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= true; + igEndCombo(); + } + + if (auth_3d_index != auth_3d_test->auth_3d_index) { + i->index = auth_3d_index; + auth_3d_test->auth_3d_uid_load = true; + auth_3d_test->auth_3d_uid = i->uid.begin[auth_3d_index]; + auth_3d_test->auth_3d_index = auth_3d_index; + } + auth_3d_category_found = true; + break; + } + + if (!auth_3d_category_found && igBeginCombo("##Auth 3D Index", "", 0)) { + data->imgui_focus |= true; + igEndCombo(); + } + + auth_3d* auth = auth_3d_data_get_auth_3d(auth_3d_test->auth_3d_id); + if (auth) { + float_t frame = auth->frame; + float_t last_frame = auth->last_frame; + igText("frame[ 0,%4.0f)", last_frame); + + imguiGetContentRegionAvailSetNextItemWidth(); + igSliderFloatButton("##frame slider", &frame, 1.0f, + 0.0f, last_frame, "%5.0f", 0); + if (igIsItemActivated()) + auth->paused = true; + + if (igButton("|<<", (ImVec2) { 32.0, 0.0f })) + frame = 0.0f; + igSameLine(0.0f, -1.0f); + if (igButton(auth->paused ? " > " : "||", (ImVec2) { 32.0, 0.0f })) + auth->paused = auth->paused ? false : true; + igSameLine(0.0f, -1.0f); + if (igButton(">>|", (ImVec2) { 32.0, 0.0f })) + frame = last_frame; + igSameLine(0.0f, -1.0f); + igCheckbox("repeat", &auth->repeat); + + if (igCheckbox("Left Right Reverse", &auth->left_right_reverse)) + frame = 0.0f; + + if (frame != auth->frame) { + auth->frame_changed = true; + auth->set_frame = frame; + } + } + else { + float_t frame = 0.0f; + bool repeat = true; + bool left_right_reverse = false; + + igText("frame[ 0,%4.0f)", 0.0f); + imguiGetContentRegionAvailSetNextItemWidth(); + igSliderFloatButton("##frame slider", &frame, 1.0f, + 0.0f, 0.0f, "%5.0f", 0); + + igPushItemFlag(ImGuiItemFlags_Disabled, true); + igButton("|<<", (ImVec2) { 32.0, 0.0f }); + igSameLine(0.0f, -1.0f); + igButton(" > ", (ImVec2) { 32.0, 0.0f }); + igSameLine(0.0f, -1.0f); + igButton(">>|", (ImVec2) { 32.0, 0.0f }); + igSameLine(0.0f, -1.0f); + igCheckbox("repeat", &repeat); + igCheckbox("Left Right Reverse", &left_right_reverse); + igPopItemFlag(); + } + + imguiColumnSliderFloat("transX", &auth_3d_test->trans_x, 0.1f, -5.0f, 5.0f, "%.2f", 0, true); + imguiColumnSliderFloat("transZ", &auth_3d_test->trans_z, 0.1f, -5.0f, 5.0f, "%.2f", 0, true); + imguiColumnSliderFloat("rotY", &auth_3d_test->rot_y, 1.0f, -360.0f, 360.0f, "%.0f", 0, true); + + if (igButton("cam reset", (ImVec2) { 72.0f, 0.0f }) + && auth_3d_test->rctx && auth_3d_test->rctx->camera) { + camera* cam = auth_3d_test->rctx->camera; + camera_set_fov(cam, 32.2673416137695); + camera_set_roll(cam, 0.0); + camera_set_interest(cam, &((vec3) { 0.0, 1.0f, 0.0f })); + camera_set_view_point(cam, &((vec3) { 0.0, 1.0f, 6.0f })); + } + + igSeparator(); + + imguiColumnSliderFloat("Frame Speed", &frame_speed, 0.01f, 0.0f, 3.0f, "%.2f", 0, true); + + data->imgui_focus |= igIsWindowFocused(0); + igEnd(); + + float_t x = w; + float_t y = 0.0f; + + w = min((float_t)width, 200.0f); + h = min((float_t)height, 100.0f); + + igSetNextWindowPos((ImVec2) { x, y }, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + window_flags |= ImGuiWindowFlags_NoCollapse; + + if (igBegin("A3D STAGE", 0, window_flags)) { + stage* stg = auth_3d_test->rctx->stage; + if (!stg) + if (stage_test_data.stage) + stg = &stage_test_data; + else + stg = &stage_stgtst; + + igCheckbox("stage", &stg->display); + igCheckbox("stg auth", &stg->effects); + + int32_t stage_index = auth_3d_test->stage_index; + + ImVec2 t; + igGetContentRegionAvail(&t); + igSetNextItemWidth(t.x); + if (igBeginCombo("##Stage Index", stage_index > -1 + ? auth_3d_test->stage.begin[stage_index] : "", 0)) { + for (char** i = auth_3d_test->stage.begin; i != auth_3d_test->stage.end; i++) { + int32_t stage_idx = (int32_t)(i - auth_3d_test->stage.begin); + + igPushID_Ptr(i); + if (igSelectable_Bool((char*)*i, stage_index == stage_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && stage_index != stage_idx)) { + auth_3d_test->stage_index = -1; + stage_index = stage_idx; + } + igPopID(); + + if (stage_index == stage_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (stage_index != auth_3d_test->stage_index) { + auth_3d_test->stage_load = true; + auth_3d_test->stage_index = stage_index; + } + + data->imgui_focus |= igIsWindowFocused(0); + } + +End: + igEnd(); +} + +void data_test_auth_3d_test_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void data_test_auth_3d_test_render(class_data* data) { + data_test_auth_3d_test* auth_3d_test = data->data; + if (!auth_3d_test) + return; + + if (auth_3d_test->auth_3d_uid_load) { + render_context* rctx = auth_3d_test->rctx; + + data_struct* aft_data = rctx->data; + stage_database* aft_stage_data = &aft_data->data_ft.stage_data; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + auth_3d_database_uid* uids = aft_auth_3d_db->uid.begin; + char* uid_name = string_data(&uids[auth_3d_test->auth_3d_uid].name); + + string name = string_empty; + char* s = 0; + if (s = strchr(uid_name, '_')) + string_init_length(&name, uid_name, s - uid_name); + else + string_init(&name, uid_name); + + for (stage_info* i = aft_stage_data->stage.begin; i != aft_stage_data->stage.end; i++) + if (string_compare(&name, &i->name)) { + int32_t stage_index = (int32_t)(i - aft_stage_data->stage.begin); + if (stage_index != auth_3d_test->stage_index) + auth_3d_test->stage_load = true; + auth_3d_test->stage_index = stage_index; + break; + } + string_free(&name); + auth_3d_data_unload_id(auth_3d_test->auth_3d_id, auth_3d_test->rctx); + auth_3d_test->auth_3d_id = -1; + } + + if (auth_3d_test->auth_3d_load) { + render_context* rctx = auth_3d_test->rctx; + data_test_auth_3d_test_category* cat + = &auth_3d_test->category.begin[auth_3d_test->auth_3d_category_index]; + + auth_3d_farc_free(&auth_3d_test->farc); + + data_struct* aft_data = rctx->data; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + + auth_3d_farc_init(&auth_3d_test->farc); + auth_3d_farc_load(&auth_3d_test->farc, aft_data, cat->name, aft_obj_db); + auth_3d_test->auth_3d_load = false; + } + + if (auth_3d_test->auth_3d_uid_load) { + data_test_auth_3d_test_load_auth_file(auth_3d_test); + auth_3d_test->auth_3d_uid_load = false; + } + + if (auth_3d_test->stage_load) { + render_context* rctx = auth_3d_test->rctx; + + data_struct* aft_data = rctx->data; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + stage_database* aft_stage_data = &aft_data->data_ft.stage_data; + + stage_free(&stage_test_data, rctx); + stage_init(&stage_test_data); + stage_load(&stage_test_data, aft_data, aft_auth_3d_db, + aft_obj_db, aft_tex_db, aft_stage_data, + (char*)auth_3d_test->stage.begin[auth_3d_test->stage_index], rctx); + stage_set(&stage_test_data, rctx); + auth_3d_test->stage_load = false; + } + + float_t max_frame = 0.0f; + auth_3d* auth = auth_3d_data_get_auth_3d(auth_3d_test->auth_3d_id); + if (auth) { + mat4 mat; + mat4_translate(auth_3d_test->trans_x, 0.0f, auth_3d_test->trans_z, &mat); + mat4_rotate_y_mult(&mat, auth_3d_test->rot_y * DEG_TO_RAD_FLOAT, &mat); + auth_3d_get_value(auth, &mat, get_delta_frame()); + + auth_3d_data_set(auth, &mat, auth_3d_test->rctx); + } +} + +bool data_test_auth_3d_test_show(class_data* data) { + data_test_auth_3d_test* auth_3d_test = data->data; + if (!auth_3d_test) + return false; + + bool ret = false; + lock_trylock(&pv_lock); + if (!lock_data_init(&stage_data_lock, &data->lock, data, data_test_auth_3d_test_hide)) + goto End; + + ret = true; + +End: + lock_unlock(&pv_lock); + return ret; +} + +bool data_test_auth_3d_test_dispose(class_data* data) { + data_test_auth_3d_test* auth_3d_test = data->data; + if (auth_3d_test) { + memset(auth_3d_test->stage.begin, 0, + sizeof(char*) * (auth_3d_test->stage.end - auth_3d_test->stage.begin)); + + vector_data_test_auth_3d_test_category_free(&auth_3d_test->category, + data_test_auth_3d_test_category_free); + vector_ptr_char_free(&auth_3d_test->stage, 0); + } + free(data->data); + return true; +} + +static void data_test_auth_3d_test_category_free(data_test_auth_3d_test_category* cat) { + vector_int32_t_free(&cat->uid, 0); +} + +static void data_test_auth_3d_test_load_auth_file(data_test_auth_3d_test* auth_3d_test) { + render_context* rctx = auth_3d_test->rctx; + data_struct* aft_data = rctx->data; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + auth_3d_database_uid* uids = aft_auth_3d_db->uid.begin; + char* uid_name = string_data(&uids[auth_3d_test->auth_3d_uid].name); + + auth_3d_test->auth_3d_id = auth_3d_data_load_uid(auth_3d_test->auth_3d_uid, aft_auth_3d_db); + auth_3d* auth = auth_3d_data_get_auth_3d(auth_3d_test->auth_3d_id); + if (!auth) + return; + + string file; + string_init(&file, uid_name); + string_add_length(&file, ".a3da", 5); + auth_3d_load_from_farc(auth, &auth_3d_test->farc.auth_3d_farc, string_data(&file), aft_obj_db, aft_tex_db); + string_free(&file); + + auth_3d_test->trans_x = 0.0f; + auth_3d_test->trans_z = 0.0f; + auth_3d_test->rot_y = 0.0f; +} diff --git a/src/CLOUD/classes/data_test/auth_3d_test.h b/src/CLOUD/classes/data_test/auth_3d_test.h new file mode 100644 index 00000000..65b5c431 --- /dev/null +++ b/src/CLOUD/classes/data_test/auth_3d_test.h @@ -0,0 +1,17 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool data_test_auth_3d_test_init(class_data* data, render_context* rctx); +extern bool data_test_auth_3d_test_hide(class_data* data); +extern void data_test_auth_3d_test_imgui(class_data* data); +extern void data_test_auth_3d_test_input(class_data* data); +extern void data_test_auth_3d_test_render(class_data* data); +extern bool data_test_auth_3d_test_show(class_data* data); +extern bool data_test_auth_3d_test_dispose(class_data* data); diff --git a/src/CLOUD/classes/data_test/glitter_test.c b/src/CLOUD/classes/data_test/glitter_test.c index a621b29f..5ff0f884 100644 --- a/src/CLOUD/classes/data_test/glitter_test.c +++ b/src/CLOUD/classes/data_test/glitter_test.c @@ -4,288 +4,321 @@ */ #include "glitter_test.h" -#include "../../../KKdLib/io_path.h" +#include "../../../KKdLib/io/path.h" #include "../../../KKdLib/str_utils.h" +#include "../../../KKdLib/vector.h" #include "../../../CRE/Glitter/glitter.h" #include "../../../CRE/Glitter/effect_group.h" #include "../../../CRE/Glitter/file_reader.h" #include "../../../CRE/Glitter/particle_manager.h" #include "../../../CRE/Glitter/scene.h" +#include "../../../CRE/data.h" +#include "../../../CRE/render_context.h" #include "../../input.h" +#include "../data_test.h" #include "../imgui_helper.h" -typedef struct glitter_test_struct { - bool dispose; - bool disposed; - bool imgui_focus; +typedef struct data_test_glitter_test_struct { bool input_play; bool input_stop; bool input_auto; bool input_pause; - float_t frame_counter; + int32_t frame_counter; + double_t delta_frame; + char* path; char* file; - vector_string files; - lock lock; -} glitter_test_struct; + vector_data_struct_file files; + + bool stage_test; + render_context* rctx; +} data_test_glitter_test_struct; extern int32_t width; extern int32_t height; extern bool input_reset; extern bool input_locked; -extern float_t frame_speed; -extern bool grid_3d; +extern bool draw_grid_3d; -extern GPM; +static const char* data_test_glitter_test_window_title = "Glitter Test##Data Test"; -const char* glitter_test_window_title = "Glitter"; +static data_test_glitter_test_struct data_test_glitter_test; -#if defined(CLOUD_DEV) -bool glitter_test_enabled = false; -#else -bool glitter_test_enabled = true; -#endif -static glitter_test_struct glitter_test; +bool data_test_glitter_test_init(class_data* data, render_context* rctx) { + if (!lock_data_init(&glitter_data_lock, &data->lock, data, data_test_glitter_test_dispose)) + return false; -void glitter_test_dispose() { - lock_lock(&glitter_test.lock); - vector_ptr_glitter_scene_free(&GPM_VAL->scenes, glitter_scene_dispose); - vector_ptr_glitter_effect_group_free(&GPM_VAL->effect_groups, glitter_effect_group_dispose); - - vector_string_free(&glitter_test.files); - glitter_test_enabled = false; - glitter_test.file = 0; - glitter_test.imgui_focus = false; - glitter_test.input_play = false; - glitter_test.input_stop = false; - glitter_test.input_auto = false; - glitter_test.input_pause = false; - glitter_test.frame_counter = 0.0f; - glitter_test.dispose = false; - glitter_test.disposed = true; - lock_unlock(&glitter_test.lock); - lock_free(&glitter_test.lock); -} - -void glitter_test_init() { - bool dispose = false; - lock_lock(&glitter_test.lock); - dispose = glitter_test_enabled || glitter_test.dispose; - lock_unlock(&glitter_test.lock); - - if (dispose) - glitter_test_dispose(); - - lock_init(&glitter_test.lock); - lock_lock(&glitter_test.lock); - vector_string_free(&glitter_test.files); - path_get_files(&glitter_test.files, "rom\\particle"); - for (string* i = glitter_test.files.begin; i != glitter_test.files.end;) - if (str_utils_check_ends_with(string_data(i), ".farc")) { - string s; - char* temp = str_utils_get_without_extension(string_data(i)); - string_init(&s, temp); - string_free(i); - vector_string_erase(&glitter_test.files, i - glitter_test.files.begin); - vector_string_insert(&glitter_test.files, i - glitter_test.files.begin, &s); - free(temp); - i++; - } - else { - string_free(i); - vector_string_erase(&glitter_test.files, i - glitter_test.files.begin); - } - - glitter_test.file = glitter_test.files.end - glitter_test.files.begin > 0 - ? string_data(&glitter_test.files.begin[0]) : 0; + lock_trylock(&pv_lock); + data->data = force_malloc(sizeof(data_test_glitter_test_struct)); LARGE_INTEGER time; QueryPerformanceCounter(&time); - GPM_VAL->counter = (uint32_t)(time.LowPart * 0x0CAD3078LL); - glitter_test_enabled = true; - GPM_VAL->emission = 1.0f; - GPM_VAL->draw_all = false; - GPM_VAL->draw_all_mesh = false; - grid_3d = false; - lock_unlock(&glitter_test.lock); + GPM_VAL->counter = (uint32_t)(time.LowPart * 0x0CAD3078ULL); + + data_test_glitter_test_struct* glt_test = data->data; + if (glt_test) { + data_struct_get_directory_files(&data_list[DATA_AFT], "rom\\particle\\", &glt_test->files); + for (data_struct_file* i = glt_test->files.begin; i != glt_test->files.end;) + if (str_utils_check_ends_with(string_data(&i->name), ".farc")) { + char* temp = str_utils_get_without_extension(string_data(&i->name)); + string_free(&i->name); + string_init(&i->name, temp); + free(temp); + i++; + } + else + vector_data_struct_file_erase(&glt_test->files, + i - glt_test->files.begin, data_struct_file_free); + + glt_test->path = glt_test->files.end - glt_test->files.begin > 0 + ? string_data(&glt_test->files.begin[0].path) : 0; + glt_test->file = glt_test->files.end - glt_test->files.begin > 0 + ? string_data(&glt_test->files.begin[0].name) : 0; + glt_test->stage_test = false; + glt_test->rctx = rctx; + GPM_VAL->emission = 1.0f; + GPM_VAL->draw_all = false; + GPM_VAL->draw_all_mesh = false; + draw_grid_3d = false; + } + lock_unlock(&pv_lock); + return true; } -void glitter_test_imgui() { - bool ret = false; - lock_lock(&glitter_test.lock); - if (!glitter_test_enabled) { - if (!glitter_test.disposed) - glitter_test.dispose = true; - ret = true; - } - else if (glitter_test.disposed) - glitter_test.disposed = false; - lock_unlock(&glitter_test.lock); +void data_test_glitter_test_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); - if (ret) - return; - - lock_lock(&glitter_test.lock); - float_t w = min((float_t)width / 4.0f, 360.0f); - float_t h = min((float_t)height, 348.0f); + float_t w = min((float_t)width, 320.0f); + float_t h = min((float_t)height, 256.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); - igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); ImGuiWindowFlags window_flags = 0; window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - glitter_test.imgui_focus = false; - if (!igBegin(glitter_test_window_title, &glitter_test_enabled, window_flags)) { - glitter_test.dispose = true; + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(data_test_glitter_test_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; goto End; } + else if (collapsed) + goto End; + + data_test_glitter_test_struct* glt_test = data->data; + if (!glt_test) + goto End; int32_t file_index = -1; - if (glitter_test.file) - for (string* i = glitter_test.files.begin; i != glitter_test.files.end; i++) - if (!strcmp(string_data(i), glitter_test.file)) { - file_index = (int32_t)(i - glitter_test.files.begin); + if (glt_test->file) + for (data_struct_file* i = glt_test->files.begin; i != glt_test->files.end; i++) + if (!str_utils_compare(string_data(&i->name), glt_test->file)) { + file_index = (int32_t)(i - glt_test->files.begin); break; } int32_t file_index_old = file_index; - imguiColumnComboBoxString("File", glitter_test.files.begin, - glitter_test.files.end - glitter_test.files.begin, - &file_index, 0, false, &glitter_test.imgui_focus); + imguiColumnComboBoxConfigFile("File", glt_test->files.begin, + glt_test->files.end - glt_test->files.begin, + &file_index, 0, false, &data->imgui_focus); if (file_index != file_index_old) { - glitter_test.file = string_data(&glitter_test.files.begin[file_index]); - glitter_test.input_stop = true; + glt_test->path = string_data(&glt_test->files.begin[file_index].path); + glt_test->file = string_data(&glt_test->files.begin[file_index].name); + glt_test->input_stop = true; } if (imguiButton("Reset Camera (R)", ImVec2_Empty)) input_reset = true; - if (imguiButton("Play (F)", ImVec2_Empty) || igIsKeyPressed(GLFW_KEY_F, true)) - glitter_test.input_play = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Play (F)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_F, true)) + glt_test->input_play = true; - if (imguiButton("Stop (V)", ImVec2_Empty) || igIsKeyPressed(GLFW_KEY_V, true)) - glitter_test.input_stop = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Stop (V)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_V, true)) + glt_test->input_stop = true; - imguiCheckbox("Auto (T)", &glitter_test.input_auto); + imguiCheckbox("Auto (T)", &glt_test->input_auto); if (igIsKeyPressed(GLFW_KEY_T, true)) - glitter_test.input_auto ^= true; + glt_test->input_auto ^= true; - imguiCheckbox("Pause (G)", &glitter_test.input_pause); + imguiCheckbox("Pause (G)", &glt_test->input_pause); if (igIsKeyPressed(GLFW_KEY_G, true)) - glitter_test.input_pause ^= true; + glt_test->input_pause ^= true; igSeparator(); - size_t ctrl; - size_t disp; - float_t frame; - int32_t life_time; - - frame = 0.0f; - life_time = 0; - glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); - igText("%.0f - %.0f/%d", glitter_test.frame_counter, frame, life_time); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - igText(" Quad: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - igText("Locus: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); - igText(" Line: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); - igText(" Mesh: ctrl%lld, disp%lld", ctrl, disp); + imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 0.01f, 1.0f, 2.0f, "%.2f", 0, true); igSeparator(); - imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 1.0f, 2.0f, "%.2f", 0); - imguiColumnSliderFloat("Frame Speed", &frame_speed, 0.0f, 3.0f, "%.2f", 0); + imguiCheckbox("Show Grid", &draw_grid_3d); - igSeparator(); + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Stage", (ImVec2) { w, 0.0f })) + glt_test->stage_test = true; - imguiCheckbox("Grid", &grid_3d); + data->imgui_focus |= igIsWindowFocused(0); + igEnd(); - glitter_test.imgui_focus |= igIsWindowFocused(0); + float_t win_x = min((float_t)width, 240.0f); + float_t win_y = min((float_t)height, 96.0f); + + float_t x = 0.0f; + float_t y = (float_t)height - win_y; + w = win_x; + h = win_y; + + igSetNextWindowPos((ImVec2) { x, y }, ImGuiCond_Always, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + window_flags = 0; + window_flags |= ImGuiWindowFlags_NoTitleBar; + window_flags |= ImGuiWindowFlags_NoResize; + window_flags |= ImGuiWindowFlags_NoScrollbar; + window_flags |= ImGuiWindowFlags_NoCollapse; + window_flags |= ImGuiWindowFlags_NoMouseInputs; + window_flags |= ImGuiWindowFlags_NoNavInputs; + window_flags |= ImGuiWindowFlags_NoNavFocus; + + igPushStyleColor_U32(ImGuiCol_Border, 0); + igPushStyleColor_U32(ImGuiCol_WindowBg, 0); + if (igBegin("Glitter Test Sub##Data Test", 0, window_flags)) { + size_t ctrl; + size_t disp; + float_t frame; + int32_t life_time; + + frame = 0.0f; + life_time = 0; + glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); + igText("%d - %.0f/%d", glt_test->frame_counter, frame, life_time); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + igText(" Quad: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + igText("Locus: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); + igText(" Line: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); + igText(" Mesh: ctrl%lld, disp%lld", ctrl, disp); + } + igPopStyleColor(2); End: igEnd(); - lock_unlock(&glitter_test.lock); } -void glitter_test_input() { - bool ret = false; - lock_lock(&glitter_test.lock); - if (!glitter_test_enabled) - ret = true; - lock_unlock(&glitter_test.lock); - - if (ret) +void data_test_glitter_test_input(class_data* data) { + data_test_glitter_test_struct* glt_test = data->data; + if (!glt_test) return; - input_locked |= glitter_test.imgui_focus; + input_locked |= data->imgui_focus; } -void glitter_test_render() { - bool dispose = false; - bool ret = false; - lock_lock(&glitter_test.lock); - if (glitter_test.dispose) { - dispose = true; - ret = true; +void data_test_glitter_test_render(class_data* data) { + data_test_glitter_test_struct* glt_test = data->data; + if (!glt_test) + return; + + if (!glt_test->input_pause) { } - else if (!glitter_test_enabled) - ret = true; - lock_unlock(&glitter_test.lock); - - if (dispose) - glitter_test_dispose(); - - if (ret) - return; - - lock_lock(&glitter_test.lock); - if (!glitter_test.input_pause) { + if (!glt_test->input_pause) { if (GPM_VAL->scenes.end != GPM_VAL->scenes.begin) - glitter_test.frame_counter += get_frame_speed(); + glt_test->delta_frame += get_delta_frame(); - glitter_particle_manager_update_scene(GPM_VAL); + int32_t delta_frame = (int32_t)glt_test->delta_frame; + glt_test->frame_counter += delta_frame; + glt_test->delta_frame -= (double_t)delta_frame; + + glitter_particle_manager_update_scene(GPM_VAL, (float_t)delta_frame); } - if (glitter_test.file) { - if (glitter_test.input_play || glitter_test.input_stop) { + if (glt_test->file) { + if (glt_test->input_play || glt_test->input_stop) { glitter_particle_manager_free_scenes(GPM_VAL); - glitter_test.frame_counter = 0.0f; + glt_test->frame_counter = 0; } - uint64_t hash = hash_utf8_fnv1a64(glitter_test.file); - if (glitter_test.input_auto && !glitter_particle_manager_check_scene(GPM_VAL, hash)) { + uint64_t hash = hash_utf8_fnv1a64m(glt_test->file); + if (glt_test->input_auto && !glitter_particle_manager_check_scene(GPM_VAL, hash)) { if (glitter_particle_manager_check_effect_group(GPM_VAL, hash)) goto load; else goto reset; } - else if (glitter_test.input_play && !glitter_particle_manager_test_load_scene(GPM_VAL, hash, true)) { + else if (glt_test->input_play && !glitter_particle_manager_test_load_scene(GPM_VAL, hash, true)) { reset: glitter_particle_manager_free_scenes(GPM_VAL); glitter_particle_manager_free_effect_groups(GPM_VAL); - glitter_file_reader* fr = glitter_file_reader_init(GLITTER_AFT, 0, glitter_test.file, -1.0f); + glitter_file_reader* fr = glitter_file_reader_init(GLITTER_FT, + glt_test->path, glt_test->file, -1.0f); vector_ptr_glitter_file_reader_push_back(&GPM_VAL->file_readers, &fr); glitter_particle_manager_update_file_reader(GPM_VAL); load: - glitter_test.frame_counter = 0.0f; + glt_test->frame_counter = 0; glitter_particle_manager_test_load_scene(GPM_VAL, hash, true); } - glitter_test.input_play = false; - glitter_test.input_stop = false; + glt_test->input_play = false; + glt_test->input_stop = false; + } + + if (glt_test->stage_test) { + classes_struct* c = &data_test_classes[DATA_TEST_STAGE_TEST]; + if (~c->data.flags & CLASS_INIT) { + lock_init(&c->data.lock); + if (lock_check_init(&c->data.lock) && c->init) { + lock_lock(&c->data.lock); + c->init(&c->data, glt_test->rctx); + lock_unlock(&c->data.lock); + } + } + + if (lock_check_init(&c->data.lock)) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT && ((c->show && c->show(&c->data)) || !c->show)) + c->data.flags &= ~(CLASS_HIDE | CLASS_HIDDEN); + lock_unlock(&c->data.lock); + } + glt_test->stage_test = false; } - lock_unlock(&glitter_test.lock); +} + +bool data_test_glitter_test_dispose(class_data* data) { + vector_ptr_glitter_scene_free(&GPM_VAL->scenes, glitter_scene_dispose); + vector_ptr_glitter_effect_group_free(&GPM_VAL->effect_groups, glitter_effect_group_dispose); + + lock_data_free(&glitter_data_lock, data_test_glitter_test_dispose); + + data_test_glitter_test_struct* glt_test = data->data; + + draw_grid_3d = false; + if (glt_test) { + vector_data_struct_file_free(&glt_test->files, data_struct_file_free); + glt_test->path = 0; + glt_test->file = 0; + glt_test->input_play = false; + glt_test->input_stop = false; + glt_test->input_auto = false; + glt_test->input_pause = false; + glt_test->frame_counter = 0; + } + free(data->data); + + data->flags = CLASS_HIDDEN | CLASS_DISPOSED; + data->imgui_focus = false; + return true; } diff --git a/src/CLOUD/classes/data_test/glitter_test.h b/src/CLOUD/classes/data_test/glitter_test.h index 724cc496..2fe4c5df 100644 --- a/src/CLOUD/classes/data_test/glitter_test.h +++ b/src/CLOUD/classes/data_test/glitter_test.h @@ -6,12 +6,10 @@ #pragma once #include "../../../KKdLib/default.h" -#include "../../../KKdLib/vector.h" +#include "../../classes.h" -extern bool glitter_test_enabled; - -extern void glitter_test_dispose(); -extern void glitter_test_init(); -extern void glitter_test_imgui(); -extern void glitter_test_input(); -extern void glitter_test_render(); +extern bool data_test_glitter_test_init(class_data* data, render_context* rctx); +extern void data_test_glitter_test_imgui(class_data* data); +extern void data_test_glitter_test_input(class_data* data); +extern void data_test_glitter_test_render(class_data* data); +extern bool data_test_glitter_test_dispose(class_data* data); diff --git a/src/CLOUD/classes/data_test/stage_test.c b/src/CLOUD/classes/data_test/stage_test.c new file mode 100644 index 00000000..98d055c8 --- /dev/null +++ b/src/CLOUD/classes/data_test/stage_test.c @@ -0,0 +1,471 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "stage_test.h" +#include "../../../KKdLib/io/path.h" +#include "../../../KKdLib/str_utils.h" +#include "../../../KKdLib/vector.h" +#include "../../../CRE/Glitter/glitter.h" +#include "../../../CRE/Glitter/effect_group.h" +#include "../../../CRE/Glitter/file_reader.h" +#include "../../../CRE/Glitter/particle_manager.h" +#include "../../../CRE/Glitter/scene.h" +#include "../../../CRE/data.h" +#include "../../../CRE/render_context.h" +#include "../../../CRE/stage.h" +#include "../../input.h" +#include "../imgui_helper.h" + +typedef struct data_test_stage_test_stage_pv { + int32_t pv_id; + vector_string stage; +} data_test_stage_test_stage_pv; + +vector(data_test_stage_test_stage_pv) + +typedef struct data_test_stage_test { + int32_t pv_id; + int32_t pv_index; + int32_t ns_index; + int32_t other_index; + int32_t stage_index; + + char* stage_name; + bool stage_load; + + render_context* rctx; + + vector_data_test_stage_test_stage_pv stage_pv; + vector_string stage_ns; + vector_string stage_other; +} data_test_stage_test; + +vector_func(data_test_stage_test_stage_pv) + +extern int32_t width; +extern int32_t height; +extern bool input_locked; +extern stage stage_stgtst; +extern stage stage_test_data; + +static const char* data_test_stage_test_window_title = "Stage Test##Data Test"; + +static void data_test_stage_test_stage_pv_free(data_test_stage_test_stage_pv* pv); + +bool data_test_stage_test_init(class_data* data, render_context* rctx) { + data->data = force_malloc(sizeof(data_test_stage_test)); + + data_test_stage_test* stage_test = data->data; + if (stage_test) { + vector_stage_info* stg_info = &rctx->data->data_ft.stage_data.stage; + + stage_test->pv_id = -1; + stage_test->pv_index = -1; + stage_test->ns_index = -1; + stage_test->other_index = -1; + stage_test->stage_index = -1; + + stage_test->stage_name = 0; + stage_test->stage_load = false; + + stage_test->rctx = rctx; + + vector_data_test_stage_test_stage_pv* stage_pv = &stage_test->stage_pv; + vector_string* stage_ns = &stage_test->stage_ns; + vector_string* stage_other = &stage_test->stage_other; + + *stage_pv = vector_empty(data_test_stage_test_stage_pv); + *stage_ns = vector_empty(string); + *stage_other = vector_empty(string); + + for (stage_info* i = stg_info->begin; i != stg_info->end; i++) { + bool stgpv = false; + bool stgd2pv = false; + bool stgns = false; + bool stgd2ns = false; + if (i->name.length >= 8 && !memcmp(string_data(&i->name), "STGPV", 5)) + stgpv = true; + else if (i->name.length >= 10 && !memcmp(string_data(&i->name), "STGD2PV", 7)) + stgd2pv = true; + else if (i->name.length >= 8 && !memcmp(string_data(&i->name), "STGNS", 5)) + stgns = true; + else if (i->name.length >= 10 && !memcmp(string_data(&i->name), "STGD2NS", 7)) + stgd2ns = true; + + if (stgpv || stgd2pv) { + int32_t pv_id = 0; + int32_t ret; + if (stgpv) + ret = sscanf_s(string_data(&i->name) + 5, "%03d", &pv_id); + else + ret = sscanf_s(string_data(&i->name) + 8, "%03d", &pv_id); + + if (ret != 1) + continue; + + data_test_stage_test_stage_pv* stg_pv = 0; + for (stg_pv = stage_pv->begin; stg_pv != stage_pv->end; stg_pv++) + if (pv_id == stg_pv->pv_id) + break; + + if (stg_pv == stage_pv->end) { + stg_pv = vector_data_test_stage_test_stage_pv_reserve_back(stage_pv); + stg_pv->pv_id = pv_id; + stg_pv->stage = vector_empty(string); + } + + string stg; + string_copy(&i->name, &stg); + vector_string_push_back(&stg_pv->stage, &stg); + } + else if (stgns || stgd2ns) { + int32_t ns_id = 0; + int32_t ret; + if (stgns) + ret = sscanf_s(string_data(&i->name) + 5, "%03d", &ns_id); + else + ret = sscanf_s(string_data(&i->name) + 8, "%03d", &ns_id); + + if (ret != 1) + continue; + + string stg; + string_copy(&i->name, &stg); + vector_string_push_back(stage_ns, &stg); + } + else { + string stg; + string_copy(&i->name, &stg); + vector_string_push_back(stage_other, &stg); + } + } + + for (data_test_stage_test_stage_pv* i = stage_pv->begin; i != &stage_pv->end[-1]; i++) + for (data_test_stage_test_stage_pv* j = i + 1; j != stage_pv->end; j++) + if (i->pv_id > j->pv_id) { + data_test_stage_test_stage_pv temp = *i; + *i = *j; + *j = temp; + } + + if (stage_pv->end - stage_pv->begin > 0) + stage_test->pv_id = stage_pv->begin[0].pv_id; + + stage* stg = rctx->stage; + if ((stg && !stg->modern && stg->stage) || !stg) { + if (!stg) { + stg = &stage_stgtst; + stage_set(&stage_stgtst, rctx); + } + + stage_info* info = stg->stage; + if (info - stg_info->begin >= 0 && info - stg_info->begin < stg_info->end - stg_info->begin) { + stage_test->stage_index = (int32_t)(info - stg_info->begin); + stage_test->stage_name = string_data(&info->name); + } + } + } + return true; +} + +bool data_test_stage_test_hide(class_data* data) { + data_test_stage_test* stage_test = data->data; + if (!stage_test) + return false; + + lock_data_free(&stage_data_lock, data_test_stage_test_hide); + + data->flags &= ~CLASS_HIDE; + data->flags |= CLASS_HIDDEN; + return true; +} + +void data_test_stage_test_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); + + float_t w = min((float_t)width, 240.0f); + float_t h = min((float_t)height, 240.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + ImGuiWindowFlags window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(data_test_stage_test_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + data_test_stage_test* stage_test = data->data; + + vector_stage_info* stg_info = &stage_test->rctx->data->data_ft.stage_data.stage; + + vector_data_test_stage_test_stage_pv* stage_pv = &stage_test->stage_pv; + vector_string* stage_ns = &stage_test->stage_ns; + vector_string* stage_other = &stage_test->stage_other; + + int32_t pv_id = stage_test->pv_id; + + char buf[0x100]; + sprintf_s(buf, sizeof(buf), "%03d", pv_id); + + igText("PV:"); + igSameLine(0.0f, 1.0f); + igSetNextItemWidth(48.0f); + if (igBeginCombo("##PV:", buf, 0)) { + for (data_test_stage_test_stage_pv* i = stage_pv->begin; i != stage_pv->end; i++) { + igPushID_Ptr(i); + sprintf_s(buf, sizeof(buf), "%03d", i->pv_id); + if (igSelectable_Bool(buf, pv_id == i->pv_id, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && pv_id != i->pv_id)) + pv_id = i->pv_id; + igPopID(); + + if (pv_id == i->pv_id) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (pv_id != stage_test->pv_id) { + stage_test->pv_index = -1; + stage_test->pv_id = pv_id; + } + + int32_t pv_index = stage_test->pv_index; + + igSameLine(0.0f, 1.0f); + igSetNextItemWidth(160.0f); + bool pv_id_found = false; + for (data_test_stage_test_stage_pv* i = stage_pv->begin; i != stage_pv->end; i++) { + if (pv_id != i->pv_id) + continue; + + if (igBeginCombo("##PV Index", pv_index > -1 + ? string_data(&i->stage.begin[pv_index]) : "", 0)) { + for (string* j = i->stage.begin; j != i->stage.end; j++) { + int32_t pv_idx = (int32_t)(j - i->stage.begin); + + igPushID_Ptr(j); + if (igSelectable_Bool(string_data(j), pv_index == pv_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && pv_index != pv_idx)) { + stage_test->pv_index = -1; + pv_index = pv_idx; + } + igPopID(); + + if (pv_index == pv_idx) + igSetItemDefaultFocus(); + } + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (pv_index != stage_test->pv_index) { + stage_test->stage_load = true; + stage_test->stage_name = string_data(&i->stage.begin[pv_index]); + stage_test->pv_index = pv_index; + } + pv_id_found = true; + break; + } + + if (!pv_id_found && igBeginCombo("##PV Index", "", 0)) { + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + int32_t ns_index = stage_test->ns_index; + + igText("NS:"); + igSameLine(0.0f, 1.0f); + igSetNextItemWidth(160.0f); + if (igBeginCombo("##NS Index", ns_index > -1 + ? string_data(&stage_ns->begin[ns_index]) : "", 0)) { + for (string* i = stage_ns->begin; i != stage_ns->end; i++) { + int32_t ns_idx = (int32_t)(i - stage_ns->begin); + + igPushID_Ptr(i); + if (igSelectable_Bool(string_data(i), ns_index == ns_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && ns_index != ns_idx)) { + stage_test->ns_index = -1; + ns_index = ns_idx; + } + igPopID(); + + if (ns_index == ns_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (ns_index != stage_test->ns_index) { + stage_test->stage_load = true; + stage_test->stage_name = string_data(&stage_ns->begin[ns_index]); + stage_test->ns_index = ns_index; + } + + int32_t other_index = stage_test->other_index; + + igText("Other:"); + igSameLine(0.0f, 1.0f); + igSetNextItemWidth(160.0f); + if (igBeginCombo("##Other Index", other_index > -1 + ? string_data(&stage_other->begin[other_index]) : "", 0)) { + for (string* i = stage_other->begin; i != stage_other->end; i++) { + int32_t other_idx = (int32_t)(i - stage_other->begin); + + igPushID_Ptr(i); + if (igSelectable_Bool(string_data(i), other_index == other_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && other_index != other_idx)) { + stage_test->other_index = -1; + other_index = other_idx; + } + igPopID(); + + if (other_index == other_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (other_index != stage_test->other_index) { + stage_test->stage_load = true; + stage_test->stage_name = string_data(&stage_other->begin[other_index]); + stage_test->other_index = other_index; + } + + int32_t stage_index = stage_test->stage_index; + + ImVec2 t; + igGetContentRegionAvail(&t); + igSetNextItemWidth(t.x); + if (igBeginCombo("##Stage Index", stage_index > -1 + ? string_data(&stg_info->begin[stage_index].name) : "", 0)) { + for (stage_info* i = stg_info->begin; i != stg_info->end; i++) { + int32_t stage_idx = (int32_t)(i - stg_info->begin); + + igPushID_Ptr(i); + if (igSelectable_Bool(string_data(&i->name), stage_index == stage_idx, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && stage_index != stage_idx)) { + stage_test->stage_index = -1; + stage_index = stage_idx; + } + igPopID(); + + if (stage_index == stage_idx) + igSetItemDefaultFocus(); + } + + data->imgui_focus |= igIsWindowFocused(0); + igEndCombo(); + } + + if (stage_index != stage_test->stage_index) { + stage_test->stage_load = true; + stage_test->stage_name = string_data(&stg_info->begin[stage_index].name); + stage_test->stage_index = stage_index; + } + + stage* stg = stage_test->rctx->stage; + if (!stg) + if (stage_test_data.stage) + stg = &stage_test_data; + else + stg = &stage_stgtst; + + igCheckbox("Stage display", &stg->display); + igCheckbox("[Ring]", &stg->ring); + igCheckbox("[Ground]", &stg->ground); + igCheckbox("[Sky]", &stg->sky); + igCheckbox("Effects display", &stg->effects); + + data->imgui_focus |= igIsWindowFocused(0); + +End: + igEnd(); +} + +void data_test_stage_test_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void data_test_stage_test_render(class_data* data) { + data_test_stage_test* stage_test = data->data; + + if (stage_test->stage_load) { + render_context* rctx = stage_test->rctx; + stage_free(&stage_test_data, rctx); + + data_struct* aft_data = rctx->data; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + stage_database* aft_stage_data = &aft_data->data_ft.stage_data; + + stage_init(&stage_test_data); + stage_load(&stage_test_data, aft_data, aft_auth_3d_db, + aft_obj_db, aft_tex_db, aft_stage_data, stage_test->stage_name, rctx); + stage_set(&stage_test_data, rctx); + stage_test->stage_load = false; + } +} + +bool data_test_stage_test_show(class_data* data) { + data_test_stage_test* stage_test = data->data; + if (!stage_test) + return false; + + bool ret = false; + lock_trylock(&pv_lock); + if (!lock_data_init(&stage_data_lock, &data->lock, data, data_test_stage_test_hide)) + goto End; + + ret = true; + +End: + lock_unlock(&pv_lock); + return ret; +} + +bool data_test_stage_test_dispose(class_data* data) { + lock_data_free(&stage_data_lock, data_test_stage_test_dispose); + + data_test_stage_test* stage_test = data->data; + if (stage_test) { + vector_data_test_stage_test_stage_pv_free(&stage_test->stage_pv, + data_test_stage_test_stage_pv_free); + vector_string_free(&stage_test->stage_ns, string_free); + vector_string_free(&stage_test->stage_other, string_free); + } + free(data->data); + + data->flags = CLASS_HIDDEN | CLASS_DISPOSED; + data->imgui_focus = false; + return true; +} + +static void data_test_stage_test_stage_pv_free(data_test_stage_test_stage_pv* pv) { + vector_string_free(&pv->stage, string_free); +} diff --git a/src/CLOUD/classes/data_test/stage_test.h b/src/CLOUD/classes/data_test/stage_test.h new file mode 100644 index 00000000..689d24c7 --- /dev/null +++ b/src/CLOUD/classes/data_test/stage_test.h @@ -0,0 +1,17 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool data_test_stage_test_init(class_data* data, render_context* rctx); +extern bool data_test_stage_test_hide(class_data* data); +extern void data_test_stage_test_imgui(class_data* data); +extern void data_test_stage_test_input(class_data* data); +extern void data_test_stage_test_render(class_data* data); +extern bool data_test_stage_test_show(class_data* data); +extern bool data_test_stage_test_dispose(class_data* data); diff --git a/src/CLOUD/classes/data_view.c b/src/CLOUD/classes/data_view.c new file mode 100644 index 00000000..283265a7 --- /dev/null +++ b/src/CLOUD/classes/data_view.c @@ -0,0 +1,55 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "data_view.h" +#include "data_view/auth_3d.h" +#include "data_view/draw_task.h" + +classes_struct data_view_classes[] = { + [DATA_VIEW_AUTH_3D] = { + .name = "Auth 3D##Data View", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = data_view_auth_3d_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .input = data_view_auth_3d_input, + .imgui = data_view_auth_3d_imgui, + .render = data_view_auth_3d_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = data_view_auth_3d_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = 0, + .sub_classes_count = 0, + }, + [DATA_VIEW_DRAW_TASK] = { + .name = "Draw Task##Data View", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = data_view_draw_task_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .input = data_view_draw_task_input, + .imgui = data_view_draw_task_imgui, + .render = data_view_draw_task_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = data_view_draw_task_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = 0, + .sub_classes_count = 0, + }, +}; diff --git a/src/CLOUD/classes/data_view.h b/src/CLOUD/classes/data_view.h new file mode 100644 index 00000000..abf44d51 --- /dev/null +++ b/src/CLOUD/classes/data_view.h @@ -0,0 +1,16 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../classes.h" + +typedef enum data_view_classes_enum { + DATA_VIEW_AUTH_3D, + DATA_VIEW_DRAW_TASK, + DATA_VIEW_MAX, +} data_view_classes_enum; + +extern classes_struct data_view_classes[]; diff --git a/src/CLOUD/classes/data_view/auth_3d.c b/src/CLOUD/classes/data_view/auth_3d.c new file mode 100644 index 00000000..c53adc5d --- /dev/null +++ b/src/CLOUD/classes/data_view/auth_3d.c @@ -0,0 +1,998 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "auth_3d.h" +#include "../../../CRE/auth_3d.h" +#include "../../input.h" +#include "../imgui_helper.h" + +static const char* auth_3d_fog_name[] = { + [FOG_DEPTH] = "Depth", + [FOG_HEIGHT] = "Height", + [FOG_BUMP] = "Bump", +}; + +static const char* auth_3d_light_name[] = { + [LIGHT_CHARA] = "Chara", + [LIGHT_STAGE] = "Stage", + [LIGHT_SUN] = "Sun", + [LIGHT_REFLECT] = "Reflect", + [LIGHT_SHADOW] = "Shadow", + [LIGHT_CHARA_COLOR] = "Chara Color", + [LIGHT_TONE_CURVE] = "Tone Curve", + [LIGHT_PROJECTION] = "Projection", +}; + +extern int32_t width; +extern int32_t height; +extern bool input_locked; + +const char* data_view_auth_3d_window_title = "Auth 3D##Data Viewer"; + +static void data_view_auth_3d_imgui_auth_3d_key(auth_3d_key* k, char* format, bool offset); +static void data_view_auth_3d_imgui_auth_3d_rgba(auth_3d_rgba* rgba, char* format); +static void data_view_auth_3d_imgui_auth_3d_vec3(auth_3d_vec3* vec, char* format); +static void data_view_auth_3d_imgui_auth_3d_model_transform(auth_3d_model_transform* mt); + +static void data_view_auth_3d_imgui_auth_3d_ambient(auth_3d_ambient* a); +static void data_view_auth_3d_imgui_auth_3d_camera_auxiliary(auth_3d_camera_auxiliary* ca); +static void data_view_auth_3d_imgui_auth_3d_camera_root(auth_3d_camera_root* cr, size_t index); +static void data_view_auth_3d_imgui_auth_3d_chara(auth_3d_chara* c); +static void data_view_auth_3d_imgui_auth_3d_curve(auth_3d_curve* c); +static void data_view_auth_3d_imgui_auth_3d_dof(auth_3d_dof* d); +static void data_view_auth_3d_imgui_auth_3d_fog(auth_3d_fog* f); +static void data_view_auth_3d_imgui_auth_3d_light(auth_3d_light* l); +static void data_view_auth_3d_imgui_auth_3d_m_object_hrc(auth_3d_m_object_hrc* moh); +static void data_view_auth_3d_imgui_auth_3d_material_list(auth_3d_material_list* ml); +static void data_view_auth_3d_imgui_auth_3d_object(auth_3d_object* o); +static void data_view_auth_3d_imgui_auth_3d_object_curve(auth_3d_object_curve* oc, char* format); +static void data_view_auth_3d_imgui_auth_3d_object_hrc(auth_3d_object_hrc* oh); +static void data_view_auth_3d_imgui_auth_3d_object_instance(auth_3d_object_instance* oi); +static void data_view_auth_3d_imgui_auth_3d_object_model_transform(auth_3d_object_model_transform* omt); +static void data_view_auth_3d_imgui_auth_3d_object_node(auth_3d_object_node* on); +static void data_view_auth_3d_imgui_auth_3d_object_texture_pattern(auth_3d_object_texture_pattern* otp); +static void data_view_auth_3d_imgui_auth_3d_object_texture_transform(auth_3d_object_texture_transform* ott); +static void data_view_auth_3d_imgui_auth_3d_point(auth_3d_point* p); +static void data_view_auth_3d_imgui_auth_3d_post_process(auth_3d_post_process* pp); + +bool data_view_auth_3d_init(class_data* data, render_context* rctx) { + data_view_auth_3d_dispose(data); + return true; +} + +void data_view_auth_3d_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); + + float_t w = min((float_t)width, 480.0f); + float_t h = min((float_t)height, 540.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(data_view_auth_3d_window_title, &open, 0); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + ImGuiTreeNodeFlags tree_node_base_flags = 0; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + ImGuiTreeNodeFlags tree_node_flags; + + char buf[0x200]; + for (size_t i = 0; i < AUTH_3D_DATA_COUNT; i++) { + auth_3d* auth = &auth_3d_data.data[i]; + if (auth->id == -1) + continue; + + size_t str_len = min(sizeof(buf) - 1, auth->file_name.length); + memcpy(buf, string_data(&auth->file_name), str_len); + buf[str_len] = 0; + + if (str_len >= 5 && !memcmp(&buf[str_len - 5], ".a3da", 6)) + buf[str_len - 5] = 0; + + tree_node_flags = tree_node_base_flags; + + igPushID_Int(auth->id); + if (!igTreeNodeEx_Ptr(auth, tree_node_flags, + "ID: %5d; File: %s; Frame: %5d", auth->id & 0x7FFF, buf, auth->frame_int)) { + igPopID(); + continue; + } + + tree_node_flags = tree_node_base_flags; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + + if (auth->ambient.end - auth->ambient.begin + && igTreeNodeEx_Str("Ambient", tree_node_flags)) { + for (auth_3d_ambient* l = auth->ambient.begin; + l != auth->ambient.end; l++) + data_view_auth_3d_imgui_auth_3d_ambient(l); + igTreePop(); + } + + if (auth->auth_2d.end - auth->auth_2d.begin + && igTreeNodeEx_Str("Auth 2D", tree_node_flags)) { + for (string* l = auth->auth_2d.begin; + l != auth->auth_2d.end; l++) + igText(string_data(l)); + igTreePop(); + } + + data_view_auth_3d_imgui_auth_3d_camera_auxiliary(&auth->camera_auxiliary); + + if (auth->camera_root.end - auth->camera_root.begin > 1 + && igTreeNodeEx_Str("Camera Root", tree_node_flags)) { + for (auth_3d_camera_root* l = auth->camera_root.begin; + l != auth->camera_root.end; l++) + data_view_auth_3d_imgui_auth_3d_camera_root(l, l - auth->camera_root.begin); + igTreePop(); + } + else if (auth->camera_root.end - auth->camera_root.begin == 1) + data_view_auth_3d_imgui_auth_3d_camera_root(&auth->camera_root.begin[0], -1); + + if (auth->chara.end - auth->chara.begin + && igTreeNodeEx_Str("Chara", tree_node_flags)) { + for (auth_3d_chara* l = auth->chara.begin; + l != auth->chara.end; l++) + data_view_auth_3d_imgui_auth_3d_chara(l); + igTreePop(); + } + + data_view_auth_3d_imgui_auth_3d_dof(&auth->dof); + + if (auth->fog.end - auth->fog.begin + && igTreeNodeEx_Str("Fog", tree_node_flags)) { + for (auth_3d_fog* l = auth->fog.begin; + l != auth->fog.end; l++) + data_view_auth_3d_imgui_auth_3d_fog(l); + igTreePop(); + } + + if (auth->light.end - auth->light.begin + && igTreeNodeEx_Str("Light", tree_node_flags)) { + for (auth_3d_light* l = auth->light.begin; + l != auth->light.end; l++) + data_view_auth_3d_imgui_auth_3d_light(l); + igTreePop(); + } + + if (auth->m_object_hrc_list.end - auth->m_object_hrc_list.begin + && igTreeNodeEx_Str("M Object HRC", tree_node_flags)) { + for (auth_3d_m_object_hrc** l = auth->m_object_hrc_list.begin; + l != auth->m_object_hrc_list.end; l++) + data_view_auth_3d_imgui_auth_3d_m_object_hrc(*l); + igTreePop(); + } + + if (auth->material_list.end - auth->material_list.begin + && igTreeNodeEx_Str("Material List", tree_node_flags)) { + for (auth_3d_material_list* l = auth->material_list.begin; + l != auth->material_list.end; l++) + data_view_auth_3d_imgui_auth_3d_material_list(l); + igTreePop(); + } + + if (auth->motion.end - auth->motion.begin + && igTreeNodeEx_Str("Motion", tree_node_flags)) { + for (string* l = auth->motion.begin; + l != auth->motion.end; l++) + igText(string_data(l)); + igTreePop(); + } + + if (auth->object_list.end - auth->object_list.begin + && igTreeNodeEx_Str("Object", tree_node_flags)) { + for (auth_3d_object** l = auth->object_list.begin; + l != auth->object_list.end; l++) + data_view_auth_3d_imgui_auth_3d_object(*l); + igTreePop(); + } + + if (auth->object_hrc_list.end - auth->object_hrc_list.begin + && igTreeNodeEx_Str("Object HRC", tree_node_flags)) { + for (auth_3d_object_hrc** l = auth->object_hrc_list.begin; + l != auth->object_hrc_list.end; l++) + data_view_auth_3d_imgui_auth_3d_object_hrc(*l); + igTreePop(); + } + + if (auth->point.end - auth->point.begin + && igTreeNodeEx_Str("Point", tree_node_flags)) { + for (auth_3d_point* l = auth->point.begin; + l != auth->point.end; l++) + data_view_auth_3d_imgui_auth_3d_point(l); + igTreePop(); + } + + data_view_auth_3d_imgui_auth_3d_post_process(&auth->post_process); + + igTreePop(); + igPopID(); + } + + data->imgui_focus |= igIsWindowFocused(0); + +End: + igEnd(); +} + +void data_view_auth_3d_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void data_view_auth_3d_render(class_data* data) { + +} + +bool data_view_auth_3d_dispose(class_data* data) { + return true; +} + +static void data_view_auth_3d_imgui_auth_3d_key(auth_3d_key* k, char* format, bool offset) { + if (!k) + return; + + if (offset) { + igText(" "); + if (format) { + igSameLine(0.0f, -1.0f); + igText(format); + } + igSameLine(0.0f, -1.0f); + } + else if (format) { + igText(format); + igSameLine(0.0f, -1.0f); + } + + switch (k->type) { + case A3DA_KEY_NONE: + default: + igText("V: %#.6g", 0.0f); + break; + case A3DA_KEY_STATIC: + igText("V: %#.6g", k->value); + break; + case A3DA_KEY_LINEAR: + case A3DA_KEY_HERMITE: + case A3DA_KEY_HOLD: + igText("F: %5g; V: %#.6g", k->frame, k->value_interp); + break; + } +} + +static void data_view_auth_3d_imgui_auth_3d_rgba(auth_3d_rgba* rgba, char* format) { + if (!rgba || !rgba->flags || !format) + return; + + igText(format); + if (rgba->flags & A3DA_RGBA_R) + data_view_auth_3d_imgui_auth_3d_key(&rgba->r, "R:", true); + if (rgba->flags & A3DA_RGBA_G) + data_view_auth_3d_imgui_auth_3d_key(&rgba->g, "G:", true); + if (rgba->flags & A3DA_RGBA_B) + data_view_auth_3d_imgui_auth_3d_key(&rgba->b, "B:", true); + if (rgba->flags & A3DA_RGBA_A) + data_view_auth_3d_imgui_auth_3d_key(&rgba->a, "A:", true); +} + +static void data_view_auth_3d_imgui_auth_3d_vec3(auth_3d_vec3* vec, char* format) { + if (!vec || !format) + return; + + igText(format); + igPushStyleColor_U32(ImGuiCol_WindowBg, 0xFF404040); + data_view_auth_3d_imgui_auth_3d_key(&vec->x, "X:", true); + data_view_auth_3d_imgui_auth_3d_key(&vec->y, "Y:", true); + data_view_auth_3d_imgui_auth_3d_key(&vec->z, "Z:", true); + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_model_transform(auth_3d_model_transform* mt) { + if (!mt) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(mt, tree_node_flags, "Model Transform")) + return; + + data_view_auth_3d_imgui_auth_3d_vec3(&mt->translation, "Translation"); + data_view_auth_3d_imgui_auth_3d_vec3(&mt->rotation, "Rotation"); + data_view_auth_3d_imgui_auth_3d_vec3(&mt->scale, "Scale"); + + igText("Visibility"); + data_view_auth_3d_imgui_auth_3d_key(&mt->visibility, 0, true); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_ambient(auth_3d_ambient* a) { + if (!a || !a->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(a, tree_node_flags, string_data(&a->name))) + return; + + if (a->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) + data_view_auth_3d_imgui_auth_3d_rgba(&a->light_diffuse, "Light Diffuse"); + if (a->flags & A3DA_AMBIENT_RIM_LIGHT_DIFFUSE) + data_view_auth_3d_imgui_auth_3d_rgba(&a->rim_light_diffuse, "Rim Light Diffuse"); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_camera_auxiliary(auth_3d_camera_auxiliary* ca) { + if (!ca || !ca->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(ca, tree_node_flags, "Camera Auxiliary")) + return; + + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE) { + igText("Auto Exposure"); + data_view_auth_3d_imgui_auth_3d_key(&ca->auto_exposure, 0, true); + } + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE) { + igText("Exposure"); + data_view_auth_3d_imgui_auth_3d_key(&ca->exposure, 0, true); + } + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE_RATE) { + igText("Exposure Rate"); + data_view_auth_3d_imgui_auth_3d_key(&ca->exposure_rate, 0, true); + } + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA) { + igText("Gamma"); + data_view_auth_3d_imgui_auth_3d_key(&ca->gamma, 0, true); + } + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE) { + igText("Gamma Rate"); + data_view_auth_3d_imgui_auth_3d_key(&ca->gamma_rate, 0, true); + } + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_SATURATE) { + igText("Saturate"); + data_view_auth_3d_imgui_auth_3d_key(&ca->saturate, 0, true); + } + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_camera_root(auth_3d_camera_root* cr, size_t index) { + if (!cr) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + if (index == -1) + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(cr, tree_node_flags, + index == -1 ? "Camera Root" : "%d", (int32_t)index)) + return; + + data_view_auth_3d_imgui_auth_3d_vec3(&cr->interest.translation, "Interest"); + data_view_auth_3d_imgui_auth_3d_model_transform(&cr->model_transform); + + auth_3d_camera_root_view_point* vp = &cr->view_point; + data_view_auth_3d_imgui_auth_3d_vec3(&vp->model_transform.translation, "View Point"); + + igText("Aspect"); + igText(" %#.6g", vp->aspect); + + if (vp->flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_FOV) { + igText(vp->fov_is_horizontal ? "FOV Horizontal" : "FOV"); + data_view_auth_3d_imgui_auth_3d_key(&vp->fov, 0, true); + } + else { + igText("Camera Aperture Width"); + igText(" %#.6g", vp->camera_aperture_w); + + igText("Camera Aperture Height"); + igText(" %#.6g", vp->camera_aperture_h); + + igText("Focal Length"); + data_view_auth_3d_imgui_auth_3d_key(&vp->focal_length, 0, true); + } + + if (vp->flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_ROLL) { + igText("Roll"); + data_view_auth_3d_imgui_auth_3d_key(&vp->roll, 0, true); + } + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_chara(auth_3d_chara* c) { + if (!c) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(c, tree_node_flags, string_data(&c->name))) + return; + + data_view_auth_3d_imgui_auth_3d_model_transform(&c->model_transform); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_curve(auth_3d_curve* c) { + if (!c) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(c, tree_node_flags, string_data(&c->name))) + return; + + data_view_auth_3d_imgui_auth_3d_key(&c->curve, 0, false); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_dof(auth_3d_dof* d) { + if (!d || !d->has_dof) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + bool enable = fabsf(d->model_transform.rotation_value.z) > 0.000001f; + if (!enable) + igPushStyleColor_U32(ImGuiCol_Text, 0xFF888888); + if (!igTreeNodeEx_Ptr(d, tree_node_flags, "DOF")) + if (!enable) + igPopStyleColor(1); + return; + + auth_3d_model_transform* mt = &d->model_transform; + + data_view_auth_3d_imgui_auth_3d_vec3(&mt->translation, "Position"); + + igText("Focus Range"); + data_view_auth_3d_imgui_auth_3d_key(&mt->scale.y, 0, true); + + igText("Fuzzing Range"); + data_view_auth_3d_imgui_auth_3d_key(&mt->rotation.y, 0, true); + + igText("Ratio"); + data_view_auth_3d_imgui_auth_3d_key(&mt->rotation.z, 0, true); + igTreePop(); + + if (!enable) + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_fog(auth_3d_fog* f) { + if (!f || !f->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(f, tree_node_flags, auth_3d_fog_name[f->id])) + return; + + if (f->flags & AUTH_3D_FOG_COLOR) + data_view_auth_3d_imgui_auth_3d_rgba(&f->color, "Color"); + + if (f->flags & AUTH_3D_FOG_DENSITY) { + igText("Density"); + data_view_auth_3d_imgui_auth_3d_key(&f->density, 0, true); + } + + if (f->flags & AUTH_3D_FOG_END) { + igText("End"); + data_view_auth_3d_imgui_auth_3d_key(&f->end, 0, true); + } + + if (f->flags & AUTH_3D_FOG_START) { + igText("Start"); + data_view_auth_3d_imgui_auth_3d_key(&f->start, 0, true); + } + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_light(auth_3d_light* l) { + if (!l || !l->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(l, tree_node_flags, auth_3d_light_name[l->id])) + return; + + if (l->flags & AUTH_3D_LIGHT_AMBIENT) + data_view_auth_3d_imgui_auth_3d_rgba(&l->ambient, "Ambient"); + + if (l->flags & AUTH_3D_LIGHT_CONE_ANGLE) { + igText("Cone Angle"); + data_view_auth_3d_imgui_auth_3d_key(&l->cone_angle, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_CONSTANT) { + igText("Constant"); + data_view_auth_3d_imgui_auth_3d_key(&l->constant, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_DIFFUSE) + data_view_auth_3d_imgui_auth_3d_rgba(&l->diffuse, "Diffuse"); + + if (l->flags & AUTH_3D_LIGHT_DROP_OFF) { + igText("Drop Off"); + data_view_auth_3d_imgui_auth_3d_key(&l->drop_off, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_FAR) { + igText("Far"); + data_view_auth_3d_imgui_auth_3d_key(&l->_far, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_INTENSITY) { + igText("Intensity"); + data_view_auth_3d_imgui_auth_3d_key(&l->intensity, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_LINEAR) { + igText("Linear"); + data_view_auth_3d_imgui_auth_3d_key(&l->linear, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_POSITION) + data_view_auth_3d_imgui_auth_3d_vec3(&l->position.translation, "Position"); + + if (l->flags & AUTH_3D_LIGHT_QUADRATIC) { + igText("Quadratic"); + data_view_auth_3d_imgui_auth_3d_key(&l->quadratic, 0, true); + } + + if (l->flags & AUTH_3D_LIGHT_SPECULAR) + data_view_auth_3d_imgui_auth_3d_rgba(&l->specular, "Specular"); + + if (l->flags & AUTH_3D_LIGHT_SPOT_DIRECTION) + data_view_auth_3d_imgui_auth_3d_vec3(&l->spot_direction.translation, "Spot Direction"); + + if (l->flags & AUTH_3D_LIGHT_TONE_CURVE) + data_view_auth_3d_imgui_auth_3d_rgba(&l->tone_curve, "Tone Curve"); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_m_object_hrc(auth_3d_m_object_hrc* moh) { + if (!moh) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + bool visible = moh->model_transform.visible; + if (!visible) + igPushStyleColor_U32(ImGuiCol_Text, 0xFF888888); + + if (!igTreeNodeEx_Ptr(moh, tree_node_flags, string_data(&moh->name))) { + if (!visible) + igPopStyleColor(1); + return; + } + + if (moh->instance.end - moh->instance.begin + && igTreeNodeEx_Str("Instance", tree_node_flags)) { + for (auth_3d_object_instance* i = moh->instance.begin; i != moh->instance.end; i++) + data_view_auth_3d_imgui_auth_3d_object_instance(i); + igTreePop(); + } + + data_view_auth_3d_imgui_auth_3d_object_model_transform(&moh->model_transform); + + if (moh->node.end - moh->node.begin + && igTreeNodeEx_Str("Node", tree_node_flags)) { + for (auth_3d_object_node* i = moh->node.begin; i != moh->node.end; i++) + data_view_auth_3d_imgui_auth_3d_object_node(i); + igTreePop(); + } + igTreePop(); + + if (!visible) + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_material_list(auth_3d_material_list* ml) { + if (!ml || !ml->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(ml, tree_node_flags, string_data(&ml->name))) + return; + + if (ml->flags & AUTH_3D_MATERIAL_LIST_BLEND_COLOR) + data_view_auth_3d_imgui_auth_3d_rgba(&ml->blend_color, "Blend Color"); + + if (ml->flags & AUTH_3D_MATERIAL_LIST_GLOW_INTENSITY) { + igText("Glow Intensity"); + data_view_auth_3d_imgui_auth_3d_key(&ml->glow_intensity, 0, false); + } + + if (ml->flags & AUTH_3D_MATERIAL_LIST_INCANDESCENCE) + data_view_auth_3d_imgui_auth_3d_rgba(&ml->incandescence, "Incandescence"); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_object(auth_3d_object* o) { + if (!o) + return; + + ImGuiTreeNodeFlags tree_node_base_flags = 0; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + ImGuiTreeNodeFlags tree_node_flags; + + char* s = string_data(&o->name); + char* name = s; + while (s = strchr(name = s, '|')) + s++; + + bool visible = o->model_transform.visible; + if (!visible) + igPushStyleColor_U32(ImGuiCol_Text, 0xFF888888); + + tree_node_flags = tree_node_base_flags; + + if (!igTreeNodeEx_Ptr(o, tree_node_flags, name)) { + if (!visible) + igPopStyleColor(1); + return; + } + + data_view_auth_3d_imgui_auth_3d_model_transform(&o->model_transform); + + data_view_auth_3d_imgui_auth_3d_object_curve(&o->morph, "Morph"); + data_view_auth_3d_imgui_auth_3d_object_curve(&o->pattern, "Pattern"); + + tree_node_flags = tree_node_base_flags; + + if (o->texture_pattern.end - o->texture_pattern.begin + && igTreeNodeEx_Str("Texture Pattern", tree_node_flags)) { + for (auth_3d_object_texture_pattern* i = o->texture_pattern.begin; + i != o->texture_pattern.end; i++) + data_view_auth_3d_imgui_auth_3d_object_texture_pattern(i); + igTreePop(); + } + + tree_node_flags = tree_node_base_flags; + + if (o->texture_transform.end - o->texture_transform.begin + && igTreeNodeEx_Str("Texture Transform", tree_node_flags)) { + for (auth_3d_object_texture_transform* i = o->texture_transform.begin; + i != o->texture_transform.end; i++) + data_view_auth_3d_imgui_auth_3d_object_texture_transform(i); + igTreePop(); + } + + + tree_node_flags = tree_node_base_flags; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + + if (o->children_object.end - o->children_object.begin + && igTreeNodeEx_Str("Children Object", tree_node_flags)) { + for (auth_3d_object** i = o->children_object.begin; + i != o->children_object.end; i++) + data_view_auth_3d_imgui_auth_3d_object(*i); + igTreePop(); + } + + tree_node_flags = tree_node_base_flags; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + + if (o->children_object_hrc.end - o->children_object_hrc.begin + && igTreeNodeEx_Str("Children Object HRC", tree_node_flags)) { + for (auth_3d_object_hrc** i = o->children_object_hrc.begin; + i != o->children_object_hrc.end; i++) + data_view_auth_3d_imgui_auth_3d_object_hrc(*i); + igTreePop(); + } + igTreePop(); + + if (!visible) + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_object_curve(auth_3d_object_curve* oc, char* format) { + if (!oc || !oc->curve || !format) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(oc, tree_node_flags, format)) + return; + + data_view_auth_3d_imgui_auth_3d_curve(oc->curve); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_object_hrc(auth_3d_object_hrc* oh) { + if (!oh) + return; + + ImGuiTreeNodeFlags tree_node_base_flags = 0; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + ImGuiTreeNodeFlags tree_node_flags; + + char* s = string_data(&oh->name); + char* name = s; + while (s = strchr(name = s, '|')) + s++; + + bool visible = oh->node.begin[0].model_transform.visible; + if (!visible) + igPushStyleColor_U32(ImGuiCol_Text, 0xFF888888); + + tree_node_flags = tree_node_base_flags; + + if (!igTreeNodeEx_Ptr(oh, tree_node_flags, name)) { + if (!visible) + igPopStyleColor(1); + return; + } + + tree_node_flags = tree_node_base_flags; + + if (oh->node.end - oh->node.begin + && igTreeNodeEx_Str("Node", tree_node_flags)) { + for (auth_3d_object_node* i = oh->node.begin; i != oh->node.end; i++) + data_view_auth_3d_imgui_auth_3d_object_node(i); + igTreePop(); + } + + tree_node_flags = tree_node_base_flags; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + + if (oh->children_object.end - oh->children_object.begin + && igTreeNodeEx_Str("Children Object", tree_node_flags)) { + for (auth_3d_object** i = oh->children_object.begin; + i != oh->children_object.end; i++) + data_view_auth_3d_imgui_auth_3d_object(*i); + igTreePop(); + } + + tree_node_flags = tree_node_base_flags; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + + if (oh->children_object_hrc.end - oh->children_object_hrc.begin + && igTreeNodeEx_Str("Children Object HRC", tree_node_flags)) { + for (auth_3d_object_hrc** i = oh->children_object_hrc.begin; + i != oh->children_object_hrc.end; i++) + data_view_auth_3d_imgui_auth_3d_object_hrc(*i); + igTreePop(); + } + igTreePop(); + + if (!visible) + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_object_instance(auth_3d_object_instance* oi) { + if (!oi) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + bool visible = oi->model_transform.visible; + if (!visible) + igPushStyleColor_U32(ImGuiCol_Text, 0xFF888888); + + if (!igTreeNodeEx_Ptr(oi, tree_node_flags, string_data(&oi->name))) { + if (!visible) + igPopStyleColor(1); + return; + } + + data_view_auth_3d_imgui_auth_3d_object_model_transform(&oi->model_transform); + + if (oi->shadow) + igText("Shadow: True"); + + igText("UID Name: %s", string_data(&oi->uid_name)); + igTreePop(); + + if (!visible) + igPopStyleColor(1); +} + +static void data_view_auth_3d_imgui_auth_3d_object_model_transform(auth_3d_object_model_transform* omt) { + if (!omt) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(omt, tree_node_flags, "Model Transform")) + return; + + igText("Frame: %5f", omt->frame); + + data_view_auth_3d_imgui_auth_3d_vec3(&omt->translation, "Translation"); + data_view_auth_3d_imgui_auth_3d_vec3(&omt->rotation, "Rotation"); + data_view_auth_3d_imgui_auth_3d_vec3(&omt->scale, "Scale"); + + igText("Visibility"); + data_view_auth_3d_imgui_auth_3d_key(&omt->visibility, 0, true); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_object_node(auth_3d_object_node* on) { + if (!on) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(on, tree_node_flags, string_data(&on->name))) + return; + + data_view_auth_3d_imgui_auth_3d_object_model_transform(&on->model_transform); + + if (on->flags & AUTH_3D_OBJECT_NODE_JOINT_ORIENT) { + igText("Joint Orient "); + igText(" X: %#.6g", on->joint_orient.x); + igText(" Y: %#.6g", on->joint_orient.y); + igText(" Z: %#.6g", on->joint_orient.z); + } + + igText("Parent: %d", on->parent); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_object_texture_pattern(auth_3d_object_texture_pattern* otp) { + if (!otp) + return; + + data_view_auth_3d_imgui_auth_3d_object_curve(&otp->pattern, string_data(&otp->name)); +} + +static void data_view_auth_3d_imgui_auth_3d_object_texture_transform(auth_3d_object_texture_transform* ott) { + if (!ott || !ott->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(ott, tree_node_flags, string_data(&ott->name))) + return; + + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + data_view_auth_3d_imgui_auth_3d_key(&ott->coverage_u, "Coverage U:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + data_view_auth_3d_imgui_auth_3d_key(&ott->coverage_v, "Coverage V:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + data_view_auth_3d_imgui_auth_3d_key(&ott->offset_u, "Offset U:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + data_view_auth_3d_imgui_auth_3d_key(&ott->offset_v, "Offset V:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + data_view_auth_3d_imgui_auth_3d_key(&ott->repeat_u, "Repeat U:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + data_view_auth_3d_imgui_auth_3d_key(&ott->repeat_v, "Repeat V:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE) + data_view_auth_3d_imgui_auth_3d_key(&ott->rotate, "Rotate:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + data_view_auth_3d_imgui_auth_3d_key(&ott->rotate_frame, "Rotate Frame:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + data_view_auth_3d_imgui_auth_3d_key(&ott->translate_frame_u, "Translate Frame U:", false); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + data_view_auth_3d_imgui_auth_3d_key(&ott->translate_frame_v, "Translate Frame V:", false);; + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_point(auth_3d_point* p) { + if (!p) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(p, tree_node_flags, string_data(&p->name))) + return; + + data_view_auth_3d_imgui_auth_3d_model_transform(&p->model_transform); + igTreePop(); +} + +static void data_view_auth_3d_imgui_auth_3d_post_process(auth_3d_post_process* pp) { + if (!pp || !pp->flags) + return; + + ImGuiTreeNodeFlags tree_node_flags = 0; + tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + if (!igTreeNodeEx_Ptr(pp, tree_node_flags, "Post Process")) + return; + + if (pp->flags & AUTH_3D_POST_PROCESS_INTENSITY) + data_view_auth_3d_imgui_auth_3d_rgba(&pp->intensity, "intensity"); + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_FLARE) { + igText("Lens Flare"); + data_view_auth_3d_imgui_auth_3d_key(&pp->lens_flare, 0, false); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_GHOST) { + igText("Lens Gghost"); + data_view_auth_3d_imgui_auth_3d_key(&pp->lens_ghost, 0, false); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_SHAFT) { + igText("Lens Shaft"); + data_view_auth_3d_imgui_auth_3d_key(&pp->lens_shaft, 0, false); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_RADIUS) + data_view_auth_3d_imgui_auth_3d_rgba(&pp->radius, "Radius"); + + if (pp->flags & AUTH_3D_POST_PROCESS_SCENE_FADE) + data_view_auth_3d_imgui_auth_3d_rgba(&pp->scene_fade, "Scene Fade"); + igTreePop(); +} diff --git a/src/CLOUD/classes/data_view/auth_3d.h b/src/CLOUD/classes/data_view/auth_3d.h new file mode 100644 index 00000000..13088478 --- /dev/null +++ b/src/CLOUD/classes/data_view/auth_3d.h @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool data_view_auth_3d_init(class_data* data, render_context* rctx); +extern void data_view_auth_3d_imgui(class_data* data); +extern void data_view_auth_3d_input(class_data* data); +extern void data_view_auth_3d_render(class_data* data); +extern bool data_view_auth_3d_dispose(class_data* data); diff --git a/src/CLOUD/classes/data_view/draw_task.c b/src/CLOUD/classes/data_view/draw_task.c new file mode 100644 index 00000000..be285d09 --- /dev/null +++ b/src/CLOUD/classes/data_view/draw_task.c @@ -0,0 +1,247 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "draw_task.h" +#include "../../../CRE/render_context.h" +#include "../imgui_helper.h" + +static const char* draw_object_type_name[] = { + [DRAW_OBJECT_OPAQUE] = "Opaque", + [DRAW_OBJECT_TRANSLUCENT] = "Translucent", + [DRAW_OBJECT_TRANSLUCENT_NO_SHADOW] = "Translucent (No Shadow)", + [DRAW_OBJECT_TRANSPARENT] = "Transparent", + [DRAW_OBJECT_SHADOW_CHARA] = "Shadow Chara", + [DRAW_OBJECT_SHADOW_STAGE] = "Shadow Stage", + [DRAW_OBJECT_TYPE_6] = "Type 6", + [DRAW_OBJECT_TYPE_7] = "Type 7", + [DRAW_OBJECT_SHADOW_OBJECT_CHARA] = "Shadow Object Chara", + [DRAW_OBJECT_SHADOW_OBJECT_STAGE] = "Shadow Object Stage", + [DRAW_OBJECT_REFLECT_CHARA_OPAQUE] = "Reflect Chara Opaque", + [DRAW_OBJECT_REFLECT_CHARA_TRANSLUCENT] = "Reflect Chara Translucent", + [DRAW_OBJECT_REFLECT_CHARA_TRANSPARENT] = "Reflect Chara Transparent", + [DRAW_OBJECT_REFLECT_OPAQUE] = "Reflect Opaque", + [DRAW_OBJECT_REFLECT_TRANSLUCENT] = "Reflect Translucent", + [DRAW_OBJECT_REFLECT_TRANSPARENT] = "Reflect Transparent", + [DRAW_OBJECT_REFRACT_OPAQUE] = "Refract Opaque", + [DRAW_OBJECT_REFRACT_TRANSLUCENT] = "Refract Translucent", + [DRAW_OBJECT_REFRACT_TRANSPARENT] = "Refract Transparent", + [DRAW_OBJECT_SSS] = "SSS", + [DRAW_OBJECT_OPAQUE_TYPE_20] = "Opaque (Type 20)", + [DRAW_OBJECT_TRANSPARENT_TYPE_21] = "Transparent (Type 21)", + [DRAW_OBJECT_TRANSLUCENT_TYPE_22] = "Translucent (Type 22)", + [DRAW_OBJECT_OPAQUE_TYPE_23] = "Opaque (Type 23)", + [DRAW_OBJECT_TRANSPARENT_TYPE_24] = "Transparent (Type 24)", + [DRAW_OBJECT_TRANSLUCENT_TYPE_25] = "Translucent (Type 25)", + [DRAW_OBJECT_OPAQUE_TYPE_26] = "Opaque (Type 26)", + [DRAW_OBJECT_TRANSPARENT_TYPE_27] = "Transparent (Type 27)", + [DRAW_OBJECT_TRANSLUCENT_TYPE_28] = "Translucent (Type 28)", + [DRAW_OBJECT_RIPPLE] = "Ripple", +}; + +static const char* draw_task_type_name[] = { + [DRAW_TASK_TYPE_OBJECT] = "Object", + [DRAW_TASK_TYPE_PRIMITIVE] = "Primitive", + [DRAW_TASK_TYPE_PREPROCESS] = "Preprocess", + [DRAW_TASK_TYPE_OBJECT_TRANSLUCENT] = "Object Translucent", +}; + +typedef struct data_view_draw_task { + render_context* rctx; + vector_ptr_draw_task draw_tasks; + vector_uint32_t draw_task_hashes; + vector_uint32_t draw_task_indices; +} data_view_draw_task; + +extern int32_t width; +extern int32_t height; +extern bool input_locked; + +const char* data_view_draw_task_window_title = "Draw Task##Data Viewer"; + +static void data_view_draw_task_imgui_draw_object(draw_object* object); + +bool data_view_draw_task_init(class_data* data, render_context* rctx) { + data->data = force_malloc(sizeof(data_view_draw_task)); + data_view_draw_task* data_view = data->data; + if (data_view) { + data_view->rctx = rctx; + data_view->draw_tasks = vector_ptr_empty(draw_task); + data_view->draw_task_hashes = vector_empty(uint32_t); + data_view->draw_task_indices = vector_empty(uint32_t); + } + return true; +} + +void data_view_draw_task_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); + + float_t w = min((float_t)width, 480.0f); + float_t h = min((float_t)height, 542.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(data_view_draw_task_window_title, &open, 0); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + data_view_draw_task* data_view = data->data; + if (!data_view) + goto End; + + render_context* rctx = data_view->rctx; + vector_ptr_draw_task* draw_task_array = rctx->object_data.draw_task_array; + vector_ptr_draw_task* draw_tasks_sort = &data_view->draw_tasks; + vector_uint32_t* draw_task_hashes = &data_view->draw_task_hashes; + vector_uint32_t* draw_task_indices = &data_view->draw_task_indices; + + ImGuiTreeNodeFlags tree_node_base_flags = 0; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow; + tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + + ImGuiTreeNodeFlags tree_node_flags; + + for (draw_object_type i = DRAW_OBJECT_OPAQUE; i < DRAW_OBJECT_MAX; i++) { + bool translucent_no_shadow = i == DRAW_OBJECT_TRANSLUCENT_NO_SHADOW; + tree_node_flags = tree_node_base_flags; + + igPushID_Int(i); + vector_ptr_draw_task* draw_tasks = &draw_task_array[i]; + size_t count = draw_tasks->end - draw_tasks->begin; + bool enable = count > 0; + imguiDisableElementPush(enable); + if (!igTreeNodeEx_StrStr("", tree_node_flags, + "%s; Count: %llu", draw_object_type_name[i], count)) { + imguiDisableElementPop(enable); + igPopID(); + continue; + } + + vector_ptr_draw_task_insert_range(draw_tasks_sort, 0, draw_tasks->begin, draw_tasks->end); + vector_uint32_t_reserve(draw_task_hashes, count); + vector_uint32_t_reserve(draw_task_indices, count); + for (draw_task** j = draw_tasks_sort->begin; j != draw_tasks_sort->end; j++) { + *vector_uint32_t_reserve_back(draw_task_hashes) = hash_murmurhash((void*)j, 8, 0, true, false); + *vector_uint32_t_reserve_back(draw_task_indices) = (uint32_t)(j - draw_tasks_sort->begin); + } + + for (uint32_t* i = draw_task_hashes->begin; i != &draw_task_hashes->end[-1]; i++) + for (uint32_t* j = i + 1; j != draw_task_hashes->end; j++) + if (*i > *j) { + size_t i_idx = i - draw_task_hashes->begin; + size_t j_idx = j - draw_task_hashes->begin; + + draw_task* temp = draw_tasks_sort->begin[i_idx]; + draw_tasks_sort->begin[i_idx] = draw_tasks_sort->begin[j_idx]; + draw_tasks_sort->begin[j_idx] = temp; + + uint32_t temp_hash = *i; + *i = *j; + *j = temp_hash; + + uint32_t temp_index = draw_task_indices->begin[i_idx]; + draw_task_indices->begin[i_idx] = draw_task_indices->begin[j_idx]; + draw_task_indices->begin[j_idx] = temp_index; + } + + igText(" Hash; Index; Type"); + + for (draw_task** j = draw_tasks_sort->begin; j != draw_tasks_sort->end; j++) { + size_t task_idx = j - draw_tasks_sort->begin; + draw_task* task = *j; + igPushID_Ptr(task); + if (!igTreeNodeEx_StrStr("", tree_node_flags, + "%08x; %8u; %s", draw_task_hashes->begin[task_idx], + draw_task_indices->begin[task_idx], draw_task_type_name[task->type])) { + igPopID(); + continue; + } + + if (igTreeNodeEx_Str("Matrix", ImGuiTreeNodeFlags_DefaultOpen)) { + mat4u* mat = &task->mat; + igText("%9.4f %9.4f %9.4f %9.4f", mat->row0.x, mat->row1.x, mat->row2.x, mat->row3.x); + igText("%9.4f %9.4f %9.4f %9.4f", mat->row0.y, mat->row1.y, mat->row2.y, mat->row3.y); + igText("%9.4f %9.4f %9.4f %9.4f", mat->row0.z, mat->row1.z, mat->row2.z, mat->row3.z); + igText("%9.4f %9.4f %9.4f %9.4f", mat->row0.w, mat->row1.w, mat->row2.w, mat->row3.w); + igTreePop(); + } + + switch (task->type) { + case DRAW_TASK_TYPE_OBJECT: { + if (igTreeNodeEx_Str("Data", ImGuiTreeNodeFlags_DefaultOpen)) { + data_view_draw_task_imgui_draw_object(&task->data.object); + igTreePop(); + } + } break; + case DRAW_TASK_TYPE_PRIMITIVE: { + + } break; + case DRAW_TASK_TYPE_PREPROCESS: { + + } break; + case DRAW_TASK_TYPE_OBJECT_TRANSLUCENT: { + draw_task_object_translucent* object_translucent = &task->data.object_translucent; + for (int32_t l = 0; l < 40 && l < object_translucent->count; l++) { + igPushID_Int(l); + if (igTreeNodeEx_StrStr("", ImGuiTreeNodeFlags_DefaultOpen, "Data %2d", l)) { + data_view_draw_task_imgui_draw_object(object_translucent->objects[l]); + igTreePop(); + } + igPopID(); + } + } break; + } + + igTreePop(); + igPopID(); + } + draw_tasks_sort->end = draw_tasks_sort->begin; + draw_task_hashes->end = draw_task_hashes->begin; + draw_task_indices->end = draw_task_indices->begin; + + igTreePop(); + imguiDisableElementPop(enable); + igPopID(); + } + + data->imgui_focus |= igIsWindowFocused(0); + +End: + igEnd(); +} + +void data_view_draw_task_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void data_view_draw_task_render(class_data* data) { + +} + +bool data_view_draw_task_dispose(class_data* data) { + data_view_draw_task* data_view = data->data; + if (data_view) { + data_view->draw_tasks.end = data_view->draw_tasks.begin; + vector_ptr_draw_task_free(&data_view->draw_tasks, 0); + vector_uint32_t_free(&data_view->draw_task_hashes, 0); + vector_uint32_t_free(&data_view->draw_task_indices, 0); + } + free(data->data); + return true; +} + +static void data_view_draw_task_imgui_draw_object(draw_object* object) { + igText("Mesh Name: %s", object->mesh->name); + igText("Sub Mesh Index: %lld", object->sub_mesh - object->mesh->sub_meshes); +} \ No newline at end of file diff --git a/src/CLOUD/classes/data_view/draw_task.h b/src/CLOUD/classes/data_view/draw_task.h new file mode 100644 index 00000000..50a1eb22 --- /dev/null +++ b/src/CLOUD/classes/data_view/draw_task.h @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool data_view_draw_task_init(class_data* data, render_context* rctx); +extern void data_view_draw_task_imgui(class_data* data); +extern void data_view_draw_task_input(class_data* data); +extern void data_view_draw_task_render(class_data* data); +extern bool data_view_draw_task_dispose(class_data* data); diff --git a/src/CLOUD/Classes/glitter_editor.c b/src/CLOUD/classes/glitter_editor.c similarity index 63% rename from src/CLOUD/Classes/glitter_editor.c rename to src/CLOUD/classes/glitter_editor.c index d839e6ca..d5aa9918 100644 --- a/src/CLOUD/Classes/glitter_editor.c +++ b/src/CLOUD/classes/glitter_editor.c @@ -7,13 +7,14 @@ #if defined(CLOUD_DEV) #include "glitter_editor.h" +#include "../../KKdLib/io/path.h" +#include "../../KKdLib/io/stream.h" #include "../../KKdLib/dds.h" #include "../../KKdLib/interpolation.h" -#include "../../KKdLib/io_path.h" -#include "../../KKdLib/io_stream.h" #include "../../KKdLib/str_utils.h" #include "../../KKdLib/txp.h" #include "../../KKdLib/str_utils.h" +#include "../../KKdLib/vec.h" #include "../../CRE/Glitter/animation.h" #include "../../CRE/Glitter/curve.h" #include "../../CRE/Glitter/diva_effect.h" @@ -23,12 +24,16 @@ #include "../../CRE/Glitter/effect_group.h" #include "../../CRE/Glitter/emitter.h" #include "../../CRE/Glitter/file_reader.h" +#include "../../CRE/Glitter/glitter.h" #include "../../CRE/Glitter/particle.h" #include "../../CRE/Glitter/particle_manager.h" #include "../../CRE/Glitter/scene.h" #include "../../CRE/Glitter/texture.h" #include "../../CRE/camera.h" +#include "../../CRE/data.h" +#include "../../CRE/draw_task.h" #include "../../CRE/gl_state.h" +#include "../../CRE/render_context.h" #include "../../CRE/shader_glsl.h" #include "../../CRE/static_var.h" #include "../input.h" @@ -58,45 +63,9 @@ typedef enum glitter_editor_flags { typedef enum glitter_editor_draw_flags { GLITTER_EDITOR_DRAW_WIREFRAME = 0x01, GLITTER_EDITOR_DRAW_SELECTED = 0x02, + GLITTER_EDITOR_DRAW_NO_DRAW = 0x04, } glitter_editor_draw_flags; -typedef struct glitter_editor_struct { - bool dispose; - bool disposed; - bool test; - bool imgui_focus; - bool create_popup; - bool load; - bool load_popup; - bool load_error_list_popup; - bool save; - bool save_popup; - bool save_compress; - bool close; - bool input_play; - bool input_reload; - bool input_pause; - bool input_reset; - bool effect_group_add; - glitter_editor_draw_flags draw_flags; - glitter_editor_flags resource_flags; - glitter_editor_flags effect_flags; - glitter_editor_flags emitter_flags; - glitter_editor_flags particle_flags; - glitter_type load_glt_type; - glitter_type save_glt_type; - int32_t frame_counter; - int32_t old_frame_counter; - double_t delta_frame; - int32_t start_frame; - int32_t end_frame; - glitter_random random; - int32_t counter; - glitter_effect_group* effect_group; - glitter_scene* scene; - char file[MAX_PATH * 2]; -} glitter_editor_struct; - typedef struct glitter_curve_editor { glitter_curve_type type; glitter_animation* animation; @@ -134,9 +103,57 @@ typedef struct glitter_editor_gl { glitter_editor_gl_wireframe wireframe; } glitter_editor_gl; +typedef struct glitter_editor_struct { + bool test; + bool create_popup; + bool load; + bool load_data; + bool load_popup; + bool load_data_popup; + bool load_error_list_popup; + bool save; + bool save_popup; + bool save_compress; + bool close; + bool input_play; + bool input_reload; + bool input_pause; + bool input_pause_temp; + bool input_reset; + bool effect_group_add; + glitter_editor_draw_flags draw_flags; + glitter_editor_flags resource_flags; + glitter_editor_flags effect_flags; + glitter_editor_flags emitter_flags; + glitter_editor_flags particle_flags; + glitter_type load_glt_type; + glitter_type save_glt_type; + data_type load_data_type; + int32_t frame_counter; + int32_t old_frame_counter; + double_t delta_frame; + int32_t start_frame; + int32_t end_frame; + glitter_random random; + int32_t counter; + glitter_effect_group* effect_group; + glitter_scene* scene; + char file[MAX_PATH * 2]; + GLuint vao; + + glitter_editor_selected_enum selected_type; + int32_t selected_resource; + glitter_effect* selected_effect; + glitter_emitter* selected_emitter; + glitter_particle* selected_particle; + glitter_curve_editor curve_editor; + + glitter_editor_gl gl_data; +} glitter_editor_struct; + static const char* glitter_emitter_direction_name[] = { [GLITTER_EMITTER_DIRECTION_BILLBOARD] = "Billboard", - [GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_ONLY] = "Billboard Y Only", + [GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_AXIS] = "Billboard (Y Axis)", [GLITTER_EMITTER_DIRECTION_X_AXIS] = "X Axis", [GLITTER_EMITTER_DIRECTION_Y_AXIS] = "Y Axis", [GLITTER_EMITTER_DIRECTION_Z_AXIS] = "Z Axis", @@ -145,7 +162,7 @@ static const char* glitter_emitter_direction_name[] = { static const char* glitter_particle_draw_type_name[] = { [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD] = "Billboard", - [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_ONLY] = "Billboard Y Only", + [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_AXIS] = "Billboard (Y Axis)", [GLITTER_PARTICLE_DRAW_TYPE_X_AXIS] = "X Axis", [GLITTER_PARTICLE_DRAW_TYPE_Y_AXIS] = "Y Axis", [GLITTER_PARTICLE_DRAW_TYPE_Z_AXIS] = "Z Axis", @@ -320,163 +337,127 @@ extern vec2i internal_2d_res; extern vec2i internal_3d_res; extern bool input_reset; extern bool input_locked; -extern float_t frame_speed; -extern bool grid_3d; - -extern camera* cam; - -extern GPM; +extern bool draw_grid_3d; extern bool close; extern bool global_context_menu; -const char* glitter_editor_window_title = "Glitter Editor"; +static const char* glitter_editor_window_title = "Glitter Editor"; -bool glitter_editor_enabled; -static glitter_editor_struct glitter_editor; +static void glitter_editor_windows(glitter_editor_struct* glt_edt, class_data* data); -static glitter_editor_selected_enum selected_type; -static int32_t selected_resource; -static glitter_effect* selected_effect; -static glitter_emitter* selected_emitter; -static glitter_particle* selected_particle; -static glitter_curve_editor curve_editor; - -static glitter_editor_gl gl_data; - -static void glitter_editor_windows(); - -static void glitter_editor_reload(); -static void glitter_editor_reset(); +static void glitter_editor_reload(glitter_editor_struct* glt_edt); +static void glitter_editor_reset(glitter_editor_struct* glt_edt); static void glitter_editor_reset_draw(); -static void glitter_editor_save(); -static void glitter_editor_open_window(); -static void glitter_editor_save_window(); -static void glitter_editor_save_as_window(); -static void glitter_editor_load_file(char* path, char* file); -static void glitter_editor_save_file(char* path, char* file); +static void glitter_editor_save(glitter_editor_struct* glt_edt); +static void glitter_editor_open_window(glitter_editor_struct* glt_edt); +static void glitter_editor_save_window(glitter_editor_struct* glt_edt); +static void glitter_editor_save_as_window(glitter_editor_struct* glt_edt); +static void glitter_editor_load_file(glitter_editor_struct* glt_edt, char* path, char* file); +static void glitter_editor_save_file(glitter_editor_struct* glt_edt, char* path, char* file); static bool glitter_editor_list_open_window(glitter_effect_group* eg); -static bool glitter_editor_list_parse(uint8_t* data, size_t length, char** buf, char*** lines, size_t* count); -static bool glitter_editor_resource_import(); -static bool glitter_editor_resource_export(); +static bool glitter_editor_resource_import(glitter_editor_struct* glt_edt); +static bool glitter_editor_resource_export(glitter_editor_struct* glt_edt); -static void glitter_editor_test_window(); -static void glitter_editor_effects(); -static void glitter_editor_effects_context_menu(glitter_effect* effect, - glitter_emitter* emitter, glitter_particle* particle, +static void glitter_editor_test_window(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_effects(glitter_editor_struct* glt_edt); +static void glitter_editor_effects_context_menu(glitter_editor_struct* glt_edt, + glitter_effect* effect, glitter_emitter* emitter, glitter_particle* particle, ssize_t i_idx, ssize_t j_idx, ssize_t k_idx, glitter_editor_selected_enum type); -static void glitter_editor_resources(); -static void glitter_editor_resources_context_menu(int32_t resource, - ssize_t i_idx, bool selected_none); -static void glitter_editor_play_manager(); -static void glitter_editor_property(); -static void glitter_editor_property_effect(); -static void glitter_editor_property_emitter(); -static void glitter_editor_property_particle(); -static bool glitter_editor_property_particle_texture(char* label, char** items, - glitter_particle* particle, int32_t* tex, uint64_t* tex_hash, int32_t texture, - bool* tex_anim, int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex); +static void glitter_editor_resources(glitter_editor_struct* glt_edt); +static void glitter_editor_resources_context_menu(glitter_editor_struct* glt_edt, + int32_t resource, ssize_t i_idx, bool selected_none); +static void glitter_editor_play_manager(glitter_editor_struct* glt_edt); +static void glitter_editor_property(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_property_emitter(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_property_particle(glitter_editor_struct* glt_edt, class_data* data); +static bool glitter_editor_property_particle_texture(glitter_editor_struct* glt_edt, + class_data* data, char* label, char** items, glitter_particle* particle, + int32_t* tex, uint64_t* tex_hash, int32_t tex_idx, bool* tex_anim, + int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex); -static void glitter_editor_popups(); -static void glitter_editor_file_create_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size); -static void glitter_editor_file_load_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size); -static void glitter_editor_file_load_error_list_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size); -static void glitter_editor_file_save_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size); +static void glitter_editor_popups(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_file_create_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size); +static void glitter_editor_file_load_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size); +static void glitter_editor_file_load_model_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size); +static void glitter_editor_file_load_error_list_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size); +static void glitter_editor_file_save_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size); -static void glitter_editor_curve_editor(); -static void glitter_editor_curve_editor_curve_reset(glitter_curve* curve); -static void glitter_editor_curve_editor_curve_set(glitter_curve* curve, glitter_curve_type type); -static void glitter_editor_curve_editor_curves_reset(); -static glitter_curve_key* glitter_editor_curve_editor_get_selected_key(glitter_curve* curve); -static void glitter_editor_curve_editor_key_manager(vector_glitter_curve_key* keys, - bool* add_key, bool* del_key); -static void glitter_editor_curve_editor_property_window(); -static void glitter_editor_curve_editor_reset_state(glitter_curve_type type); -static void glitter_editor_curve_editor_selector(); +static void glitter_editor_curve_editor(glitter_editor_struct* glt_edt); +static void glitter_editor_curve_editor_curve_reset(glitter_editor_struct* glt_edt, + glitter_curve* curve); +static void glitter_editor_curve_editor_curve_set(glitter_editor_struct* glt_edt, + glitter_curve* curve, glitter_curve_type type); +static void glitter_editor_curve_editor_curves_reset(glitter_editor_struct* glt_edt); +static glitter_curve_key* glitter_editor_curve_editor_get_closest_key(glitter_editor_struct* glt_edt, + glitter_curve* curve); +static glitter_curve_key* glitter_editor_curve_editor_get_selected_key(glitter_editor_struct* glt_edt, + glitter_curve* curve); +static float_t glitter_editor_curve_editor_get_value(glitter_editor_struct* glt_edt, + glitter_curve_type type); +static void glitter_editor_curve_editor_key_manager(glitter_editor_struct* glt_edt, + vector_glitter_curve_key* keys, bool* add_key, bool* del_key); +static void glitter_editor_curve_editor_property_window(glitter_editor_struct* glt_edt, class_data* data); +static void glitter_editor_curve_editor_reset_state(glitter_editor_struct* glt_edt, + glitter_curve_type type); +static void glitter_editor_curve_editor_selector(glitter_editor_struct* glt_edt, class_data* data); -static void glitter_editor_gl_load(); -static void glitter_editor_gl_draw(); -static void glitter_editor_gl_process(); -static void glitter_editor_gl_free(); +static void glitter_editor_gl_load(glitter_editor_struct* glt_edt); +static void glitter_editor_gl_draw(glitter_editor_struct* glt_edt); +static void glitter_editor_gl_process(glitter_editor_struct* glt_edt); +static void glitter_editor_gl_free(glitter_editor_struct* glt_edt); -static void glitter_editor_gl_draw_wireframe(); -static size_t glitter_editor_gl_draw_wireframe_calc(glitter_effect_inst* eff, - glitter_particle_inst* ptcl); -static void glitter_editor_gl_draw_wireframe_draw(glitter_effect_inst* eff, - glitter_particle_inst* ptcl); +static void glitter_editor_gl_draw_wireframe(glitter_editor_struct* glt_edt); +static size_t glitter_editor_gl_draw_wireframe_calc(glitter_editor_struct* glt_edt, + glitter_effect_inst* eff, glitter_particle_inst* ptcl); +static void glitter_editor_gl_draw_wireframe_draw(glitter_editor_struct* glt_edt, + glitter_effect_inst* eff, glitter_particle_inst* ptcl); +static void glitter_editor_gl_draw_wireframe_draw_mesh(glitter_editor_struct* glt_edt, + glitter_render_group* rg); -static void glitter_editor_gl_select_particle(); +static void glitter_editor_gl_select_particle(glitter_editor_struct* glt_edt); -static bool glitter_editor_hash_input(const char* label, uint64_t* hash); +static bool glitter_editor_hash_input(glitter_editor_struct* glt_edt, + const char* label, uint64_t* hash); -void glitter_editor_dispose() { - glitter_editor_gl_free(); +bool glitter_editor_init(class_data* data, render_context* rctx) { + if (!lock_data_init(&glitter_data_lock, &data->lock, data, glitter_editor_dispose)) + return false; - vector_ptr_glitter_scene_free(&GPM_VAL->scenes, glitter_scene_dispose); - vector_ptr_glitter_effect_group_free(&GPM_VAL->effect_groups, glitter_effect_group_dispose); - - glitter_editor_enabled = false; - glitter_editor.test = false; - glitter_editor.imgui_focus = false; - glitter_editor.create_popup = false; - glitter_editor.load = false; - glitter_editor.load_popup = false; - glitter_editor.load_error_list_popup = false; - glitter_editor.save = false; - glitter_editor.save_popup = false; - glitter_editor.save_compress = false; - glitter_editor.close = false; - glitter_editor.input_play = false; - glitter_editor.input_reload = false; - glitter_editor.input_pause = true; - glitter_editor.input_reset = false; - glitter_editor.effect_group_add = false; - glitter_editor.draw_flags = 0; - glitter_editor.resource_flags = 0; - glitter_editor.effect_flags = 0; - glitter_editor.emitter_flags = 0; - glitter_editor.particle_flags = 0; - glitter_editor.frame_counter = 0; - glitter_editor.old_frame_counter = 0; - glitter_editor.delta_frame = 0.0; - glitter_editor.start_frame = 0; - glitter_editor.end_frame = 0; - glitter_editor.random.value = 0; - glitter_editor.random.step = 1; - glitter_editor.counter = 0; - glitter_editor.effect_group = 0; - glitter_editor.scene = 0; - memset(glitter_editor.file, 0, sizeof(glitter_editor.file)); - glitter_editor.dispose = false; - glitter_editor.disposed = true; -} - -void glitter_editor_init() { - if (glitter_editor_enabled || glitter_editor.dispose) - glitter_editor_dispose(); + bool ret = false; + lock_trylock(&pv_lock); + data->data = force_malloc(sizeof(glitter_editor_struct)); LARGE_INTEGER time; QueryPerformanceCounter(&time); - GPM_VAL->random.value = (uint32_t)(time.LowPart * hash_fnv1a64_empty); + GPM_VAL->random.value = (uint32_t)(time.LowPart * hash_fnv1a64m_empty); GPM_VAL->random.step = 1; QueryPerformanceCounter(&time); GPM_VAL->counter = (uint32_t)(time.LowPart * hash_murmurhash_empty); - glitter_editor_enabled = true; - glitter_editor.test = false; - glitter_editor.draw_flags = 0; - GPM_VAL->emission = 1.0f; - GPM_VAL->draw_all = true; - GPM_VAL->draw_all_mesh = true; - grid_3d = true; - glitter_editor_reset(); - glitter_editor_gl_load(); + glitter_editor_struct* glt_edt = data->data; + if (glt_edt) { + glt_edt->test = false; + glt_edt->draw_flags = 0; + GPM_VAL->emission = 1.0f; + GPM_VAL->draw_all = true; + GPM_VAL->draw_all_mesh = true; + glGenVertexArrays(1, &glt_edt->vao); + draw_grid_3d = true; + + glitter_editor_reset(glt_edt); + glitter_editor_gl_load(glt_edt); + } + ret = true; + lock_unlock(&pv_lock); /*char* path_x = "VRFL\\"; vector_string files_x = vector_empty(string); @@ -502,10 +483,18 @@ void glitter_editor_init() { char* buf; char** lines; size_t count; - if (glitter_editor_list_parse(data, length, &buf, &lines, &count)) { + if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) { + for (size_t i = 0; i < count; i++) { + char* t = strstr(lines[i], "#(?)"); + if (t) + *t = 0; + } + uint64_t* hashes = force_malloc_s(uint64_t, count); - for (size_t i = 0; i < count; i++) - hashes[i] = hash_murmurhash(lines[i], min(utf8_length(lines[i]), 0x7F), 0, false, false); + for (size_t i = 0; i < count; i++) { + size_t len = utf8_length(lines[i]); + hashes[i] = hash_murmurhash(lines[i], min(len, 0x7F), 0, false, false); + } for (ssize_t i = 0; i < c; i++) { char* file_x = str_utils_get_without_extension(string_data(&files_x.begin[i])); @@ -514,7 +503,7 @@ void glitter_editor_init() { sprintf_s(buf, 0x100, "%hs\n", file_x); OutputDebugStringA(buf); - glitter_editor.load_glt_type = GLITTER_X; + glt_edt->load_glt_type = GLITTER_X; fr = glitter_file_reader_init(GLITTER_X, path_x, file_x, 1.0f); glitter_file_reader_read(fr, GPM_VAL->emission); @@ -553,7 +542,7 @@ void glitter_editor_init() { string_free(i); vector_string_free(&files_x); glitter_file_reader_dispose(fr); - glitter_editor.effect_group = 0; + glt_edt->effect_group = 0; return;*/ /*char* path_x = "X\\"; @@ -577,7 +566,7 @@ void glitter_editor_init() { sprintf_s(buf, 0x100, "%hs\n", file_x); OutputDebugStringA(buf); - glitter_editor.load_glt_type = GLITTER_X; + glt_edt->load_glt_type = GLITTER_X; fr = glitter_file_reader_init(GLITTER_X, path_x, file_x, 1.0f); glitter_file_reader_read(fr, GPM_VAL->emission); @@ -607,15 +596,15 @@ void glitter_editor_init() { string_free(i); vector_string_free(&files_x); glitter_file_reader_dispose(fr); - glitter_editor.effect_group = 0; + glt_edt->effect_group = 0; return;*/ /*char* path_f2 = "F2\\"; - char* path_aft = "AFT\\"; + char* path_ft = "AFT\\"; vector_string files_f2 = vector_empty(string); - vector_string files_aft = vector_empty(string); + vector_string files_ft = vector_empty(string); path_get_files(&files_f2, path_f2); - path_get_files(&files_aft, path_aft); + path_get_files(&files_ft, path_ft); for (string* i = files_f2.begin; i != files_f2.end;) if (str_utils_check_ends_with(string_data(i), ".farc")) i++; @@ -624,16 +613,16 @@ void glitter_editor_init() { vector_string_erase(&files_f2, i - files_f2.begin); } - for (string* i = files_aft.begin; i != files_aft.end;) + for (string* i = files_ft.begin; i != files_ft.end;) if (str_utils_check_ends_with(string_data(i), ".farc")) i++; else { string_free(i); - vector_string_erase(&files_aft, i - files_aft.begin); + vector_string_erase(&files_ft, i - files_ft.begin); } stream s; - io_wopen(&s, L"name_F2nd.glitter.txt", L"rb"); + io_wopen(&s, L"name_F2.glitter.txt", L"rb"); size_t length = s.length; uint8_t* data = force_malloc(length); io_read(&s, data, length); @@ -642,18 +631,26 @@ void glitter_editor_init() { char* buf; char** lines; size_t count; - if (glitter_editor_list_parse(data, length, &buf, &lines, &count)) { + if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) { + for (size_t i = 0; i < count; i++) { + char* t = strstr(lines[i], "#(?)"); + if (t) + *t = 0; + } + uint64_t* hashes = force_malloc_s(uint64_t, count); - for (size_t i = 0; i < count; i++) - hashes[i] = hash_murmurhash(lines[i], min(utf8_length(lines[i]), 0x7F), 0, false, false); + for (size_t i = 0; i < count; i++) { + size_t len = utf8_length(lines[i]); + hashes[i] = hash_murmurhash(lines[i], min(len, 0x7F), 0, false, false); + } ssize_t c = files_f2.end - files_f2.begin; glitter_file_reader* fr = 0; - if (files_f2.begin && files_aft.begin) + if (files_f2.begin && files_ft.begin) for (ssize_t i = 0; i < c; i++) { char* file_f2 = str_utils_get_without_extension(string_data(&files_f2.begin[i])); - char* file_aft = str_utils_get_without_extension(string_data(&files_aft.begin[i])); - glitter_editor.load_glt_type = GLITTER_F2; + char* file_ft = str_utils_get_without_extension(string_data(&files_ft.begin[i])); + glt_edt->load_glt_type = GLITTER_F2; fr = glitter_file_reader_init(GLITTER_F2, path_f2, file_f2, 1.0f); glitter_file_reader_read(fr, GPM_VAL->emission); @@ -675,16 +672,18 @@ void glitter_editor_init() { if (j == count) break; - memcpy(e->name, lines[j], min(utf8_length(lines[j]), 0x7F)); + + size_t len = utf8_length(lines[j]); + memcpy(e->name, lines[j], min(len, 0x7F)); } - glitter_editor.effect_group = fr->effect_group; - //glitter_editor.save_glt_type = GLITTER_AFT; - //glitter_editor_save_file(path_aft, file_aft); + glt_edt->effect_group = fr->effect_group; + //glt_edt->save_glt_type = GLITTER_FT; + //glitter_editor_save_file(path_ft, file_ft); glitter_effect_group_dispose(fr->effect_group); } free(file_f2); - free(file_aft); + free(file_ft); } glitter_file_reader_dispose(fr); @@ -696,139 +695,139 @@ void glitter_editor_init() { string_free(i); vector_string_free(&files_f2); - for (string* i = files_aft.begin; i != files_aft.end; i++) + for (string* i = files_ft.begin; i != files_ft.end; i++) string_free(i); - vector_string_free(&files_aft); + vector_string_free(&files_ft); free(data); - glitter_editor.effect_group = 0;*/ + glt_edt->effect_group = 0;*/ + return ret; } -void glitter_editor_draw() { - glitter_editor_gl_draw(); +void glitter_editor_draw(class_data* data) { + glitter_editor_struct* glt_edt = data->data; + if (!glt_edt) + return; + + glitter_editor_gl_draw(glt_edt); } -void glitter_editor_drop(size_t count, char** paths) { - if (!glitter_editor_enabled) +void glitter_editor_drop(class_data* data, size_t count, char** paths) { + glitter_editor_struct* glt_edt = data->data; + if (!glt_edt) return; - if (count < 1 || !paths[0]) - return; - - size_t c = min(utf8_length(paths[0]), sizeof(glitter_editor.file) - 1); - memcpy(glitter_editor.file, paths[0], c); - glitter_editor.file[c] = 0; - glitter_editor.load_popup = true; + size_t c = min(utf8_length(paths[0]), sizeof(glt_edt->file) - 1); + memcpy(glt_edt->file, paths[0], c); + glt_edt->file[c] = 0; + glt_edt->load_popup = true; } -void glitter_editor_imgui() { - if (!glitter_editor_enabled) { - if (!glitter_editor.disposed) - glitter_editor.dispose = true; +void glitter_editor_imgui(class_data* data) { + glitter_editor_struct* glt_edt = data->data; + if (!glt_edt) return; - } - else if (glitter_editor.disposed) { - glitter_editor_enabled = false; - glitter_editor.disposed = false; - return; - } - glitter_editor.imgui_focus = false; - if (glitter_editor.test) - glitter_editor_test_window(); + data->imgui_focus = false; + if (glt_edt->test) + glitter_editor_test_window(glt_edt, data); else - glitter_editor_windows(); - glitter_editor_popups(); + glitter_editor_windows(glt_edt, data); + glitter_editor_popups(glt_edt, data); } -void glitter_editor_input() { - if (!glitter_editor_enabled) +void glitter_editor_input(class_data* data) { + input_locked |= data->imgui_focus; + + if (igGetIO()->WantTextInput) return; - input_locked |= glitter_editor.imgui_focus; - - bool ret = false; - if (igGetIO()->WantTextInput) - ret = true; - - if (ret) + glitter_editor_struct* glt_edt = data->data; + if (!glt_edt) return; if (input_is_down(VK_CONTROL) && input_is_tapped('O')) - glitter_editor_open_window(); + glitter_editor_open_window(glt_edt); else if (input_is_down(VK_CONTROL) && input_is_tapped(VK_F4)) - glitter_editor.close = true; + glt_edt->close = true; + else if (input_is_down(VK_CONTROL) && input_is_tapped(VK_F3)) + data->flags |= CLASS_DISPOSE; + else if (input_is_down(VK_CONTROL) && input_is_tapped('Q')) + close = true; else if (input_is_tapped('P')) - glitter_editor.test ^= true; + glt_edt->test ^= true; else if (input_is_tapped('T')) - glitter_editor.input_play = true; + glt_edt->input_play = true; else if (input_is_tapped('Y')) - glitter_editor.input_reload = true; + glt_edt->input_reload = true; else if (input_is_tapped('F')) - glitter_editor.input_pause = true; + glt_edt->input_pause = true; else if (input_is_tapped('G')) - glitter_editor.input_reset = true; + glt_edt->input_reset = true; - if (glitter_editor.imgui_focus) { + if (data->imgui_focus) { if (input_is_down(VK_CONTROL) && input_is_down(VK_SHIFT) && input_is_tapped('S')) - glitter_editor_save_as_window(); + glitter_editor_save_as_window(glt_edt); else if (input_is_down(VK_CONTROL) && input_is_tapped('S')) - glitter_editor_save_window(); + glitter_editor_save_window(glt_edt); } } -void glitter_editor_render() { - if (glitter_editor.dispose) { - glitter_editor_dispose(); - return; - } - else if (!glitter_editor_enabled) +void glitter_editor_render(class_data* data) { + glitter_editor_struct* glt_edt = data->data; + if (!glt_edt) return; - if (glitter_editor.effect_group_add) { + int32_t sel_rsrc = glt_edt->selected_resource; + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_emitter* sel_emit = glt_edt->selected_emitter; + glitter_particle* sel_ptcl = glt_edt->selected_particle; + + if (glt_edt->effect_group_add) { glitter_editor_reset_draw(); - glitter_editor.effect_group = glitter_effect_group_init(glitter_editor.load_glt_type); - vector_ptr_glitter_effect_group_push_back(&GPM_VAL->effect_groups, &glitter_editor.effect_group); + glt_edt->effect_group = glitter_effect_group_init(glt_edt->load_glt_type); + vector_ptr_glitter_effect_group_push_back(&GPM_VAL->effect_groups, + &glt_edt->effect_group); } - bool has_resource = selected_resource != -1; - bool has_effect = selected_effect != 0; - bool has_emitter = selected_emitter != 0 && has_effect; - bool has_particle = selected_particle != 0 && has_emitter; - glitter_effect_group* eg = glitter_editor.effect_group; + bool has_resource = sel_rsrc != -1; + bool has_effect = glt_edt->selected_effect != 0; + bool has_emitter = glt_edt->selected_emitter != 0 && has_effect; + bool has_particle = glt_edt->selected_particle != 0 && has_emitter; + glitter_effect_group* eg = glt_edt->effect_group; bool tex_reload = false; - if (glitter_editor.resource_flags & GLITTER_EDITOR_IMPORT) - if (glitter_editor_resource_import()) + if (glt_edt->resource_flags & GLITTER_EDITOR_IMPORT) + if (glitter_editor_resource_import(glt_edt)) tex_reload = true; - if (has_resource) { - if (glitter_editor.resource_flags & GLITTER_EDITOR_EXPORT) - glitter_editor_resource_export(); - else if (glitter_editor.resource_flags & GLITTER_EDITOR_DELETE) { + if (eg && has_resource) { + if (glt_edt->resource_flags & GLITTER_EDITOR_EXPORT) + glitter_editor_resource_export(glt_edt); + else if (glt_edt->resource_flags & GLITTER_EDITOR_DELETE) { size_t rc = eg->resources_count; ssize_t j = -1; for (size_t i = 0; i < rc; i++) - if (i == selected_resource) { + if (i == sel_rsrc) { j = i; break; } if (j > -1) { uint64_t hash = eg->resource_hashes.begin[j]; - txp_free(&eg->resources_tex.begin[j]); - vector_uint64_t_erase(&eg->resource_hashes, j); - vector_txp_erase(&eg->resources_tex, j); + vector_uint64_t_erase(&eg->resource_hashes, j, 0); + vector_txp_erase(&eg->resources_tex, j, txp_free); eg->resources_count--; - uint64_t empty_hash = eg->type != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + uint64_t empty_hash = eg->type != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { if (!*i) continue; glitter_effect* effect = *i; - for (glitter_emitter** j = effect->emitters.begin; j != effect->emitters.end; j++) { + for (glitter_emitter** j = effect->emitters.begin; + j != effect->emitters.end; j++) { if (!*j) continue; @@ -852,63 +851,63 @@ void glitter_editor_render() { } } } - selected_resource = -1; + glt_edt->selected_resource = -1; tex_reload = true; } - else if (glitter_editor.resource_flags & GLITTER_EDITOR_MOVE_UP) { + else if (glt_edt->resource_flags & GLITTER_EDITOR_MOVE_UP) { size_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; txp* rt = eg->resources_tex.begin; ssize_t j = -1; for (size_t i = 0; i < rc; i++) - if (i == selected_resource) { + if (i == sel_rsrc) { j = i; break; } if (j > 0) { uint64_t temp_hash = rh[j - 1]; - txp temp_txp = rt[j - 1]; + txp temp_tex = rt[j - 1]; rh[j - 1] = rh[j]; rt[j - 1] = rt[j]; rh[j] = temp_hash; - rt[j] = temp_txp; - glitter_editor.input_reload = true; + rt[j] = temp_tex; + glt_edt->input_reload = true; } tex_reload = true; } - else if (glitter_editor.resource_flags & GLITTER_EDITOR_MOVE_DOWN) { + else if (glt_edt->resource_flags & GLITTER_EDITOR_MOVE_DOWN) { size_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; txp* rt = eg->resources_tex.begin; ssize_t j = -1; for (size_t i = 0; i < rc; i++) - if (i == selected_resource) { + if (i == sel_rsrc) { j = i; break; } if (j > -1 && j < (ssize_t)rc - 1) { uint64_t temp_hash = rh[j + 1]; - txp temp_txp = rt[j + 1]; + txp temp_tex = rt[j + 1]; rh[j + 1] = rh[j]; rt[j + 1] = rt[j]; rh[j] = temp_hash; - rt[j] = temp_txp; - glitter_editor.input_reload = true; + rt[j] = temp_tex; + glt_edt->input_reload = true; } tex_reload = true; } } - if (tex_reload && glitter_editor.effect_group) { - glitter_texture_load(glitter_editor.effect_group); - glitter_editor.input_reload = true; + if (tex_reload && glt_edt->effect_group) { + glitter_texture_load(GPM_VAL, glt_edt->effect_group); + glt_edt->input_reload = true; } - if (eg && glitter_editor.effect_flags & GLITTER_EDITOR_ADD) { + if (eg && glt_edt->effect_flags & GLITTER_EDITOR_ADD) { ssize_t eff_count = eg->effects.end - eg->effects.begin; LARGE_INTEGER time; @@ -918,48 +917,48 @@ void glitter_editor_render() { snprintf(e->name, sizeof(e->name), "eff_%08x", (uint32_t)((eff_count + 1) * time.LowPart * hash_murmurhash_empty)); vector_ptr_glitter_effect_push_back(&eg->effects, &e); - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } - if (has_effect) - if (glitter_editor.effect_flags & GLITTER_EDITOR_DUPLICATE) { + if (eg && has_effect) + if (glt_edt->effect_flags & GLITTER_EDITOR_DUPLICATE) { ssize_t eff_count = eg->effects.end - eg->effects.begin; LARGE_INTEGER time; QueryPerformanceCounter(&time); - glitter_effect* e = glitter_effect_copy(selected_effect); + glitter_effect* e = glitter_effect_copy(glt_edt->selected_effect); snprintf(e->name, sizeof(e->name), "eff_%08x", (uint32_t)((eff_count + 1) * time.LowPart * hash_murmurhash_empty)); vector_ptr_glitter_effect_push_back(&eg->effects, &e); - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } - else if ((glitter_editor.effect_flags & GLITTER_EDITOR_DELETE)) { + else if ((glt_edt->effect_flags & GLITTER_EDITOR_DELETE)) { ssize_t j = -1; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) - if (*i && *i == selected_effect) { + if (*i && *i == glt_edt->selected_effect) { j = i - eg->effects.begin; break; } if (j > -1) vector_ptr_glitter_effect_erase(&eg->effects, j, glitter_effect_dispose); - selected_type = GLITTER_EDITOR_SELECTED_NONE; - selected_resource = -1; - selected_effect = 0; - selected_emitter = 0; - selected_particle = 0; + glt_edt->selected_type = GLITTER_EDITOR_SELECTED_NONE; + glt_edt->selected_resource = -1; + glt_edt->selected_effect = 0; + glt_edt->selected_emitter = 0; + glt_edt->selected_particle = 0; if (eg->effects.end - eg->effects.begin < 1) - glitter_editor.close = true; + glt_edt->close = true; else - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } - else if (glitter_editor.effect_flags & GLITTER_EDITOR_MOVE_UP) { + else if (glt_edt->effect_flags & GLITTER_EDITOR_MOVE_UP) { ssize_t j = -1; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) - if (*i == selected_effect) { + if (*i == glt_edt->selected_effect) { j = i - eg->effects.begin; break; } @@ -968,14 +967,14 @@ void glitter_editor_render() { glitter_effect* temp = eg->effects.begin[j - 1]; eg->effects.begin[j - 1] = eg->effects.begin[j]; eg->effects.begin[j] = temp; - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } } - else if (glitter_editor.effect_flags & GLITTER_EDITOR_MOVE_DOWN) { + else if (glt_edt->effect_flags & GLITTER_EDITOR_MOVE_DOWN) { ssize_t j = -1; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) - if (*i == selected_effect) { + if (*i == glt_edt->selected_effect) { j = i - eg->effects.begin; break; } @@ -984,249 +983,396 @@ void glitter_editor_render() { glitter_effect* temp = eg->effects.begin[j + 1]; eg->effects.begin[j + 1] = eg->effects.begin[j]; eg->effects.begin[j] = temp; - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } } - else if (glitter_editor.emitter_flags & GLITTER_EDITOR_ADD) { + else if (glt_edt->emitter_flags & GLITTER_EDITOR_ADD) { glitter_emitter* e = glitter_emitter_init(eg->type); - vector_ptr_glitter_emitter_push_back(&selected_effect->emitters, &e); - glitter_editor.input_reload = true; + vector_ptr_glitter_emitter_push_back(&sel_efct->emitters, &e); + glt_edt->input_reload = true; } - if (has_emitter) - if (glitter_editor.emitter_flags & GLITTER_EDITOR_DUPLICATE) { - glitter_emitter* e = glitter_emitter_copy(selected_emitter); - vector_ptr_glitter_emitter_push_back(&selected_effect->emitters, &e); - glitter_editor.input_reload = true; + if (eg && has_emitter) + if (glt_edt->emitter_flags & GLITTER_EDITOR_DUPLICATE) { + glitter_emitter* e = glitter_emitter_copy(glt_edt->selected_emitter); + vector_ptr_glitter_emitter_push_back(&sel_efct->emitters, &e); + glt_edt->input_reload = true; } - else if (glitter_editor.emitter_flags & GLITTER_EDITOR_DELETE) { + else if (glt_edt->emitter_flags & GLITTER_EDITOR_DELETE) { ssize_t j = -1; - for (glitter_emitter** i = selected_effect->emitters.begin; - i != selected_effect->emitters.end; i++) - if (*i && *i == selected_emitter) { - j = i - selected_effect->emitters.begin; + for (glitter_emitter** i = sel_efct->emitters.begin; + i != sel_efct->emitters.end; i++) + if (*i && *i == glt_edt->selected_emitter) { + j = i - sel_efct->emitters.begin; break; } if (j > -1) - vector_ptr_glitter_emitter_erase(&selected_effect->emitters, j, glitter_emitter_dispose); - selected_type = GLITTER_EDITOR_SELECTED_EFFECT; - selected_emitter = 0; - selected_particle = 0; - glitter_editor.input_reload = true; + vector_ptr_glitter_emitter_erase(&sel_efct->emitters, + j, glitter_emitter_dispose); + glt_edt->selected_type = GLITTER_EDITOR_SELECTED_EFFECT; + glt_edt->selected_emitter = 0; + glt_edt->selected_particle = 0; + glt_edt->input_reload = true; } - else if (glitter_editor.emitter_flags & GLITTER_EDITOR_MOVE_UP) { + else if (glt_edt->emitter_flags & GLITTER_EDITOR_MOVE_UP) { ssize_t j = -1; - for (glitter_emitter** i = selected_effect->emitters.begin; - i != selected_effect->emitters.end; i++) - if (*i == selected_emitter) { - j = i - selected_effect->emitters.begin; + for (glitter_emitter** i = sel_efct->emitters.begin; + i != sel_efct->emitters.end; i++) + if (*i == glt_edt->selected_emitter) { + j = i - sel_efct->emitters.begin; break; } if (j > 0) { - glitter_emitter* temp = selected_effect->emitters.begin[j - 1]; - selected_effect->emitters.begin[j - 1] = selected_effect->emitters.begin[j]; - selected_effect->emitters.begin[j] = temp; - glitter_editor.input_reload = true; + glitter_emitter* temp = sel_efct->emitters.begin[j - 1]; + sel_efct->emitters.begin[j - 1] + = sel_efct->emitters.begin[j]; + sel_efct->emitters.begin[j] = temp; + glt_edt->input_reload = true; } } - else if (glitter_editor.emitter_flags & GLITTER_EDITOR_MOVE_DOWN) { + else if (glt_edt->emitter_flags & GLITTER_EDITOR_MOVE_DOWN) { ssize_t j = -1; - for (glitter_emitter** i = selected_effect->emitters.begin; - i != selected_effect->emitters.end; i++) - if (*i == selected_emitter) { - j = i - selected_effect->emitters.begin; + for (glitter_emitter** i = sel_efct->emitters.begin; + i != sel_efct->emitters.end; i++) + if (*i == glt_edt->selected_emitter) { + j = i - sel_efct->emitters.begin; break; } - if (j > -1 && j < selected_effect->emitters.end - selected_effect->emitters.begin - 1) { - glitter_emitter* temp = selected_effect->emitters.begin[j + 1]; - selected_effect->emitters.begin[j + 1] = selected_effect->emitters.begin[j]; - selected_effect->emitters.begin[j] = temp; - glitter_editor.input_reload = true; + if (j > -1 && j < sel_efct->emitters.end + - sel_efct->emitters.begin - 1) { + glitter_emitter* temp = sel_efct->emitters.begin[j + 1]; + sel_efct->emitters.begin[j + 1] + = sel_efct->emitters.begin[j]; + sel_efct->emitters.begin[j] = temp; + glt_edt->input_reload = true; } } - else if (glitter_editor.particle_flags & GLITTER_EDITOR_ADD) { + else if (glt_edt->particle_flags & GLITTER_EDITOR_ADD) { glitter_particle* p = glitter_particle_init(eg->type); - vector_ptr_glitter_particle_push_back(&selected_emitter->particles, &p); - glitter_editor.input_reload = true; + vector_ptr_glitter_particle_push_back(&sel_emit->particles, &p); + glt_edt->input_reload = true; } - if (has_particle) - if (glitter_editor.particle_flags & GLITTER_EDITOR_DUPLICATE) { - glitter_particle* p = glitter_particle_copy(selected_particle); - vector_ptr_glitter_particle_push_back(&selected_emitter->particles, &p); - glitter_editor.input_reload = true; + if (eg && has_particle) + if (glt_edt->particle_flags & GLITTER_EDITOR_DUPLICATE) { + glitter_particle* p = glitter_particle_copy(glt_edt->selected_particle); + vector_ptr_glitter_particle_push_back(&sel_emit->particles, &p); + glt_edt->input_reload = true; } - else if (glitter_editor.particle_flags & GLITTER_EDITOR_DELETE) { + else if (glt_edt->particle_flags & GLITTER_EDITOR_DELETE) { ssize_t j = (ssize_t)-1; - for (glitter_particle** i = selected_emitter->particles.begin; - i != selected_emitter->particles.end; i++) - if (*i && *i == selected_particle) { - j = i - selected_emitter->particles.begin; + for (glitter_particle** i = sel_emit->particles.begin; + i != sel_emit->particles.end; i++) + if (*i && *i == glt_edt->selected_particle) { + j = i - sel_emit->particles.begin; break; } if (j > -1) - vector_ptr_glitter_particle_erase(&selected_emitter->particles, j, glitter_particle_dispose); - selected_type = GLITTER_EDITOR_SELECTED_EMITTER; - selected_particle = 0; - glitter_editor.input_reload = true; + vector_ptr_glitter_particle_erase(&sel_emit->particles, + j, glitter_particle_dispose); + glt_edt->selected_type = GLITTER_EDITOR_SELECTED_EMITTER; + glt_edt->selected_particle = 0; + glt_edt->input_reload = true; } - else if (glitter_editor.particle_flags & GLITTER_EDITOR_MOVE_UP) { + else if (glt_edt->particle_flags & GLITTER_EDITOR_MOVE_UP) { ssize_t j = -1; - for (glitter_particle** i = selected_emitter->particles.begin; - i != selected_emitter->particles.end; i++) - if (*i == selected_particle) { - j = i - selected_emitter->particles.begin; + for (glitter_particle** i = sel_emit->particles.begin; + i != sel_emit->particles.end; i++) + if (*i == glt_edt->selected_particle) { + j = i - sel_emit->particles.begin; break; } if (j > 0) { - glitter_particle* temp = selected_emitter->particles.begin[j - 1]; - selected_emitter->particles.begin[j - 1] = selected_emitter->particles.begin[j]; - selected_emitter->particles.begin[j] = temp; - glitter_editor.input_reload = true; + glitter_particle* temp = sel_emit->particles.begin[j - 1]; + sel_emit->particles.begin[j - 1] + = sel_emit->particles.begin[j]; + sel_emit->particles.begin[j] = temp; + glt_edt->input_reload = true; } } - else if (glitter_editor.particle_flags & GLITTER_EDITOR_MOVE_DOWN) { + else if (glt_edt->particle_flags & GLITTER_EDITOR_MOVE_DOWN) { ssize_t j = -1; - for (glitter_particle** i = selected_emitter->particles.begin; - i != selected_emitter->particles.end; i++) - if (*i == selected_particle) { - j = i - selected_emitter->particles.begin; + for (glitter_particle** i = sel_emit->particles.begin; + i != sel_emit->particles.end; i++) + if (*i == glt_edt->selected_particle) { + j = i - sel_emit->particles.begin; break; } - if (j > -1 && j < selected_emitter->particles.end - selected_emitter->particles.begin - 1) { - glitter_particle* temp = selected_emitter->particles.begin[j + 1]; - selected_emitter->particles.begin[j + 1] = selected_emitter->particles.begin[j]; - selected_emitter->particles.begin[j] = temp; - glitter_editor.input_reload = true; + if (j > -1 && j < sel_emit->particles.end + - sel_emit->particles.begin - 1) { + glitter_particle* temp = sel_emit->particles.begin[j + 1]; + sel_emit->particles.begin[j + 1] + = sel_emit->particles.begin[j]; + sel_emit->particles.begin[j] = temp; + glt_edt->input_reload = true; } } - glitter_editor.effect_group_add = false; - glitter_editor.resource_flags = 0; - glitter_editor.effect_flags = 0; - glitter_editor.emitter_flags = 0; - glitter_editor.particle_flags = 0; + glt_edt->effect_group_add = false; + glt_edt->resource_flags = 0; + glt_edt->effect_flags = 0; + glt_edt->emitter_flags = 0; + glt_edt->particle_flags = 0; - if (glitter_editor.load || glitter_editor.save) { - char* file = str_utils_get_without_extension(glitter_editor.file); - char* path = str_utils_split_right_get_left_include(glitter_editor.file, '\\'); + if (glt_edt->load || glt_edt->save) { + char* file = str_utils_get_without_extension(glt_edt->file); + char* path = str_utils_split_right_get_left_include(glt_edt->file, '\\'); - if (glitter_editor.load) - glitter_editor_load_file(path, file); - else if (glitter_editor.save && glitter_editor.effect_group) - glitter_editor_save_file(path, file); + if (glt_edt->load) + glitter_editor_load_file(glt_edt, path, file); + else if (glt_edt->save && glt_edt->effect_group) + glitter_editor_save_file(glt_edt, path, file); - glitter_editor.load = false; - glitter_editor.save = false; - glitter_editor.save_compress = false; + glt_edt->load = false; + glt_edt->save = false; + glt_edt->save_compress = false; free(path); free(file); return; } - else if (glitter_editor.close) { + else if (eg && glt_edt->load_data) { + bool load_success = true; + data_struct* ds = &data_list[glt_edt->load_data_type]; + switch (ds->type) { + case DATA_F2LE: + case DATA_F2BE: + case DATA_VRFL: + case DATA_X: + case DATA_XHD: { + vector_uint32_t* hashes = &ds->glitter_list_murmurhash; + for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { + if (!*i) + continue; + + glitter_effect* e = *i; + memset(e->name, 0, 0x80); + if (e->data.name_hash == hash_murmurhash_empty) + continue; + + uint32_t* j; + for (j = hashes->begin; j != hashes->end; j++) + if (e->data.name_hash == *j) + break; + + if (j == hashes->end) { + load_success = false; + continue; + } + + string* s = &ds->glitter_list_names.begin[j - hashes->begin]; + size_t len = s->length; + memcpy(e->name, string_data(s), min(len, 0x7F)); + } + + switch (ds->type) { + case DATA_VRFL: + case DATA_X: + case DATA_XHD: + if (glitter_effect_group_check_model(eg)) + glitter_effect_group_load_model(eg, ds); + break; + } + } break; + case DATA_AFT: + case DATA_FT: + case DATA_M39: { + vector_uint64_t* hashes = &ds->glitter_list_fnv1a64m; + for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { + if (!*i) + continue; + + glitter_effect* e = *i; + memset(e->name, 0, 0x80); + if (e->data.name_hash == hash_fnv1a64m_empty) + continue; + + uint64_t* j; + for (j = hashes->begin; j != hashes->end; j++) + if (e->data.name_hash == *j) + break; + + if (j == hashes->end) { + load_success = false; + continue; + } + + string* s = &ds->glitter_list_names.begin[j - hashes->begin]; + size_t len = s->length; + memcpy(e->name, string_data(s), min(len, 0x7F)); + } + } break; + } + + glt_edt->load_data = false; + + if (!load_success && !glitter_editor_list_open_window(glt_edt->effect_group)) { + glt_edt->load_error_list_popup = true; + goto effect_unload; + } + return; + } + else if (glt_edt->close) { + effect_unload: vector_ptr_glitter_scene_clear(&GPM_VAL->scenes, glitter_scene_dispose); - vector_ptr_glitter_effect_group_clear(&GPM_VAL->effect_groups, glitter_effect_group_dispose); + vector_ptr_glitter_effect_group_clear(&GPM_VAL->effect_groups, + glitter_effect_group_dispose); glitter_editor_reset_draw(); - glitter_editor.effect_group = 0; - glitter_editor.scene = 0; - memset(glitter_editor.file, 0, sizeof(glitter_editor.file)); - glitter_editor.close = false; + glt_edt->effect_group = 0; + glt_edt->scene = 0; + memset(glt_edt->file, 0, sizeof(glt_edt->file)); + glt_edt->close = false; return; } glitter_particle_manager_get_start_end_frame(GPM_VAL, - &glitter_editor.start_frame, &glitter_editor.end_frame); + &glt_edt->start_frame, &glt_edt->end_frame); - if (!glitter_editor.effect_group) { - glitter_editor.input_play = false; - glitter_editor.input_reset = false; + if (!glt_edt->effect_group) { + glt_edt->input_play = false; + glt_edt->input_reset = false; return; } - if (!glitter_editor.input_pause && glitter_editor.old_frame_counter == glitter_editor.frame_counter) { - glitter_editor.old_frame_counter = glitter_editor.frame_counter; + if (!glt_edt->input_pause && !glt_edt->input_pause_temp + && glt_edt->old_frame_counter == glt_edt->frame_counter) { + glt_edt->old_frame_counter = glt_edt->frame_counter; if (GPM_VAL->scenes.end != GPM_VAL->scenes.begin) - glitter_editor.delta_frame += get_frame_speed(); + glt_edt->delta_frame += get_delta_frame(); - while (glitter_editor.delta_frame >= 1.0) { - glitter_editor.frame_counter++; - glitter_editor.delta_frame -= 1.0; - } + int32_t delta_frame = (int32_t)glt_edt->delta_frame; + glt_edt->frame_counter += delta_frame; + glt_edt->delta_frame -= (double_t)delta_frame; } - if (glitter_editor.input_reload) { + if (glt_edt->input_reload) { vector_ptr_glitter_scene_clear(&GPM_VAL->scenes, glitter_scene_dispose); - glitter_editor.effect_group->emission = GPM_VAL->emission; - glitter_particle_manager_set_frame(GPM_VAL, glitter_editor.effect_group, - &glitter_editor.scene, (float_t)glitter_editor.frame_counter, - (float_t)glitter_editor.old_frame_counter, - glitter_editor.counter, &glitter_editor.random, true); - glitter_editor.old_frame_counter = glitter_editor.frame_counter; - glitter_editor.input_reload = false; + glt_edt->effect_group->emission = GPM_VAL->emission; + glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, + &glt_edt->scene, (float_t)glt_edt->frame_counter, + (float_t)glt_edt->old_frame_counter, + glt_edt->counter, &glt_edt->random, true); + glt_edt->old_frame_counter = glt_edt->frame_counter; + glt_edt->input_reload = false; } - if (glitter_editor.old_frame_counter != glitter_editor.frame_counter) { - if (glitter_editor.end_frame > 0) - while (glitter_editor.frame_counter >= glitter_editor.end_frame) - glitter_editor.frame_counter -= glitter_editor.end_frame - glitter_editor.start_frame; + if (glt_edt->old_frame_counter != glt_edt->frame_counter) { + if (glt_edt->end_frame > 0) + while (glt_edt->frame_counter >= glt_edt->end_frame) + glt_edt->frame_counter -= glt_edt->end_frame - glt_edt->start_frame; - if (glitter_editor.frame_counter < glitter_editor.start_frame) - glitter_editor.frame_counter = glitter_editor.start_frame; + if (glt_edt->frame_counter < glt_edt->start_frame) + glt_edt->frame_counter = glt_edt->start_frame; - glitter_particle_manager_set_frame(GPM_VAL, glitter_editor.effect_group, - &glitter_editor.scene, (float_t)glitter_editor.frame_counter, - (float_t)glitter_editor.old_frame_counter, - glitter_editor.counter, &glitter_editor.random, false); - glitter_editor.old_frame_counter = glitter_editor.frame_counter; + glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, + &glt_edt->scene, (float_t)glt_edt->frame_counter, + (float_t)glt_edt->old_frame_counter, + glt_edt->counter, &glt_edt->random, false); + glt_edt->old_frame_counter = glt_edt->frame_counter; } - if (glitter_editor.input_play) - glitter_editor.input_pause = false; - else if (glitter_editor.input_reset) { - GPM_VAL->counter = glitter_editor.counter; - glitter_editor.frame_counter = glitter_editor.start_frame; - glitter_particle_manager_set_frame(GPM_VAL, glitter_editor.effect_group, - &glitter_editor.scene, (float_t)glitter_editor.frame_counter, - (float_t)glitter_editor.old_frame_counter, - glitter_editor.counter, &glitter_editor.random, true); - glitter_editor.old_frame_counter = glitter_editor.frame_counter; - glitter_editor.input_pause = true; + if (glt_edt->input_play) + glt_edt->input_pause = false; + else if (glt_edt->input_reset) { + GPM_VAL->counter = glt_edt->counter; + glt_edt->frame_counter = glt_edt->start_frame; + glitter_particle_manager_set_frame(GPM_VAL, glt_edt->effect_group, + &glt_edt->scene, (float_t)glt_edt->frame_counter, + (float_t)glt_edt->old_frame_counter, + glt_edt->counter, &glt_edt->random, true); + glt_edt->old_frame_counter = glt_edt->frame_counter; + glt_edt->input_pause = true; } - glitter_editor.input_play = false; - glitter_editor.input_reset = false; + glt_edt->input_play = false; + glt_edt->input_reset = false; - glitter_editor_gl_process(); + glitter_editor_gl_process(glt_edt); } -static void glitter_editor_windows() { +bool glitter_editor_dispose(class_data* data) { + vector_ptr_glitter_scene_free(&GPM_VAL->scenes, glitter_scene_dispose); + vector_ptr_glitter_effect_group_free(&GPM_VAL->effect_groups, + glitter_effect_group_dispose); + + lock_data_free(&glitter_data_lock, glitter_editor_dispose); + + glitter_editor_struct* glt_edt = data->data; + if (glt_edt) { + glitter_editor_gl_free(glt_edt); + + glt_edt->test = false; + glt_edt->create_popup = false; + glt_edt->load = false; + glt_edt->load_data = false; + glt_edt->load_popup = false; + glt_edt->load_data_popup = false; + glt_edt->load_error_list_popup = false; + glt_edt->save = false; + glt_edt->save_popup = false; + glt_edt->save_compress = false; + glt_edt->close = false; + glt_edt->input_play = false; + glt_edt->input_reload = false; + glt_edt->input_pause = true; + glt_edt->input_reset = false; + glt_edt->effect_group_add = false; + glt_edt->draw_flags = 0; + glt_edt->resource_flags = 0; + glt_edt->effect_flags = 0; + glt_edt->emitter_flags = 0; + glt_edt->particle_flags = 0; + glt_edt->frame_counter = 0; + glt_edt->old_frame_counter = 0; + glt_edt->delta_frame = 0.0; + glt_edt->start_frame = 0; + glt_edt->end_frame = 0; + glt_edt->random.value = 0; + glt_edt->random.step = 1; + glt_edt->counter = 0; + glt_edt->effect_group = 0; + glt_edt->scene = 0; + memset(glt_edt->file, 0, sizeof(glt_edt->file)); + glDeleteVertexArrays(1, &glt_edt->vao); + } + draw_grid_3d = false; + free(data->data); + + data->flags = CLASS_HIDDEN | CLASS_DISPOSED; + data->imgui_focus = false; + return true; +} + +static void glitter_editor_windows(glitter_editor_struct* glt_edt, class_data* data) { ImGuiIO* io = igGetIO(); ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); - const float_t title_bar_size = font->FontSize + style->ItemSpacing.y + style->FramePadding.y * 2.0f; + const float_t title_bar_size = font->FontSize + + style->ItemSpacing.y + style->FramePadding.y * 2.0f; ImVec2 main_menu_bar_size = ImVec2_Empty; if (igBeginMainMenuBar()) { - bool is_x = glitter_editor.effect_group - && glitter_editor.effect_group->type == GLITTER_X ? true : false; + bool is_x = glt_edt->effect_group + && glt_edt->effect_group->type == GLITTER_X ? true : false; if (igBeginMenu("File", true)) { if (igMenuItem_Bool("Open", "Ctrl+O", false, true)) - glitter_editor_open_window(); + glitter_editor_open_window(glt_edt); if (igMenuItem_Bool("Save", "Ctrl+S", false, !is_x)) - glitter_editor_save_window(); + glitter_editor_save_window(glt_edt); if (igMenuItem_Bool("Save As..", "Ctrl+Shift+S", false, !is_x)) - glitter_editor_save_as_window(); + glitter_editor_save_as_window(glt_edt); if (igMenuItem_Bool("Close", "Ctrl+F4", false, true)) - glitter_editor.close = true; - if (igMenuItem_Bool("Quit", 0, false, true)) + glt_edt->close = true; + if (igMenuItem_Bool("Close Editor", "Ctrl+F3", false, true)) + data->flags |= CLASS_DISPOSE; + if (igMenuItem_Bool("Quit", "Ctrl+Q", false, true)) close = true; igEndMenu(); } @@ -1235,36 +1381,38 @@ static void glitter_editor_windows() { igEndMenu(); } - if (igBeginMenu("Mode", glitter_editor.effect_group ? true : false)) { - glitter_effect_group* eg = glitter_editor.effect_group; + if (igBeginMenu("Mode", glt_edt->effect_group ? true : false)) { + glitter_effect_group* eg = glt_edt->effect_group; if (eg->type != GLITTER_X) { - if (igMenuItem_Bool("F2nd", 0, false, eg->type != GLITTER_F2)) { + if (igMenuItem_Bool("F2", 0, false, eg->type != GLITTER_F2)) { eg->type = GLITTER_F2; - glitter_editor_reload(); + glitter_editor_reload(glt_edt); } - if (igMenuItem_Bool("AFT", 0, false, eg->type != GLITTER_AFT)) { - eg->type = GLITTER_AFT; - glitter_editor_reload(); + if (igMenuItem_Bool("FT", 0, false, eg->type != GLITTER_FT)) { + eg->type = GLITTER_FT; + glitter_editor_reload(glt_edt); } } else { if (igMenuItem_Bool("X", 0, false, eg->type != GLITTER_X)) { eg->type = GLITTER_X; - glitter_editor_reload(); + glitter_editor_reload(glt_edt); } } igEndMenu(); } - if (igBeginMenu("View", glitter_editor.effect_group ? true : false)) { + if (igBeginMenu("View", true)) { igCheckboxFlags_UintPtr("Draw Wireframe", - (uint32_t*)&glitter_editor.draw_flags, GLITTER_EDITOR_DRAW_WIREFRAME); + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_WIREFRAME); igCheckboxFlags_UintPtr("Draw Selected", - (uint32_t*)&glitter_editor.draw_flags, GLITTER_EDITOR_DRAW_SELECTED); + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_SELECTED); + igCheckboxFlags_UintPtr("No Draw", + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_NO_DRAW); igEndMenu(); } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igGetWindowSize(&main_menu_bar_size); igEndMainMenuBar(); } @@ -1277,7 +1425,8 @@ static void glitter_editor_windows() { float_t win_y; ImGuiWindowFlags window_flags; - bool selected = selected_effect || selected_emitter || selected_particle ? true : false; + bool selected = glt_edt->selected_effect || glt_edt->selected_emitter + || glt_edt->selected_particle ? true : false; win_x = min((float_t)width / 4.0f, 400.0f); @@ -1301,28 +1450,27 @@ static void glitter_editor_windows() { if (igBegin("Effects", 0, window_flags)) { if (igBeginTabBar("Effects Tab", 0)) { if (igBeginTabItem("Effects", 0, 0)) { - glitter_editor_effects_context_menu(0, 0, 0, 0, 0, 0, GLITTER_EDITOR_SELECTED_NONE); - if (glitter_editor.effect_group) - glitter_editor_effects(); + if (glt_edt->effect_group) + glitter_editor_effects(glt_edt); igEndTabItem(); } - imguiDisableElementPush(glitter_editor.effect_group != 0); + imguiDisableElementPush(glt_edt->effect_group != 0); if (igBeginTabItem("Resources", 0, 0)) { - glitter_editor_resources_context_menu(-1, 0, true); - if (glitter_editor.effect_group) - glitter_editor_resources(); + glitter_editor_resources_context_menu(glt_edt, -1, 0, true); + if (glt_edt->effect_group) + glitter_editor_resources(glt_edt); igEndTabItem(); } - imguiDisableElementPop(glitter_editor.effect_group != 0); + imguiDisableElementPop(glt_edt->effect_group != 0); if (igBeginTabItem("Play Manager", 0, 0)) { - glitter_editor_play_manager(); + glitter_editor_play_manager(glt_edt); igEndTabItem(); } igEndTabBar(); } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); } igEnd(); igPopID(); @@ -1346,9 +1494,9 @@ static void glitter_editor_windows() { igPushID_Str("Glitter Editor Property Window"); if (igBegin("Property", 0, window_flags)) { - if (glitter_editor.effect_group && selected) - glitter_editor_property(); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + if (glt_edt->effect_group && selected) + glitter_editor_property(glt_edt, data); + data->imgui_focus |= igIsWindowFocused(0); } igEnd(); igPopID(); @@ -1373,9 +1521,9 @@ static void glitter_editor_windows() { igPushID_Str("Glitter Editor Curve Editor Selector Window"); if (igBegin("Curve Editor Selector", 0, window_flags)) { - if (glitter_editor.effect_group && selected) - glitter_editor_curve_editor_selector(); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + if (glt_edt->effect_group && selected) + glitter_editor_curve_editor_selector(glt_edt, data); + data->imgui_focus |= igIsWindowFocused(0); } igEnd(); igPopID(); @@ -1400,9 +1548,9 @@ static void glitter_editor_windows() { igPushID_Str("Glitter Editor Curve Editor Property Window"); if (igBegin("Curve Editor Property", 0, window_flags)) { - if (glitter_editor.effect_group && selected) - glitter_editor_curve_editor_property_window(); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + if (glt_edt->effect_group && selected) + glitter_editor_curve_editor_property_window(glt_edt, data); + data->imgui_focus |= igIsWindowFocused(0); } igEnd(); igPopID(); @@ -1427,31 +1575,34 @@ static void glitter_editor_windows() { igPushID_Str("Glitter Editor Curve Editor Window"); if (igBegin("Curve Editor", 0, window_flags)) { - if (glitter_editor.effect_group && selected) - glitter_editor_curve_editor(); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + if (glt_edt->effect_group && selected) + glitter_editor_curve_editor(glt_edt); + data->imgui_focus |= igIsWindowFocused(0); } igEnd(); igPopID(); } -static void glitter_editor_reload() { - if (!glitter_editor.effect_group) +static void glitter_editor_reload(glitter_editor_struct* glt_edt) { + if (!glt_edt->effect_group) return; - glitter_editor.input_reload = true; - glitter_effect_group* eg = glitter_editor.effect_group; + glt_edt->input_reload = true; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_scene* sc = glt_edt->scene; + sc->type = eg->type; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { if (!*i) continue; glitter_effect* effect = *i; - if (eg->type != GLITTER_AFT) + size_t len = utf8_length(effect->name); + if (eg->type != GLITTER_FT) effect->data.name_hash = hash_murmurhash(effect->name, - min(utf8_length(effect->name), 0x7F), 0, false, false); + min(len, 0x7F), 0, false, false); else - effect->data.name_hash = hash_fnv1a64(effect->name, - min(utf8_length(effect->name), 0x7F)); + effect->data.name_hash = hash_fnv1a64m(effect->name, + min(len, 0x7F)); for (glitter_curve** c = effect->animation.begin; c != effect->animation.end; c++) if (*c) @@ -1481,14 +1632,14 @@ static void glitter_editor_reload() { } } -static void glitter_editor_reset() { - selected_type = GLITTER_EDITOR_SELECTED_NONE; - selected_resource = -1; - selected_effect = 0; - selected_emitter = 0; - selected_particle = 0; - glitter_editor_curve_editor_reset_state(-1); - glitter_editor_curve_editor_curves_reset(); +static void glitter_editor_reset(glitter_editor_struct* glt_edt) { + glt_edt->selected_type = GLITTER_EDITOR_SELECTED_NONE; + glt_edt->selected_resource = -1; + glt_edt->selected_effect = 0; + glt_edt->selected_emitter = 0; + glt_edt->selected_particle = 0; + glitter_editor_curve_editor_reset_state(glt_edt, -1); + glitter_editor_curve_editor_curves_reset(glt_edt); glitter_editor_reset_draw(); } @@ -1499,12 +1650,12 @@ static void glitter_editor_reset_draw() { GPM_VAL->particle = 0; } -static void glitter_editor_save() { - glitter_editor.save_popup = glitter_editor.effect_group - && glitter_editor.effect_group->type == GLITTER_X ? false : true; +static void glitter_editor_save(glitter_editor_struct* glt_edt) { + glt_edt->save_popup = glt_edt->effect_group + && glt_edt->effect_group->type == GLITTER_X ? false : true; } -static void glitter_editor_open_window() { +static void glitter_editor_open_window(glitter_editor_struct* glt_edt) { if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) return; @@ -1520,32 +1671,32 @@ static void glitter_editor_open_window() { ofn.lpstrTitle = L"File to Open"; if (GetOpenFileNameW(&ofn)) { char* file_temp = utf16_to_utf8(file); - memcpy(glitter_editor.file, file_temp, utf8_length(file_temp) + 1); + memcpy(glt_edt->file, file_temp, utf8_length(file_temp) + 1); free(file_temp); - glitter_editor.load_popup = true; + glt_edt->load_popup = true; } CoUninitialize(); } -static void glitter_editor_save_window() { - if (!glitter_editor.effect_group || !glitter_editor.scene) +static void glitter_editor_save_window(glitter_editor_struct* glt_edt) { + if (!glt_edt->effect_group || !glt_edt->scene) return; - if (glitter_editor.file[0]) - glitter_editor_save(); + if (glt_edt->file[0]) + glitter_editor_save(glt_edt); else - glitter_editor_save_as_window(); + glitter_editor_save_as_window(glt_edt); } -static void glitter_editor_save_as_window() { - if (glitter_editor.effect_group - && glitter_editor.effect_group->type == GLITTER_X) { - glitter_editor.save_popup = false; +static void glitter_editor_save_as_window(glitter_editor_struct* glt_edt) { + if (glt_edt->effect_group + && glt_edt->effect_group->type == GLITTER_X) { + glt_edt->save_popup = false; return; } if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { - glitter_editor.save_popup = false; + glt_edt->save_popup = false; return; } @@ -1562,85 +1713,78 @@ static void glitter_editor_save_as_window() { ofn.Flags = OFN_NONETWORKBUTTON; if (GetSaveFileNameW(&ofn)) { char* file_temp = utf16_to_utf8(file); - memcpy(glitter_editor.file, file_temp, utf8_length(file_temp) + 1); + memcpy(glt_edt->file, file_temp, utf8_length(file_temp) + 1); free(file_temp); - glitter_editor_save(); + glitter_editor_save(glt_edt); } else - glitter_editor.save_popup = false; + glt_edt->save_popup = false; CoUninitialize(); } -static void glitter_editor_load_file(char* path, char* file) { +static void glitter_editor_load_file(glitter_editor_struct* glt_edt, char* path, char* file) { vector_ptr_glitter_scene_clear(&GPM_VAL->scenes, glitter_scene_dispose); - vector_ptr_glitter_effect_group_clear(&GPM_VAL->effect_groups, glitter_effect_group_dispose); + vector_ptr_glitter_effect_group_clear(&GPM_VAL->effect_groups, + glitter_effect_group_dispose); glitter_editor_reset_draw(); - glitter_editor.effect_group = 0; - glitter_editor.scene = 0; + glt_edt->effect_group = 0; + glt_edt->scene = 0; - glitter_file_reader* fr = glitter_file_reader_init(glitter_editor.load_glt_type, path, file, -1.0f); - if (glitter_file_reader_read(fr, GPM_VAL->emission)) { - if (fr->type == GLITTER_AFT) { - bool lst_valid = true; + glitter_file_reader* fr = glitter_file_reader_init(glt_edt->load_glt_type, + path, file, -1.0f); + if (glitter_file_reader_read(GPM_VAL, fr, GPM_VAL->emission)) { + bool lst_not_valid = true; + if (fr->type == GLITTER_FT) { + lst_not_valid = false; glitter_effect_group* eg = fr->effect_group; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { if (!*i) continue; glitter_effect* e = *i; - if (e->data.name_hash != hash_fnv1a64(e->name, min(utf8_length(e->name), 0x80))) { - lst_valid = false; + size_t len = utf8_length(e->name); + if (e->data.name_hash != hash_fnv1a64m(e->name, min(len, 0x80))) { + lst_not_valid = true; break; } } - - if (!lst_valid && !glitter_editor_list_open_window(fr->effect_group)) { - glitter_effect_group_dispose(fr->effect_group); - glitter_editor.load_error_list_popup = true; - } - else - goto add_effect_group; } - else if (!glitter_editor_list_open_window(fr->effect_group)) { - glitter_effect_group_dispose(fr->effect_group); - glitter_editor.load_error_list_popup = true; + + glitter_editor_reset_draw(); + glt_edt->counter = GPM_VAL->counter; + glt_edt->effect_group = fr->effect_group; + glt_edt->scene = glitter_scene_init(fr->effect_group); + + glitter_effect_group* eg = glt_edt->effect_group; + glitter_effect** i; + size_t id = 1; + for (i = eg->effects.begin, id = 1; i != eg->effects.end; i++, id++) { + if (!*i) + continue; + + glitter_scene_init_effect(GPM_VAL, glt_edt->scene, *i, id, false); } - else { - add_effect_group: - glitter_editor_reset_draw(); - glitter_editor.counter = GPM_VAL->counter; - glitter_editor.effect_group = fr->effect_group; - glitter_editor.scene = glitter_scene_init(fr->effect_group); - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_effect** i; - size_t id = 1; - for (i = eg->effects.begin, id = 1; i != eg->effects.end; i++, id++) { - if (!*i) - continue; - - glitter_scene_init_effect(GPM_VAL, glitter_editor.scene, *i, id, false); - } - - vector_ptr_glitter_effect_group_push_back(&GPM_VAL->effect_groups, &glitter_editor.effect_group); - vector_ptr_glitter_scene_push_back(&GPM_VAL->scenes, &glitter_editor.scene); - glitter_particle_manager_get_start_end_frame(GPM_VAL, - &glitter_editor.start_frame, &glitter_editor.end_frame); - glitter_editor.frame_counter = 0; - glitter_editor.old_frame_counter = 0; - glitter_editor.input_pause = true; - } + vector_ptr_glitter_effect_group_push_back(&GPM_VAL->effect_groups, + &glt_edt->effect_group); + vector_ptr_glitter_scene_push_back(&GPM_VAL->scenes, &glt_edt->scene); + glitter_particle_manager_get_start_end_frame(GPM_VAL, + &glt_edt->start_frame, &glt_edt->end_frame); + glt_edt->frame_counter = 0; + glt_edt->old_frame_counter = 0; + glt_edt->input_pause = true; + glt_edt->load_data_popup = lst_not_valid; } else if (fr->effect_group) glitter_effect_group_dispose(fr->effect_group); glitter_file_reader_dispose(fr); - glitter_editor_reset(); + glitter_editor_reset(glt_edt); } -static void glitter_editor_save_file(char* path, char* file) { - glitter_type glt_type = glitter_editor.save_glt_type; +static void glitter_editor_save_file(glitter_editor_struct* glt_edt, char* path, char* file) { + glitter_type glt_type = glt_edt->save_glt_type; f2_struct st; farc_file ff_drs; @@ -1651,8 +1795,9 @@ static void glitter_editor_save_file(char* path, char* file) { memset(&ff_dve, 0, sizeof(farc_file)); memset(&ff_lst, 0, sizeof(farc_file)); - farc* f = farc_init(); - if (glitter_diva_effect_unparse_file(glt_type, glitter_editor.effect_group, &st)) { + farc f; + farc_init(&f); + if (glitter_diva_effect_unparse_file(glt_type, glt_edt->effect_group, &st)) { f2_struct_mwrite(&st, &ff_dve.data, &ff_dve.size, true, false); string_init(&ff_dve.name, file); string_add(&ff_dve.name, ".dve"); @@ -1661,15 +1806,15 @@ static void glitter_editor_save_file(char* path, char* file) { else goto End; - if (glitter_diva_resource_unparse_file(glitter_editor.effect_group, &st)) { + if (glitter_diva_resource_unparse_file(glt_edt->effect_group, &st)) { f2_struct_mwrite(&st, &ff_drs.data, &ff_drs.size, true, false); string_init(&ff_drs.name, file); string_add(&ff_drs.name, ".drs"); } f2_struct_free(&st); - if (glt_type == GLITTER_AFT) - if (glitter_diva_list_unparse_file(glitter_editor.effect_group, &st)) { + if (glt_type == GLITTER_FT) + if (glitter_diva_list_unparse_file(glt_edt->effect_group, &st)) { f2_struct_mwrite(&st, &ff_lst.data, &ff_lst.size, true, false); string_init(&ff_lst.name, file); string_add(&ff_lst.name, ".lst"); @@ -1683,24 +1828,24 @@ static void glitter_editor_save_file(char* path, char* file) { } if (ff_drs.data) - vector_farc_file_push_back(&f->files, &ff_drs); - vector_farc_file_push_back(&f->files, &ff_dve); - if (glt_type == GLITTER_AFT) - vector_farc_file_push_back(&f->files, &ff_lst); + vector_farc_file_push_back(&f.files, &ff_drs); + vector_farc_file_push_back(&f.files, &ff_dve); + if (glt_type == GLITTER_FT) + vector_farc_file_push_back(&f.files, &ff_lst); farc_compress_mode mode; - if (glitter_editor.save_compress) - mode = glt_type != GLITTER_AFT ? FARC_COMPRESS_FARC_GZIP_AES : FARC_COMPRESS_FArC; + if (glt_edt->save_compress) + mode = glt_type != GLITTER_FT ? FARC_COMPRESS_FARC_GZIP_AES : FARC_COMPRESS_FArC; else mode = FARC_COMPRESS_FArc; char* temp = str_utils_add(path, file); - if (glt_type != GLITTER_AFT) { + if (glt_type != GLITTER_FT) { char* list_temp = str_utils_add(temp, ".glitter.txt"); stream s; io_open(&s, list_temp, "wb"); if (s.io.stream) { - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) if (*i) { io_write(&s, (*i)->name, utf8_length((*i)->name)); @@ -1710,18 +1855,19 @@ static void glitter_editor_save_file(char* path, char* file) { io_free(&s); free(list_temp); } - farc_write(f, temp, mode, false); + farc_write(&f, temp, mode, false); free(temp); End: f2_struct_free(&st); - farc_dispose(f); + farc_free(&f); } static bool glitter_editor_list_open_window(glitter_effect_group* eg) { - bool ret = false; if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) - return ret; + return false; + + bool ret = false; wchar_t file[MAX_PATH]; memset(&file, 0, sizeof(file)); @@ -1744,16 +1890,26 @@ static bool glitter_editor_list_open_window(glitter_effect_group* eg) { char* buf; char** lines; size_t count; - if (glitter_editor_list_parse(data, length, &buf, &lines, &count)) { - uint64_t empty_hash = eg->type != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) { + for (size_t i = 0; i < count; i++) { + char* t = strstr(lines[i], "#(?)"); + if (t) + *t = 0; + } + + uint64_t empty_hash = eg->type != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; uint64_t* hashes = force_malloc_s(uint64_t, count); - if (eg->type != GLITTER_AFT) - for (size_t i = 0; i < count; i++) - hashes[i] = hash_murmurhash(lines[i], min(utf8_length(lines[i]), 0x7F), 0, false, false); + if (eg->type != GLITTER_FT) + for (size_t i = 0; i < count; i++) { + size_t len = utf8_length(lines[i]); + hashes[i] = hash_murmurhash(lines[i], min(len, 0x7F), 0, false, false); + } else - for (size_t i = 0; i < count; i++) - hashes[i] = hash_fnv1a64(lines[i], min(utf8_length(lines[i]), 0x7F)); + for (size_t i = 0; i < count; i++) { + size_t len = utf8_length(lines[i]); + hashes[i] = hash_fnv1a64m(lines[i], min(len, 0x7F)); + } ret = true; for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { @@ -1775,7 +1931,8 @@ static bool glitter_editor_list_open_window(glitter_effect_group* eg) { continue; } - memcpy(e->name, lines[j], min(utf8_length(lines[j]), 0x7F)); + size_t len = utf8_length(lines[j]); + memcpy(e->name, lines[j], min(len, 0x7F)); } free(buf); @@ -1788,130 +1945,7 @@ static bool glitter_editor_list_open_window(glitter_effect_group* eg) { return ret; } -static bool glitter_editor_list_parse(uint8_t* data, size_t length, char** buf, char*** lines, size_t* count) { - if (!data || !length || !buf || !lines || !count) - return false; - - char* d = data; - bool del = false; - size_t c; - *buf = 0; - *lines = 0; - *count = 0; - if (data[0] == 0x00) - return false; - else if (data[0] == 0xFF) { - if (length == 1 || data[1] != 0xFE || length == 2) - return false; - - wchar_t* w_d = (wchar_t*)data + 1; - d = utf16_to_utf8(w_d); - length = utf8_length(d); - del = true; - goto decode_utf8_ansi; - } - else if (data[0] == 0xFE) { - if (length == 1 || data[1] != 0xFF || length == 2) - return false; - - length /= 2; - wchar_t* w_d = (wchar_t*)data + 1; - w_d = str_utils_wcopy(w_d); - for (size_t i = 0; i < length; i++) - w_d[i] = (wchar_t)reverse_endianness_uint16_t((uint16_t)w_d[i]); - d = utf16_to_utf8(w_d); - length = utf8_length(d); - del = true; - free(w_d); - goto decode_utf8_ansi; - } - else if (data[0] == 0xEF) { - if (length == 1 || data[1] != 0xBB || length == 2 || data[2] != 0xBF || length == 3) - return false; - - d += 3; - length -= 3; - goto decode_utf8_ansi; - } - else { - decode_utf8_ansi: - c = 1; - bool lf; - char ch; - lf = false; - for (size_t i = 0; i < length; i++) { - ch = d[i]; - while ((ch == '\r' || ch == '\n') && ++i < length) { - ch = d[i]; - lf = true; - } - - if (lf && i < length) { - c++; - lf = false; - } - } - - lf = false; - size_t* line_lengths = force_malloc_s(size_t, c); - size_t* line_offsets = force_malloc_s(size_t, c); - line_lengths[0] = 0; - line_offsets[0] = 0; - for (size_t i = 0, j = 0, l = 0; j < c; ) { - ch = d[i]; - while ((ch == '\r' || ch == '\n') && ++i < length) { - ch = d[i]; - lf = true; - } - - if (i >= length) { - line_lengths[j] = l; - break; - } - else if (lf) { - line_lengths[j++] = l; - line_offsets[j] = i; - l = 0; - lf = false; - } - else { - l++; - i++; - } - } - - size_t buf_len = 0; - for (size_t i = 0; i < c; i++) - buf_len += line_lengths[i] + 1; - - *buf = force_malloc(buf_len); - char* b = *buf; - - char** temp_lines = force_malloc_s(char*, c); - for (size_t i = 0, l = 0; i < c; i++) { - l = line_lengths[i]; - memcpy(b, d + line_offsets[i], l); - b[l] = 0; - - char* t; - if (t = strstr(b, "#(?)")) - *t = 0; - - temp_lines[i] = b; - b += l + 1; - } - *lines = temp_lines; - *count = c; - free(line_offsets); - free(line_lengths); - } - - if (del) - free(d); - return true; -} - -static bool glitter_editor_resource_import() { +static bool glitter_editor_resource_import(glitter_editor_struct* glt_edt) { if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) return false; @@ -1932,30 +1966,31 @@ static bool glitter_editor_resource_import() { wchar_t* p = str_utils_wsplit_right_get_left(file, L'.'); dds* d = dds_init(); - uint64_t hash_aft = hash_utf16_fnv1a64(f); + uint64_t hash_ft = hash_utf16_fnv1a64m(f); uint64_t hash_f2 = hash_utf16_murmurhash(f, 0, false); - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; int32_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; for (int32_t i = 0; i < rc; i++) - if (rh[i] == hash_aft || rh[i] == hash_f2) + if (rh[i] == hash_ft || rh[i] == hash_f2) goto DDSEnd; dds_wread(d, p); - if (d->width == 0 || d->height == 0 || d->mipmaps_count == 0 || d->data.end - d->data.begin < 1) + if (d->width == 0 || d->height == 0 + || d->mipmaps_count == 0 || d->data.end - d->data.begin < 1) goto DDSEnd; - txp tex; - memset(&tex, 0, sizeof(txp)); - tex.array_size = d->has_cube_map ? 6 : 1; - tex.has_cube_map = d->has_cube_map; - tex.mipmaps_count = d->mipmaps_count; + txp* tex = vector_txp_reserve_back(&eg->resources_tex); + tex->array_size = d->has_cube_map ? 6 : 1; + tex->has_cube_map = d->has_cube_map; + tex->mipmaps_count = d->mipmaps_count; - vector_txp_mipmap_reserve(&tex.data, (tex.has_cube_map ? 6LL : 1LL) * tex.mipmaps_count); + vector_txp_mipmap_reserve(&tex->data, + (tex->has_cube_map ? 6LL : 1LL) * tex->mipmaps_count); uint32_t index = 0; do - for (uint32_t i = 0; i < tex.mipmaps_count; i++) { + for (uint32_t i = 0; i < tex->mipmaps_count; i++) { txp_mipmap tex_mip; memset(&tex_mip, 0, sizeof(txp_mipmap)); tex_mip.width = max(d->width >> i, 1); @@ -1967,17 +2002,16 @@ static bool glitter_editor_resource_import() { tex_mip.size = size; tex_mip.data = force_malloc(size); memcpy(tex_mip.data, d->data.begin[index], size); - vector_txp_mipmap_push_back(&tex.data, &tex_mip); + vector_txp_mipmap_push_back(&tex->data, &tex_mip); index++; } - while (index / tex.mipmaps_count < tex.array_size); + while (index / tex->mipmaps_count < tex->array_size); eg->resources_count++; - if (eg->type == GLITTER_AFT) - vector_uint64_t_push_back(&eg->resource_hashes, &hash_aft); + if (eg->type == GLITTER_FT) + vector_uint64_t_push_back(&eg->resource_hashes, &hash_ft); else vector_uint64_t_push_back(&eg->resource_hashes, &hash_f2); - vector_txp_push_back(&eg->resources_tex, &tex); ret = true; DDSEnd: dds_dispose(d); @@ -1988,7 +2022,9 @@ static bool glitter_editor_resource_import() { return ret; } -static bool glitter_editor_resource_export() { +static bool glitter_editor_resource_export(glitter_editor_struct* glt_edt) { + int32_t sel_rsrc = glt_edt->selected_resource; + if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) return false; @@ -2009,8 +2045,8 @@ static bool glitter_editor_resource_export() { wchar_t* p = str_utils_wsplit_right_get_left(file, L'.'); dds* d = dds_init(); - glitter_effect_group* eg = glitter_editor.effect_group; - txp tex = eg->resources_tex.begin[selected_resource]; + glitter_effect_group* eg = glt_edt->effect_group; + txp tex = eg->resources_tex.begin[sel_rsrc]; txp_format format = tex.data.begin[0].format; uint32_t width = tex.data.begin[0].width; @@ -2027,8 +2063,7 @@ static bool glitter_editor_resource_export() { uint32_t index = 0; do for (uint32_t i = 0; i < tex.mipmaps_count; i++) { - uint32_t size = txp_get_size(format, - max(width >> i, 1), max(height >> i, 1)); + uint32_t size = txp_get_size(format, max(width >> i, 1), max(height >> i, 1)); void* data = force_malloc(size); memcpy(data, tex.data.begin[index].data, size); vector_ptr_void_push_back(&d->data, &data); @@ -2044,105 +2079,70 @@ static bool glitter_editor_resource_export() { return ret; } -static void glitter_editor_test_window() { - glitter_effect_group* eg = glitter_editor.effect_group; +static void glitter_editor_test_window(glitter_editor_struct* glt_edt, class_data* data) { + glitter_effect_group* eg = glt_edt->effect_group; - float_t w = min((float_t)width / 4.0f, 360.0f); - float_t h = 424.0f; + float_t w = min((float_t)width, 360.0f); + float_t h = min((float_t)height, 326.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_FirstUseEver, ImVec2_Empty); - igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_FirstUseEver); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); ImGuiWindowFlags window_flags = 0; window_flags |= ImGuiWindowFlags_NoResize; window_flags |= ImGuiWindowFlags_NoCollapse; - bool test = glitter_editor.test; - if (!igBegin("Glitter Editor Test Window", &test, window_flags)) { - glitter_editor.test = false; - glitter_editor.imgui_focus |= igIsWindowFocused(0); - igEnd(); - return; + if (!igBegin("Glitter Editor Test Window", &glt_edt->test, window_flags)) { + data->imgui_focus |= igIsWindowFocused(0); + goto End; } if (imguiButton("Reset Camera (R)", ImVec2_Empty)) input_reset = true; - ImVec2 t; - igGetContentRegionAvail(&t); + w = imguiGetContentRegionAvailWidth(); if (igBeginTable("buttons", 2, 0, ImVec2_Empty, 0.0f)) { - igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, t.x * 0.5f, 0); + igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * 0.5f, 0); igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Play (T)", (ImVec2) { t.x, 0.0f }) || igIsKeyPressed(GLFW_KEY_T, true)) - glitter_editor.input_play = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Play (T)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_T, true)) + glt_edt->input_play = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Reload (Y)", (ImVec2) { t.x, 0.0f }) || igIsKeyPressed(GLFW_KEY_Y, true)) - glitter_editor.input_reload = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Reload (Y)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_Y, true)) + glt_edt->input_reload = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Pause (F)", (ImVec2) { t.x, 0.0f }) || igIsKeyPressed(GLFW_KEY_F, true)) - glitter_editor.input_pause = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Pause (F)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_F, true)) + glt_edt->input_pause = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Reset (G)", (ImVec2) { t.x, 0.0f }) || igIsKeyPressed(GLFW_KEY_G, true)) - glitter_editor.input_reset = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Reset (G)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_G, true)) + glt_edt->input_reset = true; igEndTable(); } igSeparator(); - int32_t frame_counter = glitter_editor.frame_counter; - if (imguiColumnSliderInt("Frame", &frame_counter, glitter_editor.start_frame, - glitter_editor.end_frame, "%d", 0)) { - glitter_editor.old_frame_counter = glitter_editor.frame_counter; - glitter_editor.frame_counter = frame_counter; + int32_t frame_counter = glt_edt->frame_counter; + if (imguiColumnSliderInt("Frame", &frame_counter, glt_edt->start_frame, + glt_edt->end_frame, "%d", 0, true)) { + glt_edt->old_frame_counter = glt_edt->frame_counter; + glt_edt->frame_counter = frame_counter; } + glt_edt->input_pause_temp = igIsItemActivated(); - igText("Start/End Frame: %d/%d", glitter_editor.start_frame, glitter_editor.end_frame); + igText("Start/End Frame: %d/%d", glt_edt->start_frame, glt_edt->end_frame); + + imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 0.01f, 1.0f, 2.0f, "%.2f", 0, true); igSeparator(); - - size_t ctrl; - size_t disp; - float_t frame; - int32_t life_time; - - frame = 0.0f; - life_time = 0; - glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); - igText("%d - %.0f/%d", max(glitter_editor.frame_counter - glitter_editor.start_frame, 0), frame, life_time); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - igText(" Quad: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - igText("Locus: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); - igText(" Line: ctrl%lld, disp%lld", ctrl, disp); - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); - igText(" Mesh: ctrl%lld, disp%lld", ctrl, disp); - - igSeparator(); - - imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 1.0f, 2.0f, "%.2f", 0); - imguiColumnSliderFloat("Frame Speed", &frame_speed, 0.0f, 3.0f, "%.2f", 0); - - igSeparator(); - - imguiCheckbox("Grid", &grid_3d); + imguiCheckbox("Show Grid", &draw_grid_3d); imguiCheckbox("Draw All", &GPM_VAL->draw_all); @@ -2153,14 +2153,71 @@ static void glitter_editor_test_window() { igSeparator(); igCheckboxFlags_UintPtr("Draw Wireframe", - (uint32_t*)&glitter_editor.draw_flags, GLITTER_EDITOR_DRAW_WIREFRAME); + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_WIREFRAME); igCheckboxFlags_UintPtr("Draw Selected", - (uint32_t*)&glitter_editor.draw_flags, GLITTER_EDITOR_DRAW_SELECTED); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_SELECTED); + igCheckboxFlags_UintPtr("No Draw", + (uint32_t*)&glt_edt->draw_flags, GLITTER_EDITOR_DRAW_NO_DRAW); + + data->imgui_focus |= igIsWindowFocused(0); + igEnd(); + + float_t win_x = min((float_t)width, 240.0f); + float_t win_y = min((float_t)height, 96.0f); + + float_t x = 0.0f; + float_t y = (float_t)height - win_y; + w = win_x; + h = win_y; + + igSetNextWindowPos((ImVec2) { x, y }, ImGuiCond_Always, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + window_flags = 0; + window_flags |= ImGuiWindowFlags_NoTitleBar; + window_flags |= ImGuiWindowFlags_NoResize; + window_flags |= ImGuiWindowFlags_NoScrollbar; + window_flags |= ImGuiWindowFlags_NoCollapse; + window_flags |= ImGuiWindowFlags_NoMouseInputs; + window_flags |= ImGuiWindowFlags_NoNavInputs; + window_flags |= ImGuiWindowFlags_NoNavFocus; + + igPushStyleColor_U32(ImGuiCol_Border, 0); + igPushStyleColor_U32(ImGuiCol_WindowBg, 0); + if (igBegin("Glitter Test Sub##Data Test", 0, window_flags)) { + size_t ctrl; + size_t disp; + float_t frame; + int32_t life_time; + + frame = 0.0f; + life_time = 0; + glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); + igText("%d - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + igText(" Quad: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + igText("Locus: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); + igText(" Line: ctrl%lld, disp%lld", ctrl, disp); + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); + igText(" Mesh: ctrl%lld, disp%lld", ctrl, disp); + } + igPopStyleColor(2); + +End: igEnd(); } -static void glitter_editor_effects() { +static void glitter_editor_effects(glitter_editor_struct* glt_edt) { char buf[0x100]; ImGuiTreeNodeFlags tree_node_base_flags = 0; @@ -2170,7 +2227,7 @@ static void glitter_editor_effects() { ImGuiTreeNodeFlags tree_node_flags; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; igPushID_Ptr(eg); ssize_t i_idx = 1; for (glitter_effect** i = eg->effects.begin; @@ -2180,7 +2237,8 @@ static void glitter_editor_effects() { glitter_effect* effect = *i; tree_node_flags = tree_node_base_flags; - if (effect == selected_effect && !selected_emitter && !selected_particle) + if (effect == glt_edt->selected_effect && !glt_edt->selected_emitter + && !glt_edt->selected_particle) tree_node_flags |= ImGuiTreeNodeFlags_Selected; const char* eff_str; @@ -2198,8 +2256,8 @@ static void glitter_editor_effects() { igPushID_Ptr(effect); if (igTreeNodeEx_StrStr("effect", tree_node_flags, eff_str, - effect->name, (uint32_t)((size_t)effect * hash_fnv1a64_empty))) { - glitter_editor_effects_context_menu(effect, 0, 0, + effect->name, (uint32_t)((size_t)effect * hash_fnv1a64m_empty))) { + glitter_editor_effects_context_menu(glt_edt, effect, 0, 0, i_idx, 0, 0, GLITTER_EDITOR_SELECTED_EFFECT); ssize_t j_idx = 1; @@ -2210,7 +2268,7 @@ static void glitter_editor_effects() { glitter_emitter* emitter = *j; tree_node_flags = tree_node_base_flags; - if (emitter == selected_emitter && !selected_particle) + if (emitter == glt_edt->selected_emitter && !glt_edt->selected_particle) tree_node_flags |= ImGuiTreeNodeFlags_Selected; const char* emit_str; @@ -2229,8 +2287,8 @@ static void glitter_editor_effects() { igPushID_Ptr(emitter); if (igTreeNodeEx_StrStr("emitter", tree_node_flags, emit_str, - j_idx, (uint32_t)((size_t)emitter * hash_fnv1a64_empty))) { - glitter_editor_effects_context_menu(effect, emitter, 0, + j_idx, (uint32_t)((size_t)emitter * hash_fnv1a64m_empty))) { + glitter_editor_effects_context_menu(glt_edt, effect, emitter, 0, i_idx, j_idx, 0, GLITTER_EDITOR_SELECTED_EMITTER); ssize_t k_idx = 1; @@ -2263,39 +2321,43 @@ static void glitter_editor_effects() { igPushID_Ptr(particle); snprintf(buf, sizeof(buf), ptcl_str, - k_idx, (uint32_t)((size_t)particle * hash_fnv1a64_empty)); - igSelectable_Bool(buf, particle == selected_particle, 0, (ImVec2) { 0.0f, 0.0f }); - glitter_editor_effects_context_menu(effect, emitter, particle, + k_idx, (uint32_t)((size_t)particle * hash_fnv1a64m_empty)); + igSelectable_Bool(buf, particle == glt_edt->selected_particle, + 0, (ImVec2) { 0.0f, 0.0f }); + glitter_editor_effects_context_menu(glt_edt, effect, emitter, particle, i_idx, j_idx, k_idx, GLITTER_EDITOR_SELECTED_PARTICLE); igPopID(); } igTreePop(); } else - glitter_editor_effects_context_menu(effect, emitter, 0, + glitter_editor_effects_context_menu(glt_edt, effect, emitter, 0, i_idx, j_idx, 0, GLITTER_EDITOR_SELECTED_EMITTER); igPopID(); } igTreePop(); } else - glitter_editor_effects_context_menu(effect, 0, 0, + glitter_editor_effects_context_menu(glt_edt, effect, 0, 0, i_idx, 0, 0, GLITTER_EDITOR_SELECTED_EFFECT); igPopID(); } igPopID(); } -static void glitter_editor_effects_context_menu(glitter_effect* effect, - glitter_emitter* emitter, glitter_particle* particle, +static void glitter_editor_effects_context_menu(glitter_editor_struct* glt_edt, + glitter_effect* effect, glitter_emitter* emitter, glitter_particle* particle, ssize_t i_idx, ssize_t j_idx, ssize_t k_idx, glitter_editor_selected_enum type) { + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_emitter* sel_emit = glt_edt->selected_emitter; + bool focused = igIsItemFocused(); static void* selected; if (type == GLITTER_EDITOR_SELECTED_NONE) { if (igIsWindowHovered(0) && igIsMouseReleased(ImGuiMouseButton_Right)) { - igOpenPopup("effects popup", ImGuiPopupFlags_MouseButtonRight); + igOpenPopup_Str("effects popup", ImGuiPopupFlags_MouseButtonRight); selected = 0; } else if (selected != 0) @@ -2315,7 +2377,7 @@ static void glitter_editor_effects_context_menu(glitter_effect* effect, default: goto End; } - igOpenPopup("effects popup", ImGuiPopupFlags_MouseButtonRight); + igOpenPopup_Str("effects popup", ImGuiPopupFlags_MouseButtonRight); } else switch (type) { @@ -2348,15 +2410,15 @@ static void glitter_editor_effects_context_menu(glitter_effect* effect, switch (type) { case GLITTER_EDITOR_SELECTED_NONE: { if (igMenuItem_Bool("Add Effect", 0, false, true)) { - if (!glitter_editor.effect_group) - glitter_editor.create_popup = true; + if (!glt_edt->effect_group) + glt_edt->create_popup = true; else - glitter_editor.effect_flags |= GLITTER_EDITOR_ADD; + glt_edt->effect_flags |= GLITTER_EDITOR_ADD; close = true; } } break; case GLITTER_EDITOR_SELECTED_EFFECT: { - if (!glitter_editor.effect_group) + if (!glt_edt->effect_group) break; const char* eff_str; @@ -2371,44 +2433,44 @@ static void glitter_editor_effects_context_menu(glitter_effect* effect, else eff_str = "%s (%08X)"; - glitter_effect_group* eg = glitter_editor.effect_group; - igText(eff_str, effect->name, (uint32_t)((size_t)effect * hash_fnv1a64_empty)); + glitter_effect_group* eg = glt_edt->effect_group; + igText(eff_str, effect->name, (uint32_t)((size_t)effect * hash_fnv1a64m_empty)); igSeparator(); if (igMenuItem_Bool("Duplicate Effect", 0, false, true)) { - glitter_editor.effect_flags |= GLITTER_EDITOR_DUPLICATE; - selected_effect = effect; + glt_edt->effect_flags |= GLITTER_EDITOR_DUPLICATE; + glt_edt->selected_effect = effect; close = true; } if (igMenuItem_Bool("Delete Effect", 0, false, true)) { - glitter_editor.effect_flags |= GLITTER_EDITOR_DELETE; - selected_effect = effect; + glt_edt->effect_flags |= GLITTER_EDITOR_DELETE; + glt_edt->selected_effect = effect; close = true; } if (igMenuItem_Bool("Move Effect Up", 0, false, i_idx > 1)) { - glitter_editor.effect_flags |= GLITTER_EDITOR_MOVE_UP; - selected_effect = effect; + glt_edt->effect_flags |= GLITTER_EDITOR_MOVE_UP; + glt_edt->selected_effect = effect; close = true; } if (igMenuItem_Bool("Move Effect Down", 0, false, i_idx < eg->effects.end - eg->effects.begin)) { - glitter_editor.effect_flags |= GLITTER_EDITOR_MOVE_DOWN; - selected_effect = effect; + glt_edt->effect_flags |= GLITTER_EDITOR_MOVE_DOWN; + glt_edt->selected_effect = effect; close = true; } igSeparator(); if (igMenuItem_Bool("Add Emitter", 0, false, true)) { - glitter_editor.emitter_flags |= GLITTER_EDITOR_ADD; - selected_effect = effect; + glt_edt->emitter_flags |= GLITTER_EDITOR_ADD; + glt_edt->selected_effect = effect; close = true; } } break; case GLITTER_EDITOR_SELECTED_EMITTER: { - if (!selected_effect) + if (!glt_edt->selected_effect) break; const char* emit_str; @@ -2425,43 +2487,44 @@ static void glitter_editor_effects_context_menu(glitter_effect* effect, else emit_str = "Emitter %lld (%08X)"; - igText(emit_str, j_idx, (size_t)emitter * hash_fnv1a64_empty); + igText(emit_str, j_idx, (size_t)emitter * hash_fnv1a64m_empty); igSeparator(); if (igMenuItem_Bool("Duplicate Emitter", 0, false, true)) { - glitter_editor.emitter_flags |= GLITTER_EDITOR_DUPLICATE; - selected_emitter = emitter; + glt_edt->emitter_flags |= GLITTER_EDITOR_DUPLICATE; + glt_edt->selected_emitter = emitter; close = true; } if (igMenuItem_Bool("Delete Emitter", 0, false, true)) { - glitter_editor.emitter_flags |= GLITTER_EDITOR_DELETE; - selected_emitter = emitter; + glt_edt->emitter_flags |= GLITTER_EDITOR_DELETE; + glt_edt->selected_emitter = emitter; close = true; } if (igMenuItem_Bool("Move Emitter Up", 0, false, j_idx > 1)) { - glitter_editor.emitter_flags |= GLITTER_EDITOR_MOVE_UP; - selected_emitter = emitter; + glt_edt->emitter_flags |= GLITTER_EDITOR_MOVE_UP; + glt_edt->selected_emitter = emitter; close = true; } if (igMenuItem_Bool("Move Emitter Down", 0, false, - j_idx < selected_effect->emitters.end - selected_effect->emitters.begin)) { - glitter_editor.emitter_flags |= GLITTER_EDITOR_MOVE_DOWN; - selected_emitter = emitter; + j_idx < sel_efct->emitters.end + - sel_efct->emitters.begin)) { + glt_edt->emitter_flags |= GLITTER_EDITOR_MOVE_DOWN; + glt_edt->selected_emitter = emitter; close = true; } igSeparator(); if (igMenuItem_Bool("Add Particle", 0, false, true)) { - glitter_editor.particle_flags |= GLITTER_EDITOR_ADD; - selected_emitter = emitter; + glt_edt->particle_flags |= GLITTER_EDITOR_ADD; + glt_edt->selected_emitter = emitter; close = true; } } break; case GLITTER_EDITOR_SELECTED_PARTICLE: { - if (!selected_emitter) + if (!glt_edt->selected_emitter) break; const char* ptcl_str; @@ -2483,30 +2546,31 @@ static void glitter_editor_effects_context_menu(glitter_effect* effect, break; } - igText(ptcl_str, k_idx, (uint32_t)((size_t)particle * hash_fnv1a64_empty)); + igText(ptcl_str, k_idx, (uint32_t)((size_t)particle * hash_fnv1a64m_empty)); igSeparator(); if (igMenuItem_Bool("Duplicate Particle", 0, false, true)) { - glitter_editor.particle_flags |= GLITTER_EDITOR_DUPLICATE; - selected_particle = particle; + glt_edt->particle_flags |= GLITTER_EDITOR_DUPLICATE; + glt_edt->selected_particle = particle; close = true; } if (igMenuItem_Bool("Delete Particle", 0, false, true)) { - glitter_editor.particle_flags |= GLITTER_EDITOR_DELETE; - selected_particle = particle; + glt_edt->particle_flags |= GLITTER_EDITOR_DELETE; + glt_edt->selected_particle = particle; close = true; } if (igMenuItem_Bool("Move Particle Up", 0, false, k_idx > 1)) { - glitter_editor.particle_flags |= GLITTER_EDITOR_MOVE_UP; - selected_particle = particle; + glt_edt->particle_flags |= GLITTER_EDITOR_MOVE_UP; + glt_edt->selected_particle = particle; close = true; } if (igMenuItem_Bool("Move Particle Down", 0, false, - k_idx < selected_emitter->particles.end - selected_emitter->particles.begin)) { - glitter_editor.particle_flags |= GLITTER_EDITOR_MOVE_DOWN; - selected_particle = particle; + k_idx < sel_emit->particles.end + - sel_emit->particles.begin)) { + glt_edt->particle_flags |= GLITTER_EDITOR_MOVE_DOWN; + glt_edt->selected_particle = particle; close = true; } } break; @@ -2524,31 +2588,36 @@ End: switch (type) { case GLITTER_EDITOR_SELECTED_EFFECT: - if (selected_type != type || selected_effect != effect) - glitter_editor_reset(); - selected_effect = effect; - selected_emitter = 0; - selected_particle = 0; + if (glt_edt->selected_type != type + || glt_edt->selected_effect != effect) + glitter_editor_reset(glt_edt); + glt_edt->selected_effect = effect; + glt_edt->selected_emitter = 0; + glt_edt->selected_particle = 0; break; case GLITTER_EDITOR_SELECTED_EMITTER: - if (selected_type != type || selected_emitter != emitter) - glitter_editor_reset(); - selected_effect = effect; - selected_emitter = emitter; - selected_particle = 0; + if (glt_edt->selected_type != type + || glt_edt->selected_emitter != emitter) + glitter_editor_reset(glt_edt); + glt_edt->selected_effect = effect; + glt_edt->selected_emitter = emitter; + glt_edt->selected_particle = 0; break; case GLITTER_EDITOR_SELECTED_PARTICLE: - if (selected_type != type || selected_particle != particle) - glitter_editor_reset(); - selected_effect = effect; - selected_emitter = emitter; - selected_particle = particle; + if (glt_edt->selected_type != type + || glt_edt->selected_particle != particle) + glitter_editor_reset(glt_edt); + glt_edt->selected_effect = effect; + glt_edt->selected_emitter = emitter; + glt_edt->selected_particle = particle; break; } - selected_type = type; + glt_edt->selected_type = type; } -static void glitter_editor_resources() { +static void glitter_editor_resources(glitter_editor_struct* glt_edt) { + int32_t sel_rsrc = glt_edt->selected_resource; + char buf[0x100]; ImGuiTreeNodeFlags tree_node_base_flags = 0; @@ -2556,8 +2625,8 @@ static void glitter_editor_resources() { tree_node_base_flags |= ImGuiTreeNodeFlags_OpenOnArrow; tree_node_base_flags |= ImGuiTreeNodeFlags_SpanAvailWidth; - glitter_effect_group* eg = glitter_editor.effect_group; - texture** r = eg->resources.begin; + glitter_effect_group* eg = glt_edt->effect_group; + texture** r = eg->resources; int32_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; txp* rt = eg->resources_tex.begin; @@ -2566,7 +2635,7 @@ static void glitter_editor_resources() { for (int32_t i = 0; i < rc; i++, i_idx++) { snprintf(buf, sizeof(buf), "Texture %d (%016llX)", i + 1, rh[i]); igPushID_Int(i); - igSelectable_Bool(buf, i == selected_resource, 0, (ImVec2) { 0.0f, 0.0f }); + igSelectable_Bool(buf, i == sel_rsrc, 0, (ImVec2) { 0.0f, 0.0f }); if (igIsItemHovered(0)) { txp_mipmap* rtm = rt[i].data.begin; float_t aspect = (float_t)rtm->width / (float_t)rtm->height; @@ -2583,19 +2652,20 @@ static void glitter_editor_resources() { ImVec2_Empty, ImVec2_Identity, tint_col, border_col); igEndTooltip(); } - glitter_editor_resources_context_menu(i, i_idx, false); + glitter_editor_resources_context_menu(glt_edt, i, i_idx, false); igPopID(); } igPopID(); } -static void glitter_editor_resources_context_menu(int32_t resource, ssize_t i_idx, bool selected_none) { +static void glitter_editor_resources_context_menu(glitter_editor_struct* glt_edt, + int32_t resource, ssize_t i_idx, bool selected_none) { bool focused = igIsItemFocused(); static size_t selected; if (selected_none) { if (igIsWindowHovered(0) && igIsMouseReleased(ImGuiMouseButton_Right)) { - igOpenPopup("resources popup", ImGuiPopupFlags_MouseButtonRight); + igOpenPopup_Str("resources popup", ImGuiPopupFlags_MouseButtonRight); selected = -1; } else if (selected != -1) @@ -2603,7 +2673,7 @@ static void glitter_editor_resources_context_menu(int32_t resource, ssize_t i_id } else if (igIsItemHovered(0) && igIsMouseReleased(ImGuiMouseButton_Right)) { selected = resource; - igOpenPopup("resources popup", ImGuiPopupFlags_MouseButtonRight); + igOpenPopup_Str("resources popup", ImGuiPopupFlags_MouseButtonRight); } else if (selected != resource) goto End; @@ -2620,39 +2690,39 @@ static void glitter_editor_resources_context_menu(int32_t resource, ssize_t i_id bool close = false; if (selected_none) { if (igMenuItem_Bool("Import Resource", 0, false, true)) { - glitter_editor.resource_flags |= GLITTER_EDITOR_IMPORT; + glt_edt->resource_flags |= GLITTER_EDITOR_IMPORT; close = true; } } else { size_t i = resource; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; ssize_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; igText("Texture %lld (%016llX)", i + 1, rh[i]); igSeparator(); if (igMenuItem_Bool("Export Resource", 0, false, true)) { - glitter_editor.resource_flags |= GLITTER_EDITOR_EXPORT; - selected_resource = resource; + glt_edt->resource_flags |= GLITTER_EDITOR_EXPORT; + glt_edt->selected_resource = resource; close = true; } if (igMenuItem_Bool("Delete Resource", 0, false, true)) { - glitter_editor.resource_flags |= GLITTER_EDITOR_DELETE; - selected_resource = resource; + glt_edt->resource_flags |= GLITTER_EDITOR_DELETE; + glt_edt->selected_resource = resource; close = true; } if (igMenuItem_Bool("Move Resource Up", 0, false, i_idx > 1)) { - glitter_editor.resource_flags |= GLITTER_EDITOR_MOVE_UP; - selected_resource = resource; + glt_edt->resource_flags |= GLITTER_EDITOR_MOVE_UP; + glt_edt->selected_resource = resource; close = true; } if (igMenuItem_Bool("Move Resource Down", 0, false, i_idx < rc)) { - glitter_editor.resource_flags |= GLITTER_EDITOR_MOVE_DOWN; - selected_resource = resource; + glt_edt->resource_flags |= GLITTER_EDITOR_MOVE_DOWN; + glt_edt->selected_resource = resource; close = true; } } @@ -2667,52 +2737,52 @@ End: if (!focused) return; - selected_resource = resource; + glt_edt->selected_resource = resource; } -static void glitter_editor_play_manager() { - glitter_effect_group* eg = glitter_editor.effect_group; +static void glitter_editor_play_manager(glitter_editor_struct* glt_edt) { + glitter_effect_group* eg = glt_edt->effect_group; if (imguiButton("Reset Camera (R)", ImVec2_Empty)) input_reset = true; - ImVec2 t; - igGetContentRegionAvail(&t); + float_t w = imguiGetContentRegionAvailWidth(); if (igBeginTable("buttons", 2, 0, ImVec2_Empty, 0.0f)) { - igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, t.x * 0.5f, 0); + igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * 0.5f, 0); igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Play (T)", (ImVec2) { t.x, 0.0f })) - glitter_editor.input_play = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Play (T)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_T, true)) + glt_edt->input_play = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Reload (Y)", (ImVec2) { t.x, 0.0f })) - glitter_editor.input_reload = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Reload (Y)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_Y, true)) + glt_edt->input_reload = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Pause (F)", (ImVec2) { t.x, 0.0f })) - glitter_editor.input_pause = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Pause (F)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_F, true)) + glt_edt->input_pause = true; igTableNextColumn(); - igGetContentRegionAvail(&t); - if (imguiButton("Reset (G)", (ImVec2) { t.x, 0.0f })) - glitter_editor.input_reset = true; + w = imguiGetContentRegionAvailWidth(); + if (imguiButton("Reset (G)", (ImVec2) { w, 0.0f }) || igIsKeyPressed(GLFW_KEY_G, true)) + glt_edt->input_reset = true; igEndTable(); } igSeparator(); - int32_t frame_counter = glitter_editor.frame_counter; - if (imguiColumnSliderInt("Frame", &frame_counter, glitter_editor.start_frame, - glitter_editor.end_frame, "%d", 0)) { - glitter_editor.old_frame_counter = glitter_editor.frame_counter; - glitter_editor.frame_counter = frame_counter; + int32_t frame_counter = glt_edt->frame_counter; + if (imguiColumnSliderInt("Frame", &frame_counter, glt_edt->start_frame, + glt_edt->end_frame, "%d", 0, true)) { + glt_edt->old_frame_counter = glt_edt->frame_counter; + glt_edt->frame_counter = frame_counter; } + glt_edt->input_pause_temp = igIsItemActivated(); - igText("Start/End Frame: %d/%d", glitter_editor.start_frame, glitter_editor.end_frame); + igText("Start/End Frame: %d/%d", glt_edt->start_frame, glt_edt->end_frame); igSeparator(); @@ -2725,7 +2795,7 @@ static void glitter_editor_play_manager() { frame = 0.0f; life_time = 0; glitter_particle_manager_get_frame(GPM_VAL, &frame, &life_time); - igText("%d - %.0f/%d", max(glitter_editor.frame_counter - glitter_editor.start_frame, 0), frame, life_time); + igText("%d - %.0f/%d", max(glt_edt->frame_counter - glt_edt->start_frame, 0), frame, life_time); ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); @@ -2745,12 +2815,11 @@ static void glitter_editor_play_manager() { igSeparator(); - imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 1.0f, 2.0f, "%.2f", 0); - imguiColumnSliderFloat("Frame Speed", &frame_speed, 0.0f, 3.0f, "%.2f", 0); + imguiColumnSliderFloat("Emission", &GPM_VAL->emission, 0.01f, 1.0f, 2.0f, "%.2f", 0, true); igSeparator(); - imguiCheckbox("Grid", &grid_3d); + imguiCheckbox("Grid", &draw_grid_3d); imguiCheckbox("Draw All", &GPM_VAL->draw_all); @@ -2759,25 +2828,25 @@ static void glitter_editor_play_manager() { imguiDisableElementPop(GPM_VAL->draw_all && eg && eg->type == GLITTER_X); } -static void glitter_editor_property() { - switch (selected_type) { +static void glitter_editor_property(glitter_editor_struct* glt_edt, class_data* data) { + switch (glt_edt->selected_type) { case GLITTER_EDITOR_SELECTED_EFFECT: - glitter_editor_property_effect(); + glitter_editor_property_effect(glt_edt, data); break; case GLITTER_EDITOR_SELECTED_EMITTER: - glitter_editor_property_emitter(); + glitter_editor_property_emitter(glt_edt, data); break; case GLITTER_EDITOR_SELECTED_PARTICLE: - glitter_editor_property_particle(); + glitter_editor_property_particle(glt_edt, data); break; } } -static void glitter_editor_property_effect() { +static void glitter_editor_property_effect(glitter_editor_struct* glt_edt, class_data* data) { imguiSetColumnSpace(2.0f / 5.0f); - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_effect effect = *selected_effect; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_effect effect = *glt_edt->selected_effect; bool changed = false; glitter_curve_type_flags flags = glitter_effect_curve_flags; @@ -2790,8 +2859,8 @@ static void glitter_editor_property_effect() { char name[sizeof(effect.name)]; memcpy(name, effect.name, name_size); if (imguiColumnInputText("Name", name, name_size, 0, 0, 0)) { - effect.data.name_hash = eg->type != GLITTER_AFT - ? hash_utf8_murmurhash(name, 0, false) : hash_utf8_fnv1a64(name); + effect.data.name_hash = eg->type != GLITTER_FT + ? hash_utf8_murmurhash(name, 0, false) : hash_utf8_fnv1a64m(name); memcpy(effect.name, name, name_size - 1); changed = true; } @@ -2909,7 +2978,7 @@ static void glitter_editor_property_effect() { type = 0; if (imguiColumnComboBox("Type", glitter_effect_type_name, - 4, &type, 0, false, &glitter_editor.imgui_focus)) { + 4, &type, 0, false, &data->imgui_focus)) { if (type == 1) { effect.data.flags |= GLITTER_EFFECT_LOCAL; free(effect.data.ext_anim); @@ -2939,7 +3008,7 @@ static void glitter_editor_property_effect() { if (ext_anim.flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { const int32_t max_chara = 4; if (imguiColumnComboBox("Chara Index", glitter_effect_ext_anim_index_name, - max_chara, &ext_anim.chara_index, 0, false, &glitter_editor.imgui_focus)) + max_chara, &ext_anim.chara_index, 0, false, &data->imgui_focus)) ext_anim_changed = true; int32_t node_index = ext_anim.node_index; @@ -2950,7 +3019,7 @@ static void glitter_editor_property_effect() { if (imguiColumnComboBox("Parent Bone", glitter_effect_ext_anim_node_index_name, GLITTER_EFFECT_EXT_ANIM_CHARA_MAX, - &node_index, 0, true, &glitter_editor.imgui_focus)) { + &node_index, 0, true, &data->imgui_focus)) { node_index--; if (node_index < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node_index > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) @@ -2964,13 +3033,13 @@ static void glitter_editor_property_effect() { } else { uint32_t object_hash = (uint32_t)ext_anim.object_hash; - if (glitter_editor_hash_input("Object Hash", &ext_anim.object_hash)) + if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim.object_hash)) ext_anim_changed = true; imguiColumnInputScalar("Instance ID", ImGuiDataType_U32, &ext_anim.instance_id, 0, 0, "%d", ImGuiInputTextFlags_CharsDecimal); - if (glitter_editor_hash_input("File Name Hash", &ext_anim.file_name_hash)) + if (glitter_editor_hash_input(glt_edt, "File Name Hash", &ext_anim.file_name_hash)) ext_anim_changed = true; const size_t mesh_name_size = sizeof(ext_anim.mesh_name); @@ -3014,9 +3083,9 @@ static void glitter_editor_property_effect() { } else { if (ext_anim.flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { - const int32_t max_chara = eg->type == GLITTER_AFT ? 6 : 3; + const int32_t max_chara = eg->type == GLITTER_FT ? 6 : 3; if (imguiColumnComboBox("Chara Index", glitter_effect_ext_anim_index_name, - max_chara, &ext_anim.chara_index, 0, false, &glitter_editor.imgui_focus)) + max_chara, &ext_anim.chara_index, 0, false, &data->imgui_focus)) ext_anim_changed = true; int32_t node_index = ext_anim.node_index; @@ -3027,7 +3096,7 @@ static void glitter_editor_property_effect() { if (imguiColumnComboBox("Parent Bone", glitter_effect_ext_anim_node_index_name, GLITTER_EFFECT_EXT_ANIM_CHARA_MAX, - &node_index, 0, true, &glitter_editor.imgui_focus)) { + &node_index, 0, true, &data->imgui_focus)) { node_index--; if (node_index < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node_index > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) @@ -3040,7 +3109,7 @@ static void glitter_editor_property_effect() { } } else { - if (glitter_editor_hash_input("Object Hash", &ext_anim.object_hash)) + if (glitter_editor_hash_input(glt_edt, "Object Hash", &ext_anim.object_hash)) ext_anim_changed = true; const size_t mesh_name_size = sizeof(ext_anim.mesh_name); @@ -3058,16 +3127,16 @@ static void glitter_editor_property_effect() { ext_anim_changed = true; } - uint64_t hash1 = hash_fnv1a64((void*)effect.data.ext_anim, sizeof(glitter_effect_ext_anim)); - uint64_t hash2 = hash_fnv1a64((void*)&ext_anim, sizeof(glitter_effect_ext_anim)); + uint64_t hash1 = hash_fnv1a64m((void*)effect.data.ext_anim, sizeof(glitter_effect_ext_anim)); + uint64_t hash2 = hash_fnv1a64m((void*)&ext_anim, sizeof(glitter_effect_ext_anim)); if (hash1 != hash2 && ext_anim_changed) { *effect.data.ext_anim = ext_anim; changed = true; } } - uint64_t hash1 = hash_fnv1a64((void*)selected_effect, sizeof(glitter_effect)); - uint64_t hash2 = hash_fnv1a64((void*)&effect, sizeof(glitter_effect)); + uint64_t hash1 = hash_fnv1a64m((void*)glt_edt->selected_effect, sizeof(glitter_effect)); + uint64_t hash2 = hash_fnv1a64m((void*)&effect, sizeof(glitter_effect)); if (hash1 != hash2 && changed) { for (glitter_emitter** i = effect.emitters.begin; i != effect.emitters.end; i++) { if (!*i) @@ -3093,18 +3162,21 @@ static void glitter_editor_property_effect() { particle->data.flags = flags; } } - glitter_editor.input_reload = true; - *selected_effect = effect; + glt_edt->input_reload = true; + *glt_edt->selected_effect = effect; } imguiSetDefaultColumnSpace(); } -static void glitter_editor_property_emitter() { +static void glitter_editor_property_emitter(glitter_editor_struct* glt_edt, class_data* data) { + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_emitter* sel_emit = glt_edt->selected_emitter; + imguiSetColumnSpace(2.0f / 5.0f); - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_emitter emitter = *selected_emitter; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_emitter emitter = *glt_edt->selected_emitter; bool changed = false; glitter_curve_type_flags flags = glitter_emitter_curve_flags; @@ -3114,7 +3186,9 @@ static void glitter_editor_property_emitter() { flags &= ~(1 << i); igText("Parent Effect:\nAppear Time: %d; Life Time: %d; Start Time: %d", - selected_effect->data.appear_time, selected_effect->data.life_time, selected_effect->data.start_time); + sel_efct->data.appear_time, + sel_efct->data.life_time, + sel_efct->data.start_time); igSeparator(); @@ -3130,14 +3204,14 @@ static void glitter_editor_property_emitter() { 1.0f, -0x0001, emitter.data.start_time + emitter.data.life_time, "%d", 0)) { if (emitter.data.loop_start_time < emitter.data.start_time) emitter.data.loop_start_time = 0; - changed = emitter.data.loop_start_time != selected_emitter->data.loop_start_time; + changed = emitter.data.loop_start_time != sel_emit->data.loop_start_time; } if (imguiColumnDragInt("Loop End Time", &emitter.data.loop_end_time, 1.0f, -0x0001, emitter.data.start_time + emitter.data.life_time, "%d", 0)) { if (emitter.data.loop_end_time < 0) emitter.data.loop_end_time = -1; - changed = emitter.data.loop_end_time != selected_emitter->data.loop_end_time; + changed = emitter.data.loop_end_time != sel_emit->data.loop_end_time; } igSeparator(); @@ -3149,8 +3223,7 @@ static void glitter_editor_property_emitter() { changed = true; if (eg->type != GLITTER_X) { - bool draw_z_axis = - emitter.data.direction == GLITTER_DIRECTION_Z_AXIS; + bool draw_z_axis = emitter.data.direction == GLITTER_DIRECTION_Z_AXIS; vec3 rotation = emitter.rotation; if (draw_z_axis) @@ -3223,7 +3296,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Timer Type", glitter_emitter_timer_name, GLITTER_EMITTER_TIMER_BY_DISTANCE, - (int32_t*)&emitter.data.timer, 0, true, &glitter_editor.imgui_focus)) { + (int32_t*)&emitter.data.timer, 0, true, &data->imgui_focus)) { float_t emission_interval = emitter.data.emission_interval; if (emitter.data.timer == GLITTER_EMITTER_TIMER_BY_TIME) emission_interval = clamp(floorf(emission_interval), 1.0f, FLT_MAX); @@ -3252,7 +3325,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Emission Type", glitter_emitter_emission_name, GLITTER_EMITTER_EMISSION_ON_END, - (int32_t*)&emission, 0, true, &glitter_editor.imgui_focus)) { + (int32_t*)&emission, 0, true, &data->imgui_focus)) { float_t emission_interval; switch (emission) { case GLITTER_EMITTER_EMISSION_ON_TIMER: @@ -3298,7 +3371,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Direction", glitter_emitter_direction_name, GLITTER_EMITTER_DIRECTION_EFFECT_ROTATION, - (int32_t*)&direction, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&direction, 0, true, &data->imgui_focus)) if (glitter_emitter_direction_types[direction] != emitter.data.direction) { changed = true; if (eg->type != GLITTER_X) { @@ -3325,7 +3398,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Type", glitter_emitter_name, GLITTER_EMITTER_POLYGON, - (int32_t*)&emitter.data.type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&emitter.data.type, 0, true, &data->imgui_focus)) changed = true; igSeparator(); @@ -3376,7 +3449,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Direction", glitter_emitter_emission_direction_name, GLITTER_EMITTER_EMISSION_DIRECTION_INWARD, - (int32_t*)&emitter.data.cylinder.direction, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&emitter.data.cylinder.direction, 0, true, &data->imgui_focus)) changed = true; igPopID(); } break; @@ -3412,7 +3485,7 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Direction", glitter_emitter_emission_direction_name, GLITTER_EMITTER_EMISSION_DIRECTION_INWARD, - (int32_t*)&emitter.data.sphere.direction, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&emitter.data.sphere.direction, 0, true, &data->imgui_focus)) changed = true; igPopID(); } break; @@ -3431,27 +3504,30 @@ static void glitter_editor_property_emitter() { if (imguiColumnComboBox("Direction", glitter_emitter_emission_direction_name, GLITTER_EMITTER_EMISSION_DIRECTION_INWARD, - (int32_t*)&emitter.data.cylinder.direction, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&emitter.data.cylinder.direction, 0, true, &data->imgui_focus)) changed = true; igPopID(); } break; } - uint64_t hash1 = hash_fnv1a64((void*)selected_emitter, sizeof(glitter_emitter)); - uint64_t hash2 = hash_fnv1a64((void*)&emitter, sizeof(glitter_emitter)); + uint64_t hash1 = hash_fnv1a64m((void*)glt_edt->selected_emitter, sizeof(glitter_emitter)); + uint64_t hash2 = hash_fnv1a64m((void*)&emitter, sizeof(glitter_emitter)); if (hash1 != hash2 && changed) { - glitter_editor.input_reload = true; - *selected_emitter = emitter; + glt_edt->input_reload = true; + *glt_edt->selected_emitter = emitter; } imguiSetDefaultColumnSpace(); } -static void glitter_editor_property_particle() { +static void glitter_editor_property_particle(glitter_editor_struct* glt_edt, class_data* data) { + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_emitter* sel_emit = glt_edt->selected_emitter; + imguiSetColumnSpace(2.0f / 5.0f); - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_particle particle = *selected_particle; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_particle particle = *glt_edt->selected_particle; bool changed = false; glitter_curve_type_flags flags = 0; @@ -3473,11 +3549,15 @@ static void glitter_editor_property_particle() { flags &= ~(1 << i); igText("Parent Effect:\nAppear Time: %d; Life Time: %d; Start Time: %d", - selected_effect->data.appear_time, selected_effect->data.life_time, selected_effect->data.start_time); + sel_efct->data.appear_time, + sel_efct->data.life_time, + sel_efct->data.start_time); igText("Parent Emitter:\nStart Time: %d; Life Time: %d\nLoop Start Time: %d; Loop End Time: %d", - selected_emitter->data.start_time, selected_emitter->data.life_time, - selected_emitter->data.loop_start_time, selected_emitter->data.loop_end_time); + sel_emit->data.start_time, + sel_emit->data.life_time, + sel_emit->data.loop_start_time, + sel_emit->data.loop_end_time); igSeparator(); @@ -3568,7 +3648,7 @@ static void glitter_editor_property_particle() { if (imguiColumnComboBox("Type", glitter_particle_name, GLITTER_PARTICLE_MESH, - (int32_t*)&particle.data.type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&particle.data.type, 0, true, &data->imgui_focus)) changed = true; } else { @@ -3578,14 +3658,14 @@ static void glitter_editor_property_particle() { if (imguiColumnComboBox("Type", glitter_particle_name, GLITTER_PARTICLE_LOCUS, - (int32_t*)&particle.data.type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&particle.data.type, 0, true, &data->imgui_focus)) changed = true; } if (particle.data.type != GLITTER_PARTICLE_MESH && imguiColumnComboBox("Pivot", glitter_pivot_name, GLITTER_PIVOT_BOTTOM_RIGHT, - (int32_t*)&particle.data.pivot, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&particle.data.pivot, 0, true, &data->imgui_focus)) changed = true; if (particle.data.type == GLITTER_PARTICLE_QUAD || particle.data.type == GLITTER_PARTICLE_MESH) { @@ -3600,7 +3680,7 @@ static void glitter_editor_property_particle() { if (imguiColumnComboBox("Draw Type", glitter_particle_draw_type_name, GLITTER_PARTICLE_DRAW_TYPE_EMIT_POSITION, - (int32_t*)&draw_type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&draw_type, 0, true, &data->imgui_focus)) if (glitter_particle_draw_types[draw_type] != particle.data.draw_type) { if (eg->type != GLITTER_X) { bool draw_prev_pos = @@ -3740,9 +3820,9 @@ static void glitter_editor_property_particle() { vec2 speed; speed.x = particle.data.speed; speed.y = particle.data.speed_random; - if (imguiColumnDragVec2("Speed [R]", + if (imguiColumnSliderVec2("Speed [R]", &speed, 0.0001f, -FLT_MAX, FLT_MAX, "%g", - ImGuiSliderFlags_NoRoundToFormat)) { + ImGuiSliderFlags_NoRoundToFormat, false)) { particle.data.speed = speed.x; particle.data.speed_random = speed.y; changed = true; @@ -3792,13 +3872,16 @@ static void glitter_editor_property_particle() { igSeparator(); - if (imguiColumnColorEdit4("Color", &particle.data.color, + vec4 color; + vec4u_to_vec4(particle.data.color, color); + if (imguiColumnColorEdit4("Color", &color, ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaBar)) changed = true; + vec4_to_vec4u(color, particle.data.color); if (imguiColumnComboBox("UV Index Type", glitter_uv_index_type_name, GLITTER_UV_INDEX_USER, - (int32_t*)&particle.data.uv_index_type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&particle.data.uv_index_type, 0, true, &data->imgui_focus)) changed = true; vec2i split; @@ -3863,7 +3946,7 @@ static void glitter_editor_property_particle() { if (particle.data.type != GLITTER_PARTICLE_MESH) { int32_t idx0 = 0; int32_t idx1 = 0; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; size_t rc = eg->resources_count; uint64_t* rh = eg->resource_hashes.begin; for (size_t i = 0; i < rc && (!idx0 || !idx1); i++) { @@ -3887,7 +3970,7 @@ static void glitter_editor_property_particle() { static int32_t tex0_frame; static int32_t tex0_index; static int32_t tex0_tex; - if (glitter_editor_property_particle_texture("Texture", texture_name_list, + if (glitter_editor_property_particle_texture(glt_edt, data, "Texture", texture_name_list, &particle, &particle.data.texture, &particle.data.tex_hash, idx0, &tex0_anim, &tex0_frame, &tex0_index, &tex0_tex)) changed = true; @@ -3897,7 +3980,7 @@ static void glitter_editor_property_particle() { static int32_t tex1_frame; static int32_t tex1_index; static int32_t tex1_tex; - if (glitter_editor_property_particle_texture("Texture Mask", texture_name_list, + if (glitter_editor_property_particle_texture(glt_edt, data, "Texture Mask", texture_name_list, &particle, &particle.data.mask_texture, &particle.data.mask_tex_hash, idx1, &tex11_anim, &tex1_frame, &tex1_index, &tex1_tex)) changed = true; @@ -3914,7 +3997,7 @@ static void glitter_editor_property_particle() { if (imguiColumnComboBox("Blend Mode", glitter_particle_blend_draw_name, GLITTER_PARTICLE_BLEND_DRAW_MULTIPLY, - (int32_t*)&blend_draw, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&blend_draw, 0, true, &data->imgui_focus)) if (glitter_particle_blend_draw_types[blend_draw] != particle.data.blend_mode) { particle.data.blend_mode = glitter_particle_blend_draw_types[blend_draw]; changed = true; @@ -3930,7 +4013,7 @@ static void glitter_editor_property_particle() { if (imguiColumnComboBox("Mask Blend Mode", glitter_particle_blend_mask_name, GLITTER_PARTICLE_BLEND_MASK_MULTIPLY, - (int32_t*)&blend_mask, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&blend_mask, 0, true, &data->imgui_focus)) if (glitter_particle_blend_mask_types[blend_mask] != particle.data.mask_blend_mode) { particle.data.mask_blend_mode = glitter_particle_blend_mask_types[blend_mask]; changed = true; @@ -3987,7 +4070,7 @@ static void glitter_editor_property_particle() { if (imguiColumnDragFloat("Emission", &particle.data.emission, 0.0001f, 0.0f, HALF_MAX, "%g", ImGuiSliderFlags_NoRoundToFormat)) { - if (selected_effect->data.flags & GLITTER_EFFECT_EMISSION + if (sel_efct->data.flags & GLITTER_EFFECT_EMISSION || particle.data.emission >= glitter_min_emission) particle.data.flags |= GLITTER_PARTICLE_EMISSION; else @@ -4016,7 +4099,102 @@ static void glitter_editor_property_particle() { igSeparator(); glitter_particle_mesh* mesh = &particle.data.mesh; - if (glitter_editor_hash_input("Object Set Name Hash", &mesh->object_set_name_hash)) + uint32_t set_id = (uint32_t)mesh->object_set_name_hash; + uint32_t obj_id = (uint32_t)mesh->object_name_hash; + + object_set* set = object_storage_get_object_set(set_id); + ssize_t object_set_count = object_storage_get_object_set_count(); + + imguiStartPropertyColumn("Object Set"); + if (igBeginCombo("##Object Set", set ? string_data(&set->name) : "None", 0)) { + ssize_t set_index = set ? object_storage_get_object_set_index(set_id) : -1; + + igPushID_Int(-1); + if (igSelectable_Bool("None", !set, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + set_index = -1; + igPopID(); + + for (ssize_t i = 0; i < object_set_count; i++) { + igPushID_Int((int32_t)i); + object_set* set = object_storage_get_object_set_by_index(i); + if (igSelectable_Bool(string_data(&set->name), set->id == set_id, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && set->id != set_id)) + set_index = i; + igPopID(); + } + + if (set_index == -1) + set_id = -1; + else + set_id = object_storage_get_object_set_by_index(set_index)->id; + + if (mesh->object_set_name_hash != set_id) { + mesh->object_set_name_hash = set_id; + mesh->object_name_hash = -1; + changed = true; + } + + data->imgui_focus |= true; + igEndCombo(); + } + imguiEndPropertyColumn(); + + imguiDisableElementPush(set_id != -1); + object* obj = 0; + if (set) + for (int32_t i = 0; i < set->objects_count; i++) + if (set->objects[i].id == obj_id) { + obj = &set->objects[i]; + break; + } + + imguiStartPropertyColumn("Object"); + if (igBeginCombo("##Object", obj ? string_data(&obj->name) : "None", 0)) { + if (set && set_id != -1 && set->id == set_id) { + ssize_t obj_index = -1; + for (int32_t i = 0; i < set->objects_count; i++) + if (set->objects[i].id == obj_id) { + obj_index = i; + break; + } + + igPushID_Int(-1); + if (igSelectable_Bool("None", !obj, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && obj)) + obj_index = -1; + igPopID(); + + for (int32_t i = 0; i < set->objects_count; i++) { + igPushID_Int(i); + object* obj = &set->objects[i]; + if (igSelectable_Bool(string_data(&obj->name), obj->id == obj_id, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && obj->id != obj_id)) + obj_index = i; + igPopID(); + } + + if (obj_index == -1 || obj_index >= set->objects_count) + obj_id = -1; + else + obj_id = set->objects[obj_index].id; + + if (mesh->object_name_hash != obj_id) { + mesh->object_name_hash = obj_id; + changed = true; + } + } + + data->imgui_focus |= true; + igEndCombo(); + } + imguiEndPropertyColumn(); + imguiDisableElementPop(set_id != -1); + + /*if (glitter_editor_hash_input("Object Set Name Hash", &mesh->object_set_name_hash)) changed = true; if (glitter_editor_hash_input("Object Name Hash", &mesh->object_name_hash)) @@ -4031,37 +4209,38 @@ static void glitter_editor_property_particle() { } if (glitter_editor_hash_input("Sub Mesh Hash", &mesh->sub_mesh_hash)) - changed = true; + changed = true;*/ } - uint64_t hash1 = hash_fnv1a64((void*)selected_particle, sizeof(glitter_particle)); - uint64_t hash2 = hash_fnv1a64((void*)&particle, sizeof(glitter_particle)); + uint64_t hash1 = hash_fnv1a64m((void*)glt_edt->selected_particle, sizeof(glitter_particle)); + uint64_t hash2 = hash_fnv1a64m((void*)&particle, sizeof(glitter_particle)); if (hash1 != hash2 && changed) { - glitter_editor.input_reload = true; - *selected_particle = particle; + glt_edt->input_reload = true; + *glt_edt->selected_particle = particle; } imguiSetDefaultColumnSpace(); } -static bool glitter_editor_property_particle_texture(char* label, char** items, - glitter_particle* particle, int32_t* tex, uint64_t* tex_hash, int32_t tex_idx, - bool* tex_anim, int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex) { - glitter_effect_group* eg = glitter_editor.effect_group; +static bool glitter_editor_property_particle_texture(glitter_editor_struct* glt_edt, + class_data* data, char* label, char** items, glitter_particle* particle, + int32_t* tex, uint64_t* tex_hash, int32_t tex_idx, bool* tex_anim, + int32_t* tex_frame, int32_t* tex_index, int32_t* tex_tex) { + glitter_effect_group* eg = glt_edt->effect_group; size_t rc = eg->resources_count; - texture** r = eg->resources.begin; + texture** r = eg->resources; uint64_t* rh = eg->resource_hashes.begin; txp* rt = eg->resources_tex.begin; - const uint64_t empty_hash = eg->type != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + const uint64_t empty_hash = eg->type != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; ImVec2 uv_min; ImVec2 uv_max; - const char* temp_label = imguiStartPropertyColumn(label); + imguiStartPropertyColumn(label); int32_t prev_tex_idx = tex_idx; - if (igBeginCombo(temp_label, items[tex_idx], 0)) { + if (igBeginCombo("", items[tex_idx], 0)) { int32_t uv_index = *tex_index; if (!*tex_anim) { *tex_anim = true; @@ -4128,7 +4307,8 @@ static bool glitter_editor_property_particle_texture(char* label, char** items, for (int32_t n = 0; n <= rc; n++) { igPushID_Int(n); if (igSelectable_Bool(items[n], tex_idx == n, 0, ImVec2_Empty) - || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && tex_idx != n)) tex_idx = n; if (igIsItemHovered(0) && n) { @@ -4184,7 +4364,8 @@ static bool glitter_editor_property_particle_texture(char* label, char** items, igBeginTooltip(); igText("Frame: %d\nUV Index %d", *tex_frame, *tex_index); igText("Tex Size: %dx%d", rtm->width, rtm->height); - igImage((void*)(size_t)r[n - 1]->texture, size1, ImVec2_Empty, ImVec2_Identity, tint_col, border_col); + igImage((void*)(size_t)r[n - 1]->texture, size1, + ImVec2_Empty, ImVec2_Identity, tint_col, border_col); igText("Preview Tex Size: %gx%g", particle->data.split_u > 1 ? (float_t)rtm->width / (float_t)particle->data.split_u @@ -4201,7 +4382,7 @@ static bool glitter_editor_property_particle_texture(char* label, char** items, igPopID(); } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= true; igEndCombo(); (*tex_frame)++; } @@ -4212,7 +4393,7 @@ static bool glitter_editor_property_particle_texture(char* label, char** items, *tex_tex = 0; } bool res = prev_tex_idx != tex_idx; - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (res) if (tex_idx) { @@ -4226,7 +4407,7 @@ static bool glitter_editor_property_particle_texture(char* label, char** items, return res; } -static void glitter_editor_popups() { +static void glitter_editor_popups(glitter_editor_struct* glt_edt, class_data* data) { ImGuiIO* io = igGetIO(); ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); @@ -4234,24 +4415,33 @@ static void glitter_editor_popups() { const float_t title_bar_size = font->FontSize + style->ItemSpacing.y + style->FramePadding.y * 2.0f; igPushID_Str("Glitter Editor Glitter File Create Pop-up"); - glitter_editor_file_create_popup(io, style, font, title_bar_size); + glitter_editor_file_create_popup(glt_edt, data, io, style, font, title_bar_size); igPopID(); igPushID_Str("Glitter Editor Glitter File Load Pop-up"); - glitter_editor_file_load_popup(io, style, font, title_bar_size); + glitter_editor_file_load_popup(glt_edt, data, io, style, font, title_bar_size); + igPopID(); + + igPushID_Str("Glitter Editor Glitter File Load Pop-up"); + glitter_editor_file_load_model_popup(glt_edt, data, io, style, font, title_bar_size); igPopID(); igPushID_Str("Glitter Editor Glitter File Load Error List Pop-up"); - glitter_editor_file_load_error_list_popup(io, style, font, title_bar_size); + glitter_editor_file_load_error_list_popup(glt_edt, data, io, style, font, title_bar_size); igPopID(); igPushID_Str("Glitter Editor Glitter File Save"); - glitter_editor_file_save_popup(io, style, font, title_bar_size); + glitter_editor_file_save_popup(glt_edt, data, io, style, font, title_bar_size); igPopID(); } -static void glitter_editor_file_create_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { +static void glitter_editor_file_create_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { + if (glt_edt->create_popup) { + igOpenPopup_Str("Create Glitter File as...", 0); + glt_edt->create_popup = false; + } + float_t x; float_t y; float_t w; @@ -4259,16 +4449,11 @@ static void glitter_editor_file_create_popup(ImGuiIO* io, float_t win_x; float_t win_y; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; ImGuiWindowFlags window_flags; - if (glitter_editor.create_popup) { - igOpenPopup("Create Glitter File as...", 0); - glitter_editor.create_popup = false; - } - - const float_t button_width = 60.0f; + const float_t button_width = 70.0f; win_x = button_width * 2.0f + style->ItemSpacing.x * 1.0f; win_y = title_bar_size + font->FontSize + style->ItemSpacing.y * 1.0f + style->FramePadding.y * 2.0f; @@ -4300,41 +4485,46 @@ static void glitter_editor_file_create_popup(ImGuiIO* io, igTableNextColumn();; igGetContentRegionAvail(&t); - if (imguiButton("F2nd", t)) { - glitter_editor.load_glt_type = GLITTER_F2; + if (imguiButton("F2", t)) { + glt_edt->load_glt_type = GLITTER_F2; close = true; } igTableNextColumn();; igGetContentRegionAvail(&t); - if (imguiButton("AFT", t)) { - glitter_editor.load_glt_type = GLITTER_AFT; + if (imguiButton("FT", t)) { + glt_edt->load_glt_type = GLITTER_FT; close = true; } /*igTableNextColumn(); igGetContentRegionAvail(&t); if (imguiButton("X", t)) { - glitter_editor.load_glt_type = GLITTER_X; + glt_edt->load_glt_type = GLITTER_X; close = true; }*/ if (close) { - glitter_editor.effect_group_add = true; - glitter_editor.effect_flags |= GLITTER_EDITOR_ADD; + glt_edt->effect_group_add = true; + glt_edt->effect_flags |= GLITTER_EDITOR_ADD; igCloseCurrentPopup(); } igEndTable(); } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igEndPopup(); } igEnd(); igPopStyleVar(1); } -static void glitter_editor_file_load_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { +static void glitter_editor_file_load_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { + if (glt_edt->load_popup) { + igOpenPopup_Str("Load Glitter File as...", 0); + glt_edt->load_popup = false; + } + float_t x; float_t y; float_t w; @@ -4344,12 +4534,7 @@ static void glitter_editor_file_load_popup(ImGuiIO* io, ImGuiWindowFlags window_flags; - if (glitter_editor.load_popup) { - igOpenPopup("Load Glitter File as...", 0); - glitter_editor.load_popup = false; - } - - const float_t button_width = 60.0f; + const float_t button_width = 70.0f; win_x = button_width * 3.0f + style->ItemSpacing.x * 2.0f; win_y = title_bar_size + font->FontSize + style->ItemSpacing.y * 2.0f + style->FramePadding.y * 3.0f; @@ -4381,40 +4566,97 @@ static void glitter_editor_file_load_popup(ImGuiIO* io, igTableNextColumn();; igGetContentRegionAvail(&t); - if (imguiButton("F2nd", t)) { - glitter_editor.load_glt_type = GLITTER_F2; + if (imguiButton("F2", t)) { + glt_edt->load_glt_type = GLITTER_F2; close = true; } igTableNextColumn();; igGetContentRegionAvail(&t); - if (imguiButton("AFT", t)) { - glitter_editor.load_glt_type = GLITTER_AFT; + if (imguiButton("FT", t)) { + glt_edt->load_glt_type = GLITTER_FT; close = true; } igTableNextColumn(); igGetContentRegionAvail(&t); if (imguiButton("X", t)) { - glitter_editor.load_glt_type = GLITTER_X; + glt_edt->load_glt_type = GLITTER_X; close = true; } if (close) { - glitter_editor.load = true; + glt_edt->load = true; igCloseCurrentPopup(); } igEndTable(); } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igEndPopup(); } igEnd(); igPopStyleVar(1); } -static void glitter_editor_file_load_error_list_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { +static void glitter_editor_file_load_model_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { + if (!glt_edt->effect_group) { + glt_edt->load_data_popup = false; + return; + } + + bool data_aft_enable = data_list[DATA_AFT].data_paths.end + - data_list[DATA_AFT].data_paths.begin > 0; + bool data_f2le_enable = data_list[DATA_F2LE].data_paths.end + - data_list[DATA_F2LE].data_paths.begin > 0; + bool data_f2be_enable = data_list[DATA_F2BE].data_paths.end + - data_list[DATA_F2BE].data_paths.begin > 0; + bool data_ft_enable = data_list[DATA_FT].data_paths.end + - data_list[DATA_FT].data_paths.begin > 0; + bool data_m39_enable = data_list[DATA_M39].data_paths.end + - data_list[DATA_M39].data_paths.begin > 0; + bool data_vrfl_enable = data_list[DATA_VRFL].data_paths.end + - data_list[DATA_VRFL].data_paths.begin > 0; + bool data_x_enable = data_list[DATA_X].data_paths.end + - data_list[DATA_X].data_paths.begin > 0; + bool data_xhd_enable = data_list[DATA_XHD].data_paths.end + - data_list[DATA_XHD].data_paths.begin > 0; + + int32_t data_count = 0; + switch (glt_edt->effect_group->type) { + case GLITTER_F2: + if (data_f2le_enable) + data_count++; + if (data_f2be_enable) + data_count++; + break; + case GLITTER_FT: + if (data_aft_enable) + data_count++; + if (data_ft_enable) + data_count++; + if (data_m39_enable) + data_count++; + break; + case GLITTER_X: + if (data_x_enable) + data_count++; + if (data_xhd_enable) + data_count++; + if (data_vrfl_enable) + data_count++; + break; + } + + if (glt_edt->load_data_popup) { + if (data_count) + igOpenPopup_Str("Which data should be loaded?", 0); + glt_edt->load_data_popup = false; + } + + if (!data_count) + return; + float_t x; float_t y; float_t w; @@ -4424,10 +4666,153 @@ static void glitter_editor_file_load_error_list_popup(ImGuiIO* io, ImGuiWindowFlags window_flags; - if (glitter_editor.load_error_list_popup) { - igOpenPopup("Glitter File Load Error", 0); - glitter_editor.load_error_list_popup = false; + float_t button_width; + if (data_count == 3) { + button_width = 70.0f; + win_x = button_width * 3.0f + style->ItemSpacing.x * 2.0f; } + else if (data_count == 2) { + button_width = 105.0f; + win_x = button_width * 2.0f + style->ItemSpacing.x; + } + else { + button_width = 210.0f; + win_x = button_width; + } + win_y = title_bar_size + font->FontSize + style->ItemSpacing.y * 2.0f + style->FramePadding.y * 3.0f; + + x = (float_t)width * 0.5f - win_x * 0.5f; + y = (float_t)height * 0.5f - win_y * 0.5f; + w = win_x; + h = win_y; + + window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + window_flags |= ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoScrollbar; + window_flags |= ImGuiWindowFlags_NoScrollWithMouse; + + igPushStyleVar_Vec2(ImGuiStyleVar_WindowTitleAlign, (ImVec2) { 0.5f, 0.5f }); + igSetNextWindowPos((ImVec2) { x, y }, ImGuiCond_Always, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + if (igBeginPopupModal("Which data should be loaded?", 0, window_flags)) { + ImVec2 t; + igGetContentRegionAvail(&t); + x = win_x * 0.5f - t.x * 0.5f; + y = title_bar_size; + + igSetCursorPos((ImVec2) { x, y }); + igGetContentRegionAvail(&t); + if (igBeginTable("buttons", data_count, 0, ImVec2_Empty, 0.0f)) { + bool close = false; + + switch (glt_edt->effect_group->type) { + case GLITTER_F2: + if (data_f2le_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("F2LE", t)) { + glt_edt->load_data_type = DATA_F2LE; + close = true; + } + } + + if (data_f2be_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("F2BE", t)) { + glt_edt->load_data_type = DATA_F2BE; + close = true; + } + } + break; + case GLITTER_FT: + if (data_aft_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("AFT", t)) { + glt_edt->load_data_type = DATA_AFT; + close = true; + } + } + + if (data_ft_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("FT", t)) { + glt_edt->load_data_type = DATA_FT; + close = true; + } + } + + if (data_m39_enable) { + igTableNextColumn(); + igGetContentRegionAvail(&t); + if (imguiButton("M39", t)) { + glt_edt->load_data_type = DATA_M39; + close = true; + } + } + break; + case GLITTER_X: + if (data_x_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("X", t)) { + glt_edt->load_data_type = DATA_X; + close = true; + } + } + + if (data_xhd_enable) { + igTableNextColumn();; + igGetContentRegionAvail(&t); + if (imguiButton("XHD", t)) { + glt_edt->load_data_type = DATA_XHD; + close = true; + } + } + + if (data_vrfl_enable) { + igTableNextColumn(); + igGetContentRegionAvail(&t); + if (imguiButton("VRFL", t)) { + glt_edt->load_data_type = DATA_VRFL; + close = true; + } + } + break; + } + + + if (close) { + glt_edt->load_data = true; + igCloseCurrentPopup(); + } + igEndTable(); + } + data->imgui_focus |= igIsWindowFocused(0); + igEndPopup(); + } + igEnd(); + igPopStyleVar(1); +} + +static void glitter_editor_file_load_error_list_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { + if (glt_edt->load_error_list_popup) { + igOpenPopup_Str("Glitter File Load Error", 0); + glt_edt->load_error_list_popup = false; + } + + float_t x; + float_t y; + float_t w; + float_t h; + float_t win_x; + float_t win_y; + + ImGuiWindowFlags window_flags; win_x = 264.0f; win_y = title_bar_size + font->FontSize * 3.0f @@ -4460,15 +4845,20 @@ static void glitter_editor_file_load_error_list_popup(ImGuiIO* io, y = font->FontSize + style->FramePadding.y * 2.0f; if (imguiButton("OK", (ImVec2) { x, y })) igCloseCurrentPopup(); - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igEndPopup(); } igEnd(); igPopStyleVar(1); } -static void glitter_editor_file_save_popup(ImGuiIO* io, - ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { +static void glitter_editor_file_save_popup(glitter_editor_struct* glt_edt, class_data* data, + ImGuiIO* io, ImGuiStyle* style, ImFont* font, const float_t title_bar_size) { + if (glt_edt->save_popup) { + igOpenPopup_Str("Save Glitter File as...", 0); + glt_edt->save_popup = false; + } + float_t x; float_t y; float_t w; @@ -4476,15 +4866,10 @@ static void glitter_editor_file_save_popup(ImGuiIO* io, float_t win_x; float_t win_y; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; ImGuiWindowFlags window_flags; - if (glitter_editor.save_popup) { - igOpenPopup("Save Glitter File as...", 0); - glitter_editor.save_popup = false; - } - - const float_t button_width = 60.0f; + const float_t button_width = 70.0f; if (eg && eg->type != GLITTER_X) win_x = button_width * 4.0f + style->ItemSpacing.x * 3.0f; @@ -4521,26 +4906,26 @@ static void glitter_editor_file_save_popup(ImGuiIO* io, igTableNextColumn();; igGetContentRegionAvail(&t); if (imguiButton("X", t)) { - glitter_editor.save = true; - glitter_editor.save_compress = false; - glitter_editor.save_glt_type = GLITTER_X; + glt_edt->save = true; + glt_edt->save_compress = false; + glt_edt->save_glt_type = GLITTER_X; close = true; } igTableNextColumn();; igGetContentRegionAvail(&t); if (imguiButton("X HD", t)) { - glitter_editor.save = true; - glitter_editor.save_compress = true; - glitter_editor.save_glt_type = GLITTER_X; + glt_edt->save = true; + glt_edt->save_compress = true; + glt_edt->save_glt_type = GLITTER_X; close = true; } igTableNextColumn(); igGetContentRegionAvail(&t); if (imguiButton("None", t)) { - glitter_editor.save = false; - glitter_editor.save_compress = false; + glt_edt->save = false; + glt_edt->save_compress = false; close = true; } @@ -4556,35 +4941,35 @@ static void glitter_editor_file_save_popup(ImGuiIO* io, igTableNextColumn();; igGetContentRegionAvail(&t); if (imguiButton("F2 PSV", t)) { - glitter_editor.save = true; - glitter_editor.save_compress = false; - glitter_editor.save_glt_type = GLITTER_F2; + glt_edt->save = true; + glt_edt->save_compress = false; + glt_edt->save_glt_type = GLITTER_F2; close = true; } igTableNextColumn();; igGetContentRegionAvail(&t); if (imguiButton("F2 PS3", t)) { - glitter_editor.save = true; - glitter_editor.save_compress = true; - glitter_editor.save_glt_type = GLITTER_F2; + glt_edt->save = true; + glt_edt->save_compress = true; + glt_edt->save_glt_type = GLITTER_F2; close = true; } igTableNextColumn();; igGetContentRegionAvail(&t); - if (imguiButton("AFT", t)) { - glitter_editor.save = true; - glitter_editor.save_compress = false; - glitter_editor.save_glt_type = GLITTER_AFT; + if (imguiButton("FT", t)) { + glt_edt->save = true; + glt_edt->save_compress = false; + glt_edt->save_glt_type = GLITTER_FT; close = true; } igTableNextColumn(); igGetContentRegionAvail(&t); if (imguiButton("None", t)) { - glitter_editor.save = false; - glitter_editor.save_compress = false; + glt_edt->save = false; + glt_edt->save_compress = false; close = true; } @@ -4593,28 +4978,40 @@ static void glitter_editor_file_save_popup(ImGuiIO* io, igEndTable(); } } - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igEndPopup(); } igEnd(); igPopStyleVar(1); } -static float_t convert_height_to_value(float_t val, float_t pos, float_t size, float_t min, float_t max) { - float_t t = (val - pos - curve_editor.height_offset) / (size - curve_editor.height_offset); +static float_t convert_height_to_value(glitter_editor_struct* glt_edt, + float_t val, float_t pos, float_t size, float_t min, float_t max) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + float_t t = (val - pos - crv_edt->height_offset) + / (size - crv_edt->height_offset); return (1.0f - t) * (max - min) + min; } -static float_t convert_value_to_height(float_t val, float_t pos, float_t size, float_t min, float_t max) { +static float_t convert_value_to_height(glitter_editor_struct* glt_edt, + float_t val, float_t pos, float_t size, float_t min, float_t max) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + float_t t = 1.0f - (val - min) / (max - min); - return pos + t * (size - curve_editor.height_offset) + curve_editor.height_offset; + return pos + t * (size - crv_edt->height_offset) + + crv_edt->height_offset; } -static void glitter_editor_curve_editor() { - if (curve_editor.type < GLITTER_CURVE_TRANSLATION_X - || curve_editor.type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) +static void glitter_editor_curve_editor(glitter_editor_struct* glt_edt) { + glitter_emitter* sel_emit = glt_edt->selected_emitter; + glitter_particle* sel_ptcl = glt_edt->selected_particle; + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + if (crv_edt->type < GLITTER_CURVE_TRANSLATION_X + || crv_edt->type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) return; - switch (selected_type) { + switch (glt_edt->selected_type) { case GLITTER_EDITOR_SELECTED_EFFECT: case GLITTER_EDITOR_SELECTED_EMITTER: case GLITTER_EDITOR_SELECTED_PARTICLE: @@ -4623,58 +5020,57 @@ static void glitter_editor_curve_editor() { return; } - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_curve* curve = &curve_editor.curve; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_curve* curve = &crv_edt->curve; vector_glitter_curve_key* keys = &curve->keys_rev; bool changed = false; bool fix_rot_z = eg->type != GLITTER_X && curve->type == GLITTER_CURVE_ROTATION_Z - && ((selected_type == GLITTER_EDITOR_SELECTED_EMITTER - && selected_emitter->data.direction == GLITTER_DIRECTION_Z_AXIS) - || (selected_type == GLITTER_EDITOR_SELECTED_PARTICLE - && selected_particle->data.draw_type == GLITTER_DIRECTION_Z_AXIS)); + && ((glt_edt->selected_type == GLITTER_EDITOR_SELECTED_EMITTER + && sel_emit->data.direction == GLITTER_DIRECTION_Z_AXIS) + || (glt_edt->selected_type == GLITTER_EDITOR_SELECTED_PARTICLE + && sel_ptcl->data.draw_type == GLITTER_DIRECTION_Z_AXIS)); bool add_key = false; bool del_key = false; - glitter_editor_curve_editor_key_manager(keys, &add_key, &del_key); + glitter_editor_curve_editor_key_manager(glt_edt, keys, &add_key, &del_key); if (igIsWindowFocused(0)) { if (add_key && igIsKeyPressed(GLFW_KEY_INSERT, true)) - curve_editor.add_key = true; + crv_edt->add_key = true; else if (del_key && igIsKeyPressed(GLFW_KEY_DELETE, true)) - curve_editor.del_key = true; + crv_edt->del_key = true; else if (igIsKeyPressed(GLFW_KEY_RIGHT, true)) - curve_editor.frame++; + crv_edt->frame++; else if (igIsKeyPressed(GLFW_KEY_LEFT, true)) - curve_editor.frame--; + crv_edt->frame--; } bool exist = true; - if (curve_editor.add_key && add_key) { - if (!curve_editor.list[curve_editor.type] || keys->end - keys->begin == 0) { - glitter_curve_key key; - memset(&key, 0, sizeof(glitter_curve_key)); - key.frame = curve_editor.curve.start_time; + if (crv_edt->add_key && add_key) { + if (!crv_edt->list[crv_edt->type] || keys->end - keys->begin == 0) { + glitter_curve_key* key = vector_glitter_curve_key_reserve_back(keys); + key->frame = crv_edt->curve.start_time; + key->value = glitter_editor_curve_editor_get_value(glt_edt, curve->type); - if (!curve_editor.list[curve_editor.type]) { + if (!crv_edt->list[crv_edt->type]) { glitter_curve* curve = glitter_curve_init(eg->type); - vector_ptr_glitter_curve_push_back(curve_editor.animation, &curve); - curve_editor.list[curve_editor.type] = curve; + vector_ptr_glitter_curve_push_back(crv_edt->animation, &curve); + crv_edt->list[crv_edt->type] = curve; } - glitter_editor_curve_editor_curve_set(curve, curve_editor.type); - vector_glitter_curve_key_push_back(keys, &key); - *curve_editor.list[curve_editor.type] = curve_editor.curve; - curve_editor.frame = curve_editor.curve.start_time; + glitter_editor_curve_editor_curve_set(glt_edt, curve, crv_edt->type); + *crv_edt->list[crv_edt->type] = crv_edt->curve; + crv_edt->frame = crv_edt->curve.start_time; changed = true; } else { glitter_curve_key* i = keys->begin; - bool is_before_start = keys->begin->frame > curve_editor.frame; + bool is_before_start = keys->begin->frame > crv_edt->frame; bool has_key_after = false; if (!is_before_start) for (i++; i != keys->end; i++) - if (curve_editor.frame <= i->frame) { + if (crv_edt->frame <= i->frame) { has_key_after = keys->end - i > 0; break; } @@ -4685,7 +5081,7 @@ static void glitter_editor_curve_editor() { glitter_curve_key key; memset(&key, 0, sizeof(glitter_curve_key)); - key.frame = curve_editor.frame; + key.frame = crv_edt->frame; if (!is_before_start && has_key_after) { glitter_curve_key* c = i - 1; glitter_curve_key* n = i; @@ -4729,13 +5125,13 @@ static void glitter_editor_curve_editor() { key.random_range = c->random_range; vector_glitter_curve_key_insert(keys, ++pos, &key); } - *curve_editor.list[curve_editor.type] = *curve; + *crv_edt->list[crv_edt->type] = *curve; changed = true; } } - else if (curve_editor.del_key && del_key) { + else if (crv_edt->del_key && del_key) { for (glitter_curve_key* i = keys->begin; i != keys->end; i++) - if (i == curve_editor.key) { + if (i == crv_edt->key) { bool has_key_before = keys->begin->frame < i->frame; bool has_key_after = keys->end[-1].frame > i->frame; if (has_key_before && i[-1].type == GLITTER_KEY_HERMITE && has_key_after) { @@ -4768,14 +5164,14 @@ static void glitter_editor_curve_editor() { &n->tangent1, 0, (size_t)n->frame - c->frame); free(v_arr); } - vector_glitter_curve_key_erase(keys, i - keys->begin); + vector_glitter_curve_key_erase(keys, i - keys->begin, 0); changed = true; break; } - glitter_curve* c = curve_editor.list[curve_editor.type]; + glitter_curve* c = crv_edt->list[crv_edt->type]; if (c && keys->end - keys->begin == 0) { - glitter_animation* anim = curve_editor.animation; + glitter_animation* anim = crv_edt->animation; for (glitter_curve** i = anim->begin; i != anim->end; i++) if (*i && *i == c) { vector_ptr_glitter_curve_erase(anim, i - anim->begin, glitter_curve_dispose); @@ -4783,44 +5179,42 @@ static void glitter_editor_curve_editor() { break; } - glitter_editor_curve_editor_curve_reset(curve); - curve_editor.list[curve_editor.type] = 0; + glitter_editor_curve_editor_curve_reset(glt_edt, curve); + crv_edt->list[crv_edt->type] = 0; changed = true; } } - else if (curve_editor.add_curve) { - glitter_curve_key key; - memset(&key, 0, sizeof(glitter_curve_key)); - key.frame = curve->start_time; + else if (crv_edt->add_curve) { + glitter_curve_key* key = vector_glitter_curve_key_reserve_back(keys); + key->frame = crv_edt->curve.start_time; + key->value = glitter_editor_curve_editor_get_value(glt_edt, curve->type); + glitter_curve* c = glitter_curve_init(eg->type); - vector_ptr_glitter_curve_push_back(curve_editor.animation, &c); - curve_editor.list[curve_editor.type] = c; - glitter_editor_curve_editor_curve_set(curve, curve_editor.type); - vector_glitter_curve_key_push_back(keys, &key); - *curve_editor.list[curve_editor.type] = *curve; - curve_editor.frame = curve->start_time; + vector_ptr_glitter_curve_push_back(crv_edt->animation, &c); + crv_edt->list[crv_edt->type] = c; + glitter_editor_curve_editor_curve_set(glt_edt, curve, crv_edt->type); + *crv_edt->list[crv_edt->type] = *curve; + crv_edt->frame = curve->start_time; changed = true; } - else if (curve_editor.del_curve) { - glitter_curve* c = curve_editor.list[curve_editor.type]; - glitter_animation* anim = curve_editor.animation; + else if (crv_edt->del_curve) { + glitter_curve* c = crv_edt->list[crv_edt->type]; + glitter_animation* anim = crv_edt->animation; for (glitter_curve** i = anim->begin; i != anim->end; i++) if (*i && *i == c) { vector_ptr_glitter_curve_erase(anim, i - anim->begin, glitter_curve_dispose); break; } - glitter_editor_curve_editor_curve_reset(curve); - curve_editor.list[curve_editor.type] = 0; - curve_editor.frame = 0; + glitter_editor_curve_editor_curve_reset(glt_edt, curve); + crv_edt->list[crv_edt->type] = 0; + crv_edt->frame = 0; changed = true; } - curve_editor.add_key = false; - curve_editor.del_key = false; - curve_editor.add_curve = false; - curve_editor.del_curve = false; - - curve_editor.key = glitter_editor_curve_editor_get_selected_key(curve); + crv_edt->add_key = false; + crv_edt->del_key = false; + crv_edt->add_curve = false; + crv_edt->del_curve = false; int32_t start_time = curve->start_time; int32_t end_time = curve->end_time; @@ -4833,7 +5227,7 @@ static void glitter_editor_curve_editor() { igGetContentRegionAvail(&cont_reg_avail); ImVec2 canvas_size, canvas_pos, canvas_pos_min, canvas_pos_max; - curve_editor.draw_list = igGetWindowDrawList(); + crv_edt->draw_list = igGetWindowDrawList(); canvas_size = cont_reg_avail; igGetCursorScreenPos(&canvas_pos); canvas_pos_min.x = canvas_pos.x; @@ -4846,15 +5240,16 @@ static void glitter_editor_curve_editor() { boundaries.Max.x = canvas_pos.x + canvas_size.x; boundaries.Max.y = canvas_pos.y + canvas_size.y; - if (curve_editor.zoom_time != curve_editor.prev_zoom_time) { - float_t timeline_pos = curve_editor.timeline_pos + curve_editor_timeline_base_pos; - timeline_pos *= curve_editor.zoom_time / curve_editor.prev_zoom_time; - curve_editor.timeline_pos = timeline_pos - curve_editor_timeline_base_pos; + if (crv_edt->zoom_time != crv_edt->prev_zoom_time) { + float_t timeline_pos = crv_edt->timeline_pos + curve_editor_timeline_base_pos; + timeline_pos *= crv_edt->zoom_time / crv_edt->prev_zoom_time; + crv_edt->timeline_pos = timeline_pos - curve_editor_timeline_base_pos; } - curve_editor.prev_zoom_time = curve_editor.zoom_time; + crv_edt->prev_zoom_time = crv_edt->zoom_time; - float_t frame_width = curve_editor.frame_width * curve_editor.zoom_time; - canvas_pos.x -= curve_editor.timeline_pos; + float_t frame_width = crv_edt->frame_width + * crv_edt->zoom_time; + canvas_pos.x -= crv_edt->timeline_pos; igItemSize_Rect(boundaries, -1.0f); bool hovered = igIsMouseHoveringRect(boundaries.Min, boundaries.Max, true); @@ -4864,16 +5259,23 @@ static void glitter_editor_curve_editor() { if (hovered && igIsMouseClicked(ImGuiMouseButton_Left, false)) can_drag = true; + if (can_drag && (igIsKeyDown(GLFW_KEY_LEFT_SHIFT) || igIsKeyDown(GLFW_KEY_RIGHT_SHIFT))) { + crv_edt->key = glitter_editor_curve_editor_get_closest_key(glt_edt, curve); + crv_edt->frame = crv_edt->key->frame; + } + else + crv_edt->key = glitter_editor_curve_editor_get_selected_key(glt_edt, curve); + if (can_drag && igIsMouseReleased(ImGuiMouseButton_Left)) can_drag = false; float_t timeline_max_offset = (end_time - start_time) * frame_width; timeline_max_offset = max(timeline_max_offset, 0.0f) - curve_editor_timeline_base_pos; - ImDrawList_PushClipRect(curve_editor.draw_list, boundaries.Min, boundaries.Max, true); + ImDrawList_PushClipRect(crv_edt->draw_list, boundaries.Min, boundaries.Max, true); - int32_t start = (int32_t)(curve_editor.timeline_pos / frame_width) + start_time; - int32_t end = (int32_t)((curve_editor.timeline_pos + canvas_size.x) / frame_width) + start_time; + int32_t start = (int32_t)(crv_edt->timeline_pos / frame_width) + start_time; + int32_t end = (int32_t)((crv_edt->timeline_pos + canvas_size.x) / frame_width) + start_time; ImU32 line_color_valid_bold = igGetColorU32_Vec4((ImVec4) { 0.5f, 0.5f, 0.5f, 0.75f }); ImU32 line_color_valid = igGetColorU32_Vec4((ImVec4) { 0.4f, 0.4f, 0.4f, 0.45f }); @@ -4891,18 +5293,18 @@ static void glitter_editor_curve_editor() { ImU32 line_color = valid_frame ? (bold_frame ? line_color_valid_bold : line_color_valid) : line_color_not_valid; - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y - canvas_size.y }, (ImVec2) { x, y }, line_color, 0.80f); if (bold_frame) { char buf[0x20]; snprintf(buf, sizeof(buf), "%d", frame); - ImDrawList_AddText_Vec2(curve_editor.draw_list, + ImDrawList_AddText_Vec2(crv_edt->draw_list, (ImVec2) { x + 3, canvas_pos.y }, line_color, buf, 0); } } - float_t max = curve_editor.range * (1.0f / curve_editor.zoom_value); + float_t max = crv_edt->range * (1.0f / crv_edt->zoom_value); float_t min; if (curve->type == GLITTER_CURVE_EMISSION_INTERVAL) min = -1.0f; @@ -4914,20 +5316,20 @@ static void glitter_editor_curve_editor() { for (int32_t j = 0; j < 5; j++) { float_t x_pos = canvas_pos_min.x; float_t y_pos = canvas_pos.y + j * 0.25f * (canvas_size.y - - curve_editor.height_offset) + curve_editor.height_offset; + - crv_edt->height_offset) + crv_edt->height_offset; ImU32 line_color = j % 2 == 1 ? igGetColorU32_Vec4((ImVec4) { 0.35f, 0.35f, 0.35f, 0.45f }) : igGetColorU32_Vec4((ImVec4) { 0.45f, 0.45f, 0.45f, 0.75f }); bool last = j == 4; if (j && !last) - ImDrawList_AddLine(curve_editor.draw_list, (ImVec2) { x_pos, y_pos }, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x_pos, y_pos }, (ImVec2) { x_pos + canvas_size.x, y_pos }, line_color, 0.80f); float_t val = max - j * 0.25f * (max - min); char buf[0x20]; snprintf(buf, sizeof(buf), "%.2f", val); - ImDrawList_AddText_Vec2(curve_editor.draw_list, (ImVec2) { x_pos + 2, y_pos + (last ? -16 : -2) }, + ImDrawList_AddText_Vec2(crv_edt->draw_list, (ImVec2) { x_pos + 2, y_pos + (last ? -16 : -2) }, igGetColorU32_Vec4((ImVec4) { 0.65f, 0.65f, 0.65f, 0.85f }), buf, 0); } @@ -4940,16 +5342,16 @@ static void glitter_editor_curve_editor() { min *= (float_t)(1.0 / 255.0); } - float_t base_line = convert_value_to_height(0.0f, canvas_pos.y, canvas_size.y, min, max); + float_t base_line = convert_value_to_height(glt_edt, 0.0f, canvas_pos.y, canvas_size.y, min, max); ImVec2 p1, p2, p3; p1.x = canvas_pos_min.x; - p1.y = canvas_pos.y + curve_editor.height_offset; + p1.y = canvas_pos.y + crv_edt->height_offset; p2.x = p1.x + canvas_size.x; - p2.y = canvas_pos.y + curve_editor.height_offset; + p2.y = canvas_pos.y + crv_edt->height_offset; p3.x = canvas_pos_min.x; p3.y = canvas_pos.y; - ImDrawList_AddLine(curve_editor.draw_list, p1, p2, + ImDrawList_AddLine(crv_edt->draw_list, p1, p2, igGetColorU32_Vec4((ImVec4) { 0.5f, 0.5f, 0.5f, 0.85f }), 2.0f); ImU32 random_range_color = igGetColorU32_Vec4((ImVec4) { 0.5f, 0.5f, 0.0f, 0.25f }); @@ -4962,7 +5364,7 @@ static void glitter_editor_curve_editor() { float_t random_range = curve->random_range; bool random_range_mult = curve->flags & GLITTER_CURVE_RANDOM_RANGE_MULT; bool random_range_negate = curve->flags & GLITTER_CURVE_RANDOM_RANGE_NEGATE; - bool glt_type_aft = eg->type == GLITTER_AFT; + bool glt_type_ft = eg->type == GLITTER_FT; for (glitter_curve_key* i = keys->begin; i != keys->end; i++) { if (i->frame >= end_time || keys->end - i <= 1) break; @@ -4990,7 +5392,7 @@ static void glitter_editor_curve_editor() { } float_t c_random_range = c->random_range; float_t n_random_range = n->random_range; - if (random_range_mult && glt_type_aft) { + if (random_range_mult && glt_type_ft) { c_random_range *= c_value; n_random_range *= n_value; } @@ -5001,83 +5403,83 @@ static void glitter_editor_curve_editor() { vec3 random = { random_range, random_range, random_range }; if (random_range_mult) { vec3_mult(random, value, random); - if (!glt_type_aft) + if (!glt_type_ft) vec3_mult_scalar(random, 0.01f, random); } if (value.x != value.y) { - float_t y1 = convert_value_to_height(value.x + random.x, + float_t y1 = convert_value_to_height(glt_edt, value.x + random.x, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.x, + float_t y2 = convert_value_to_height(glt_edt, value.x, canvas_pos.y, canvas_size.y, min, max); - float_t y3 = convert_value_to_height(value.x, + float_t y3 = convert_value_to_height(glt_edt, value.x, canvas_pos.y, canvas_size.y, min, max); - float_t y4 = convert_value_to_height(value.y, + float_t y4 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y1 }, (ImVec2) { x2, y2 }, random_range_color, 0.0f, 0); y3 = clamp(y3, canvas_pos_min.y, canvas_pos_max.y); y4 = clamp(y4, canvas_pos_min.y, canvas_pos_max.y); if (y3 != y4) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y3 }, (ImVec2) { x2, y4 }, key_random_range_color, 0.0f, 0); } else { - float_t y1 = convert_value_to_height(value.y + random.y, + float_t y1 = convert_value_to_height(glt_edt, value.y + random.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.y, + float_t y2 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y1 }, (ImVec2) { x2, y2 }, random_range_color, 0.0f, 0); } if (random_range_negate) if (value.y != value.z) { - float_t y1 = convert_value_to_height(value.y, + float_t y1 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.z, + float_t y2 = convert_value_to_height(glt_edt, value.z, canvas_pos.y, canvas_size.y, min, max); - float_t y3 = convert_value_to_height(value.z, + float_t y3 = convert_value_to_height(glt_edt, value.z, canvas_pos.y, canvas_size.y, min, max); - float_t y4 = convert_value_to_height(value.z - random.z, + float_t y4 = convert_value_to_height(glt_edt, value.z - random.z, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y1 }, (ImVec2) { x2, y2 }, key_random_range_color, 0.0f, 0); y3 = clamp(y3, canvas_pos_min.y, canvas_pos_max.y); y4 = clamp(y4, canvas_pos_min.y, canvas_pos_max.y); if (y3 != y4) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y3 }, (ImVec2) { x2, y4 }, random_range_color, 0.0f, 0); } else { - float_t y1 = convert_value_to_height(value.y, + float_t y1 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.y - random.y, + float_t y2 = convert_value_to_height(glt_edt, value.y - random.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddRectFilled(curve_editor.draw_list, + ImDrawList_AddRectFilled(crv_edt->draw_list, (ImVec2) { x1, y1 }, (ImVec2) { x2, y2 }, random_range_color, 0.0f, 0); } @@ -5110,7 +5512,7 @@ static void glitter_editor_curve_editor() { vec3 random; if (random_range_mult) { vec3_mult(random_vec, value, random); - if (!glt_type_aft) + if (!glt_type_ft) vec3_mult_scalar(random, 0.01f, random); } else @@ -5119,85 +5521,85 @@ static void glitter_editor_curve_editor() { if (random_range_mult) { vec3 random = { random_range, random_range, random_range }; vec3_mult(random, value, random); - if (!glt_type_aft) + if (!glt_type_ft) vec3_mult_scalar(random, 0.01f, random); } float_t x = canvas_pos.x + (float_t)(i - start_time) * frame_width + (float_t)j; if (value.x != value.y) { - float_t y1 = convert_value_to_height(value.x + random.x, + float_t y1 = convert_value_to_height(glt_edt, value.x + random.x, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.x, + float_t y2 = convert_value_to_height(glt_edt, value.x, canvas_pos.y, canvas_size.y, min, max); - float_t y3 = convert_value_to_height(value.x, + float_t y3 = convert_value_to_height(glt_edt, value.x, canvas_pos.y, canvas_size.y, min, max); - float_t y4 = convert_value_to_height(value.y, + float_t y4 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y1 }, (ImVec2) { x, y2 }, random_range_color, 0.0f); y3 = clamp(y3, canvas_pos_min.y, canvas_pos_max.y); y4 = clamp(y4, canvas_pos_min.y, canvas_pos_max.y); if (y3 != y4) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y3 }, (ImVec2) { x, y4 }, key_random_range_color, 0.0f); } else { - float_t y1 = convert_value_to_height(value.y + random.y, + float_t y1 = convert_value_to_height(glt_edt, value.y + random.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.y, + float_t y2 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y1 }, (ImVec2) { x, y2 }, random_range_color, 0.0f); } if (random_range_negate) if (value.y != value.z) { - float_t y1 = convert_value_to_height(value.y, + float_t y1 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.z, + float_t y2 = convert_value_to_height(glt_edt, value.z, canvas_pos.y, canvas_size.y, min, max); - float_t y3 = convert_value_to_height(value.z, + float_t y3 = convert_value_to_height(glt_edt, value.z, canvas_pos.y, canvas_size.y, min, max); - float_t y4 = convert_value_to_height(value.z - random.z, + float_t y4 = convert_value_to_height(glt_edt, value.z - random.z, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y1 }, (ImVec2) { x, y2 }, key_random_range_color, 0.0f); y3 = clamp(y3, canvas_pos_min.y, canvas_pos_max.y); y4 = clamp(y4, canvas_pos_min.y, canvas_pos_max.y); if (y3 != y4) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y3 }, (ImVec2) { x, y4 }, random_range_color, 0.0f); } else { - float_t y1 = convert_value_to_height(value.y, + float_t y1 = convert_value_to_height(glt_edt, value.y, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(value.y - random.y, + float_t y2 = convert_value_to_height(glt_edt, value.y - random.y, canvas_pos.y, canvas_size.y, min, max); y1 = clamp(y1, canvas_pos_min.y, canvas_pos_max.y); y2 = clamp(y2, canvas_pos_min.y, canvas_pos_max.y); if (y1 != y2) - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y1 }, (ImVec2) { x, y2 }, random_range_color, 0.0f); } @@ -5228,8 +5630,8 @@ static void glitter_editor_curve_editor() { } if (i->type != GLITTER_KEY_HERMITE) { - float_t y1 = convert_value_to_height(c_value, canvas_pos.y, canvas_size.y, min, max); - float_t y2 = convert_value_to_height(n_value, canvas_pos.y, canvas_size.y, min, max); + float_t y1 = convert_value_to_height(glt_edt, c_value, canvas_pos.y, canvas_size.y, min, max); + float_t y2 = convert_value_to_height(glt_edt, n_value, canvas_pos.y, canvas_size.y, min, max); if (i->type == GLITTER_KEY_CONSTANT) { ImVec2 points_temp[4]; @@ -5237,10 +5639,10 @@ static void glitter_editor_curve_editor() { points_temp[1] = (ImVec2){ x2, y1 }; points_temp[2] = (ImVec2){ x2, y1 }; points_temp[3] = (ImVec2){ x2, y2 }; - ImDrawList_AddPolyline(curve_editor.draw_list, points_temp, 4, default_color, 0, 3.0f); + ImDrawList_AddPolyline(crv_edt->draw_list, points_temp, 4, default_color, 0, 3.0f); } else - ImDrawList_AddLine(curve_editor.draw_list, + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x1, y1 }, (ImVec2) { x2, y2 }, default_color, 3.0f); } else { @@ -5259,11 +5661,11 @@ static void glitter_editor_curve_editor() { ImVec2 point; point.x = canvas_pos.x + (float_t)(i - start_time) * frame_width + (float_t)j; - point.y = convert_value_to_height(value, + point.y = convert_value_to_height(glt_edt, value, canvas_pos.y, canvas_size.y, min, max); points[(i - c->frame) * frame_width_int + j] = point; } - ImDrawList_AddPolyline(curve_editor.draw_list, points, + ImDrawList_AddPolyline(crv_edt->draw_list, points, (int32_t)points_count, default_color, 0, 3.0f); free(points); } @@ -5288,7 +5690,7 @@ static void glitter_editor_curve_editor() { if (fix_rot_z) base_value -= (float_t)M_PI_2; float_t x = canvas_pos.x + ((size_t)i->frame - start_time) * frame_width; - float_t y = convert_value_to_height(base_value, canvas_pos.y, canvas_size.y, min, max); + float_t y = convert_value_to_height(glt_edt, base_value, canvas_pos.y, canvas_size.y, min, max); if (!(x >= p3.x - 10.0f && x <= p3.x + canvas_size.x + 10.0f) || !(y >= p3.y - 10.0f && y <= p3.y + canvas_size.y + 10.0f)) @@ -5326,10 +5728,10 @@ static void glitter_editor_curve_editor() { if (i->frame >= start_time && i->frame <= end_time) { int32_t start = i - keys->begin > 0 ? (i - 1)->frame + 1 : start_time; int32_t end = keys->end - i > 1 ? (i + 1)->frame - 1 : end_time; - curve_editor.frame = (int32_t)roundf((io->MousePos.x - canvas_pos.x) / frame_width); - curve_editor.frame = clamp(curve_editor.frame + start_time, start, end); - if (i->frame != curve_editor.frame) { - i->frame = curve_editor.frame; + crv_edt->frame = (int32_t)roundf((io->MousePos.x - canvas_pos.x) / frame_width); + crv_edt->frame = clamp(crv_edt->frame + start_time, start, end); + if (i->frame != crv_edt->frame) { + i->frame = crv_edt->frame; changed = true; } } @@ -5349,7 +5751,8 @@ static void glitter_editor_curve_editor() { y += io->MouseDelta.y; if (old_y != y) { - float_t value = convert_height_to_value(y, canvas_pos.y, canvas_size.y, min, max); + float_t value = convert_height_to_value(glt_edt, + y, canvas_pos.y, canvas_size.y, min, max); dragged = true; if (base_value != value) { @@ -5358,7 +5761,7 @@ static void glitter_editor_curve_editor() { i->value = value; changed = true; } - curve_editor.key = i; + crv_edt->key = i; } } @@ -5367,9 +5770,9 @@ static void glitter_editor_curve_editor() { float_t tangent1; ImVec2 circle_pos; circle_pos.x = x - 25.0f; - circle_pos.y = y - base_line + convert_value_to_height(tangent1 = i->tangent1, + circle_pos.y = y - base_line + convert_value_to_height(glt_edt, tangent1 = i->tangent1, canvas_pos.y, canvas_size.y, min, max); - ImDrawList_AddLine(curve_editor.draw_list, (ImVec2) { x, y }, circle_pos, default_color, 1.5f); + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y }, circle_pos, default_color, 1.5f); if ((circle_pos.x >= p3.x - 10.0f && circle_pos.x <= p3.x + canvas_size.x + 10.0f) && (circle_pos.y >= p3.y - 10.0f && circle_pos.y <= p3.y + canvas_size.y + 10.0f)) { @@ -5378,7 +5781,8 @@ static void glitter_editor_curve_editor() { if (can_drag && igIsItemActive()) { if (igIsMouseDragging(ImGuiMouseButton_Left, -1.0f)) { - i->tangent1 = convert_height_to_value(circle_pos.y + io->MouseDelta.y - y + base_line, + i->tangent1 = convert_height_to_value(glt_edt, + circle_pos.y + io->MouseDelta.y - y + base_line, canvas_pos.y, canvas_size.y, min, max); if (i->tangent1 != tangent1) @@ -5390,8 +5794,8 @@ static void glitter_editor_curve_editor() { else tangent1_color = default_color; - ImDrawList_AddCircleFilled(curve_editor.draw_list, circle_pos, - curve_editor.key_radius_in, tangent1_color, 12); + ImDrawList_AddCircleFilled(crv_edt->draw_list, circle_pos, + crv_edt->key_radius_in, tangent1_color, 12); } } @@ -5400,9 +5804,9 @@ static void glitter_editor_curve_editor() { float_t tangent2; ImVec2 circle_pos; circle_pos.x = x + 25.0f; - circle_pos.y = y - base_line + convert_value_to_height(tangent2 = i->tangent2, + circle_pos.y = y - base_line + convert_value_to_height(glt_edt, tangent2 = i->tangent2, canvas_pos.y, canvas_size.y, min, max); - ImDrawList_AddLine(curve_editor.draw_list, (ImVec2) { x, y }, circle_pos, default_color, 1.5f); + ImDrawList_AddLine(crv_edt->draw_list, (ImVec2) { x, y }, circle_pos, default_color, 1.5f); if ((circle_pos.x >= p3.x - 10.0f && circle_pos.x <= p3.x + canvas_size.x + 10.0f) && (circle_pos.y >= p3.y - 10.0f && circle_pos.y <= p3.y + canvas_size.y + 10.0f)) { @@ -5411,7 +5815,8 @@ static void glitter_editor_curve_editor() { if (can_drag && igIsItemActive()) { if (igIsMouseDragging(ImGuiMouseButton_Left, -1.0f)) { - i->tangent2 = convert_height_to_value(circle_pos.y + io->MouseDelta.y - y + base_line, + i->tangent2 = convert_height_to_value(glt_edt, + circle_pos.y + io->MouseDelta.y - y + base_line, canvas_pos.y, canvas_size.y, min, max); if (i->tangent2 != tangent2) @@ -5423,65 +5828,71 @@ static void glitter_editor_curve_editor() { else tangent2_color = default_color; - ImDrawList_AddCircleFilled(curve_editor.draw_list, circle_pos, - curve_editor.key_radius_in, tangent2_color, 12); + ImDrawList_AddCircleFilled(crv_edt->draw_list, circle_pos, + crv_edt->key_radius_in, tangent2_color, 12); } } - ImDrawList_AddCircleFilled(curve_editor.draw_list, (ImVec2) { x, y }, - curve_editor.key_radius_out, curve_editor.key == i ? selected_color : default_color, 12); - ImDrawList_AddCircleFilled(curve_editor.draw_list, (ImVec2) { x, y }, - curve_editor.key_radius_in, value_color, 12); + ImDrawList_AddCircleFilled(crv_edt->draw_list, (ImVec2) { x, y }, + crv_edt->key_radius_out, crv_edt->key == i ? selected_color : default_color, 12); + ImDrawList_AddCircleFilled(crv_edt->draw_list, (ImVec2) { x, y }, + crv_edt->key_radius_in, value_color, 12); igPopID(); } - if (!curve_editor.key_edit && can_drag && io->MouseDown[0] && (!holding_tan || dragged)) { + if (!crv_edt->key_edit && can_drag && io->MouseDown[0] && (!holding_tan || dragged)) { int32_t frame = (int32_t)roundf((io->MousePos.x - canvas_pos.x) / frame_width); - curve_editor.frame = clamp(frame + start_time, start_time, end_time); - curve_editor.key = glitter_editor_curve_editor_get_selected_key(curve); + crv_edt->frame = clamp(frame + start_time, start_time, end_time); + if (igIsKeyDown(GLFW_KEY_LEFT_SHIFT) || igIsKeyDown(GLFW_KEY_RIGHT_SHIFT)) { + crv_edt->key = glitter_editor_curve_editor_get_closest_key(glt_edt, curve); + crv_edt->frame = crv_edt->key->frame; + } + else + crv_edt->key = glitter_editor_curve_editor_get_selected_key(glt_edt, curve); } - curve_editor.frame = clamp(curve_editor.frame, start_time, end_time); + crv_edt->frame = clamp(crv_edt->frame, start_time, end_time); - int32_t cursor_frame = curve_editor.frame - start_time; + int32_t cursor_frame = crv_edt->frame - start_time; ImVec2 cursor_pos = canvas_pos; cursor_pos.x += cursor_frame * frame_width; if (cursor_pos.x >= p1.x - 10.0f && cursor_pos.x <= p1.x + canvas_size.x + 10.0f) { ImU32 cursor_color = igGetColorU32_Vec4((ImVec4) { 0.8f, 0.8f, 0.8f, 0.75f }); p1.x = cursor_pos.x; p1.y = canvas_pos.y + canvas_size.y; - ImDrawList_AddLine(curve_editor.draw_list, cursor_pos, p1, cursor_color, 2.5f); + ImDrawList_AddLine(crv_edt->draw_list, cursor_pos, p1, cursor_color, 2.5f); p1 = p2 = p3 = cursor_pos; p1.x -= 10.0f; p2.y += 10.0f; p3.x += 10.0f; - ImDrawList_AddTriangleFilled(curve_editor.draw_list, p1, p2, p3, cursor_color); + ImDrawList_AddTriangleFilled(crv_edt->draw_list, p1, p2, p3, cursor_color); } - ImDrawList_PopClipRect(curve_editor.draw_list); + ImDrawList_PopClipRect(crv_edt->draw_list); if (hovered) if (igIsKeyDown(GLFW_KEY_LEFT_SHIFT) || igIsKeyDown(GLFW_KEY_RIGHT_SHIFT)) - curve_editor.timeline_pos -= io->MouseWheel * 25.0f * 4.0f; + crv_edt->timeline_pos -= io->MouseWheel * 25.0f * 4.0f; else - curve_editor.timeline_pos -= io->MouseWheel * 25.0f; + crv_edt->timeline_pos -= io->MouseWheel * 25.0f; - curve_editor.timeline_pos = clamp(curve_editor.timeline_pos, + crv_edt->timeline_pos = clamp(crv_edt->timeline_pos, -curve_editor_timeline_base_pos, timeline_max_offset); - if (curve_editor.list[curve_editor.type] && changed) { + if (crv_edt->list[crv_edt->type] && changed) { glitter_curve_recalculate(eg->type, curve); - *curve_editor.list[curve_editor.type] = *curve; - glitter_editor.input_reload = true; + *crv_edt->list[crv_edt->type] = *curve; + glt_edt->input_reload = true; } } -static void glitter_editor_curve_editor_curve_reset(glitter_curve* curve) { +static void glitter_editor_curve_editor_curve_reset(glitter_editor_struct* glt_edt, glitter_curve* curve) { memset(curve, 0, sizeof(glitter_curve)); - glitter_editor_curve_editor_curve_set(curve, -1); + glitter_editor_curve_editor_curve_set(glt_edt, curve, -1); } -static void glitter_editor_curve_editor_curve_set(glitter_curve* curve, glitter_curve_type type) { - glitter_effect_group* eg = glitter_editor.effect_group; +static void glitter_editor_curve_editor_curve_set(glitter_editor_struct* glt_edt, + glitter_curve* curve, glitter_curve_type type) { + glitter_effect_group* eg = glt_edt->effect_group; curve->type = type; if (eg && eg->type == GLITTER_X) { curve->version = 2; @@ -5493,79 +5904,198 @@ static void glitter_editor_curve_editor_curve_set(glitter_curve* curve, glitter_ } } -static void glitter_editor_curve_editor_curves_reset() { - glitter_editor_curve_editor_curve_reset(&curve_editor.curve); - memset(&curve_editor.list, 0, sizeof(glitter_curve*) +static void glitter_editor_curve_editor_curves_reset(glitter_editor_struct* glt_edt) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + glitter_editor_curve_editor_curve_reset(glt_edt, &crv_edt->curve); + memset(&crv_edt->list, 0, sizeof(glitter_curve*) * GLITTER_CURVE_V_SCROLL_ALPHA_2ND - GLITTER_CURVE_TRANSLATION_X + 1); - curve_editor.animation = 0; - curve_editor.key = 0; + crv_edt->animation = 0; + crv_edt->key = 0; } -static glitter_curve_key* glitter_editor_curve_editor_get_selected_key(glitter_curve* curve) { +static glitter_curve_key* glitter_editor_curve_editor_get_closest_key(glitter_editor_struct* glt_edt, + glitter_curve* curve) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + glitter_curve_key* key = 0; vector_glitter_curve_key* keys = &curve->keys_rev; for (glitter_curve_key* i = keys->begin; i != keys->end; i++) { - if (i->frame == curve_editor.frame) + if (i->frame == crv_edt->frame) return i; + + if (!key || (key && abs(i->frame - crv_edt->frame) + <= abs(key->frame - crv_edt->frame))) + key = i; } + return key; +} + +static glitter_curve_key* glitter_editor_curve_editor_get_selected_key(glitter_editor_struct* glt_edt, glitter_curve* curve) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + vector_glitter_curve_key* keys = &curve->keys_rev; + for (glitter_curve_key* i = keys->begin; i != keys->end; i++) + if (i->frame == crv_edt->frame) + return i; return 0; } -static void glitter_editor_curve_editor_key_manager(vector_glitter_curve_key* keys, bool* add_key, bool* del_key) { - glitter_curve* curve = &curve_editor.curve; +static float_t glitter_editor_curve_editor_get_value(glitter_editor_struct* glt_edt, glitter_curve_type type) { + glitter_emitter* sel_emit = glt_edt->selected_emitter; + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_particle* sel_ptcl = glt_edt->selected_particle; + + float_t value = curve_base_values[type]; + switch (glt_edt->selected_type) { + case GLITTER_EDITOR_SELECTED_EFFECT: + switch (type) { + case GLITTER_CURVE_TRANSLATION_X: + value = sel_efct->translation.x; + break; + case GLITTER_CURVE_TRANSLATION_Y: + value = sel_efct->translation.y; + break; + case GLITTER_CURVE_TRANSLATION_Z: + value = sel_efct->translation.z; + break; + case GLITTER_CURVE_ROTATION_X: + value = sel_efct->rotation.x; + break; + case GLITTER_CURVE_ROTATION_Y: + value = sel_efct->rotation.y; + break; + case GLITTER_CURVE_ROTATION_Z: + value = sel_efct->rotation.z; + break; + case GLITTER_CURVE_SCALE_X: + value = sel_efct->scale.x; + break; + case GLITTER_CURVE_SCALE_Y: + value = sel_efct->scale.y; + break; + case GLITTER_CURVE_SCALE_Z: + value = sel_efct->scale.z; + break; + case GLITTER_CURVE_SCALE_ALL: + break; + } + break; + case GLITTER_EDITOR_SELECTED_EMITTER: + switch (type) { + case GLITTER_CURVE_TRANSLATION_X: + value = sel_emit->translation.x; + break; + case GLITTER_CURVE_TRANSLATION_Y: + value = sel_emit->translation.y; + break; + case GLITTER_CURVE_TRANSLATION_Z: + value = sel_emit->translation.z; + break; + case GLITTER_CURVE_ROTATION_X: + value = sel_emit->rotation.x; + break; + case GLITTER_CURVE_ROTATION_Y: + value = sel_emit->rotation.y; + break; + case GLITTER_CURVE_ROTATION_Z: + value = sel_emit->rotation.z; + break; + case GLITTER_CURVE_SCALE_X: + value = sel_emit->scale.x; + break; + case GLITTER_CURVE_SCALE_Y: + value = sel_emit->scale.y; + break; + case GLITTER_CURVE_SCALE_Z: + value = sel_emit->scale.z; + break; + case GLITTER_CURVE_EMISSION_INTERVAL: + value = sel_emit->data.emission_interval; + break; + case GLITTER_CURVE_PARTICLES_PER_EMISSION: + value = sel_emit->data.particles_per_emission; + break; + } + break; + case GLITTER_EDITOR_SELECTED_PARTICLE: + switch (type) { + case GLITTER_CURVE_ROTATION_X: + value = sel_ptcl->data.rotation.x; + break; + case GLITTER_CURVE_ROTATION_Y: + value = sel_ptcl->data.rotation.y; + break; + case GLITTER_CURVE_ROTATION_Z: + value = sel_ptcl->data.rotation.z; + break; + case GLITTER_CURVE_SCALE_X: + value = sel_ptcl->data.scale.x; + break; + case GLITTER_CURVE_SCALE_Y: + value = sel_ptcl->data.scale.y; + break; + case GLITTER_CURVE_SCALE_Z: + value = sel_ptcl->data.scale.z; + break; + case GLITTER_CURVE_COLOR_R: + value = sel_ptcl->data.color.x; + break; + case GLITTER_CURVE_COLOR_G: + value = sel_ptcl->data.color.y; + break; + case GLITTER_CURVE_COLOR_B: + value = sel_ptcl->data.color.z; + break; + case GLITTER_CURVE_COLOR_A: + value = sel_ptcl->data.color.w; + break; + } + break; + } + return value; +} + +static void glitter_editor_curve_editor_key_manager(glitter_editor_struct* glt_edt, + vector_glitter_curve_key* keys, bool* add_key, bool* del_key) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + + glitter_curve* curve = &crv_edt->curve; *add_key = true; *del_key = false; for (glitter_curve_key* i = keys->begin; i != keys->end; i++) if (i->frame > curve->end_time) break; - else if (i->frame == curve_editor.frame) { + else if (i->frame == crv_edt->frame) { *add_key = false; *del_key = true; break; } } -static void glitter_editor_curve_editor_property_window() { - curve_editor.key_edit = false; - if (curve_editor.type < GLITTER_CURVE_TRANSLATION_X - || curve_editor.type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) +static void glitter_editor_curve_editor_property_window(glitter_editor_struct* glt_edt, + class_data* data) { + glitter_emitter* sel_emit = glt_edt->selected_emitter; + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + glitter_particle* sel_ptcl = glt_edt->selected_particle; + + crv_edt->key_edit = false; + if (crv_edt->type < GLITTER_CURVE_TRANSLATION_X + || crv_edt->type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) return; float_t scale; float_t inv_scale; float_t min; - glitter_effect_group* eg = glitter_editor.effect_group; - glitter_curve_type_flags flags = 0; - switch (selected_type) { - case GLITTER_EDITOR_SELECTED_EFFECT: - flags = glitter_effect_curve_flags; - break; - case GLITTER_EDITOR_SELECTED_EMITTER: - flags = glitter_emitter_curve_flags; - break; - case GLITTER_EDITOR_SELECTED_PARTICLE: - if (eg->type == GLITTER_X) - flags = glitter_particle_x_curve_flags; - else - flags = glitter_particle_curve_flags; - - if (selected_particle->data.type != GLITTER_PARTICLE_MESH) { - flags &= ~GLITTER_CURVE_TYPE_UV_SCROLL_2ND; - if (selected_particle->data.draw_type != GLITTER_DIRECTION_PARTICLE_ROTATION) - flags &= ~(GLITTER_CURVE_TYPE_ROTATION_X | GLITTER_CURVE_TYPE_ROTATION_Y); - } - break; - default: - return; - } - - glitter_curve* curve = &curve_editor.curve; + glitter_effect_group* eg = glt_edt->effect_group; + glitter_curve* curve = &crv_edt->curve; bool fix_rot_z = eg->type != GLITTER_X && curve->type == GLITTER_CURVE_ROTATION_Z - && ((selected_type == GLITTER_EDITOR_SELECTED_EMITTER - && selected_emitter->data.direction == GLITTER_DIRECTION_Z_AXIS) - || (selected_type == GLITTER_EDITOR_SELECTED_PARTICLE - && selected_particle->data.draw_type == GLITTER_DIRECTION_Z_AXIS)); + && ((glt_edt->selected_type == GLITTER_EDITOR_SELECTED_EMITTER + && sel_emit->data.direction == GLITTER_DIRECTION_Z_AXIS) + || (glt_edt->selected_type == GLITTER_EDITOR_SELECTED_PARTICLE + && sel_ptcl->data.draw_type == GLITTER_DIRECTION_Z_AXIS)); if (curve->type >= GLITTER_CURVE_ROTATION_X && curve->type <= GLITTER_CURVE_ROTATION_Z) { scale = RAD_TO_DEG_FLOAT; @@ -5593,14 +6123,46 @@ static void glitter_editor_curve_editor_property_window() { bool changed = false; bool key_edit = false; - igText("Frame: %d", curve_editor.frame); + float_t value; + if (curve->keys_rev.end - curve->keys_rev.begin > 1) { + glitter_curve_key* c = curve->keys_rev.begin; + glitter_curve_key* n = curve->keys_rev.end - c > 1 ? curve->keys_rev.begin + 1 : 0; + while (n != curve->keys_rev.end && n->frame < crv_edt->frame) { + c++; + n++; + } - if (curve_editor.key && igTreeNodeEx_Str("Key", ImGuiTreeNodeFlags_DefaultOpen)) { - glitter_curve_key* c = curve_editor.key; - glitter_curve_key* n = curve->keys_rev.end - c > 1 ? curve_editor.key + 1 : 0; + if (c + 1 != curve->keys_rev.end) + switch (c->type) { + case GLITTER_KEY_CONSTANT: + value = n->frame == crv_edt->frame ? n->value : c->value; + break; + case GLITTER_KEY_LINEAR: + value = interpolate_linear_value(c->value, n->value, + (float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame); + break; + case GLITTER_KEY_HERMITE: + value = interpolate_chs_value(c->value, n->value, c->tangent2, n->tangent1, + (float_t)c->frame, (float_t)n->frame, (float_t)crv_edt->frame); + break; + } + } + else if (curve->keys_rev.end - curve->keys_rev.begin == 1) + value = curve->keys_rev.begin->value; + else if (curve->type >= GLITTER_CURVE_TRANSLATION_X && curve->type <= GLITTER_CURVE_V_SCROLL_ALPHA_2ND) + value = glitter_editor_curve_editor_get_value(glt_edt, curve->type); + else + value = 0.0f; + + value *= scale; + igText("Frame: %d; Value: %g", crv_edt->frame, value); + + if (crv_edt->key && igTreeNodeEx_Str("Key", ImGuiTreeNodeFlags_DefaultOpen)) { + glitter_curve_key* c = crv_edt->key; + glitter_curve_key* n = curve->keys_rev.end - c > 1 ? crv_edt->key + 1 : 0; if (imguiColumnComboBox("Type", glitter_key_name, GLITTER_KEY_HERMITE, - (int32_t*)&c->type, 0, true, &glitter_editor.imgui_focus)) + (int32_t*)&c->type, 0, true, &data->imgui_focus)) changed = true; key_edit |= igIsItemFocused(); @@ -5654,7 +6216,7 @@ static void glitter_editor_curve_editor_property_window() { } igTreePop(); } - curve_editor.key_edit = key_edit; + crv_edt->key_edit = key_edit; if (igTreeNodeEx_Str("Curve", ImGuiTreeNodeFlags_DefaultOpen)) { if (imguiCheckbox("Repeat", &curve->repeat)) @@ -5775,7 +6337,7 @@ static void glitter_editor_curve_editor_property_window() { GLITTER_CURVE_NEGATE)) changed = true; - if (imguiCheckboxFlags_UintPtr(eg->type == GLITTER_AFT + if (imguiCheckboxFlags_UintPtr(eg->type == GLITTER_FT ? "Scale Random by Value" : "Scale Random by Value * 0.01", (uint32_t*)&curve->flags, GLITTER_CURVE_RANDOM_RANGE_MULT)) @@ -5784,51 +6346,52 @@ static void glitter_editor_curve_editor_property_window() { igTreePop(); } - if (curve_editor.list[curve_editor.type]) { + if (crv_edt->list[crv_edt->type]) { if (changed) { glitter_curve_recalculate(eg->type, curve); - glitter_editor.input_reload = true; + glt_edt->input_reload = true; } - uint64_t hash1 = hash_fnv1a64((void*)curve_editor.list[curve_editor.type], sizeof(glitter_curve)); - uint64_t hash2 = hash_fnv1a64((void*)curve, sizeof(glitter_effect)); + uint64_t hash1 = hash_fnv1a64m((void*)crv_edt->list[crv_edt->type], sizeof(glitter_curve)); + uint64_t hash2 = hash_fnv1a64m((void*)curve, sizeof(glitter_effect)); if (hash1 != hash2) - *curve_editor.list[curve_editor.type] = *curve; + *crv_edt->list[crv_edt->type] = *curve; } } -static void glitter_editor_curve_editor_reset_state(glitter_curve_type type) { - if (curve_editor.type != type) - curve_editor.type = type; +static void glitter_editor_curve_editor_reset_state(glitter_editor_struct* glt_edt, glitter_curve_type type) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; - curve_editor.frame_width = 16; - curve_editor.zoom_time = 1.0f; - curve_editor.prev_zoom_time = 1.0f; - curve_editor.zoom_value = 1.0f; - curve_editor.key_radius_in = 6.0f; - curve_editor.key_radius_out = 8.0f; - curve_editor.height_offset = 20.0f; - curve_editor.frame = 0; - curve_editor.key = 0; + if (crv_edt->type != type) + crv_edt->type = type; - curve_editor.timeline_pos = -curve_editor_timeline_base_pos; + crv_edt->frame_width = 16; + crv_edt->zoom_time = 1.0f; + crv_edt->prev_zoom_time = 1.0f; + crv_edt->zoom_value = 1.0f; + crv_edt->key_radius_in = 6.0f; + crv_edt->key_radius_out = 8.0f; + crv_edt->height_offset = 20.0f; + crv_edt->frame = 0; + + crv_edt->timeline_pos = -curve_editor_timeline_base_pos; switch (type) { case GLITTER_CURVE_TRANSLATION_X: case GLITTER_CURVE_TRANSLATION_Y: case GLITTER_CURVE_TRANSLATION_Z: - curve_editor.range = 25.0f; + crv_edt->range = 25.0f; break; case GLITTER_CURVE_ROTATION_X: case GLITTER_CURVE_ROTATION_Y: case GLITTER_CURVE_ROTATION_Z: - curve_editor.range = 360.0f; + crv_edt->range = 360.0f; break; case GLITTER_CURVE_SCALE_X: case GLITTER_CURVE_SCALE_Y: case GLITTER_CURVE_SCALE_Z: case GLITTER_CURVE_SCALE_ALL: - curve_editor.range = 5.0f; + crv_edt->range = 5.0f; break; case GLITTER_CURVE_COLOR_R: case GLITTER_CURVE_COLOR_G: @@ -5840,13 +6403,13 @@ static void glitter_editor_curve_editor_reset_state(glitter_curve_type type) { case GLITTER_CURVE_COLOR_B_2ND: case GLITTER_CURVE_COLOR_A_2ND: case GLITTER_CURVE_COLOR_RGB_SCALE_2ND: - curve_editor.range = 255.0f; + crv_edt->range = 255.0f; break; case GLITTER_CURVE_EMISSION_INTERVAL: - curve_editor.range = 20.0f; + crv_edt->range = 20.0f; break; case GLITTER_CURVE_PARTICLES_PER_EMISSION: - curve_editor.range = 50.0f; + crv_edt->range = 50.0f; break; case GLITTER_CURVE_U_SCROLL: case GLITTER_CURVE_V_SCROLL: @@ -5856,47 +6419,53 @@ static void glitter_editor_curve_editor_reset_state(glitter_curve_type type) { case GLITTER_CURVE_V_SCROLL_2ND: case GLITTER_CURVE_U_SCROLL_ALPHA_2ND: case GLITTER_CURVE_V_SCROLL_ALPHA_2ND: - curve_editor.range = 1.0f; + crv_edt->range = 1.0f; break; default: - curve_editor.range = 1.0f; + crv_edt->range = 1.0f; break; } - curve_editor.add_key = false; - curve_editor.del_key = false; + crv_edt->add_key = false; + crv_edt->del_key = false; } -static void glitter_editor_curve_editor_selector() { - glitter_effect_group* eg = glitter_editor.effect_group; +static void glitter_editor_curve_editor_selector(glitter_editor_struct* glt_edt, class_data* data) { + glitter_curve_editor* crv_edt = &glt_edt->curve_editor; + int32_t sel_rsrc = glt_edt->selected_resource; + glitter_effect* sel_efct = glt_edt->selected_effect; + glitter_emitter* sel_emit = glt_edt->selected_emitter; + glitter_particle* sel_ptcl = glt_edt->selected_particle; + + glitter_effect_group* eg = glt_edt->effect_group; glitter_curve_type_flags flags = 0; glitter_animation* anim = 0; - switch (selected_type) { + switch (glt_edt->selected_type) { case GLITTER_EDITOR_SELECTED_EFFECT: flags = glitter_effect_curve_flags; - anim = &selected_effect->animation; + anim = &sel_efct->animation; break; case GLITTER_EDITOR_SELECTED_EMITTER: flags = glitter_emitter_curve_flags; - anim = &selected_emitter->animation; + anim = &sel_emit->animation; break; case GLITTER_EDITOR_SELECTED_PARTICLE: if (eg->type == GLITTER_X) flags = glitter_particle_x_curve_flags; else flags = glitter_particle_curve_flags; - anim = &selected_particle->animation; + anim = &sel_ptcl->animation; - if (selected_particle->data.type != GLITTER_PARTICLE_MESH) { + if (sel_ptcl->data.type != GLITTER_PARTICLE_MESH) { flags &= ~GLITTER_CURVE_TYPE_UV_SCROLL_2ND; - if (selected_particle->data.draw_type != GLITTER_DIRECTION_PARTICLE_ROTATION) + if (sel_ptcl->data.draw_type != GLITTER_DIRECTION_PARTICLE_ROTATION) flags &= ~(GLITTER_CURVE_TYPE_ROTATION_X | GLITTER_CURVE_TYPE_ROTATION_Y); } break; default: return; } - curve_editor.animation = anim; + crv_edt->animation = anim; for (glitter_curve_type i = GLITTER_CURVE_TRANSLATION_X; i <= GLITTER_CURVE_V_SCROLL_ALPHA_2ND; i++) { bool found = false; @@ -5906,9 +6475,10 @@ static void glitter_editor_curve_editor_selector() { found = true; break; } - curve_editor.list[i] = found ? *j : 0; + crv_edt->list[i] = found ? *j : 0; } + bool reset = false; ImVec2 cont_reg_avail; igGetContentRegionAvail(&cont_reg_avail); if (igBeginListBox("##Curves", (ImVec2) { cont_reg_avail.x * 0.5f, cont_reg_avail.y })) { @@ -5920,12 +6490,13 @@ static void glitter_editor_curve_editor_selector() { #define LIST_BOX(label, curve_type) \ if (flags & GLITTER_CURVE_TYPE_##curve_type){ \ - char* _l = curve_editor.list[GLITTER_CURVE_##curve_type] ? label" [*]" : label; \ - if (igSelectable_Bool(_l, curve_editor.type == GLITTER_CURVE_##curve_type, 0, ImVec2_Empty)) \ - glitter_editor_curve_editor_reset_state(GLITTER_CURVE_##curve_type); \ + char* _l = crv_edt->list[GLITTER_CURVE_##curve_type] ? label" [*]" : label; \ + igSelectable_Bool(_l, crv_edt->type == GLITTER_CURVE_##curve_type, 0, ImVec2_Empty); \ \ - if (igIsItemFocused() && curve_editor.type != GLITTER_CURVE_##curve_type) \ - glitter_editor_curve_editor_reset_state(GLITTER_CURVE_##curve_type); \ + if (igIsItemFocused() && crv_edt->type != GLITTER_CURVE_##curve_type) { \ + glitter_editor_curve_editor_reset_state(glt_edt, GLITTER_CURVE_##curve_type); \ + reset = true; \ + } \ } if (flags & GLITTER_CURVE_TYPE_TRANSLATION_XYZ @@ -6008,113 +6579,144 @@ if (flags & GLITTER_CURVE_TYPE_##curve_type){ \ igTreePop(); } #undef LIST_BOX - glitter_editor.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); igEndListBox(); } - if (curve_editor.type < GLITTER_CURVE_TRANSLATION_X || curve_editor.type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) + if (crv_edt->type < GLITTER_CURVE_TRANSLATION_X + || crv_edt->type > GLITTER_CURVE_V_SCROLL_ALPHA_2ND) return; - if (curve_editor.list[curve_editor.type]) - curve_editor.curve = *curve_editor.list[curve_editor.type]; - else if (curve_editor.curve.type != curve_editor.type) { - memset(&curve_editor.curve, 0, sizeof(glitter_curve)); - glitter_editor_curve_editor_curve_set(&curve_editor.curve, curve_editor.type); + if (crv_edt->list[crv_edt->type]) + crv_edt->curve = *crv_edt->list[crv_edt->type]; + else if (crv_edt->curve.type != crv_edt->type) { + memset(&crv_edt->curve, 0, sizeof(glitter_curve)); + glitter_editor_curve_editor_curve_set(glt_edt, &crv_edt->curve, crv_edt->type); } - glitter_curve* curve = &curve_editor.curve; + glitter_curve* curve = &crv_edt->curve; + + if (reset) + crv_edt->key = glitter_editor_curve_editor_get_closest_key(glt_edt, + &crv_edt->curve); igSameLine(0.0f, -1.0f); igBeginGroup(); imguiSetColumnSpace(3.0f / 7.0f); - float_t zoom_time = curve_editor.zoom_time * 100.0f; - imguiColumnSliderFloat("Zoom Time", &zoom_time, 5.0f, 500.0f, "%.1f%%", 0); - curve_editor.zoom_time = zoom_time * 0.01f; + float_t zoom_time = crv_edt->zoom_time * 100.0f; + imguiColumnSliderFloat("Zoom Time", &zoom_time, 1.0f, 5.0f, 500.0f, "%.1f%%", 0, true); + crv_edt->zoom_time = zoom_time * 0.01f; - int32_t zoom_value = (int32_t)roundf(curve_editor.zoom_value * 100.0f); - imguiColumnSliderInt("Zoom Value", &zoom_value, 10, 1000, "%d%%", 0); - curve_editor.zoom_value = (float_t)zoom_value * 0.01f; + int32_t zoom_value = (int32_t)roundf(crv_edt->zoom_value * 100.0f); + imguiColumnSliderInt("Zoom Value", &zoom_value, 10, 1000, "%d%%", 0, true); + crv_edt->zoom_value = (float_t)zoom_value * 0.01f; imguiColumnDragFloat("Range", - &curve_editor.range, 0.0001f, 0.0f, FLT_MAX, "%g", 0); + &crv_edt->range, 0.0001f, 0.0f, FLT_MAX, "%g", 0); imguiSetDefaultColumnSpace(); bool add_key = false; bool del_key = false; - glitter_editor_curve_editor_key_manager(&curve->keys_rev, &add_key, &del_key); + glitter_editor_curve_editor_key_manager(glt_edt, &curve->keys_rev, &add_key, &del_key); igSeparator(); - ImVec2 t; - igGetContentRegionAvail(&t); + float_t w = imguiGetContentRegionAvailWidth(); imguiDisableElementPush(add_key); - if (imguiButton("Add Key", (ImVec2) { t.x, 0.0f })) - curve_editor.add_key = true; + if (imguiButton("Add Key", (ImVec2) { w, 0.0f })) + crv_edt->add_key = true; imguiDisableElementPop(add_key); imguiDisableElementPush(del_key); - if (imguiButton("Delete Key", (ImVec2) { t.x, 0.0f })) - curve_editor.del_key = true; + if (imguiButton("Delete Key", (ImVec2) { w, 0.0f })) + crv_edt->del_key = true; imguiDisableElementPop(del_key); - bool has_curve_in_list = curve_editor.list[curve_editor.type] ? true : false; + bool has_curve_in_list = crv_edt->list[crv_edt->type] ? true : false; imguiDisableElementPush(!has_curve_in_list); - if (imguiButton("Add Curve", (ImVec2) { t.x, 0.0f })) - curve_editor.add_curve = true; + if (imguiButton("Add Curve", (ImVec2) { w, 0.0f })) + crv_edt->add_curve = true; imguiDisableElementPop(!has_curve_in_list); imguiDisableElementPush(has_curve_in_list); - if (imguiButton("Delete Curve", (ImVec2) { t.x, 0.0f })) - curve_editor.del_curve = true; + if (imguiButton("Delete Curve", (ImVec2) { w, 0.0f })) + crv_edt->del_curve = true; imguiDisableElementPop(has_curve_in_list); } -static bool glitter_editor_hash_input(const char* label, uint64_t* hash) { +static bool glitter_editor_hash_input(glitter_editor_struct* glt_edt, const char* label, uint64_t* hash) { uint64_t h = *hash; - if (imguiColumnInputScalar(label, ImGuiDataType_U64, &h, - 0, 0, "%016llX", ImGuiInputTextFlags_CharsHexadecimal)) { - if (h == 0) - h = hash_fnv1a64_empty; - - if (h != *hash) { - *hash = h; - return true; - } + if (glt_edt->effect_group->type == GLITTER_FT) { + if (imguiColumnInputScalar(label, ImGuiDataType_U64, &h, + 0, 0, "%016llX", ImGuiInputTextFlags_CharsHexadecimal) && h == 0) + h = hash_fnv1a64m_empty; } - return false; + else { + if (imguiColumnInputScalar(label, ImGuiDataType_U32, &h, + 0, 0, "%08X", ImGuiInputTextFlags_CharsHexadecimal) && (uint32_t)h == 0) + h = hash_murmurhash_empty; + } + + if (h == *hash) + return false; + + *hash = h; + return true; } -static void glitter_editor_gl_load() { - shader_glsl_param param; +static void glitter_editor_gl_load(glitter_editor_struct* glt_edt) { + const char* glitter_editor_wireframe_vert = + "#version 430 core\n" + "layout (location = 0) in vec3 a_position;\n" + "\n" + "uniform mat4 model;\n" + "\n" + "//COMMONDATA\n" + "\n" + "void main() {\n" + " vec4 pos = model * vec4(a_position, 1.0);\n" + " gl_Position = COMMON_DATA_VP * pos;\n" + "}\n"; + const char* glitter_editor_wireframe_frag = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "uniform vec4 color;\n" + "\n" + "//COMMONDATA\n" + "\n" + "void main(void) {\n" + " result = color;\n" + "}\n"; + + shader_glsl_param param; memset(¶m, 0, sizeof(shader_glsl_param)); param.name = "Glitter Editor Wireframe"; - shader_glsl_load_file(&gl_data.wireframe.shader, - "rom\\shaders\\glt_edt_wrfrm.vert", - "rom\\shaders\\glt_edt_wrfrm.frag", - 0, ¶m); + shader_glsl_load_string(&glt_edt->gl_data.wireframe.shader, + (char*)glitter_editor_wireframe_vert, (char*)glitter_editor_wireframe_frag, 0, ¶m); } -static void glitter_editor_gl_draw() { - if (!glitter_editor.effect_group) +static void glitter_editor_gl_draw(glitter_editor_struct* glt_edt) { + if (!glt_edt->effect_group) return; - if (glitter_editor.draw_flags & GLITTER_EDITOR_DRAW_WIREFRAME) - glitter_editor_gl_draw_wireframe(); + if (glt_edt->draw_flags & GLITTER_EDITOR_DRAW_WIREFRAME) + glitter_editor_gl_draw_wireframe(glt_edt); } -static void glitter_editor_gl_process() { - if (!glitter_editor.effect_group) { +static void glitter_editor_gl_process(glitter_editor_struct* glt_edt) { + if (!glt_edt->effect_group) { glitter_editor_reset_draw(); return; } - glitter_editor_gl_select_particle(); + glitter_editor_gl_select_particle(glt_edt); } -static void glitter_editor_gl_free() { - shader_glsl_free(&gl_data.wireframe.shader); +static void glitter_editor_gl_free(glitter_editor_struct* glt_edt) { + shader_glsl_free(&glt_edt->gl_data.wireframe.shader); } -static void glitter_editor_gl_draw_wireframe() { +static void glitter_editor_gl_draw_wireframe(glitter_editor_struct* glt_edt) { glitter_scene* sc = GPM_VAL->scene; glitter_effect_inst* eff = GPM_VAL->effect; glitter_emitter_inst* emit = GPM_VAL->emitter; @@ -6126,21 +6728,21 @@ static void glitter_editor_gl_draw_wireframe() { size_t count = 0; for (glitter_scene_effect* i = sc->effects.begin; i != sc->effects.end; i++) if (i->draw && i->ptr) - count += glitter_editor_gl_draw_wireframe_calc(i->ptr, 0); + count += glitter_editor_gl_draw_wireframe_calc(glt_edt, i->ptr, 0); if (count == 0) return; for (glitter_scene_effect* i = sc->effects.begin; i != sc->effects.end; i++) if (i->draw && i->ptr) - glitter_editor_gl_draw_wireframe_draw(i->ptr, 0); + glitter_editor_gl_draw_wireframe_draw(glt_edt, i->ptr, 0); } else if ((eff && ptcl) || (eff && !emit)) { - size_t count = glitter_editor_gl_draw_wireframe_calc(eff, ptcl); + size_t count = glitter_editor_gl_draw_wireframe_calc(glt_edt, eff, ptcl); if (count == 0) return; - glitter_editor_gl_draw_wireframe_draw(eff, ptcl); + glitter_editor_gl_draw_wireframe_draw(glt_edt, eff, ptcl); } else if (emit) { size_t count = 0; @@ -6149,12 +6751,12 @@ static void glitter_editor_gl_draw_wireframe() { continue; glitter_particle_inst* particle = *i; - count += glitter_editor_gl_draw_wireframe_calc(eff, particle); + count += glitter_editor_gl_draw_wireframe_calc(glt_edt, eff, particle); if (particle->data.children.begin) { vector_ptr_glitter_particle_inst* children = &particle->data.children; for (glitter_particle_inst** j = children->begin; j != children->end; j++) if (*j) - count += glitter_editor_gl_draw_wireframe_calc(eff, *j); + count += glitter_editor_gl_draw_wireframe_calc(glt_edt, eff, *j); } } @@ -6166,19 +6768,19 @@ static void glitter_editor_gl_draw_wireframe() { continue; glitter_particle_inst* particle = *i; - glitter_editor_gl_draw_wireframe_draw(eff, particle); + glitter_editor_gl_draw_wireframe_draw(glt_edt, eff, particle); if (particle->data.children.begin) { vector_ptr_glitter_particle_inst* children = &particle->data.children; for (glitter_particle_inst** j = children->begin; j != children->end; j++) if (*j) - glitter_editor_gl_draw_wireframe_draw(eff, *j); + glitter_editor_gl_draw_wireframe_draw(glt_edt, eff, *j); } } } } -static size_t glitter_editor_gl_draw_wireframe_calc(glitter_effect_inst* eff, - glitter_particle_inst* ptcl) { +static size_t glitter_editor_gl_draw_wireframe_calc(glitter_editor_struct* glt_edt, + glitter_effect_inst* eff, glitter_particle_inst* ptcl) { size_t count = 0; for (glitter_render_group** i = eff->render_scene.begin; i != eff->render_scene.end; i++) { if (!*i) @@ -6193,16 +6795,17 @@ static size_t glitter_editor_gl_draw_wireframe_calc(glitter_effect_inst* eff, return count; } -static void glitter_editor_gl_draw_wireframe_draw(glitter_effect_inst* eff, - glitter_particle_inst* ptcl) { +static void glitter_editor_gl_draw_wireframe_draw(glitter_editor_struct* glt_edt, + glitter_effect_inst* eff, glitter_particle_inst* ptcl) { gl_state_disable_blend(); gl_state_disable_depth_test(); gl_state_set_depth_mask(GL_FALSE); gl_state_disable_cull_face(); gl_state_set_polygon_mode(GL_FRONT_AND_BACK, GL_LINE); - shader_glsl_use(&gl_data.wireframe.shader); - shader_glsl_set_vec4_value(&gl_data.wireframe.shader, "color", 1.0f, 1.0f, 0.0f, 1.0f); + gl_state_bind_vertex_array(glt_edt->vao); + shader_glsl_use(&glt_edt->gl_data.wireframe.shader); + shader_glsl_set_vec4_value(&glt_edt->gl_data.wireframe.shader, "color", 1.0f, 1.0f, 0.0f, 1.0f); for (glitter_render_group** i = eff->render_scene.begin; i != eff->render_scene.end; i++) { if (!*i) continue; @@ -6213,20 +6816,44 @@ static void glitter_editor_gl_draw_wireframe_draw(glitter_effect_inst* eff, else if (rg->disp < 1) continue; - shader_glsl_set_mat4(&gl_data.wireframe.shader, "model", false, rg->mat_draw); + shader_glsl_set_mat4(&glt_edt->gl_data.wireframe.shader, "model", false, rg->mat_draw); - gl_state_bind_vertex_array(rg->vao); switch (rg->type) { - case GLITTER_PARTICLE_QUAD: + case GLITTER_PARTICLE_QUAD: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(rg->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(rg->ebo); glDrawElements(GL_TRIANGLES, (GLsizei)(6 * rg->disp), GL_UNSIGNED_INT, 0); - break; + gl_state_bind_element_array_buffer(0); + + glDisableVertexAttribArray(0); + } break; case GLITTER_PARTICLE_LINE: case GLITTER_PARTICLE_LOCUS: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(rg->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + gl_state_bind_array_buffer(0); + const GLenum mode = rg->type == GLITTER_PARTICLE_LINE ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; const size_t count = rg->vec_key.end - rg->vec_key.begin; for (size_t i = 0; i < count; i++) glDrawArrays(mode, rg->vec_key.begin[i], rg->vec_val.begin[i]); + + glDisableVertexAttribArray(0); } break; + case GLITTER_PARTICLE_MESH: + glitter_editor_gl_draw_wireframe_draw_mesh(glt_edt, rg); + break; } } gl_state_bind_vertex_array(0); @@ -6234,14 +6861,124 @@ static void glitter_editor_gl_draw_wireframe_draw(glitter_effect_inst* eff, shader_glsl_use(0); } -static void glitter_editor_gl_select_particle() { +static void glitter_editor_gl_draw_wireframe_draw_mesh(glitter_editor_struct* glt_edt, + glitter_render_group* rg) { + glitter_render_element* elem = rg->elements; + for (size_t i = rg->ctrl, j_max = 1024; i > 0; i -= j_max) { + j_max = min(i, j_max); + for (size_t j = j_max; j > 0; elem++) { + if (!elem->alive) + continue; + j--; + + if (!elem->draw) + continue; + + render_context* rctx = GPM_VAL->rctx; + object_data* object_data = &rctx->object_data; + + glitter_particle* particle = rg->particle->data.particle; + object_info object_info; + object_info.set_id = (uint32_t)particle->data.mesh.object_set_name_hash; + object_info.id = (uint32_t)particle->data.mesh.object_name_hash; + object* obj = object_storage_get_object(object_info); + object_mesh_vertex_buffer* obj_vertex_buffer + = object_storage_get_object_mesh_vertex_buffer(object_info); + object_mesh_index_buffer* obj_index_buffer + = object_storage_get_object_mesh_index_buffer(object_info); + + mat4 mat = elem->mat_draw; + if (!obj || !obj_vertex_buffer || !obj_index_buffer || (object_data->object_culling + && !object_bounding_sphere_check_visibility(&obj->bounding_sphere, + object_data, rctx->camera, &mat))) + continue; + + shader_glsl_set_mat4(&glt_edt->gl_data.wireframe.shader, "model", false, mat); + + int32_t ttc = 0; + texture_transform_struct* tt = object_data->texture_transform_array; + for (int32_t i = 0; i < obj->meshes_count; i++) { + object_mesh* mesh = &obj->meshes[i]; + + if (object_data->object_culling && !object_bounding_sphere_check_visibility( + &mesh->bounding_sphere, object_data, rctx->camera, &mat)) + continue; + + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; + + if (sub_mesh->flags & OBJECT_SUB_MESH_FLAG_8) + continue; + + if (object_data->object_culling) { + int32_t v32 = object_bounding_sphere_check_visibility( + &sub_mesh->bounding_sphere, object_data, rctx->camera, &mat); + if (v32 != 2 || (~mesh->flags & OBJECT_MESH_BILLBOARD && + ~mesh->flags & OBJECT_MESH_BILLBOARD_Y_AXIS)) { + if (v32 == 2) { + if (object_data->object_bounding_sphere_check_func) + v32 = 1; + else + v32 = object_axis_aligned_bounding_box_check_visibility( + &sub_mesh->axis_aligned_bounding_box, rctx->camera, &mat); + } + + if (!v32) + continue; + } + } + + GLenum mesh_draw_mode[] = { + [OBJECT_PRIMITIVE_POINTS] = GL_ZERO, //GL_POINTS, + [OBJECT_PRIMITIVE_LINES] = GL_LINES, + [OBJECT_PRIMITIVE_LINE_STRIP] = GL_LINE_STRIP, + [OBJECT_PRIMITIVE_LINE_LOOP] = GL_LINE_LOOP, + [OBJECT_PRIMITIVE_TRIANGLES] = GL_TRIANGLES, + [OBJECT_PRIMITIVE_TRIANGLE_STRIP] = GL_TRIANGLE_STRIP, + [OBJECT_PRIMITIVE_TRIANGLE_FAN] = GL_TRIANGLE_FAN, + [OBJECT_PRIMITIVE_QUADS] = GL_ZERO, //GL_QUADS, + [OBJECT_PRIMITIVE_QUAD_STRIP] = GL_ZERO, //GL_QUAD_STRIP, + [OBJECT_PRIMITIVE_POLYGON] = GL_ZERO, //GL_POLYGON, + }; + + GLenum mesh_indices_type[] = { + [OBJECT_INDEX_U8] = GL_ZERO, + [OBJECT_INDEX_U16] = GL_UNSIGNED_SHORT, + [OBJECT_INDEX_U32] = GL_UNSIGNED_INT, + }; + + GLuint array_buffer = object_mesh_vertex_buffer_get_buffer(&obj_vertex_buffer[i]); + gl_state_bind_array_buffer(array_buffer); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, mesh->vertex_size, (void*)0); + gl_state_bind_array_buffer(0); + + GLuint element_array_buffer = obj_index_buffer[i]; + gl_state_bind_element_array_buffer(element_array_buffer); + if (sub_mesh->primitive_type == OBJECT_PRIMITIVE_TRIANGLE_STRIP + && sub_mesh->index_format == OBJECT_INDEX_U16) + glDrawRangeElements(GL_TRIANGLE_STRIP, sub_mesh->first_index, sub_mesh->last_index, + sub_mesh->indices_count, GL_UNSIGNED_SHORT, (void*)(size_t)sub_mesh->indices_offset); + else + glDrawElements(mesh_draw_mode[sub_mesh->primitive_type], sub_mesh->indices_count, + mesh_indices_type[sub_mesh->index_format], (void*)(size_t)sub_mesh->indices_offset); + gl_state_bind_element_array_buffer(0); + + glDisableVertexAttribArray(0); + } + } + } + } +} + +static void glitter_editor_gl_select_particle(glitter_editor_struct* glt_edt) { GPM_VAL->scene = 0; GPM_VAL->effect = 0; GPM_VAL->emitter = 0; GPM_VAL->particle = 0; GPM_VAL->draw_selected = false; - glitter_effect_group* eg = glitter_editor.effect_group; + glitter_effect_group* eg = glt_edt->effect_group; glitter_scene* sc = 0; for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end; i++) { if (!*i) @@ -6264,7 +7001,7 @@ static void glitter_editor_gl_select_particle() { continue; glitter_effect_inst* effect = i->ptr; - if (effect->effect != selected_effect) + if (effect->effect != glt_edt->selected_effect) continue; eff = effect; @@ -6273,7 +7010,7 @@ static void glitter_editor_gl_select_particle() { continue; glitter_emitter_inst* emitter = *j; - if (emitter->emitter != selected_emitter) + if (emitter->emitter != glt_edt->selected_emitter) continue; emit = emitter; @@ -6282,7 +7019,7 @@ static void glitter_editor_gl_select_particle() { continue; glitter_particle_inst* particle = *k; - if (particle->particle == selected_particle) { + if (particle->particle == glt_edt->selected_particle) { ptcl = particle; break; } @@ -6300,7 +7037,7 @@ static void glitter_editor_gl_select_particle() { continue; glitter_particle_inst* particle = *i; - if (particle->particle == selected_particle) { + if (particle->particle == glt_edt->selected_particle) { ptcl = particle; break; } @@ -6314,6 +7051,7 @@ static void glitter_editor_gl_select_particle() { GPM_VAL->effect = eff; GPM_VAL->emitter = emit; GPM_VAL->particle = ptcl; - GPM_VAL->draw_selected = glitter_editor.draw_flags & GLITTER_EDITOR_DRAW_SELECTED; + GPM_VAL->draw_selected = glt_edt->draw_flags & GLITTER_EDITOR_DRAW_SELECTED; + GPM_VAL->no_draw = glt_edt->draw_flags & GLITTER_EDITOR_DRAW_NO_DRAW; } #endif diff --git a/src/CLOUD/classes/glitter_editor.h b/src/CLOUD/classes/glitter_editor.h new file mode 100644 index 00000000..19e82380 --- /dev/null +++ b/src/CLOUD/classes/glitter_editor.h @@ -0,0 +1,19 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#if defined(CLOUD_DEV) +#include "../../KKdLib/default.h" +#include "../classes.h" + +extern bool glitter_editor_init(class_data* data, render_context* rctx); +extern void glitter_editor_draw(class_data* data); +extern void glitter_editor_drop(class_data* data, size_t count, char** paths); +extern void glitter_editor_imgui(class_data* data); +extern void glitter_editor_input(class_data* data); +extern void glitter_editor_render(class_data* data); +extern bool glitter_editor_dispose(class_data* data); +#endif diff --git a/src/CLOUD/classes/graphics.c b/src/CLOUD/classes/graphics.c index 8dc43536..923e75ed 100644 --- a/src/CLOUD/classes/graphics.c +++ b/src/CLOUD/classes/graphics.c @@ -5,78 +5,92 @@ #include "graphics.h" -bool graphics_enabled = true; - classes_struct graphics_classes[] = { { - .name = "Background Color", + .name = "Background Color##Graphics", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &background_color_enabled, - .dispose = (void*)background_color_dispose, - .init = (void*)background_color_init, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)background_color_imgui, - .input = (void*)background_color_input, - .render = (void*)background_color_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = graphics_background_color_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = graphics_background_color_imgui, + .input = graphics_background_color_input, + .render = graphics_background_color_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = graphics_background_color_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, { - .name = "Post Process", + .name = "Post Process##Graphics", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &post_process_enabled, - .dispose = (void*)post_process_dispose, - .init = (void*)post_process_init, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)post_process_imgui, - .input = (void*)post_process_input, - .render = (void*)post_process_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = graphics_post_process_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = graphics_post_process_imgui, + .input = graphics_post_process_input, + .render = graphics_post_process_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = graphics_post_process_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, { - .name = "Glitter##Counter", + .name = "Glitter##Graphics", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &glitter_counter_enabled, - .dispose = (void*)glitter_counter_dispose, - .init = (void*)glitter_counter_init, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)glitter_counter_imgui, - .input = (void*)glitter_counter_input, - .render = (void*)glitter_counter_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = graphics_glitter_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = graphics_glitter_imgui, + .input = graphics_glitter_input, + .render = graphics_glitter_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = graphics_glitter_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, { - .name = "Render Settings", + .name = "Render Settings##Graphics", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &render_settings_enabled, - .dispose = (void*)render_settings_dispose, - .init = (void*)render_settings_init, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)render_settings_imgui, - .input = (void*)render_settings_input, - .render = (void*)render_settings_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = graphics_render_settings_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = graphics_render_settings_imgui, + .input = graphics_render_settings_input, + .render = graphics_render_settings_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = graphics_render_settings_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, diff --git a/src/CLOUD/classes/graphics.h b/src/CLOUD/classes/graphics.h index a721d7bf..d2937112 100644 --- a/src/CLOUD/classes/graphics.h +++ b/src/CLOUD/classes/graphics.h @@ -7,9 +7,8 @@ #include "../classes.h" #include "graphics/background_color.h" -#include "graphics/glitter_counter.h" +#include "graphics/glitter.h" #include "graphics/post_process.h" #include "graphics/render_settings.h" -extern bool graphics_enabled; extern classes_struct graphics_classes[]; diff --git a/src/CLOUD/classes/graphics/background_color.c b/src/CLOUD/classes/graphics/background_color.c index 9b4b6d55..516ce561 100644 --- a/src/CLOUD/classes/graphics/background_color.c +++ b/src/CLOUD/classes/graphics/background_color.c @@ -4,98 +4,74 @@ */ #include "background_color.h" +#include "../../../KKdLib/vec.h" #include "../imgui_helper.h" -typedef struct background_color_struct { - bool dispose; - bool disposed; - bool imgui_focus; -} background_color_struct; - extern int32_t width; extern int32_t height; extern bool input_locked; extern vec3 back3d_color; extern bool set_clear_color; -const char* background_color_window_title = "Background Color"; +static const char* graphics_background_color_window_title = "Background Color##Graphics"; -bool background_color_enabled = false; -static background_color_struct background_color; - -void background_color_dispose() { - background_color_enabled = false; - background_color.imgui_focus = false; - background_color.dispose = false; - background_color.disposed = true; +bool graphics_background_color_init(class_data* data, render_context* rctx) { + graphics_background_color_dispose(data); + return true; } -void background_color_init() { - if (background_color_enabled || background_color.dispose) - background_color_dispose(); +void graphics_background_color_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); - background_color_enabled = true; -} - -void background_color_imgui() { - if (!background_color_enabled) { - if (!background_color.disposed) - background_color.dispose = true; - return; - } - else if (background_color.disposed) - background_color_enabled = true; - - float_t w = min((float_t)width / 4.0f, 360.0f); + float_t w = min((float_t)width, 360.0f); float_t h = min((float_t)height, 100.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); - igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); ImGuiWindowFlags window_flags = 0; window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - background_color.imgui_focus = false; - if (!igBegin(background_color_window_title, &background_color_enabled, window_flags)) { - background_color.dispose = true; - igEnd(); - return; + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(graphics_background_color_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; } - - ImVec2 temp; - igGetContentRegionAvail(&temp); + else if (collapsed) + goto End; ImGuiColorEditFlags color_edit_flags = 0; color_edit_flags |= ImGuiColorEditFlags_NoLabel; color_edit_flags |= ImGuiColorEditFlags_NoSidePreview; color_edit_flags |= ImGuiColorEditFlags_NoDragDrop; - igSetNextItemWidth(temp.x); + imguiGetContentRegionAvailSetNextItemWidth(); igColorEdit3("##Background Color", (float_t*)&back3d_color, color_edit_flags); igCheckbox("Set Clear Color", &set_clear_color); if (imguiButton("Reset Color", ImVec2_Empty)) { - back3d_color = (vec3){ 0.74117647f, 0.74117647f, 0.74117647f }; + back3d_color = (vec3){ (float_t)(96.0 / 255.0), (float_t)(96.0 / 255.0), (float_t)(96.0 / 255.0) }; set_clear_color = true; } - background_color.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); + +End: igEnd(); } -void background_color_input() { - if (!background_color_enabled) - return; - - input_locked |= background_color.imgui_focus; +void graphics_background_color_input(class_data* data) { + input_locked |= data->imgui_focus; } -void background_color_render() { - if (background_color.dispose) { - background_color_dispose(); - return; - } - else if (!background_color_enabled) - return; +void graphics_background_color_render(class_data* data) { + +} + +bool graphics_background_color_dispose(class_data* data) { + return true; } diff --git a/src/CLOUD/classes/graphics/background_color.h b/src/CLOUD/classes/graphics/background_color.h index 50053e71..2e9bd002 100644 --- a/src/CLOUD/classes/graphics/background_color.h +++ b/src/CLOUD/classes/graphics/background_color.h @@ -6,12 +6,10 @@ #pragma once #include "../../../KKdLib/default.h" -#include "../../../KKdLib/vec.h" +#include "../../classes.h" -extern bool background_color_enabled; - -extern void background_color_dispose(); -extern void background_color_init(); -extern void background_color_imgui(); -extern void background_color_input(); -extern void background_color_render(); +extern bool graphics_background_color_init(class_data* data, render_context* rctx); +extern void graphics_background_color_imgui(class_data* data); +extern void graphics_background_color_input(class_data* data); +extern void graphics_background_color_render(class_data* data); +extern bool graphics_background_color_dispose(class_data* data); diff --git a/src/CLOUD/classes/graphics/glitter.c b/src/CLOUD/classes/graphics/glitter.c new file mode 100644 index 00000000..5a30cea2 --- /dev/null +++ b/src/CLOUD/classes/graphics/glitter.c @@ -0,0 +1,97 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "glitter.h" +#include "../../../CRE/Glitter/glitter.h" +#include "../../../CRE/Glitter/particle_manager.h" +#include "../../../CRE/render_context.h" +#include "../imgui_helper.h" + +extern int32_t width; +extern int32_t height; +extern bool input_locked; + +extern GPM; + +static const char* graphics_glitter_window_title = "Glitter##Graphics"; + +bool graphics_glitter_init(class_data* data, render_context* rctx) { + graphics_glitter_dispose(data); + return true; +} + +void graphics_glitter_imgui(class_data* data) { + float_t w = min((float_t)width / 4.0f, 148.0f); + float_t h = min((float_t)height, 204.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); + + ImGuiWindowFlags window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(graphics_glitter_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + size_t ctrl; + size_t disp; + size_t total_ctrl = 0; + size_t total_disp = 0; + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); + igText("QUAD (ctrl):%5lld", ctrl); + igText(" (disp):%5lld", disp); + total_ctrl += ctrl; + total_disp += disp; + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); + igText("LOCUS (ctrl):%5lld", ctrl); + igText(" (disp):%5lld", disp); + total_ctrl += ctrl; + total_disp += disp; + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); + igText("LINE (ctrl):%5lld", ctrl); + igText(" (disp):%5lld", disp); + total_ctrl += ctrl; + total_disp += disp; + + ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); + disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); + igText("MESH (ctrl):%5lld", ctrl); + igText(" (disp):%5lld", disp); + total_ctrl += ctrl; + total_disp += disp; + + igText("TOTAL (ctrl):%5lld", total_ctrl); + igText(" (disp):%5lld", total_disp); + + data->imgui_focus |= igIsWindowFocused(0); + +End: + igEnd(); +} + +void graphics_glitter_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void graphics_glitter_render(class_data* data) { + +} + +bool graphics_glitter_dispose(class_data* data) { + return true; +} diff --git a/src/CLOUD/classes/graphics/glitter.h b/src/CLOUD/classes/graphics/glitter.h new file mode 100644 index 00000000..2abf4ec6 --- /dev/null +++ b/src/CLOUD/classes/graphics/glitter.h @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool graphics_glitter_init(class_data* data, render_context* rctx); +extern void graphics_glitter_imgui(class_data* data); +extern void graphics_glitter_input(class_data* data); +extern void graphics_glitter_render(class_data* data); +extern bool graphics_glitter_dispose(class_data* data); diff --git a/src/CLOUD/classes/graphics/glitter_counter.c b/src/CLOUD/classes/graphics/glitter_counter.c deleted file mode 100644 index 2d384de3..00000000 --- a/src/CLOUD/classes/graphics/glitter_counter.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "glitter_counter.h" -#include "../../../CRE/Glitter/glitter.h" -#include "../../../CRE/Glitter/particle_manager.h" -#include "../imgui_helper.h" - -typedef struct glitter_counter_struct { - bool dispose; - bool disposed; - bool imgui_focus; -} glitter_counter_struct; - -extern int32_t width; -extern int32_t height; -extern bool input_locked; - -extern GPM; - -const char* glitter_counter_window_title = "Glitter##Counter"; - -bool glitter_counter_enabled = false; -static glitter_counter_struct glitter_counter; - -void glitter_counter_dispose() { - glitter_counter_enabled = false; - glitter_counter.imgui_focus = false; - glitter_counter.dispose = false; - glitter_counter.disposed = true; -} - -void glitter_counter_init() { - if (glitter_counter_enabled || glitter_counter.dispose) - glitter_counter_dispose(); - - glitter_counter_enabled = true; -} - -void glitter_counter_imgui() { - if (!glitter_counter_enabled) { - if (!glitter_counter.disposed) - glitter_counter.dispose = true; - return; - } - else if (glitter_counter.disposed) - glitter_counter_enabled = true; - - float_t w = min((float_t)width / 4.0f, 148.0f); - float_t h = min((float_t)height, 204.0f); - - igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); - igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); - - ImGuiWindowFlags window_flags = 0; - window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - - glitter_counter.imgui_focus = false; - if (!igBegin(glitter_counter_window_title, &glitter_counter_enabled, window_flags)) { - glitter_counter.dispose = true; - igEnd(); - return; - } - - size_t ctrl; - size_t disp; - size_t total_ctrl = 0; - size_t total_disp = 0; - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_QUAD); - igText("QUAD (ctrl):%6lld", ctrl); - igText(" (disp):%6lld", disp); - total_ctrl += ctrl; - total_disp += disp; - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LOCUS); - igText("LOCUS (ctrl):%6lld", ctrl); - igText(" (disp):%6lld", disp); - total_ctrl += ctrl; - total_disp += disp; - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_LINE); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_LINE); - igText("LINE (ctrl):%6lld", ctrl); - igText(" (disp):%6lld", disp); - total_ctrl += ctrl; - total_disp += disp; - - ctrl = glitter_particle_manager_get_ctrl_count(GPM_VAL, GLITTER_PARTICLE_MESH); - disp = glitter_particle_manager_get_disp_count(GPM_VAL, GLITTER_PARTICLE_MESH); - igText("MESH (ctrl):%6lld", ctrl); - igText(" (disp):%6lld", disp); - total_ctrl += ctrl; - total_disp += disp; - - igText("TOTAL (ctrl):%6lld", total_ctrl); - igText(" (disp):%6lld", total_disp); - - glitter_counter.imgui_focus |= igIsWindowFocused(0); - igEnd(); -} - -void glitter_counter_input() { - if (!glitter_counter_enabled) - return; - - input_locked |= glitter_counter.imgui_focus; -} - -void glitter_counter_render() { - if (glitter_counter.dispose) { - glitter_counter_dispose(); - return; - } - else if (!glitter_counter_enabled) - return; -} diff --git a/src/CLOUD/classes/graphics/glitter_counter.h b/src/CLOUD/classes/graphics/glitter_counter.h deleted file mode 100644 index 733e65ae..00000000 --- a/src/CLOUD/classes/graphics/glitter_counter.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../../../KKdLib/default.h" - -extern bool glitter_counter_enabled; - -extern void glitter_counter_dispose(); -extern void glitter_counter_init(); -extern void glitter_counter_imgui(); -extern void glitter_counter_input(); -extern void glitter_counter_render(); diff --git a/src/CLOUD/classes/graphics/post_process.c b/src/CLOUD/classes/graphics/post_process.c index 2005cd67..4eb52b34 100644 --- a/src/CLOUD/classes/graphics/post_process.c +++ b/src/CLOUD/classes/graphics/post_process.c @@ -4,93 +4,89 @@ */ #include "post_process.h" -#include "../../../CRE/post_process.h" -#include "../../../CRE/dof.h" +#include "../../../CRE/stage.h" #include "../imgui_helper.h" -typedef struct post_process_struct { - bool dispose; - bool disposed; - bool imgui_focus; -} post_process_struct; - extern int32_t width; extern int32_t height; extern bool input_locked; -const char* post_process_window_title = "Post Process"; +const char* graphics_post_process_window_title = "Post Process##Graphics"; -extern dof_struct* dof; -extern radius* rad; -extern intensity* inten; -extern tone_map* tm; - -bool post_process_enabled = false; -static post_process_struct post_process; - -extern void post_process_dispose() { - post_process_enabled = false; - post_process.imgui_focus = false; - post_process.dispose = false; - post_process.disposed = true; +bool graphics_post_process_init(class_data* data, render_context* rctx) { + graphics_post_process_dispose(data); + data->data = rctx; + return true; } -extern void post_process_init() { - if (post_process_enabled || post_process.dispose) - post_process_dispose(); - - post_process_enabled = true; -} - -extern void post_process_imgui() { - if (!post_process_enabled) { - if (!post_process.disposed) - post_process.dispose = true; - return; - } - else if (post_process.disposed) - post_process_enabled = true; - +void graphics_post_process_imgui(class_data* data) { ImGuiIO* io = igGetIO(); ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); - float_t w = min((float_t)width / 4.0f, 360.0f); - float_t h = min((float_t)height, 740.0f); + float_t w = min((float_t)width, 400.0f); + float_t h = min((float_t)height, 790.0f); igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Appearing); ImGuiWindowFlags window_flags = 0; window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - post_process.imgui_focus = false; - if (!igBegin(post_process_window_title, &post_process_enabled, window_flags)) { - post_process.dispose = true; - igEnd(); - return; + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(graphics_post_process_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; } + else if (collapsed) + goto End; + render_context* rctx = data->data; + post_process_struct* pp = &rctx->post_process; + + post_process_blur* blur = pp->blur; + post_process_dof* dof = pp->dof; + post_process_tone_map* tone_map = pp->tone_map; + + static const char* mag_filter_labels[] = { + "nearest", + "bilinear", + "sharpen(5tap)", + "sharpen(4tap)", + "cone(4tap)", + "cone(2tap)", + }; + + imguiColumnComboBox("MAG Filter", mag_filter_labels, POST_PROCESS_MAG_FILTER_MAX, + (int32_t*)&pp->mag_filter, 0, false, &data->imgui_focus); + + imguiCheckbox("Morphological AA", &pp->mlaa); + + imguiSetColumnSpace(1.0f / 4.0f); if (igTreeNode_Str("Tone Trans")) { - vec3 tone_trans_start = *tone_map_get_tone_trans_start(tm); - imguiColumnSliderVec3("Start", &tone_trans_start, 0.0f, 1.0f, "%.2f", 0); - tone_map_set_tone_trans_start(tm, &tone_trans_start); + vec3 tone_trans_start; + post_process_tone_map_get_tone_trans_start(tone_map, &tone_trans_start); + imguiColumnSliderVec3("Start", &tone_trans_start, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); + post_process_tone_map_set_tone_trans_start(tone_map, &tone_trans_start); - vec3 tone_trans_end = *tone_map_get_tone_trans_end(tm); - imguiColumnSliderVec3("End", &tone_trans_end, 0.0f, 1.0f, "%.2f", 0); - tone_map_set_tone_trans_end(tm, &tone_trans_end); + vec3 tone_trans_end; + post_process_tone_map_get_tone_trans_end(tone_map, &tone_trans_end); + imguiColumnSliderVec3("End", &tone_trans_end, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); + post_process_tone_map_set_tone_trans_end(tone_map, &tone_trans_end); igTreePop(); } if (igTreeNode_Str("Scene Fade")) { - float_t scene_fade_alpha = tone_map_get_scene_fade_alpha(tm); - imguiColumnSliderFloat("Alpha", &scene_fade_alpha, 0.0f, 1.0f, "%.2f", 0); - tone_map_set_scene_fade_alpha(tm, scene_fade_alpha); + float_t scene_fade_alpha = post_process_tone_map_get_scene_fade_alpha(tone_map); + imguiColumnSliderFloat("Alpha", &scene_fade_alpha, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); + post_process_tone_map_set_scene_fade_alpha(tone_map, scene_fade_alpha); - vec3 scene_fade_color = *tone_map_get_scene_fade_color(tm); - imguiColumnSliderVec3("Color", &scene_fade_color, 0.0f, 1.0f, "%.2f", 0); - tone_map_set_scene_fade_color(tm, &scene_fade_color); + vec3 scene_fade_color; + post_process_tone_map_get_scene_fade_color(tone_map, &scene_fade_color); + imguiColumnSliderVec3("Color", &scene_fade_color, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); + post_process_tone_map_set_scene_fade_color(tone_map, &scene_fade_color); const char* scene_fade_blend_func_labels[] = { "0: OVER", @@ -98,10 +94,10 @@ extern void post_process_imgui() { "2: PLUS", }; - int32_t scene_fade_blend_func = tone_map_get_scene_fade_blend_func(tm); + int32_t scene_fade_blend_func = post_process_tone_map_get_scene_fade_blend_func(tone_map); imguiColumnComboBox("Blend Func", scene_fade_blend_func_labels, 3, - &scene_fade_blend_func, 0, false, &post_process.imgui_focus); - tone_map_set_scene_fade_blend_func(tm, scene_fade_blend_func); + &scene_fade_blend_func, 0, false, &data->imgui_focus); + post_process_tone_map_set_scene_fade_blend_func(tone_map, scene_fade_blend_func); igTreePop(); } @@ -112,64 +108,70 @@ extern void post_process_imgui() { "RGB LINEAR2", }; - int32_t tone_map_method = tone_map_get_tone_map_method(tm); + int32_t tone_map_method = post_process_tone_map_get_tone_map_method(tone_map); imguiColumnComboBox("Tone Map", tone_map_method_labels, 3, - &tone_map_method, 0, false, &post_process.imgui_focus); - tone_map_set_tone_map_method(tm, tone_map_method); + &tone_map_method, 0, false, &data->imgui_focus); + post_process_tone_map_set_tone_map_method(tone_map, tone_map_method); - float_t exposure = tone_map_get_exposure(tm); - imguiColumnSliderFloat("Exposure", &exposure, 0.0f, 4.0f, "%.2f", 0); + float_t exposure = post_process_tone_map_get_exposure(tone_map); + imguiColumnSliderFloat("Exposure", &exposure, 0.02f, 0.0f, 4.0f, "%.2f", 0, true); exposure = roundf(exposure / 0.02f) * 0.02f; - tone_map_set_exposure(tm, exposure); + post_process_tone_map_set_exposure(tone_map, exposure); - bool auto_exposure = tone_map_get_auto_exposure(tm); + bool auto_exposure = post_process_tone_map_get_auto_exposure(tone_map); imguiCheckbox("Auto Exposure", &auto_exposure); - tone_map_set_auto_exposure(tm, auto_exposure); + post_process_tone_map_set_auto_exposure(tone_map, auto_exposure); - float_t gamma = tone_map_get_gamma(tm); - imguiColumnSliderFloat("Gamma", &gamma, 0.2f, 2.2f, "%.2f", 0); - tone_map_set_gamma(tm, gamma); + float_t gamma = post_process_tone_map_get_gamma(tone_map); + imguiColumnSliderFloat("Gamma", &gamma, 0.01f, 0.2f, 2.2f, "%.2f", 0, true); + post_process_tone_map_set_gamma(tone_map, gamma); - int32_t saturate1 = tone_map_get_saturate_power(tm); - imguiColumnSliderInt("Saturate 1", &saturate1, 1, 6, "%d", 0); - tone_map_set_saturate_power(tm, saturate1); + int32_t saturate1 = post_process_tone_map_get_saturate_power(tone_map); + imguiColumnSliderInt("Saturate 1", &saturate1, 1, 6, "%d", 0, true); + post_process_tone_map_set_saturate_power(tone_map, saturate1); - float_t saturate2 = tone_map_get_saturate_coeff(tm); - imguiColumnSliderFloat("Saturate 2", &saturate2, 0.0f, 1.0f, "%.2f", 0); - tone_map_set_saturate_coeff(tm, saturate2); + float_t saturate2 = post_process_tone_map_get_saturate_coeff(tone_map); + imguiColumnSliderFloat("Saturate 2", &saturate2, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); + post_process_tone_map_set_saturate_coeff(tone_map, saturate2); igTreePop(); } if (igTreeNodeEx_Str("Glare", ImGuiTreeNodeFlags_DefaultOpen)) { - vec3 radius = *radius_get(rad); - imguiColumnSliderFloat("Radius R", &radius.x, 1.0f, 3.0f, "%.2f", 0); - imguiColumnSliderFloat("Radius G", &radius.y, 1.0f, 3.0f, "%.2f", 0); - imguiColumnSliderFloat("Radius B", &radius.z, 1.0f, 3.0f, "%.2f", 0); - radius_set(rad, &radius); + vec3 radius; + post_process_blur_get_radius(blur, &radius); + imguiColumnSliderFloat("Radius R", &radius.x, 0.1f, 1.0f, 3.0f, "%.2f", 0, true); + imguiColumnSliderFloat("Radius G", &radius.y, 0.1f, 1.0f, 3.0f, "%.2f", 0, true); + imguiColumnSliderFloat("Radius B", &radius.z, 0.1f, 1.0f, 3.0f, "%.2f", 0, true); + post_process_blur_set_radius(blur, &radius); - vec3 intensity = *intensity_get(inten); - imguiColumnSliderFloat("Inten R", &intensity.x, 0.0f, 2.0f, "%.2f", 0); - imguiColumnSliderFloat("Inten G", &intensity.y, 0.0f, 2.0f, "%.2f", 0); - imguiColumnSliderFloat("Inten B", &intensity.z, 0.0f, 2.0f, "%.2f", 0); - intensity_set(inten, &intensity); + vec3 intensity; + post_process_blur_get_intensity(blur, &intensity); + imguiColumnSliderFloat("Inten R", &intensity.x, 0.05f, 0.0f, 2.0f, "%.2f", 0, true); + imguiColumnSliderFloat("Inten G", &intensity.y, 0.05f, 0.0f, 2.0f, "%.2f", 0, true); + imguiColumnSliderFloat("Inten B", &intensity.z, 0.05f, 0.0f, 2.0f, "%.2f", 0, true); + post_process_blur_set_intensity(blur, &intensity); igTreePop(); } + imguiSetDefaultColumnSpace(); if (igTreeNodeEx_Str("DOF", ImGuiTreeNodeFlags_DefaultOpen)) { - bool use_ui_params = dof->debug.flags & DOF_DEBUG_USE_UI_PARAMS; - bool phys = use_ui_params && dof->debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF; - bool f2 = use_ui_params && ~dof->debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF; + bool use_ui_params = dof->data.debug.flags & DOF_DEBUG_USE_UI_PARAMS; + bool phys = use_ui_params && dof->data.debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF; + bool f2 = use_ui_params && ~dof->data.debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF; float_t alpha = style->Alpha * imgui_alpha_disabled_scale; - imguiCheckboxFlags_UintPtr("use UI params", (uint32_t*)&dof->debug.flags, DOF_DEBUG_USE_UI_PARAMS); + imguiCheckboxFlags_UintPtr("use UI params", + (uint32_t*)&dof->data.debug.flags, DOF_DEBUG_USE_UI_PARAMS); if (!use_ui_params) { igPushItemFlag(ImGuiItemFlags_Disabled, true); igPushStyleVar_Float(ImGuiStyleVar_Alpha, alpha); } - imguiCheckboxFlags_UintPtr("enable DOF", (uint32_t*)&dof->debug.flags, DOF_DEBUG_ENABLE_DOF); - imguiCheckboxFlags_UintPtr("enable physical DOF", (uint32_t*)&dof->debug.flags, DOF_DEBUG_ENABLE_PHYS_DOF); + imguiCheckboxFlags_UintPtr("enable DOF", + (uint32_t*)&dof->data.debug.flags, DOF_DEBUG_ENABLE_DOF); + imguiCheckboxFlags_UintPtr("enable physical DOF", + (uint32_t*)&dof->data.debug.flags, DOF_DEBUG_ENABLE_PHYS_DOF); if (!use_ui_params) { igPopItemFlag(); igPopStyleVar(1); @@ -179,7 +181,8 @@ extern void post_process_imgui() { igPushItemFlag(ImGuiItemFlags_Disabled, true); igPushStyleVar_Float(ImGuiStyleVar_Alpha, alpha); } - imguiCheckboxFlags_UintPtr("auto focus", (uint32_t*)&dof->debug.flags, DOF_DEBUG_AUTO_FOCUS); + imguiCheckboxFlags_UintPtr("auto focus", + (uint32_t*)&dof->data.debug.flags, DOF_DEBUG_AUTO_FOCUS); if (!phys) { igPopItemFlag(); igPopStyleVar(1); @@ -190,9 +193,12 @@ extern void post_process_imgui() { igPushItemFlag(ImGuiItemFlags_Disabled, true); igPushStyleVar_Float(ImGuiStyleVar_Alpha, alpha); } - imguiColumnSliderFloat("distance to focus[m]", &dof->debug.distance_to_focus, 0.01f, 30.0f, "%.2f", 0); - imguiColumnSliderFloat("focal length[mm]", &dof->debug.focal_length, 0.1f, 100.0f, "%.2f", 0); - imguiColumnSliderFloat("F-Number", &dof->debug.f_number, 0.1f, 40.0f, "%.2f", 0); + imguiColumnSliderFloat("distance to focus[m]", + &dof->data.debug.distance_to_focus, 0.01f, 0.01f, 30.0f, "%.2f", 0, true); + imguiColumnSliderFloat("focal length[mm]", + &dof->data.debug.focal_length, 0.01f, 0.1f, 100.0f, "%.2f", 0, true); + imguiColumnSliderFloat("F-Number", + &dof->data.debug.f_number, 0.01f, 0.1f, 40.0f, "%.2f", 0, true); if (!phys) { igPopItemFlag(); igPopStyleVar(1); @@ -202,10 +208,14 @@ extern void post_process_imgui() { igPushItemFlag(ImGuiItemFlags_Disabled, true); igPushStyleVar_Float(ImGuiStyleVar_Alpha, alpha); } - imguiColumnSliderFloat("f2 distance to focus[m]", &dof->debug.f2.distance_to_focus, 0.01f, 30.0f, "%.2f", 0); - imguiColumnSliderFloat("f2 focus range[m]", &dof->debug.f2.focus_range, 0.0f, 10.0f, "%.2f", 0); - imguiColumnSliderFloat("f2 fuzzing range[m]", &dof->debug.f2.fuzzing_range, 0.0f, 10.0f, "%.2f", 0); - imguiColumnSliderFloat("f2 ratio", &dof->debug.f2.ratio, 0.0f, 1.0f, "%.2f", 0); + imguiColumnSliderFloat("f2 distance to focus[m]", + &dof->data.debug.f2.distance_to_focus, 0.01f, 0.01f, 30.0f, "%.2f", 0, true); + imguiColumnSliderFloat("f2 focus range[m]", + &dof->data.debug.f2.focus_range, 0.01f, 0.0f, 10.0f, "%.2f", 0, true); + imguiColumnSliderFloat("f2 fuzzing range[m]", + &dof->data.debug.f2.fuzzing_range, 0.01f, 0.0f, 10.0f, "%.2f", 0, true); + imguiColumnSliderFloat("f2 ratio", + &dof->data.debug.f2.ratio, 0.01f, 0.0f, 1.0f, "%.2f", 0, true); if (!f2) { igPopItemFlag(); igPopStyleVar(1); @@ -214,30 +224,29 @@ extern void post_process_imgui() { igTreePop(); } - if (imguiButton("Reset Post Process", ImVec2_Empty)) { - dof_initialize(dof, 0, 0); - radius_initialize(rad, (vec3[]) { 2.0f, 2.0f, 2.0f }); - intensity_initialize(inten, (vec3[]) { 1.0f, 1.0f, 1.0f }); - tone_map_initialize(tm, 2.0f, true, 1.0f, 1, 1.0f, (vec3[]) { 0.0f, 0.0f, 0.0f}, 0.0f, 0, - (vec3[]) { 0.0f, 0.0f, 0.0f }, (vec3[]) { 1.0f, 1.0f, 1.0f }, 0); + if (imguiButton("Reset Post Process", ImVec2_Empty) && rctx->stage) { + stage* stage = rctx->stage; + light_param_data* light_param = light_param_storage_get_light_param_data(stage->light_param_name); + post_process_reset(pp); + if (light_param->glow.ready) + render_context_light_param_data_glow_set(rctx, &light_param->glow); } - post_process.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); + +End: igEnd(); } -void post_process_input() { - if (!post_process_enabled) - return; - - input_locked |= post_process.imgui_focus; +void graphics_post_process_input(class_data* data) { + input_locked |= data->imgui_focus; } -extern void post_process_render() { - if (post_process.dispose) { - post_process_dispose(); - return; - } - else if (!post_process_enabled) - return; +void graphics_post_process_render(class_data* data) { + +} + +bool graphics_post_process_dispose(class_data* data) { + data->data = 0; + return true; } diff --git a/src/CLOUD/classes/graphics/post_process.h b/src/CLOUD/classes/graphics/post_process.h index 92fdaba3..29024681 100644 --- a/src/CLOUD/classes/graphics/post_process.h +++ b/src/CLOUD/classes/graphics/post_process.h @@ -6,11 +6,10 @@ #pragma once #include "../../../KKdLib/default.h" +#include "../../classes.h" -extern bool post_process_enabled; - -extern void post_process_dispose(); -extern void post_process_init(); -extern void post_process_imgui(); -extern void post_process_input(); -extern void post_process_render(); +extern bool graphics_post_process_init(class_data* data, render_context* rctx); +extern void graphics_post_process_imgui(class_data* data); +extern void graphics_post_process_input(class_data* data); +extern void graphics_post_process_render(class_data* data); +extern bool graphics_post_process_dispose(class_data* data); diff --git a/src/CLOUD/classes/graphics/render_settings.c b/src/CLOUD/classes/graphics/render_settings.c index 3c4bae40..2e072f96 100644 --- a/src/CLOUD/classes/graphics/render_settings.c +++ b/src/CLOUD/classes/graphics/render_settings.c @@ -9,17 +9,10 @@ #include "../../../CRE/timer.h" #include "../imgui_helper.h" -typedef struct render_settings_struct { - bool dispose; - bool disposed; - bool imgui_focus; -} render_settings_struct; - extern int32_t width; extern int32_t height; extern bool input_locked; -extern timer control_timer; extern timer render_timer; extern timer sound_timer; extern timer input_timer; @@ -29,10 +22,7 @@ extern void render_set_scale(double_t value); extern int32_t render_get_scale_index(); extern void render_set_scale_index(int32_t index); -const char* render_settings_window_title = "Render Settings"; - -bool render_settings_enabled = false; -static render_settings_struct render_settings; +const char* graphics_render_settings_window_title = "Render Settings##Graphics"; inline static void render_settings_freq_to_string(double_t freq, char* freq_str, char* ms_str) { int32_t freq_int = (int32_t)freq; @@ -44,38 +34,21 @@ inline static void render_settings_freq_to_string(double_t freq, char* freq_str, snprintf(ms_str, 0x20, "%4d.%03d", ms_int, ms_frac); } -void render_settings_dispose() { - render_settings_enabled = false; - render_settings.imgui_focus = false; - render_settings.dispose = false; - render_settings.disposed = true; +bool graphics_render_settings_init(class_data* data, render_context* rctx) { + graphics_render_settings_dispose(data); + return true; } -void render_settings_init() { - if (render_settings_enabled || render_settings.dispose) - render_settings_dispose(); - - render_settings_enabled = true; -} - -void render_settings_imgui() { - if (!render_settings_enabled) { - if (!render_settings.disposed) - render_settings.dispose = true; - return; - } - else if (render_settings.disposed) - render_settings_enabled = true; - +void graphics_render_settings_imgui(class_data* data) { ImGuiIO* io = igGetIO(); ImGuiStyle* style = igGetStyle(); ImFont* font = igGetFont(); - float_t w = min((float_t)width / 4.0f, 360.0f); + float_t w = min((float_t)width / 4.0f, 280.0f); #if defined(CLOUD_DEV) - float_t h = min((float_t)height, 248.0f); + float_t h = min((float_t)height, 196.0f); #else - float_t h = min((float_t)height, 164.0f); + float_t h = min((float_t)height, 86.0f); #endif igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); @@ -83,107 +56,84 @@ void render_settings_imgui() { ImGuiWindowFlags window_flags = 0; window_flags |= ImGuiWindowFlags_NoResize; - window_flags |= ImGuiWindowFlags_NoCollapse; - render_settings.imgui_focus = false; - if (!igBegin(render_settings_window_title, &render_settings_enabled, window_flags)) { - render_settings.dispose = true; - igEnd(); - return; + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(graphics_render_settings_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; } + else if (collapsed) + goto End; double_t scale = render_get_scale() * 100.0; int32_t scale_index = render_get_scale_index(); char buf[0x80]; snprintf(buf, sizeof(buf), "%g%%%%", scale); - if (imguiColumnSliderInt("Scale", &scale_index, 0, 7, buf, ImGuiSliderFlags_NoInput)) + if (imguiColumnSliderInt("Scale", &scale_index, 0, 7, buf, ImGuiSliderFlags_NoInput, true)) render_set_scale_index(scale_index); - int32_t fxaa_preset = sv_fxaa_preset; - if (imguiColumnSliderInt("FXAA Preset", &fxaa_preset, 3, 5, "%d", ImGuiSliderFlags_NoInput)) - sv_fxaa_preset_set(fxaa_preset); - - bool fxaa = sv_fxaa; - if (igCheckbox("FXAA", &fxaa)) - sv_fxaa_set(fxaa); - #if defined(CLOUD_DEV) igSeparator(); - double_t control_freq = timer_get_freq(&control_timer); double_t render_freq = timer_get_freq(&render_timer); double_t sound_freq = timer_get_freq(&sound_timer); double_t input_freq = timer_get_freq(&input_timer); - double_t control_freq_hist = timer_get_freq_hist(&control_timer); double_t render_freq_hist = timer_get_freq_hist(&render_timer); double_t sound_freq_hist = timer_get_freq_hist(&sound_timer); double_t input_freq_hist = timer_get_freq_hist(&input_timer); - char control_freq_str[0x20]; char render_freq_str[0x20]; char sound_freq_str[0x20]; char input_freq_str[0x20]; - char control_ms_str[0x20]; char render_ms_str[0x20]; char sound_ms_str[0x20]; char input_ms_str[0x20]; - render_settings_freq_to_string(control_freq, control_freq_str, control_ms_str); render_settings_freq_to_string(render_freq, render_freq_str, render_ms_str); render_settings_freq_to_string(sound_freq, sound_freq_str, sound_ms_str); render_settings_freq_to_string(input_freq, input_freq_str, input_ms_str); - char control_freq_hist_str[0x20]; char render_freq_hist_str[0x20]; char sound_freq_hist_str[0x20]; char input_freq_hist_str[0x20]; - char control_ms_hist_str[0x20]; char render_ms_hist_str[0x20]; char sound_ms_hist_str[0x20]; char input_ms_hist_str[0x20]; - render_settings_freq_to_string(control_freq_hist, control_freq_hist_str, control_ms_hist_str); render_settings_freq_to_string(render_freq_hist, render_freq_hist_str, render_ms_hist_str); render_settings_freq_to_string(sound_freq_hist, sound_freq_hist_str, sound_ms_hist_str); render_settings_freq_to_string(input_freq_hist, input_freq_hist_str, input_ms_hist_str); - igText("Targ: Control / Render / Sound / Input"); - igText("freq: %s / %s / %s / %s", control_freq_str, render_freq_str, - sound_freq_str, input_freq_str); - igText(" ms: %s / %s / %s / %s", control_ms_str, render_ms_str, - sound_ms_str, input_ms_str); + igText("Targ: Render / Sound / Input"); + igText("freq: %s / %s / %s", render_freq_str, sound_freq_str, input_freq_str); + igText(" ms: %s / %s / %s", render_ms_str, sound_ms_str, input_ms_str); igSeparator(); - igText("Curr: Control / Render / Sound / Input"); - igText("freq: %s / %s / %s / %s", control_freq_hist_str, render_freq_hist_str, - sound_freq_hist_str, input_freq_hist_str); - igText(" ms: %s / %s / %s / %s", control_ms_hist_str, render_ms_hist_str, - sound_ms_hist_str, input_ms_hist_str); + igText("Curr: Render / Sound / Input"); + igText("freq: %s / %s / %s", render_freq_hist_str, sound_freq_hist_str, input_freq_hist_str); + igText(" ms: %s / %s / %s", render_ms_hist_str, sound_ms_hist_str, input_ms_hist_str); #endif igSeparator(); - if (imguiButton("Reset Render Settings", ImVec2_Empty)) { + if (imguiButton("Reset Render Settings", ImVec2_Empty)) render_set_scale(1.0); - sv_fxaa_preset_set(5); - sv_fxaa_set(false); - } - render_settings.imgui_focus |= igIsWindowFocused(0); + data->imgui_focus |= igIsWindowFocused(0); + +End: igEnd(); } -void render_settings_input() { - if (!render_settings_enabled) - return; - - input_locked |= render_settings.imgui_focus; +void graphics_render_settings_input(class_data* data) { + input_locked |= data->imgui_focus; } -void render_settings_render() { - if (render_settings.dispose) { - render_settings_dispose(); - return; - } - else if (!render_settings_enabled) - return; +void graphics_render_settings_render(class_data* data) { + +} + +bool graphics_render_settings_dispose(class_data* data) { + return true; } diff --git a/src/CLOUD/classes/graphics/render_settings.h b/src/CLOUD/classes/graphics/render_settings.h index e21dcdad..d090a961 100644 --- a/src/CLOUD/classes/graphics/render_settings.h +++ b/src/CLOUD/classes/graphics/render_settings.h @@ -6,11 +6,10 @@ #pragma once #include "../../../KKdLib/default.h" +#include "../../classes.h" -extern bool render_settings_enabled; - -extern void render_settings_dispose(); -extern void render_settings_init(); -extern void render_settings_imgui(); -extern void render_settings_input(); -extern void render_settings_render(); +extern bool graphics_render_settings_init(class_data* data, render_context* rctx); +extern void graphics_render_settings_imgui(class_data* data); +extern void graphics_render_settings_input(class_data* data); +extern void graphics_render_settings_render(class_data* data); +extern bool graphics_render_settings_dispose(class_data* data); diff --git a/src/CLOUD/classes/imgui_helper.c b/src/CLOUD/classes/imgui_helper.c index 18ff1662..78d1f10c 100644 --- a/src/CLOUD/classes/imgui_helper.c +++ b/src/CLOUD/classes/imgui_helper.c @@ -5,6 +5,7 @@ #include "imgui_helper.h" #include "../../KKdLib/str_utils.h" +#include "../../CRE/data.h" const ImVec1 ImVec1_Empty = { 0.0f }; const ImVec2 ImVec2_Empty = { 0.0f, 0.0f }; @@ -17,72 +18,190 @@ const float_t imgui_alpha_disabled_scale = 0.5f; static float_t column_space = (float_t)(1.0 / 3.0); static float_t cell_padding; -bool imguiItemKeyDown(int32_t key) { +#undef min +#undef max + +inline bool imguiItemKeyDown(int32_t key) { return igIsItemFocused() && igIsKeyDown(key); } -bool imguiItemKeyPressed(int32_t key, bool repeat) { +inline bool imguiItemKeyPressed(int32_t key, bool repeat) { return igIsItemFocused() && igIsKeyPressed(key, repeat); } -bool imguiItemKeyReleased(int32_t key) { +inline bool imguiItemKeyReleased(int32_t key) { return igIsItemFocused() && igIsKeyReleased(key); } -float_t imguiGetColumnSpace() { +inline float_t imguiGetColumnSpace() { return column_space; } -void imguiSetColumnSpace(float_t val) { +inline void imguiSetColumnSpace(float_t val) { column_space = val; } -void imguiSetDefaultColumnSpace() { +inline void imguiSetDefaultColumnSpace() { column_space = (float_t)(1.0 / 3.0); } -void imguiDisableElementPush(bool enable) { +inline void imguiDisableElementPush(bool enable) { if (!enable) { igPushItemFlag(ImGuiItemFlags_Disabled, true); igPushStyleVar_Float(ImGuiStyleVar_Alpha, igGetStyle()->Alpha * imgui_alpha_disabled_scale); } } -void imguiDisableElementPop(bool enable) { +inline void imguiDisableElementPop(bool enable) { if (!enable) { igPopItemFlag(); igPopStyleVar(1); } } -const char* imguiStartPropertyColumn(const char* label) { - igPushID_Str(label); - +inline float_t imguiGetContentRegionAvailWidth() { ImVec2 t; igGetContentRegionAvail(&t); + return t.x; +} + +inline float_t imguiGetContentRegionAvailHeight() { + ImVec2 t; + igGetContentRegionAvail(&t); + return t.y; +} + +inline void imguiGetContentRegionAvailSetNextItemWidth() { + ImVec2 t; + igGetContentRegionAvail(&t); + igSetNextItemWidth(t.x); +} + +void imguiStartPropertyColumn(const char* label) { + igPushID_Str(label); + + float_t w = imguiGetContentRegionAvailWidth(); igBeginTable("table", 2, 0, ImVec2_Empty, 0.0f); - igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, t.x * column_space, 0); + igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * column_space, 0); char* label_temp = str_utils_copy((char*)label); char* temp; if (temp = strstr(label_temp, "##")) *temp = 0; igTableNextColumn(); - igGetContentRegionAvail(&t); - igSetNextItemWidth(t.x); + imguiGetContentRegionAvailSetNextItemWidth(); igText(label_temp); free(label_temp); igTableNextColumn(); - igGetContentRegionAvail(&t); - igSetNextItemWidth(t.x); - return (const char*)str_utils_add("##", (char*)label); + imguiGetContentRegionAvailSetNextItemWidth(); } -void imguiEndPropertyColumn(const char* temp) { +void imguiEndPropertyColumn() { igEndTable(); igPopID(); - free((void*)temp); +} + +bool igSliderFloatButton(const char* label, float_t* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { + float_t button_size = igGetFont()->FontSize + igGetStyle()->FramePadding.y * 2.0f; + ImGuiIO* io = igGetIO(); + + float_t key_repeat_delay = io->KeyRepeatDelay; + float_t key_repeat_rate = io->KeyRepeatRate; + io->KeyRepeatDelay = (float_t)(30.0 / 60.0); + io->KeyRepeatRate = (float_t)(10.0 / 60.0); + + ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat; + if (flags & ImGuiSliderFlags_NoInput) + igPushItemFlag(ImGuiItemFlags_Disabled, true); + + float_t v = *val; + float_t w = igCalcItemWidth(); + igPushID_Str(label); + igBeginGroup(); + igPushButtonRepeat(true); + igButtonEx("<", (ImVec2) { button_size, button_size }, ImGuiButtonFlags_Repeat); + bool l = igIsItemActive() && (igIsKeyPressed(VK_RETURN, true) + || igIsMouseClicked(ImGuiMouseButton_Left, true)); + igSameLine(0.0f, 0.0f); + igSetNextItemWidth(w - button_size * 2.0f); + igSliderScalar(label, ImGuiDataType_Float, &v, &min, &max, format, flags); + igSameLine(0.0f, 0.0f); + igButtonEx(">", (ImVec2) { button_size, button_size }, ImGuiButtonFlags_Repeat); + bool r = igIsItemActive() && (igIsKeyPressed(VK_RETURN, true) + || igIsMouseClicked(ImGuiMouseButton_Left, true)); + igPopButtonRepeat(); + igEndGroup(); + igPopID(); + if (flags & ImGuiSliderFlags_NoInput) + igPopItemFlag(); + + io->KeyRepeatDelay = key_repeat_delay; + io->KeyRepeatRate = key_repeat_rate; + + if (l) { + v -= step; + if (v < min) + v = min; + } + else if (r) { + v += step; + if (v > max) + v = max; + } + + bool res = *val != v ? true : false; + *val = v; + return res; +} + +bool igSliderIntButton(const char* label, int32_t* val, + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { + float_t button_size = igGetFont()->FontSize + igGetStyle()->FramePadding.y * 2.0f; + ImGuiIO* io = igGetIO(); + + float_t key_repeat_delay = io->KeyRepeatDelay; + float_t key_repeat_rate = io->KeyRepeatRate; + io->KeyRepeatDelay = (float_t)(30.0 / 60.0); + io->KeyRepeatRate = (float_t)(10.0 / 60.0); + + int32_t v = *val; + float_t w = igCalcItemWidth(); + igPushID_Str(label); + igBeginGroup(); + igPushButtonRepeat(true); + igButtonEx("<", (ImVec2) { button_size, button_size }, ImGuiButtonFlags_Repeat); + bool l = igIsItemActive() && (igIsKeyPressed(VK_RETURN, true) + || igIsMouseClicked(ImGuiMouseButton_Left, true)); + igSameLine(0.0f, 0.0f); + igSetNextItemWidth(w - button_size * 2.0f); + igSliderScalar(label, ImGuiDataType_S32, &v, &min, &max, format, flags); + igSameLine(0.0f, 0.0f); + igButtonEx(">", (ImVec2) { button_size, button_size }, ImGuiButtonFlags_Repeat); + bool r = igIsItemActive() && (igIsKeyPressed(VK_RETURN, true) + || igIsMouseClicked(ImGuiMouseButton_Left, true)); + igPopButtonRepeat(); + igEndGroup(); + igPopID(); + + io->KeyRepeatDelay = key_repeat_delay; + io->KeyRepeatRate = key_repeat_rate; + + if (l) { + v--; + if (v < min) + v = min; + } + else if (r) { + v++; + if (v > max) + v = max; + } + + bool res = *val != v ? true : false; + *val = v; + return res; } bool imguiButton(const char* label, const ImVec2 size) { @@ -97,7 +216,7 @@ bool imguiCheckbox(const char* label, bool* v) { if (igCheckbox(label, v)) return true; else if (imguiItemKeyPressed(GLFW_KEY_ENTER, true)) { - *v ^= true; + v[0] ^= true; return true; } else @@ -159,6 +278,17 @@ static bool igSliderFloatDisable(const char* label, float_t* val, return res; } +static bool igSliderFloatButtonDisable(const char* label, float_t* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool enable) { + igPushID_Str(label); + imguiDisableElementPush(enable); + bool res = igSliderFloatButton("", val, step, min, max, enable ? format : "...", flags); + imguiDisableElementPop(enable); + igPopID(); + igPopItemWidth(); + return res; +} + static bool igSliderIntDisable(const char* label, int32_t* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool enable) { igPushID_Str(label); @@ -170,29 +300,37 @@ static bool igSliderIntDisable(const char* label, int32_t* val, return res; } +static bool igSliderIntButtonDisable(const char* label, int32_t* val, + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool enable) { + igPushID_Str(label); + imguiDisableElementPush(enable); + bool res = igSliderIntButton("", val, min, max, enable ? format : "...", flags); + imguiDisableElementPop(enable); + igPopID(); + igPopItemWidth(); + return res; +} + static const char* imguiStartPropertyColumnDisable(const char* label, bool enable) { igPushID_Str(label); - ImVec2 t; - igGetContentRegionAvail(&t); + float_t w = imguiGetContentRegionAvailWidth(); igBeginTable("table", 2, 0, ImVec2_Empty, 0.0f); - igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, t.x * column_space, 0); + igTableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, w * column_space, 0); char* label_temp = str_utils_copy((char*)label); char* temp; if (temp = strstr(label_temp, "##")) *temp = 0; igTableNextColumn(); - igGetContentRegionAvail(&t); - igSetNextItemWidth(t.x); + imguiGetContentRegionAvailSetNextItemWidth(); imguiDisableElementPush(enable); igText(label_temp); imguiDisableElementPop(enable); free(label_temp); igTableNextColumn(); - igGetContentRegionAvail(&t); - igSetNextItemWidth(t.x); + imguiGetContentRegionAvailSetNextItemWidth(); return (const char*)str_utils_add("##", (char*)label); } @@ -202,8 +340,11 @@ bool imguiComboBox(const char* label, const char** items, const size_t size, if (!include_last && size < 1) { imguiDisableElementPush(false); - if (igBeginCombo(label, "None", flags)) + if (igBeginCombo(label, "None", flags)) { + if (focus) + *focus |= true; igEndCombo(); + } imguiDisableElementPop(false); return false; } @@ -213,7 +354,8 @@ bool imguiComboBox(const char* label, const char** items, const size_t size, for (size_t n = 0; n <= size; n++) { igPushID_Int((int32_t)n); if (igSelectable_Bool(items[n], *selected_idx == n, 0, ImVec2_Empty) - || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) *selected_idx = (int32_t)n; igPopID(); @@ -224,7 +366,8 @@ bool imguiComboBox(const char* label, const char** items, const size_t size, for (size_t n = 0; n < size; n++) { igPushID_Int((int32_t)n); if (igSelectable_Bool(items[n], *selected_idx == n, 0, ImVec2_Empty) - || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) *selected_idx = (int32_t)n; igPopID(); @@ -233,7 +376,7 @@ bool imguiComboBox(const char* label, const char** items, const size_t size, } if (focus) - *focus |= igIsWindowFocused(0); + *focus |= true; igEndCombo(); } return prev_selected_idx != *selected_idx; @@ -245,8 +388,11 @@ bool imguiComboBoxString(const char* label, string* items, const size_t size, if (!include_last && size < 1) { imguiDisableElementPush(false); - if (igBeginCombo(label, "None", flags)) + if (igBeginCombo(label, "None", flags)) { + if (focus) + *focus |= true; igEndCombo(); + } imguiDisableElementPop(false); return false; } @@ -257,7 +403,8 @@ bool imguiComboBoxString(const char* label, string* items, const size_t size, igPushID_Int((int32_t)n); if (igSelectable_Bool((const char*)string_data(&items[n]), *selected_idx == n, 0, ImVec2_Empty) - || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) *selected_idx = (int32_t)n; igPopID(); @@ -269,7 +416,8 @@ bool imguiComboBoxString(const char* label, string* items, const size_t size, igPushID_Int((int32_t)n); if (igSelectable_Bool((const char*)string_data(&items[n]), *selected_idx == n, 0, ImVec2_Empty) - || imguiItemKeyPressed(GLFW_KEY_ENTER, true)) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) *selected_idx = (int32_t)n; igPopID(); @@ -278,7 +426,58 @@ bool imguiComboBoxString(const char* label, string* items, const size_t size, } if (focus) - *focus |= igIsWindowFocused(0); + *focus |= true; + igEndCombo(); + } + return prev_selected_idx != *selected_idx; +} + +bool imguiComboBoxConfigFile(const char* label, void* items, const size_t size, + int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus) { + int32_t prev_selected_idx = *selected_idx; + + if (!include_last && size < 1) { + imguiDisableElementPush(false); + if (igBeginCombo(label, "None", flags)) { + if (focus) + *focus |= true; + igEndCombo(); + } + imguiDisableElementPop(false); + return false; + } + + data_struct_file* items_ds = items; + if (igBeginCombo(label, string_data(&items_ds[*selected_idx].name), flags)) { + if (include_last) + for (size_t n = 0; n <= size; n++) { + igPushID_Int((int32_t)n); + if (igSelectable_Bool((const char*)string_data(&items_ds[n].name), + *selected_idx == n, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) + *selected_idx = (int32_t)n; + igPopID(); + + if (*selected_idx == n) + igSetItemDefaultFocus(); + } + else + for (size_t n = 0; n < size; n++) { + igPushID_Int((int32_t)n); + if (igSelectable_Bool((const char*)string_data(&items_ds[n].name), + *selected_idx == n, 0, ImVec2_Empty) + || imguiItemKeyPressed(GLFW_KEY_ENTER, true) + || (igIsItemFocused() && *selected_idx != n)) + *selected_idx = (int32_t)n; + igPopID(); + + if (*selected_idx == n) + igSetItemDefaultFocus(); + } + + if (focus) + *focus |= true; igEndCombo(); } return prev_selected_idx != *selected_idx; @@ -287,9 +486,9 @@ bool imguiComboBoxString(const char* label, string* items, const size_t size, bool imguiColumnColorEdit3(const char* label, vec3* val, ImGuiColorEditFlags flags) { float_t v[3]; *(vec3*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igColorEdit3(temp_label, v, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igColorEdit3("", v, flags); + imguiEndPropertyColumn(); if (res) *val = *(vec3*)v; return res; @@ -298,9 +497,9 @@ bool imguiColumnColorEdit3(const char* label, vec3* val, ImGuiColorEditFlags fla bool imguiColumnColorEdit4(const char* label, vec4* val, ImGuiColorEditFlags flags) { float_t v[4]; *(vec4*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igColorEdit4(temp_label, v, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igColorEdit4("", v, flags); + imguiEndPropertyColumn(); if (res) *val = *(vec4*)v; return res; @@ -308,35 +507,43 @@ bool imguiColumnColorEdit4(const char* label, vec4* val, ImGuiColorEditFlags fla bool imguiColumnComboBox(const char* label, const char** items, const size_t size, int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus) { - const char* temp_label = imguiStartPropertyColumn(label); - bool res = imguiComboBox(temp_label, items, size, selected_idx, flags, include_last, focus); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = imguiComboBox("", items, size, selected_idx, flags, include_last, focus); + imguiEndPropertyColumn(); return res; } bool imguiColumnComboBoxString(const char* label, string* items, const size_t size, int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus) { - const char* temp_label = imguiStartPropertyColumn(label); - bool res = imguiComboBoxString(temp_label, items, size, selected_idx, flags, include_last, focus); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = imguiComboBoxString("", items, size, selected_idx, flags, include_last, focus); + imguiEndPropertyColumn(); + return res; +} + +bool imguiColumnComboBoxConfigFile(const char* label, void* items, const size_t size, + int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus) { + imguiStartPropertyColumn(label); + bool res = imguiComboBoxConfigFile("", items, size, selected_idx, flags, include_last, focus); + imguiEndPropertyColumn(); return res; } bool imguiColumnDragFloat(const char* label, float_t* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { float_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragFloat(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = igDragFloat("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -344,9 +551,9 @@ bool imguiColumnDragVec2(const char* label, vec2* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { float_t v[2]; *(vec2*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragFloat2(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragFloat2("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -363,9 +570,9 @@ bool imguiColumnDragVec3(const char* label, vec3* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { float_t v[3]; *(vec3*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragFloat3(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragFloat3("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -383,9 +590,9 @@ bool imguiColumnDragVec4(const char* label, vec4* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { float_t v[4]; *(vec4*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragFloat4(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragFloat4("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -403,18 +610,18 @@ bool imguiColumnDragVec4(const char* label, vec4* val, float_t speed, bool imguiColumnDragInt(const char* label, int32_t* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { int32_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragInt(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = igDragInt("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -422,9 +629,9 @@ bool imguiColumnDragVec2I(const char* label, vec2i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { int32_t v[2]; *(vec2i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragInt2(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragInt2("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -441,9 +648,9 @@ bool imguiColumnDragVec3I(const char* label, vec3i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { int32_t v[3]; *(vec3i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragInt3(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragInt3("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -461,9 +668,9 @@ bool imguiColumnDragVec4I(const char* label, vec4i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { int32_t v[4]; *(vec4i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igDragInt4(temp_label, v, speed, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igDragInt4("", v, speed, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -480,37 +687,54 @@ bool imguiColumnDragVec4I(const char* label, vec4i* val, float_t speed, bool imguiColumnInputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igInputText(temp_label, buf, buf_size, flags, callback, user_data); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igInputText("", buf, buf_size, flags, callback, user_data); + imguiEndPropertyColumn(); return res; } -bool imguiColumnSliderFloat(const char* label, float_t* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { +bool imguiColumnSliderFloat(const char* label, float_t* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button) { float_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderFloat(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = false; + if (button) + res = igSliderFloatButton("", v, step, min, max, format, flags); + else + res = igSliderFloat("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } -bool imguiColumnSliderVec2(const char* label, vec2* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { +bool imguiColumnSliderVec2(const char* label, vec2* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button) { float_t v[2]; *(vec2*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderFloat2(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(2, igCalcItemWidth()); + res |= igSliderFloatButton("##X", &v[0], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##Y", &v[1], step, min, max, format, flags); + igPopItemWidth(); + igEndGroup(); + } + else + res = igSliderFloat2("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -523,13 +747,29 @@ bool imguiColumnSliderVec2(const char* label, vec2* val, return true; } -bool imguiColumnSliderVec3(const char* label, vec3* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { +bool imguiColumnSliderVec3(const char* label, vec3* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button) { float_t v[3]; *(vec3*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderFloat3(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(3, igCalcItemWidth()); + res |= igSliderFloatButton("##X", &v[0], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##Y", &v[1], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##Z", &v[2], step, min, max, format, flags); + igPopItemWidth(); + igEndGroup(); + } + else + res = igSliderFloat3("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -543,13 +783,32 @@ bool imguiColumnSliderVec3(const char* label, vec3* val, return true; } -bool imguiColumnSliderVec4(const char* label, vec4* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags) { +bool imguiColumnSliderVec4(const char* label, vec4* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button) { float_t v[4]; *(vec4*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderFloat4(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(4, igCalcItemWidth()); + res |= igSliderFloatButton("##X", &v[0], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##Y", &v[1], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##Z", &v[2], step, min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderFloatButton("##W", &v[3], step, min, max, format, flags); + igPopItemWidth(); + igEndGroup(); + } + else + res = igSliderFloat4("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -565,30 +824,48 @@ bool imguiColumnSliderVec4(const char* label, vec4* val, } bool imguiColumnSliderInt(const char* label, int32_t* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button) { int32_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderInt(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = false; + if (button) + res = igSliderIntButton("", v, min, max, format, flags); + else + res = igSliderInt("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } bool imguiColumnSliderVec2I(const char* label, vec2i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button) { int32_t v[2]; *(vec2i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderInt2(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(4, igCalcItemWidth()); + res |= igSliderIntButton("##X", &v[0], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##Y", &v[1], min, max, format, flags); + igPopItemWidth(); + + igEndGroup(); + } + else + res = igSliderInt2("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -602,12 +879,28 @@ bool imguiColumnSliderVec2I(const char* label, vec2i* val, } bool imguiColumnSliderVec3I(const char* label, vec3i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button) { int32_t v[3]; *(vec3i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderInt3(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(4, igCalcItemWidth()); + res |= igSliderIntButton("##X", &v[0], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##Y", &v[1], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##Z", &v[2], min, max, format, flags); + igPopItemWidth(); + igEndGroup(); + } + else + res = igSliderInt3("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -622,12 +915,31 @@ bool imguiColumnSliderVec3I(const char* label, vec3i* val, } bool imguiColumnSliderVec4I(const char* label, vec4i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button) { int32_t v[4]; *(vec4i*)v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igSliderInt4(temp_label, v, min, max, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = false; + if (button) { + ImGuiStyle* style = igGetStyle(); + igBeginGroup(); + igPushMultiItemsWidths(4, igCalcItemWidth()); + res |= igSliderIntButton("##X", &v[0], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##Y", &v[1], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##Z", &v[2], min, max, format, flags); + igPopItemWidth(); + igSameLine(0.0f, style->ItemInnerSpacing.x); + res |= igSliderIntButton("##W", &v[3], min, max, format, flags); + igPopItemWidth(); + igEndGroup(); + } + else + res = igSliderInt4("", v, min, max, format, flags); + imguiEndPropertyColumn(); if (!res) return false; @@ -646,24 +958,24 @@ bool imguiColumnSliderLogInt(const char* label, int32_t* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { char buf[0x1000]; int32_t v[1]; - min = max(min, 1); - max = max(min, max); + if (min < 1) + min = 1; + if (min > max) + max = min; flags |= ImGuiSliderFlags_NoInput; v[0] = (int32_t)roundf(log2f((float_t)*val)); - const char* temp_label = imguiStartPropertyColumn(label); + imguiStartPropertyColumn(label); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(1, igCalcItemWidth()); min = (int32_t)roundf(log2f((float_t)min)); max = (int32_t)roundf(log2f((float_t)max)); snprintf(buf, sizeof(buf), format, 1 << v[0]); res |= igSliderIntDisable("##X", &v[0], min, max, buf, flags, true); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -679,17 +991,18 @@ bool imguiColumnSliderLogVec2I(const char* label, vec2i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { char buf[0x1000]; int32_t v[2]; - min = max(min, 1); - max = max(min, max); + if (min < 1) + min = 1; + if (min > max) + max = min; flags |= ImGuiSliderFlags_NoInput; v[0] = (int32_t)roundf(log2f((float_t)val->x)); v[1] = (int32_t)roundf(log2f((float_t)val->y)); - const char* temp_label = imguiStartPropertyColumn(label); + imguiStartPropertyColumn(label); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(2, igCalcItemWidth()); min = (int32_t)roundf(log2f((float_t)min)); max = (int32_t)roundf(log2f((float_t)max)); @@ -698,9 +1011,8 @@ bool imguiColumnSliderLogVec2I(const char* label, vec2i* val, igSameLine(0.0f, style->ItemInnerSpacing.x); snprintf(buf, sizeof(buf), format, 1 << v[1]); res |= igSliderIntDisable("##Y", &v[1], min, max, buf, flags, true); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -717,18 +1029,19 @@ bool imguiColumnSliderLogVec3I(const char* label, vec3i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { char buf[0x1000]; int32_t v[3]; - min = max(min, 1); - max = max(min, max); + if (min < 1) + min = 1; + if (min > max) + max = min; flags |= ImGuiSliderFlags_NoInput; v[0] = (int32_t)roundf(log2f((float_t)val->x)); v[1] = (int32_t)roundf(log2f((float_t)val->y)); v[2] = (int32_t)roundf(log2f((float_t)val->z)); - const char* temp_label = imguiStartPropertyColumn(label); + imguiStartPropertyColumn(label); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(3, igCalcItemWidth()); min = (int32_t)roundf(log2f((float_t)min)); max = (int32_t)roundf(log2f((float_t)max)); @@ -740,9 +1053,8 @@ bool imguiColumnSliderLogVec3I(const char* label, vec3i* val, igSameLine(0.0f, style->ItemInnerSpacing.x); snprintf(buf, sizeof(buf), format, 1 << v[2]); res |= igSliderIntDisable("##Z", &v[2], min, max, buf, flags, true); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -760,20 +1072,20 @@ bool imguiColumnSliderLogVec4I(const char* label, vec4i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags) { char buf[0x1000]; int32_t v[4]; - - min = max(min, 1); - max = max(min, max); + if (min < 1) + min = 1; + if (min > max) + max = min; flags |= ImGuiSliderFlags_NoInput; v[0] = (int32_t)roundf(log2f((float_t)val->x)); v[1] = (int32_t)roundf(log2f((float_t)val->y)); v[2] = (int32_t)roundf(log2f((float_t)val->z)); v[3] = (int32_t)roundf(log2f((float_t)val->w)); - const char* temp_label = imguiStartPropertyColumn(label); + imguiStartPropertyColumn(label); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(4, igCalcItemWidth()); min = (int32_t)roundf(log2f((float_t)min)); max = (int32_t)roundf(log2f((float_t)max)); @@ -788,9 +1100,8 @@ bool imguiColumnSliderLogVec4I(const char* label, vec4i* val, igSameLine(0.0f, style->ItemInnerSpacing.x); snprintf(buf, sizeof(buf), format, 1 << v[3]); res |= igSliderIntDisable("##W", &v[3], min, max, buf, flags, true); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -808,57 +1119,55 @@ bool imguiColumnSliderLogVec4I(const char* label, vec4i* val, bool imguiColumnInputFloat(const char* label, float_t* val, float_t step, float_t step_fast, const char* format, ImGuiInputTextFlags flags) { float_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igInputFloat(temp_label, v, step, step_fast, format, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = igInputFloat("", v, step, step_fast, format, flags); + imguiEndPropertyColumn(); if (res) - *val = *v; + *val = v[0]; return res; } bool imguiColumnInputInt(const char* label, int32_t* val, int32_t step, int32_t step_fast, ImGuiInputTextFlags flags) { int32_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igInputInt(temp_label, v, step, step_fast, flags); - imguiEndPropertyColumn(temp_label); + v[0] = *val; + imguiStartPropertyColumn(label); + bool res = igInputInt("", v, step, step_fast, flags); + imguiEndPropertyColumn(); if (res) - *val = *v; + *val = v[0]; return res; } bool imguiColumnInputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { - const char* temp_label = imguiStartPropertyColumn(label); - bool res = igInputScalar(temp_label, data_type, p_data, p_step, p_step_fast, format, flags); - imguiEndPropertyColumn(temp_label); + imguiStartPropertyColumn(label); + bool res = igInputScalar("", data_type, p_data, p_step, p_step_fast, format, flags); + imguiEndPropertyColumn(); return res; } bool imguiColumnDragFloatFlag(const char* label, float_t* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); + v[0] = *val; + imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(1, igCalcItemWidth()); res |= igDragFloatDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -866,18 +1175,16 @@ bool imguiColumnDragVec2Flag(const char* label, vec2* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[2]; *(vec2*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(2, igCalcItemWidth()); res |= igDragFloatDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragFloatDisable("##Y", &v[1], speed, min, max, format, flags, bit_flag & 0x02 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -894,20 +1201,18 @@ bool imguiColumnDragVec3Flag(const char* label, vec3* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[3]; *(vec3*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(3, igCalcItemWidth()); res |= igDragFloatDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragFloatDisable("##Y", &v[1], speed, min, max, format, flags, bit_flag & 0x02 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragFloatDisable("##Z", &v[2], speed, min, max, format, flags, bit_flag & 0x04 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -925,11 +1230,10 @@ bool imguiColumnDragVec4Flag(const char* label, vec4* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[4]; *(vec4*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(4, igCalcItemWidth()); res |= igDragFloatDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); @@ -938,9 +1242,8 @@ bool imguiColumnDragVec4Flag(const char* label, vec4* val, float_t speed, res |= igDragFloatDisable("##Z", &v[2], speed, min, max, format, flags, bit_flag & 0x04 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragFloatDisable("##W", &v[3], speed, min, max, format, flags, bit_flag & 0x08 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -958,25 +1261,23 @@ bool imguiColumnDragVec4Flag(const char* label, vec4* val, float_t speed, bool imguiColumnDragIntFlag(const char* label, int32_t* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); + v[0] = *val; + imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(1, igCalcItemWidth()); res |= igDragIntDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -984,18 +1285,16 @@ bool imguiColumnDragVec2IFlag(const char* label, vec2i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[2]; *(vec2i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(2, igCalcItemWidth()); res |= igDragIntDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragIntDisable("##Y", &v[1], speed, min, max, format, flags, bit_flag & 0x02 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1012,20 +1311,18 @@ bool imguiColumnDragVec3IFlag(const char* label, vec3i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[3]; *(vec3i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(3, igCalcItemWidth()); res |= igDragIntDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragIntDisable("##Y", &v[1], speed, min, max, format, flags, bit_flag & 0x02 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragIntDisable("##Z", &v[2], speed, min, max, format, flags, bit_flag & 0x04 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1043,11 +1340,10 @@ bool imguiColumnDragVec4IFlag(const char* label, vec4i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[4]; *(vec4i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(4, igCalcItemWidth()); res |= igDragIntDisable("##X", &v[0], speed, min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); @@ -1056,9 +1352,8 @@ bool imguiColumnDragVec4IFlag(const char* label, vec4i* val, float_t speed, res |= igDragIntDisable("##Z", &v[2], speed, min, max, format, flags, bit_flag & 0x04 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igDragIntDisable("##W", &v[3], speed, min, max, format, flags, bit_flag & 0x08 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1076,25 +1371,23 @@ bool imguiColumnDragVec4IFlag(const char* label, vec4i* val, float_t speed, bool imguiColumnSliderFloatFlag(const char* label, float_t* val, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); + v[0] = *val; + imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(1, igCalcItemWidth()); res |= igSliderFloatDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -1102,18 +1395,16 @@ bool imguiColumnSliderVec2Flag(const char* label, vec2* val, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[2]; *(vec2*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(2, igCalcItemWidth()); res |= igSliderFloatDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderFloatDisable("##Y", &v[1], min, max, format, flags, bit_flag & 0x02 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1130,20 +1421,18 @@ bool imguiColumnSliderVec3Flag(const char* label, vec3* val, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[3]; *(vec3*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(3, igCalcItemWidth()); res |= igSliderFloatDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderFloatDisable("##Y", &v[1], min, max, format, flags, bit_flag & 0x02 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderFloatDisable("##Z", &v[2], min, max, format, flags, bit_flag & 0x04 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1161,11 +1450,10 @@ bool imguiColumnSliderVec4Flag(const char* label, vec4* val, float_t min, float_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { float_t v[4]; *(vec4*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(4, igCalcItemWidth()); res |= igSliderFloatDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); @@ -1174,9 +1462,8 @@ bool imguiColumnSliderVec4Flag(const char* label, vec4* val, res |= igSliderFloatDisable("##Z", &v[2], min, max, format, flags, bit_flag & 0x04 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderFloatDisable("##W", &v[3], min, max, format, flags, bit_flag & 0x08 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1194,25 +1481,23 @@ bool imguiColumnSliderVec4Flag(const char* label, vec4* val, bool imguiColumnSliderIntFlag(const char* label, int32_t* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[1]; - *v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); + v[0] = *val; + imguiStartPropertyColumnDisable(label, bit_flag & 0x01 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(1, igCalcItemWidth()); res |= igSliderIntDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; - *v = clamp(*v, min, max); - if (*v == *val) + v[0] = clamp(v[0], min, max); + if (v[0] == *val) return false; - *val = *v; + *val = v[0]; return true; } @@ -1220,18 +1505,16 @@ bool imguiColumnSliderVec2IFlag(const char* label, vec2i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[2]; *(vec2i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x03 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(2, igCalcItemWidth()); res |= igSliderIntDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderIntDisable("##Y", &v[1], min, max, format, flags, bit_flag & 0x02 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1248,20 +1531,18 @@ bool imguiColumnSliderVec3IFlag(const char* label, vec3i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[3]; *(vec3i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x07 ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(3, igCalcItemWidth()); res |= igSliderIntDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderIntDisable("##Y", &v[1], min, max, format, flags, bit_flag & 0x02 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderIntDisable("##Z", &v[2], min, max, format, flags, bit_flag & 0x04 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; @@ -1279,11 +1560,10 @@ bool imguiColumnSliderVec4IFlag(const char* label, vec4i* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, int32_t bit_flag) { int32_t v[4]; *(vec4i*)v = *val; - const char* temp_label = imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); + imguiStartPropertyColumnDisable(label, bit_flag & 0x0F ? true : false); bool res = false; ImGuiStyle* style = igGetStyle(); igBeginGroup(); - igPushID_Str(label); igPushMultiItemsWidths(4, igCalcItemWidth()); res |= igSliderIntDisable("##X", &v[0], min, max, format, flags, bit_flag & 0x01 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); @@ -1292,9 +1572,8 @@ bool imguiColumnSliderVec4IFlag(const char* label, vec4i* val, res |= igSliderIntDisable("##Z", &v[2], min, max, format, flags, bit_flag & 0x04 ? true : false); igSameLine(0.0f, style->ItemInnerSpacing.x); res |= igSliderIntDisable("##W", &v[3], min, max, format, flags, bit_flag & 0x08 ? true : false); - igPopID(); igEndGroup(); - imguiEndPropertyColumn(temp_label); + imguiEndPropertyColumn(); if (!res) return false; diff --git a/src/CLOUD/classes/imgui_helper.h b/src/CLOUD/classes/imgui_helper.h index 93f1a22e..ae585f69 100644 --- a/src/CLOUD/classes/imgui_helper.h +++ b/src/CLOUD/classes/imgui_helper.h @@ -29,9 +29,17 @@ extern void imguiSetColumnSpace(float_t val); extern void imguiSetDefaultColumnSpace(); extern void imguiDisableElementPush(bool enable); extern void imguiDisableElementPop(bool enable); +extern float_t imguiGetContentRegionAvailWidth(); +extern float_t imguiGetContentRegionAvailHeight(); +extern void imguiGetContentRegionAvailSetNextItemWidth(); -extern const char* imguiStartPropertyColumn(const char* label); -extern void imguiEndPropertyColumn(const char* temp); +extern void imguiStartPropertyColumn(const char* label); +extern void imguiEndPropertyColumn(); + +bool igSliderFloatButton(const char* label, float_t* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags); +bool igSliderIntButton(const char* label, int32_t* val, + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); extern bool imguiButton(const char* label, const ImVec2 size); extern bool imguiButtonEx(const char* label, const ImVec2 size, ImGuiButtonFlags flags); @@ -42,12 +50,16 @@ extern bool imguiComboBox(const char* label, const char** items, const size_t si int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); extern bool imguiComboBoxString(const char* label, string* items, const size_t size, int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); +extern bool imguiComboBoxConfigFile(const char* label, void* items, const size_t size, + int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); extern bool imguiColumnColorEdit3(const char* label, vec3* val, ImGuiColorEditFlags flags); extern bool imguiColumnColorEdit4(const char* label, vec4* val, ImGuiColorEditFlags flags); extern bool imguiColumnComboBox(const char* label, const char** items, const size_t size, int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); extern bool imguiColumnComboBoxString(const char* label, string* items, const size_t size, int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); +extern bool imguiColumnComboBoxConfigFile(const char* label, void* items, const size_t size, + int32_t* selected_idx, ImGuiComboFlags flags, bool include_last, bool* focus); extern bool imguiColumnDragFloat(const char* label, float_t* val, float_t speed, float_t min, float_t max, const char* format, ImGuiSliderFlags flags); extern bool imguiColumnDragVec2(const char* label, vec2* val, float_t speed, @@ -66,22 +78,22 @@ extern bool imguiColumnDragVec4I(const char* label, vec4i* val, float_t speed, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); extern bool imguiColumnInputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data); -extern bool imguiColumnSliderFloat(const char* label, float_t* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags); -extern bool imguiColumnSliderVec2(const char* label, vec2* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags); -extern bool imguiColumnSliderVec3(const char* label, vec3* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags); -extern bool imguiColumnSliderVec4(const char* label, vec4* val, - float_t min, float_t max, const char* format, ImGuiSliderFlags flags); +extern bool imguiColumnSliderFloat(const char* label, float_t* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button); +extern bool imguiColumnSliderVec2(const char* label, vec2* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button); +extern bool imguiColumnSliderVec3(const char* label, vec3* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button); +extern bool imguiColumnSliderVec4(const char* label, vec4* val, float_t step, + float_t min, float_t max, const char* format, ImGuiSliderFlags flags, bool button); extern bool imguiColumnSliderInt(const char* label, int32_t* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button); extern bool imguiColumnSliderVec2I(const char* label, vec2i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button); extern bool imguiColumnSliderVec3I(const char* label, vec3i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button); extern bool imguiColumnSliderVec4I(const char* label, vec4i* val, - int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); + int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags, bool button); extern bool imguiColumnSliderLogInt(const char* label, int32_t* val, int32_t min, int32_t max, const char* format, ImGuiSliderFlags flags); extern bool imguiColumnSliderLogVec2I(const char* label, vec2i* val, diff --git a/src/CLOUD/classes/information.c b/src/CLOUD/classes/information.c new file mode 100644 index 00000000..7e81ff37 --- /dev/null +++ b/src/CLOUD/classes/information.c @@ -0,0 +1,32 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "information.h" +#include "information/frame_speed.h" + +classes_struct information_classes[] = { + [INFORMATION_FRAME_SPEED] = { + .name = "FrameSpeed##Information", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = information_frame_speed_init, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .input = information_frame_speed_input, + .imgui = information_frame_speed_imgui, + .render = information_frame_speed_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = information_frame_speed_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = 0, + .sub_classes_count = 0, + }, +}; diff --git a/src/CLOUD/classes/information.h b/src/CLOUD/classes/information.h new file mode 100644 index 00000000..c49d71be --- /dev/null +++ b/src/CLOUD/classes/information.h @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../classes.h" + +typedef enum information_classes_enum { + INFORMATION_FRAME_SPEED, + INFORMATION_MAX, +} information_classes_enum; + +extern classes_struct information_classes[]; diff --git a/src/CLOUD/classes/information/frame_speed.c b/src/CLOUD/classes/information/frame_speed.c new file mode 100644 index 00000000..e6363ded --- /dev/null +++ b/src/CLOUD/classes/information/frame_speed.c @@ -0,0 +1,70 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "frame_speed.h" +#include "../../../KKdLib/vec.h" +#include "../imgui_helper.h" + +extern int32_t width; +extern int32_t height; +extern bool input_locked; +extern float_t frame_speed; + +static const char* information_frame_speed_window_title = "FrameSpeedWindow##Information"; + +bool information_frame_speed_init(class_data* data, render_context* rctx) { + information_frame_speed_dispose(data); + return true; +} + +void information_frame_speed_imgui(class_data* data) { + ImGuiIO* io = igGetIO(); + ImGuiStyle* style = igGetStyle(); + ImFont* font = igGetFont(); + + float_t w = min((float_t)width, 204.0f); + float_t h = min((float_t)height, 60.0f); + + igSetNextWindowPos(ImVec2_Empty, ImGuiCond_Appearing, ImVec2_Empty); + igSetNextWindowSize((ImVec2) { w, h }, ImGuiCond_Always); + + ImGuiWindowFlags window_flags = 0; + window_flags |= ImGuiWindowFlags_NoResize; + + data->imgui_focus = false; + bool open = data->flags & CLASS_HIDDEN ? false : true; + bool collapsed = !igBegin(information_frame_speed_window_title, &open, window_flags); + if (!open) { + data->flags |= CLASS_HIDE; + goto End; + } + else if (collapsed) + goto End; + + ImGuiColorEditFlags color_edit_flags = 0; + color_edit_flags |= ImGuiColorEditFlags_NoLabel; + color_edit_flags |= ImGuiColorEditFlags_NoSidePreview; + color_edit_flags |= ImGuiColorEditFlags_NoDragDrop; + + imguiGetContentRegionAvailSetNextItemWidth(); + imguiColumnSliderFloat("frame speed", &frame_speed, 0.01f, 0.0f, 3.0f, "%.2f", 0, true); + + data->imgui_focus |= igIsWindowFocused(0); + +End: + igEnd(); +} + +void information_frame_speed_input(class_data* data) { + input_locked |= data->imgui_focus; +} + +void information_frame_speed_render(class_data* data) { + +} + +bool information_frame_speed_dispose(class_data* data) { + return true; +} diff --git a/src/CLOUD/classes/information/frame_speed.h b/src/CLOUD/classes/information/frame_speed.h new file mode 100644 index 00000000..a325cd21 --- /dev/null +++ b/src/CLOUD/classes/information/frame_speed.h @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../../KKdLib/default.h" +#include "../../classes.h" + +extern bool information_frame_speed_init(class_data* data, render_context* rctx); +extern void information_frame_speed_imgui(class_data* data); +extern void information_frame_speed_input(class_data* data); +extern void information_frame_speed_render(class_data* data); +extern bool information_frame_speed_dispose(class_data* data); diff --git a/src/CLOUD/control.c b/src/CLOUD/control.c deleted file mode 100644 index 83b7f0ca..00000000 --- a/src/CLOUD/control.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "control.h" -#include "input.h" -#include "../KKdLib/io_path.h" -#include "../CRE/lock.h" -#include "../CRE/timer.h" - -timer control_timer; - -extern bool close; -HANDLE control_lock; -extern lock render_lock; -extern HWND window_handle; - -extern int32_t width; -extern int32_t height; -extern bool input_reset; -extern float_t frame_speed; - -int32_t control_main(void* arg) { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - timer_init(&control_timer, 60.0); - - while (!lock_check_init(&render_lock)) - msleep(control_timer.timer, 0.0625); - - bool local_close = false; - while (!close && !local_close) { - timer_start_of_cycle(&control_timer); - lock_lock(&state_lock); - local_close = state == RENDER_DISPOSING || state == RENDER_DISPOSED; - lock_unlock(&state_lock); - - classes_process_control(classes, classes_count); - timer_end_of_cycle(&control_timer); - } - timer_dispose(&control_timer); - close = true; - return 0; -} diff --git a/src/CLOUD/input.c b/src/CLOUD/input.c index 45e52926..f691d423 100644 --- a/src/CLOUD/input.c +++ b/src/CLOUD/input.c @@ -10,6 +10,7 @@ #include "../CRE/timer.h" #define CIMGUI_DEFINE_ENUMS_AND_STRUCTS #include +#include #define KEYBOARD_KEYS 0xFF @@ -36,11 +37,13 @@ vec2d input_rotate; double_t input_roll; bool input_reset; bool input_reset_mouse_position; +bool input_shaders_reload; bool input_locked; extern bool close; lock input_lock; extern lock render_lock; +extern timer render_timer; extern HANDLE window_handle; extern ImGuiContext* imgui_context; lock imgui_context_lock; @@ -49,6 +52,7 @@ static void input_poll(); int32_t input_main(void* arg) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + timeBeginPeriod(1); timer_init(&input_timer, 60.0); lock_init(&input_lock); if (!lock_check_init(&input_lock)) @@ -59,20 +63,21 @@ int32_t input_main(void* arg) { do { lock_lock(&state_lock); state_wait = state != RENDER_INITIALIZED; - state_disposed = state == RENDER_DISPOSING || state == RENDER_DISPOSED; + state_disposed = state == RENDER_DISPOSED; lock_unlock(&state_lock); if (state_disposed) { lock_free(&input_lock); goto End; } - msleep(input_timer.timer, 0.0625); + timer_sleep(&input_timer, 0.0625); } while (state_wait); bool local_close = false; + timer_reset(&input_timer); while (!close && !local_close) { timer_start_of_cycle(&input_timer); lock_lock(&state_lock); - local_close = state == RENDER_DISPOSING || state == RENDER_DISPOSED; + local_close = state == RENDER_DISPOSED; lock_unlock(&state_lock); lock_lock(&input_lock); @@ -108,6 +113,10 @@ static void input_poll() { if (!window_handle || window_handle != GetForegroundWindow()) return; + double_t freq = timer_get_freq(&render_timer); + double_t freq_hist = timer_get_freq_hist(&render_timer); + double_t frame_speed = freq / freq_hist; + input_locked = false; classes_process_input(classes, classes_count); @@ -119,6 +128,7 @@ static void input_poll() { speed = input_movement_speed / 10.0; else speed = input_movement_speed; + speed *= freq / freq_hist; if (input_is_down('W')) input_move.x += speed; @@ -130,12 +140,7 @@ static void input_poll() { if (input_is_down('D')) input_move.y += speed; - if (input_is_down(VK_SHIFT)) - speed = input_movement_speed * 100.0; - else if (input_is_down(VK_CONTROL)) - speed = input_movement_speed; - else - speed = input_movement_speed * 10.0; + speed *= 10.0; if (input_is_down(VK_UP)) input_rotate.y += speed; @@ -153,7 +158,10 @@ static void input_poll() { input_roll += speed; if (input_is_tapped('R')) - input_reset = true; + if (input_is_down(VK_CONTROL)) + input_shaders_reload = true; + else + input_reset = true; } lock_lock(&imgui_context_lock); diff --git a/src/CLOUD/main.c b/src/CLOUD/main.c index a6f8dff3..24789812 100644 --- a/src/CLOUD/main.c +++ b/src/CLOUD/main.c @@ -4,6 +4,9 @@ */ #include "../KKdLib/kkfs.h" +#include "../KKdLib/a3da.h" +#include "../KKdLib/f2/struct.h" +#include "../CRE/auth_3d.h" #include "elf.h" #include "main.h" #include "shared.h" @@ -89,11 +92,151 @@ static void decrypt_edat() { io_free(&f1); } -bool close; +static void a3da_to_dft_dsc(char* a3da_path, int32_t pv_id) { + a3da cam_a3da_file; + a3da_init(&cam_a3da_file); + a3da_load_file(&cam_a3da_file, "", a3da_path, 0); -extern LARGE_INTEGER performance_frequency; -extern double_t inv_performance_frequency_msec; -extern double_t inv_performance_frequency_sec; + if (!cam_a3da_file.dof.has_dof) { + a3da_free(&cam_a3da_file); + return; + } + + typedef struct dof_data { + int32_t flags; + float_t focus; + float_t focus_range; + float_t fuzzing_range; + float_t ratio; + float_t quality; + } dof_data; + + auth_3d cam_a3da; + auth_3d_init(&cam_a3da); + auth_3d_load(&cam_a3da, &cam_a3da_file, 0, 0); + a3da_free(&cam_a3da_file); + + int32_t frames = (int32_t)cam_a3da.play_control.size; + + dof_data* dof = force_malloc_s(dof_data, frames + 1ULL); + int32_t* dof_index = force_malloc_s(int32_t, frames); + size_t count = 0; + + *dof++ = (dof_data){ 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + + auth_3d_camera_root* cr = &cam_a3da.camera_root.begin[0]; + + for (int32_t i = 0; i < frames; i++) { + auth_3d_get_value(&cam_a3da, (mat4*)&mat4_identity, (float_t)1.0f); + bool enable = fabs(cam_a3da.dof.model_transform.rotation_value.z) > 0.000001f; + if (!enable) { + dof_index[i] = 0; + continue; + } + + vec3 diff; + float_t focus; + vec3_sub(cam_a3da.dof.model_transform.translation_value, cr->view_point_value, diff); + vec3_length(diff, focus); + + dof_data d; + d.flags = 0x1F; + d.focus = focus; + d.focus_range = cam_a3da.dof.model_transform.scale_value.y; + d.fuzzing_range = cam_a3da.dof.model_transform.rotation_value.y; + d.ratio = cam_a3da.dof.model_transform.rotation_value.z; + d.quality = 1.0f; + + bool found = false; + for (size_t j = 0; j < count; j++) + if (!memcmp(&d, &dof[j], sizeof(dof_data))) { + dof_index[i] = (int32_t)j; + found = true; + break; + } + + if (found) + continue; + + dof[count] = d; + dof_index[i] = (int32_t)count; + count++; + } + + dof--; + + auth_3d_free(&cam_a3da); + + char buf[0x100]; + sprintf_s(buf, sizeof(buf), "pv_%03d_dof.dsc", pv_id); + + stream s_dsc; + io_open(&s_dsc, buf, "wb"); + io_write_uint32_t(&s_dsc, 0x15122517); + int32_t last_dof_index = -1; + for (int32_t i = 0; i < frames; i++) { + if (last_dof_index == dof_index[i]) + continue; + + io_write_int32_t(&s_dsc, 0x01); + io_write_int32_t(&s_dsc, (int32_t)((double_t)i * (100000.0 / 60.0))); // 00000 + io_write_int32_t(&s_dsc, 0x5F); + io_write_int32_t(&s_dsc, dof_index[i] ? 0x01 : 0x00); + io_write_int32_t(&s_dsc, dof_index[i]); + io_write_int32_t(&s_dsc, 0x00); + last_dof_index = dof_index[i]; + } + io_free(&s_dsc); + + stream s_dft; + io_mopen(&s_dft, 0, 0); + uint32_t off; + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + vector_size_t pof = vector_empty(size_t); + + ee = (enrs_entry){ 0, 1, 8, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 8; + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, 24, (int32_t)count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 6, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(count * 24ULL); + off = align_val(off, 0x10); + + io_write_uint32_t(&s_dft, (int32_t)count); + io_write_offset_f2_pof_add(&s_dft, 0x10, 0x40, &pof); + io_align_write(&s_dft, 0x10); + io_write(&s_dft, dof, sizeof(dof_data) * count); + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + + io_align_write(&s_dft, 0x10); + io_mcopy(&s_dft, &st.data, &st.length); + io_free(&s_dft); + + st.enrs = e; + st.pof = pof; + + st.header.signature = reverse_endianness_uint32_t('DOFT'); + st.header.length = 0x40; + st.header.use_big_endian = false; + st.header.use_section_size = true; + st.header.inner_signature = 0x03; + + sprintf_s(buf, sizeof(buf), "pv%03d.dft", pv_id); + f2_struct_write(&st, buf, true, false); + f2_struct_free(&st); + + free(dof); + free(dof_index); +} + +bool close; typedef struct thread { HANDLE handle; @@ -103,12 +246,8 @@ typedef struct thread { int32_t wmain(int32_t argc, wchar_t** argv) { //ShowWindow(GetConsoleWindow(), SW_HIDE); timeBeginPeriod(1); - QueryPerformanceFrequency(&performance_frequency); SetProcessDPIAware(); - inv_performance_frequency_msec = 1000.0 / (double_t)performance_frequency.QuadPart; - inv_performance_frequency_sec = 1000000.0 / (double_t)performance_frequency.QuadPart; - int32_t cpuid_data[4]; __cpuid(cpuid_data, 1); aes_ni = cpuid_data[2] & 0x2000000 ? true : false; @@ -118,58 +257,14 @@ int32_t wmain(int32_t argc, wchar_t** argv) { ris.res.y = 0; ris.scale = 0.0f; -#if defined(VIDEO) -#if defined(DEBUG) || defined(DEBUG_DEV) -#pragma comment(lib, "libx264d.lib") -#else -#pragma comment(lib, "libx264.lib") -#endif + //a3da_to_dft_dsc("CAMPV269_BASE.a3da", 269); - thread control, input, render, sound, video; - HANDLE h[5]; - h[0] = control.handle = CreateThread(0, 0, &control_main, 0, 0, &control.id); - h[1] = input.handle = CreateThread(0, 0, &input_main, 0, 0, &input.id); - h[2] = render.handle = CreateThread(0, 0, &render_main, &ris, 0, &render.id); - h[3] = sound.handle = CreateThread(0, 0, &sound_main, 0, 0, &sound.id); - h[4] = video.handle = CreateThread(0, 0, &video_main, 0, 0, &video.id); + thread input, render, sound; + HANDLE h[3]; + h[0] = input.handle = CreateThread(0, 0, &input_main, 0, 0, &input.id); + h[1] = render.handle = CreateThread(0, 0, &render_main, &ris, 0, &render.id); + h[2] = sound.handle = CreateThread(0, 0, &sound_main, 0, 0, &sound.id); - if (control.handle) - SetThreadDescription(control.handle, L"Control Thread"); - if (input.handle) - SetThreadDescription(input.handle, L"Input Thread"); - if (render.handle) - SetThreadDescription(render.handle, L"Render Thread"); - if (sound.handle) - SetThreadDescription(sound.handle, L"Sound Thread"); - if (video.handle) - SetThreadDescription(sound.handle, L"Video Thread"); - - lock_init(&state_lock); - state = RENDER_UNINITIALIZED; - if (control.handle && input.handle && render.handle && sound.handle && video.handle) - WaitForMultipleObjects(5, h, true, INFINITE); - lock_free(&state_lock); - - if (control.handle) - CloseHandle(control.handle); - if (input.handle) - CloseHandle(input.handle); - if (render.handle) - CloseHandle(render.handle); - if (sound.handle) - CloseHandle(sound.handle); - if (video.handle) - CloseHandle(video.handle); -#else - thread control, input, render, sound; - HANDLE h[4]; - h[0] = control.handle = CreateThread(0, 0, &control_main, 0, 0, &control.id); - h[1] = input.handle = CreateThread(0, 0, &input_main, 0, 0, &input.id); - h[2] = render.handle = CreateThread(0, 0, &render_main, &ris, 0, &render.id); - h[3] = sound.handle = CreateThread(0, 0, &sound_main, 0, 0, &sound.id); - - if (control.handle) - SetThreadDescription(control.handle, L"Control Thread"); if (input.handle) SetThreadDescription(input.handle, L"Input Thread"); if (render.handle) @@ -179,19 +274,16 @@ int32_t wmain(int32_t argc, wchar_t** argv) { lock_init(&state_lock); state = RENDER_UNINITIALIZED; - if (control.handle && input.handle && render.handle && sound.handle) - WaitForMultipleObjects(4, h, true, INFINITE); + if (input.handle && render.handle && sound.handle) + WaitForMultipleObjects(3, h, true, INFINITE); lock_free(&state_lock); - if (control.handle) - CloseHandle(control.handle); if (input.handle) CloseHandle(input.handle); if (render.handle) CloseHandle(render.handle); if (sound.handle) CloseHandle(sound.handle); -#endif timeEndPeriod(1); return 0; } diff --git a/src/CLOUD/main.h b/src/CLOUD/main.h index 5c9754b9..efb890c3 100644 --- a/src/CLOUD/main.h +++ b/src/CLOUD/main.h @@ -6,8 +6,6 @@ #pragma once #include "../KKdLib/default.h" -#include "control.h" #include "input.h" #include "render.h" #include "sound.h" -#include "video.h" diff --git a/src/CLOUD/render.c b/src/CLOUD/render.c index 31545912..530da4aa 100644 --- a/src/CLOUD/render.c +++ b/src/CLOUD/render.c @@ -6,73 +6,58 @@ */ #include "render.h" -#include "../CRE/camera.h" -#include "../CRE/dof.h" -#include "../CRE/gl_state.h" -#include "../CRE/post_process.h" -#include "../CRE/random.h" -#include "../CRE/shader.h" -#include "../CRE/shader_aft.h" -#include "../CRE/static_var.h" -#include "../KKdLib/farc.h" #include #include #define GLFW_EXPOSE_NATIVE_WIN32 #include #include -#include "../CRE/fbo_hdr.h" -#include "../CRE/fbo_pp.h" -#include "../CRE/fbo_render.h" -#include "../CRE/fbo_helper.h" -#include "../CRE/lock.h" -#include "../CRE/shader_glsl.h" -#include "../CRE/timer.h" #include "../CRE/Glitter/particle_manager.h" -#include "../CRE/post_process/dof.h" -#include "../CRE/fbo_hdr.h" +#include "../CRE/camera.h" +#include "../CRE/data.h" +#include "../CRE/draw_pass.h" +#include "../CRE/fbo.h" +#include "../CRE/gl_state.h" +#include "../CRE/light_param.h" +#include "../CRE/lock.h" +#include "../CRE/object.h" +#include "../CRE/random.h" +#include "../CRE/rob.h" +#include "../CRE/shader.h" +#include "../CRE/shader_ft.h" +#include "../CRE/shader_glsl.h" +#include "../CRE/stage.h" +#include "../CRE/static_var.h" +#include "../CRE/texture.h" +#include "../CRE/timer.h" +#include "../CRE/post_process.h" +#include "../KKdLib/io/path.h" +#include "../KKdLib/farc.h" +#include"classes/imgui_helper.h" +#include #if defined(DEBUG) #define OPENGL_DEBUG 0 #endif -fbo_render* rfbo; -fbo_hdr* hfbo; -fbo_pp* pfbo; - -post_process_dof pp_dof; - -shader_set_data shaders_aft; - -static shader_glsl bfbs[14]; -static shader_glsl cfbs[2]; -static shader_glsl dfbs[9]; -static shader_glsl fxaas[3]; -static shader_glsl ffbs; shader_glsl grid_shader; timer render_timer; #define grid_size 50.0f -#define grid_spacing 0.5f -#define grid_vertex_count ((size_t)((grid_size * 2.0f) / grid_spacing) + 1) * 4 +#define grid_spacing 1.0f +const size_t grid_vertex_count = ((size_t)(grid_size / grid_spacing) * 2 + 1) * 4; -static int32_t fb_vao, fb_vbo; -static int32_t grid_vao, grid_vbo; -static int32_t common_data_ubo = 0; +GLuint grid_vbo; +static GLuint common_data_ubo = 0; +stage stage_stgtst; +stage stage_test_data; #define COMMON_DATA_SIZE (int32_t)(sizeof(vec4) + sizeof(mat4) * 3 + sizeof(vec4)) -bool imgui = true; -bool ui = true; -bool front_2d = true; -bool grid_3d = false; -bool front_3d = true; -bool back_2d = true; -bool glitter_3d = true; +bool draw_imgui = true; +bool draw_grid_3d = false; -bool enable_post_process = true; - -extern const double_t render_scale_table[] = { +const double_t render_scale_table[] = { 1.0 / 4.0, // 25% 2.0 / 4.0, // 50% 3.0 / 4.0, // 75% @@ -89,41 +74,34 @@ static vec2i old_internal_2d_res; static vec2i old_internal_3d_res; vec2i internal_2d_res; vec2i internal_3d_res; +static int32_t old_width; +static int32_t old_height; int32_t width; int32_t height; static const double_t aspect = 16.0 / 9.0; -camera* cam; -dof_struct* dof; -radius* rad; -intensity* inten; -tone_map* tm; -glitter_particle_manager* gpm; vec3 back3d_color; bool set_clear_color; -static void render_load(); -static void render_update(); -static void render_draw(); -static void render_dispose(); +bool light_chara_ambient; +vec4 npr_spec_color; -static void render_imgui(); -static void render_2d(); -static void render_3d(); -static void render_3d_translucent(); -static void render_grid_3d(); -static void render_glitter_3d(alpha_pass_type alpha); +static render_context* render_load(); +static bool render_load_shaders(void* data, char* path, char* file, uint32_t hash); +static void render_update(render_context* rctx); +static void render_draw(render_context* rctx); +static void render_dispose(render_context* rctx); -static void render_get_aspect_correct_2d_res(vec2i* res); -static void render_get_aspect_correct_3d_res(vec2i* res); +static void render_imgui(render_context* rctx); static void render_drop_glfw(GLFWwindow* window, int32_t count, char** paths); static void render_resize_fb_glfw(GLFWwindow* window, int32_t w, int32_t h); -static void render_resize_fb(bool change_fb); +static void render_resize_fb(render_context* rctx, bool change_fb); -static void render_imgui_context_menu(classes_struct* classes, const size_t classes_count); -static bool render_glitter_mesh_update(glitter_render_element* element, - glitter_particle_mesh* mesh_data, vec4* color, mat4* mat, mat4* uv_mat); +static void render_imgui_context_menu(classes_struct* classes, + const size_t classes_count, render_context* rctx); +static void render_shaders_load(); +static void render_shaders_free(); #if defined (DEBUG) && OPENGL_DEBUG static void APIENTRY render_debug_output(GLenum source, GLenum type, uint32_t id, @@ -131,15 +109,20 @@ static void APIENTRY render_debug_output(GLenum source, GLenum type, uint32_t id #endif extern bool close; +bool reload_render; lock render_lock; HWND window_handle; GLFWwindow* window; ImGuiContext* imgui_context; lock imgui_context_lock; bool global_context_menu; +extern size_t frame_counter; +wind* wind_ptr; +object_database* obj_db_ptr; int32_t render_main(void* arg) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + timeBeginPeriod(1); timer_init(&render_timer, 60.0); state = RENDER_UNINITIALIZED; @@ -202,7 +185,7 @@ int32_t render_main(void* arg) { glfwFocusWindow(window); glfwSetDropCallback(window, (void*)render_drop_glfw); glfwSetWindowSizeCallback(window, (void*)render_resize_fb_glfw); - glfwSetWindowSizeLimits(window, 960, 540, GLFW_DONT_CARE, GLFW_DONT_CARE); + glfwSetWindowSizeLimits(window, 896, 504, GLFW_DONT_CARE, GLFW_DONT_CARE); RECT window_rect; GetClientRect(window_handle, &window_rect); @@ -230,57 +213,70 @@ int32_t render_main(void* arg) { glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &sv_max_texture_max_anisotropy); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + lock_init(&pv_lock); + lock_lock(&state_lock); state = RENDER_INITIALIZING; lock_unlock(&state_lock); - lock_lock(&render_lock); - render_load(); - lock_unlock(&render_lock); + do { + close = false; + reload_render = false; - lock_lock(&state_lock); - state = RENDER_INITIALIZED; - lock_unlock(&state_lock); + render_context* rctx = 0; + lock_lock(&render_lock); + rctx = render_load(); + lock_unlock(&render_lock); + + lock_lock(&state_lock); + frame_counter = 0; + state = RENDER_INITIALIZED; + lock_unlock(&state_lock); #pragma region GL Init - glfwGetFramebufferSize(window, &width, &height); - glViewport(0, 0, width, height); - glfwSwapInterval(0); + glfwGetFramebufferSize(window, &width, &height); + glViewport(0, 0, width, height); + glfwSwapInterval(0); - gl_state_disable_blend(); - gl_state_disable_depth_test(); - gl_state_set_depth_mask(GL_FALSE); - gl_state_disable_cull_face(); - gl_state_disable_stencil_test(); + gl_state_disable_blend(); + gl_state_disable_depth_test(); + gl_state_set_depth_mask(GL_FALSE); + gl_state_disable_cull_face(); + gl_state_disable_stencil_test(); #pragma endregion - while (!close) { - timer_start_of_cycle(&render_timer); - glfwPollEvents(); - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - igNewFrame(); + timer_reset(&render_timer); + while (!close && !reload_render) { + timer_start_of_cycle(&render_timer); + glfwPollEvents(); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + igNewFrame(); + lock_lock(&render_lock); + render_update(rctx); + lock_unlock(&render_lock); + render_draw(rctx); + glfwSwapBuffers(window); + close |= glfwWindowShouldClose(window); + frame_counter++; + timer_end_of_cycle(&render_timer); + } + + lock_lock(&state_lock); + state = RENDER_DISPOSING; + lock_unlock(&state_lock); + lock_lock(&render_lock); - render_update(); + render_dispose(rctx); lock_unlock(&render_lock); - render_draw(); - glfwSwapBuffers(window); - close |= glfwWindowShouldClose(window); - timer_end_of_cycle(&render_timer); - } - - lock_lock(&state_lock); - state = RENDER_DISPOSING; - lock_unlock(&state_lock); - - lock_lock(&render_lock); - render_dispose(); - lock_unlock(&render_lock); + } while (reload_render); lock_lock(&state_lock); state = RENDER_DISPOSED; lock_unlock(&state_lock); + lock_free(&pv_lock); + #pragma region GLFW Dispose glfwDestroyWindow(window); glfwTerminate(); @@ -337,274 +333,220 @@ void render_set_scale_index(int32_t index) { scale = (float_t)value; } -static void render_load() { +static render_context* render_load() { + object_storage_init(); + texture_storage_init(); + + render_context* rctx = render_context_init(); + gl_state_get(); + render_texture_data_init(); - cam = camera_init(); - dof = dof_init(); - rad = radius_init(); - inten = intensity_init(); - tm = tone_map_init(); - gpm = glitter_particle_manager_init(); + auth_3d_data_init(); + light_param_storage_init(); + motion_storage_init(); - dof_initialize(dof, 0, 0); - radius_initialize(rad, (vec3[]) { 2.0f, 2.0f, 2.0f }); - intensity_initialize(inten, (vec3[]) { 1.0f, 1.0f, 1.0f }); - tone_map_initialize(tm, 2.0f, true, 1.0f, 1, 1.0f, (vec3[]) { 0.0f, 0.0f, 0.0f}, - 0.0f, 0, (vec3[]) { 0.0f, 0.0f, 0.0f }, (vec3[]) { 1.0f, 1.0f, 1.0f }, 0); + GPM_VAL = glitter_particle_manager_init(); + GPM_VAL->rctx = rctx; - camera_initialize(cam, aspect, 70.0); - camera_reset(cam); - //camera_set_position(cam, &(vec3){ 1.35542f, 1.41634f, 1.27852f }); - //camera_rotate(cam, &(vec2d){ -45.0, -32.5 }); - //camera_set_position(cam, &(vec3){ -6.67555f, 4.68882f, -3.67537f }); - //camera_rotate(cam, &(vec2d){ 136.5, -20.5 }); - camera_set_position(cam, &(vec3){ 0.0f, 1.0f, 3.45f }); + data_struct_init(); + data_struct_load("CLOUD_data.txt"); glGenBuffers(1, &common_data_ubo); gl_state_bind_uniform_buffer(common_data_ubo); glBufferData(GL_UNIFORM_BUFFER, COMMON_DATA_SIZE, 0, GL_STREAM_DRAW); - glBindBufferRange(GL_UNIFORM_BUFFER, 0, common_data_ubo, 0, COMMON_DATA_SIZE); + gl_state_bind_uniform_buffer(0); -#pragma region Load Shaders - char temp[0x80]; - memset(temp, 0, sizeof(temp)); + uniform_value[U16] = 1; - hfbo = fbo_hdr_init(); - rfbo = fbo_render_init(); - pfbo = fbo_pp_init(); + render_shaders_load(); - post_process_dof_init(&pp_dof); + const char* grid_vert_shader = + "#version 430 core\n" + "layout(location = 0) in vec4 a_position;\n" + "layout(location = 1) in int a_color_index;\n" + "\n" + "out VertexData {\n" + " vec4 color;\n" + "} result;\n" + "\n" + "layout(location = 0) uniform mat4 vp;\n" + "\n" + "vec4 colors[] = {\n" + " vec4(1.0, 0.0, 0.0, 1.0),\n" + " vec4(0.0, 1.0, 0.0, 1.0),\n" + " vec4(0.2, 0.2, 0.2, 1.0),\n" + "};\n" + "\n" + "void main() {\n" + " gl_Position = vp * a_position.xzyw;\n" + " result.color = colors[a_color_index];\n" + "}\n"; - const float_t verts_quad[] = { - -1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -3.0f, 0.0f, -1.0f, - 3.0f, 1.0f, 2.0f, 1.0f, - }; + const char* grid_frag_shader = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "in VertexData {\n" + " vec4 color;\n" + "} frg;\n" + "\n" + "void main() {\n" + " result = frg.color;\n" + "}\n"; - glGenBuffers(1, &fb_vbo); - glGenVertexArrays(1, &fb_vao); - glBindBuffer(GL_ARRAY_BUFFER, fb_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(verts_quad), verts_quad, GL_STATIC_DRAW); + const char* fbo_render_vert_shader = "#version 430 core\n" + "void main() {\n" + " gl_Position.x = -1.0 + float(gl_VertexID / 2) * 4.0;\n" + " gl_Position.y = 1.0 - float(gl_VertexID % 2) * 4.0;\n" + " gl_Position.z = 0.0;\n" + " gl_Position.w = 1.0;\n" + "}\n"; - gl_state_bind_vertex_array(fb_vao); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, (void*)0); // Pos - glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); // Color0 - glVertexAttrib4f(4, 1.0f, 1.0f, 1.0f, 1.0f); // Color1 - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord0 - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord1 - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord2 - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord3 - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord4 - glEnableVertexAttribArray(13); - glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord5 - glEnableVertexAttribArray(14); - glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord6 - glEnableVertexAttribArray(15); - glVertexAttribPointer(15, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord7 - gl_state_bind_vertex_array(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + const char* fbo_render_color_frag_shader = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "layout(binding = 0) uniform sampler2D g_color;\n" + "\n" + "void main() {\n" + " result = texelFetch(g_color, ivec2(gl_FragCoord.xy), 0);\n" + "}\n"; - farc* f = farc_init(); - farc_read(f, "rom\\aft_shaders.farc", true, false); - shader_aft_load(&shaders_aft, f, false); - farc_dispose(f); - - f = farc_init(); - farc_read(f, "rom\\core_shaders.farc", true, false); + const char* fbo_render_depth_frag_shader = "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "layout(binding = 0) uniform sampler2D g_color;\n" + "layout(binding = 1) uniform sampler2D g_depth;\n" + "\n" + "void main() {\n" + " result = texelFetch(g_color, ivec2(gl_FragCoord.xy), 0);\n" + " gl_FragDepth = texelFetch(g_depth, ivec2(gl_FragCoord.xy), 0).r;\n" + "}\n"; shader_glsl_param param; - - memset(¶m, 0, sizeof(shader_glsl_param)); - param.name = "Color FB Color"; - param.vert = "rfb"; - param.frag = "cfbc"; - shader_glsl_load(&cfbs[0], f, ¶m); - - memset(¶m, 0, sizeof(shader_glsl_param)); - param.name = "Color FB Depth"; - param.vert = "rfb"; - param.frag = "cfbd"; - shader_glsl_load(&cfbs[1], f, ¶m); - - for (int32_t i = 3; i < 6; i++) { - memset(¶m, 0, sizeof(shader_glsl_param)); - param.name = "FXAA"; - param.vert = "rfb"; - param.frag = "fxaa"; - snprintf(temp, sizeof(temp), "FXAA_PRESET %d", i); - param.param[0] = temp; - shader_glsl_load(&fxaas[i - 3], f, ¶m); - } - - memset(¶m, 0, sizeof(shader_glsl_param)); - param.name = "Final FB"; - param.vert = "rfb"; - param.frag = "rfb"; - shader_glsl_load(&ffbs, f, ¶m); - - char* post_process_vert_shaders[] = { - "rfb", - "rfb", - "rfb", - "exposure1", - "rfb", - "rfb", - "rfb", - "rfb", - "rfb", - "rfb", - "blur5", - "rfb", - "exposure2", - "exposure3", - }; - - char* post_process_frag_shaders[] = { - "blur1", - "blur2", - "blur3", - "exposure1", - "blur4", - "blur4", - "blur4", - "blur4", - "blur4", - "blur4", - "blur5", - "blur6", - "exposure2", - "exposure3", - }; - - for (int32_t i = 0; i < 14; i++) { - memset(¶m, 0, sizeof(shader_glsl_param)); - param.param[0] = temp; - param.name = "Post Process FB"; - param.vert = post_process_vert_shaders[i]; - param.frag = post_process_frag_shaders[i]; - shader_glsl_load(&bfbs[i], f, ¶m); - } - memset(¶m, 0, sizeof(shader_glsl_param)); param.name = "Grid"; - param.vert = "grid"; - param.frag = "grid"; - shader_glsl_load(&grid_shader, f, ¶m); - farc_dispose(f); + shader_glsl_load_string(&grid_shader, + (char*)grid_vert_shader, (char*)grid_frag_shader, 0, ¶m); - shader_glsl_set_int(&cfbs[0], "g_color", 0); - shader_glsl_set_int(&cfbs[1], "g_color", 0); - shader_glsl_set_int(&cfbs[1], "g_depth", 1); + render_resize_fb(rctx, false); - for (int32_t i = 0; i < 3; i++) - shader_glsl_set_int(&fxaas[i], "g_color", 0); + post_process_init_fbo(&rctx->post_process, internal_3d_res.x, internal_3d_res.y, + internal_2d_res.x, internal_2d_res.y, width, height); - shader_glsl_set_int(&ffbs, "g_color", 0); + render_resize_fb(rctx, true); - for (int32_t i = 0; i < 2; i++) - shader_glsl_set_int(&bfbs[i], "g_color", 0); + rob_chara_data_array_init(); - shader_glsl_set_int(&bfbs[2], "g_color", 0); + data_struct* aft_data = &data_list[DATA_AFT]; + auth_3d_database* aft_auth_3d_db = &aft_data->data_ft.auth_3d_db; + bone_database* aft_bone_data = &aft_data->data_ft.bone_data; + motion_database* aft_mot_db = &aft_data->data_ft.mot_db; + object_database* aft_obj_db = &aft_data->data_ft.obj_db; + texture_database* aft_tex_db = &aft_data->data_ft.tex_db; + stage_database* aft_stage_data = &aft_data->data_ft.stage_data; - shader_glsl_set_int(&bfbs[3], "g_color", 0); + rctx->data = aft_data; - for (int32_t i = 4; i < 11; i++) - shader_glsl_set_int(&bfbs[i], "g_color", 0); + stage_init(&stage_stgtst); + stage_load(&stage_stgtst, aft_data, aft_auth_3d_db, + aft_obj_db, aft_tex_db, aft_stage_data, "STGTST", rctx); + stage_set(&stage_stgtst, rctx); - shader_glsl_set_int(&bfbs[11], "g_bloom_full", 0); - shader_glsl_set_int(&bfbs[11], "g_bloom_half", 1); - shader_glsl_set_int(&bfbs[11], "g_bloom_quat", 2); - shader_glsl_set_int(&bfbs[11], "g_bloom_eight", 3); - shader_glsl_set_int(&bfbs[12], "g_luma", 0); - shader_glsl_set_int(&bfbs[13], "g_exp_hist", 0); + object_set_info* set_info; + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM000"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM001"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM301"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM500"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM181"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM481"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM681"); + object_set_load_db_entry(&set_info, aft_data, aft_obj_db, "MIKITM981"); + motion_set_load_motion(216, 0, aft_mot_db); - render_resize_fb(false); + rob_chara_pv_data pv_data; + rob_chara_pv_data_init(&pv_data); + item_sub_data sub_data; + memset(&sub_data, 0, sizeof(item_sub_data)); + sub_data.kami = 500; + sub_data.outer = 1; + sub_data.kata = 301; + //sub_data.kami = 681; + //sub_data.outer = 181; + //sub_data.kata = 481; + //sub_data.head = 981; + rob_chara_data_set(&rob_chara_data_array[0], 0, CHARA_MIKU, 0, &pv_data); + rob_chara_data_reset(&rob_chara_data_array[0], + &rob_chara_data_array[0].pv_data, aft_bone_data, aft_mot_db); + rob_chara_data_reload_items(&rob_chara_data_array[0], &sub_data, aft_bone_data); + rob_chara_data_load_motion(&rob_chara_data_array[0], 1294, 2, aft_bone_data, aft_mot_db); - fbo_render_initialize(rfbo, &internal_3d_res, fb_vao, &cfbs[0], &cfbs[1]); - fbo_hdr_initialize(hfbo, &internal_3d_res, fb_vao, fxaas); - fbo_pp_initialize(pfbo, &internal_3d_res, fb_vao, bfbs); - - post_process_dof_init_fbo(&pp_dof, internal_3d_res.x, internal_3d_res.y); - - render_resize_fb(true); -#pragma endregion - - float_t* grid_verts = force_malloc_s(float_t, grid_vertex_count * 4); - - vec4h r_color, g_color, b_color, m_color; - vec4_to_vec4h(((vec4) { 1.0f, 0.0f, 0.0f, 1.0f }), r_color); - vec4_to_vec4h(((vec4) { 0.0f, 1.0f, 0.0f, 1.0f }), g_color); - vec4_to_vec4h(((vec4) { 0.2f, 0.2f, 0.2f, 0.6f }), b_color); - vec4_to_vec4h(((vec4) { 0.5f, 0.5f, 0.5f, 0.6f }), m_color); + float_t* grid_verts = force_malloc(sizeof(float_t) * 3 * grid_vertex_count); size_t v = 0; for (float_t x = -grid_size; x <= grid_size; x += grid_spacing) { - vec4h x_color; - vec4h z_color; + int32_t x_color_index; + int32_t z_color_index; if (x == 0) { - x_color = r_color; - z_color = g_color; - } - else if (abs((int32_t)(x / grid_spacing)) % 2 == 0) { - x_color = b_color; - z_color = b_color; + x_color_index = 0; + z_color_index = 1; } else { - x_color = m_color; - z_color = m_color; + x_color_index = 2; + z_color_index = 2; } grid_verts[v++] = x; grid_verts[v++] = -grid_size; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&x_color.x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&x_color.z; + *(int32_t*)&grid_verts[v++] = x_color_index; grid_verts[v++] = x; grid_verts[v++] = grid_size; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&x_color.x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&x_color.z; + *(int32_t*)&grid_verts[v++] = x_color_index; grid_verts[v++] = -grid_size; grid_verts[v++] = x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&z_color.x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&z_color.z; + *(int32_t*)&grid_verts[v++] = z_color_index; grid_verts[v++] = grid_size; grid_verts[v++] = x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&z_color.x; - *(vec2h*)&grid_verts[v++] = *(vec2h*)&z_color.z; + *(int32_t*)&grid_verts[v++] = z_color_index; } glGenBuffers(1, &grid_vbo); - glBindBuffer(GL_ARRAY_BUFFER, grid_vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(float_t) - * grid_vertex_count * 4, grid_verts, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glGenVertexArrays(1, &grid_vao); - gl_state_bind_vertex_array(grid_vao); - glBindBuffer(GL_ARRAY_BUFFER, grid_vbo); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, - sizeof(float_t) * 4, (void*)0); // Pos - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_HALF_FLOAT, GL_FALSE, - sizeof(float_t) * 4, (void*)(sizeof(float_t) * 2)); // Color - gl_state_bind_vertex_array(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + gl_state_bind_array_buffer(grid_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(float_t) * 3 + * grid_vertex_count, grid_verts, GL_STATIC_DRAW); + gl_state_bind_array_buffer(0); free(grid_verts); + camera* cam = rctx->camera; + + camera_initialize(cam, aspect, internal_3d_res.x, internal_3d_res.y); + camera_reset(cam); + //camera_set_position(cam, &((vec3){ 1.35542f, 1.41634f, 1.27852f })); + //camera_rotate(cam, &((vec2d){ -45.0, -32.5 })); + //camera_set_position(cam, &((vec3){ -6.67555f, 4.68882f, -3.67537f })); + //camera_rotate(cam, &((vec2d){ 136.5, -20.5 })); + camera_set_position(cam, &((vec3) { 0.0f, 1.0f, 3.45f })); + camera_set_fov(cam, 70.0); + + typedef struct struc_403 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + } struc_403; + + typedef struct struc_404 { + int32_t field_0; + int32_t field_4; + } struc_404; + imgui_context = igCreateContext(0); lock_init(&imgui_context_lock); @@ -619,59 +561,90 @@ static void render_load() { ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 430"); - back3d_color = (vec3){ 0.74117647f, 0.74117647f, 0.74117647f }; + back3d_color = (vec3){ (float_t)(96.0 / 255.0), (float_t)(96.0 / 255.0), (float_t)(96.0 / 255.0) }; set_clear_color = true; - shader_env_vert_set_ptr(&shaders_aft, 3, (vec4*)&vec4_identity); - shader_env_vert_set_ptr(&shaders_aft, 4, (vec4*)&vec4_null); - classes_process_init(classes, classes_count); + shader_env_vert_set_ptr(&shaders_ft, 3, (vec4*)&vec4_identity); + shader_env_vert_set_ptr(&shaders_ft, 4, (vec4*)&vec4_null); + classes_process_init(classes, classes_count, rctx); + return rctx; +} + +static bool render_load_shaders(void* data, char* path, char* file, uint32_t hash) { + string s; + string_init(&s, path); + string_add(&s, file); + + farc f; + farc_init(&f); + farc_read(&f, string_data(&s), true, false); + shader_ft_load(data, &f, false); + farc_free(&f); + + string_free(&s); + return true; } extern vec2d input_move; extern vec2d input_rotate; extern double_t input_roll; extern bool input_reset; +extern bool input_shaders_reload; + +static void render_update(render_context* rctx) { + camera* cam = rctx->camera; + + for (int32_t i = 0; i < 32; i++) { + if (!gl_state_check_texture_binding_2d(i) && !gl_state_check_texture_binding_cube_map(i)) + continue; + + gl_state_active_bind_texture_2d(i, 0); + gl_state_active_bind_texture_cube_map(i, 0); + gl_state_bind_sampler(i, 0); + } -static void render_update() { global_context_menu = true; lock_lock(&imgui_context_lock); igSetCurrentContext(imgui_context); classes_process_imgui(classes, classes_count); lock_unlock(&imgui_context_lock); - if (sv_fxaa_changed) - sv_fxaa_changed = false; - - if (sv_fxaa_preset_changed) - sv_fxaa_preset_changed = false; - - if (old_scale != scale) - render_resize_fb(true); + if (old_width != width || old_height != height || old_scale != scale) { + render_resize_fb(rctx, true); + camera_set_res(cam, internal_3d_res.x, internal_3d_res.y); + } + old_width = width; + old_height = height; old_scale = scale; lock_lock(&imgui_context_lock); igSetCurrentContext(imgui_context); if (global_context_menu && igIsMouseReleased(ImGuiMouseButton_Right) && !igIsItemHovered(0) && imgui_context->OpenPopupStack.Size <= 0) - igOpenPopup("Classes init context menu", 0); + igOpenPopup_Str("Classes init context menu", 0); if (igBeginPopupContextItem("Classes init context menu", 0)) { - render_imgui_context_menu(classes, classes_count); + render_imgui_context_menu(classes, classes_count, rctx); igEndPopup(); } lock_unlock(&imgui_context_lock); - igRender(); + if (input_shaders_reload) { + input_shaders_reload = false; + render_shaders_free(); + render_shaders_load(); + } if (window_handle == GetForegroundWindow()) { if (input_reset) { input_reset = false; camera_reset(cam); - //camera_set_position(cam, &(vec3){ 1.35542f, 1.41634f, 1.27852f }); - //camera_rotate(cam, &(vec2d){ -45.0, -32.5 }); - //camera_set_position(cam, &(vec3){ -6.67555f, 4.68882f, -3.67537f }); - //camera_rotate(cam, &(vec2d){ 136.5, -20.5 }); - camera_set_position(cam, &(vec3){ 0.0f, 1.0f, 3.45f }); + //camera_set_position(cam, &((vec3){ 1.35542f, 1.41634f, 1.27852f })); + //camera_rotate(cam, &((vec2d){ -45.0, -32.5 })); + //camera_set_position(cam, &((vec3){ -6.67555f, 4.68882f, -3.67537f })); + //camera_rotate(cam, &((vec2d){ 136.5, -20.5 })); + camera_set_position(cam, &((vec3){ 0.0f, 1.0f, 3.45f })); + camera_set_fov(cam, 70.0); } else { camera_rotate(cam, &input_rotate); @@ -681,93 +654,29 @@ static void render_update() { } camera_update(cam); - glitter_render_mesh_update_func = render_glitter_mesh_update; + float_t frame = rob_chara_data_get_frame(&rob_chara_data_array[0]); + float_t frame_count = rob_chara_data_get_frame_count(&rob_chara_data_array[0]); + frame += get_delta_frame(); + if (frame >= frame_count) + frame -= frame_count; + rob_chara_data_set_frame(&rob_chara_data_array[0], frame); + rob_chara_data_array[0].item_equip->shadow_type = SHADOW_CHARA; + + data_struct* aft_data = &data_list[DATA_AFT]; + obj_db_ptr = &aft_data->data_ft.obj_db; + render_context_update(rctx); + classes_process_render(classes, classes_count); - GPM_VAL->updated = false; + wind_ptr = rctx->wind; + rob_chara_data_calc(&rob_chara_data_array[0]); + rob_chara_data_draw(&rob_chara_data_array[0], rctx); - if (memcmp(&GPM_VAL->cam_projection, &cam->projection, sizeof(GPM_VAL->cam_projection))) - GPM_VAL->cam_projection = cam->projection; + stage_update(rctx->stage, rctx); - if (memcmp(&GPM_VAL->cam_view, &cam->view, sizeof(GPM_VAL->cam_view))) { - GPM_VAL->cam_view = cam->view; - GPM_VAL->updated = true; - } + shadow_update(rctx->draw_pass.shadow_ptr, rctx); - if (memcmp(&GPM_VAL->cam_inv_view, &cam->inv_view, sizeof(GPM_VAL->cam_inv_view))) { - GPM_VAL->cam_inv_view = cam->inv_view; - GPM_VAL->updated = true; - } - - if (memcmp(&GPM_VAL->cam_inv_view_mat3, &cam->inv_view_mat3, - sizeof(GPM_VAL->cam_inv_view_mat3))) { - GPM_VAL->cam_inv_view_mat3 = cam->inv_view_mat3; - GPM_VAL->updated = true; - } - - if (memcmp(&GPM_VAL->cam_view_point, &cam->view_point, sizeof(GPM_VAL->cam_view_point))) { - GPM_VAL->cam_view_point = cam->view_point; - GPM_VAL->updated = true; - } - - if (memcmp(&GPM_VAL->cam_rotation_y, &cam->rotation.y, sizeof(GPM_VAL->cam_rotation_y))) { - GPM_VAL->cam_rotation_y = cam->rotation.y; - GPM_VAL->updated = true; - } - - glitter_render_mesh_update_func = render_glitter_mesh_update; - glitter_particle_manager_calc_draw(GPM_VAL); - - /*cam.Set(camStruct); - - if (camStruct.DOF.HasValue) - { - ModelTrans dofMT = camStruct.DOF.Value; - - dof.Debug.Flags = 0; - dof.PV.DistanceToFocus = (dofMT.Trans - cam.Pos).Length; - dof.PV.FocusRange = dofMT.Scale.X; - dof.PV.FuzzingRange = dofMT.Rot.X; - dof.PV.Ratio = dofMT.Rot.Y; - dof.PV.Enable = camStruct.DOF.Value.Rot.Z > 0.000001f; - - if (dof.PV.Ratio > 0.0f && dof.PV.Enable) - { - double fov = cam.FOVIsHorizontal ? 2 - * Math.Atan(1 / cam.Aspect * Math.Tan(cam.FOV / 2)) : cam.FOV; - float[] data = GetDOFData(ref dof, (float)fov); - - GL.BindBuffer(BufferTarget.UniformBuffer, dofCommonUBO); - GL.BufferSubData(BufferTarget.UniformBuffer, (IntPtr)0, data.Length * 4, data); - GL.BindBuffer(BufferTarget.UniformBuffer, 0); - } - }*/ - - //static bool show_demo_window; - //igShowDemoWindow(&show_demo_window); - - if (rad->update || inten->update) { - rad->update = false; - inten->update = false; - - vec3 rgb = inten->val; - vec3* radius = rad->val; - - float_t intensity_scale = 1.0f; - vec3_mult_scalar(rgb, intensity_scale, rgb); - - vec3 v[GAUSSIAN_KERNEL_SIZE]; - for (int32_t i = 0; i < GAUSSIAN_KERNEL_SIZE; i++) - vec3_mult(radius[i], rgb, v[i]); - - for (int32_t i = 4; i < 10; i++) - shader_glsl_set_vec3_array(&bfbs[i], "gaussian_kernel", GAUSSIAN_KERNEL_SIZE, v); - } - - if (tm->update_tex) { - tm->update_tex = false; - fbo_pp_tone_map_set(pfbo, tm->tex, 16 * TONE_MAP_SAT_GAMMA_SAMPLES); - } + igRender(); struct common_data_struct { vec4 res; //x=width, y=height, z=1/width, w=1/height @@ -791,11 +700,20 @@ static void render_update() { gl_state_bind_uniform_buffer(0); } -static void render_draw() { +static void render_draw(render_context* rctx) { static const GLfloat color_clear[] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const GLfloat depth_clear = 1.0f; static const GLint stencil_clear = 0; + for (int32_t i = 0; i < 32; i++) { + if (!gl_state_check_texture_binding_2d(i) && !gl_state_check_texture_binding_cube_map(i)) + continue; + + gl_state_active_bind_texture_2d(i, 0); + gl_state_active_bind_texture_cube_map(i, 0); + gl_state_bind_sampler(i, 0); + } + gl_state_bind_framebuffer(0); gl_state_set_depth_mask(GL_TRUE); gl_state_set_stencil_mask(0xFF); @@ -805,229 +723,82 @@ static void render_draw() { gl_state_set_depth_mask(GL_FALSE); gl_state_bind_uniform_buffer_base(0, common_data_ubo); - for (int32_t i = 0; i < 32; i++) { - if (!gl_state_check_texture_binding_2d(i) && !gl_state_check_texture_binding_cube_map(i)) - continue; + glViewport(0, 0, internal_3d_res.x, internal_3d_res.y); - gl_state_active_texture(i); - gl_state_bind_texture_2d(0); - gl_state_bind_texture_cube_map(0); - gl_state_bind_sampler(i, 0); + render_texture_bind(&rctx->post_process.render_texture, 0); + gl_state_set_depth_mask(GL_TRUE); + glClearBufferfv(GL_COLOR, 0, color_clear); + glClearBufferfv(GL_DEPTH, 0, &depth_clear); + gl_state_set_depth_mask(GL_FALSE); + + if (set_clear_color) { + vec4 color; + *(vec3*)&color = back3d_color; + color.w = 1.0f; + glClearBufferfv(GL_COLOR, 0, (GLfloat*)&color); } - if (back_2d || front_3d || glitter_3d) { - glViewport(0, 0, internal_3d_res.x, internal_3d_res.y); + draw_pass_main(rctx); - if (back_2d) { - gl_state_bind_framebuffer(hfbo->back_2d.fbos[0]); - glClearBufferfv(GL_COLOR, 0, color_clear); - render_2d(); - } + int32_t screen_x_offset = (width - internal_2d_res.x) / 2 + (width - internal_2d_res.x) % 2; + int32_t screen_y_offset = (height - internal_2d_res.y) / 2 + (width - internal_2d_res.x) % 2; + glViewport(screen_x_offset, screen_y_offset, internal_2d_res.x, internal_2d_res.y); + render_texture_bind(&rctx->post_process.screen_texture, 0); + gl_state_bind_uniform_buffer_base(0, common_data_ubo); + classes_process_draw(classes, classes_count); - if (front_3d || glitter_3d) { - gl_state_bind_framebuffer(rfbo->tex.fbos[0]); - glDrawBuffers(1, fbo_render_attachments); - gl_state_set_depth_mask(GL_TRUE); - gl_state_set_stencil_mask(0xFF); - glClearBufferfi(GL_DEPTH_STENCIL, 0, depth_clear, stencil_clear); - gl_state_set_stencil_mask(0x00); - gl_state_set_depth_mask(GL_FALSE); + gl_state_bind_framebuffer(0); + render_texture_shader_set_glsl(0); + glViewport(0, 0, width, height); + if (rctx->draw_pass.enable[DRAW_PASS_POST_PROCESS]) + render_texture_draw(&rctx->post_process.screen_texture, false); - if (set_clear_color) { - vec4 color; - *(vec3*)&color = back3d_color; - color.w = 1.0f; - glClearBufferfv(GL_COLOR, 0, (GLfloat*)&color); - } - - if (grid_3d) - render_grid_3d(); - - if (front_3d) - render_3d(); - - if (glitter_3d) - render_glitter_3d(ALPHA_PASS_OPAQUE); - - if (glitter_3d) { - gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - render_glitter_3d(ALPHA_PASS_TRANSPARENT); - gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - - if (glitter_3d) { - gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - render_glitter_3d(ALPHA_PASS_TRANSLUCENT); - gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - - if (front_3d) - render_3d_translucent(); - - gl_state_bind_framebuffer(hfbo->color.fbos[0]); - gl_state_set_depth_mask(GL_TRUE); - glClearBufferfv(GL_COLOR, 0, color_clear); - glClearBufferfv(GL_DEPTH, 0, &depth_clear); - gl_state_set_depth_mask(GL_FALSE); - - fbo_render_draw(rfbo, true); - post_process_apply_dof(&pp_dof, &hfbo->color, dof); - } - - if (enable_post_process) - fbo_pp_draw(pfbo, tm, hfbo->color.color_texture, 0, hfbo->back_2d.color_texture, - hfbo, fbo_hdr_set_fbo_begin, fbo_hdr_set_fbo_end); - - if (sv_fxaa) - fbo_hdr_draw_fxaa(hfbo, sv_fxaa_preset); - - gl_state_bind_framebuffer(hfbo->color.fbos[0]); - gl_state_bind_uniform_buffer_base(0, common_data_ubo); - classes_process_draw(classes, classes_count); - - vec2i bb_offset; - bb_offset.x = (width - internal_2d_res.x) / 2; - bb_offset.y = (height - internal_2d_res.y) / 2; - - glViewport(bb_offset.x, bb_offset.y, internal_2d_res.x, internal_2d_res.y); - gl_state_bind_framebuffer(0); - shader_glsl_use(&ffbs); - gl_state_active_bind_texture_2d(0, hfbo->color.color_texture->texture); - gl_state_bind_vertex_array(fb_vao); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - } - - if (front_2d || ui) { - glViewport((width - internal_2d_res.x) / 2, (height - internal_2d_res.y) / 2, - internal_2d_res.x, internal_2d_res.y); - if (front_2d) - render_2d(); - if (ui) - render_2d(); - glViewport(0, 0, width, height); - } - - if (imgui) - render_imgui(); + if (draw_imgui) + render_imgui(rctx); } -static void render_dispose() { +static void render_dispose(render_context* rctx) { classes_process_dispose(classes, classes_count); - camera_dispose(cam); - dof_dispose(dof); - radius_dispose(rad); - intensity_dispose(inten); - tone_map_dispose(tm); - glitter_particle_manager_dispose(gpm); - - fbo_render_dispose(rfbo); - fbo_hdr_dispose(hfbo); - fbo_pp_dispose(pfbo); - - post_process_dof_free(&pp_dof); - - shader_free(&shaders_aft); - - shader_glsl_free(&cfbs[0]); - shader_glsl_free(&cfbs[1]); - - for (int32_t i = 0; i < 3; i++) - shader_glsl_free(&fxaas[i]); - - shader_glsl_free(&ffbs); - - shader_glsl_free(&dfbs[0]); - - for (int32_t i = 0; i < 2; i++) - for (int32_t j = 0; j < 4; j++) - shader_glsl_free(&dfbs[1 + i * 4 + j]); - - for (int32_t i = 0; i < 14; i++) - shader_glsl_free(&bfbs[i]); - - shader_glsl_free(&grid_shader); - - glDeleteBuffers(1, &common_data_ubo); - glDeleteBuffers(1, &grid_vbo); - glDeleteVertexArrays(1, &grid_vao); - glDeleteBuffers(1, &fb_vbo); - glDeleteVertexArrays(1, &fb_vao); - ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); igDestroyContext(imgui_context); lock_free(&imgui_context_lock); + + glitter_particle_manager_dispose(GPM_VAL); + + stage_free(&stage_test_data, rctx); + stage_free(&stage_stgtst, rctx); + + data_struct_free(); + + render_shaders_free(); + + shader_glsl_free(&grid_shader); + + glDeleteBuffers(1, &common_data_ubo); + glDeleteBuffers(1, &grid_vbo); + + rob_chara_data_array_free(); + + auth_3d_data_free(rctx); + light_param_storage_free(); + motion_storage_free(); + + render_texture_data_free(); + render_context_free(rctx); + + object_storage_free(); + texture_storage_free(); } -static void render_imgui() { +static void render_imgui(render_context* rctx) { lock_lock(&imgui_context_lock); igSetCurrentContext(imgui_context); ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData()); lock_unlock(&imgui_context_lock); } -static void render_2d() { -} - -static void render_3d() { -} - -static void render_3d_translucent() { -} - -static void render_grid_3d() { - glDrawBuffers(1, fbo_render_attachments); - - gl_state_enable_blend(); - gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gl_state_set_blend_equation(GL_FUNC_ADD); - gl_state_enable_depth_test(); - gl_state_set_depth_func(GL_LESS); - gl_state_set_depth_mask(GL_TRUE); - - shader_glsl_use(&grid_shader); - gl_state_bind_vertex_array(grid_vao); - glDrawArrays(GL_LINES, 0, grid_vertex_count); - shader_glsl_use(0); - - gl_state_disable_depth_test(); - gl_state_set_depth_mask(GL_FALSE); - gl_state_disable_blend(); -} - -static void render_glitter_3d(alpha_pass_type alpha) { - glitter_particle_manager_draw(GPM_VAL, alpha); -} - -inline static void render_get_aspect_correct_2d_res(vec2i* res) { - double_t width = (double_t)res->x; - double_t height = (double_t)res->y; - double_t view_aspect = width / height; - width = round(height * aspect); - height = round(width / aspect); - if (view_aspect < aspect) - width = round(height * aspect); - else if (view_aspect > aspect) - height = round(width / aspect); - res->x = (int32_t)width; - res->y = (int32_t)height; -} - -inline static void render_get_aspect_correct_3d_res(vec2i* res) { - double_t width = (double_t)res->x; - double_t height = (double_t)res->y; - double_t view_aspect = width / height; - width = round(height * aspect); - height = round(width / aspect); - if (view_aspect < aspect) - width = round(height * aspect); - else if (view_aspect > aspect) - height = round(width / aspect); - res->x = (int32_t)width; - res->y = (int32_t)height; -} - static void render_drop_glfw(GLFWwindow* window, int32_t count, char** paths) { if (!count || !paths) return; @@ -1037,34 +808,46 @@ static void render_drop_glfw(GLFWwindow* window, int32_t count, char** paths) { } static void render_resize_fb_glfw(GLFWwindow* window, int32_t w, int32_t h) { - bool change_fb = width != w || height != h; width = w; height = h; - render_resize_fb(change_fb); } -static void render_resize_fb(bool change_fb) { +static void render_resize_fb(render_context* rctx, bool change_fb) { if (internal_3d_res.x < 20) internal_3d_res.x = 20; if (internal_3d_res.y < 20) internal_3d_res.y = 20; - internal_2d_res.x = width; - internal_2d_res.y = height; - render_get_aspect_correct_2d_res(&internal_2d_res); - internal_2d_res.x = clamp(internal_2d_res.x, 1, sv_max_texture_size); - internal_2d_res.y = clamp(internal_2d_res.y, 1, sv_max_texture_size); + double_t res_width = (double_t)width; + double_t res_height = (double_t)height; + double_t view_aspect = res_width / res_height; + res_width = round(res_height * aspect); + res_height = round(res_width / aspect); + if (view_aspect < aspect) { + res_width = (double_t)width; + res_height = round(res_width / aspect); + } + else { + res_width = round(res_height * aspect); + res_height = round(res_width / aspect); + if (view_aspect > aspect) + res_height = round(res_width / aspect); + } - internal_3d_res.x = width; - internal_3d_res.y = height; - render_get_aspect_correct_3d_res(&internal_3d_res); - internal_3d_res.x = (int32_t)roundf((float_t)internal_3d_res.x * scale); - internal_3d_res.y = (int32_t)roundf((float_t)internal_3d_res.y * scale); + vec2i internal_res; + internal_res.x = (int32_t)res_width; + internal_res.y = (int32_t)res_height; + + internal_2d_res.x = clamp(internal_res.x, 1, sv_max_texture_size); + internal_2d_res.y = clamp(internal_res.y, 1, sv_max_texture_size); + internal_3d_res.x = (int32_t)roundf((float_t)internal_res.x * scale); + internal_3d_res.y = (int32_t)roundf((float_t)internal_res.y * scale); internal_3d_res.x = clamp(internal_3d_res.x, 1, sv_max_texture_size); internal_3d_res.y = clamp(internal_3d_res.y, 1, sv_max_texture_size); bool fb_changed = old_internal_2d_res.x != internal_2d_res.x || old_internal_2d_res.y != internal_2d_res.y || old_internal_3d_res.x != internal_3d_res.x - || old_internal_3d_res.y != internal_3d_res.y; + || old_internal_3d_res.y != internal_3d_res.y + || old_width != width || old_height != height; old_internal_2d_res = internal_2d_res; old_internal_3d_res = internal_3d_res; @@ -1073,42 +856,59 @@ static void render_resize_fb(bool change_fb) { st = state == RENDER_INITIALIZED; lock_unlock(&state_lock); - if (st && change_fb) { - fbo_render_resize(rfbo, &internal_3d_res); - fbo_hdr_resize(hfbo, &internal_3d_res); - fbo_pp_resize(pfbo, &internal_3d_res); - - post_process_dof_init_fbo(&pp_dof, internal_3d_res.x, internal_3d_res.y); + if (st && fb_changed && change_fb) { + post_process_init_fbo(&rctx->post_process, internal_3d_res.x, internal_3d_res.y, + internal_2d_res.x, internal_2d_res.y, width, height); + light_proj_resize(rctx->litproj, internal_3d_res.x, internal_3d_res.y); } - - st = false; - lock_lock(&state_lock); - st = state == RENDER_INITIALIZING || state == RENDER_INITIALIZED; - lock_unlock(&state_lock); } -static void render_imgui_context_menu(classes_struct* classes, const size_t classes_count) { +static void render_imgui_context_menu(classes_struct* classes, + const size_t classes_count, render_context* rctx) { for (size_t i = 0; i < classes_count; i++) { - if (!classes[i].enabled || !classes[i].name || ~classes[i].flags & CLASSES_IN_CONTEXT_MENU) + classes_struct* c = &classes[i]; + if (!c->name || ~c->flags & CLASSES_IN_CONTEXT_MENU) continue; - if (classes[i].sub_classes && classes[i].sub_classes_count) { - if (igBeginMenu(classes[i].name, *classes[i].enabled)) { - render_imgui_context_menu(classes[i].sub_classes, classes[i].sub_classes_count); + if (c->sub_classes && c->sub_classes_count) { + if (igBeginMenu(c->name, ~c->data.flags & CLASS_HIDDEN)) { + render_imgui_context_menu(c->sub_classes, + c->sub_classes_count, rctx); igEndMenu(); } } - else if (*classes[i].enabled) - igMenuItem_Bool(classes[i].name, 0, false, false); - else if (igMenuItem_Bool(classes[i].name, 0, false, true)) - if (classes[i].init) - classes[i].init(); + else if (~c->data.flags & CLASS_HIDDEN) + igMenuItem_Bool(c->name, 0, false, false); + else if (igMenuItem_Bool(c->name, 0, false, true)) { + if (~c->data.flags & CLASS_INIT) { + lock_init(&c->data.lock); + if (lock_check_init(&c->data.lock) && c->init) { + lock_lock(&c->data.lock); + if (c->init(&c->data, rctx)) + c->data.flags = CLASS_INIT; + else + c->data.flags = CLASS_DISPOSED | CLASS_HIDDEN; + lock_unlock(&c->data.lock); + } + } + + if (lock_check_init(&c->data.lock)) { + lock_lock(&c->data.lock); + if (c->data.flags & CLASS_INIT && ((c->show && c->show(&c->data)) || !c->show)) + c->data.flags &= ~(CLASS_HIDE | CLASS_HIDDEN); + lock_unlock(&c->data.lock); + } + } } } -static bool render_glitter_mesh_update(glitter_render_element* element, - glitter_particle_mesh* mesh_data, vec4* color, mat4* model, mat4* uv_mat) { - return true; +inline static void render_shaders_load() { + data_struct_load_file(&data_list[DATA_AFT], &shaders_ft, + "rom\\", "ft_shaders.farc", render_load_shaders); +} + +inline static void render_shaders_free() { + shader_free(&shaders_ft); } #if defined (DEBUG) && OPENGL_DEBUG @@ -1118,73 +918,73 @@ static void APIENTRY render_debug_output(GLenum source, GLenum type, uint32_t id return; printf("########################################\n"); - printf("Debug message (%d): %s\n", id, message); - - switch (source) { - case GL_DEBUG_SOURCE_API: - printf("Source: API"); - break; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM: - printf("Source: Window System"); - break; - case GL_DEBUG_SOURCE_SHADER_COMPILER: - printf("Source: Shader Compiler"); - break; - case GL_DEBUG_SOURCE_THIRD_PARTY: - printf("Source: Third Party"); - break; - case GL_DEBUG_SOURCE_APPLICATION: - printf("Source: Application"); - break; - case GL_DEBUG_SOURCE_OTHER: - printf("Source: Other"); - break; - } - switch (type) { case GL_DEBUG_TYPE_ERROR: - printf("Type: Error\n"); + printf("Type: Error; "); break; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - printf("Type: Deprecated Behaviour\n"); + printf("Type: Deprecated Behaviour; "); break; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - printf("Type: Undefined Behaviour\n"); + printf("Type: Undefined Behaviour; "); break; case GL_DEBUG_TYPE_PORTABILITY: - printf("Type: Portability\n"); + printf("Type: Portability; "); break; case GL_DEBUG_TYPE_PERFORMANCE: - printf("Type: Performance\n"); + printf("Type: Performance; "); break; case GL_DEBUG_TYPE_MARKER: - printf("Type: Marker\n"); + printf("Type: Marker; "); break; case GL_DEBUG_TYPE_PUSH_GROUP: - printf("Type: Push Group\n"); + printf("Type: Push Group; "); break; case GL_DEBUG_TYPE_POP_GROUP: - printf("Type: Pop Group\n"); + printf("Type: Pop Group; "); break; case GL_DEBUG_TYPE_OTHER: - printf("Type: Other\n"); + printf("Type: Other; "); break; } switch (severity) { case GL_DEBUG_SEVERITY_HIGH: - printf("Severity: high\n"); + printf("Severity: high; "); break; case GL_DEBUG_SEVERITY_MEDIUM: - printf("Severity: medium\n"); + printf("Severity: medium; "); break; case GL_DEBUG_SEVERITY_LOW: - printf("Severity: low\n"); + printf("Severity: low; "); break; case GL_DEBUG_SEVERITY_NOTIFICATION: - printf("Severity: notification\n"); + printf("Severity: notif; "); break; } + + switch (source) { + case GL_DEBUG_SOURCE_API: + printf("Source: API\n"); + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + printf("Source: Window System\n"); + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + printf("Source: Shader Compiler\n"); + break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + printf("Source: Third Party\n"); + break; + case GL_DEBUG_SOURCE_APPLICATION: + printf("Source: Application\n"); + break; + case GL_DEBUG_SOURCE_OTHER: + printf("Source: Other\n"); + break; + } + + printf("Debug message (%d): %s\n", id, message); printf("########################################\n\n"); } -#endif \ No newline at end of file +#endif diff --git a/src/CLOUD/shared.c b/src/CLOUD/shared.c index 013ad0db..9f00b96a 100644 --- a/src/CLOUD/shared.c +++ b/src/CLOUD/shared.c @@ -4,82 +4,119 @@ */ #include "shared.h" +#include "classes/data_test.h" +#include "classes/data_view.h" +#include "classes/glitter_editor.h" +#include "classes/graphics.h" +#include "classes/information.h" classes_struct classes[] = { -#if !defined(CLOUD_DEV) { .name = "Data Test", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &data_test_enabled, - .dispose = (void*)0, - .init = (void*)0, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)0, - .input = (void*)0, - .render = (void*)0, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = CLASSES_STRUCT_NO_FUNC, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = CLASSES_STRUCT_NO_FUNC, + .input = CLASSES_STRUCT_NO_FUNC, + .render = CLASSES_STRUCT_NO_FUNC, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = CLASSES_STRUCT_NO_FUNC, + .data = { + .lock = 0, + .flags = CLASS_INIT, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = data_test_classes, - .sub_classes_count = 1, + .sub_classes_count = 3, + }, + { + .name = "Data View", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = CLASSES_STRUCT_NO_FUNC, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = CLASSES_STRUCT_NO_FUNC, + .input = CLASSES_STRUCT_NO_FUNC, + .render = CLASSES_STRUCT_NO_FUNC, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = CLASSES_STRUCT_NO_FUNC, + .data = { + .lock = 0, + .flags = CLASS_INIT, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = data_view_classes, + .sub_classes_count = 2, }, -#endif { .name = "Graphics", .flags = CLASSES_IN_CONTEXT_MENU, - .enabled = &graphics_enabled, - .dispose = (void*)0, - .init = (void*)0, - .control = (void*)0, - .draw = (void*)0, - .drop = (void*)0, - .imgui = (void*)0, - .input = (void*)0, - .render = (void*)0, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, + .init = CLASSES_STRUCT_NO_FUNC, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = CLASSES_STRUCT_NO_FUNC, + .input = CLASSES_STRUCT_NO_FUNC, + .render = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = CLASSES_STRUCT_NO_FUNC, + .data = { + .lock = 0, + .flags = CLASS_INIT, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = graphics_classes, .sub_classes_count = 4, }, + { + .name = "Information", + .flags = CLASSES_IN_CONTEXT_MENU, + .init = CLASSES_STRUCT_NO_FUNC, + .draw = CLASSES_STRUCT_NO_FUNC, + .drop = CLASSES_STRUCT_NO_FUNC, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = CLASSES_STRUCT_NO_FUNC, + .input = CLASSES_STRUCT_NO_FUNC, + .render = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = CLASSES_STRUCT_NO_FUNC, + .data = { + .lock = 0, + .flags = CLASS_INIT, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, + .sub_classes = information_classes, + .sub_classes_count = 1, + }, #if defined(CLOUD_DEV) { .name = "Glitter Editor", - .flags = CLASSES_INIT_AT_STARTUP, - .enabled = &glitter_editor_enabled, - .dispose = (void*)glitter_editor_dispose, - .init = (void*)glitter_editor_init, - .control = (void*)0, - .draw = (void*)glitter_editor_draw, - .drop = (void*)glitter_editor_drop, - .imgui = (void*)glitter_editor_imgui, - .input = (void*)glitter_editor_input, - .render = (void*)glitter_editor_render, - .sound = (void*)0, - .video = (void*)0, - .lock = 0, - .sub_classes = 0, - .sub_classes_count = 0, - }, -#endif -#if defined(VIDEO) - { - .name = "Data Player", - .flags = 0, - .enabled = &data_player_enabled, - .dispose = (void*)data_player_dispose, - .init = (void*)data_player_init, - .control = (void*)0, - .draw = (void*)data_player_draw, - .drop = (void*)0, - .imgui = (void*)data_player_imgui, - .input = (void*)data_player_input, - .render = (void*)data_player_render, - .sound = (void*)0, - .video = (void*)data_player_video, - .lock = 0, + .flags = CLASSES_IN_CONTEXT_MENU, + .init = glitter_editor_init, + .draw = glitter_editor_draw, + .drop = glitter_editor_drop, + .hide = CLASSES_STRUCT_NO_FUNC, + .imgui = glitter_editor_imgui, + .input = glitter_editor_input, + .render = glitter_editor_render, + .show = CLASSES_STRUCT_NO_FUNC, + .sound = CLASSES_STRUCT_NO_FUNC, + .dispose = glitter_editor_dispose, + .data = { + .lock = 0, + .flags = CLASS_DISPOSED | CLASS_HIDDEN, + .imgui_focus = false, + .data = CLASS_DATA_NO_DATA, + }, .sub_classes = 0, .sub_classes_count = 0, }, @@ -90,3 +127,7 @@ const size_t classes_count = sizeof(classes) / sizeof(classes_struct); render_state state; lock state_lock; + +lock_data glitter_data_lock; +lock_data stage_data_lock; +lock pv_lock; diff --git a/src/CLOUD/shared.h b/src/CLOUD/shared.h index 355f513b..fde84597 100644 --- a/src/CLOUD/shared.h +++ b/src/CLOUD/shared.h @@ -8,10 +8,6 @@ #include "classes.h" #define CIMGUI_DEFINE_ENUMS_AND_STRUCTS #include -#include "classes/data_player.h" -#include "classes/data_test.h" -#include "classes/glitter_editor.h" -#include "classes/graphics.h" typedef enum render_state { RENDER_UNINITIALIZED = 0, @@ -25,3 +21,6 @@ extern classes_struct classes[]; extern const size_t classes_count; extern render_state state; extern lock state_lock; +extern lock_data glitter_data_lock; +extern lock_data stage_data_lock; +extern lock pv_lock; diff --git a/src/CLOUD/sound.c b/src/CLOUD/sound.c index e5057dbf..59d25013 100644 --- a/src/CLOUD/sound.c +++ b/src/CLOUD/sound.c @@ -5,6 +5,7 @@ #include "sound.h" #include "../CRE/timer.h" +#include timer sound_timer; @@ -12,6 +13,7 @@ extern bool close; int32_t sound_main(void* arg) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + timeBeginPeriod(1); timer_init(&sound_timer, 60.0); bool state_wait = false; @@ -19,18 +21,19 @@ int32_t sound_main(void* arg) { do { lock_lock(&state_lock); state_wait = state != RENDER_INITIALIZED; - state_disposed = state == RENDER_DISPOSING || state == RENDER_DISPOSED; + state_disposed = state == RENDER_DISPOSED; lock_unlock(&state_lock); if (state_disposed) goto End; - msleep(sound_timer.timer, 0.0625); + timer_sleep(&sound_timer, 0.0625); } while (state_wait); bool local_close = false; + timer_reset(&sound_timer); while (!close && !local_close) { timer_start_of_cycle(&sound_timer); lock_lock(&state_lock); - local_close = state == RENDER_DISPOSING || state == RENDER_DISPOSED; + local_close = state == RENDER_DISPOSED; lock_unlock(&state_lock); classes_process_sound(classes, classes_count); diff --git a/src/CLOUD/unedat.h b/src/CLOUD/unedat.h index 10d90d40..3a5b61ac 100644 --- a/src/CLOUD/unedat.h +++ b/src/CLOUD/unedat.h @@ -1,7 +1,7 @@ #pragma once #include "../KKdLib/default.h" -#include "../KKdLib/io_stream.h" +#include "../KKdLib/io/stream.h" #define SDAT_FLAG 0x01000000 #define EDAT_COMPRESSED_FLAG 0x00000001 diff --git a/src/CLOUD/video.c b/src/CLOUD/video.c deleted file mode 100644 index 85e85ddd..00000000 --- a/src/CLOUD/video.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "video.h" -#include "../CRE/timer.h" -#include "../CRE/video_x264.h" - -timer video_timer; - -extern bool close; -lock video_lock; - -int32_t video_main(void* arg) { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); - timer_init(&video_timer, 60.0); - - lock_init(&video_lock); - if (!lock_check_init(&video_lock)) - goto End; - - bool state_wait = false; - bool state_disposed = false; - do { - lock_lock(&state_lock); - state_wait = state != RENDER_INITIALIZED; - state_disposed = state == RENDER_DISPOSING || state == RENDER_DISPOSED; - lock_unlock(&state_lock); - if (state_disposed) { - lock_free(&video_lock); - goto End; - } - msleep(video_timer.timer, 0.0625); - } while (state_wait); - - //data_player_init(); - - bool local_close = false; - while (!close && !local_close) { - timer_start_of_cycle(&video_timer); - lock_lock(&state_lock); - local_close = state == RENDER_DISPOSING || state == RENDER_DISPOSED; - lock_unlock(&state_lock); - - classes_process_video(classes, classes_count); - timer_end_of_cycle(&video_timer); - } - lock_free(&video_lock); -End: - timer_dispose(&video_timer); - return 0; -} diff --git a/src/CRE/Glitter/curve.c b/src/CRE/Glitter/curve.c index ad636e96..6d6ef3c0 100644 --- a/src/CRE/Glitter/curve.c +++ b/src/CRE/Glitter/curve.c @@ -4,8 +4,8 @@ */ #include "curve.h" -#include "random.h" #include "../../KKdLib/interpolation.h" +#include "random.h" static const float_t glitter_curve_baked_reverse_bias[] = { 0.00001f, @@ -96,7 +96,7 @@ void glitter_curve_recalculate(GLT, glitter_curve* curve) { vector_glitter_curve_key keys_rev = curve->keys_rev; vector_glitter_curve_key* keys = &curve->keys; - vector_glitter_curve_key_clear(keys); + vector_glitter_curve_key_clear(keys, 0); if (keys_rev.end - keys_rev.begin == 1) vector_glitter_curve_key_push_back(keys, &keys_rev.begin[0]); else if (keys_rev.end - keys_rev.begin > 1) { @@ -215,16 +215,16 @@ bool glitter_curve_unparse_file(GLT, f2_struct* st, glitter_curve* c) { glitter_curve_key_pack_file(GLT_VAL, &s, c, &c->keys); vector_f2_struct_push_back(&st->sub_structs, &s); #if defined(CRE_DEV) - vector_glitter_curve_key_free(&c->keys); + vector_glitter_curve_key_free(&c->keys, 0); #endif c->keys = keys; return true; } void glitter_curve_dispose(glitter_curve* c) { - vector_glitter_curve_key_free(&c->keys); + vector_glitter_curve_key_free(&c->keys, 0); #if defined(CRE_DEV) - vector_glitter_curve_key_free(&c->keys_rev); + vector_glitter_curve_key_free(&c->keys_rev, 0); #endif free(c); } diff --git a/src/CRE/Glitter/curve_get_value.c b/src/CRE/Glitter/curve_get_value.c index 1bac1ed8..ff417277 100644 --- a/src/CRE/Glitter/curve_get_value.c +++ b/src/CRE/Glitter/curve_get_value.c @@ -178,7 +178,7 @@ static float_t glitter_curve_randomize(GLT, c->flags & GLITTER_CURVE_RANDOM_RANGE_NEGATE ? -c->random_range : 0.0f, c->random_range); if (c->flags & GLITTER_CURVE_RANDOM_RANGE_MULT) - if (GLT_VAL != GLITTER_AFT) + if (GLT_VAL != GLITTER_FT) rand *= value * 0.01f; else rand *= value; diff --git a/src/CRE/Glitter/diva_resource.c b/src/CRE/Glitter/diva_resource.c index d8f319c0..6ee00442 100644 --- a/src/CRE/Glitter/diva_resource.c +++ b/src/CRE/Glitter/diva_resource.c @@ -7,7 +7,7 @@ #include "effect_group.h" #include "texture.h" -bool glitter_diva_resource_parse_file(glitter_effect_group* a1, f2_struct* st) { +bool glitter_diva_resource_parse_file(GPM, glitter_effect_group* a1, f2_struct* st) { f2_struct* i; if (!st || !st->header.data_size) @@ -18,7 +18,7 @@ bool glitter_diva_resource_parse_file(glitter_effect_group* a1, f2_struct* st) { continue; if (i->header.signature == reverse_endianness_uint32_t('TXPC')) { - glitter_texture_resource_unpack_file(a1, i); + glitter_texture_resource_unpack_file(GPM_VAL, a1, i); break; } } diff --git a/src/CRE/Glitter/diva_resource.h b/src/CRE/Glitter/diva_resource.h index bcd5c14f..d8a5d2b2 100644 --- a/src/CRE/Glitter/diva_resource.h +++ b/src/CRE/Glitter/diva_resource.h @@ -7,5 +7,5 @@ #include "glitter.h" -extern bool glitter_diva_resource_parse_file(glitter_effect_group* a1, f2_struct* st); +extern bool glitter_diva_resource_parse_file(GPM, glitter_effect_group* a1, f2_struct* st); extern bool glitter_diva_resource_unparse_file(glitter_effect_group* a1, f2_struct* st); diff --git a/src/CRE/Glitter/effect.c b/src/CRE/Glitter/effect.c index 887b0c71..a7aea692 100644 --- a/src/CRE/Glitter/effect.c +++ b/src/CRE/Glitter/effect.c @@ -7,10 +7,13 @@ #include "animation.h" #include "emitter.h" +static object_info glitter_effect_ext_anim_get_object_info(uint64_t hash); static bool glitter_effect_pack_file(GLT, f2_struct* st, glitter_effect* a3); static bool glitter_effect_unpack_file(GLT, void* data, glitter_effect* a3, bool use_big_endian); +extern object_database* obj_db_ptr; + glitter_effect* glitter_effect_init(GLT) { glitter_effect* e = force_malloc(sizeof(glitter_effect)); e->version = GLT_VAL == GLITTER_X ? 0x0C : 0x07; @@ -18,7 +21,7 @@ glitter_effect* glitter_effect_init(GLT) { e->data.start_time = 0; e->data.ext_anim = 0; e->data.flags = 0; - e->data.name_hash = GLT_VAL != GLITTER_AFT ? hash_murmurhash_empty : hash_fnv1a64_empty; + e->data.name_hash = GLT_VAL != GLITTER_FT ? hash_murmurhash_empty : hash_fnv1a64m_empty; e->data.seed = 0; return e; } @@ -104,6 +107,16 @@ void glitter_effect_dispose(glitter_effect* e) { free(e); } +static object_info glitter_effect_ext_anim_get_object_info(uint64_t hash) { + vector_object_set_info* object_set = &obj_db_ptr->object_set; + for (object_set_info* i = object_set->begin; i != object_set->end; i++) { + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (hash == j->name_hash_murmurhash || hash == j->name_hash_fnv1a64m_upper) + return (object_info) { j->id, i->id }; + } + return object_info_null; +} + static bool glitter_effect_pack_file(GLT, f2_struct* st, glitter_effect* a2) { size_t l; size_t d; @@ -172,8 +185,8 @@ static bool glitter_effect_pack_file(GLT, f2_struct* st, glitter_effect* a2) { if (a2->data.flags & GLITTER_EFFECT_EMISSION) flags |= GLITTER_EFFECT_FILE_EMISSION; - *(uint64_t*)d = GLT_VAL != GLITTER_AFT - ? hash_utf8_murmurhash(a2->name, 0, false) : hash_utf8_fnv1a64(a2->name);; + *(uint64_t*)d = GLT_VAL != GLITTER_FT + ? hash_utf8_murmurhash(a2->name, 0, false) : hash_utf8_fnv1a64m(a2->name);; *(int32_t*)(d + 8) = a2->data.appear_time; *(int32_t*)(d + 12) = a2->data.life_time; *(int32_t*)(d + 16) = a2->data.start_time; @@ -337,7 +350,7 @@ static bool glitter_effect_unpack_file(GLT, ext_anim->instance_id = 0; ext_anim->file_name_hash = hash_murmurhash_empty; - ext_anim->object = (object_info){ 0xFFFF, 0xFFFF }; + ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); ext_anim->node_index = 18; if (*(uint8_t*)(d + 12)) { strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 20), 0x80); @@ -362,7 +375,7 @@ static bool glitter_effect_unpack_file(GLT, ext_anim->instance_id = 0; ext_anim->file_name_hash = hash_murmurhash_empty; - ext_anim->object = (object_info){ 0xFFFF, 0xFFFF }; + ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); ext_anim->node_index = 18; if (*(uint8_t*)(d + 16)) { strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 16), 0x80); @@ -389,7 +402,7 @@ static bool glitter_effect_unpack_file(GLT, ext_anim->file_name_hash = *(uint64_t*)(d + 16); } - ext_anim->object = (object_info){ 0xFFFF, 0xFFFF }; + ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); ext_anim->node_index = 18; if (*(uint8_t*)(d + 32)) { strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 32), 0x80); @@ -406,7 +419,7 @@ static bool glitter_effect_unpack_file(GLT, a2->data.start_time = 0; a2->data.ext_anim = 0; a2->data.flags = 0; - a2->data.name_hash = GLT_VAL != GLITTER_AFT ? hash_murmurhash_empty : hash_fnv1a64_empty; + a2->data.name_hash = GLT_VAL != GLITTER_FT ? hash_murmurhash_empty : hash_fnv1a64m_empty; a2->data.seed = 0; if (a2->version != 6 && a2->version != 7) @@ -492,7 +505,6 @@ static bool glitter_effect_unpack_file(GLT, ext_anim = force_malloc(sizeof(glitter_effect_ext_anim)); a2->data.ext_anim = ext_anim; if (ext_anim) { - ext_anim->object = (object_info){ 0xFFFF, 0xFFFF }; if (use_big_endian) { ext_anim->object_hash = load_reverse_endianness_uint64_t((void*)d); ext_anim->flags = load_reverse_endianness_int32_t((void*)(d + 8)); @@ -502,6 +514,7 @@ static bool glitter_effect_unpack_file(GLT, ext_anim->flags = *(int32_t*)(d + 8); } + ext_anim->object = glitter_effect_ext_anim_get_object_info(ext_anim->object_hash); ext_anim->node_index = 18; if (*(uint8_t*)(d + 12)) { strncpy_s(ext_anim->mesh_name, 0x80, (uint8_t*)(d + 12), 0x80); @@ -512,5 +525,7 @@ static bool glitter_effect_unpack_file(GLT, } } } + + snprintf(a2->name, sizeof(a2->name), "eff_%08x", (uint32_t)a2->data.name_hash); return true; } diff --git a/src/CRE/Glitter/effect_group.c b/src/CRE/Glitter/effect_group.c index 1b71de83..6385bf64 100644 --- a/src/CRE/Glitter/effect_group.c +++ b/src/CRE/Glitter/effect_group.c @@ -4,6 +4,16 @@ */ #include "effect_group.h" +#include "../../KKdLib/database/object.h" +#include "../../KKdLib/database/texture.h" +#include "../../KKdLib/io/path.h" +#include "../../KKdLib/obj.h" +#include "../../KKdLib/farc.h" +#include "../../KKdLib/obj.h" +#include "../../KKdLib/str_utils.h" +#include "../data.h" +#include "../object.h" +#include "../texture.h" #include "effect.h" #include "scene.h" #include "texture.h" @@ -12,54 +22,128 @@ glitter_effect_group* glitter_effect_group_init(GLT) { glitter_effect_group* eg = force_malloc(sizeof(glitter_effect_group)); eg->emission = 1.0f; eg->version = GLT_VAL == GLITTER_X ? 0x0C : 0x09; +#if defined(CRE_DEV) + eg->object_set_ids = vector_empty(uint32_t); +#endif return eg; } -bool glitter_effect_group_parse_file(glitter_effect_group* a1, f2_struct* st) { +bool glitter_effect_group_parse_file(glitter_effect_group* eg, f2_struct* st) { for (f2_struct* i = st->sub_structs.begin; i != st->sub_structs.end; i++) { if (!i->header.data_size) continue; if (i->header.signature == reverse_endianness_uint32_t('EFCT') - && !glitter_effect_parse_file(a1, i, &a1->effects)) + && !glitter_effect_parse_file(eg, i, &eg->effects)) return false; else if (i->header.signature == reverse_endianness_uint32_t('DVRS') - && !glitter_texture_hashes_unpack_file(a1, i)) + && !glitter_texture_hashes_unpack_file(eg, i)) return false; } return true; } -bool glitter_effect_group_unparse_file(GLT, glitter_effect_group* a1, f2_struct* st) { +bool glitter_effect_group_unparse_file(GLT, glitter_effect_group* eg, f2_struct* st) { memset(st, 0, sizeof(f2_struct)); - for (glitter_effect** i = a1->effects.begin; i != a1->effects.end; i++) { + for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { if (!*i) continue; f2_struct s; memset(&s, 0, sizeof(f2_struct)); - if (glitter_effect_unparse_file(GLT_VAL, a1, &s, *i)) + if (glitter_effect_unparse_file(GLT_VAL, eg, &s, *i)) vector_f2_struct_push_back(&st->sub_structs, &s); } f2_struct s; memset(&s, 0, sizeof(f2_struct)); - if (glitter_texture_hashes_pack_file(a1, &s)) + if (glitter_texture_hashes_pack_file(eg, &s)) vector_f2_struct_push_back(&st->sub_structs, &s); st->header.signature = reverse_endianness_uint32_t('DVEF'); st->header.length = 0x20; st->header.use_big_endian = false; st->header.use_section_size = true; - st->header.version = a1->version; + st->header.version = eg->version; return true; } +#if defined(CRE_DEV) +bool glitter_effect_group_check_model(glitter_effect_group* eg) { + if (eg->type != GLITTER_X) + return false; + + bool has_model = false; + vector_uint32_t* object_set_ids = &eg->object_set_ids; + for (glitter_effect** i = eg->effects.begin; i != eg->effects.end; i++) { + if (!*i) + continue; + + glitter_effect* efct = *i; + for (glitter_emitter** j = efct->emitters.begin; j != efct->emitters.end; j++) { + if (!*j) + continue; + + glitter_emitter* emit = *j; + for (glitter_particle** k = emit->particles.begin; k != emit->particles.end; k++) { + if (!*k) + continue; + + glitter_particle* ptcl = *k; + if (ptcl->data.type != GLITTER_PARTICLE_MESH) + continue; + + has_model = true; + uint32_t object_set_hash = (uint32_t)ptcl->data.mesh.object_set_name_hash; + bool found = false; + for (uint32_t* l = object_set_ids->begin; l != object_set_ids->end; l++) + if (*l == object_set_hash) { + found = true; + break; + } + + if (!found) + vector_uint32_t_push_back(object_set_ids, &object_set_hash); + } + } + } + return has_model; +} + +void glitter_effect_group_load_model(glitter_effect_group* eg, void* ds) { + if (eg->type != GLITTER_X) + return; + + vector_uint32_t* object_set_ids = &eg->object_set_ids; + if (!(object_set_ids->end - object_set_ids->begin)) + return; + + for (uint32_t* i = object_set_ids->begin; i != object_set_ids->end; i++) { + object_database obj_db; + texture_database tex_db; + object_database_init(&obj_db); + texture_database_init(&tex_db); + object_set_load_by_hash(ds, &obj_db, &tex_db, *i); + object_database_free(&obj_db); + texture_database_free(&tex_db); + } +} + +void glitter_effect_group_free_model(glitter_effect_group* eg) { + for (uint32_t* i = eg->object_set_ids.begin; i != eg->object_set_ids.end; i++) + object_storage_delete_object_set(*i); + vector_uint32_t_free(&eg->object_set_ids, 0); +} +#endif + void glitter_effect_group_dispose(glitter_effect_group* eg) { vector_ptr_glitter_effect_free(&eg->effects, glitter_effect_dispose); - vector_uint64_t_free(&eg->resource_hashes); + vector_uint64_t_free(&eg->resource_hashes, 0); glitter_texture_unload(eg); - tex_set_free(&eg->resources_tex); + txp_set_free(&eg->resources_tex); +#if defined(CRE_DEV) + glitter_effect_group_free_model(eg); +#endif free(eg); } diff --git a/src/CRE/Glitter/effect_group.h b/src/CRE/Glitter/effect_group.h index 149515c2..ed97585c 100644 --- a/src/CRE/Glitter/effect_group.h +++ b/src/CRE/Glitter/effect_group.h @@ -8,6 +8,11 @@ #include "glitter.h" extern glitter_effect_group* glitter_effect_group_init(GLT); -extern bool glitter_effect_group_parse_file(glitter_effect_group* a1, f2_struct* st); -extern bool glitter_effect_group_unparse_file(GLT, glitter_effect_group* a1, f2_struct* st); +extern bool glitter_effect_group_parse_file(glitter_effect_group* eg, f2_struct* st); +extern bool glitter_effect_group_unparse_file(GLT, glitter_effect_group* eg, f2_struct* st); +#if defined(CRE_DEV) || defined(CLOUD_DEV) +extern bool glitter_effect_group_check_model(glitter_effect_group* eg); +extern void glitter_effect_group_load_model(glitter_effect_group* eg, void* ds); +extern void glitter_effect_group_free_model(glitter_effect_group* eg); +#endif extern void glitter_effect_group_dispose(glitter_effect_group* eg); diff --git a/src/CRE/Glitter/effect_inst.c b/src/CRE/Glitter/effect_inst.c index 40ecbccd..0040d342 100644 --- a/src/CRE/Glitter/effect_inst.c +++ b/src/CRE/Glitter/effect_inst.c @@ -9,8 +9,10 @@ #include "emitter_inst.h" #include "random.h" #include "render_scene.h" +#include "../auth_3d.h" +#include "../rob.h" -static void glitter_effect_inst_get_ext_anim(GLT, glitter_effect_inst* a1); +static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1); static int32_t glitter_effect_inst_get_ext_anim_bone_index( glitter_effect_ext_anim_chara_node index); static void glitter_effect_inst_get_value(GLT, glitter_effect_inst* a1); @@ -26,7 +28,7 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, glitter_effect_inst* ei = force_malloc(sizeof(glitter_effect_inst)); ei->effect = a1; ei->data = a1->data; - ei->color = vec4_identity; + ei->color = vec4u_identity; ei->scale_all = 1.0f; ei->id = id; ei->translation = a1->translation; @@ -42,8 +44,8 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, if (~a1->data.flags & GLITTER_EFFECT_LOCAL && ei->data.ext_anim) { inst_ext_anim = force_malloc(sizeof(glitter_effect_inst_ext_anim)); inst_ext_anim->a3da_id = -1; - inst_ext_anim->object_hash = GLT_VAL != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + inst_ext_anim->object_hash = GLT_VAL != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; inst_ext_anim->chara_index = -1; inst_ext_anim->mesh_index = -1; inst_ext_anim->mat = mat4_identity; @@ -57,12 +59,12 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, ei->flags |= GLITTER_EFFECT_INST_EXT_ANIM_TRANS_ONLY; if (ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_CHARA_ANIM) { - inst_ext_anim->object = ext_anim->object; inst_ext_anim->bone_index = glitter_effect_inst_get_ext_anim_bone_index(ext_anim->node_index); ei->flags |= GLITTER_EFFECT_INST_CHARA_ANIM; } else { + inst_ext_anim->object = ext_anim->object; inst_ext_anim->object_hash = ext_anim->object_hash; inst_ext_anim->file_name_hash = ext_anim->file_name_hash; inst_ext_anim->instance_id = ext_anim->instance_id; @@ -83,7 +85,7 @@ glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, } glitter_random_set_value(ei->random_ptr, - GLT_VAL == GLITTER_AFT ? (uint32_t)ei->data.name_hash : 0); + GLT_VAL == GLITTER_FT ? (uint32_t)ei->data.name_hash : 0); ei->random = glitter_random_get_value(ei->random_ptr); ei->mat = mat4_identity; @@ -104,12 +106,12 @@ void glitter_effect_inst_calc_draw(GPM, glitter_effect_inst* a1) { glitter_render_scene_calc_draw(GPM_VAL, &a1->render_scene); } -void glitter_effect_inst_draw(GPM, glitter_effect_inst* a1, alpha_pass_type alpha) { +void glitter_effect_inst_draw(GPM, glitter_effect_inst* a1, draw_pass_3d_type alpha) { glitter_render_scene_draw(GPM_VAL, &a1->render_scene, alpha); } -alpha_pass_type glitter_effect_inst_get_alpha(glitter_effect_inst* a1) { - return a1->data.flags & GLITTER_EFFECT_ALPHA ? ALPHA_PASS_TRANSPARENT : ALPHA_PASS_TRANSLUCENT; +draw_pass_3d_type glitter_effect_inst_get_alpha(glitter_effect_inst* a1) { + return a1->data.flags & GLITTER_EFFECT_ALPHA ? DRAW_PASS_3D_TRANSPARENT : DRAW_PASS_3D_TRANSLUCENT; } size_t glitter_effect_inst_get_ctrl_count(glitter_effect_inst* a1, glitter_particle_type type) { @@ -122,11 +124,11 @@ size_t glitter_effect_inst_get_disp_count(glitter_effect_inst* a1, glitter_parti fog_type glitter_effect_inst_get_fog(glitter_effect_inst* a1) { if (a1->data.flags & GLITTER_EFFECT_FOG) - return FOG_NORMAL; + return FOG_DEPTH; else if (a1->data.flags & GLITTER_EFFECT_FOG_HEIGHT) return FOG_HEIGHT; else - return FOG_NONE; + return -1; } bool glitter_effect_inst_has_ended(glitter_effect_inst* effect, bool a2) { @@ -163,7 +165,7 @@ void glitter_effect_inst_update(GPM, GLT, vec3 rot; vec3 scale; - glitter_effect_inst_get_ext_anim(GLT_VAL, effect); + glitter_effect_inst_get_ext_anim(effect); glitter_effect_inst_get_value(GLT_VAL, effect); if (effect->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS && effect->ext_anim) { vec3_add(effect->translation, effect->ext_anim->translation, trans); @@ -212,14 +214,7 @@ void glitter_effect_inst_dispose(glitter_effect_inst* ei) { free(ei); } -static void glitter_effect_inst_get_ext_anim(GLT, glitter_effect_inst* a1) { - glitter_effect_ext_anim* ext_anim; - glitter_effect_inst_ext_anim* inst_ext_anim; - vec3 scale; - mat4 temp; - mat4* mat; - vec3* trans; - +static void glitter_effect_inst_get_ext_anim(glitter_effect_inst* a1) { if (!a1->ext_anim || !a1->data.ext_anim) return; @@ -228,109 +223,139 @@ static void glitter_effect_inst_get_ext_anim(GLT, glitter_effect_inst* a1) { && a1->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS)) return; - ext_anim = a1->data.ext_anim; - inst_ext_anim = a1->ext_anim; - mat = 0; - trans = 0; + glitter_effect_inst_ext_anim* inst_ext_anim = a1->ext_anim; if (a1->flags & GLITTER_EFFECT_INST_CHARA_ANIM) { - if (inst_ext_anim->chara_index < 0 - || inst_ext_anim->chara_index > (GLT_VAL == GLITTER_AFT ? 5 : 2)) + rob_chara_data* rob_chr_data = rob_chara_data_array_get(inst_ext_anim->chara_index); + if (!rob_chr_data) return; + mat4 mat = mat4_identity/*chara root mat*/; - temp = mat4_identity/*chara root mat*/; - mat4_get_scale((mat4*)&mat4_identity/*chara root mat*/, &scale); + vec3 scale; + mat4_get_scale(&mat, &scale); vec3_sub_scalar(scale, 1.0f, a1->ext_anim_scale); a1->ext_anim_scale.z = 0.0f; a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_SCALE; - if (inst_ext_anim->bone_index >= 0) - mat4_mult(&temp, (mat4*)&mat4_identity/*chara node mat*/, &temp); - - mat = &temp; - goto SetMat; - } - else if (a1->flags & GLITTER_EFFECT_INST_FLAG_GET_EXT_ANIM_MAT) { - if (inst_ext_anim->a3da_id == -1) { - inst_ext_anim->a3da_id = -1;/*try get a3da id*/ - //fun(inst_ext_anim->object_hash, - // &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc) - inst_ext_anim->mesh_index = -1; - - if (inst_ext_anim->a3da_id > -1) - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; + int32_t bone_index = inst_ext_anim->bone_index; + if (bone_index == -1) { + if (a1->flags & GLITTER_EFFECT_INST_EXT_ANIM_TRANS_ONLY) { + inst_ext_anim->mat = mat4_identity; + mat4_get_translation(&mat, &inst_ext_anim->translation); + } + else + inst_ext_anim->mat = mat; } else { - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; - if (!mat) { - inst_ext_anim->a3da_id = -1;/*try get a3da id*/ - //fun(inst_ext_anim->object_hash, - // &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc) - if (inst_ext_anim->a3da_id != -1) - mat = (mat4*)&mat4_identity/*try get obj a3da mat*/; - } - } - - if (!mat) - return; - - mat4_get_scale(mat, &scale); - vec3_sub_scalar(scale, 1.0f, a1->ext_anim_scale); - a1->ext_anim_scale.z = 0.0f; - a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_SCALE; - - if (!inst_ext_anim->mesh_name) - goto SetMat; - - if (inst_ext_anim->mesh_index < 0) - inst_ext_anim->mesh_index = -1/*try get mesh index*/; - - if (inst_ext_anim->mesh_index > -1) { - trans = (vec3*)&vec3_null/*try get mesh bounding sphere center*/; - if (trans) { - inst_ext_anim->mat = *mat; - inst_ext_anim->translation = *trans; - goto SetFlags; + mat4* bone_mat = rob_chara_data_get_bone_data_mat(rob_chr_data, bone_index); + if (!bone_mat) + return; + + mat4_mult(bone_mat, &mat, &mat); + if (a1->flags & GLITTER_EFFECT_INST_EXT_ANIM_TRANS_ONLY) { + inst_ext_anim->mat = mat4_identity; + mat4_get_translation(&mat, &inst_ext_anim->translation); } + else + inst_ext_anim->mat = mat; + } + goto SetFlags; } - else if (inst_ext_anim->object_hash != (GLT_VAL != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty)) { + + if (~a1->flags & GLITTER_EFFECT_INST_FLAG_GET_EXT_ANIM_MAT) { if (inst_ext_anim->mesh_index < 0) { if (!inst_ext_anim->mesh_name) return; - inst_ext_anim->mesh_index = -1/*try get mesh index*/; + inst_ext_anim->mesh_index = object_storage_get_object_mesh_index( + inst_ext_anim->object, inst_ext_anim->mesh_name); } + int32_t v46 = inst_ext_anim->mesh_index; + if (v46 >= 0) { + object_mesh* mesh = object_storage_get_object_mesh_by_index(inst_ext_anim->object, v46); + if (mesh) { + inst_ext_anim->translation = mesh->bounding_sphere.center; + goto SetFlags; + } + } + return; + } + + mat4* obj_mat = 0; + mat4 temp; + if (inst_ext_anim->a3da_id != -1) + obj_mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, + inst_ext_anim->a3da_index, inst_ext_anim->object_is_hrc, &temp); + + if (!obj_mat) { + inst_ext_anim->a3da_id = auth_3d_data_get_auth_3d_id_by_object_info(inst_ext_anim->object, + &inst_ext_anim->a3da_index, &inst_ext_anim->object_is_hrc); + if (inst_ext_anim->a3da_id == -1) + return; + + inst_ext_anim->mesh_index = -1; + obj_mat = auth_3d_data_struct_get_auth_3d_object_mat(inst_ext_anim->a3da_id, + inst_ext_anim->a3da_index, inst_ext_anim->object_is_hrc, &temp); + if (!obj_mat) + return; + } + + mat4 mat = mat4_identity; + int32_t chara_id = -1;// auth_3d_data_get_chara_id(inst_ext_anim->a3da_id); + if (chara_id >= 0 && chara_id <= 5) { + rob_chara_data* rob_chr_data = rob_chara_data_array_get(chara_id); + if (rob_chr_data) { + mat = mat4_identity/*chara root mat*/; + + vec3 scale; + mat4_get_scale(&mat, &scale); + vec3_sub_scalar(scale, 1.0f, a1->ext_anim_scale); + a1->ext_anim_scale.z = 0.0f; + a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_SCALE; + } + } + + if (inst_ext_anim->mesh_name) { + if (inst_ext_anim->mesh_index < 0) + inst_ext_anim->mesh_index = object_storage_get_object_mesh_index( + inst_ext_anim->object, inst_ext_anim->mesh_name); + if (inst_ext_anim->mesh_index >= 0) { - trans = (vec3*)&vec3_null/*try get mesh bounding sphere center*/; - if (trans) { - inst_ext_anim->translation = *trans; + object_mesh* mesh = object_storage_get_object_mesh_by_index( + inst_ext_anim->object, inst_ext_anim->mesh_index); + if (mesh) { + mat4_mult(obj_mat, &mat, &mat); + inst_ext_anim->mat = mat; + inst_ext_anim->translation = mesh->bounding_sphere.center; goto SetFlags; } } } - return; - -SetMat: - if (mat) + else { + mat4_mult(obj_mat, &mat, &mat); if (a1->flags & GLITTER_EFFECT_INST_EXT_ANIM_TRANS_ONLY) { inst_ext_anim->mat = mat4_identity; - mat4_get_translation(mat, &inst_ext_anim->translation); + mat4_get_translation(&mat, &inst_ext_anim->translation); } else - inst_ext_anim->mat = *mat; + inst_ext_anim->mat = mat; + goto SetFlags; + } + return; SetFlags: - a1->flags &= ~GLITTER_EFFECT_INST_HAS_EXT_ANIM_NON_INIT; - a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS; + if (a1->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_NON_INIT) { + a1->flags &= ~GLITTER_EFFECT_INST_HAS_EXT_ANIM_NON_INIT; + a1->flags |= GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS; + } } static int32_t glitter_effect_inst_get_ext_anim_bone_index( glitter_effect_ext_anim_chara_node node) { - if (node < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) + /*if (node < GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD || node > GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE) return -1; const char* bone_names[] = { @@ -354,8 +379,48 @@ static int32_t glitter_effect_inst_get_ext_anim_bone_index( [GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE] = "kl_toe_r_wj" }; - // find bone index - return -1; + return -1;*/ + + switch (node) { + case GLITTER_EFFECT_EXT_ANIM_CHARA_HEAD: + return 0x0F; + case GLITTER_EFFECT_EXT_ANIM_CHARA_MOUTH: + return 0x36; + case GLITTER_EFFECT_EXT_ANIM_CHARA_BELLY: + return 0x00; + case GLITTER_EFFECT_EXT_ANIM_CHARA_CHEST: + return 0x07; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_SHOULDER: + return 0x6A; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_ELBOW: + return 0x6C; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_ELBOW_DUP: + return 0x6D; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_HAND: + return 0x7B; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_SHOULDER: + return 0x8E; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_ELBOW: + return 0x90; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_ELBOW_DUP: + return 0x91; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_HAND: + return 0x9F; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_THIGH: + return 0xC2; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_KNEE: + return 0xB8; + case GLITTER_EFFECT_EXT_ANIM_CHARA_LEFT_TOE: + return 0xB7; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_THIGH: + return 0xC5; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_KNEE: + return 0xBF; + case GLITTER_EFFECT_EXT_ANIM_CHARA_RIGHT_TOE: + return 0xBE; + default: + return -1; + } } static void glitter_effect_inst_get_value(GLT, glitter_effect_inst* a1) { diff --git a/src/CRE/Glitter/effect_inst.h b/src/CRE/Glitter/effect_inst.h index ed66e9b4..663e84ee 100644 --- a/src/CRE/Glitter/effect_inst.h +++ b/src/CRE/Glitter/effect_inst.h @@ -10,8 +10,8 @@ extern glitter_effect_inst* glitter_effect_inst_init(GPM, GLT, glitter_effect* a1, size_t id, float_t emission, bool appear_now); extern void glitter_effect_inst_calc_draw(GPM, glitter_effect_inst* a1); -extern void glitter_effect_inst_draw(GPM, glitter_effect_inst* a1, alpha_pass_type alpha); -extern alpha_pass_type glitter_effect_inst_get_alpha(glitter_effect_inst* a1); +extern void glitter_effect_inst_draw(GPM, glitter_effect_inst* a1, draw_pass_3d_type alpha); +extern draw_pass_3d_type glitter_effect_inst_get_alpha(glitter_effect_inst* a1); extern size_t glitter_effect_inst_get_ctrl_count(glitter_effect_inst* a1, glitter_particle_type type); extern size_t glitter_effect_inst_get_disp_count(glitter_effect_inst* a1, glitter_particle_type type); extern fog_type glitter_effect_inst_get_fog(glitter_effect_inst* a1); diff --git a/src/CRE/Glitter/emitter_inst.c b/src/CRE/Glitter/emitter_inst.c index d7224981..0a753c39 100644 --- a/src/CRE/Glitter/emitter_inst.c +++ b/src/CRE/Glitter/emitter_inst.c @@ -308,7 +308,7 @@ static void glitter_emitter_inst_update_mat(GPM, GLT, case GLITTER_DIRECTION_Z_AXIS: mat4_rotate_z((float_t)-M_PI_2, &dir_mat); break; - case GLITTER_DIRECTION_BILLBOARD_Y_ONLY: + case GLITTER_DIRECTION_BILLBOARD_Y_AXIS: mat4_rotate_y(GPM_VAL->cam_rotation_y, &dir_mat); break; default: diff --git a/src/CRE/Glitter/file_reader.c b/src/CRE/Glitter/file_reader.c index e4166662..2dfeac48 100644 --- a/src/CRE/Glitter/file_reader.c +++ b/src/CRE/Glitter/file_reader.c @@ -10,6 +10,7 @@ #include "effect_group.h" #include "particle_manager.h" #include "scene.h" +#include "../../KKdLib/io/path.h" #include "../../KKdLib/farc.h" #include "../../KKdLib/str_utils.h" @@ -20,9 +21,9 @@ glitter_file_reader* glitter_file_reader_init(GLT, fr->file = str_utils_copy(file); fr->emission = emission; fr->type = GLT_VAL; - fr->hash = GLT_VAL != GLITTER_AFT + fr->hash = GLT_VAL != GLITTER_FT ? hash_utf8_murmurhash(fr->file, 0, false) - : hash_utf8_fnv1a64(fr->file); + : hash_utf8_fnv1a64m(fr->file); return fr; } @@ -33,26 +34,27 @@ glitter_file_reader* glitter_file_reader_winit(GLT, fr->file = utf16_to_utf8(file); fr->emission = emission; fr->type = GLT_VAL; - fr->hash = GLT_VAL != GLITTER_AFT + fr->hash = GLT_VAL != GLITTER_FT ? hash_utf8_murmurhash(fr->file, 0, false) - : hash_utf8_fnv1a64(fr->file); + : hash_utf8_fnv1a64m(fr->file); return fr; } -bool glitter_file_reader_read(glitter_file_reader* fr, float_t emission) { - farc* f = farc_init(); +bool glitter_file_reader_read(GPM, glitter_file_reader* fr, float_t emission) { + farc f; + farc_init(&f); char* file_temp; char* path_temp; file_temp = str_utils_add(fr->file, ".farc"); path_temp = str_utils_add(fr->path, file_temp); free(file_temp); - farc_read(f, path_temp, true, false); + farc_read(&f, path_temp, true, false); free(path_temp); farc_file* ff; bool ret = false; file_temp = str_utils_add(fr->file, ".dve"); - ff = farc_read_file(f, file_temp); + ff = farc_read_file(&f, file_temp); free(file_temp); if (!ff) goto End; @@ -69,19 +71,19 @@ bool glitter_file_reader_read(glitter_file_reader* fr, float_t emission) { goto End; file_temp = str_utils_add(fr->file, ".drs"); - ff = farc_read_file(f, file_temp); + ff = farc_read_file(&f, file_temp); free(file_temp); if (ff) { f2_struct st; f2_struct_mread(&st, ff->data, ff->size); if (st.header.signature == reverse_endianness_uint32_t('DVRS')) - glitter_diva_resource_parse_file(fr->effect_group, &st); + glitter_diva_resource_parse_file(GPM_VAL, fr->effect_group, &st); f2_struct_free(&st); } file_temp = str_utils_add(fr->file, ".lst"); - ff = farc_read_file(f, file_temp); + ff = farc_read_file(&f, file_temp); free(file_temp); if (ff) { @@ -93,7 +95,7 @@ bool glitter_file_reader_read(glitter_file_reader* fr, float_t emission) { } End: - farc_dispose(f); + farc_free(&f); return ret; } diff --git a/src/CRE/Glitter/file_reader.h b/src/CRE/Glitter/file_reader.h index 43598e7b..a17923e1 100644 --- a/src/CRE/Glitter/file_reader.h +++ b/src/CRE/Glitter/file_reader.h @@ -11,5 +11,5 @@ extern glitter_file_reader* glitter_file_reader_init(GLT, char* path, char* file, float_t emission); extern glitter_file_reader* glitter_file_reader_winit(GLT, wchar_t* path, wchar_t* file, float_t emission); -extern bool glitter_file_reader_read(glitter_file_reader* fr, float_t emission); +extern bool glitter_file_reader_read(GPM, glitter_file_reader* fr, float_t emission); extern void glitter_file_reader_dispose(glitter_file_reader* fr); diff --git a/src/CRE/Glitter/glitter.c b/src/CRE/Glitter/glitter.c index 30f6da84..0f1e5d5a 100644 --- a/src/CRE/Glitter/glitter.c +++ b/src/CRE/Glitter/glitter.c @@ -19,9 +19,6 @@ vector_ptr_func(glitter_render_group) vector_func(glitter_scene_effect) vector_ptr_func(glitter_scene) -bool(* glitter_render_mesh_update_func)(glitter_render_element*, - glitter_particle_mesh*, vec4*, mat4*, mat4*); - const float_t glitter_min_emission = 0.01f; const glitter_curve_type_flags glitter_effect_curve_flags = 0 @@ -58,7 +55,7 @@ const glitter_curve_type_flags glitter_particle_x_curve_flags = 0 const glitter_direction glitter_emitter_direction_types[] = { [GLITTER_EMITTER_DIRECTION_BILLBOARD] = GLITTER_DIRECTION_BILLBOARD, - [GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_ONLY] = GLITTER_DIRECTION_BILLBOARD_Y_ONLY, + [GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_AXIS] = GLITTER_DIRECTION_BILLBOARD_Y_AXIS, [GLITTER_EMITTER_DIRECTION_X_AXIS] = GLITTER_DIRECTION_X_AXIS, [GLITTER_EMITTER_DIRECTION_Y_AXIS] = GLITTER_DIRECTION_Y_AXIS, [GLITTER_EMITTER_DIRECTION_Z_AXIS] = GLITTER_DIRECTION_Z_AXIS, @@ -75,7 +72,7 @@ const glitter_emitter_direction glitter_emitter_direction_default = const glitter_direction glitter_particle_draw_types[] = { [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD] = GLITTER_DIRECTION_BILLBOARD, - [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_ONLY] = GLITTER_DIRECTION_BILLBOARD_Y_ONLY, + [GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_AXIS] = GLITTER_DIRECTION_BILLBOARD_Y_AXIS, [GLITTER_PARTICLE_DRAW_TYPE_X_AXIS] = GLITTER_DIRECTION_X_AXIS, [GLITTER_PARTICLE_DRAW_TYPE_Y_AXIS] = GLITTER_DIRECTION_Y_AXIS, [GLITTER_PARTICLE_DRAW_TYPE_Z_AXIS] = GLITTER_DIRECTION_Z_AXIS, @@ -134,3 +131,5 @@ const glitter_pivot glitter_pivot_reverse[] = { [GLITTER_PIVOT_BOTTOM_CENTER] = GLITTER_PIVOT_TOP_CENTER, [GLITTER_PIVOT_BOTTOM_RIGHT] = GLITTER_PIVOT_TOP_LEFT, }; + +GPM; diff --git a/src/CRE/Glitter/glitter.h b/src/CRE/Glitter/glitter.h index f4086f42..416e79b8 100644 --- a/src/CRE/Glitter/glitter.h +++ b/src/CRE/Glitter/glitter.h @@ -102,7 +102,7 @@ typedef enum glitter_direction { GLITTER_DIRECTION_Y_AXIS = 4, GLITTER_DIRECTION_X_AXIS = 5, GLITTER_DIRECTION_Z_AXIS = 6, - GLITTER_DIRECTION_BILLBOARD_Y_ONLY = 7, + GLITTER_DIRECTION_BILLBOARD_Y_AXIS = 7, GLITTER_DIRECTION_PREV_POSITION_DUP = 8, GLITTER_DIRECTION_EMITTER_ROTATION = 9, GLITTER_DIRECTION_EFFECT_ROTATION = 10, @@ -185,7 +185,7 @@ typedef enum glitter_effect_inst_flag { typedef enum glitter_emitter_direction { GLITTER_EMITTER_DIRECTION_BILLBOARD = 0, - GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_ONLY = 1, + GLITTER_EMITTER_DIRECTION_BILLBOARD_Y_AXIS = 1, GLITTER_EMITTER_DIRECTION_Y_AXIS = 2, GLITTER_EMITTER_DIRECTION_X_AXIS = 3, GLITTER_EMITTER_DIRECTION_Z_AXIS = 4, @@ -265,7 +265,7 @@ typedef enum glitter_particle_draw_flag { typedef enum glitter_particle_draw_type { GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD = 0, - GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_ONLY = 1, + GLITTER_PARTICLE_DRAW_TYPE_BILLBOARD_Y_AXIS = 1, GLITTER_PARTICLE_DRAW_TYPE_X_AXIS = 2, GLITTER_PARTICLE_DRAW_TYPE_Y_AXIS = 3, GLITTER_PARTICLE_DRAW_TYPE_Z_AXIS = 4, @@ -293,8 +293,8 @@ typedef enum glitter_particle_flag { } glitter_particle_flag; typedef enum glitter_particle_inst_flag { - GLITTER_PARTICLE_INST_NONE = 0x00, - GLITTER_PARTICLE_INST_ENDED = 0x01, + GLITTER_PARTICLE_INST_NONE = 0x00, + GLITTER_PARTICLE_INST_ENDED = 0x01, GLITTER_PARTICLE_INST_NO_CHILD = 0x02, } glitter_particle_inst_flag; @@ -324,9 +324,9 @@ typedef enum glitter_pivot { } glitter_pivot; typedef enum glitter_type { - GLITTER_AFT = 0, - GLITTER_F2 = 1, - GLITTER_X = 2, + GLITTER_FT = 0, + GLITTER_F2 = 1, + GLITTER_X = 2, } glitter_type; typedef enum glitter_uv_index_type { @@ -394,9 +394,6 @@ vector_ptr(glitter_scene) typedef vector_ptr_glitter_curve glitter_animation; typedef vector_ptr_glitter_render_group glitter_render_scene; -extern bool(* glitter_render_mesh_update_func)(glitter_render_element*, - glitter_particle_mesh*, vec4*, mat4*, mat4*); - extern const float_t glitter_min_emission; extern const glitter_curve_type_flags glitter_effect_curve_flags; extern const glitter_curve_type_flags glitter_emitter_curve_flags; @@ -428,8 +425,7 @@ struct glitter_random { struct glitter_buffer { vec3 position; vec2 uv; - vec3 color; - float_t alpha; + vec4u color; }; struct glitter_curve_key { @@ -498,7 +494,10 @@ struct glitter_effect_group { uint32_t resources_count; vector_uint64_t resource_hashes; vector_txp resources_tex; - vector_ptr_texture resources; + texture** resources; +#if defined(CRE_DEV) || defined(CLOUD_DEV) + vector_uint32_t object_set_ids; +#endif bool scene_init; bool buffer_init; uint32_t version; @@ -530,7 +529,7 @@ struct glitter_effect_inst { glitter_effect_data data; float_t frame0; float_t frame1; - vec4 color; + vec4u color; vec3 translation; vec3 rotation; vec3 scale; @@ -650,8 +649,11 @@ struct glitter_particle_manager { glitter_effect_inst* effect; glitter_emitter_inst* emitter; glitter_particle_inst* particle; - float_t delta_frame; + void* rctx; float_t emission; + float_t delta_frame; + uint32_t texture_counter; + glitter_random random; uint32_t counter; mat4 cam_projection; mat4 cam_view; @@ -659,11 +661,10 @@ struct glitter_particle_manager { mat3 cam_inv_view_mat3; vec3 cam_view_point; float_t cam_rotation_y; - glitter_random random; bool draw_all; bool draw_all_mesh; - bool updated; bool draw_selected; + bool no_draw; }; struct glitter_locus_history { @@ -671,7 +672,7 @@ struct glitter_locus_history { }; struct glitter_locus_history_data { - vec4 color; + vec4u color; vec3 translation; float_t scale; }; @@ -679,8 +680,8 @@ struct glitter_locus_history_data { struct glitter_particle_mesh { uint64_t object_name_hash; uint64_t object_set_name_hash; - char mesh_name[64]; - uint64_t sub_mesh_hash; + //char mesh_name[64]; // Unused + //uint64_t sub_mesh_hash; // Unused }; struct glitter_particle_data { @@ -713,7 +714,7 @@ struct glitter_particle_data { float_t reflection_coeff; float_t reflection_coeff_random; float_t rebound_plane_y; - vec4 color; + vec4u color; glitter_uv_index_type uv_index_type; int32_t uv_index; int32_t frame_step_uv; @@ -782,7 +783,7 @@ struct glitter_render_element { float_t speed; float_t deceleration; vec2 uv; - vec4 color; + vec4u color; vec3 base_translation; vec3 base_direction; vec3 translation; @@ -799,6 +800,7 @@ struct glitter_render_element { float_t fade_out_frames; float_t fade_in_frames; mat4 mat; + mat4 mat_draw; glitter_locus_history* locus_history; uint32_t random; uint8_t step; @@ -826,20 +828,17 @@ struct glitter_render_group { mat4 mat_rot; mat4 mat_draw; glitter_render_element* elements; - glitter_buffer* buffer; size_t max_count; glitter_particle_inst* particle; glitter_random* random_ptr; - alpha_pass_type alpha; + draw_pass_3d_type alpha; fog_type fog; - int32_t vao; int32_t vbo; int32_t ebo; float_t emission; vector_int32_t vec_key; vector_int32_t vec_val; bool use_culling; - bool update_data; }; struct glitter_scene_effect { @@ -856,3 +855,5 @@ struct glitter_scene { float_t delta_frame_history; bool skip; }; + +extern GPM; diff --git a/src/CRE/Glitter/list.c b/src/CRE/Glitter/list.c index 916d36a8..499777ef 100644 --- a/src/CRE/Glitter/list.c +++ b/src/CRE/Glitter/list.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "texture.h" +#include "list.h" bool glitter_list_pack_file(glitter_effect_group* a1, f2_struct* st) { size_t data; diff --git a/src/CRE/Glitter/locus_history.c b/src/CRE/Glitter/locus_history.c index 6e1a2236..b7e12d16 100644 --- a/src/CRE/Glitter/locus_history.c +++ b/src/CRE/Glitter/locus_history.c @@ -56,6 +56,6 @@ void glitter_locus_history_append(glitter_locus_history* a1, } void glitter_locus_history_dispose(glitter_locus_history* lh) { - vector_glitter_locus_history_data_free(&lh->data); + vector_glitter_locus_history_data_free(&lh->data, 0); free(lh); } diff --git a/src/CRE/Glitter/particle.c b/src/CRE/Glitter/particle.c index a81ad70d..1e10b5d3 100644 --- a/src/CRE/Glitter/particle.c +++ b/src/CRE/Glitter/particle.c @@ -18,7 +18,7 @@ glitter_particle* glitter_particle_init(GLT) { p->data.pivot = GLITTER_PIVOT_MIDDLE_CENTER; p->data.scale = vec3_identity; p->data.reflection_coeff = 1.0f; - p->data.color = vec4_identity; + p->data.color = vec4u_identity; p->data.uv_index = 0; p->data.uv_index_start = 0; p->data.uv_index_end = 1; @@ -30,10 +30,17 @@ glitter_particle* glitter_particle_init(GLT) { p->data.sub_flags = GLITTER_PARTICLE_SUB_USE_CURVE; p->data.blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; p->data.mask_blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; - p->data.tex_hash = GLT_VAL != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; - p->data.mask_tex_hash = GLT_VAL != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + p->data.tex_hash = GLT_VAL != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; + p->data.mask_tex_hash = GLT_VAL != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; + + if (GLT_VAL == GLITTER_X) { + p->data.mesh.object_set_name_hash = hash_murmurhash_empty; + p->data.mesh.object_name_hash = hash_murmurhash_empty; + //p->data.mesh.mesh_name[0] = 0; + //p->data.mesh.sub_mesh_hash = hash_murmurhash_empty; + } return p; } @@ -294,8 +301,8 @@ static bool glitter_particle_unpack_file(GLT, glitter_effect_group* a1, if (GLT_VAL == GLITTER_X) { a3->data.mesh.object_set_name_hash = hash_murmurhash_empty; a3->data.mesh.object_name_hash = hash_murmurhash_empty; - a3->data.mesh.mesh_name[0] = 0; - a3->data.mesh.sub_mesh_hash = hash_murmurhash_empty; + //a3->data.mesh.mesh_name[0] = 0; + //a3->data.mesh.sub_mesh_hash = hash_murmurhash_empty; d = (size_t)data; if (use_big_endian) { @@ -462,11 +469,11 @@ static bool glitter_particle_unpack_file(GLT, glitter_effect_group* a1, a3->data.mesh.object_name_hash = *(uint64_t*)d; a3->data.mesh.object_set_name_hash = *(uint64_t*)(d + 8); } - memcpy(a3->data.mesh.mesh_name, (void*)(d + 16), 0x40); - if (use_big_endian) + //memcpy(a3->data.mesh.mesh_name, (void*)(d + 16), 0x40); + /*if (use_big_endian) a3->data.mesh.sub_mesh_hash = load_reverse_endianness_uint64_t((void*)(d + 80)); else - a3->data.mesh.sub_mesh_hash = *(uint64_t*)(d + 80); + a3->data.mesh.sub_mesh_hash = *(uint64_t*)(d + 80);*/ d += 88; has_tex = false; } @@ -722,8 +729,8 @@ static bool glitter_particle_unpack_file(GLT, glitter_effect_group* a1, mask_blend_mode = *(int32_t*)(d + 8); } else { - mask_tex_hash = GLT_VAL != GLITTER_AFT - ? hash_murmurhash_empty : hash_fnv1a64_empty; + mask_tex_hash = GLT_VAL != GLITTER_FT + ? hash_murmurhash_empty : hash_fnv1a64m_empty; mask_blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; } } @@ -749,7 +756,11 @@ static bool glitter_particle_unpack_file(GLT, glitter_effect_group* a1, a3->data.unk1 = unk1; vec2_rcp(a3->data.split_uv, a3->data.split_uv); - vec4_mult_scalar(a3->data.color, (float_t)(1.0 / 255.0), a3->data.color); + + vec4 color; + vec4u_to_vec4(a3->data.color, color); + vec4_mult_scalar(color, (float_t)(1.0 / 255.0), color); + vec4_to_vec4u(color, a3->data.color); uv_max_count = (int32_t)(split_u * split_v); if (uv_max_count) diff --git a/src/CRE/Glitter/particle_inst.c b/src/CRE/Glitter/particle_inst.c index 646747d6..a23b1bad 100644 --- a/src/CRE/Glitter/particle_inst.c +++ b/src/CRE/Glitter/particle_inst.c @@ -30,7 +30,7 @@ glitter_particle_inst* glitter_particle_inst_init(glitter_particle* a1, rg->fog = glitter_effect_inst_get_fog(a2); if (pi->data.data.type == GLITTER_PARTICLE_QUAD && pi->data.data.blend_mode == GLITTER_PARTICLE_BLEND_PUNCH_THROUGH) - rg->alpha = ALPHA_PASS_OPAQUE; + rg->alpha = DRAW_PASS_3D_OPAQUE; if (pi->data.data.draw_flags & GLITTER_PARTICLE_DRAW_NO_BILLBOARD_CULL) rg->use_culling = false; @@ -150,7 +150,7 @@ static glitter_particle_inst* glitter_particle_inst_init_child(glitter_particle_ rg->fog = glitter_effect_inst_get_fog(effect); if (pi->data.data.blend_mode == GLITTER_PARTICLE_BLEND_PUNCH_THROUGH && pi->data.data.type == GLITTER_PARTICLE_QUAD) - rg->alpha = ALPHA_PASS_OPAQUE; + rg->alpha = DRAW_PASS_3D_OPAQUE; if (effect->data.emission >= glitter_min_emission) rg->emission = effect->data.emission; else diff --git a/src/CRE/Glitter/particle_manager.c b/src/CRE/Glitter/particle_manager.c index 9cee26ec..b7e9f8d1 100644 --- a/src/CRE/Glitter/particle_manager.c +++ b/src/CRE/Glitter/particle_manager.c @@ -4,12 +4,12 @@ */ #include "particle_manager.h" +#include "../GlitterX/effect_inst_x.h" #include "effect_group.h" #include "effect_inst.h" #include "file_reader.h" #include "render_group.h" #include "scene.h" -#include "../GlitterX/effect_inst_x.h" glitter_particle_manager* glitter_particle_manager_init() { glitter_particle_manager* gpm = force_malloc(sizeof(glitter_particle_manager)); @@ -93,7 +93,10 @@ bool glitter_particle_manager_check_scene(GPM, uint64_t effect_group_hash) { return i != GPM_VAL->scenes.end; } -void glitter_particle_manager_draw(GPM, alpha_pass_type alpha) { +void glitter_particle_manager_draw(GPM, draw_pass_3d_type alpha) { + if (GPM_VAL->no_draw) + return; + glitter_scene** i; glitter_scene* scene; glitter_scene_effect* j; @@ -294,14 +297,11 @@ void glitter_particle_manager_set_frame(GPM, glitter_effect_group* effect_group, glitter_scene** scene, float_t curr_frame, float_t prev_frame, uint32_t counter, glitter_random* random, bool reset) { if (curr_frame < prev_frame || reset) { - for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end; ) { - if (*i != *scene) { - i++; - continue; + for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end; i++) + if (*i == *scene) { + vector_ptr_glitter_scene_erase(&GPM_VAL->scenes, i - GPM_VAL->scenes.begin, glitter_scene_dispose); + break; } - - vector_ptr_glitter_scene_erase(&GPM_VAL->scenes, i - GPM_VAL->scenes.begin, glitter_scene_dispose); - } GPM_VAL->counter = counter; GPM_VAL->random = *random; @@ -411,7 +411,7 @@ void glitter_particle_manager_update_file_reader(GPM) { for (glitter_file_reader** i = GPM_VAL->file_readers.begin; i != GPM_VAL->file_readers.end;) { if (*i) { glitter_file_reader* file_reader = *i; - if (glitter_file_reader_read(file_reader, GPM_VAL->emission)) { + if (glitter_file_reader_read(GPM_VAL, file_reader, GPM_VAL->emission)) { file_reader->effect_group->emission = file_reader->emission; if (file_reader->emission <= 0.0) file_reader->effect_group->emission = GPM_VAL->emission; @@ -425,8 +425,8 @@ void glitter_particle_manager_update_file_reader(GPM) { } } -void glitter_particle_manager_update_scene(GPM) { - GPM_VAL->delta_frame = get_frame_speed(); +void glitter_particle_manager_update_scene(GPM, float_t delta_frame) { + GPM_VAL->delta_frame = delta_frame; for (glitter_scene** i = GPM_VAL->scenes.begin; i != GPM_VAL->scenes.end;) { glitter_scene* scene = *i; if (scene && !glitter_scene_has_ended(scene, true)) { diff --git a/src/CRE/Glitter/particle_manager.h b/src/CRE/Glitter/particle_manager.h index 8d98a031..d5eebd36 100644 --- a/src/CRE/Glitter/particle_manager.h +++ b/src/CRE/Glitter/particle_manager.h @@ -12,7 +12,7 @@ extern void glitter_particle_manager_calc_draw(GPM); extern bool glitter_particle_manager_check_effect_group(GPM, uint64_t effect_group_hash); extern bool glitter_particle_manager_check_file_reader(GPM, uint64_t effect_group_hash); extern bool glitter_particle_manager_check_scene(GPM, uint64_t effect_group_hash); -extern void glitter_particle_manager_draw(GPM, alpha_pass_type alpha); +extern void glitter_particle_manager_draw(GPM, draw_pass_3d_type alpha); extern bool glitter_particle_manager_free_effect_group(GPM, uint64_t effect_group_hash); extern void glitter_particle_manager_free_effect_groups(GPM); extern bool glitter_particle_manager_free_scene(GPM, uint64_t effect_group_hash); @@ -30,5 +30,5 @@ extern bool glitter_particle_manager_test_load_effect(GPM, uint64_t effect_group_hash, uint64_t effect_hash); extern bool glitter_particle_manager_test_load_scene(GPM, uint64_t effect_group_hash, bool appear_now); extern void glitter_particle_manager_update_file_reader(GPM); -extern void glitter_particle_manager_update_scene(GPM); +extern void glitter_particle_manager_update_scene(GPM, float_t delta_frame); extern void glitter_particle_manager_dispose(GPM); diff --git a/src/CRE/Glitter/random.c b/src/CRE/Glitter/random.c index 65223972..e2078c50 100644 --- a/src/CRE/Glitter/random.c +++ b/src/CRE/Glitter/random.c @@ -1114,7 +1114,7 @@ float_t glitter_random_get_float(GLT, glitter_random* random, float_t value) { switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: val = *(float_t*)&glitter_full_float_table[random->value % 0x1000]; break; case GLITTER_F2: @@ -1130,7 +1130,7 @@ float_t glitter_random_get_float_min_max(GLT, glitter_random* random, float_t mi switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: value = *(float_t*)&glitter_full_float_table[random->value % 0x1000]; break; case GLITTER_F2: @@ -1147,7 +1147,7 @@ void glitter_random_get_vec3(GLT, glitter_random* random, vec3* src, vec3* dst) switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: val.x = *(float_t*)&glitter_full_float_table[random->value % 0x1000]; random->value++; val.y = *(float_t*)&glitter_full_float_table[random->value % 0x1000]; @@ -1174,7 +1174,7 @@ int32_t glitter_random_get_int(GLT, glitter_random* random, int32_t value) { int32_t val; switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: val = glitter_full_int_table[random->value % 0x1000]; break; case GLITTER_F2: @@ -1193,7 +1193,7 @@ int32_t glitter_random_get_int_min_max(GLT, glitter_random* random, int32_t min, switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: value = glitter_full_int_table[random->value % 0x1000]; break; case GLITTER_F2: @@ -1207,7 +1207,7 @@ int32_t glitter_random_get_int_min_max(GLT, glitter_random* random, int32_t min, int32_t glitter_random_get_max(GLT) { switch (GLT_VAL) { default: - case GLITTER_AFT: + case GLITTER_FT: return 0x1000; case GLITTER_F2: return 0x100; diff --git a/src/CRE/Glitter/render_element.c b/src/CRE/Glitter/render_element.c index cce7bb7b..a77a9484 100644 --- a/src/CRE/Glitter/render_element.c +++ b/src/CRE/Glitter/render_element.c @@ -216,7 +216,7 @@ void glitter_render_element_update(GLT, particle->data.data.uv_scroll_add_scale * delta_frame, uv_scroll); vec2_add(a2->uv_scroll, uv_scroll, a2->uv_scroll); glitter_render_element_step_uv(GLT_VAL, particle, a2, delta_frame, a1->random_ptr); - a2->color = (vec4){ -1.0f, -1.0f, -1.0f, -1.0f }; + a2->color = (vec4u){ -1.0f, -1.0f, -1.0f, -1.0f }; a2->draw = true; if (particle->data.data.sub_flags & GLITTER_PARTICLE_SUB_USE_CURVE) { diff --git a/src/CRE/Glitter/render_group.c b/src/CRE/Glitter/render_group.c index e75f8268..47adea6d 100644 --- a/src/CRE/Glitter/render_group.c +++ b/src/CRE/Glitter/render_group.c @@ -4,17 +4,15 @@ */ #include "emitter_inst.h" +#include "../gl_state.h" +#include "../shader.h" +#include "../shader_ft.h" +#include "../static_var.h" #include "random.h" #include "render_group.h" #include "render_element.h" -#include "../gl_state.h" -#include "../shader.h" -#include "../shader_aft.h" -#include "../static_var.h" #include -extern shader_set_data shaders_aft; - static glitter_render_element* glitter_render_group_add_render_element(glitter_render_group* a1, glitter_render_element* a2); static void glitter_render_group_calc_draw_line(glitter_render_group* a1); @@ -59,13 +57,11 @@ glitter_render_group* glitter_render_group_init(glitter_particle_inst* a1) { rg->mat_draw = mat4_identity; rg->max_count = max_count; rg->particle = a1; - rg->alpha = ALPHA_PASS_TRANSLUCENT; + rg->alpha = DRAW_PASS_3D_TRANSLUCENT; rg->emission = 1.0f; rg->blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; rg->mask_blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; rg->random_ptr = a1->data.random_ptr; - rg->buffer = 0; - rg->vao = 0; rg->vbo = 0; rg->ebo = 0; rg->vec_key = vector_empty(int32_t); @@ -82,12 +78,10 @@ glitter_render_group* glitter_render_group_init(glitter_particle_inst* a1) { bool is_quad = a1->data.data.type == GLITTER_PARTICLE_QUAD; - rg->buffer = force_malloc_s(glitter_buffer, rg->max_count); - if (!rg->buffer) - rg->max_count = 0; - - glGenVertexArrays(1, &rg->vao); glGenBuffers(1, &rg->vbo); + gl_state_bind_array_buffer(rg->vbo); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * rg->max_count), 0, GL_DYNAMIC_DRAW); + gl_state_bind_array_buffer(rg->vbo); if (is_quad) { size_t count = rg->max_count / 4 * 6; @@ -100,41 +94,20 @@ glitter_render_group* glitter_render_group_init(glitter_particle_inst* a1) { ebo_data[i + 4] = (int32_t)(j + 2); ebo_data[i + 5] = (int32_t)(j + 3); } + glGenBuffers(1, &rg->ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->ebo); + gl_state_bind_element_array_buffer(rg->ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int32_t) * count, ebo_data, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + gl_state_bind_element_array_buffer(0); free(ebo_data); } static const GLsizei buffer_size = sizeof(glitter_buffer); - gl_state_bind_vertex_array(rg->vao); - if (is_quad) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->ebo); - glBindBuffer(GL_ARRAY_BUFFER, rg->vbo); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, position)); // Pos - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, color)); // Color - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, uv)); // TexCoord0 - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, uv)); // TexCoord1 - gl_state_bind_vertex_array(0); - if (is_quad) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - if (!is_quad) { vector_int32_t_reserve(&rg->vec_key, rg->count); vector_int32_t_reserve(&rg->vec_val, rg->count); } - rg->update_data = true; return rg; } @@ -143,15 +116,11 @@ void glitter_render_group_calc_draw(GPM, glitter_render_group* a1) { case GLITTER_PARTICLE_QUAD: case GLITTER_PARTICLE_LINE: case GLITTER_PARTICLE_LOCUS: - if (!a1->update_data && !GPM_VAL->updated) - return; break; default: - a1->update_data = false; return; } - a1->update_data = false; a1->disp = 0; switch (a1->type) { case GLITTER_PARTICLE_QUAD: @@ -197,12 +166,6 @@ void glitter_render_group_delete_buffers(glitter_render_group* a1, bool a2) { a1->vbo = 0; } - if (a1->vao) { - glDeleteVertexArrays(1, &a1->vao); - a1->vao = 0; - } - free(a1->buffer); - if (!a2 && a1->elements) { glitter_render_group_free(a1); free(a1->elements); @@ -261,11 +224,10 @@ void glitter_render_group_draw(GPM, glitter_render_group* a1) { switch (a1->type) { case GLITTER_PARTICLE_QUAD: switch (a1->fog) { - case FOG_NONE: default: uniform_value[U_FOG_HEIGHT] = 0; break; - case FOG_NORMAL: + case FOG_DEPTH: uniform_value[U_FOG_HEIGHT] = 1; break; case FOG_HEIGHT: @@ -280,7 +242,7 @@ void glitter_render_group_draw(GPM, glitter_render_group* a1) { gl_state_set_depth_mask(GL_TRUE); } else { - uniform_value[U_ALPHA_BLEND] = a1->alpha != ALPHA_PASS_OPAQUE ? 2 : 0; + uniform_value[U_ALPHA_BLEND] = a1->alpha != DRAW_PASS_3D_OPAQUE ? 2 : 0; gl_state_enable_depth_test(); gl_state_set_depth_func(GL_LESS); gl_state_set_depth_mask(GL_FALSE); @@ -314,36 +276,80 @@ void glitter_render_group_draw(GPM, glitter_render_group* a1) { break; } - vec4 emission; + float_t emission = 1.0f; if (a1->flags & GLITTER_PARTICLE_EMISSION || a1->blend_mode == GLITTER_PARTICLE_BLEND_TYPICAL) - emission = (vec4){ a1->emission, a1->emission, a1->emission, 1.0f }; - else - emission = vec4_identity; + emission = a1->emission; - shader_state_material_set_emission(&shaders_aft, false, &emission); - shader_state_matrix_set_mvp_separate(&shaders_aft, + shader_state_material_set_emission(&shaders_ft, false, emission, emission, emission, 1.0f); + shader_state_matrix_set_mvp_separate(&shaders_ft, &a1->mat_draw, &GPM_VAL->cam_view, &GPM_VAL->cam_projection); - shader_state_matrix_set_texture(&shaders_aft, 0, (mat4*)&mat4_identity); - shader_state_matrix_set_texture(&shaders_aft, 1, (mat4*)&mat4_identity); - shader_env_vert_set_ptr(&shaders_aft, 3, (vec4*)&vec4_identity); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity); + shader_env_vert_set_ptr(&shaders_ft, 3, (vec4*)&vec4_identity); - shader_set(&shaders_aft, SHADER_AFT_GLITTER_PT); - gl_state_bind_vertex_array(a1->vao); + shader_set(&shaders_ft, SHADER_FT_GLITTER_PT); switch (a1->type) { - case GLITTER_PARTICLE_QUAD: - shader_draw_elements(&shaders_aft, + case GLITTER_PARTICLE_QUAD: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(a1->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, color)); // Color + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord0 + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord1 + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(a1->ebo); + shader_draw_elements(&shaders_ft, GL_TRIANGLES, (GLsizei)(6 * a1->disp), GL_UNSIGNED_INT, 0); - break; + gl_state_bind_element_array_buffer(0); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(3); + glDisableVertexAttribArray(8); + glDisableVertexAttribArray(9); + + } break; case GLITTER_PARTICLE_LINE: case GLITTER_PARTICLE_LOCUS: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(a1->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, color)); // Color + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord0 + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord1 + gl_state_bind_array_buffer(0); + const GLenum mode = a1->type == GLITTER_PARTICLE_LINE ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; const size_t count = a1->vec_key.end - a1->vec_key.begin; for (size_t i = 0; i < count; i++) - shader_draw_arrays(&shaders_aft, + shader_draw_arrays(&shaders_ft, mode, a1->vec_key.begin[i], a1->vec_val.begin[i]); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(3); + glDisableVertexAttribArray(8); + glDisableVertexAttribArray(9); + } break; } - gl_state_bind_vertex_array(0); gl_state_disable_blend(); gl_state_enable_cull_face(); gl_state_disable_depth_test(); @@ -377,50 +383,49 @@ void glitter_render_group_free(glitter_render_group* a1) { } void glitter_render_group_update(GLT, - glitter_render_group* render_group, float_t delta_frame, bool copy_mats) { + glitter_render_group* rg, float_t delta_frame, bool copy_mats) { glitter_particle_inst* particle_inst; glitter_particle_inst_data* data; glitter_emitter_inst* emitter; size_t ctrl; size_t i; - if (!render_group->particle) + if (!rg->particle) return; - particle_inst = render_group->particle; + particle_inst = rg->particle; data = &particle_inst->data; - render_group->blend_mode = data->data.blend_mode; - render_group->mask_blend_mode = data->data.mask_blend_mode; - render_group->texture = data->data.texture; - render_group->mask_texture = data->data.mask_texture; - render_group->split_u = data->data.split_u; - render_group->split_v = data->data.split_v; - render_group->split_uv = data->data.split_uv; - render_group->type = data->data.type; - render_group->draw_type = data->data.draw_type; - render_group->z_offset = data->data.z_offset; - render_group->pivot = data->data.pivot; - render_group->flags = data->data.flags; + rg->blend_mode = data->data.blend_mode; + rg->mask_blend_mode = data->data.mask_blend_mode; + rg->texture = data->data.texture; + rg->mask_texture = data->data.mask_texture; + rg->split_u = data->data.split_u; + rg->split_v = data->data.split_v; + rg->split_uv = data->data.split_uv; + rg->type = data->data.type; + rg->draw_type = data->data.draw_type; + rg->z_offset = data->data.z_offset; + rg->pivot = data->data.pivot; + rg->flags = data->data.flags; if (copy_mats && (emitter = particle_inst->data.emitter)) { - render_group->mat = emitter->mat; - render_group->mat_rot = emitter->mat_rot; + rg->mat = emitter->mat; + rg->mat_rot = emitter->mat_rot; } - for (ctrl = render_group->ctrl, i = 0; ctrl > 0; i++) { - if (!render_group->elements[i].alive) + for (ctrl = rg->ctrl, i = 0; ctrl > 0; i++) { + if (!rg->elements[i].alive) continue; - glitter_render_element_update(GLT_VAL, render_group, &render_group->elements[i], delta_frame); + glitter_render_element_update(GLT_VAL, rg, &rg->elements[i], delta_frame); ctrl--; } - render_group->frame += delta_frame; - render_group->update_data |= delta_frame != 0.0f; + rg->frame += delta_frame; } void glitter_render_group_dispose(glitter_render_group* rg) { - vector_int32_t_free(&rg->vec_key); - vector_int32_t_free(&rg->vec_val); + vector_int32_t_free(&rg->vec_key, 0); + vector_int32_t_free(&rg->vec_val, 0); glitter_render_group_delete_buffers(rg, false); free(rg); } @@ -457,9 +462,6 @@ static void glitter_render_group_calc_draw_line(glitter_render_group* a1) { vec3 scale; vec3 pos; vec3 pos_diff; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; glitter_buffer* buf; size_t disp; @@ -467,9 +469,8 @@ static void glitter_render_group_calc_draw_line(glitter_render_group* a1) { glitter_locus_history* hist; glitter_locus_history_data* hist_data; size_t index; - uint32_t temp; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; for (count = 0, i = a1->ctrl, elem = a1->elements; i > 0; i--, elem++) { @@ -486,31 +487,28 @@ static void glitter_render_group_calc_draw_line(glitter_render_group* a1) { if (!count || count > a1->max_count) return; + has_scale = false; scale = vec3_null; - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { mat4_get_scale(&a1->mat, &scale); vec3_sub(scale, vec3_identity, scale); - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; mat4_normalize_rotation(&a1->mat, &a1->mat_draw); } else a1->mat_draw = mat4_identity; - has_scale = has_scale_x || has_scale_y || has_scale_z; - - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; - vector_int32_t_clear(&a1->vec_key); - vector_int32_t_clear(&a1->vec_val); + vector_int32_t_clear(&a1->vec_key, 0); + vector_int32_t_clear(&a1->vec_val, 0); for (i = a1->ctrl, index = 0; i > 0; elem++) { if (!elem->alive) continue; @@ -527,31 +525,25 @@ static void glitter_render_group_calc_draw_line(glitter_render_group* a1) { vec3_mult(pos_diff, scale, pos_diff); vec3_add(pos, pos_diff, buf->position); buf->uv = vec2_null; - buf->color = *(vec3*)&hist_data->color; - buf->alpha = hist_data->color.w; + buf->color = hist_data->color; } else for (j = 0, hist_data = hist->data.begin; hist_data != hist->data.end; j++, buf++, hist_data++) { buf->position = hist_data->translation; buf->uv = vec2_null; - buf->color = *(vec3*)&hist_data->color; - buf->alpha = hist_data->color.w; + buf->color = hist_data->color; } if (j > 0) { disp += j; - temp = (uint32_t)index; - vector_int32_t_push_back(&a1->vec_key, &temp); - temp = (uint32_t)j; - vector_int32_t_push_back(&a1->vec_val, &temp); + *vector_int32_t_reserve_back(&a1->vec_key) = (uint32_t)index; + *vector_int32_t_reserve_back(&a1->vec_val) = (uint32_t)j; index += j; } } a1->disp = disp; - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) { @@ -559,9 +551,6 @@ static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) size_t j; size_t count; vec3 scale; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; glitter_render_element* elem; glitter_locus_history* hist; @@ -574,15 +563,14 @@ static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) vec3 pos; vec3 pos_diff; size_t index; - uint32_t temp; float_t v00; float_t v01; vec3 x_vec; glitter_locus_history_data* hist_data; - mat4 mat; + mat3 model_mat; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; for (count = 0, i = a1->ctrl, elem = a1->elements; i > 0; i--, elem++) { @@ -600,9 +588,9 @@ static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) if (!count || count > a1->max_count) return; - scale = vec3_null; x_vec = (vec3){ 1.0f, 0.0f, 0.0f }; if (a1->flags & GLITTER_PARTICLE_LOCAL) { + mat4 mat; mat4_mult(&GPM_VAL->cam_inv_view, &a1->mat, &mat); mat4_mult(&GPM_VAL->cam_view, &mat, &mat); mat4_mult(&mat, &GPM_VAL->cam_inv_view, &a1->mat_draw); @@ -610,36 +598,36 @@ static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) else a1->mat_draw = mat4_identity; - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; + has_scale = false; + scale = vec3_null; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { mat4_get_scale(&a1->mat, &scale); if (a1->flags & GLITTER_PARTICLE_SCALE) x_vec.x = scale.x; vec3_sub(scale, vec3_identity, scale); - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; mat4_mult_vec3(&a1->mat_rot, &scale, &scale); + + mat4 mat; mat4_normalize_rotation(&a1->mat, &mat); mat3_from_mat4(&mat, &model_mat); } else model_mat = mat3_identity; - has_scale = has_scale_x || has_scale_y || has_scale_z; - mat3_mult_vec(&GPM_VAL->cam_inv_view_mat3, &x_vec, &x_vec); - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; - vector_int32_t_clear(&a1->vec_key); - vector_int32_t_clear(&a1->vec_val); + vector_int32_t_clear(&a1->vec_key, 0); + vector_int32_t_clear(&a1->vec_val, 0); for (i = a1->ctrl, index = 0; i > 0; elem++) { if (!elem->alive) continue; @@ -674,31 +662,25 @@ static void glitter_render_group_calc_draw_locus(GPM, glitter_render_group* a1) vec3_add(buf[0].position, pos, buf[0].position); buf[0].uv.x = uv_u; buf[0].uv.y = uv_v_2nd + (float_t)j * uv_v_scale; - buf[0].color = *(vec3*)&hist_data->color; - buf[0].alpha = hist_data->color.w; + buf[0].color = hist_data->color; vec3_mult_scalar(x_vec, v01, buf[1].position); vec3_add(buf[1].position, pos, buf[1].position); buf[1].uv.x = uv_u_2nd; buf[1].uv.y = uv_v_2nd + (float_t)j * uv_v_scale; - buf[1].color = *(vec3*)&hist_data->color; - buf[1].alpha = hist_data->color.w; + buf[1].color = hist_data->color; } if (j > 0) { disp += j; - temp = (uint32_t)index; - vector_int32_t_push_back(&a1->vec_key, &temp); - temp = (uint32_t)(j * 2); - vector_int32_t_push_back(&a1->vec_val, &temp); + *vector_int32_t_reserve_back(&a1->vec_key) = (uint32_t)index; + *vector_int32_t_reserve_back(&a1->vec_val) = (uint32_t)(j * 2); index += j * 2; } } a1->disp = disp; - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp * 2), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_render_group_calc_draw_quad(GPM, glitter_render_group* a1) { @@ -707,12 +689,12 @@ static void glitter_render_group_calc_draw_quad(GPM, glitter_render_group* a1) { mat4 view_mat; mat4 inv_view_mat; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { model_mat = a1->mat; - mat4_normalize_rotation(&a1->mat, &view_mat); + mat4_normalize_rotation(&model_mat, &view_mat); mat4_mult(&view_mat, &GPM_VAL->cam_view, &view_mat); mat4_inverse(&view_mat, &inv_view_mat); } @@ -727,6 +709,7 @@ static void glitter_render_group_calc_draw_quad(GPM, glitter_render_group* a1) { mat4_mult(&view_mat, &inv_view_mat, &view_mat); mat4_inverse(&view_mat, &inv_view_mat); } + mat4_mult(&view_mat, &GPM_VAL->cam_inv_view, &a1->mat_draw); switch (a1->draw_type) { @@ -755,7 +738,7 @@ static void glitter_render_group_calc_draw_quad(GPM, glitter_render_group* a1) { case GLITTER_DIRECTION_Z_AXIS: mat4_rotate_z((float_t)-M_PI_2, &dir_mat); break; - case GLITTER_DIRECTION_BILLBOARD_Y_ONLY: + case GLITTER_DIRECTION_BILLBOARD_Y_AXIS: mat4_rotate_y(GPM_VAL->cam_rotation_y, &dir_mat); break; default: @@ -773,10 +756,6 @@ static void glitter_render_group_calc_draw_quad(GPM, glitter_render_group* a1) { glitter_render_group_calc_draw_quad_normal(GPM_VAL, a1, &model_mat, &dir_mat); break; } - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp * 4), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); } static void glitter_render_group_calc_draw_quad_normal(GPM, @@ -789,9 +768,6 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, size_t disp; glitter_buffer* buf; vec3 z_offset_dir; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; vec3 pos; bool use_z_offset; @@ -836,9 +812,7 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, } } - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; + has_scale = false; emitter_local = false; scale = vec3_null; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { @@ -848,18 +822,16 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, y_vec.y = scale.y; } vec3_sub(scale, vec3_identity, scale); - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; mat4_mult_vec3(&a1->mat_rot, &scale, &scale); emitter_local = true; } - has_scale = has_scale_x || has_scale_y || has_scale_z; - if (glitter_render_group_get_ext_anim_scale(a1, &ext_scale)) { vec2_add(*(vec2*)&ext_scale, vec2_identity, *(vec2*)&ext_scale); x_vec.x *= ext_scale.x; @@ -876,7 +848,8 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, mat4_mult_vec3(&inv_model_mat, &x_vec, &x_vec); mat4_mult_vec3(&inv_model_mat, &y_vec, &y_vec); - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; if (a1->draw_type == GLITTER_DIRECTION_PARTICLE_ROTATION) @@ -945,8 +918,7 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, mat3_mult_vec(&ptc_rot, &x_vec_rot, &x_vec_rot); vec3_add(x_vec_rot, pos, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } @@ -1017,13 +989,14 @@ static void glitter_render_group_calc_draw_quad_normal(GPM, vec3_add(x_vec_rot, y_vec_rot, x_vec_rot); vec3_add(x_vec_rot, pos, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } } a1->disp = disp; + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_render_group_calc_draw_quad_direction_rotation(glitter_render_group* a1, @@ -1080,8 +1053,9 @@ static void glitter_render_group_calc_draw_quad_direction_rotation(glitter_rende mat4_get_scale(model_mat, &scale); + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); use_scale = a1->flags & GLITTER_PARTICLE_SCALE ? true : false; - buf = a1->buffer; elem = a1->elements; disp = 0; for (i = a1->ctrl, j_max = 1024; i > 0; i -= j_max) { @@ -1145,13 +1119,14 @@ static void glitter_render_group_calc_draw_quad_direction_rotation(glitter_rende vec3_add(x_vec_rot, y_vec_rot, pos_add_rot); vec3_add(pos, pos_add_rot, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } } a1->disp = disp; + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_render_group_calc_draw_locus_set_pivot(glitter_pivot pivot, diff --git a/src/CRE/Glitter/render_scene.c b/src/CRE/Glitter/render_scene.c index 0d0322c4..7e7f971c 100644 --- a/src/CRE/Glitter/render_scene.c +++ b/src/CRE/Glitter/render_scene.c @@ -59,7 +59,7 @@ void glitter_render_scene_calc_draw(GPM, glitter_render_scene* rs) { } } -void glitter_render_scene_draw(GPM, glitter_render_scene* rs, alpha_pass_type alpha) { +void glitter_render_scene_draw(GPM, glitter_render_scene* rs, draw_pass_3d_type alpha) { glitter_render_group** i; glitter_render_group* rg; diff --git a/src/CRE/Glitter/render_scene.h b/src/CRE/Glitter/render_scene.h index b29901c7..1c8e6fd1 100644 --- a/src/CRE/Glitter/render_scene.h +++ b/src/CRE/Glitter/render_scene.h @@ -10,7 +10,7 @@ extern void glitter_render_scene_append(glitter_render_scene* rs, glitter_render_group* rg); extern void glitter_render_scene_calc_draw(GPM, glitter_render_scene* rs); -extern void glitter_render_scene_draw(GPM, glitter_render_scene* rs, alpha_pass_type alpha); +extern void glitter_render_scene_draw(GPM, glitter_render_scene* rs, draw_pass_3d_type alpha); extern size_t glitter_render_scene_get_ctrl_count(glitter_render_scene* rs, glitter_particle_type type); extern size_t glitter_render_scene_get_disp_count(glitter_render_scene* rs, diff --git a/src/CRE/Glitter/scene.c b/src/CRE/Glitter/scene.c index 1be1d21d..74d7bafe 100644 --- a/src/CRE/Glitter/scene.c +++ b/src/CRE/Glitter/scene.c @@ -4,8 +4,8 @@ */ #include "scene.h" -#include "effect_inst.h" #include "../GlitterX/effect_inst_x.h" +#include "effect_inst.h" glitter_scene* glitter_scene_init(glitter_effect_group* eg) { glitter_scene* s = force_malloc(sizeof(glitter_scene)); @@ -162,6 +162,6 @@ void glitter_scene_dispose(glitter_scene* s) { if (i->ptr) glitter_effect_inst_dispose(i->ptr); } - vector_glitter_scene_effect_free(&s->effects); + vector_glitter_scene_effect_free(&s->effects, 0); free(s); } diff --git a/src/CRE/Glitter/shared.c b/src/CRE/Glitter/shared.c index c412536e..83fe2dfc 100644 --- a/src/CRE/Glitter/shared.c +++ b/src/CRE/Glitter/shared.c @@ -35,13 +35,10 @@ void mat3_mult_axis_angle(mat3* src, mat3* dst, vec3* axis, float_t angle) { quat q2; quat q3; - quat_from_mat3(src->row0.x, src->row0.y, src->row0.z, src->row1.x, - src->row1.y, src->row1.z, src->row2.x, src->row2.y, src->row2.z, &q1); + quat_from_mat3(src->row0.x, src->row1.x, src->row2.x, src->row0.y, + src->row1.y, src->row2.y, src->row0.z, src->row1.z, src->row2.z, &q1); quat_from_axis_angle(axis, angle, &q2); - q3.x = q1.x * q2.w - q1.y * q2.z + q1.z * q2.y + q1.w * q2.x; - q3.y = q1.x * q2.z + q1.y * q2.w - q1.z * q2.x + q1.w * q2.y; - q3.z = -q1.x * q2.y + q1.y * q2.x + q1.z * q2.w + q1.w * q2.z; - q3.w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w; + quat_mult(&q2, &q1, &q3); mat3_from_quat(&q3, dst); } @@ -49,21 +46,22 @@ void mat4_mult_axis_angle(mat4* src, mat4* dst, vec3* axis, float_t angle) { quat q1; quat q2; quat q3; - mat3 yt; + float_t t0; + float_t t1; + float_t t2; + vec4 t3; - quat_from_mat3(src->row0.x, src->row0.y, src->row0.z, src->row1.x, - src->row1.y, src->row1.z, src->row2.x, src->row2.y, src->row2.z, &q1); + t0 = src->row0.w; + t1 = src->row1.w; + t2 = src->row2.w; + t3 = src->row3; + quat_from_mat3(src->row0.x, src->row1.x, src->row2.x, src->row0.y, + src->row1.y, src->row2.y, src->row0.z, src->row1.z, src->row2.z, &q1); quat_from_axis_angle(axis, angle, &q2); - q3.x = q1.x * q2.w - q1.y * q2.z + q1.z * q2.y + q1.w * q2.x; - q3.y = q1.x * q2.z + q1.y * q2.w - q1.z * q2.x + q1.w * q2.y; - q3.z = -q1.x * q2.y + q1.y * q2.x + q1.z * q2.w + q1.w * q2.z; - q3.w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w; - mat3_from_quat(&q3, &yt); - *(vec3*)&dst->row0 = yt.row0; - *(vec3*)&dst->row1 = yt.row1; - *(vec3*)&dst->row2 = yt.row2; - dst->row0.w = src->row0.w; - dst->row1.w = src->row2.w; - dst->row2.w = src->row3.w; - dst->row3 = src->row3; + quat_mult(&q2, &q1, &q3); + mat4_from_quat(&q3, dst); + dst->row0.w = t0; + dst->row1.w = t1; + dst->row2.w = t2; + dst->row3 = t3; } diff --git a/src/CRE/Glitter/shared.h b/src/CRE/Glitter/shared.h index 0f1b06e5..29fdccc3 100644 --- a/src/CRE/Glitter/shared.h +++ b/src/CRE/Glitter/shared.h @@ -6,16 +6,16 @@ #pragma once #include "../../KKdLib/default.h" -#include "../../KKdLib/f2_header.h" -#include "../../KKdLib/f2_struct.h" +#include "../../KKdLib/database/object.h" +#include "../../KKdLib/f2/header.h" +#include "../../KKdLib/f2/struct.h" #include "../../KKdLib/hash.h" #include "../../KKdLib/mat.h" -#include "../../KKdLib/mot.h" #include "../../KKdLib/txp.h" #include "../../KKdLib/vec.h" #include "../../KKdLib/vector.h" -#include "../texture.h" #include "../static_var.h" +#include "../texture.h" extern void axis_angle_from_vectors(vec3* axis, float_t* angle, vec3* vec0, vec3* vec1); extern void mat3_mult_axis_angle(mat3* src, mat3* dst, vec3* axis, float_t angle); diff --git a/src/CRE/Glitter/texture.c b/src/CRE/Glitter/texture.c index 806b9207..e4e50e32 100644 --- a/src/CRE/Glitter/texture.c +++ b/src/CRE/Glitter/texture.c @@ -94,10 +94,10 @@ bool glitter_texture_resource_pack_file(glitter_effect_group* a1, f2_struct* st) memset(st, 0, sizeof(f2_struct)); - if (!tex_set_produce_enrs(&a1->resources_tex, &st->enrs)) + if (!txp_set_produce_enrs(&a1->resources_tex, &st->enrs)) return false; - tex_set_pack_file(&a1->resources_tex, &st->data, &st->length, false); + txp_set_pack_file(&a1->resources_tex, &st->data, &st->length, false); st->header.signature = reverse_endianness_uint32_t('TXPC'); st->header.length = 0x20; @@ -106,15 +106,15 @@ bool glitter_texture_resource_pack_file(glitter_effect_group* a1, f2_struct* st) return true; } -bool glitter_texture_resource_unpack_file(glitter_effect_group* a1, f2_struct* st) { +bool glitter_texture_resource_unpack_file(GPM, glitter_effect_group* a1, f2_struct* st) { if (!st || !st->header.data_size) return false; - tex_set_unpack_file(&a1->resources_tex, st->data, st->header.use_big_endian); - return glitter_texture_load(a1); + txp_set_unpack_file(&a1->resources_tex, st->data, st->header.use_big_endian); + return glitter_texture_load(GPM_VAL, a1); } -bool glitter_texture_load(glitter_effect_group* a1) { +bool glitter_texture_load(GPM, glitter_effect_group* a1) { if (!a1->resources_count) return false; @@ -123,24 +123,33 @@ bool glitter_texture_load(glitter_effect_group* a1) { if (!count || !a1->resources_count || a1->resources_count != count) return false; - if (!texture_txp_set_load(&a1->resources_tex, &a1->resources)) - return false; + uint32_t* ids = force_malloc_s(uint32_t, count); + for (size_t i = 0; i < count; i++) { + ids[i] = texture_make_id(0x2A, GPM_VAL->texture_counter); + GPM_VAL->texture_counter++; + } - for (glitter_effect** l = a1->effects.begin; l != a1->effects.end; l++) { - if (!*l) + if (!texture_txp_set_load(&a1->resources_tex, &a1->resources, ids)) { + free(ids); + return false; + } + free(ids); + + for (glitter_effect** i = a1->effects.begin; i != a1->effects.end; i++) { + if (!*i) continue; - glitter_effect* effect = *l; - for (glitter_emitter** m = effect->emitters.begin; m != effect->emitters.end; m++) { - if (!*m) + glitter_effect* effect = *i; + for (glitter_emitter** j = effect->emitters.begin; j != effect->emitters.end; j++) { + if (!*j) continue; - glitter_emitter* emitter = *m; - for (glitter_particle** n = emitter->particles.begin; n != emitter->particles.end; n++) { - if (!*n) + glitter_emitter* emitter = *j; + for (glitter_particle** k = emitter->particles.begin; k != emitter->particles.end; k++) { + if (!*k) continue; - glitter_particle* particle = *n; + glitter_particle* particle = *k; particle->data.texture = 0; particle->data.mask_texture = 0; } @@ -148,29 +157,29 @@ bool glitter_texture_load(glitter_effect_group* a1) { } for (size_t i = 0; i < a1->resources_count; i++) - for (glitter_effect** l = a1->effects.begin; l != a1->effects.end; l++) { - if (!*l) + for (glitter_effect** j = a1->effects.begin; j != a1->effects.end; j++) { + if (!*j) continue; - glitter_effect* effect = *l; - for (glitter_emitter** m = effect->emitters.begin; m != effect->emitters.end; m++) { - if (!*m) + glitter_effect* effect = *j; + for (glitter_emitter** k = effect->emitters.begin; k != effect->emitters.end; k++) { + if (!*k) continue; - glitter_emitter* emitter = *m; - for (glitter_particle** n = emitter->particles.begin; n != emitter->particles.end; n++) { - if (!*n) + glitter_emitter* emitter = *k; + for (glitter_particle** l = emitter->particles.begin; l != emitter->particles.end; l++) { + if (!*l) continue; - glitter_particle* particle = *n; + glitter_particle* particle = *l; if (particle->data.type == GLITTER_PARTICLE_LINE || particle->data.type == GLITTER_PARTICLE_MESH) continue; if (particle->data.tex_hash == a1->resource_hashes.begin[i]) - particle->data.texture = a1->resources.begin[i]->texture; + particle->data.texture = a1->resources[i]->texture; if (particle->data.mask_tex_hash == a1->resource_hashes.begin[i]) - particle->data.mask_texture = a1->resources.begin[i]->texture; + particle->data.mask_texture = a1->resources[i]->texture; } } } @@ -178,5 +187,9 @@ bool glitter_texture_load(glitter_effect_group* a1) { } void glitter_texture_unload(glitter_effect_group* a1) { - vector_ptr_texture_free(&a1->resources, texture_dispose); + if (a1->resources) { + for (texture** i = a1->resources; *i; i++) + texture_free(*i); + free(a1->resources); + } } diff --git a/src/CRE/Glitter/texture.h b/src/CRE/Glitter/texture.h index 62912acd..38af62ec 100644 --- a/src/CRE/Glitter/texture.h +++ b/src/CRE/Glitter/texture.h @@ -10,6 +10,6 @@ extern bool glitter_texture_hashes_pack_file(glitter_effect_group* a1, f2_struct* st); extern bool glitter_texture_hashes_unpack_file(glitter_effect_group* a1, f2_struct* st); extern bool glitter_texture_resource_pack_file(glitter_effect_group* a1, f2_struct* st); -extern bool glitter_texture_resource_unpack_file(glitter_effect_group* a1, f2_struct* st); -extern bool glitter_texture_load(glitter_effect_group* a1); +extern bool glitter_texture_resource_unpack_file(GPM, glitter_effect_group* a1, f2_struct* st); +extern bool glitter_texture_load(GPM, glitter_effect_group* a1); extern void glitter_texture_unload(glitter_effect_group* a1); diff --git a/src/CRE/GlitterX/effect_inst_x.c b/src/CRE/GlitterX/effect_inst_x.c index 9f9e766f..5eb35bbe 100644 --- a/src/CRE/GlitterX/effect_inst_x.c +++ b/src/CRE/GlitterX/effect_inst_x.c @@ -26,7 +26,7 @@ glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, glitter_effect_inst* ei = force_malloc(sizeof(glitter_effect_inst)); ei->effect = a1; ei->data = a1->data; - ei->color = vec4_identity; + ei->color = vec4u_identity; ei->scale_all = 1.0f; ei->id = id; ei->translation = a1->translation; @@ -54,7 +54,8 @@ glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, inst_ext_anim->chara_index = -1; inst_ext_anim->mesh_index = -1; inst_ext_anim->mat = mat4_identity; - inst_ext_anim = ei->ext_anim; + inst_ext_anim->translation = vec3_null; + if (inst_ext_anim != (glitter_effect_inst_ext_anim*)0x0) { ext_anim = ei->data.ext_anim; if (ext_anim->flags & GLITTER_EFFECT_EXT_ANIM_SET_ONCE) @@ -118,21 +119,21 @@ void glitter_x_effect_inst_calc_draw(GPM, glitter_effect_inst* a1) { glitter_x_render_scene_calc_draw(GPM_VAL, &a1->render_scene); } -void glitter_x_effect_inst_draw(GPM, glitter_effect_inst* a1, alpha_pass_type alpha) { +void glitter_x_effect_inst_draw(GPM, glitter_effect_inst* a1, draw_pass_3d_type alpha) { glitter_x_render_scene_draw(GPM_VAL, &a1->render_scene, alpha); } -alpha_pass_type glitter_x_effect_inst_get_alpha(glitter_effect_inst* a1) { - return a1->data.flags & GLITTER_EFFECT_ALPHA ? ALPHA_PASS_TRANSPARENT : ALPHA_PASS_TRANSLUCENT; +draw_pass_3d_type glitter_x_effect_inst_get_alpha(glitter_effect_inst* a1) { + return a1->data.flags & GLITTER_EFFECT_ALPHA ? DRAW_PASS_3D_TRANSPARENT : DRAW_PASS_3D_TRANSLUCENT; } fog_type glitter_x_effect_inst_get_fog(glitter_effect_inst* a1) { if (a1->data.flags & GLITTER_EFFECT_FOG) - return FOG_NORMAL; + return FOG_DEPTH; else if (a1->data.flags & GLITTER_EFFECT_FOG_HEIGHT) return FOG_HEIGHT; else - return FOG_NONE; + return -1; } bool glitter_x_effect_inst_has_ended(glitter_effect_inst* effect, bool a2) { @@ -161,7 +162,7 @@ void glitter_x_effect_inst_reset(glitter_effect_inst* a1, float_t emission) { glitter_x_effect_inst_update_init(a1, emission); } -void glitter_x_effect_inst_update(GPM, glitter_effect_inst* a1, +void glitter_x_effect_inst_update(GPM, glitter_effect_inst* effect, float_t delta_frame, float_t emission) { glitter_effect_inst_ext_anim* ext_anim; glitter_emitter_inst** i; @@ -171,55 +172,55 @@ void glitter_x_effect_inst_update(GPM, glitter_effect_inst* a1, vec3 rot; vec3 scale; - glitter_x_effect_inst_get_ext_anim(a1); - if (a1->flags & GLITTER_EFFECT_INST_GET_EXT_ANIM_THEN_UPDATE && !GPM_VAL->draw_all) + glitter_x_effect_inst_get_ext_anim(effect); + if (effect->flags & GLITTER_EFFECT_INST_GET_EXT_ANIM_THEN_UPDATE && !GPM_VAL->draw_all) return; - glitter_x_effect_inst_get_value(a1); - trans = a1->translation; - rot = a1->rotation; - vec3_mult_scalar(a1->scale, a1->scale_all, scale); + glitter_x_effect_inst_get_value(effect); + trans = effect->translation; + rot = effect->rotation; + vec3_mult_scalar(effect->scale, effect->scale_all, scale); - if (a1->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS && a1->ext_anim) { + if (effect->flags & GLITTER_EFFECT_INST_HAS_EXT_ANIM_TRANS && effect->ext_anim) { vec3 ext_trans; - ext_anim = a1->ext_anim; + ext_anim = effect->ext_anim; ext_trans = ext_anim->translation; mat4_translate_mult(&ext_anim->mat, ext_trans.x, ext_trans.y, ext_trans.z, &mat); mat4_normalize_rotation(&mat, &mat_rot); mat4_clear_trans(&mat_rot, &mat_rot); - a1->mat_rot = mat_rot; - mat4_rot(&mat_rot, rot.x, rot.y, rot.z, &a1->mat_rot_eff_rot); + effect->mat_rot = mat_rot; + mat4_rot(&mat_rot, rot.x, rot.y, rot.z, &effect->mat_rot_eff_rot); mat4_translate_mult(&mat, trans.x, trans.y, trans.z, &mat); } else { - a1->mat_rot = mat4_identity; - mat4_rotate(rot.x, rot.y, rot.z, &a1->mat_rot_eff_rot); + effect->mat_rot = mat4_identity; + mat4_rotate(rot.x, rot.y, rot.z, &effect->mat_rot_eff_rot); mat4_translate(trans.x, trans.y, trans.z, &mat); } mat4_rot(&mat, rot.x, rot.y, rot.z, &mat); - mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &a1->mat); - for (i = a1->emitters.begin; i != a1->emitters.end; i++) + mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &effect->mat); + for (i = effect->emitters.begin; i != effect->emitters.end; i++) if (*i) - glitter_x_emitter_inst_update(GPM_VAL, *i, a1, delta_frame); + glitter_x_emitter_inst_update(GPM_VAL, *i, effect, delta_frame); - if (a1->frame0 >= 0.0f) - if (a1->frame0 < (float_t)a1->data.life_time) { - for (i = a1->emitters.begin; i != a1->emitters.end; i++) + if (effect->frame0 >= 0.0f) + if (effect->frame0 < (float_t)effect->data.life_time) { + for (i = effect->emitters.begin; i != effect->emitters.end; i++) if (*i) glitter_x_emitter_inst_emit(*i, delta_frame, emission); } - else if (a1->data.flags & GLITTER_EFFECT_LOOP) - a1->frame0 -= (float_t)a1->data.life_time; + else if (effect->data.flags & GLITTER_EFFECT_LOOP) + effect->frame0 -= (float_t)effect->data.life_time; else { - a1->flags |= GLITTER_EFFECT_INST_FREE; - for (i = a1->emitters.begin; i != a1->emitters.end; i++) + effect->flags |= GLITTER_EFFECT_INST_FREE; + for (i = effect->emitters.begin; i != effect->emitters.end; i++) if (*i) glitter_x_emitter_inst_free(*i, emission); } - glitter_x_render_scene_update(&a1->render_scene, delta_frame, true); - a1->frame0 += delta_frame; + glitter_x_render_scene_update(&effect->render_scene, delta_frame, true); + effect->frame0 += delta_frame; } void glitter_x_effect_inst_dispose(glitter_effect_inst* ei) { diff --git a/src/CRE/GlitterX/effect_inst_x.h b/src/CRE/GlitterX/effect_inst_x.h index 35773701..dc396ddc 100644 --- a/src/CRE/GlitterX/effect_inst_x.h +++ b/src/CRE/GlitterX/effect_inst_x.h @@ -10,7 +10,7 @@ extern glitter_effect_inst* glitter_x_effect_inst_init(GPM, glitter_effect* a1, size_t id, float_t emission, bool appear_now); extern void glitter_x_effect_inst_calc_draw(GPM, glitter_effect_inst* a1); -extern void glitter_x_effect_inst_draw(GPM, glitter_effect_inst* a1, alpha_pass_type alpha); +extern void glitter_x_effect_inst_draw(GPM, glitter_effect_inst* a1, draw_pass_3d_type alpha); extern int32_t glitter_x_effect_inst_get_alpha(glitter_effect_inst* a1); extern fog_type glitter_x_effect_inst_get_fog(glitter_effect_inst* a1); extern bool glitter_x_effect_inst_has_ended(glitter_effect_inst* effect, bool a2); diff --git a/src/CRE/GlitterX/emitter_inst_x.c b/src/CRE/GlitterX/emitter_inst_x.c index 1b383fb7..2876bdc8 100644 --- a/src/CRE/GlitterX/emitter_inst_x.c +++ b/src/CRE/GlitterX/emitter_inst_x.c @@ -267,7 +267,7 @@ void glitter_x_emitter_inst_update(GPM, case GLITTER_DIRECTION_X_AXIS: mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; - case GLITTER_DIRECTION_BILLBOARD_Y_ONLY: + case GLITTER_DIRECTION_BILLBOARD_Y_AXIS: mat4_rotate_y(GPM_VAL->cam_rotation_y, &dir_mat); break; default: @@ -280,10 +280,9 @@ void glitter_x_emitter_inst_update(GPM, mat4_mult(&dir_mat, &mat_rot, &mat_rot); } mat4_rot(&mat, rot.x, rot.y, rot.z, &mat); - mat4_rot(&mat_rot, rot.x, rot.y, rot.z, &mat_rot); + mat4_rot(&mat_rot, rot.x, rot.y, rot.z, &a1->mat_rot); mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &mat); a1->mat = mat; - a1->mat_rot = mat_rot; if (has_dist) { mat4_get_translation(&mat, &trans); @@ -301,10 +300,6 @@ void glitter_x_emitter_inst_update(GPM, void glitter_x_emitter_inst_update_init(glitter_emitter_inst* a1, glitter_effect_inst* a2, float_t delta_frame) { - vec3 trans; - vec3 rot; - vec3 rotation_add; - if (a1->frame < 0.0f) return; @@ -330,6 +325,8 @@ void glitter_x_emitter_inst_update_init(glitter_emitter_inst* a1, } glitter_x_emitter_inst_get_value(a1); + + vec3 rotation_add; vec3_mult_scalar(a1->data.rotation_add, delta_frame, rotation_add); vec3_add(a1->rotation, rotation_add, a1->rotation); if (a1->data.timer == GLITTER_EMITTER_TIMER_BY_DISTANCE && a1->flags & GLITTER_EMITTER_INST_HAS_DISTANCE) { @@ -343,14 +340,12 @@ void glitter_x_emitter_inst_update_init(glitter_emitter_inst* a1, mat_ext_anim = a2->mat_rot; mat4_get_translation(&a1->mat, &trans_prev); - mat = a2->mat; - trans = a1->translation; - rot = a1->rotation; - mat4_translate_mult(&mat, trans.x, trans.y, trans.z, &mat); + vec3 trans = a1->translation; + vec3 rot = a1->rotation; + mat4_translate_mult(&a2->mat, trans.x, trans.y, trans.z, &mat); mat4_rot(&mat, rot.x, rot.y, rot.z, &mat); - mat4_rot(&mat_ext_anim, rot.x, rot.y, rot.z, &mat_ext_anim); + mat4_rot(&mat_ext_anim, rot.x, rot.y, rot.z, &a1->mat_rot); a1->mat = mat; - a1->mat_rot = mat_ext_anim; vec3 trans_diff; mat4_get_translation(&mat, &trans); diff --git a/src/CRE/GlitterX/locus_history_x.c b/src/CRE/GlitterX/locus_history_x.c index 8657c5ad..42322cc6 100644 --- a/src/CRE/GlitterX/locus_history_x.c +++ b/src/CRE/GlitterX/locus_history_x.c @@ -58,6 +58,6 @@ void glitter_x_locus_history_append(glitter_locus_history* a1, } void glitter_x_locus_history_dispose(glitter_locus_history* lh) { - vector_glitter_locus_history_data_free(&lh->data); + vector_glitter_locus_history_data_free(&lh->data, 0); free(lh); } diff --git a/src/CRE/GlitterX/render_element_x.c b/src/CRE/GlitterX/render_element_x.c index 935e7414..a81212e3 100644 --- a/src/CRE/GlitterX/render_element_x.c +++ b/src/CRE/GlitterX/render_element_x.c @@ -46,7 +46,7 @@ void glitter_x_render_element_emit(glitter_render_element* a1, a1->life_time += a1->fade_in_frames + a1->fade_out_frames; a1->color = a2->data.color; - if (a2->data.draw_type == GLITTER_DIRECTION_PARTICLE_ROTATION) { + if (a2->data.draw_type == GLITTER_DIRECTION_PARTICLE_ROTATION || a2->data.type == GLITTER_PARTICLE_MESH) { a1->rotation.x = glitter_x_random_get_float(random, a2->data.rotation_random.x) + a2->data.rotation.x; a1->rotation_add.x = glitter_x_random_get_float(random, a2->data.rotation_add_random.x) @@ -277,7 +277,7 @@ void glitter_x_render_element_update(glitter_render_group* a1, a2->uv_scroll_2nd.y = fmodf(a2->uv_scroll_2nd.y + uv_scroll_2nd.y, 1.0f); } glitter_x_render_element_step_uv(particle, a2, delta_frame, a1->random_ptr); - a2->color = (vec4){ -1.0f, -1.0f, -1.0f, -1.0f }; + a2->color = (vec4u){ -1.0f, -1.0f, -1.0f, -1.0f }; color_scale = -1.0f; a2->draw = true; diff --git a/src/CRE/GlitterX/render_group_x.c b/src/CRE/GlitterX/render_group_x.c index 75245d22..a5fc742b 100644 --- a/src/CRE/GlitterX/render_group_x.c +++ b/src/CRE/GlitterX/render_group_x.c @@ -4,17 +4,17 @@ */ #include "emitter_inst_x.h" +#include "../draw_task.h" +#include "../gl_state.h" +#include "../render_context.h" +#include "../shader.h" +#include "../shader_ft.h" +#include "../static_var.h" #include "random_x.h" #include "render_group_x.h" #include "render_element_x.h" -#include "../gl_state.h" -#include "../shader.h" -#include "../shader_aft.h" -#include "../static_var.h" #include -extern shader_set_data shaders_aft; - static glitter_render_element* glitter_x_render_group_add_render_element(glitter_render_group* a1, glitter_render_element* a2); static void glitter_x_render_group_calc_draw_line(glitter_render_group* a1); @@ -73,13 +73,11 @@ glitter_render_group* glitter_x_render_group_init(glitter_particle_inst* a1) { rg->mat_draw = mat4_identity; rg->max_count = max_count; rg->particle = a1; - rg->alpha = ALPHA_PASS_TRANSLUCENT; + rg->alpha = DRAW_PASS_3D_TRANSLUCENT; rg->emission = 1.0f; rg->blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; rg->mask_blend_mode = GLITTER_PARTICLE_BLEND_TYPICAL; rg->random_ptr = a1->data.random_ptr; - rg->buffer = 0; - rg->vao = 0; rg->vbo = 0; rg->ebo = 0; rg->vec_key = vector_empty(int32_t); @@ -96,12 +94,14 @@ glitter_render_group* glitter_x_render_group_init(glitter_particle_inst* a1) { bool is_quad = a1->data.data.type == GLITTER_PARTICLE_QUAD; - rg->buffer = force_malloc_s(glitter_buffer, rg->max_count); - if (!rg->buffer) - rg->max_count = 0; - - glGenVertexArrays(1, &rg->vao); - glGenBuffers(1, &rg->vbo); + if (a1->data.data.type != GLITTER_PARTICLE_MESH) { + glGenBuffers(1, &rg->vbo); + gl_state_bind_array_buffer(rg->vbo); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * rg->max_count), 0, GL_DYNAMIC_DRAW); + gl_state_bind_array_buffer(rg->vbo); + } + else + rg->vbo = 0; if (is_quad) { size_t count = rg->max_count / 4 * 6; @@ -114,42 +114,20 @@ glitter_render_group* glitter_x_render_group_init(glitter_particle_inst* a1) { ebo_data[i + 4] = (int32_t)(j + 2); ebo_data[i + 5] = (int32_t)(j + 3); } + glGenBuffers(1, &rg->ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->ebo); + gl_state_bind_element_array_buffer(rg->ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int32_t) * count, ebo_data, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + gl_state_bind_element_array_buffer(0); free(ebo_data); } static const GLsizei buffer_size = sizeof(glitter_buffer); - gl_state_bind_vertex_array(rg->vao); - if (is_quad) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rg->ebo); - glBindBuffer(GL_ARRAY_BUFFER, rg->vbo); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, position)); // Pos - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, color)); // Color - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, uv)); // TexCoord0 - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, - (void*)offsetof(glitter_buffer, uv)); // TexCoord1 - gl_state_bind_vertex_array(0); - if (is_quad) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - if (!is_quad) { vector_int32_t_reserve(&rg->vec_key, rg->count); vector_int32_t_reserve(&rg->vec_val, rg->count); } - rg->update_data = true; return rg; } @@ -159,15 +137,11 @@ void glitter_x_render_group_calc_draw(GPM, glitter_render_group* a1) { case GLITTER_PARTICLE_LINE: case GLITTER_PARTICLE_LOCUS: case GLITTER_PARTICLE_MESH: - if (!a1->update_data && !GPM_VAL->updated) - return; break; default: - a1->update_data = false; return; } - a1->update_data = false; a1->disp = 0; switch (a1->type) { case GLITTER_PARTICLE_QUAD: @@ -264,11 +238,10 @@ void glitter_x_render_group_draw(GPM, glitter_render_group* a1) { } switch (a1->fog) { - case FOG_NONE: default: uniform_value[U_FOG_HEIGHT] = 0; break; - case FOG_NORMAL: + case FOG_DEPTH: uniform_value[U_FOG_HEIGHT] = 1; break; case FOG_HEIGHT: @@ -277,9 +250,9 @@ void glitter_x_render_group_draw(GPM, glitter_render_group* a1) { } if (a1->blend_mode == GLITTER_PARTICLE_BLEND_PUNCH_THROUGH) - uniform_value[U_ALPHA_BLEND] = a1->alpha != ALPHA_PASS_OPAQUE ? 3 : 1; + uniform_value[U_ALPHA_BLEND] = a1->alpha != DRAW_PASS_3D_OPAQUE ? 3 : 1; else - uniform_value[U_ALPHA_BLEND] = a1->alpha != ALPHA_PASS_OPAQUE ? 2 : 0; + uniform_value[U_ALPHA_BLEND] = a1->alpha != DRAW_PASS_3D_OPAQUE ? 2 : 0; if (~a1->particle->data.flags & GLITTER_PARTICLE_DEPTH_TEST) { gl_state_enable_depth_test(); @@ -300,35 +273,78 @@ void glitter_x_render_group_draw(GPM, glitter_render_group* a1) { else gl_state_disable_cull_face(); - vec4 emission; + float_t emission = 1.0f; if (a1->flags & GLITTER_PARTICLE_EMISSION || a1->blend_mode == GLITTER_PARTICLE_BLEND_TYPICAL) - emission = (vec4){ a1->emission, a1->emission, a1->emission, 1.0f }; - else - emission = vec4_identity; + emission = a1->emission; - shader_state_material_set_emission(&shaders_aft, false, &emission); - shader_state_matrix_set_mvp_separate(&shaders_aft, + shader_state_material_set_emission(&shaders_ft, false, emission, emission, emission, 1.0f); + shader_state_matrix_set_mvp_separate(&shaders_ft, &a1->mat_draw, &GPM_VAL->cam_view, &GPM_VAL->cam_projection); - shader_state_matrix_set_texture(&shaders_aft, 0, (mat4*)&mat4_identity); - shader_state_matrix_set_texture(&shaders_aft, 1, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity); - shader_set(&shaders_aft, SHADER_AFT_GLITTER_PT); - gl_state_bind_vertex_array(a1->vao); + shader_set(&shaders_ft, SHADER_FT_GLITTER_PT); switch (a1->type) { - case GLITTER_PARTICLE_QUAD: - shader_draw_elements(&shaders_aft, + case GLITTER_PARTICLE_QUAD: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(a1->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, color)); // Color + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord0 + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord1 + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(a1->ebo); + shader_draw_elements(&shaders_ft, GL_TRIANGLES, (GLsizei)(6 * a1->disp), GL_UNSIGNED_INT, 0); - break; + gl_state_bind_element_array_buffer(0); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(3); + glDisableVertexAttribArray(8); + glDisableVertexAttribArray(9); + } break; case GLITTER_PARTICLE_LINE: case GLITTER_PARTICLE_LOCUS: { + static const GLsizei buffer_size = sizeof(glitter_buffer); + + gl_state_bind_array_buffer(a1->vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, position)); // Pos + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, color)); // Color + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord0 + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(glitter_buffer, uv)); // TexCoord1 + gl_state_bind_array_buffer(0); + const GLenum mode = a1->type == GLITTER_PARTICLE_LINE ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; const size_t count = a1->vec_key.end - a1->vec_key.begin; for (size_t i = 0; i < count; i++) - shader_draw_arrays(&shaders_aft, + shader_draw_arrays(&shaders_ft, mode, a1->vec_key.begin[i], a1->vec_val.begin[i]); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(3); + glDisableVertexAttribArray(8); + glDisableVertexAttribArray(9); + } break; } - gl_state_bind_vertex_array(0); gl_state_disable_blend(); gl_state_disable_cull_face(); gl_state_disable_depth_test(); @@ -352,12 +368,6 @@ void glitter_x_render_group_delete_buffers(glitter_render_group* a1, a1->vbo = 0; } - if (a1->vao) { - glDeleteVertexArrays(1, &a1->vao); - a1->vao = 0; - } - free(a1->buffer); - if (!a2 && a1->elements) { glitter_x_render_group_free(a1); free(a1->elements); @@ -434,12 +444,11 @@ void glitter_x_render_group_update(glitter_render_group* rg, ctrl--; } rg->frame += delta_frame; - rg->update_data |= delta_frame != 0.0f; } void glitter_x_render_group_dispose(glitter_render_group* rg) { - vector_int32_t_free(&rg->vec_key); - vector_int32_t_free(&rg->vec_val); + vector_int32_t_free(&rg->vec_key, 0); + vector_int32_t_free(&rg->vec_val, 0); glitter_x_render_group_delete_buffers(rg, false); free(rg); } @@ -476,9 +485,6 @@ static void glitter_x_render_group_calc_draw_line(glitter_render_group* a1) { vec3 scale; vec3 pos; vec3 pos_diff; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; glitter_buffer* buf; size_t disp; @@ -486,9 +492,8 @@ static void glitter_x_render_group_calc_draw_line(glitter_render_group* a1) { glitter_locus_history* hist; glitter_locus_history_data* hist_data; size_t index; - uint32_t temp; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; for (count = 0, i = a1->ctrl, elem = a1->elements; i > 0; i--, elem++) { @@ -505,30 +510,27 @@ static void glitter_x_render_group_calc_draw_line(glitter_render_group* a1) { if (!count || count > a1->max_count) return; + has_scale = false; scale = vec3_null; - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { glitter_x_render_group_get_emitter_scale(a1, &scale); - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; mat4_normalize_rotation(&a1->mat, &a1->mat_draw); } else a1->mat_draw = mat4_identity; - has_scale = has_scale_x || has_scale_y || has_scale_z; - - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; - vector_int32_t_clear(&a1->vec_key); - vector_int32_t_clear(&a1->vec_val); + vector_int32_t_clear(&a1->vec_key, 0); + vector_int32_t_clear(&a1->vec_val, 0); for (i = a1->ctrl, index = 0; i > 0; elem++) { if (!elem->alive) continue; @@ -545,31 +547,25 @@ static void glitter_x_render_group_calc_draw_line(glitter_render_group* a1) { vec3_mult(pos_diff, scale, pos_diff); vec3_add(pos, pos_diff, buf->position); buf->uv = vec2_null; - buf->color = *(vec3*)&hist_data->color; - buf->alpha = hist_data->color.w; + buf->color = hist_data->color; } else for (j = 0, hist_data = hist->data.begin; hist_data != hist->data.end; j++, buf++, hist_data++) { buf->position = hist_data->translation; buf->uv = vec2_null; - buf->color = *(vec3*)&hist_data->color; - buf->alpha = hist_data->color.w; + buf->color = hist_data->color; } if (j > 0) { disp += j; - temp = (uint32_t)index; - vector_int32_t_push_back(&a1->vec_key, &temp); - temp = (uint32_t)j; - vector_int32_t_push_back(&a1->vec_val, &temp); + *vector_int32_t_reserve_back(&a1->vec_key) = (uint32_t)index; + *vector_int32_t_reserve_back(&a1->vec_val) = (uint32_t)j; index += j; } } a1->disp = disp; - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1) { @@ -577,9 +573,6 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 size_t j; size_t count; vec3 scale; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; glitter_render_element* elem; glitter_locus_history* hist; @@ -592,7 +585,6 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 vec3 pos; vec3 pos_diff; size_t index; - uint32_t temp; float_t v00; float_t v01; vec3 x_vec; @@ -600,7 +592,7 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 mat4 mat; mat3 model_mat; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; for (count = 0, i = a1->ctrl, elem = a1->elements; i > 0; i--, elem++) { @@ -627,19 +619,17 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 else a1->mat_draw = mat4_identity; - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; + has_scale = false; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { mat4_get_scale(&a1->mat, &scale); if (a1->flags & GLITTER_PARTICLE_SCALE) x_vec.x = scale.x; vec3_sub(scale, vec3_identity, scale); - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; mat4_normalize_rotation(&a1->mat, &mat); mat3_from_mat4(&mat, &model_mat); @@ -647,15 +637,14 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 else model_mat = mat3_identity; - has_scale = has_scale_x || has_scale_y || has_scale_z; - mat3_mult_vec(&GPM_VAL->cam_inv_view_mat3, &x_vec, &x_vec); - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; - vector_int32_t_clear(&a1->vec_key); - vector_int32_t_clear(&a1->vec_val); + vector_int32_t_clear(&a1->vec_key, 0); + vector_int32_t_clear(&a1->vec_val, 0); for (i = a1->ctrl, index = 0; i > 0; elem++) { if (!elem->alive) continue; @@ -689,31 +678,25 @@ static void glitter_x_render_group_calc_draw_locus(GPM, glitter_render_group* a1 vec3_add(buf[0].position, pos, buf[0].position); buf[0].uv.x = uv_u; buf[0].uv.y = uv_v_2nd + (float_t)j * uv_v_scale; - buf[0].color = *(vec3*)&hist_data->color; - buf[0].alpha = hist_data->color.w; + buf[0].color = hist_data->color; vec3_mult_scalar(x_vec, v01, buf[1].position); vec3_add(buf[1].position, pos, buf[1].position); buf[1].uv.x = uv_u_2nd; buf[1].uv.y = uv_v_2nd + (float_t)j * uv_v_scale; - buf[1].color = *(vec3*)&hist_data->color; - buf[1].alpha = hist_data->color.w; + buf[1].color = hist_data->color; } if (j > 0) { disp += j; - temp = (uint32_t)index; - vector_int32_t_push_back(&a1->vec_key, &temp); - temp = (uint32_t)(j * 2); - vector_int32_t_push_back(&a1->vec_val, &temp); + *vector_int32_t_reserve_back(&a1->vec_key) = (uint32_t)index; + *vector_int32_t_reserve_back(&a1->vec_val) = (uint32_t)(j * 2); index += j * 2; } } a1->disp = disp; - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp * 2), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_x_render_group_calc_draw_mesh(GPM, glitter_render_group* a1) { @@ -745,15 +728,12 @@ static void glitter_x_render_group_calc_draw_mesh(GPM, glitter_render_group* a1) if (a1->object_name_hash == hash_murmurhash_empty || a1->object_name_hash == 0xFFFFFFFF) return; - elem = a1->elements; - emit_scale = vec3_null; - - emitter_local = false; has_scale = false; - + emitter_local = false; + emit_scale = vec3_null; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { model_mat = a1->mat; - mat4_normalize_rotation(&a1->mat, &view_mat); + mat4_normalize_rotation(&model_mat, &view_mat); mat4_mult(&view_mat, &GPM_VAL->cam_view, &view_mat); mat4_inverse(&view_mat, &inv_view_mat); @@ -777,6 +757,7 @@ static void glitter_x_render_group_calc_draw_mesh(GPM, glitter_render_group* a1) mat4_inverse(&view_mat, &inv_view_mat); draw_local = true; } + mat4_mult(&view_mat, &GPM_VAL->cam_inv_view, &a1->mat_draw); dir_mat = mat4_identity; up_vec = (vec3){ 0.0f, 0.0f, 1.0f }; @@ -806,7 +787,7 @@ static void glitter_x_render_group_calc_draw_mesh(GPM, glitter_render_group* a1) case GLITTER_DIRECTION_X_AXIS: mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; - case GLITTER_DIRECTION_BILLBOARD_Y_ONLY: + case GLITTER_DIRECTION_BILLBOARD_Y_AXIS: mat4_rotate_y(GPM_VAL->cam_rotation_y, &dir_mat); break; case GLITTER_DIRECTION_EMITTER_ROTATION: @@ -859,11 +840,65 @@ static void glitter_x_render_group_calc_draw_mesh(GPM, glitter_render_group* a1) mat4_rot(&mat, rot.x, rot.y, rot.z, &mat); mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &mat); - mat4_translate(elem->uv_scroll.x, elem->uv_scroll.y, 0.0f, &uv_mat[0]); - mat4_translate(elem->uv_scroll_2nd.x, elem->uv_scroll_2nd.y, 0.0f, &uv_mat[1]); - if (glitter_render_mesh_update_func) - glitter_render_mesh_update_func(elem, &a1->particle->data.data.mesh, &elem->color, &mat, uv_mat); - disp++; + mat4_translate(elem->uv_scroll.x, -elem->uv_scroll.y, 0.0f, &uv_mat[0]); + mat4_translate(elem->uv_scroll_2nd.x, -elem->uv_scroll_2nd.y, 0.0f, &uv_mat[1]); + + render_context* rctx = GPM_VAL->rctx; + object_data* object_data = &rctx->object_data; + + glitter_particle* particle = a1->particle->data.particle; + object_info object_info; + object_info.set_id = (uint32_t)particle->data.mesh.object_set_name_hash; + object_info.id = (uint32_t)particle->data.mesh.object_name_hash; + object* obj = object_storage_get_object(object_info); + if (!obj) + continue; + + object_data->texture_pattern_count = 0; + int32_t ttc = 0; + texture_transform_struct* tt = object_data->texture_transform_array; + for (int32_t i = 0; i < obj->meshes_count; i++) { + object_mesh* mesh = &obj->meshes[i]; + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; + object_material* material = &obj->materials[sub_mesh->material_index].material; + + for (int32_t k = 0, l = 0; k < 8; k++) { + object_material_texture* texture = &material->textures[k]; + if (texture->texture_flags.type != OBJECT_MATERIAL_TEXTURE_COLOR) + continue; + + tt->id = texture->texture_id; + mat4_to_mat4u(&uv_mat[l], &tt->mat); + ttc++; + tt++; + + if (++l == 2 || ttc == 24) + break; + } + + if (ttc == 24) + break; + } + + if (ttc == 24) + break; + } + object_data->texture_transform_count = ttc; + + if (a1->flags & GLITTER_PARTICLE_LOCAL) + mat4_mult(&mat, &GPM_VAL->cam_inv_view, &mat); + + if (!GPM_VAL->no_draw) { + vec4u color = elem->color; + if (draw_task_add_draw_object_by_object_info_color(rctx, &mat, + object_info, color.x, color.y, color.z, color.w)) + disp++; + } + elem->mat_draw = mat; + + object_data->texture_pattern_count = 0; + object_data->texture_transform_count = 0; } } a1->disp = disp; @@ -875,7 +910,7 @@ static void glitter_x_render_group_calc_draw_quad(GPM, glitter_render_group* a1) mat4 view_mat; mat4 inv_view_mat; - if (!a1->elements || !a1->buffer || a1->ctrl <= 0) + if (!a1->elements || !a1->vbo || a1->ctrl <= 0) return; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { @@ -916,7 +951,7 @@ static void glitter_x_render_group_calc_draw_quad(GPM, glitter_render_group* a1) case GLITTER_DIRECTION_X_AXIS: mat4_rotate_x((float_t)-M_PI_2, &dir_mat); break; - case GLITTER_DIRECTION_BILLBOARD_Y_ONLY: + case GLITTER_DIRECTION_BILLBOARD_Y_AXIS: mat4_rotate_y(GPM_VAL->cam_rotation_y, &dir_mat); break; default: @@ -926,20 +961,14 @@ static void glitter_x_render_group_calc_draw_quad(GPM, glitter_render_group* a1) switch (a1->draw_type) { case GLITTER_DIRECTION_PREV_POSITION: - case GLITTER_DIRECTION_PREV_POSITION_DUP: - glitter_x_render_group_calc_draw_quad_direction_rotation(a1, &model_mat); - break; case GLITTER_DIRECTION_EMIT_POSITION: + case GLITTER_DIRECTION_PREV_POSITION_DUP: glitter_x_render_group_calc_draw_quad_direction_rotation(a1, &model_mat); break; default: glitter_x_render_group_calc_draw_quad_normal(GPM_VAL, a1, &model_mat, &dir_mat); break; } - - glBindBuffer(GL_ARRAY_BUFFER, a1->vbo); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(glitter_buffer) * a1->disp * 4), a1->buffer, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); } static void glitter_x_render_group_calc_draw_quad_normal(GPM, @@ -952,9 +981,6 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, size_t disp; glitter_buffer* buf; vec3 z_offset_dir; - bool has_scale_x; - bool has_scale_y; - bool has_scale_z; bool has_scale; vec3 pos; bool use_z_offset; @@ -998,9 +1024,7 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, } } - has_scale_x = false; - has_scale_y = false; - has_scale_z = false; + has_scale = false; emitter_local = false; scale = vec3_null; if (a1->flags & GLITTER_PARTICLE_EMITTER_LOCAL) { @@ -1009,17 +1033,15 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, x_vec.x = scale.x; y_vec.y = scale.y; } - if (!(has_scale_x = fabsf(scale.x) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.x) > 0.000001f ? true : false)) scale.x = 0.0f; - if (!(has_scale_y = fabsf(scale.y) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.y) > 0.000001f ? true : false)) scale.y = 0.0f; - if (!(has_scale_z = fabsf(scale.z) > 0.000001f ? true : false)) + if (!(has_scale |= fabsf(scale.z) > 0.000001f ? true : false)) scale.z = 0.0f; emitter_local = true; } - has_scale = has_scale_x || has_scale_y || has_scale_z; - if (glitter_x_render_group_get_ext_anim_scale(a1, &ext_scale)) { vec2_add(*(vec2*)&ext_scale, vec2_identity, *(vec2*)&ext_scale); x_vec.x *= ext_scale.x; @@ -1036,7 +1058,8 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, mat4_mult_vec3(&inv_model_mat, &x_vec, &x_vec); mat4_mult_vec3(&inv_model_mat, &y_vec, &y_vec); - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; if (a1->draw_type == GLITTER_DIRECTION_PARTICLE_ROTATION) @@ -1102,8 +1125,7 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, mat3_mult_vec(&ptc_rot, &x_vec_rot, &x_vec_rot); vec3_add(x_vec_rot, pos, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } @@ -1171,13 +1193,14 @@ static void glitter_x_render_group_calc_draw_quad_normal(GPM, vec3_add(x_vec_rot, y_vec_rot, x_vec_rot); vec3_add(x_vec_rot, pos, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } } a1->disp = disp; + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_x_render_group_calc_draw_quad_direction_rotation(glitter_render_group* a1, @@ -1239,7 +1262,8 @@ static void glitter_x_render_group_calc_draw_quad_direction_rotation(glitter_ren && glitter_x_render_group_get_emitter_scale(a1, &scale)) use_scale = a1->flags & GLITTER_PARTICLE_SCALE ? true : false; - buf = a1->buffer; + gl_state_bind_array_buffer(a1->vbo); + buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); elem = a1->elements; disp = 0; for (i = a1->ctrl, j_max = 1024; i > 0; i -= j_max) { @@ -1303,13 +1327,14 @@ static void glitter_x_render_group_calc_draw_quad_direction_rotation(glitter_ren vec3_add(x_vec_rot, y_vec_rot, pos_add_rot); vec3_add(pos, pos_add_rot, buf->position); vec2_add(base_uv, uv_add[k], buf->uv); - buf->color = *(vec3*)&elem->color; - buf->alpha = elem->color.w; + buf->color = elem->color; } disp++; } } a1->disp = disp; + glUnmapBuffer(GL_ARRAY_BUFFER); + gl_state_bind_array_buffer(0); } static void glitter_x_render_group_calc_draw_locus_set_pivot(glitter_pivot pivot, diff --git a/src/CRE/GlitterX/render_scene_x.c b/src/CRE/GlitterX/render_scene_x.c index 7216d824..c4122e50 100644 --- a/src/CRE/GlitterX/render_scene_x.c +++ b/src/CRE/GlitterX/render_scene_x.c @@ -58,7 +58,7 @@ void glitter_x_render_scene_calc_draw(GPM, glitter_render_scene* rs) { } } -void glitter_x_render_scene_draw(GPM, glitter_render_scene* rs, alpha_pass_type alpha) { +void glitter_x_render_scene_draw(GPM, glitter_render_scene* rs, draw_pass_3d_type alpha) { glitter_render_group** i; glitter_render_group* rg; diff --git a/src/CRE/GlitterX/render_scene_x.h b/src/CRE/GlitterX/render_scene_x.h index d90a97f8..f580a5a3 100644 --- a/src/CRE/GlitterX/render_scene_x.h +++ b/src/CRE/GlitterX/render_scene_x.h @@ -10,7 +10,7 @@ extern void glitter_x_render_scene_append(glitter_render_scene* rs, glitter_render_group* rg); extern void glitter_x_render_scene_calc_draw(GPM, glitter_render_scene* rs); -extern void glitter_x_render_scene_draw(GPM, glitter_render_scene* rs, alpha_pass_type alpha); +extern void glitter_x_render_scene_draw(GPM, glitter_render_scene* rs, draw_pass_3d_type alpha); extern void glitter_x_render_scene_free(glitter_render_scene* rs); extern void glitter_x_render_scene_update(glitter_render_scene* rs, float_t delta_frame, bool copy_mats); diff --git a/src/CRE/auth_3d.c b/src/CRE/auth_3d.c new file mode 100644 index 00000000..d5858ec8 --- /dev/null +++ b/src/CRE/auth_3d.c @@ -0,0 +1,3481 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "auth_3d.h" +#include "../KKdLib/interpolation.h" +#include "../KKdLib/str_utils.h" +#include "draw_task.h" +#include "object.h" + +typedef a3da_ambient auth_3d_ambient_file; +typedef a3da_camera_auxiliary auth_3d_camera_auxiliary_file; +typedef a3da_camera_root auth_3d_camera_root_file; +typedef a3da_camera_root_view_point auth_3d_camera_root_view_point_file; +typedef a3da_chara auth_3d_chara_file; +typedef a3da_curve auth_3d_curve_file; +typedef a3da_dof auth_3d_dof_file; +typedef a3da_event auth_3d_event_file; +typedef a3da_fog auth_3d_fog_file; +typedef a3da_key auth_3d_key_file; +typedef a3da_light auth_3d_light_file; +typedef a3da_m_object_hrc auth_3d_m_object_hrc_file; +typedef a3da_object_instance auth_3d_object_instance_file; +typedef a3da_material_list auth_3d_material_list_file; +typedef a3da_model_transform auth_3d_model_transform_file; +typedef a3da_object auth_3d_object_file; +typedef a3da_object_hrc auth_3d_object_hrc_file; +typedef a3da_object_node auth_3d_object_node_file; +typedef a3da_object_texture_pattern auth_3d_object_texture_pattern_file; +typedef a3da_object_texture_transform auth_3d_object_texture_transform_file; +typedef a3da_play_control auth_3d_play_control_file; +typedef a3da_point auth_3d_point_file; +typedef a3da_post_process auth_3d_post_process_file; +typedef a3da_rgba auth_3d_rgba_file; +typedef a3da_vec3 auth_3d_vec3_file; + +vector_func(auth_3d_ambient) +vector_func(auth_3d_model_transform) +vector_func(auth_3d_camera_root) +vector_func(auth_3d_chara) +vector_func(auth_3d_curve) +vector_func(auth_3d_event) +vector_func(auth_3d_fog) +vector_func(auth_3d_light) +vector_func(auth_3d_m_object_hrc) +vector_func(auth_3d_object_instance) +vector_func(auth_3d_material_list) +vector_func(auth_3d_object) +vector_func(auth_3d_object_hrc) +vector_func(auth_3d_object_node) +vector_func(auth_3d_object_texture_pattern) +vector_func(auth_3d_object_texture_transform) +vector_func(auth_3d_point) +vector_func(ptr_auth_3d_m_object_hrc) +vector_func(ptr_auth_3d_object) +vector_func(ptr_auth_3d_object_hrc) + +static kft3* auth_3d_key_find_keyframe(auth_3d_key* data, float_t frame); +static float_t auth_3d_key_get_value(auth_3d_key* data, float_t frame); +static float_t auth_3d_key_interpolate(auth_3d_key* data, float_t frame); +static float_t auth_3d_interpolate_value(auth_3d_key_type type, + float_t frame, kft3* curr_key, kft3* next_key); +static void auth_3d_key_load(auth_3d* auth, auth_3d_key* k, auth_3d_key_file* kf); +static void auth_3d_rgba_get_value(auth_3d_rgba* rgba, float_t frame); +static void auth_3d_rgba_load(auth_3d* auth, auth_3d_rgba* rgba, auth_3d_rgba_file* rgbaf); +static void auth_3d_vec3_get_value(auth_3d_vec3* vec, float_t frame, vec3* value); +static void auth_3d_vec3_load(auth_3d* auth, auth_3d_vec3* vec, auth_3d_vec3_file* vecf); +static void auth_3d_model_transform_get_value(auth_3d_model_transform* mt, float_t frame); +static void auth_3d_model_transform_load(auth_3d* auth, auth_3d_model_transform* mt, auth_3d_model_transform_file* mtf); +static void auth_3d_model_transform_set_mat(auth_3d_model_transform* mt, mat4* parent_mat); + +static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, object_info obj_info); +static mat4* auth_3d_get_auth_3d_object_hrc_bone_mats(auth_3d* auth, size_t index); +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, object_info obj_info); + +static void auth_3d_ambient_data_set(auth_3d_ambient* a, render_context* rctx); +static void auth_3d_ambient_get_value(auth_3d_ambient* a, float_t frame); +static void auth_3d_ambient_load(auth_3d* auth, auth_3d_ambient_file* af); +static void auth_3d_camera_auxiliary_data_set(auth_3d_camera_auxiliary* ca, render_context* rctx); +static void auth_3d_camera_auxiliary_get_value(auth_3d_camera_auxiliary* ca, float_t frame); +static void auth_3d_camera_auxiliary_load(auth_3d* auth, auth_3d_camera_auxiliary_file* caf); +static void auth_3d_camera_auxiliary_restore_prev_value(auth_3d_camera_auxiliary* ca, render_context* rctx); +static void auth_3d_camera_root_data_set(auth_3d_camera_root* cr, + bool left_right_reverse, mat4* mat, render_context* rctx); +static void auth_3d_camera_root_get_value(auth_3d_camera_root* cr, float_t frame, mat4* mat); +static void auth_3d_camera_root_load(auth_3d* auth, auth_3d_camera_root_file* crf); +static void auth_3d_camera_root_view_point_load(auth_3d* auth, auth_3d_camera_root* cr, + auth_3d_camera_root_view_point_file* crvpf); +static void auth_3d_chara_data_set(auth_3d_chara* c, mat4* parent_mat, render_context* rctx); +static void auth_3d_chara_get_value(auth_3d_chara* c, float_t frame); +static void auth_3d_chara_load(auth_3d* auth, auth_3d_chara_file* cf); +static void auth_3d_curve_get_value(auth_3d_curve* c, float_t frame); +static void auth_3d_curve_load(auth_3d* auth, auth_3d_curve_file* cf); +static void auth_3d_dof_data_set(auth_3d_dof* d, render_context* rctx); +static void auth_3d_dof_get_value(auth_3d_dof* d, float_t frame); +static void auth_3d_dof_load(auth_3d* auth, auth_3d_dof_file* df); +static void auth_3d_dof_restore_prev_value(auth_3d_dof* d, render_context* rctx); +static void auth_3d_event_load(auth_3d* auth, auth_3d_event_file* ef); +static void auth_3d_fog_data_set(auth_3d_fog* f, render_context* rctx); +static void auth_3d_fog_get_value(auth_3d_fog* f, float_t frame); +static void auth_3d_fog_load(auth_3d* auth, auth_3d_fog_file* ff); +static void auth_3d_fog_restore_prev_value(auth_3d_fog* f, render_context* rctx); +static void auth_3d_light_data_set(auth_3d_light* l, render_context* rctx); +static void auth_3d_light_get_value(auth_3d_light* l, float_t frame); +static void auth_3d_light_load(auth_3d* auth, auth_3d_light_file* lf); +static void auth_3d_light_restore_prev_value(auth_3d_light* l, render_context* rctx); +static void auth_3d_m_object_hrc_get_mat(auth_3d_m_object_hrc* moh, mat4* mat); +static void auth_3d_m_object_hrc_get_value(auth_3d_m_object_hrc* moh, float_t frame); +static void auth_3d_m_object_hrc_load(auth_3d* auth, + auth_3d_m_object_hrc_file* mohf, object_database* obj_db); +static void auth_3d_m_object_hrc_data_set(auth_3d_m_object_hrc* moh, auth_3d* auth, render_context* rctx); +static void auth_3d_m_object_hrc_list_get_value(auth_3d_m_object_hrc* moh, mat4* parent_mat); +static void auth_3d_m_object_hrc_nodes_mat_mult(auth_3d_m_object_hrc* moh); +static void auth_3d_material_list_load(auth_3d* auth, auth_3d_material_list_file* mlf); +static void auth_3d_object_data_set(auth_3d_object* o, auth_3d* auth, render_context* rctx); +static void auth_3d_object_get_value(auth_3d_object* o, float_t frame); +static void auth_3d_object_load(auth_3d* auth, auth_3d_object_file* of, + object_database* obj_db, texture_database* tex_db); +static void auth_3d_object_curve_get_value(auth_3d_object_curve* oc, float_t frame); +static void auth_3d_object_curve_load(auth_3d* auth, auth_3d_object_curve* curve, + string* name, float_t frame_offset); +static void auth_3d_object_list_get_value(auth_3d_object* o, mat4* parent_mat); +static void auth_3d_object_hrc_data_set(auth_3d_object_hrc* oh, auth_3d* auth, render_context* rctx); +static void auth_3d_object_hrc_get_value(auth_3d_object_hrc* oh, float_t frame); +static void auth_3d_object_hrc_load(auth_3d* auth, + auth_3d_object_hrc_file* ohf, object_database* obj_db); +static void auth_3d_object_hrc_list_get_value(auth_3d_object_hrc* oh, mat4* mat); +static void auth_3d_object_hrc_nodes_mat_mult(auth_3d_object_hrc* oh, mat4* mat); +static void auth_3d_object_instance_load(auth_3d* auth, auth_3d_m_object_hrc* moh, + auth_3d_object_instance_file* oif, object_database* obj_db); +static void auth_3d_object_model_transform_get_value(auth_3d_object_model_transform* obj_mt, float_t frame); +static void auth_3d_object_model_transform_load(auth_3d* auth, + auth_3d_object_model_transform* omt, auth_3d_model_transform_file* mtf); +static void auth_3d_object_model_transform_mat_mult(auth_3d_object_model_transform* obj_mt, mat4* mat); +static void auth_3d_object_model_transform_set_mat_inner(auth_3d_object_model_transform* obj_mt); +static void auth_3d_object_node_load(auth_3d* auth, + vector_auth_3d_object_node* von, auth_3d_object_node_file* onf); +static void auth_3d_object_texture_pattern_get_value( + auth_3d_object_texture_pattern* otp, float_t frame); +static void auth_3d_object_texture_pattern_load(auth_3d* auth, auth_3d_object* o, + auth_3d_object_texture_pattern_file* otpf, texture_database* tex_db); +static void auth_3d_object_texture_transform_get_value( + auth_3d_object_texture_transform* ott, float_t frame); +static void auth_3d_object_texture_transform_load(auth_3d* auth, auth_3d_object* o, + auth_3d_object_texture_transform_file* ottf, texture_database* tex_db); +static void auth_3d_play_control_load(auth_3d* auth, auth_3d_play_control_file* pcf); +static void auth_3d_point_data_set(auth_3d_point* p, mat4* parent_mat, render_context* rctx); +static void auth_3d_point_get_value(auth_3d_point* p, float_t frame); +static void auth_3d_point_load(auth_3d* auth, auth_3d_point_file* pf); +static void auth_3d_post_process_data_set(auth_3d_post_process* pp, render_context* rctx); +static void auth_3d_post_process_get_value(auth_3d_post_process* pp, float_t frame); +static void auth_3d_post_process_load(auth_3d* auth, auth_3d_post_process_file* ppf); +static void auth_3d_post_process_restore_prev_value(auth_3d_post_process* pp, render_context* rctx); + +auth_3d_data_struct auth_3d_data; +static int16_t auth_3d_load_counter; + +void auth_3d_init(auth_3d* auth) { + if (!auth) + return; + + memset(auth, 0, sizeof(auth_3d)); +} + +void auth_3d_data_set(auth_3d* auth, mat4* mat, render_context* rctx) { + if (!auth) + return; + + for (auth_3d_ambient* i = auth->ambient.begin; i != auth->ambient.end; i++) + auth_3d_ambient_data_set(i, rctx); + + for (auth_3d_camera_root* i = auth->camera_root.begin; i != auth->camera_root.end; i++) { + auth_3d_camera_root_data_set(i, auth->left_right_reverse, mat, rctx); + break; + } + + for (auth_3d_chara* i = auth->chara.begin; i != auth->chara.end; i++) + auth_3d_chara_data_set(i, mat, rctx); + + for (auth_3d_fog* i = auth->fog.begin; i != auth->fog.end; i++) + auth_3d_fog_data_set(i, rctx); + + for (auth_3d_light* i = auth->light.begin; i != auth->light.end; i++) + auth_3d_light_data_set(i, rctx); + + for (auth_3d_point* i = auth->point.begin; i != auth->point.end; i++) + auth_3d_point_data_set(i, mat, rctx); + + for (ptr_auth_3d_object* i = auth->object_list.begin; i != auth->object_list.end; i++) + auth_3d_object_data_set(*i, auth, rctx); + + for (ptr_auth_3d_object_hrc* i = auth->object_hrc_list.begin; i != auth->object_hrc_list.end; i++) + auth_3d_object_hrc_data_set(*i, auth, rctx); + + for (ptr_auth_3d_m_object_hrc* i = auth->m_object_hrc_list.begin; + i != auth->m_object_hrc_list.end; i++) + auth_3d_m_object_hrc_data_set(*i, auth, rctx); + + auth_3d_camera_auxiliary_data_set(&auth->camera_auxiliary, rctx); + auth_3d_dof_data_set(&auth->dof, rctx); + auth_3d_post_process_data_set(&auth->post_process, rctx); +} + +void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t delta_frame) { + if (!auth || !auth->enable) + return; + + bool set = false; + while (true) { + if (auth->frame_changed) { + auth->frame_changed = false; + auth->frame = auth->set_frame; + auth->ended = false; + if (auth->max_frame >= 0.0f && auth->frame >= auth->max_frame) + auth->max_frame = -1.0f; + } + else if (!auth->paused) { + auth->frame += delta_frame; + if (auth->max_frame >= 0.0f && auth->frame > auth->max_frame) + auth->frame = auth->max_frame; + } + + float_t frame = auth->frame; + + auth->frame_int = (int32_t)frame; + frame = (float_t)auth->frame_int; + + for (auth_3d_ambient* i = auth->ambient.begin; i != auth->ambient.end; i++) + auth_3d_ambient_get_value(i, frame); + + for (auth_3d_chara* i = auth->chara.begin; i != auth->chara.end; i++) + auth_3d_chara_get_value(i, frame); + + if (auth->camera_root_update) + for (auth_3d_camera_root* i = auth->camera_root.begin; i != auth->camera_root.end; i++) + auth_3d_camera_root_get_value(i, frame, mat); + + for (auth_3d_chara* i = auth->chara.begin; i != auth->chara.end; i++) + auth_3d_chara_get_value(i, frame); + + for (auth_3d_curve* i = auth->curve.begin; i != auth->curve.end; i++) + auth_3d_curve_get_value(i, frame); + + for (auth_3d_fog* i = auth->fog.begin; i != auth->fog.end; i++) + auth_3d_fog_get_value(i, frame); + + for (auth_3d_light* i = auth->light.begin; i != auth->light.end; i++) + auth_3d_light_get_value(i, frame); + + for (auth_3d_object* i = auth->object.begin; i != auth->object.end; i++) + auth_3d_object_get_value(i, frame); + + for (auth_3d_object_hrc* i = auth->object_hrc.begin; i != auth->object_hrc.end; i++) + auth_3d_object_hrc_get_value(i, frame); + + for (auth_3d_m_object_hrc* i = auth->m_object_hrc.begin; i != auth->m_object_hrc.end; i++) + auth_3d_m_object_hrc_get_value(i, frame); + + for (auth_3d_point* i = auth->point.begin; i != auth->point.end; i++) + auth_3d_point_get_value(i, frame); + + for (ptr_auth_3d_object* i = auth->object_list.begin; i != auth->object_list.end; i++) + auth_3d_object_list_get_value(*i, mat); + + for (ptr_auth_3d_object_hrc* i = auth->object_hrc_list.begin; i != auth->object_hrc_list.end; i++) + auth_3d_object_hrc_list_get_value(*i, mat); + + for (ptr_auth_3d_m_object_hrc* i = auth->m_object_hrc_list.begin; + i != auth->m_object_hrc_list.end; i++) + auth_3d_m_object_hrc_list_get_value(*i, mat); + + auth_3d_camera_auxiliary_get_value(&auth->camera_auxiliary, frame); + auth_3d_dof_get_value(&auth->dof, frame); + auth_3d_post_process_get_value(&auth->post_process, frame); + + auth_3d_model_transform_get_value(&auth->dof.model_transform, frame); + if (set || !auth->repeat || auth->last_frame > auth->frame) + break; + + auth->set_frame = auth->frame - auth->frame + auth->frame_offset; + auth->frame_changed = true; + set = true; + } + + bool ended = auth->play_control.size <= auth->frame; + if (ended && auth->ended != ended) { + auth->paused = true; + if (auth->once) + auth->enable = false; + } + auth->ended = ended; +} + +void auth_3d_unload(auth_3d* auth, render_context* rctx) { + if (!auth) + return; + + auth_3d_camera_auxiliary_restore_prev_value(&auth->camera_auxiliary, rctx); + for (auth_3d_light* i = auth->light.begin; i != auth->light.end; i++) + auth_3d_light_restore_prev_value(i, rctx); + for (auth_3d_fog* i = auth->fog.begin; i != auth->fog.end; i++) + auth_3d_fog_restore_prev_value(i, rctx); + auth_3d_dof_restore_prev_value(&auth->dof, rctx); + auth_3d_post_process_restore_prev_value(&auth->post_process, rctx); + auth_3d_free(auth); +} + +void auth_3d_load(auth_3d* auth, a3da* auth_file, + object_database* obj_db, texture_database* tex_db) { + if (!auth || !auth_file) + return; + + auth_3d_camera_auxiliary_load(auth, &auth_file->camera_auxiliary); + auth_3d_dof_load(auth, &auth_file->dof); + auth_3d_play_control_load(auth, &auth_file->play_control); + auth_3d_post_process_load(auth, &auth_file->post_process); + + auth->frame = -1; + auth->max_frame = auth->play_control.size; + + auth->enable = true; + auth->camera_root_update = true; + auth->repeat = true; + auth->ended = false; + auth->left_right_reverse = false; + auth->once = false; + + auth->frame = 0.0f; + auth->set_frame = 0.0f; + auth->max_frame = auth->play_control.size; + auth->frame_changed = false; + auth->frame_offset = 0.0f; + auth->last_frame = auth->play_control.size; + auth->paused = false; + + if (auth_file->ambient.end - auth_file->ambient.begin > 0) { + vector_auth_3d_ambient* va = &auth->ambient; + vector_a3da_ambient* vaf = &auth_file->ambient; + vector_auth_3d_ambient_reserve(va, vaf->end - vaf->begin); + for (auth_3d_ambient_file* i = vaf->begin; i != vaf->end; i++) + auth_3d_ambient_load(auth, i); + } + + if (auth_file->auth_2d.end - auth_file->auth_2d.begin > 0) { + vector_string* va2 = &auth->auth_2d; + vector_string* va2f = &auth_file->auth_2d; + vector_string_reserve(va2, va2f->end - va2f->begin); + for (string* i = va2f->begin; i != va2f->end; i++) { + string* m = vector_string_reserve_back(va2f); + string_copy(i, m); + } + } + + if (auth_file->camera_root.end - auth_file->camera_root.begin > 0) { + vector_auth_3d_camera_root* vcr = &auth->camera_root; + vector_a3da_camera_root* vcrf = &auth_file->camera_root; + vector_auth_3d_camera_root_reserve(vcr, vcrf->end - vcrf->begin); + for (auth_3d_camera_root_file* i = vcrf->begin; i != vcrf->end; i++) + auth_3d_camera_root_load(auth, i); + } + + if (auth_file->chara.end - auth_file->chara.begin > 0) { + vector_auth_3d_chara* vc = &auth->chara; + vector_a3da_chara* vcf = &auth_file->chara; + vector_auth_3d_chara_reserve(vc, vcf->end - vcf->begin); + for (auth_3d_chara_file* i = vcf->begin; i != vcf->end; i++) + auth_3d_chara_load(auth, i); + } + + if (auth_file->curve.end - auth_file->curve.begin > 0) { + vector_auth_3d_curve* vc = &auth->curve; + vector_a3da_curve* vcf = &auth_file->curve; + vector_auth_3d_curve_reserve(vc, vcf->end - vcf->begin); + for (auth_3d_curve_file* i = vcf->begin; i != vcf->end; i++) + auth_3d_curve_load(auth, i); + } + + if (auth_file->event.end - auth_file->event.begin > 0) { + vector_auth_3d_event* ve = &auth->event; + vector_a3da_event* vef = &auth_file->event; + vector_auth_3d_event_reserve(ve, vef->end - vef->begin); + for (auth_3d_event_file* i = vef->begin; i != vef->end; i++) + auth_3d_event_load(auth, i); + } + + if (auth_file->fog.end - auth_file->fog.begin > 0) { + vector_auth_3d_fog* vf = &auth->fog; + vector_a3da_fog* vff = &auth_file->fog; + vector_auth_3d_fog_reserve(vf, vff->end - vff->begin); + for (auth_3d_fog_file* i = vff->begin; i != vff->end; i++) + auth_3d_fog_load(auth, i); + } + + if (auth_file->light.end - auth_file->light.begin > 0) { + vector_auth_3d_light* vl = &auth->light; + vector_a3da_light* vlf = &auth_file->light; + vector_auth_3d_light_reserve(vl, vlf->end - vlf->begin); + for (auth_3d_light_file* i = vlf->begin; i != vlf->end; i++) + auth_3d_light_load(auth, i); + } + + if (auth_file->m_object_hrc.end - auth_file->m_object_hrc.begin > 0) { + vector_auth_3d_m_object_hrc* vmoh = &auth->m_object_hrc; + vector_a3da_m_object_hrc* vmohf = &auth_file->m_object_hrc; + vector_auth_3d_m_object_hrc_reserve(vmoh, vmohf->end - vmohf->begin); + for (auth_3d_m_object_hrc_file* i = vmohf->begin; i != vmohf->end; i++) + auth_3d_m_object_hrc_load(auth, i, obj_db); + } + + if (auth_file->material_list.end - auth_file->material_list.begin > 0) { + vector_auth_3d_material_list* vml = &auth->material_list; + vector_a3da_material_list* vmlf = &auth_file->material_list; + vector_auth_3d_material_list_reserve(vml, vmlf->end - vmlf->begin); + for (auth_3d_material_list_file* i = vmlf->begin; i != vmlf->end; i++) + auth_3d_material_list_load(auth, i); + } + + if (auth_file->motion.end - auth_file->motion.begin > 0) { + vector_string* vm = &auth->motion; + vector_string* vmf = &auth_file->motion; + vector_string_reserve(vm, vmf->end - vmf->begin); + for (string* i = vmf->begin; i != vmf->end; i++) { + string* m = vector_string_reserve_back(vm); + string_copy(i, m); + } + } + + if (auth_file->object.end - auth_file->object.begin > 0) { + vector_auth_3d_object* vo = &auth->object; + vector_a3da_object* vof = &auth_file->object; + vector_auth_3d_object_reserve(vo, vof->end - vof->begin); + for (auth_3d_object_file* i = vof->begin; i != vof->end; i++) + auth_3d_object_load(auth, i, obj_db, tex_db); + } + + if (auth_file->object_hrc.end - auth_file->object_hrc.begin > 0) { + vector_auth_3d_object_hrc* voh = &auth->object_hrc; + vector_a3da_object_hrc* vohf = &auth_file->object_hrc; + vector_auth_3d_object_hrc_reserve(voh, vohf->end - vohf->begin); + for (auth_3d_object_hrc_file* i = vohf->begin; i != vohf->end; i++) + auth_3d_object_hrc_load(auth, i, obj_db); + } + + if (auth_file->point.end - auth_file->point.begin > 0) { + vector_auth_3d_point* vp = &auth->point; + vector_a3da_point* vpf = &auth_file->point; + vector_auth_3d_point_reserve(vp, vpf->end - vpf->begin); + for (auth_3d_point_file* i = vpf->begin; i != vpf->end; i++) + auth_3d_point_load(auth, i); + } + + if (auth_file->m_object_hrc_list.end - auth_file->m_object_hrc_list.begin > 0) { + vector_auth_3d_m_object_hrc* vmoh = &auth->m_object_hrc; + vector_ptr_auth_3d_m_object_hrc* vmohl = &auth->m_object_hrc_list; + vector_string* vmohlf = &auth_file->m_object_hrc_list; + vector_ptr_auth_3d_m_object_hrc_reserve(vmohl, vmohlf->end - vmohlf->begin); + for (string* i = vmohlf->begin; i != vmohlf->end; i++) + for (auth_3d_m_object_hrc* j = vmoh->begin; vmoh->begin != vmoh->end; j++) + if (string_compare(i, &j->name)) { + vector_ptr_auth_3d_m_object_hrc_push_back(vmohl, &j); + break; + } + } + + if (auth_file->object_list.end - auth_file->object_list.begin > 0) { + vector_auth_3d_object* vo = &auth->object; + vector_ptr_auth_3d_object* vol = &auth->object_list; + vector_string* volf = &auth_file->object_list; + vector_ptr_auth_3d_object_reserve(vol, volf->end - volf->begin); + for (string* i = volf->begin; i != volf->end; i++) + for (auth_3d_object* j = vo->begin; vo->begin != vo->end; j++) + if (string_compare(i, &j->name)) { + vector_ptr_auth_3d_object_push_back(vol, &j); + break; + } + } + + if (auth_file->object_hrc_list.end - auth_file->object_hrc_list.begin > 0) { + vector_auth_3d_object_hrc* voh = &auth->object_hrc; + vector_ptr_auth_3d_object_hrc* vohl = &auth->object_hrc_list; + vector_string* vohlf = &auth_file->object_hrc_list; + vector_ptr_auth_3d_object_hrc_reserve(vohl, vohlf->end - vohlf->begin); + for (string* i = vohlf->begin; i != vohlf->end; i++) + for (auth_3d_object_hrc* j = voh->begin; voh->begin != voh->end; j++) + if (string_compare(i, &j->name)) { + vector_ptr_auth_3d_object_hrc_push_back(vohl, &j); + break; + } + } + + if (auth->object.end - auth->object.begin > 0) { + vector_auth_3d_object* vo = &auth->object; + vector_auth_3d_object_hrc* voh = &auth->object_hrc; + for (auth_3d_object* i = vo->begin; i != vo->end; i++) { + if (!i->parent_name.length) + continue; + + if (i->parent_node.length) + for (auth_3d_object_hrc* j = voh->begin; j != voh->end; j++) { + if (!string_compare(&i->parent_name, &j->name)) + continue; + + vector_auth_3d_object_node* von = &j->node; + for (auth_3d_object_node* k = von->begin; von->begin != von->end; k++) { + if (!string_compare(&i->parent_node, &k->name)) + continue; + + int32_t node_index = (int32_t)(k - von->begin); + vector_int32_t_push_back(&j->childer_object_parent_node, &node_index); + vector_ptr_auth_3d_object_push_back(&j->children_object, &i); + break; + } + break; + } + else + for (auth_3d_object* j = vo->begin; j != vo->end; j++) { + if (!string_compare(&i->parent_name, &j->name)) + continue; + + vector_ptr_auth_3d_object_push_back(&j->children_object, &i); + } + } + } + + if (auth->object_hrc.end - auth->object_hrc.begin > 0) { + vector_auth_3d_object* vo = &auth->object; + vector_auth_3d_object_hrc* voh = &auth->object_hrc; + for (auth_3d_object_hrc* i = voh->begin; i != voh->end; i++) { + if (!i->parent_name.length) + continue; + + if (i->parent_node.length) + for (auth_3d_object_hrc* j = voh->begin; j != voh->end; j++) { + if (!string_compare(&i->parent_name, &j->name)) + continue; + + vector_auth_3d_object_node* von = &j->node; + for (auth_3d_object_node* k = von->begin; von->begin != von->end; k++) { + if (!string_compare(&i->parent_node, &k->name)) + continue; + + int32_t node_index = (int32_t)(k - von->begin); + vector_int32_t_push_back(&j->childer_object_hrc_parent_node, &node_index); + vector_ptr_auth_3d_object_hrc_push_back(&j->children_object_hrc, &i); + break; + } + break; + } + else + for (auth_3d_object* j = vo->begin; j != vo->end; j++) { + if (!string_compare(&i->parent_name, &j->name)) + continue; + + vector_ptr_auth_3d_object_hrc_push_back(&j->children_object_hrc, &i); + } + } + } + + string_copy(&auth_file->_file_name, &auth->file_name); +} + +void auth_3d_load_from_farc(auth_3d* auth, farc* f, char* file, + object_database* obj_db, texture_database* tex_db) { + farc_file* ff = farc_read_file(f, file); + if (!ff) + return; + + a3da a; + a3da_init(&a); + a3da_mread(&a, ff->data, ff->size); + auth_3d_load(auth, &a, obj_db, tex_db); + a3da_free(&a); +} + +void auth_3d_free(auth_3d* auth) { + if (!auth) + return; + + auth->uid = -1; + auth->id = -1; + auth->alpha = 1.0f; + + auth_3d_camera_auxiliary_free(&auth->camera_auxiliary); + auth_3d_dof_free(&auth->dof); + auth_3d_post_process_free(&auth->post_process); + + vector_auth_3d_ambient_free(&auth->ambient, auth_3d_ambient_free); + vector_string_free(&auth->auth_2d, string_free); + vector_auth_3d_camera_root_free(&auth->camera_root, auth_3d_camera_root_free); + vector_auth_3d_chara_free(&auth->chara, auth_3d_chara_free); + vector_auth_3d_curve_free(&auth->curve, auth_3d_curve_free); + vector_auth_3d_event_free(&auth->event, auth_3d_event_free); + vector_auth_3d_fog_free(&auth->fog, auth_3d_fog_free); + vector_auth_3d_light_free(&auth->light, auth_3d_light_free); + vector_auth_3d_m_object_hrc_free(&auth->m_object_hrc, auth_3d_m_object_hrc_free); + vector_ptr_auth_3d_m_object_hrc_free(&auth->m_object_hrc_list, 0); + vector_auth_3d_material_list_free(&auth->material_list, auth_3d_material_list_free); + vector_string_free(&auth->motion, string_free); + vector_auth_3d_object_free(&auth->object, auth_3d_object_free); + vector_auth_3d_object_hrc_free(&auth->object_hrc, auth_3d_object_hrc_free); + vector_ptr_auth_3d_object_hrc_free(&auth->object_hrc_list, 0); + vector_ptr_auth_3d_object_free(&auth->object_list, 0); + vector_auth_3d_point_free(&auth->point, auth_3d_point_free); + + string_free(&auth->file_name); +} + +void auth_3d_farc_init(auth_3d_farc* f) { + if (!f) + return; + + memset(f, 0, sizeof(auth_3d_farc)); +} + +void auth_3d_farc_load(auth_3d_farc* f, void* data, char* name, object_database* obj_db) { + string file; + string_init(&file, name); + string_add_length(&file, ".farc", 5); + data_struct_load_file(data, &f->auth_3d_farc, + "rom\\auth_3d\\", string_data(&file), farc_load_file); + string_free(&file); + + bool found_base = false; + f->obj_set_id = vector_empty(uint32_t); + vector_uint32_t* obj_set_id = &f->obj_set_id; + for (farc_file* i = f->auth_3d_farc.files.begin; i != f->auth_3d_farc.files.end; i++) { + char* name_str = string_data(&i->name); + size_t name_len = i->name.length; + + string name = string_empty; + char* s = 0; + if (s = strchr(name_str, '_')) + string_init_length(&name, name_str, s - name_str); + else + string_init_length(&name, name_str, name_len); + + object_set_info* set_info; + if (!object_database_get_object_set_info(obj_db, string_data(&name), &set_info)) { + string_free(&name); + continue; + } + + string_free(&name); + + uint32_t set_id = set_info->id; + for (uint32_t* j = obj_set_id->begin; j != obj_set_id->end; j++) + if (set_id == *j) { + set_id = -1; + break; + } + + if (set_id == -1) + continue; + + if (!found_base) { + char* n = string_data(&set_info->name); + size_t n_len = set_info->name.length; + + char set_name[11]; + set_name[0] = 0; + if (!str_utils_compare_length(n, n_len, "STGPV", 5)) { + memcpy(set_name, n, 8); + set_name[8] = 0; + found_base = true; + } + else if (!str_utils_compare_length(n, n_len, "STGD2PV", 7)) { + memcpy(set_name, n, 10); + set_name[10] = 0; + found_base = true; + } + + if (found_base && object_database_get_object_set_info(obj_db, set_name, &set_info)) { + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + vector_uint32_t_push_back(obj_set_id, &set_info->id); + found_base = true; + } + else + found_base = false; + } + + object_set_load_by_db_index(&set_info, data, obj_db, set_id); + vector_uint32_t_push_back(obj_set_id, &set_id); + } + + char* name_str = name; + size_t name_len = utf8_length(name); + + object_set_info* set_info; + if (!memcmp(name_str, "ITMPV", 5) + && object_database_get_object_set_info(obj_db, name_str, &set_info)) { + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + vector_uint32_t_push_back(obj_set_id, &set_info->id); + } + + if (!memcmp(name_str, "EFFCHRPV", 8) + && object_database_get_object_set_info(obj_db, name_str, &set_info)) { + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + vector_uint32_t_push_back(obj_set_id, &set_info->id); + } + + string obj = string_empty; + for (size_t i = 0; i < name_len && name_len - i >= 8; i++) + if (!memcmp(&name_str[i], "STGPV", 5)) { + string_free(&obj); + string_init_length(&obj, &name_str[i], 8); + break; + } + + for (size_t i = 0; i < name_len && name_len - i >= 10; i++) + if (!memcmp(&name_str[i], "STGD2PV", 7)) { + string_free(&obj); + string_init_length(&obj, &name_str[i], 10); + break; + } + + if (object_database_get_object_set_info(obj_db, string_data(&obj), &set_info)) { + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + vector_uint32_t_push_back(obj_set_id, &set_info->id); + } + + string_add_length(&obj, "HRC", 3); + if (object_database_get_object_set_info(obj_db, string_data(&obj), &set_info)) { + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + vector_uint32_t_push_back(obj_set_id, &set_info->id); + } + string_free(&obj); +} + +void auth_3d_farc_free(auth_3d_farc* f) { + farc_free(&f->auth_3d_farc); + vector_uint32_t_free(&f->obj_set_id, 0); +} + +void auth_3d_key_free(auth_3d_key* k) { + vector_kft3_free(&k->keys_vec, 0); +} + +void auth_3d_rgba_free(auth_3d_rgba* rgba) { + if (rgba->flags & AUTH_3D_RGBA_R) + auth_3d_key_free(&rgba->r); + if (rgba->flags & AUTH_3D_RGBA_G) + auth_3d_key_free(&rgba->g); + if (rgba->flags & AUTH_3D_RGBA_B) + auth_3d_key_free(&rgba->b); + if (rgba->flags & AUTH_3D_RGBA_A) + auth_3d_key_free(&rgba->a); +} + +void auth_3d_vec3_free(auth_3d_vec3* vec) { + auth_3d_key_free(&vec->x); + auth_3d_key_free(&vec->y); + auth_3d_key_free(&vec->z); +} + +void auth_3d_model_transform_free(auth_3d_model_transform* mt) { + auth_3d_vec3_free(&mt->rotation); + auth_3d_vec3_free(&mt->scale); + auth_3d_vec3_free(&mt->translation); + auth_3d_key_free(&mt->visibility); +} + +void auth_3d_ambient_free(auth_3d_ambient* a) { + if (a->flags & AUTH_3D_AMBIENT_LIGHT_DIFFUSE) + auth_3d_rgba_free(&a->light_diffuse); + string_free(&a->name); + if (a->flags & AUTH_3D_AMBIENT_RIM_LIGHT_DIFFUSE) + auth_3d_rgba_free(&a->rim_light_diffuse); +} + +void auth_3d_camera_auxiliary_free(auth_3d_camera_auxiliary* ca) { + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE) + auth_3d_key_free(&ca->auto_exposure); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE) + auth_3d_key_free(&ca->exposure); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE_RATE) + auth_3d_key_free(&ca->exposure_rate); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA) + auth_3d_key_free(&ca->gamma); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE) + auth_3d_key_free(&ca->gamma_rate); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_SATURATE) + auth_3d_key_free(&ca->saturate); +} + +void auth_3d_camera_root_free(auth_3d_camera_root* cr) { + auth_3d_model_transform_free(&cr->interest); + auth_3d_model_transform_free(&cr->model_transform); + auth_3d_camera_root_view_point_free(&cr->view_point); +} + +void auth_3d_camera_root_view_point_free(auth_3d_camera_root_view_point* crvp) { + if (crvp->flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_FOV) + auth_3d_key_free(&crvp->fov); + else + auth_3d_key_free(&crvp->focal_length); + auth_3d_model_transform_free(&crvp->model_transform); + if (crvp->flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_ROLL) + auth_3d_key_free(&crvp->roll); +} + +void auth_3d_chara_free(auth_3d_chara* c) { + auth_3d_model_transform_free(&c->model_transform); + string_free(&c->name); +} + +void auth_3d_curve_free(auth_3d_curve* c) { + auth_3d_key_free(&c->curve); + string_free(&c->name); +} + +void auth_3d_dof_free(auth_3d_dof* d) { + auth_3d_model_transform_free(&d->model_transform); +} + +void auth_3d_event_free(auth_3d_event* e) { + string_free(&e->name); + string_free(&e->param_1); + string_free(&e->ref); +} + +void auth_3d_fog_free(auth_3d_fog* f) { + if (f->flags & AUTH_3D_FOG_COLOR) + auth_3d_rgba_free(&f->color); + if (f->flags & AUTH_3D_FOG_DENSITY) + auth_3d_key_free(&f->density); + if (f->flags & AUTH_3D_FOG_END) + auth_3d_key_free(&f->end); + if (f->flags & AUTH_3D_FOG_START) + auth_3d_key_free(&f->start); +} + +void auth_3d_light_free(auth_3d_light* l) { + if (l->flags & AUTH_3D_LIGHT_AMBIENT) + auth_3d_rgba_free(&l->ambient); + if (l->flags & AUTH_3D_LIGHT_CONE_ANGLE) + auth_3d_key_free(&l->cone_angle); + if (l->flags & AUTH_3D_LIGHT_CONSTANT) + auth_3d_key_free(&l->constant); + if (l->flags & AUTH_3D_LIGHT_DIFFUSE) + auth_3d_rgba_free(&l->diffuse); + if (l->flags & AUTH_3D_LIGHT_DROP_OFF) + auth_3d_key_free(&l->drop_off); + if (l->flags & AUTH_3D_LIGHT_FAR) + auth_3d_key_free(&l->_far); + if (l->flags & AUTH_3D_LIGHT_INTENSITY) + auth_3d_key_free(&l->intensity); + if (l->flags & AUTH_3D_LIGHT_LINEAR) + auth_3d_key_free(&l->linear); + if (l->flags & AUTH_3D_LIGHT_POSITION) + auth_3d_model_transform_free(&l->position); + if (l->flags & AUTH_3D_LIGHT_QUADRATIC) + auth_3d_key_free(&l->quadratic); + if (l->flags & AUTH_3D_LIGHT_SPECULAR) + auth_3d_rgba_free(&l->specular); + if (l->flags & AUTH_3D_LIGHT_SPOT_DIRECTION) + auth_3d_model_transform_free(&l->spot_direction); + if (l->flags & AUTH_3D_LIGHT_TONE_CURVE) + auth_3d_rgba_free(&l->tone_curve); + string_free(&l->type); +} + +void auth_3d_m_object_hrc_free(auth_3d_m_object_hrc* moh) { + vector_auth_3d_object_instance_free(&moh->instance, auth_3d_object_instance_free); + auth_3d_object_model_transform_free(&moh->model_transform); + string_free(&moh->name); + vector_auth_3d_object_node_free(&moh->node, auth_3d_object_node_free); +} + +void auth_3d_material_list_free(auth_3d_material_list* ml) { + if (ml->flags & AUTH_3D_MATERIAL_LIST_BLEND_COLOR) + auth_3d_rgba_free(&ml->blend_color); + if (ml->flags & AUTH_3D_MATERIAL_LIST_GLOW_INTENSITY) + auth_3d_key_free(&ml->glow_intensity); + if (ml->flags & AUTH_3D_MATERIAL_LIST_INCANDESCENCE) + auth_3d_rgba_free(&ml->incandescence); + string_free(&ml->name); +} + +void auth_3d_object_free(auth_3d_object* o) { + vector_ptr_auth_3d_object_free(&o->children_object, 0); + vector_ptr_auth_3d_object_hrc_free(&o->children_object_hrc, 0); + auth_3d_model_transform_free(&o->model_transform); + auth_3d_object_curve_free(&o->morph); + string_free(&o->name); + string_free(&o->parent_name); + string_free(&o->parent_node); + auth_3d_object_curve_free(&o->pattern); + vector_auth_3d_object_texture_pattern_free(&o->texture_pattern, + auth_3d_object_texture_pattern_free); + vector_auth_3d_object_texture_transform_free(&o->texture_transform, + auth_3d_object_texture_transform_free); + string_free(&o->uid_name); +} + +void auth_3d_object_curve_free(auth_3d_object_curve* oc) { + string_free(&oc->name); +} + +void auth_3d_object_hrc_free(auth_3d_object_hrc* oh) { + vector_ptr_auth_3d_object_free(&oh->children_object, 0); + vector_ptr_auth_3d_object_hrc_free(&oh->children_object_hrc, 0); + vector_int32_t_free(&oh->childer_object_hrc_parent_node, 0); + vector_int32_t_free(&oh->childer_object_parent_node, 0); + vector_mat4_free(&oh->mats, 0); + string_free(&oh->name); + vector_auth_3d_object_node_free(&oh->node, auth_3d_object_node_free); + string_free(&oh->parent_name); + string_free(&oh->parent_node); + string_free(&oh->uid_name); +} + +void auth_3d_object_instance_free(auth_3d_object_instance* oi) { + vector_mat4_free(&oi->mats, 0); + auth_3d_object_model_transform_free(&oi->model_transform); + string_free(&oi->name); + vector_int32_t_free(&oi->object_bone_indices, 0); + string_free(&oi->uid_name); +} + +void auth_3d_object_model_transform_free(auth_3d_object_model_transform* omt) { + auth_3d_vec3_free(&omt->translation); + auth_3d_vec3_free(&omt->rotation); + auth_3d_vec3_free(&omt->scale); + auth_3d_key_free(&omt->visibility); +} + +void auth_3d_object_node_free(auth_3d_object_node* on) { + auth_3d_object_model_transform_free(&on->model_transform); + string_free(&on->name); +} + +void auth_3d_object_texture_pattern_free(auth_3d_object_texture_pattern* otp) { + string_free(&otp->name); + auth_3d_object_curve_free(&otp->pattern); +} + +void auth_3d_object_texture_transform_free(auth_3d_object_texture_transform* ott) { + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + auth_3d_key_free(&ott->coverage_u); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + auth_3d_key_free(&ott->coverage_v); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + auth_3d_key_free(&ott->offset_u); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + auth_3d_key_free(&ott->offset_v); + string_free(&ott->name); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + auth_3d_key_free(&ott->repeat_u); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + auth_3d_key_free(&ott->repeat_v); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE) + auth_3d_key_free(&ott->rotate); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + auth_3d_key_free(&ott->rotate_frame); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + auth_3d_key_free(&ott->translate_frame_u); + if (ott->flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + auth_3d_key_free(&ott->translate_frame_v); +} + +void auth_3d_point_free(auth_3d_point* p) { + auth_3d_model_transform_free(&p->model_transform); + string_free(&p->name); +} + +void auth_3d_post_process_free(auth_3d_post_process* pp) { + if (pp->flags & AUTH_3D_POST_PROCESS_INTENSITY) + auth_3d_rgba_free(&pp->intensity); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_FLARE) + auth_3d_key_free(&pp->lens_flare); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_GHOST) + auth_3d_key_free(&pp->lens_ghost); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_SHAFT) + auth_3d_key_free(&pp->lens_shaft); + if (pp->flags & AUTH_3D_POST_PROCESS_RADIUS) + auth_3d_rgba_free(&pp->radius); + if (pp->flags & AUTH_3D_POST_PROCESS_SCENE_FADE) + auth_3d_rgba_free(&pp->scene_fade); +} +/* +void __fastcall sub_140248480(string *a1, list_int32_t *a2) +{ + list_int32_t_node *v4; // rcx + list_int32_t_node *v5; // rbx + char *v6; // rcx + int32_t *i; // rbx + char *v8; // rax + size_t v9; // r8 + size_t v10; // rsi + char *v11; // rdi + _BYTE *v12; // rax + _BYTE *v13; // r9 + int v14; // ecx + char *v15; // rax + ssize_t v16; // r9 + char *v17; // rcx + list_int32_t_node *v18; // rdi + list_int32_t_node *v19; // rax + size_t v20; // rdx + int32_t v21; // eax + pv_db_pv *v22; // rax + pv_db_pv_difficulty *v23; // rcx + string_union v24; // kr00_16 + pv_item *__shifted(pv_item,8) v25; // rbx + char *v26; // rcx + object_info v27; // eax + list_int32_t_node *v28; // rdi + list_int32_t_node *v29; // rax + size_t v30; // rdx + pv_item *__shifted(pv_item,0x20) v31; // rbx + char *v32; // rcx + list_int32_t_node *v33; // rbx + list_int32_t_node *v34; // rdx + size_t v35; // rax + ssize_t v36; // rax + string *v37; // rbx + ssize_t v38; // rax + string *v39; // rbx + char *v40; // rcx + list_int32_t_node *v41; // rbx + list_int32_t_node *v42; // rdx + size_t v43; // rax + char *v44; // rcx + list_int32_t_node *v45; // rbx + list_int32_t_node *v46; // rcx + size_t v47; // rax + int32_t a4; // [rsp+20h] [rbp-49h] BYREF + __int64 v49; // [rsp+28h] [rbp-41h] + string Dst; // [rsp+30h] [rbp-39h] BYREF + string v51; // [rsp+30h] [rbp-39h] FORCED BYREF + string Memory; // [rsp+50h] [rbp-19h] BYREF + vector_int32_t uids; // [rsp+70h] [rbp+7h] BYREF + + v49 = -2i64; + v4 = a2->head->next; + a2->head->next = a2->head; + a2->head->prev = a2->head; + a2->size = 0i64; + if ( v4 != a2->head ) + { + do + { + v5 = v4->next; + j_free_2(v4); + v4 = v5; + } + while ( v5 != a2->head ); + } + uids.begin = 0i64; + uids.end = 0i64; + uids.capacity_end = 0i64; + if ( a1->capacity < 0x10 ) + v6 = (char *)a1; + else + v6 = a1->data.ptr; + sub_1401CBC70(v6, &uids); + for ( i = uids.begin; i != uids.end; ++i ) + { + v8 = sub_1401E7E90(*i); + Dst.capacity = 15i64; + Dst.length = 0i64; + Dst.data.data[0] = 0; + if ( *v8 ) + { + v9 = -1i64; + do + ++v9; + while ( v8[v9] ); + } + else + { + v9 = 0i64; + } + string_append_char_str(&Dst, v8, v9); + v10 = Dst.length; + if ( Dst.length ) + { + v11 = (char *)&Dst; + if ( Dst.capacity >= 0x10 ) + v11 = Dst.data.ptr; + while ( v10 ) + { + v12 = memchr(v11, '_', v10); + v13 = v12; + if ( !v12 ) + break; + if ( *v12 == asc_14096CDF0[0] ) + v14 = 0; + else + v14 = *v12 < asc_14096CDF0[0] ? -1 : 1; + if ( !v14 ) + { + v15 = (char *)&Dst; + if ( Dst.capacity >= 0x10 ) + v15 = Dst.data.ptr; + v16 = v13 - v15; + if ( v16 != -1 ) + { + sub_1400215A0(&Dst, &Memory, 0i64, v16); + v17 = (char *)&Memory; + if ( Memory.capacity >= 0x10 ) + v17 = Memory.data.ptr; + a4 = obj_database_get_object_set(v17); + if ( a4 != -1 ) + { + v18 = a2->head; + v19 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); + v20 = a2->size; + if ( v20 == 0xAAAAAAAAAAAAAA9i64 ) + ThrowException("list too long"); + a2->size = v20 + 1; + v18->prev = v19; + v19->prev->next = v19; + } + if ( Memory.capacity >= 0x10 ) + j_free_2(Memory.data.ptr); + } + break; + } + v10 += v11 - v12 - 1; + v11 = v12 + 1; + } + } + if ( Dst.capacity >= 0x10 ) + j_free_2(Dst.data.ptr); + } + if ( !string_compare_ptr_char(a1, "ITMPV", 0i64, 5ui64) ) + { + sub_1400215A0(a1, &Memory, 5i64, -1i64); + v21 = sub_1400D29A0(&Memory, 0xAu); + v22 = task_pv_db_get_pv(v21); + if ( v22 ) + { + v23 = v22->difficulty[2].begin; + if ( v22->difficulty[2].end - v23 ) + { + v51.data = 0ui64; + v51.length = 0i64; + sub_14023FDE0((vector_pv_db_pv_pv_item *)&v51, &v23->pv_item); + v24 = v51.data; + if ( v51.data.ptr != *(char **)&v51.data.data[8] ) + { + v25 = (pv_item *__shifted(pv_item,8))(v51.data.ptr + 8); + do + { + if ( ADJ(v25)->index > 0 ) + { + v26 = (char *)(ADJ(v25)->name.capacity < 0x10 ? v25 : ADJ(v25)->name.data.ptr); + v27 = obj_database_get_object_info(v26); + if ( v27 != -1 ) + { + a4 = HIWORD(*(unsigned int *)&v27); + v28 = a2->head; + v29 = sub_14023B3E0(&a2->head, a2->head, a2->head->prev, &a4); + v30 = a2->size; + if ( v30 == 0xAAAAAAAAAAAAAA9i64 ) + ThrowException("list too long"); + a2->size = v30 + 1; + v28->prev = v29; + v29->prev->next = v29; + } + } + ++v25; + } + while ( ADJ(v25) != *(pv_item *__shifted(pv_item,8) *)&v24.data[8] ); + } + if ( v24.ptr ) + { + if ( v24.ptr != *(char **)&v24.data[8] ) + { + v31 = (pv_item *__shifted(pv_item,0x20))(v24.ptr + 32); + do + { + if ( ADJ(v31)->name.capacity >= 0x10 ) + j_free_2(ADJ(v31)->name.data.ptr); + ADJ(v31)->name.capacity = 15i64; + ADJ(v31)->name.length = 0i64; + ADJ(v31++)->name.data.data[0] = 0; + } + while ( ADJ(v31) != *(pv_item *__shifted(pv_item,0x20) *)&v24.data[8] ); + } + j_free_2(v24.ptr); + } + } + } + if ( Memory.capacity >= 0x10 ) + j_free_2(Memory.data.ptr); + } + if ( !string_compare_ptr_char(a1, "EFFCHRPV", 0i64, 8ui64) ) + { + v32 = (char *)(a1->capacity < 0x10 ? a1 : a1->data.ptr); + a4 = obj_database_get_object_set(v32); + if ( a4 != -1 ) + { + v33 = a2->head; + v34 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); + v35 = a2->size; + if ( v35 == 0xAAAAAAAAAAAAAA9i64 ) + ThrowException("list too long"); + a2->size = v35 + 1; + v33->prev = v34; + v34->prev->next = v34; + } + } + sub_14023EF10(a2); + sub_14023F860(a2); + v51.capacity = 15i64; + v51.length = 0i64; + v51.data.data[0] = 0; + string_append_char_str(&v51, null_string, 0i64); + v36 = string_compare_ptr_char(a1, "STGPV", 0i64, 5ui64); + if ( v36 != -1 ) + { + v37 = sub_1400215A0(a1, &Memory, v36, 8i64); + if ( &v51 != v37 ) + { + if ( v51.capacity >= 0x10 ) + j_free_2(v51.data.ptr); + v51.capacity = 15i64; + v51.length = 0i64; + v51.data.data[0] = 0; + if ( v37->capacity >= 0x10 ) + { + v51.data.ptr = v37->data.ptr; + v37->data.ptr = 0i64; + } + else if ( v37->length != -1i64 ) + { + memmove(&v51, v37, v37->length + 1); + } + v51.length = v37->length; + v51.capacity = v37->capacity; + v37->capacity = 15i64; + v37->length = 0i64; + v37->data.data[0] = 0; + } + if ( Memory.capacity >= 0x10 ) + j_free_2(Memory.data.ptr); + } + v38 = string_compare_ptr_char(a1, "STGD2PV", 0i64, 7ui64); + if ( v38 != -1 ) + { + v39 = sub_1400215A0(a1, &Memory, v38, 10i64); + if ( &v51 != v39 ) + { + if ( v51.capacity >= 0x10 ) + j_free_2(v51.data.ptr); + v51.capacity = 15i64; + v51.length = 0i64; + v51.data.data[0] = 0; + if ( v39->capacity >= 0x10 ) + { + v51.data.ptr = v39->data.ptr; + v39->data.ptr = 0i64; + } + else if ( v39->length != -1i64 ) + { + memmove(&v51, v39, v39->length + 1); + } + v51.length = v39->length; + v51.capacity = v39->capacity; + v39->capacity = 15i64; + v39->length = 0i64; + v39->data.data[0] = 0; + } + if ( Memory.capacity >= 0x10 ) + j_free_2(Memory.data.ptr); + } + if ( v51.length ) + { + v40 = (char *)&v51; + if ( v51.capacity >= 0x10 ) + v40 = v51.data.ptr; + a4 = obj_database_get_object_set(v40); + if ( a4 != -1 ) + { + v41 = a2->head->next; + v42 = list_int32_t_buy_node(a2, v41, v41->prev, &a4); + v43 = a2->size; + if ( v43 == 0xAAAAAAAAAAAAAA9i64 ) + ThrowException("list too long"); + a2->size = v43 + 1; + v41->prev = v42; + v42->prev->next = v42; + } + } + sub_14000BF30(&Memory, &v51, "HRC"); + v44 = (char *)&Memory; + if ( Memory.capacity >= 0x10 ) + v44 = Memory.data.ptr; + a4 = obj_database_get_object_set(v44); + if ( a4 != -1 ) + { + v45 = a2->head; + v46 = list_int32_t_buy_node(a2, a2->head, a2->head->prev, &a4); + v47 = a2->size; + if ( 0xAAAAAAAAAAAAAA9i64 == v47 ) + ThrowException("list too long"); + a2->size = v47 + 1; + v45->prev = v46; + v46->prev->next = v46; + } + if ( Memory.capacity >= 0x10 ) + j_free_2(Memory.data.ptr); + if ( v51.capacity >= 0x10 ) + j_free_2(v51.data.ptr); + if ( uids.begin ) + j_free_2(uids.begin); +} + +void sub_140248480(string* a1, vector_uint32_t* a2) { + char* v6; // rcx + int32_t* i; // rbx + char* v8; // rax + size_t v9; // r8 + size_t v10; // rsi + char* v11; // rdi + char* v12; // rax + char* v13; // r9 + int v14; // ecx + char* v15; // rax + ssize_t v16; // r9 + char* v17; // rcx + list_int32_t_node* v18; // rdi + list_int32_t_node* v19; // rax + size_t v20; // rdx + int v21; // eax + ssize_t* v22; // rax + __int64 v23; // rcx + string_union v24; // kr00_16 + string* v25; // rbx + string* v26; // rcx + object_info v27; // eax + list_int32_t_node* v28; // rdi + list_int32_t_node* v29; // rax + size_t v30; // rdx + string* v31; // rbx + char* v32; // rcx + list_int32_t_node* v33; // rbx + list_int32_t_node* v34; // rdx + size_t v35; // rax + __int64 v36; // rax + string* v37; // rbx + __int64 v38; // rax + string* v39; // rbx + char* v40; // rcx + list_int32_t_node* v41; // rbx + list_int32_t_node* v42; // rdx + size_t v43; // rax + char* v44; // rcx + list_int32_t_node* v45; // rbx + list_int32_t_node* v46; // rcx + size_t v47; // rax + int32_t a4; // [rsp+20h] [rbp-49h] BYREF + __int64 v49; // [rsp+28h] [rbp-41h] + string Dst; // [rsp+30h] [rbp-39h] BYREF + vector_int32_t uids; // [rsp+70h] [rbp+7h] BYREF + + v49 = -2; + vector_uint32_t_free(a2, 0); + + uids.begin = 0; + uids.end = 0; + uids.capacity_end = 0; + v6 = string_data(a1); + sub_1401CBC70(v6, &uids); + for (i = uids.begin; i != uids.end; i++) { + v8 = sub_1401E7E90(*i); + string_init(&Dst, v8); + v10 = Dst.length; + if (Dst.length) + { + v11 = string_data(&Dst); + while (v10) + { + v12 = memchr(v11, '_', v10); + v13 = v12; + if (!v12) + break; + if (*v12 == "_"[0]) + v14 = 0; + else + v14 = *v12 < "_"[0] ? -1 : 1; + if (!v14) + { + v15 = string_data(&Dst); + v16 = v13 - v15; + if (v16 != -1) + { + sub_1400215A0(&Dst, &Memory, 0, v16); + v17 = string_data(&Memory); + a4 = obj_database_get_object_set(v17); + if (a4 != -1) + vector_uint32_t_push_back(a2, &a4); + string_free(&Memory); + } + break; + } + v10 += v11 - v12 - 1; + v11 = v12 + 1; + } + } + string_free(&Dst); + } + + if (!str_utils_get_substring_offset(string_data(a1), a1->length, 0, "ITMPV", 5)) { + string_init_length(&Dst, string_data(a1), 8); + sscanf_s(string_data(a1) + 5, "%03d", &v21); + v22 = sub_1404E6220(v21); + if (v22) { + v23 = v22[28]; + if ((v22[29] - v23) / 1248) { + Dst.data = 0; + Dst.length = 0; + sub_14023FDE0(&Dst, (_QWORD*)(v23 + 504)); + v24 = Dst.data; + if (Dst.data.ptr != *(char**)&Dst.data[8]) { + v25 = (string*)(Dst.data.ptr + 8); + do { + if (SLODWORD(v25[-1].max_length) > 0) { + v26 = string_data(v25); + v27 = obj_database_get_object_info((char*)v26); + if (v27.id != -1 && v27.set_id != -1) + vector_uint32_t_push_back(a2, &v27.set_id); + } + v25 = (string*)((char*)v25 + 40); + } while (&v25[-1].max_length != (size_t*)*(string**)&v24.data[8]); + } + if (v24.ptr) { + if (v24.ptr != *(char**)&v24.data[8]) { + v31 = (string * __shifted(string, 0x18))(v24.ptr + 32); + do { + if (v31->max_length >= 0x10) + j_free_2(v31->data.ptr); + v31->max_length = 15; + v31->length = 0; + v31->data[0] = 0; + v31 = (string * __shifted(string, 0x18))((char*)v31 + 40); + } while (&v31[-1] != *(string * __shifted(string, 0x18)*) & v24.data[8]); + } + j_free_2(v24.ptr); + } + } + } + } + if (!str_utils_get_substring_offset(string_data(a1), a1->length, 0, "EFFCHRPV", 8)) { + v32 = string_data(a1->data); + a4 = obj_database_get_object_set(v32); + if (a4 != -1) + vector_uint32_t_push_back(a2, &a4); + } + sub_14023EF10(a2); + sub_14023F860(a2); + + string_init(&Dst, 0); + v36 = str_utils_get_substring_offset(string_data(a1), a1->length, 0, "STGPV", 5); + if (v36 != -1) + string_init_length(&Dst, string_data(a1) + v36, 8); + v38 = str_utils_get_substring_offset(string_data(a1), a1->length, 0, "STGD2PV", 7); + if (v38 != -1) + string_init_length(&Dst, string_data(a1) + v36, 10); + + if (Dst.length) { + v40 = string_data(&Dst); + a4 = obj_database_get_object_set(v40); + if (a4 != -1) + vector_uint32_t_push_back(a2, &a4); + } + + string_add_length(&Dst, "HRC", 3); + v44 = string_data(&Dst); + a4 = obj_database_get_object_set(v44); + if (a4 != -1) + vector_uint32_t_push_back(a2, &a4); + + string_free(&Dst); + vector_uint32_t_free(&uids, 0); +} +*/ +void auth_3d_data_init() { + memset(&auth_3d_data, 0, sizeof(auth_3d_data_struct)); + for (int32_t i = 0; i < AUTH_3D_DATA_COUNT; i++) + auth_3d_free(&auth_3d_data.data[i]); +} + +inline int32_t auth_3d_data_load_uid(int32_t uid, auth_3d_database* auth_3d_db) { + if (uid >= auth_3d_db->uid.end - auth_3d_db->uid.begin + || !auth_3d_db->uid.begin[uid].enabled) + return -1; + + int32_t index = 0; + while (auth_3d_data.data[index].uid != -1) + if (++index >= AUTH_3D_DATA_COUNT) + return -1; + + auth_3d_free(&auth_3d_data.data[index]); + + if (++auth_3d_load_counter < 0) + auth_3d_load_counter = 1; + + int32_t id = ((auth_3d_load_counter & 0x7FFF) << 16) | index & 0x7FFF; + auth_3d_data.data[index].uid = uid; + auth_3d_data.data[index].id = id; + vector_int32_t_push_back(&auth_3d_data.loaded_ids, &id); + return id; +} + +inline auth_3d* auth_3d_data_get_auth_3d(int32_t id) { + int32_t index = 0; + while (auth_3d_data.data[index].id != id) + if (++index >= AUTH_3D_DATA_COUNT) + return 0; + + return &auth_3d_data.data[index]; +} + +mat4* auth_3d_data_struct_get_auth_3d_object_mat(int32_t id, size_t index, bool hrc, mat4* mat) { + if (id < 0 || (id & 0x7FFF) >= AUTH_3D_DATA_COUNT) + return 0; + + auth_3d* auth = &auth_3d_data.data[id & 0x7FFF]; + if (auth->id != id || !auth->enable) + return 0; + + if (hrc) + return auth_3d_get_auth_3d_object_hrc_bone_mats(auth, index); + + if ((ssize_t)index < auth->object.end - auth->object.begin) { + mat4u_to_mat4(&auth->object.begin[index].model_transform.mat, mat); + return mat; + } + return 0; +} + + +int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, uint64_t* mesh_index, bool* hrc) { + for (int32_t* i = auth_3d_data.loaded_ids.begin; + i != auth_3d_data.loaded_ids.end; i++) { + if (*i < 0 || (*i & 0x7FFF) >= AUTH_3D_DATA_COUNT) + continue; + + auth_3d* auth = &auth_3d_data.data[*i & 0x7FFF]; + if (auth->id != *i || !auth->enable) + continue; + + int32_t obj_hrc_mesh_index = auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth, obj_info); + if (obj_hrc_mesh_index >= 0) { + if (mesh_index) + *mesh_index = obj_hrc_mesh_index; + if (hrc) + *hrc = true; + return *i; + } + + int32_t obj_mesh_index = auth_3d_get_auth_3d_object_index_by_object_info(auth, obj_info); + if (obj_mesh_index >= 0) + { + if (mesh_index) + *mesh_index = obj_mesh_index; + if (hrc) + *hrc = false; + return *i; + } + } + return -1; +} + +void auth_3d_data_unload_id(int32_t id, render_context* rctx) { + if (id < 0 || (id & 0x7FFF) >= AUTH_3D_DATA_COUNT) + return; + + auth_3d* auth = &auth_3d_data.data[id & 0x7FFF]; + if (!auth || auth->id != id) + return; + + int32_t* v5 = auth_3d_data.loaded_ids.end; + int32_t* v6 = auth_3d_data.loaded_ids.begin; + if (v6 == v5) + return; + + int32_t index = 0; + while (*v6 != id) + if (++index >= AUTH_3D_DATA_COUNT) + return; + else + v6++; + + if (v6 != v5) { + vector_int32_t_erase(&auth_3d_data.loaded_ids, v6 - auth_3d_data.loaded_ids.begin, 0); + auth_3d_unload(auth, rctx); + } +} + +void auth_3d_data_free() { + int32_t index = 0; + while (true) + if (++index >= AUTH_3D_DATA_COUNT) + break; + else + auth_3d_free(&auth_3d_data.data[index]); + vector_int32_t_free(&auth_3d_data.loaded_ids, 0); +} + +static kft3* auth_3d_key_find_keyframe(auth_3d_key* data, float_t frame) { + kft3* key = data->keys; + size_t length = data->length; + size_t temp; + while (length > 0) { + if (frame < key[temp = length / 2].frame) + length = temp; + else { + key += temp + 1; + length -= temp + 1; + } + } + return key; +} + +static float_t auth_3d_key_get_value(auth_3d_key* data, float_t frame) { + if (data->type == AUTH_3D_KEY_STATIC) + return data->value; + else if (data->type < AUTH_3D_KEY_STATIC || data->type > AUTH_3D_KEY_HOLD || !data->length) + return 0.0f; + + kft3* first_key = &data->keys[0]; + kft3* last_key = &data->keys[data->length - 1]; + float_t first_frame = first_key->frame; + float_t last_frame = last_key->frame; + float_t frame_delta = data->frame_delta; + + size_t v4 = data->length; + float_t offset = 0.0f; + if (frame < first_frame) { + float_t delta_frame = first_frame - frame; + switch (data->ep_type_pre) { + case A3DA_EP_NONE: + default: + data->frame = frame; + data->value_interp = first_key->value; + return data->value_interp; + case A3DA_EP_LINEAR: + data->frame = frame; + data->value_interp = first_key->value + delta_frame * first_key->tangent1; + return data->value_interp; + case A3DA_EP_CYCLE: + frame = last_frame - fmodf(delta_frame, frame_delta); + break; + case A3DA_EP_CYCLE_OFFSET: + offset = -(float_t)((int32_t)(delta_frame / frame_delta + 1.0)) * data->value_delta; + frame = last_frame - fmodf(delta_frame, frame_delta); + break; + } + } + else if (frame >= last_frame) { + float_t delta_frame = frame - last_frame; + switch (data->ep_type_post) { + case A3DA_EP_NONE: + default: + data->frame = frame; + data->value_interp = last_key->value; + return data->value_interp; + case A3DA_EP_LINEAR: + data->frame = frame; + data->value_interp = last_key->value - delta_frame * last_key->tangent2; + return data->value_interp; + case A3DA_EP_CYCLE: + frame = first_frame + fmodf(delta_frame, frame_delta); + break; + case A3DA_EP_CYCLE_OFFSET: + offset = (float_t)((int32_t)(delta_frame / frame_delta + 1.0)) * data->value_delta; + frame = first_frame + fmodf(delta_frame, frame_delta); + break; + } + } + + data->frame = frame; + data->value_interp = auth_3d_key_interpolate(data, frame) + offset; + return data->value_interp; +} + +static float_t auth_3d_key_interpolate(auth_3d_key* data, float_t frame) { + kft3* first_key = data->keys; + kft3* key = auth_3d_key_find_keyframe(data, frame); + + if (key == first_key) + return first_key->value; + else if (key == &first_key[data->length]) + return key[-1].value; + else + return auth_3d_interpolate_value(data->type, frame, key - 1, key); +} + +static float_t auth_3d_interpolate_value(auth_3d_key_type type, + float_t frame, kft3* curr_key, kft3* next_key) { + switch (type) { + case AUTH_3D_KEY_LINEAR: + if (curr_key->frame < next_key->frame) + return interpolate_linear_value(curr_key->value, next_key->value, + curr_key->frame, next_key->frame, frame); + else + return curr_key->value; + case AUTH_3D_KEY_HERMITE: + if (curr_key->frame < next_key->frame) { + float_t df = next_key->frame - curr_key->frame; + return interpolate_chs_value(curr_key->value, next_key->value, + curr_key->tangent2, next_key->tangent1, + curr_key->frame, next_key->frame, frame); + } + else + return curr_key->value; + case AUTH_3D_KEY_HOLD: + if (frame >= next_key->frame) + return next_key->value; + else + return curr_key->value; + default: + return 0.0f; + } +} + +static void auth_3d_key_load(auth_3d* auth, auth_3d_key* k, auth_3d_key_file* kf) { + k->max_frame = auth->max_frame; + k->frame_delta = k->max_frame; + k->value_delta = 0.0f; + + ssize_t length = kf->keys.end - kf->keys.begin; + switch (kf->type) { + case A3DA_KEY_NONE: + k->type = AUTH_3D_KEY_NONE; + k->value = 0.0f; + return; + case A3DA_KEY_STATIC: + k->type = kf->value != 0.0f ? AUTH_3D_KEY_STATIC : AUTH_3D_KEY_NONE; + k->value = kf->value; + return; + case A3DA_KEY_LINEAR: + k->type = AUTH_3D_KEY_LINEAR; + break; + case A3DA_KEY_HERMITE: + default: + k->type = AUTH_3D_KEY_HERMITE; + break; + case A3DA_KEY_HOLD: + k->type = AUTH_3D_KEY_HOLD; + break; + } + + k->keys_vec = vector_empty(kft3); + if (length > 1) { + vector_kft3_insert_range(&k->keys_vec, 0, kf->keys.begin, kf->keys.end); + k->length = length; + k->keys = k->keys_vec.begin; + + kft3* first_key = &k->keys[0]; + kft3* last_key = &k->keys[length - 1]; + if (first_key->frame < last_key->frame + && last_key->frame > 0.0f && k->max_frame > first_key->frame) { + k->ep_type_pre = kf->ep_type_pre; + k->ep_type_post = kf->ep_type_post; + k->frame_delta = last_key->frame - first_key->frame; + k->value_delta = last_key->value - first_key->value; + } + } + else if (length == 1) { + float_t value = kf->keys.begin[0].value; + k->type = value != 0.0f ? AUTH_3D_KEY_STATIC : AUTH_3D_KEY_NONE; + k->value = value; + } + else { + k->type = AUTH_3D_KEY_NONE; + k->value = 0.0f; + } +} + +static void auth_3d_rgba_get_value(auth_3d_rgba* rgba, float_t frame) { + if (rgba->flags & A3DA_RGBA_R) + rgba->value.x = auth_3d_key_get_value(&rgba->r, frame); + + if (rgba->flags & A3DA_RGBA_G) + rgba->value.y = auth_3d_key_get_value(&rgba->g, frame); + + if (rgba->flags & A3DA_RGBA_B) + rgba->value.z = auth_3d_key_get_value(&rgba->b, frame); + + if (rgba->flags & A3DA_RGBA_A) + rgba->value.w = auth_3d_key_get_value(&rgba->a, frame); +} + +static void auth_3d_rgba_load(auth_3d* auth, auth_3d_rgba* rgba, auth_3d_rgba_file* rgbaf) { + if (rgbaf->flags & A3DA_RGBA_R) { + auth_3d_key_load(auth, &rgba->r, &rgbaf->r); + rgba->flags |= AUTH_3D_RGBA_R; + } + + if (rgbaf->flags & A3DA_RGBA_G) { + auth_3d_key_load(auth, &rgba->g, &rgbaf->g); + rgba->flags |= AUTH_3D_RGBA_G; + } + + if (rgbaf->flags & A3DA_RGBA_B) { + auth_3d_key_load(auth, &rgba->b, &rgbaf->b); + rgba->flags |= AUTH_3D_RGBA_B; + } + + if (rgbaf->flags & A3DA_RGBA_A) { + auth_3d_key_load(auth, &rgba->a, &rgbaf->a); + rgba->flags |= AUTH_3D_RGBA_A; + } +} + +static void auth_3d_vec3_get_value(auth_3d_vec3* vec, float_t frame, vec3* value) { + value->x = auth_3d_key_get_value(&vec->x, frame); + value->y = auth_3d_key_get_value(&vec->y, frame); + value->z = auth_3d_key_get_value(&vec->z, frame); +} + +static void auth_3d_vec3_load(auth_3d* auth, auth_3d_vec3* vec, auth_3d_vec3_file* vecf) { + auth_3d_key_load(auth, &vec->x, &vecf->x); + auth_3d_key_load(auth, &vec->y, &vecf->y); + auth_3d_key_load(auth, &vec->z, &vecf->z); +} + +static void auth_3d_model_transform_get_value(auth_3d_model_transform* mt, float_t frame) { + auth_3d_vec3_get_value(&mt->scale, frame, &mt->scale_value); + auth_3d_vec3_get_value(&mt->rotation, frame, &mt->rotation_value); + auth_3d_vec3_get_value(&mt->translation, frame, &mt->translation_value); + mt->visible = auth_3d_key_get_value(&mt->visibility, frame) >= 0.99900001f; + if (mt->visible && (mt->scale_value.x == 0.0f + || mt->scale_value.y == 0.0f || mt->scale_value.z == 0.0f)) + mt->visible = false; +} + +static void auth_3d_model_transform_load(auth_3d* auth, auth_3d_model_transform* mt, auth_3d_model_transform_file* mtf) { + auth_3d_vec3_load(auth, &mt->rotation, &mtf->rotation); + auth_3d_vec3_load(auth, &mt->scale, &mtf->scale); + auth_3d_vec3_load(auth, &mt->translation, &mtf->translation); + auth_3d_key_load(auth, &mt->visibility, &mtf->visibility); +} + +static void auth_3d_model_transform_set_mat(auth_3d_model_transform* mt, mat4* parent_mat) { + mat4 mat; + mat4_translate_mult(parent_mat, mt->translation_value.x, + mt->translation_value.y, mt->translation_value.z, &mat); + mat4_rotate_mult(&mat, mt->rotation_value.x, mt->rotation_value.y, mt->rotation_value.z, &mat); + mat4_scale_rot(&mat, mt->scale_value.x, mt->scale_value.y, mt->scale_value.z, &mat); + mat4_to_mat4u(&mat, &mt->mat); +} + +static int32_t auth_3d_get_auth_3d_object_index_by_object_info(auth_3d* auth, object_info obj_info) { + auth_3d_object* v2 = auth->object.begin; + auth_3d_object* v3 = auth->object.end; + int32_t v4 = 0; + if (v2 == v3) + return -1; + + while (obj_info.id != v2->object_info.id + || obj_info.set_id != v2->object_info.set_id) { + v2++; + v4++; + if (v2 == v3) + return -1; + } + return v4; +} + +static mat4* auth_3d_get_auth_3d_object_hrc_bone_mats(auth_3d* auth, size_t index) { + vector_auth_3d_object_hrc* voh = &auth->object_hrc; + if ((ssize_t)index >= voh->end - voh->begin + || voh->begin[index].mats.begin == voh->begin[index].mats.end) + return 0; + return voh->begin[index].mats.begin; +} + +static int32_t auth_3d_get_auth_3d_object_hrc_index_by_object_info(auth_3d* auth, object_info obj_info) { + auth_3d_object_hrc* v2 = auth->object_hrc.begin; + auth_3d_object_hrc* v3 = auth->object_hrc.end; + int32_t v4 = 0; + if (v2 == v3) + return -1; + + while (obj_info.id != v2->object_info.id + || obj_info.set_id != v2->object_info.set_id) { + v2++; + v4++; + if (v2 == v3) + return -1; + } + return v4; +} + +static void auth_3d_ambient_data_set(auth_3d_ambient* a, render_context* rctx) { + +} + +static void auth_3d_ambient_get_value(auth_3d_ambient* a, float_t frame) { + if (a->flags & AUTH_3D_AMBIENT_LIGHT_DIFFUSE) + auth_3d_rgba_get_value(&a->light_diffuse, frame); + + if (a->flags & AUTH_3D_AMBIENT_LIGHT_DIFFUSE) + auth_3d_rgba_get_value(&a->rim_light_diffuse, frame); +} + +static void auth_3d_ambient_load(auth_3d* auth, auth_3d_ambient_file* af) { + auth_3d_ambient* a = vector_auth_3d_ambient_reserve_back(&auth->ambient); + + if (af->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) { + auth_3d_rgba_load(auth, &a->light_diffuse, &af->light_diffuse); + a->flags |= AUTH_3D_AMBIENT_LIGHT_DIFFUSE; + } + + string_copy(&af->name, &a->name); + + if (af->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) { + auth_3d_rgba_load(auth, &a->rim_light_diffuse, &af->rim_light_diffuse); + a->flags |= AUTH_3D_AMBIENT_LIGHT_DIFFUSE; + } +} + +static void auth_3d_camera_auxiliary_data_set(auth_3d_camera_auxiliary* ca, render_context* rctx) { + post_process_tone_map* tm = rctx->post_process.tone_map; + + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE) + post_process_tone_map_set_auto_exposure(tm, ca->auto_exposure_value > 0.0); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE) + post_process_tone_map_set_exposure(tm, ca->exposure_value); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA) + post_process_tone_map_set_gamma(tm, ca->gamma_value); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE) + post_process_tone_map_set_gamma_rate(tm, ca->gamma_rate_value); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_SATURATE) + post_process_tone_map_set_saturate_coeff(tm, ca->saturate_value); +} + +void auth_3d_camera_auxiliary_get_value(auth_3d_camera_auxiliary* ca, float_t frame) { + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE) + ca->auto_exposure_value = auth_3d_key_get_value(&ca->auto_exposure, frame); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE) + ca->exposure_value = auth_3d_key_get_value(&ca->exposure, frame); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE_RATE) + ca->exposure_rate_value = auth_3d_key_get_value(&ca->exposure_rate, frame); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA) + ca->gamma_value = auth_3d_key_get_value(&ca->gamma, frame); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE) + ca->gamma_rate_value = auth_3d_key_get_value(&ca->gamma_rate, frame); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_SATURATE) + ca->saturate_value = auth_3d_key_get_value(&ca->saturate, frame); +} + +static void auth_3d_camera_auxiliary_load(auth_3d* auth, auth_3d_camera_auxiliary_file* caf) { + memset(&auth->camera_auxiliary, 0, sizeof(auth_3d_camera_auxiliary)); + auth_3d_camera_auxiliary* ca = &auth->camera_auxiliary; + + if (caf->flags & A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE) { + auth_3d_key_load(auth, &ca->auto_exposure, &caf->auto_exposure); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE; + } + + if (caf->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE) { + auth_3d_key_load(auth, &ca->exposure, &caf->exposure); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_EXPOSURE; + } + + if (caf->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE) { + auth_3d_key_load(auth, &ca->exposure_rate, &caf->exposure_rate); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_EXPOSURE_RATE; + } + + if (caf->flags & A3DA_CAMERA_AUXILIARY_GAMMA) { + auth_3d_key_load(auth, &ca->gamma, &caf->gamma); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_GAMMA; + } + + if (caf->flags & A3DA_CAMERA_AUXILIARY_GAMMA_RATE) { + auth_3d_key_load(auth, &ca->gamma_rate, &caf->gamma_rate); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE; + } + + if (caf->flags & A3DA_CAMERA_AUXILIARY_SATURATE) { + auth_3d_key_load(auth, &ca->saturate, &caf->saturate); + ca->flags |= AUTH_3D_CAMERA_AUXILIARY_SATURATE; + } +} + +static void auth_3d_camera_auxiliary_restore_prev_value(auth_3d_camera_auxiliary* ca, render_context* rctx) { + post_process_tone_map* tm = rctx->post_process.tone_map; + + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE) + post_process_tone_map_set_auto_exposure(tm, true); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_EXPOSURE) + post_process_tone_map_set_exposure(tm, 1.0); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA) + post_process_tone_map_set_gamma(tm, 1.0); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE) + post_process_tone_map_set_gamma_rate(tm, 1.0); + if (ca->flags & AUTH_3D_CAMERA_AUXILIARY_SATURATE) + post_process_tone_map_set_saturate_coeff(tm, 1.0); +} + +static void auth_3d_camera_root_data_set(auth_3d_camera_root* cr, + bool left_right_reverse, mat4* mat, render_context* rctx) { + vec3 interest = cr->interest_value; + vec3 view_point = cr->view_point_value; + float_t fov = cr->fov_value; + float_t roll = cr->roll_value; + + mat4_mult_vec3_trans(mat, &interest, &interest); + mat4_mult_vec3_trans(mat, &view_point, &view_point); + + if (left_right_reverse) { + interest.x = -interest.x; + view_point.x = -view_point.x; + roll = -roll; + } + + camera* cam = rctx->camera; + camera_set_interest(cam, &interest); + camera_set_view_point(cam, &view_point); + camera_set_fov(cam, fov * RAD_TO_DEG); + camera_set_roll(cam, roll * RAD_TO_DEG); +} + +static void auth_3d_camera_root_get_value(auth_3d_camera_root* cr, float_t frame, mat4* mat) { + auth_3d_model_transform_get_value(&cr->model_transform, frame); + auth_3d_model_transform_set_mat(&cr->model_transform, mat); + + mat4 cr_mat; + mat4u_to_mat4(&cr->model_transform.mat, &cr_mat); + + vec3 view_point; + auth_3d_vec3_get_value(&cr->view_point.model_transform.translation, frame, &view_point); + mat4_mult_vec3_trans(&cr_mat, &view_point, &cr->view_point_value); + + vec3 interest; + auth_3d_vec3_get_value(&cr->interest.translation, frame, &interest); + mat4_mult_vec3_trans(&cr_mat, &interest, &cr->interest_value); + + float_t fov; + if (cr->view_point.flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_FOV) { + fov = auth_3d_key_get_value(&cr->view_point.fov, frame); + if (cr->view_point.fov_is_horizontal) + fov = atanf(tanf(fov * 0.5f) / cr->view_point.aspect) * 2.0f; + } + else { + float_t camera_aperture_h = cr->view_point.camera_aperture_h; + float_t focal_lenth = auth_3d_key_get_value(&cr->view_point.focal_length, frame); + fov = atanf((camera_aperture_h * 25.4f) * 0.5f / focal_lenth) * 2.0f; + } + cr->fov_value = fov; + + if (cr->view_point.flags & AUTH_3D_CAMERA_ROOT_VIEW_POINT_ROLL) + cr->roll_value = auth_3d_key_get_value(&cr->view_point.roll, frame); +} + +static void auth_3d_camera_root_load(auth_3d* auth, auth_3d_camera_root_file* crf) { + auth_3d_camera_root* cr = vector_auth_3d_camera_root_reserve_back(&auth->camera_root); + + auth_3d_model_transform_load(auth, &cr->interest, &crf->interest); + auth_3d_model_transform_load(auth, &cr->model_transform, &crf->model_transform); + auth_3d_camera_root_view_point_load(auth, cr, &crf->view_point); +} + +static void auth_3d_camera_root_view_point_load(auth_3d* auth, auth_3d_camera_root* cr, + auth_3d_camera_root_view_point_file* crvpf) { + auth_3d_camera_root_view_point* crvp = &cr->view_point; + + crvp->aspect = crvpf->aspect; + + if (crvpf->flags & A3DA_CAMERA_ROOT_VIEW_POINT_FOV) { + auth_3d_key_load(auth, &crvp->fov, &crvpf->fov); + crvp->fov_is_horizontal = crvpf->fov_is_horizontal; + crvp->flags |= AUTH_3D_CAMERA_ROOT_VIEW_POINT_FOV; + } + else { + crvp->camera_aperture_h = crvpf->camera_aperture_h; + crvp->camera_aperture_w = crvpf->camera_aperture_w; + auth_3d_key_load(auth, &crvp->focal_length, &crvpf->focal_length); + } + + auth_3d_model_transform_load(auth, &crvp->model_transform, &crvpf->model_transform); + + if (crvpf->flags & A3DA_CAMERA_ROOT_VIEW_POINT_ROLL) { + auth_3d_key_load(auth, &crvp->roll, &crvpf->roll); + crvp->flags |= AUTH_3D_CAMERA_ROOT_VIEW_POINT_ROLL; + } +} + +static void auth_3d_chara_data_set(auth_3d_chara* c, mat4* parent_mat, render_context* rctx) { + +} + +static void auth_3d_chara_get_value(auth_3d_chara* c, float_t frame) { + auth_3d_model_transform_get_value(&c->model_transform, frame); +} + +static void auth_3d_chara_load(auth_3d* auth, auth_3d_chara_file* cf) { + auth_3d_chara* c = vector_auth_3d_chara_reserve_back(&auth->chara); + + auth_3d_model_transform_load(auth, &c->model_transform, &cf->model_transform); + string_copy(&cf->name, &c->name); +} + +static void auth_3d_curve_get_value(auth_3d_curve* c, float_t frame) { + c->value = auth_3d_key_get_value(&c->curve, frame); +} + +static void auth_3d_curve_load(auth_3d* auth, auth_3d_curve_file* cf) { + auth_3d_curve* c = vector_auth_3d_curve_reserve_back(&auth->curve); + + auth_3d_key_load(auth, &c->curve, &cf->curve); + string_copy(&cf->name, &c->name); +} + +static void auth_3d_dof_data_set(auth_3d_dof* d, render_context* rctx) { + if (!d->has_dof) + return; + + vec3 view_point; + camera_get_view_point(rctx->camera, &view_point); + + vec3 diff; + float_t focus; + vec3_sub(d->model_transform.translation_value, view_point, diff); + vec3_length(diff, focus); + + dof_pv pv; + pv.enable = fabsf(d->model_transform.rotation_value.z) > 0.000001f; + pv.f2.distance_to_focus = focus; + pv.f2.focus_range = d->model_transform.scale_value.y; + pv.f2.fuzzing_range = d->model_transform.rotation_value.y; + pv.f2.ratio = d->model_transform.rotation_value.z; + post_process_dof_set_dof_pv(rctx->post_process.dof, &pv); +} + +static void auth_3d_dof_get_value(auth_3d_dof* d, float_t frame) { + if (!d->has_dof) + return; + + auth_3d_model_transform_get_value(&d->model_transform, frame); +} + +static void auth_3d_dof_load(auth_3d* auth, auth_3d_dof_file* df) { + memset(&auth->dof, 0, sizeof(auth_3d_dof)); + auth_3d_dof* d = &auth->dof; + + if (df->has_dof) { + auth_3d_model_transform_load(auth, &d->model_transform, &df->model_transform); + d->has_dof = true; + } +} + +static void auth_3d_dof_restore_prev_value(auth_3d_dof* d, render_context* rctx) { + if (!d->has_dof) + return; + + post_process_dof_set_dof_pv(rctx->post_process.dof, 0); +} + +static void auth_3d_event_load(auth_3d* auth, auth_3d_event_file* ef) { + auth_3d_event* e = vector_auth_3d_event_reserve_back(&auth->event); + + e->begin = ef->begin; + e->clip_begin = ef->clip_begin; + e->clip_end = ef->clip_end; + e->end = ef->end; + string_copy(&ef->name, &e->name); + string_copy(&ef->param_1, &e->param_1); + string_copy(&ef->ref, &e->ref); + e->time_ref_scale = ef->time_ref_scale; + switch (ef->type) { + case A3DA_EVENT_MISC: + default: + e->type = AUTH_3D_EVENT_MISC; + case A3DA_EVENT_FILT: + e->type = AUTH_3D_EVENT_FILT; + case A3DA_EVENT_FX: + e->type = AUTH_3D_EVENT_FX; + case A3DA_EVENT_SND: + e->type = AUTH_3D_EVENT_SND; + case A3DA_EVENT_MOT: + e->type = AUTH_3D_EVENT_MOT; + case A3DA_EVENT_A2D: + e->type = AUTH_3D_EVENT_A2D; + } +} + +static void auth_3d_fog_data_set(auth_3d_fog* f, render_context* rctx) { + fog_id id = f->id; + if (id < FOG_DEPTH || id > FOG_BUMP) + return; + + fog* data = &rctx->fog_data[id]; + if (f->flags & AUTH_3D_FOG_COLOR) { + if (~f->flags_init & AUTH_3D_FOG_COLOR) { + vec4 color_init; + fog_get_color(data, &color_init); + vec4_to_vec4u(color_init, f->color_init); + f->flags_init |= AUTH_3D_FOG_COLOR; + } + + vec4 color; + vec4u_to_vec4(f->color.value, color); + fog_set_color(data, &color); + } + + if (f->flags & AUTH_3D_FOG_DENSITY) { + if (~f->flags_init & AUTH_3D_FOG_DENSITY) { + f->density_init = fog_get_density(data); + f->flags_init |= AUTH_3D_FOG_DENSITY; + } + + fog_set_density(data, f->density_value); + } + + if (f->flags & AUTH_3D_FOG_END) { + if (~f->flags_init & AUTH_3D_FOG_END) { + f->end_init = fog_get_end(data); + f->flags_init |= AUTH_3D_FOG_END; + } + + fog_set_end(data, f->end_value); + } + + if (f->flags & AUTH_3D_FOG_START) { + if (~f->flags_init & AUTH_3D_FOG_START) { + f->start_init = fog_get_start(data); + f->flags_init |= AUTH_3D_FOG_START; + } + + fog_set_start(data, f->start_value); + } +} + +static void auth_3d_fog_get_value(auth_3d_fog* f, float_t frame) { + if (f->flags & AUTH_3D_FOG_DENSITY) + f->density_value = auth_3d_key_get_value(&f->density, frame); + if (f->flags & AUTH_3D_FOG_START) + f->start_value = auth_3d_key_get_value(&f->start, frame); + if (f->flags & AUTH_3D_FOG_END) + f->end_value = auth_3d_key_get_value(&f->end, frame); + if (f->flags & AUTH_3D_FOG_COLOR) + auth_3d_rgba_get_value(&f->color, frame); +} + +static void auth_3d_fog_load(auth_3d* auth, auth_3d_fog_file* ff) { + auth_3d_fog* f = vector_auth_3d_fog_reserve_back(&auth->fog); + + if (ff->flags & A3DA_FOG_COLOR) { + auth_3d_rgba_load(auth, &f->color, &ff->color); + f->flags |= AUTH_3D_FOG_COLOR; + } + + if (ff->flags & A3DA_FOG_DENSITY) { + auth_3d_key_load(auth, &f->density, &ff->density); + f->flags |= AUTH_3D_FOG_DENSITY; + } + + if (ff->flags & A3DA_FOG_END) { + auth_3d_key_load(auth, &f->end, &ff->end); + f->flags |= AUTH_3D_FOG_END; + } + + f->id = ff->id; + + if (ff->flags & A3DA_FOG_START) { + auth_3d_key_load(auth, &f->start, &ff->start); + f->flags |= AUTH_3D_FOG_START; + } +} + +static void auth_3d_fog_restore_prev_value(auth_3d_fog* f, render_context* rctx) { + fog_id id = f->id; + if (id < FOG_DEPTH || id > FOG_BUMP) + return; + + fog* data = &rctx->fog_data[id]; + if (f->flags_init & AUTH_3D_FOG_COLOR) { + vec4 color; + vec4u_to_vec4(f->color_init, color); + fog_set_color(data, &color); + } + + if (f->flags_init & AUTH_3D_FOG_DENSITY) + fog_set_density(data, f->density_value); + + if (f->flags_init & AUTH_3D_FOG_END) + fog_set_end(data, f->end_value); + + if (f->flags_init & AUTH_3D_FOG_START) + fog_set_start(data, f->start_value); +} + +static void auth_3d_light_data_set(auth_3d_light* l, render_context* rctx) { + light_set* set_data = &rctx->light_set_data[LIGHT_SET_MAIN]; + + light_id id = l->id; + if (id < LIGHT_CHARA || id > LIGHT_PROJECTION) + return; + + light_data* data = &set_data->lights[id]; + if (l->flags & AUTH_3D_LIGHT_AMBIENT) { + if (~l->flags_init & AUTH_3D_LIGHT_AMBIENT) { + vec4 ambient_init; + light_get_ambient(data, &ambient_init); + vec4_to_vec4u(ambient_init, l->ambient_init); + l->flags_init |= AUTH_3D_LIGHT_AMBIENT; + } + + vec4 ambient; + vec4u_to_vec4(l->ambient.value, ambient); + light_set_ambient(data, &ambient); + } + + if (l->flags & AUTH_3D_LIGHT_DIFFUSE) { + if (~l->flags_init & AUTH_3D_LIGHT_DIFFUSE) { + vec4 diffuse_init; + light_get_diffuse(data, &diffuse_init); + vec4_to_vec4u(diffuse_init, l->diffuse_init); + l->flags_init |= AUTH_3D_LIGHT_DIFFUSE; + } + + vec4 diffuse; + vec4u_to_vec4(l->diffuse.value, diffuse); + light_set_diffuse(data, &diffuse); + } + + if (l->flags & AUTH_3D_LIGHT_POSITION) + light_set_position(data, &l->position.translation_value); + + if (l->flags & AUTH_3D_LIGHT_SPECULAR) { + if (~l->flags_init & AUTH_3D_LIGHT_SPECULAR) { + vec4 specular_init; + light_get_specular(data, &specular_init); + vec4_to_vec4u(specular_init, l->specular_init); + l->flags_init |= AUTH_3D_LIGHT_SPECULAR; + } + + vec4 specular; + vec4u_to_vec4(l->specular.value, specular); + light_set_specular(data, &specular); + } + + if (l->flags & AUTH_3D_LIGHT_SPOT_DIRECTION) + light_set_spot_direction(data, &l->spot_direction.translation_value); + + if (l->flags & AUTH_3D_LIGHT_TONE_CURVE) { + if (~l->flags_init & AUTH_3D_LIGHT_TONE_CURVE) { + light_get_tone_curve(data, &l->tone_curve_init); + l->flags_init |= AUTH_3D_LIGHT_TONE_CURVE; + } + + light_set_tone_curve(data, (vec3*)&l->tone_curve.value); + } +} + +static void auth_3d_light_get_value(auth_3d_light* l, float_t frame) { + if (l->flags & AUTH_3D_LIGHT_AMBIENT) + auth_3d_rgba_get_value(&l->ambient, frame); + if (l->flags & AUTH_3D_LIGHT_CONE_ANGLE) + l->cone_angle_value = auth_3d_key_get_value(&l->cone_angle, frame); + if (l->flags & AUTH_3D_LIGHT_CONSTANT) + l->constant_value = auth_3d_key_get_value(&l->constant, frame); + if (l->flags & AUTH_3D_LIGHT_DIFFUSE) + auth_3d_rgba_get_value(&l->diffuse, frame); + if (l->flags & AUTH_3D_LIGHT_DROP_OFF) + l->drop_off_value = auth_3d_key_get_value(&l->drop_off, frame); + if (l->flags & AUTH_3D_LIGHT_FAR) + l->far_value = auth_3d_key_get_value(&l->_far, frame); + if (l->flags & AUTH_3D_LIGHT_INTENSITY) + l->intensity_value = auth_3d_key_get_value(&l->intensity, frame); + if (l->flags & AUTH_3D_LIGHT_LINEAR) + l->linear_value = auth_3d_key_get_value(&l->linear, frame); + if (l->flags & AUTH_3D_LIGHT_POSITION) + auth_3d_model_transform_get_value(&l->position, frame); + if (l->flags & AUTH_3D_LIGHT_QUADRATIC) + l->quadratic_value = auth_3d_key_get_value(&l->quadratic, frame); + if (l->flags & AUTH_3D_LIGHT_SPECULAR) + auth_3d_rgba_get_value(&l->specular, frame); + if (l->flags & AUTH_3D_LIGHT_SPOT_DIRECTION) + auth_3d_model_transform_get_value(&l->spot_direction, frame); + if (l->flags & AUTH_3D_LIGHT_TONE_CURVE) + auth_3d_rgba_get_value(&l->tone_curve, frame); + +} + +static void auth_3d_light_load(auth_3d* auth, auth_3d_light_file* lf) { + auth_3d_light* l = vector_auth_3d_light_reserve_back(&auth->light); + + if (lf->flags & A3DA_LIGHT_AMBIENT) { + auth_3d_rgba_load(auth, &l->ambient, &lf->ambient); + l->flags |= AUTH_3D_LIGHT_AMBIENT; + } + + if (lf->flags & A3DA_LIGHT_CONE_ANGLE) { + auth_3d_key_load(auth, &l->cone_angle, &lf->cone_angle); + l->flags |= AUTH_3D_LIGHT_CONE_ANGLE; + } + + if (lf->flags & A3DA_LIGHT_CONSTANT) { + auth_3d_key_load(auth, &l->constant, &lf->constant); + l->flags |= AUTH_3D_LIGHT_CONSTANT; + } + + if (lf->flags & A3DA_LIGHT_DIFFUSE) { + auth_3d_rgba_load(auth, &l->diffuse, &lf->diffuse); + l->flags |= AUTH_3D_LIGHT_DIFFUSE; + } + + if (lf->flags & A3DA_LIGHT_DROP_OFF) { + auth_3d_key_load(auth, &l->drop_off, &lf->drop_off); + l->flags |= AUTH_3D_LIGHT_DROP_OFF; + } + + if (lf->flags & A3DA_LIGHT_FAR) { + auth_3d_key_load(auth, &l->_far, &lf->_far); + l->flags |= AUTH_3D_LIGHT_FAR; + } + + l->id = lf->id; + + if (lf->flags & A3DA_LIGHT_INTENSITY) { + auth_3d_key_load(auth, &l->intensity, &lf->intensity); + l->flags |= AUTH_3D_LIGHT_INTENSITY; + } + + if (lf->flags & A3DA_LIGHT_LINEAR) { + auth_3d_key_load(auth, &l->linear, &lf->linear); + l->flags |= AUTH_3D_LIGHT_LINEAR; + } + + if (lf->flags & A3DA_LIGHT_POSITION) { + auth_3d_model_transform_load(auth, &l->position, &lf->position); + l->flags |= AUTH_3D_LIGHT_POSITION; + } + + if (lf->flags & A3DA_LIGHT_QUADRATIC) { + auth_3d_key_load(auth, &l->quadratic, &lf->quadratic); + l->flags |= AUTH_3D_LIGHT_QUADRATIC; + } + + if (lf->flags & A3DA_LIGHT_SPECULAR) { + auth_3d_rgba_load(auth, &l->specular, &lf->specular); + l->flags |= AUTH_3D_LIGHT_SPECULAR; + } + + if (lf->flags & A3DA_LIGHT_SPOT_DIRECTION) { + auth_3d_model_transform_load(auth, &l->spot_direction, &lf->spot_direction); + l->flags |= AUTH_3D_LIGHT_SPOT_DIRECTION; + } + + if (lf->flags & A3DA_LIGHT_TONE_CURVE) { + auth_3d_rgba_load(auth, &l->tone_curve, &lf->tone_curve); + l->flags |= AUTH_3D_LIGHT_TONE_CURVE; + } + + string_copy(&lf->type, &l->type); +} + +static void auth_3d_light_restore_prev_value(auth_3d_light* l, render_context* rctx) { + light_set* set_data = &rctx->light_set_data[LIGHT_SET_MAIN]; + + light_id id = l->id; + if (id < LIGHT_CHARA || id > LIGHT_PROJECTION) + return; + + light_data* data = &set_data->lights[id]; + if (l->flags_init & AUTH_3D_LIGHT_AMBIENT) { + vec4 ambient_init; + vec4u_to_vec4(l->ambient_init, ambient_init); + light_set_ambient(data, &ambient_init); + } + + if (l->flags_init & AUTH_3D_LIGHT_DIFFUSE) { + vec4 diffuse_init; + vec4u_to_vec4(l->diffuse_init, diffuse_init); + light_set_diffuse(data, &diffuse_init); + } + + if (l->flags_init & AUTH_3D_LIGHT_SPECULAR) { + vec4 specular_init; + vec4u_to_vec4(l->specular_init, specular_init); + light_set_specular(data, &specular_init); + } + + if (l->flags_init & AUTH_3D_LIGHT_TONE_CURVE) + light_set_tone_curve(data, &l->tone_curve_init); +} + +static void auth_3d_m_object_hrc_get_mat(auth_3d_m_object_hrc* moh, mat4* mat) { + for (auth_3d_object_node* i = moh->node.begin; i != moh->node.end; i++) + if (i->mat) { + *mat = *i->mat; + return; + } + + mat4u_to_mat4(&moh->node.begin[0].model_transform.mat, mat); +} + +static void auth_3d_m_object_hrc_get_value(auth_3d_m_object_hrc* moh, float_t frame) { + auth_3d_object_model_transform_get_value(&moh->model_transform, frame); + auth_3d_object_model_transform_set_mat_inner(&moh->model_transform); + + for (auth_3d_object_instance* i = moh->instance.begin; i != moh->instance.end; i++) { + auth_3d_object_model_transform_get_value(&i->model_transform, frame); + auth_3d_object_model_transform_set_mat_inner(&i->model_transform); + } + + for (auth_3d_object_node* i = moh->node.begin; i != moh->node.end; i++) { + auth_3d_object_model_transform_get_value(&i->model_transform, frame); + auth_3d_object_model_transform_set_mat_inner(&i->model_transform); + } +} + +static void auth_3d_m_object_hrc_load(auth_3d* auth, + auth_3d_m_object_hrc_file* mohf, object_database* obj_db) { + auth_3d_m_object_hrc* moh + = vector_auth_3d_m_object_hrc_reserve_back(&auth->m_object_hrc); + + vector_auth_3d_object_node_reserve(&moh->node, mohf->node.end - mohf->node.begin); + for (auth_3d_object_node_file* i = mohf->node.begin; i != mohf->node.end; i++) + auth_3d_object_node_load(auth, &moh->node, i); + + auth_3d_object_model_transform_load(auth, &moh->model_transform, &mohf->model_transform); + string_copy(&mohf->name, &moh->name); + + for (auth_3d_object_instance_file* i = mohf->instance.begin; i != mohf->instance.end; i++) + auth_3d_object_instance_load(auth, moh, i, obj_db); +} + +static void auth_3d_m_object_hrc_data_set(auth_3d_m_object_hrc* moh, auth_3d* auth, render_context* rctx) { + if (!moh->model_transform.visible) + return; + + object_data* object_data = &rctx->object_data; + object_database* obj_db = &rctx->data->data_ft.obj_db; + texture_database* tex_db = &rctx->data->data_ft.tex_db; + + for (auth_3d_object_instance* i = moh->instance.begin; i != moh->instance.end; i++) { + if (!i->model_transform.visible) + return; + + draw_task_flags flags = DRAW_TASK_SSS; + shadow_type_enum shadow_type = SHADOW_CHARA; + if (i->shadow) { + flags |= DRAW_TASK_4 | DRAW_TASK_SHADOW; + shadow_type = SHADOW_STAGE; + } + + object_data_set_draw_task_flags(object_data, flags); + object_data_set_shadow_type(object_data, shadow_type); + + shadow* shad = rctx->draw_pass.shadow_ptr; + if (shad && flags & DRAW_TASK_SHADOW) { + object_data_set_shadow_type(object_data, SHADOW_STAGE); + + mat4u* m = &moh->model_transform.mat; + for (auth_3d_object_node* i = moh->node.begin; i != moh->node.end; i++) + if (i->mat) { + m = (mat4u*)i->mat; + break; + } + + mat4 mat; + mat4 t; + mat4u_to_mat4(&i->model_transform.mat, &mat); + mat4u_to_mat4(m, &t); + mat4_mult(&mat, &t, &mat); + + vec3 pos = *(vec3*)&mat.row3; + pos.y -= 0.2f; + vector_vec3_push_back(&shad->field_1D0[shadow_type], &pos); + } + + if (i->mats.end - i->mats.begin > 0) { + mat4 mat; + mat4u_to_mat4(&i->model_transform.mat, &mat); + draw_task_add_draw_object_by_object_info_object_skin(rctx, + i->object_info, 0, 0, auth->alpha, i->mats.begin, 0, 0, &mat); + } + } + + object_data_set_draw_task_flags(object_data, 0); + object_data_set_shadow_type(object_data, SHADOW_CHARA); +} + +static void auth_3d_m_object_hrc_list_get_value(auth_3d_m_object_hrc* moh, mat4* parent_mat) { + if (!moh->model_transform.visible) + return; + + auth_3d_object_node* node = moh->node.begin; + size_t instance_count = moh->instance.end - moh->instance.begin; + + auth_3d_m_object_hrc_nodes_mat_mult(moh); + + auth_3d_object_model_transform_mat_mult(&moh->model_transform, parent_mat); + + mat4 mat; + mat4u_to_mat4(&moh->model_transform.mat, &mat); + + for (auth_3d_object_instance* i = moh->instance.begin; i != moh->instance.end; i++) { + if (!i->model_transform.visible) + continue; + + auth_3d_object_model_transform_mat_mult(&i->model_transform, &mat); + int32_t* object_bone_indices = i->object_bone_indices.begin; + size_t object_bone_indices_count = i->object_bone_indices.end - i->object_bone_indices.begin; + mat4* mats = i->mats.begin; + for (size_t j = 0; j < object_bone_indices_count; j++) + mat4u_to_mat4(&node[object_bone_indices[j]].model_transform.mat, &mats[j]); + } +} + +static void auth_3d_m_object_hrc_nodes_mat_mult(auth_3d_m_object_hrc* moh) { + auth_3d_object_node* node = moh->node.begin; + + for (auth_3d_object_node* i = moh->node.begin; i != moh->node.end; i++) + if (i->parent >= 0) { + mat4 mat; + mat4u_to_mat4(&node[i->parent].model_transform.mat, &mat); + auth_3d_object_model_transform_mat_mult(&i->model_transform, &mat); + } + else + i->model_transform.mat = i->model_transform.mat_inner; +} + +static void auth_3d_material_list_load(auth_3d* auth, auth_3d_material_list_file* mlf) { + auth_3d_material_list* ml = vector_auth_3d_material_list_reserve_back(&auth->material_list); + + if (mlf->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) { + auth_3d_rgba_load(auth, &ml->blend_color, &mlf->blend_color); + ml->flags |= AUTH_3D_MATERIAL_LIST_BLEND_COLOR; + } + + if (mlf->flags & A3DA_MATERIAL_LIST_GLOW_INTENSITY) { + auth_3d_key_load(auth, &ml->glow_intensity, &mlf->glow_intensity); + ml->flags |= AUTH_3D_MATERIAL_LIST_GLOW_INTENSITY; + } + + if (mlf->flags & A3DA_MATERIAL_LIST_INCANDESCENCE) { + auth_3d_rgba_load(auth, &ml->incandescence, &mlf->incandescence); + ml->flags |= AUTH_3D_MATERIAL_LIST_INCANDESCENCE; + } + + string_copy(&mlf->name, &ml->name); +} + +static void auth_3d_object_get_value(auth_3d_object* o, float_t frame) { + auth_3d_model_transform_get_value(&o->model_transform, frame); + auth_3d_object_curve_get_value(&o->pattern, frame); + auth_3d_object_curve_get_value(&o->morph, frame); + for (auth_3d_object_texture_pattern* i = o->texture_pattern.begin; + i != o->texture_pattern.end; i++) + auth_3d_object_texture_pattern_get_value(i, frame); + for (auth_3d_object_texture_transform* i = o->texture_transform.begin; + i != o->texture_transform.end; i++) + auth_3d_object_texture_transform_get_value(i, frame); +} + +static void auth_3d_object_load(auth_3d* auth, auth_3d_object_file* of, + object_database* obj_db, texture_database* tex_db) { + auth_3d_object* o = vector_auth_3d_object_reserve_back(&auth->object); + + auth_3d_model_transform_load(auth, &o->model_transform, &of->model_transform); + auth_3d_object_curve_load(auth, &o->morph, &of->morph, of->morph_offset); + string_copy(&of->name, &o->name); + string_copy(&of->parent_name, &o->parent_name); + string_copy(&of->parent_node, &o->parent_node); + auth_3d_object_curve_load(auth, &o->pattern, &of->pattern, of->pattern_offset); + + vector_auth_3d_object_texture_pattern_reserve(&o->texture_pattern, + of->texture_pattern.end - of->texture_pattern.begin); + for (auth_3d_object_texture_pattern_file* i = of->texture_pattern.begin; + i != of->texture_pattern.end; i++) + auth_3d_object_texture_pattern_load(auth, o, i, tex_db); + + vector_auth_3d_object_texture_transform_reserve(&o->texture_transform, + of->texture_transform.end - of->texture_transform.begin); + for (auth_3d_object_texture_transform_file* i = of->texture_transform.begin; + i != of->texture_transform.end; i++) + auth_3d_object_texture_transform_load(auth, o, i, tex_db); + + string_copy(&of->uid_name, &o->uid_name); + + o->reflect = strstr(string_data(&o->uid_name), "_REFLECT"); + o->refract = strstr(string_data(&o->uid_name), "_REFRACT"); + + o->object_info = object_database_get_object_info(obj_db, string_data(&o->uid_name)); +} + +static void auth_3d_object_curve_get_value(auth_3d_object_curve* oc, float_t frame) { + auth_3d_curve* c = oc->curve; + if (!c) + return; + + if (oc->frame_offset != 0.0f) { + frame += oc->frame_offset; + if (frame >= c->curve.max_frame) + frame -= c->curve.max_frame; + } + oc->value = auth_3d_key_get_value(&c->curve, frame); +} + +static void auth_3d_object_curve_load(auth_3d* auth, auth_3d_object_curve* oc, + string* name, float_t frame_offset) { + oc->curve = 0; + string_copy(name, &oc->name); + oc->frame_offset = 0.0f; + oc->value = 0.0f; + + for (auth_3d_curve* i = auth->curve.begin; i != auth->curve.end; i++) + if (string_compare(name, &i->name)) { + oc->curve = i; + oc->frame_offset = frame_offset; + return; + } +} + +static void auth_3d_object_data_set(auth_3d_object* o, auth_3d* auth, render_context* rctx) { + if (!o->model_transform.visible) + return; + + mat4 mat; + mat4u_to_mat4(&o->model_transform.mat, &mat); + + object_data* object_data = &rctx->object_data; + object_database* obj_db = &rctx->data->data_ft.obj_db; + texture_database* tex_db = &rctx->data->data_ft.tex_db; + + draw_task_flags flags = 0; + if (o->reflect) + flags |= DRAW_TASK_NO_TRANSLUCENCY | DRAW_TASK_REFLECT; + if (o->refract) + flags |= DRAW_TASK_NO_TRANSLUCENCY | DRAW_TASK_REFRACT; + + object_data_set_draw_task_flags(object_data, flags); + + char buf[0x80]; + int32_t tex_pat_count = 0; + texture_pattern_struct tex_pat[TEXTURE_PATTERN_COUNT]; + + for (auth_3d_object_texture_pattern* i = o->texture_pattern.begin; + i != o->texture_pattern.end; i++) { + if (!i->pattern.curve || i->name.length <= 3) + continue; + else if (tex_pat_count >= TEXTURE_PATTERN_COUNT) + break; + + float_t pat = i->pattern.value; + if (pat > 0.0f) + pat = (float_t)(int32_t)(pat + 0.5f); + else if (pat < 0.0f) + pat = (float_t)(int32_t)(pat - 0.5f); + + sprintf_s(buf, sizeof(buf), "%.*s%03d", (int32_t)(i->name.length - 3), + string_data(&i->name), (int32_t)pat); + + tex_pat[tex_pat_count].src = i->texture_id; + tex_pat[tex_pat_count].dst = texture_database_get_texture_id(tex_db, buf); + tex_pat_count++; + } + + if (tex_pat_count) + object_data_set_texture_pattern(object_data, tex_pat_count, tex_pat); + + int32_t tex_trans_count = 0; + texture_transform_struct tex_trans[TEXTURE_TRANSFORM_COUNT]; + + for (auth_3d_object_texture_transform* i = o->texture_transform.begin; + i != o->texture_transform.end; i++) { + if (tex_trans_count >= TEXTURE_TRANSFORM_COUNT) + break; + + tex_trans[tex_trans_count].id = i->texture_id; + tex_trans[tex_trans_count].mat = i->mat; + tex_trans_count++; + } + + if (tex_trans_count) + object_data_set_texture_transform(object_data, tex_trans_count, tex_trans); + + char* uid_name = string_data(&o->uid_name); + int32_t uid_name_length = (int32_t)o->uid_name.length; + + if (uid_name_length <= 3) + draw_task_add_draw_object_by_object_info_opaque(rctx, &mat, o->object_info); + else if (o->morph.curve) { + float_t morph = o->morph.value; + int32_t morph_int = (int32_t)morph; + morph = fmodf(morph, 1.0f); + if (morph > 0.0f && morph < 1.0f) { + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, morph_int + 1); + object_info morph_obj_info = object_database_get_object_info(obj_db, buf); + if (morph_obj_info.set_id == -1 && morph_obj_info.id == -1) + morph_obj_info = o->object_info; + object_data_set_morph(object_data, morph_obj_info, morph); + + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, morph_int); + object_info obj_info = object_database_get_object_info(obj_db, buf); + draw_task_add_draw_object_by_object_info_opaque(rctx, &mat, obj_info); + object_data_set_morph(object_data, object_info_null, 0.0f); + } + else { + if (morph >= 1.0f) + morph_int++; + + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, morph_int); + object_info obj_info = object_database_get_object_info(obj_db, buf); + if (obj_info.set_id == -1 && obj_info.id == -1) + obj_info = o->object_info; + draw_task_add_draw_object_by_object_info_opaque(rctx, &mat, obj_info); + } + } + else if (o->pattern.curve) { + float_t pat = o->pattern.value; + if (pat > 0.0f) + pat = (float_t)(int32_t)(pat + 0.5f); + else if (pat < 0.0f) + pat = (float_t)(int32_t)(pat - 0.5f); + + sprintf_s(buf, sizeof(buf), "%.*s%03d", uid_name_length - 3, uid_name, (int32_t)pat); + object_info obj_info = object_database_get_object_info(obj_db, buf); + draw_task_add_draw_object_by_object_info_opaque(rctx, &mat, obj_info); + } + else + draw_task_add_draw_object_by_object_info_opaque(rctx, &mat, o->object_info); + + object_data_set_texture_transform(object_data, 0, 0); + object_data_set_texture_pattern(object_data, 0, 0); + object_data_set_draw_task_flags(object_data, 0); + + for (ptr_auth_3d_object* i = o->children_object.begin; + i != o->children_object.end; i++) + auth_3d_object_data_set(*i, auth, rctx); + + for (ptr_auth_3d_object_hrc* i = o->children_object_hrc.begin; + i != o->children_object_hrc.end; i++) + auth_3d_object_hrc_data_set(*i, auth, rctx); +} + +static void auth_3d_object_list_get_value(auth_3d_object* o, mat4* parent_mat) { + if (!o->model_transform.visible) + return; + + auth_3d_model_transform_set_mat(&o->model_transform, parent_mat); + + mat4 mat; + mat4u_to_mat4(&o->model_transform.mat, &mat); + + for (auth_3d_object** i = o->children_object.begin; + i != o->children_object.end; i++) + auth_3d_object_list_get_value(*i, &mat); + for (auth_3d_object_hrc** j = o->children_object_hrc.begin; + j != o->children_object_hrc.end; j++) + auth_3d_object_hrc_list_get_value(*j, &mat); +} + +static void auth_3d_object_hrc_get_value(auth_3d_object_hrc* oh, float_t frame) { + for (auth_3d_object_node* i = oh->node.begin; i != oh->node.end; i++) + auth_3d_object_model_transform_get_value(&i->model_transform, frame); +} + +static void auth_3d_object_hrc_load(auth_3d* auth, + auth_3d_object_hrc_file* ohf, object_database* obj_db) { + auth_3d_object_hrc* oh = vector_auth_3d_object_hrc_reserve_back(&auth->object_hrc); + + string_copy(&ohf->name, &oh->name); + + vector_auth_3d_object_node_reserve(&oh->node, ohf->node.end - ohf->node.begin); + for (auth_3d_object_node_file* i = ohf->node.begin; i != ohf->node.end; i++) + auth_3d_object_node_load(auth, &oh->node, i); + + string_copy(&ohf->parent_name, &oh->parent_name); + string_copy(&ohf->parent_node, &oh->parent_node); + oh->shadow = ohf->shadow; + string_copy(&ohf->uid_name, &oh->uid_name); + + oh->reflect = strstr(string_data(&oh->uid_name), "_REFLECT"); + oh->refract = strstr(string_data(&oh->uid_name), "_REFRACT"); + + oh->object_info = object_database_get_object_info(obj_db, string_data(&oh->uid_name)); + + object* obj = object_storage_get_object(oh->object_info); + if (!obj || !obj->skin_init) + return; + + object_skin* skin = &obj->skin; + + oh->mats = vector_empty(mat4); + vector_mat4_reserve(&oh->mats, skin->bones_count); + oh->mats.end += skin->bones_count; + mat4* mats = oh->mats.begin; + + for (auth_3d_object_node* i = oh->node.begin; i != oh->node.end; i++) { + i->bone_id = -1; + for (int32_t j = 0; j != skin->bones_count; j++) + if (string_compare(&i->name, &skin->bones[j].name)) { + i->bone_id = skin->bones[j].id; + break; + } + + if (i->bone_id > -1 && !(i->bone_id & 0x8000)) + i->mat = &mats[i->bone_id]; + } +} + +static void auth_3d_object_hrc_data_set(auth_3d_object_hrc* oh, auth_3d* auth, render_context* rctx) { + if (!oh->node.begin[0].model_transform.visible) + return; + + object_data* object_data = &rctx->object_data; + object_database* obj_db = &rctx->data->data_ft.obj_db; + texture_database* tex_db = &rctx->data->data_ft.tex_db; + + draw_task_flags flags = DRAW_TASK_SSS; + if (oh->shadow) + flags |= DRAW_TASK_4 | DRAW_TASK_SHADOW; + if (oh->reflect) + flags |= DRAW_TASK_NO_TRANSLUCENCY | DRAW_TASK_REFLECT; + if (oh->refract) + flags |= DRAW_TASK_NO_TRANSLUCENCY | DRAW_TASK_REFRACT; + + object_data_set_draw_task_flags(object_data, flags); + object_data_set_shadow_type(object_data, SHADOW_CHARA); + + shadow* shad = rctx->draw_pass.shadow_ptr; + if (shad && flags & DRAW_TASK_SHADOW) { + object_data_set_shadow_type(object_data, SHADOW_STAGE); + + mat4u* m = &oh->node.begin->model_transform.mat; + for (auth_3d_object_node* i = oh->node.begin; i != oh->node.end; i++) + if (i->mat) { + m = (mat4u*)i->mat; + break; + } + + vec3 pos = *(vec3*)&m->row3; + pos.y -= 0.2f; + vector_vec3_push_back(&shad->field_1D0[SHADOW_STAGE], &pos); + } + + if (oh->mats.end - oh->mats.begin > 0) { + mat4 mat = mat4_identity; + draw_task_add_draw_object_by_object_info_object_skin(rctx, + oh->object_info, 0, 0, auth->alpha, oh->mats.begin, 0, 0, &mat); + } + + object_data_set_draw_task_flags(object_data, 0); + object_data_set_shadow_type(object_data, SHADOW_CHARA); + + for (ptr_auth_3d_object* i = oh->children_object.begin; + i != oh->children_object.end; i++) + auth_3d_object_data_set(*i, auth, rctx); + + for (ptr_auth_3d_object_hrc* i = oh->children_object_hrc.begin; + i != oh->children_object_hrc.end; i++) + auth_3d_object_hrc_data_set(*i, auth, rctx); +} + +static void auth_3d_object_hrc_list_get_value(auth_3d_object_hrc* oh, mat4* mat) { + if (!(oh->node.end - oh->node.begin) + || ! oh->node.begin[0].model_transform.visible) + return; + + auth_3d_object_hrc_nodes_mat_mult(oh, mat); + + int32_t* childer_object_parent_node = oh->childer_object_parent_node.begin; + size_t children_object_count = oh->children_object.end - oh->children_object.begin; + for (size_t i = 0; i < children_object_count; i++) { + mat4 mat; + mat4u_to_mat4(&oh->node.begin[childer_object_parent_node[i]].model_transform.mat, &mat); + auth_3d_object_list_get_value(oh->children_object.begin[i], &mat); + } + + int32_t* childer_object_hrc_parent_node = oh->childer_object_hrc_parent_node.begin; + size_t children_object_hrc_count = oh->children_object_hrc.end - oh->children_object_hrc.begin; + for (size_t i = 0; i < children_object_hrc_count; i++) { + mat4 mat; + mat4u_to_mat4(&oh->node.begin[childer_object_hrc_parent_node[i]].model_transform.mat, &mat); + auth_3d_object_hrc_list_get_value(oh->children_object_hrc.begin[i], &mat); + } +} + +static void auth_3d_object_hrc_nodes_mat_mult(auth_3d_object_hrc* oh, mat4* mat) { + for (auth_3d_object_node* i = oh->node.begin; i != oh->node.end; i++) { + auth_3d_object_model_transform_set_mat_inner(&i->model_transform); + + mat4 m; + if (i->parent >= 0) + mat4u_to_mat4(&oh->node.begin[i->parent].model_transform.mat, &m); + else + m = *mat; + + mat4 joint_orient; + mat4u_to_mat4(&i->joint_orient_mat, &joint_orient); + mat4_mult(&joint_orient, &m, &m); + auth_3d_object_model_transform_mat_mult(&i->model_transform, &m); + + if (i->mat) + mat4u_to_mat4(&i->model_transform.mat, i->mat); + } +} + +static void auth_3d_object_instance_load(auth_3d* auth, auth_3d_m_object_hrc* moh, + auth_3d_object_instance_file* oif, object_database* obj_db) { + auth_3d_object_instance* oi + = vector_auth_3d_object_instance_reserve_back(&moh->instance); + + auth_3d_object_model_transform_load(auth, &oi->model_transform, &oif->model_transform); + string_copy(&oif->name, &oi->name); + oi->shadow = oif->shadow; + string_copy(&oif->uid_name, &oi->uid_name); + + oi->object_info = object_database_get_object_info(obj_db, string_data(&oi->uid_name)); + + object* obj = object_storage_get_object(oi->object_info); + if (!obj || !obj->skin_init) + return; + + object_skin* skin = &obj->skin; + + oi->object_bone_indices = vector_empty(int32_t); + vector_int32_t_reserve(&oi->object_bone_indices, skin->bones_count); + oi->object_bone_indices.end += skin->bones_count; + int32_t* object_bone_indices = oi->object_bone_indices.begin; + + oi->mats = vector_empty(mat4); + vector_mat4_reserve(&oi->mats, skin->bones_count); + oi->mats.end += skin->bones_count; + mat4* mats = oi->mats.begin; + + for (int32_t i = 0; i < skin->bones_count; i++) + for (auth_3d_object_node* j = moh->node.begin; j != moh->node.end; j++) + if (string_compare(&j->name, &skin->bones[i].name)) { + int32_t bone_id = skin->bones[i].id; + if (!(bone_id & 0x8000)) + object_bone_indices[bone_id] = (int32_t)(j - moh->node.begin); + break; + } +} + +static void auth_3d_object_model_transform_get_value(auth_3d_object_model_transform* obj_mt, float_t frame) { + if (frame == obj_mt->frame && !obj_mt->has_rotation) + return; + + auth_3d_vec3_get_value(&obj_mt->translation, frame, &obj_mt->translation_value); + auth_3d_vec3_get_value(&obj_mt->rotation, frame, &obj_mt->rotation_value); + + if (obj_mt->has_scale) + auth_3d_vec3_get_value(&obj_mt->scale, frame, &obj_mt->scale_value); + + if (obj_mt->has_visibility) + obj_mt->visible = auth_3d_key_get_value(&obj_mt->visibility, frame) >= 0.99900001f; + + mat4 mat_rot; + vec3 rotation = obj_mt->rotation_value; + mat4_rotate(rotation.x, rotation.y, rotation.z, &mat_rot); + mat4_to_mat4u(&mat_rot, &obj_mt->mat_rot); + obj_mt->frame = frame; + obj_mt->has_rotation = false; + obj_mt->has_translation = false; +} + +static void auth_3d_object_model_transform_load(auth_3d* auth, + auth_3d_object_model_transform* omt, auth_3d_model_transform_file* mtf) { + omt->mat = mat4u_identity; + omt->mat_inner = mat4u_identity; + omt->mat_rot = mat4u_identity; + memset(&omt->translation, 0, sizeof(auth_3d_vec3)); + memset(&omt->rotation, 0, sizeof(auth_3d_vec3)); + memset(&omt->scale, 0, sizeof(auth_3d_vec3)); + memset(&omt->visibility, 0, sizeof(auth_3d_key)); + omt->translation_value = vec3_null; + omt->rotation_value = vec3_null; + omt->scale_value = vec3_identity; + omt->visible = false; + omt->frame = 0.0f; + omt->has_rotation = false; + omt->has_translation = false; + omt->has_scale = false; + omt->has_visibility = false; + + auth_3d_vec3_load(auth, &omt->translation, &mtf->translation); + auth_3d_vec3_load(auth, &omt->rotation, &mtf->rotation); + auth_3d_vec3_load(auth, &omt->scale, &mtf->scale); + auth_3d_key_load(auth, &omt->visibility, &mtf->visibility); + + if (omt->scale.x.type == AUTH_3D_KEY_STATIC && fabsf(1.0f - omt->scale.x.value) <= 0.000001f + && omt->scale.y.type == AUTH_3D_KEY_STATIC && fabsf(1.0f - omt->scale.y.value) <= 0.000001f + && omt->scale.z.type == AUTH_3D_KEY_STATIC && fabsf(1.0f - omt->scale.z.value) <= 0.000001f) { + omt->has_scale = false; + omt->scale_value = vec3_identity; + } + else + omt->has_scale = true; + + if (omt->visibility.type == AUTH_3D_KEY_STATIC) { + omt->has_visibility = false; + omt->visible = omt->visibility.value >= 0.99900001f; + } + else + omt->has_visibility = true; +} + +static void auth_3d_object_model_transform_mat_mult(auth_3d_object_model_transform* obj_mt, mat4* mat) { + mat4 obj_mt_mat; + mat4u_to_mat4(&obj_mt->mat_inner, &obj_mt_mat); + mat4_mult(&obj_mt_mat, mat, &obj_mt_mat); + mat4_to_mat4u(&obj_mt_mat, &obj_mt->mat); +} + +static void auth_3d_object_model_transform_set_mat_inner(auth_3d_object_model_transform* obj_mt) { + if (obj_mt->has_translation && !obj_mt->has_rotation) + return; + + mat4 mat; + vec3 translation = obj_mt->translation_value; + mat4_translate(translation.x, translation.y, translation.z, &mat); + + mat4 mat_rot; + mat4u_to_mat4(&obj_mt->mat_rot, &mat_rot); + mat4_mult(&mat_rot, &mat, &mat); + if (obj_mt->has_scale) { + vec3 scale = obj_mt->scale_value; + mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &mat); + } + mat4_to_mat4u(&mat, &obj_mt->mat_inner); + obj_mt->has_translation = true; +} + +static void auth_3d_object_node_load(auth_3d* auth, + vector_auth_3d_object_node* von, auth_3d_object_node_file* onf) { + auth_3d_object_node* on = vector_auth_3d_object_node_reserve_back(von); + + if (onf->flags & A3DA_OBJECT_NODE_JOINT_ORIENT) { + vec3 rot = onf->joint_orient; + mat4 mat; + mat4_rotate(rot.x, rot.y, rot.z, &mat); + on->joint_orient = rot; + mat4_to_mat4u(&mat, &on->joint_orient_mat); + on->flags |= AUTH_3D_OBJECT_NODE_JOINT_ORIENT; + } + else { + on->joint_orient = vec3_null; + on->joint_orient_mat = mat4u_identity; + } + + auth_3d_object_model_transform_load(auth, &on->model_transform, &onf->model_transform); + string_copy(&onf->name, &on->name); + on->parent = onf->parent; +} + +static void auth_3d_object_texture_pattern_get_value( + auth_3d_object_texture_pattern* otp, float_t frame) { + auth_3d_object_curve_get_value(&otp->pattern, frame); +} + +static void auth_3d_object_texture_pattern_load(auth_3d* auth, auth_3d_object* o, + auth_3d_object_texture_pattern_file* otpf, texture_database* tex_db) { + auth_3d_object_texture_pattern* otp + = vector_auth_3d_object_texture_pattern_reserve_back(&o->texture_pattern); + + string_copy(&otpf->name, &otp->name); + auth_3d_object_curve_load(auth, &otp->pattern, &otpf->pattern, otpf->pattern_offset); + otp->texture_id = texture_database_get_texture_id(tex_db, string_data(&otp->name)); +} + +static void auth_3d_object_texture_transform_get_value( + auth_3d_object_texture_transform* ott, float_t frame) { + auth_3d_object_texture_transform_flags flags = ott->flags; + + vec3 scale = vec3_identity; + vec3 repeat = vec3_identity; + vec3 rotate = vec3_null; + vec3 translate_frame = vec3_null; + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U && ott->coverage_u.max_frame > 0.0f) { + float_t coverage_u = auth_3d_key_get_value(&ott->coverage_u, frame); + if (fabsf(coverage_u) > 0.000001f) + scale.x = 1.0f / coverage_u; + } + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V && ott->coverage_v.max_frame > 0.0f) { + float_t coverage_v = auth_3d_key_get_value(&ott->coverage_v, frame); + if (fabsf(coverage_v) > 0.000001f) + scale.y = 1.0f / coverage_v; + } + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_U && ott->repeat_u.max_frame > 0.0f) { + float_t value = auth_3d_key_get_value(&ott->repeat_u, frame); + if (fabsf(value) > 0.000001f) + repeat.x = value; + } + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_V && ott->repeat_v.max_frame > 0.0f) { + float_t value = auth_3d_key_get_value(&ott->repeat_v, frame); + if (fabsf(value) > 0.000001f) + repeat.y = value; + } + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + rotate.z = auth_3d_key_get_value(&ott->rotate_frame, frame); + + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE) + rotate.z += auth_3d_key_get_value(&ott->rotate, frame); + + float_t translate_frame_u; + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + translate_frame_u = -auth_3d_key_get_value(&ott->translate_frame_u, frame); + else + translate_frame_u = 0.0f; + + float_t offset_u; + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + offset_u = auth_3d_key_get_value(&ott->offset_u, frame); + else + offset_u = 0.0f; + + translate_frame.x = (translate_frame_u + offset_u) * repeat.x; + + float_t translate_frame_v; + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + translate_frame_v = -auth_3d_key_get_value(&ott->translate_frame_v, frame); + else + translate_frame_v = 0.0f; + + float_t offset_v; + if (flags & AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + offset_v = auth_3d_key_get_value(&ott->offset_v, frame); + else + offset_v = 0.0f; + + translate_frame.y = (translate_frame_v + offset_v) * repeat.y; + + mat4 mat; + mat4_translate(translate_frame.x, translate_frame.y, translate_frame.z, &mat); + mat4_scale_rot(&mat, scale.x, scale.y, scale.z, &mat); + + mat4_translate_mult(&mat, 1.0f, 1.0f, 0.0f, &mat); + mat4_scale_rot(&mat, repeat.x, repeat.y, repeat.z, &mat); + mat4_translate_mult(&mat, -1.0f, -1.0f, 0.0f, &mat); + + mat4_translate_mult(&mat, 0.5f, 0.5f, 0.0f, &mat); + mat4_rotate_z_mult(&mat, rotate.z, &mat); + mat4_translate_mult(&mat, -0.5f, -0.5f, 0.0f, &mat); + mat4_to_mat4u(&mat, &ott->mat); +} + +static void auth_3d_object_texture_transform_load(auth_3d* auth, auth_3d_object* o, + auth_3d_object_texture_transform_file* ottf, texture_database* tex_db) { + auth_3d_object_texture_transform* ott + = vector_auth_3d_object_texture_transform_reserve_back(&o->texture_transform); + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) { + auth_3d_key_load(auth, &ott->coverage_u, &ottf->coverage_u); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) { + auth_3d_key_load(auth, &ott->coverage_v, &ottf->coverage_v); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V; + } + + string_copy(&ottf->name, &ott->name); + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) { + auth_3d_key_load(auth, &ott->offset_u, &ottf->offset_u); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_U; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) { + auth_3d_key_load(auth, &ott->offset_v, &ottf->offset_v); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_V; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) { + auth_3d_key_load(auth, &ott->repeat_u, &ottf->repeat_u); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_U; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) { + auth_3d_key_load(auth, &ott->repeat_v, &ottf->repeat_v); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_V; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE) { + auth_3d_key_load(auth, &ott->rotate, &ottf->rotate); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) { + auth_3d_key_load(auth, &ott->rotate_frame, &ottf->rotate_frame); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) { + auth_3d_key_load(auth, &ott->translate_frame_u, &ottf->translate_frame_u); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U; + } + + if (ottf->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) { + auth_3d_key_load(auth, &ott->translate_frame_v, &ottf->translate_frame_v); + ott->flags |= AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V; + } + + ott->texture_id = texture_database_get_texture_id(tex_db, string_data(&ott->name)); +} + +static void auth_3d_play_control_load(auth_3d* auth, auth_3d_play_control_file* pcf) { + memset(&auth->play_control, 0, sizeof(auth_3d_play_control)); + auth_3d_play_control* pc = &auth->play_control; + + pc->begin = pcf->begin; + + if (pcf->flags & A3DA_PLAY_CONTROL_DIV) { + pc->div = pcf->div; + pc->flags |= AUTH_3D_PLAY_CONTROL_DIV; + } + + pc->fps = pcf->fps; + + if (pcf->flags & A3DA_PLAY_CONTROL_OFFSET) { + pc->div = pcf->div; + pc->flags |= AUTH_3D_PLAY_CONTROL_OFFSET; + } + + pc->size = pcf->size; +} + +static void auth_3d_point_data_set(auth_3d_point* p, mat4* parent_mat, render_context* rctx) { + +} + +static void auth_3d_point_get_value(auth_3d_point* p, float_t frame) { + auth_3d_model_transform_get_value(&p->model_transform, frame); +} + +static void auth_3d_point_load(auth_3d* auth, auth_3d_point_file* pf) { + auth_3d_point* p = vector_auth_3d_point_reserve_back(&auth->point); + + auth_3d_model_transform_load(auth, &p->model_transform, &pf->model_transform); + string_copy(&pf->name, &p->name); +} + +static void auth_3d_post_process_data_set(auth_3d_post_process* pp, render_context* rctx) { + post_process_blur* blur = rctx->post_process.blur; + post_process_tone_map* tm = rctx->post_process.tone_map; + + if (pp->flags & AUTH_3D_POST_PROCESS_INTENSITY) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_INTENSITY) { + post_process_blur_get_intensity(blur, &pp->intensity_init); + pp->flags_init |= AUTH_3D_POST_PROCESS_INTENSITY; + } + + post_process_blur_set_intensity(blur, (vec3*)&pp->intensity.value); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_FLARE) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_LENS_FLARE) { + pp->lens_flare_init = post_process_tone_map_get_lens_flare(tm); + //pp->flags_init |= AUTH_3D_POST_PROCESS_LENS_FLARE; + } + + post_process_tone_map_set_lens_ghost(tm, pp->lens_flare_value); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_GHOST) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_LENS_GHOST) { + pp->lens_ghost_init = post_process_tone_map_get_lens_ghost(tm); + //pp->flags_init |= AUTH_3D_POST_PROCESS_LENS_GHOST; + } + + post_process_tone_map_set_lens_ghost(tm, pp->lens_ghost_value); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_SHAFT) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_LENS_SHAFT) { + pp->lens_shaft_init = post_process_tone_map_get_lens_shaft(tm); + //pp->flags_init |= AUTH_3D_POST_PROCESS_LENS_SHAFT; + } + + post_process_tone_map_set_lens_shaft(tm, pp->lens_shaft_value); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_RADIUS) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_RADIUS) { + post_process_blur_get_radius(blur, &pp->radius_init); + pp->flags_init |= AUTH_3D_POST_PROCESS_RADIUS; + } + + post_process_blur_set_radius(blur, (vec3*)&pp->radius.value); + } + + if (pp->flags & AUTH_3D_POST_PROCESS_SCENE_FADE) { + if (~pp->flags_init & AUTH_3D_POST_PROCESS_SCENE_FADE) { + vec4 scene_fade_init; + post_process_tone_map_get_scene_fade(tm, &scene_fade_init); + vec4_to_vec4u(scene_fade_init, pp->scene_fade_init); + pp->flags_init |= AUTH_3D_POST_PROCESS_SCENE_FADE; + } + + vec4 scene_fade; + vec4u_to_vec4(pp->scene_fade.value, scene_fade); + post_process_tone_map_set_scene_fade(tm, &scene_fade); + } +} + +static void auth_3d_post_process_get_value(auth_3d_post_process* pp, float_t frame) { + if (pp->flags & AUTH_3D_POST_PROCESS_INTENSITY) + auth_3d_rgba_get_value(&pp->intensity, frame); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_FLARE) + pp->lens_flare_value = auth_3d_key_get_value(&pp->lens_flare, frame); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_SHAFT) + pp->lens_shaft_value = auth_3d_key_get_value(&pp->lens_shaft, frame); + if (pp->flags & AUTH_3D_POST_PROCESS_LENS_GHOST) + pp->lens_ghost_value = auth_3d_key_get_value(&pp->lens_ghost, frame); + if (pp->flags & AUTH_3D_POST_PROCESS_RADIUS) + auth_3d_rgba_get_value(&pp->radius, frame); + if (pp->flags & AUTH_3D_POST_PROCESS_SCENE_FADE) + auth_3d_rgba_get_value(&pp->scene_fade, frame); +} + +static void auth_3d_post_process_load(auth_3d* auth, auth_3d_post_process_file* ppf) { + memset(&auth->post_process, 0, sizeof(auth_3d_post_process)); + auth_3d_post_process* pp = &auth->post_process; + + if (ppf->flags & A3DA_POST_PROCESS_INTENSITY) { + auth_3d_rgba_load(auth, &pp->intensity, &ppf->intensity); + pp->flags |= AUTH_3D_POST_PROCESS_INTENSITY; + } + + if (ppf->flags & A3DA_POST_PROCESS_LENS_FLARE) { + auth_3d_key_load(auth, &pp->lens_flare, &ppf->lens_flare); + pp->flags |= AUTH_3D_POST_PROCESS_LENS_FLARE; + } + + if (ppf->flags & A3DA_POST_PROCESS_LENS_GHOST) { + auth_3d_key_load(auth, &pp->lens_ghost, &ppf->lens_ghost); + pp->flags |= AUTH_3D_POST_PROCESS_LENS_GHOST; + } + + if (ppf->flags & A3DA_POST_PROCESS_LENS_SHAFT) { + auth_3d_key_load(auth, &pp->lens_shaft, &ppf->lens_shaft); + pp->flags |= AUTH_3D_POST_PROCESS_LENS_SHAFT; + } + + if (ppf->flags & A3DA_POST_PROCESS_RADIUS) { + auth_3d_rgba_load(auth, &pp->radius, &ppf->radius); + pp->flags |= AUTH_3D_POST_PROCESS_RADIUS; + } + + if (ppf->flags & A3DA_POST_PROCESS_SCENE_FADE) { + auth_3d_rgba_load(auth, &pp->scene_fade, &ppf->scene_fade); + pp->flags |= AUTH_3D_POST_PROCESS_SCENE_FADE; + } +} + +static void auth_3d_post_process_restore_prev_value(auth_3d_post_process* pp, render_context* rctx) { + post_process_blur* blur = rctx->post_process.blur; + post_process_tone_map* tm = rctx->post_process.tone_map; + + if (pp->flags_init & AUTH_3D_POST_PROCESS_INTENSITY) + post_process_blur_set_intensity(blur, &pp->intensity_init); + + if (pp->flags_init & AUTH_3D_POST_PROCESS_LENS_FLARE) + post_process_tone_map_set_lens_ghost(tm, pp->lens_flare_init); + + if (pp->flags_init & AUTH_3D_POST_PROCESS_LENS_GHOST) + post_process_tone_map_set_lens_ghost(tm, pp->lens_ghost_init); + + if (pp->flags_init & AUTH_3D_POST_PROCESS_LENS_SHAFT) + post_process_tone_map_set_lens_shaft(tm, pp->lens_shaft_init); + + if (pp->flags_init & AUTH_3D_POST_PROCESS_RADIUS) + post_process_blur_set_radius(blur, &pp->radius_init); + + if (pp->flags_init & AUTH_3D_POST_PROCESS_SCENE_FADE) { + vec4 scene_fade_init; + vec4u_to_vec4(pp->scene_fade_init, scene_fade_init); + post_process_tone_map_set_scene_fade(tm, &scene_fade_init); + } +} diff --git a/src/CRE/auth_3d.h b/src/CRE/auth_3d.h new file mode 100644 index 00000000..2f6b634c --- /dev/null +++ b/src/CRE/auth_3d.h @@ -0,0 +1,653 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/database/object.h" +#include "../KKdLib/database/texture.h" +#include "../KKdLib/a3da.h" +#include "../KKdLib/kf.h" +#include "render_context.h" + +typedef enum auth_3d_ambient_flags { + AUTH_3D_AMBIENT_LIGHT_DIFFUSE = 0x01, + AUTH_3D_AMBIENT_RIM_LIGHT_DIFFUSE = 0x02, +} auth_3d_ambient_flags; + +typedef enum auth_3d_camera_auxiliary_flags { + AUTH_3D_CAMERA_AUXILIARY_AUTO_EXPOSURE = 0x01, + AUTH_3D_CAMERA_AUXILIARY_EXPOSURE = 0x02, + AUTH_3D_CAMERA_AUXILIARY_EXPOSURE_RATE = 0x04, + AUTH_3D_CAMERA_AUXILIARY_GAMMA = 0x08, + AUTH_3D_CAMERA_AUXILIARY_GAMMA_RATE = 0x10, + AUTH_3D_CAMERA_AUXILIARY_SATURATE = 0x20, +} auth_3d_camera_auxiliary_flags; + +typedef enum auth_3d_camera_root_view_point_flags { + AUTH_3D_CAMERA_ROOT_VIEW_POINT_FOV = 0x01, + AUTH_3D_CAMERA_ROOT_VIEW_POINT_ROLL = 0x02, +} auth_3d_camera_root_view_point_flags; + +typedef enum auth_3d_compress_f16 { + AUTH_3D_COMPRESS_F32F32F32F32 = 0, + AUTH_3D_COMPRESS_I16F16F32F32 = 1, + AUTH_3D_COMPRESS_I16F16F16F16 = 2, +} auth_3d_compress_f16; + +typedef enum auth_3d_ep_type { + AUTH_3D_EP_NONE = 0, + AUTH_3D_EP_LINEAR = 1, + AUTH_3D_EP_CYCLE = 2, + AUTH_3D_EP_CYCLE_OFFSET = 3, +} auth_3d_ep_type; // Pre/Post Infinity + +typedef enum auth_3d_event_type { + AUTH_3D_EVENT_MISC = 0x00, + AUTH_3D_EVENT_FILT = 0x01, + AUTH_3D_EVENT_FX = 0x02, + AUTH_3D_EVENT_SND = 0x03, + AUTH_3D_EVENT_MOT = 0x04, + AUTH_3D_EVENT_A2D = 0x05, +} auth_3d_event_type; + +typedef enum auth_3d_event_filter_fade_type { + AUTH_3D_EVENT_FILTER_FADE_NONE = -1, + AUTH_3D_EVENT_FILTER_FADE_OUT = 0, + AUTH_3D_EVENT_FILTER_FADE_IN = 1, +} auth_3d_event_filter_fade_type; + +typedef enum auth_3d_fog_flags { + AUTH_3D_FOG_COLOR = 0x01, + AUTH_3D_FOG_DENSITY = 0x02, + AUTH_3D_FOG_END = 0x04, + AUTH_3D_FOG_START = 0x08, +} auth_3d_fog_flags; + +typedef enum auth_3d_format { + AUTH_3D_FORMAT_DT = 0, + AUTH_3D_FORMAT_F = 1, + AUTH_3D_FORMAT_FT = 2, + AUTH_3D_FORMAT_F2 = 3, + AUTH_3D_FORMAT_MGF = 4, + AUTH_3D_FORMAT_X = 5, + AUTH_3D_FORMAT_XHD = 6, +} auth_3d_format; + +typedef enum auth_3d_key_flags { + AUTH_3D_KEY_BIN_OFFSET = 0x01, +} auth_3d_key_flags; + +typedef enum auth_3d_key_type { + AUTH_3D_KEY_NONE = 0, + AUTH_3D_KEY_STATIC = 1, + AUTH_3D_KEY_LINEAR = 2, + AUTH_3D_KEY_HERMITE = 3, + AUTH_3D_KEY_HOLD = 4, +} auth_3d_key_type; + +typedef enum auth_3d_light_flags { + AUTH_3D_LIGHT_AMBIENT = 0x0001, + AUTH_3D_LIGHT_CONE_ANGLE = 0x0002, + AUTH_3D_LIGHT_CONSTANT = 0x0004, + AUTH_3D_LIGHT_DIFFUSE = 0x0008, + AUTH_3D_LIGHT_DROP_OFF = 0x0010, + AUTH_3D_LIGHT_FAR = 0x0020, + AUTH_3D_LIGHT_INTENSITY = 0x0040, + AUTH_3D_LIGHT_LINEAR = 0x0080, + AUTH_3D_LIGHT_POSITION = 0x0100, + AUTH_3D_LIGHT_QUADRATIC = 0x0200, + AUTH_3D_LIGHT_SPECULAR = 0x0400, + AUTH_3D_LIGHT_SPOT_DIRECTION = 0x0800, + AUTH_3D_LIGHT_TONE_CURVE = 0x1000, +} auth_3d_light_flags; + +typedef enum auth_3d_material_list_flags { + AUTH_3D_MATERIAL_LIST_BLEND_COLOR = 0x01, + AUTH_3D_MATERIAL_LIST_GLOW_INTENSITY = 0x02, + AUTH_3D_MATERIAL_LIST_INCANDESCENCE = 0x04, +} auth_3d_material_list_flags; + +typedef enum auth_3d_model_transform_flags { + AUTH_3D_MODEL_TRANSFORM_BIN_OFFSET = 0x01, +} auth_3d_model_transform_flags; + +typedef enum auth_3d_object_node_flags { + AUTH_3D_OBJECT_NODE_JOINT_ORIENT = 0x01, +} auth_3d_object_node_flags; + +typedef enum auth_3d_object_texture_transform_flags { + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U = 0x001, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V = 0x002, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_U = 0x004, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_OFFSET_V = 0x008, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_U = 0x010, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_REPEAT_V = 0x020, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE = 0x040, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME = 0x080, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U = 0x100, + AUTH_3D_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V = 0x200, +} auth_3d_object_texture_transform_flags; + +typedef enum auth_3d_play_control_flags { + AUTH_3D_PLAY_CONTROL_DIV = 0x01, + AUTH_3D_PLAY_CONTROL_OFFSET = 0x02, +} auth_3d_play_control_flags; + +typedef enum auth_3d_post_process_flags { + AUTH_3D_POST_PROCESS_INTENSITY = 0x01, + AUTH_3D_POST_PROCESS_LENS_FLARE = 0x02, + AUTH_3D_POST_PROCESS_LENS_GHOST = 0x04, + AUTH_3D_POST_PROCESS_LENS_SHAFT = 0x08, + AUTH_3D_POST_PROCESS_RADIUS = 0x10, + AUTH_3D_POST_PROCESS_SCENE_FADE = 0x20, +} auth_3d_post_process_flags; + +typedef enum auth_3d_rgba_flags { + AUTH_3D_RGBA_R = 0x01, + AUTH_3D_RGBA_G = 0x02, + AUTH_3D_RGBA_B = 0x04, + AUTH_3D_RGBA_A = 0x08, +} auth_3d_rgba_flags; + +typedef struct auth_3d_ambient auth_3d_ambient; +typedef struct auth_3d_camera_auxiliary auth_3d_camera_auxiliary; +typedef struct auth_3d_camera_root auth_3d_camera_root; +typedef struct auth_3d_camera_root_view_point auth_3d_camera_root_view_point; +typedef struct auth_3d_chara auth_3d_chara; +typedef struct auth_3d_curve auth_3d_curve; +typedef struct auth_3d_dof auth_3d_dof; +typedef struct auth_3d_event auth_3d_event; +typedef struct auth_3d_fog auth_3d_fog; +typedef struct auth_3d_key auth_3d_key; +typedef struct auth_3d_light auth_3d_light; +typedef struct auth_3d_m_object_hrc auth_3d_m_object_hrc; +typedef struct auth_3d_material_list auth_3d_material_list; +typedef struct auth_3d_model_transform auth_3d_model_transform; +typedef struct auth_3d_object auth_3d_object; +typedef struct auth_3d_object_curve auth_3d_object_curve; +typedef struct auth_3d_object_hrc auth_3d_object_hrc; +typedef struct auth_3d_object_instance auth_3d_object_instance; +typedef struct auth_3d_object_model_transform auth_3d_object_model_transform; +typedef struct auth_3d_object_node auth_3d_object_node; +typedef struct auth_3d_object_texture_pattern auth_3d_object_texture_pattern; +typedef struct auth_3d_object_texture_transform auth_3d_object_texture_transform; +typedef struct auth_3d_play_control auth_3d_play_control; +typedef struct auth_3d_point auth_3d_point; +typedef struct auth_3d_post_process auth_3d_post_process; +typedef struct auth_3d_rgba auth_3d_rgba; +typedef struct auth_3d_vec3 auth_3d_vec3; + +ptr_t(auth_3d_m_object_hrc) +ptr_t(auth_3d_object) +ptr_t(auth_3d_object_hrc) + +vector(auth_3d_ambient) +vector(auth_3d_model_transform) +vector(auth_3d_camera_root) +vector(auth_3d_chara) +vector(auth_3d_curve) +vector(auth_3d_event) +vector(auth_3d_fog) +vector(auth_3d_light) +vector(auth_3d_m_object_hrc) +vector(auth_3d_material_list) +vector(auth_3d_object) +vector(auth_3d_object_hrc) +vector(auth_3d_object_instance) +vector(auth_3d_object_node) +vector(auth_3d_object_texture_pattern) +vector(auth_3d_object_texture_transform) +vector(auth_3d_point) +vector(ptr_auth_3d_m_object_hrc) +vector(ptr_auth_3d_object) +vector(ptr_auth_3d_object_hrc) + +struct auth_3d_key { + auth_3d_key_type type; + float_t value; + float_t max_frame; + auth_3d_ep_type ep_type_pre; + auth_3d_ep_type ep_type_post; + float_t frame_delta; + float_t value_delta; + vector_kft3 keys_vec; + size_t length; + kft3* keys; + + float_t frame; + float_t value_interp; + float_t value_init; +}; + +struct auth_3d_rgba { + auth_3d_rgba_flags flags; + auth_3d_key r; + auth_3d_key g; + auth_3d_key b; + auth_3d_key a; + + vec4u value; +}; + +struct auth_3d_vec3 { + auth_3d_key x; + auth_3d_key y; + auth_3d_key z; +}; + +struct auth_3d_model_transform { + mat4u mat; + auth_3d_vec3 scale; + auth_3d_vec3 rotation; + auth_3d_vec3 translation; + auth_3d_key visibility; + + vec3 scale_value; + vec3 rotation_value; + vec3 translation_value; + bool visible; +}; + +struct auth_3d_ambient { + auth_3d_ambient_flags flags; + auth_3d_rgba light_diffuse; + string name; + auth_3d_rgba rim_light_diffuse; +}; + +struct auth_3d_camera_auxiliary { + auth_3d_camera_auxiliary_flags flags; + auth_3d_key auto_exposure; + auth_3d_key exposure; + auth_3d_key exposure_rate; + auth_3d_key gamma; + auth_3d_key gamma_rate; + auth_3d_key saturate; + + float_t auto_exposure_value; + float_t exposure_value; + float_t exposure_rate_value; + float_t gamma_value; + float_t gamma_rate_value; + float_t saturate_value; +}; + +struct auth_3d_camera_root_view_point { + auth_3d_camera_root_view_point_flags flags; + float_t aspect; + float_t camera_aperture_h; + float_t camera_aperture_w; + auth_3d_key focal_length; + auth_3d_key fov; + bool fov_is_horizontal; + auth_3d_model_transform model_transform; + auth_3d_key roll; +}; + +struct auth_3d_camera_root { + auth_3d_model_transform interest; + auth_3d_model_transform model_transform; + auth_3d_camera_root_view_point view_point; + + float_t fov_value; + vec3 interest_value; + float_t roll_value; + vec3 view_point_value; +}; + +struct auth_3d_chara { + auth_3d_model_transform model_transform; + string name; +}; + +struct auth_3d_curve { + auth_3d_key curve; + string name; + float_t value; +}; + +struct auth_3d_dof { + bool has_dof; + auth_3d_model_transform model_transform; +}; + +struct auth_3d_event { + float_t begin; + float_t clip_begin; + float_t clip_end; + float_t end; + string name; + string param_1; + string ref; + float_t time_ref_scale; + auth_3d_event_type type; +}; + +struct auth_3d_fog { + auth_3d_fog_flags flags; + auth_3d_fog_flags flags_init; + auth_3d_rgba color; + auth_3d_key density; + auth_3d_key end; + fog_id id; + auth_3d_key start; + + float_t density_value; + float_t end_value; + float_t start_value; + + vec4u color_init; + float_t density_init; + float_t end_init; + float_t start_init; +}; + +struct auth_3d_light { + auth_3d_light_flags flags; + auth_3d_light_flags flags_init; + auth_3d_rgba ambient; + auth_3d_key cone_angle; + auth_3d_key constant; + auth_3d_rgba diffuse; + auth_3d_key drop_off; + auth_3d_key _far; + light_id id; + auth_3d_key intensity; + auth_3d_key linear; + auth_3d_model_transform position; + auth_3d_key quadratic; + auth_3d_rgba specular; + auth_3d_model_transform spot_direction; + auth_3d_rgba tone_curve; + string type; + + float_t cone_angle_value; + float_t constant_value; + float_t drop_off_value; + float_t far_value; + float_t intensity_value; + float_t linear_value; + float_t quadratic_value; + + vec4u ambient_init; + float_t cone_angle_init; + float_t constant_init; + vec4u diffuse_init; + float_t drop_off_init; + float_t far_init; + float_t intensity_init; + float_t linear_init; + float_t quadratic_init; + vec4u specular_init; + vec3 tone_curve_init; +}; + +struct auth_3d_object_model_transform { + mat4u mat; + mat4u mat_inner; + mat4u mat_rot; + auth_3d_vec3 translation; + auth_3d_vec3 rotation; + auth_3d_vec3 scale; + auth_3d_key visibility; + + vec3 translation_value; + vec3 rotation_value; + vec3 scale_value; + bool visible; + float_t frame; + bool has_rotation; + bool has_translation; + bool has_scale; + bool has_visibility; +}; + +struct auth_3d_m_object_hrc { + vector_auth_3d_object_instance instance; + auth_3d_object_model_transform model_transform; + string name; + vector_auth_3d_object_node node; +}; + +struct auth_3d_material_list { + auth_3d_material_list_flags flags; + auth_3d_rgba blend_color; + auth_3d_key glow_intensity; + auth_3d_rgba incandescence; + string name; + + float_t glow_intensity_value; +}; + +struct auth_3d_object_curve { + auth_3d_curve* curve; + string name; + float_t frame_offset; + float_t value; +}; + +struct auth_3d_object { + vector_ptr_auth_3d_object children_object; + vector_ptr_auth_3d_object_hrc children_object_hrc; + auth_3d_model_transform model_transform; + auth_3d_object_curve morph; + object_info object_info; + string name; + string parent_name; + string parent_node; + auth_3d_object_curve pattern; + bool reflect; + bool refract; + vector_auth_3d_object_texture_pattern texture_pattern; + vector_auth_3d_object_texture_transform texture_transform; + string uid_name; +}; + +struct auth_3d_object_hrc { + vector_ptr_auth_3d_object children_object; + vector_ptr_auth_3d_object_hrc children_object_hrc; + vector_int32_t childer_object_hrc_parent_node; + vector_int32_t childer_object_parent_node; + vector_mat4 mats; + string name; + vector_auth_3d_object_node node; + object_info object_info; + string parent_name; + string parent_node; + bool reflect; + bool refract; + bool shadow; + string uid_name; +}; + +struct auth_3d_object_instance { + vector_mat4 mats; + auth_3d_object_model_transform model_transform; + string name; + vector_int32_t object_bone_indices; + object_info object_info; + bool shadow; + string uid_name; +}; + +struct auth_3d_object_node { + auth_3d_object_node_flags flags; + int32_t bone_id; + vec3 joint_orient; + mat4u joint_orient_mat; + mat4* mat; + auth_3d_object_model_transform model_transform; + string name; + int32_t parent; +}; + +struct auth_3d_object_texture_pattern { + string name; + auth_3d_object_curve pattern; + int32_t texture_id; +}; + +struct auth_3d_object_texture_transform { + auth_3d_object_texture_transform_flags flags; + auth_3d_key coverage_u; + auth_3d_key coverage_v; + mat4u mat; + string name; + auth_3d_key offset_u; + auth_3d_key offset_v; + auth_3d_key repeat_u; + auth_3d_key repeat_v; + auth_3d_key rotate; + auth_3d_key rotate_frame; + int32_t texture_id; + auth_3d_key translate_frame_u; + auth_3d_key translate_frame_v; +}; + +struct auth_3d_play_control { + auth_3d_play_control_flags flags; + float_t begin; + int32_t div; + float_t fps; + float_t offset; + float_t size; +}; + +struct auth_3d_point { + auth_3d_model_transform model_transform; + string name; +}; + +struct auth_3d_post_process { + auth_3d_post_process_flags flags; + auth_3d_post_process_flags flags_init; + auth_3d_rgba intensity; + auth_3d_key lens_flare; + auth_3d_key lens_ghost; + auth_3d_key lens_shaft; + auth_3d_rgba radius; + auth_3d_rgba scene_fade; + + float_t lens_flare_value; + float_t lens_ghost_value; + float_t lens_shaft_value; + + vec3 intensity_init; + float_t lens_flare_init; + float_t lens_ghost_init; + float_t lens_shaft_init; + vec3 radius_init; + vec4u scene_fade_init; +}; + +typedef struct auth_3d { + int32_t uid; + int32_t id; + bool enable; + bool camera_root_update; + bool repeat; + bool ended; + bool left_right_reverse; + bool once; + + float_t alpha; + float_t frame; + float_t set_frame; + float_t max_frame; + bool frame_changed; + float_t frame_offset; + float_t last_frame; + bool paused; + + vector_auth_3d_ambient ambient; + vector_string auth_2d; + auth_3d_camera_auxiliary camera_auxiliary; + vector_auth_3d_camera_root camera_root; + vector_auth_3d_chara chara; + vector_auth_3d_curve curve; + auth_3d_dof dof; + vector_auth_3d_event event; + vector_auth_3d_fog fog; + vector_auth_3d_light light; + vector_auth_3d_m_object_hrc m_object_hrc; + vector_ptr_auth_3d_m_object_hrc m_object_hrc_list; + vector_auth_3d_material_list material_list; + vector_string motion; + vector_auth_3d_object object; + vector_auth_3d_object_hrc object_hrc; + vector_ptr_auth_3d_object_hrc object_hrc_list; + vector_ptr_auth_3d_object object_list; + auth_3d_play_control play_control; + vector_auth_3d_point point; + auth_3d_post_process post_process; + + string file_name; + int32_t frame_int; +} auth_3d; + +#define AUTH_3D_DATA_COUNT 0x100 + +typedef struct auth_3d_data_struct { + vector_int32_t loaded_ids; + auth_3d data[AUTH_3D_DATA_COUNT]; +} auth_3d_data_struct; + +typedef struct auth_3d_farc { + farc auth_3d_farc; + vector_uint32_t obj_set_id; +} auth_3d_farc; + +extern auth_3d_data_struct auth_3d_data; + +extern void auth_3d_init(auth_3d* auth); +extern void auth_3d_data_set(auth_3d* auth, mat4* mat, render_context* rctx); +extern void auth_3d_get_value(auth_3d* auth, mat4* mat, float_t frame); +extern void auth_3d_unload(auth_3d* auth, render_context* rctx); +extern void auth_3d_load(auth_3d* auth, a3da* auth_file, + object_database* obj_db, texture_database* tex_db); +extern void auth_3d_load_from_farc(auth_3d* auth, farc* f, char* file, + object_database* obj_db, texture_database* tex_db); +extern void auth_3d_free(auth_3d* auth); + +extern void auth_3d_farc_init(auth_3d_farc* f); +extern void auth_3d_farc_load(auth_3d_farc* f, void* data, char* name, object_database* obj_db); +extern void auth_3d_farc_free(auth_3d_farc* f); + +extern void auth_3d_key_free(auth_3d_key* k); +extern void auth_3d_rgba_free(auth_3d_rgba* rgba); +extern void auth_3d_vec3_free(auth_3d_vec3* vec); +extern void auth_3d_model_transform_free(auth_3d_model_transform* mt); + +extern void auth_3d_ambient_free(auth_3d_ambient* a); +extern void auth_3d_camera_auxiliary_free(auth_3d_camera_auxiliary* ca); +extern void auth_3d_camera_root_free(auth_3d_camera_root* cr); +extern void auth_3d_camera_root_view_point_free(auth_3d_camera_root_view_point* crvp); +extern void auth_3d_chara_free(auth_3d_chara* c); +extern void auth_3d_curve_free(auth_3d_curve* c); +extern void auth_3d_dof_free(auth_3d_dof* d); +extern void auth_3d_event_free(auth_3d_event* e); +extern void auth_3d_fog_free(auth_3d_fog* f); +extern void auth_3d_light_free(auth_3d_light* l); +extern void auth_3d_m_object_hrc_free(auth_3d_m_object_hrc* moh); +extern void auth_3d_material_list_free(auth_3d_material_list* ml); +extern void auth_3d_object_free(auth_3d_object* o); +extern void auth_3d_object_curve_free(auth_3d_object_curve* oc); +extern void auth_3d_object_hrc_free(auth_3d_object_hrc* oh); +extern void auth_3d_object_instance_free(auth_3d_object_instance* oi); +extern void auth_3d_object_model_transform_free(auth_3d_object_model_transform* omt); +extern void auth_3d_object_node_free(auth_3d_object_node* on); +extern void auth_3d_object_texture_pattern_free(auth_3d_object_texture_pattern* otp); +extern void auth_3d_object_texture_transform_free(auth_3d_object_texture_transform* ott); +extern void auth_3d_point_free(auth_3d_point* p); +extern void auth_3d_post_process_free(auth_3d_post_process* pp); + +extern void auth_3d_data_init(); +extern int32_t auth_3d_data_load_uid(int32_t uid, auth_3d_database* auth_3d_db); +extern auth_3d* auth_3d_data_get_auth_3d(int32_t id); +extern int32_t auth_3d_data_get_auth_3d_id_by_object_info(object_info obj_info, uint64_t* mesh_index, bool* hrc); +extern mat4* auth_3d_data_struct_get_auth_3d_object_mat(int32_t id, size_t index, bool hrc, mat4* mat); +extern void auth_3d_data_unload_id(int32_t id, render_context* rctx); +extern void auth_3d_data_free(); diff --git a/src/CRE/camera.c b/src/CRE/camera.c index 376fa4b1..68c84d53 100644 --- a/src/CRE/camera.c +++ b/src/CRE/camera.c @@ -14,11 +14,15 @@ static void camera_calculate_projection(camera* c); static void camera_calculate_view(camera* c); static void camera_calculate_forward(camera* c); -void camera_initialize(camera* c, double_t aspect, double_t fov) { +void camera_initialize(camera* c, double_t aspect, int32_t width, int32_t height) { c->aspect = aspect; - c->fov = fov; + c->fov = 32.2673416137695; + c->forward = (vec3){ 0.0f, 0.0f, -1.0f }; + c->rotation = (vec3){ 0.0f, 0.0f, 0.0f }; c->view_point = (vec3){ 0.0, 0.0f, 0.0f }; c->interest = (vec3){ 0.0f, 0.0f, -1.0f }; + c->width = width; + c->height = height; c->view = mat4_identity; c->projection = mat4_identity; c->view_projection = mat4_identity; @@ -31,6 +35,7 @@ void camera_initialize(camera* c, double_t aspect, double_t fov) { camera_set_pitch(c, 0.0); camera_set_yaw(c, 0.0); camera_set_roll(c, 0.0); + camera_calculate_forward(c); camera_update(c); } @@ -75,6 +80,7 @@ void camera_set_fov(camera* c, double_t value) { value = clamp(value, 1.0, 180.0); if (value != c->fov) { c->fov = value; + c->fov_rad = value * DEG_TO_RAD; c->changed_proj = true; } } @@ -84,10 +90,7 @@ double_t camera_get_pitch(camera* c) { } void camera_set_pitch(camera* c, double_t value) { - while (value > 180.0) - value -= 360.0; - while (value < -180.0) - value += 360.0; + value = fmod(value, 360.0); value = clamp(value, -89.5, 89.5); if (c->pitch != value) { c->pitch = value; @@ -96,15 +99,11 @@ void camera_set_pitch(camera* c, double_t value) { } double_t camera_get_yaw(camera* c) { - return c->yaw + 90.0; + return c->yaw; } void camera_set_yaw(camera* c, double_t value) { - while (value > 180.0) - value -= 360.0; - while (value < -180.0) - value += 360.0; - value -= 90.0; + value = fmod(value, 360.0); if (c->yaw != value) { c->yaw = value; c->changed_view = true; @@ -116,11 +115,7 @@ double_t camera_get_roll(camera* c) { } void camera_set_roll(camera* c, double_t value) { - while (value > 180.0) - value -= 360.0; - while (value < -180.0) - value += 360.0; - value = -value; + value = fmod(value, 360.0); if (c->roll != value) { c->roll = value; c->changed_view = true; @@ -128,7 +123,7 @@ void camera_set_roll(camera* c, double_t value) { } void camera_get_view_point(camera* c, vec3* value) { - + *value = c->view_point; } void camera_set_view_point(camera* c, vec3* value) { @@ -140,11 +135,11 @@ void camera_set_view_point(camera* c, vec3* value) { } } -void camera_get_interest_point(camera* c, vec3* value) { +void camera_get_interest(camera* c, vec3* value) { *value = c->interest; } -void camera_set_interest_point(camera* c, vec3* value) { +void camera_set_interest(camera* c, vec3* value) { if (c->interest.x != value->x || c->interest.y != value->y || c->interest.z != value->z) { @@ -153,12 +148,26 @@ void camera_set_interest_point(camera* c, vec3* value) { } } +void camera_get_res(camera* c, int32_t* width, int32_t* height) { + *width = c->width; + *height = c->height; +} + +void camera_set_res(camera* c, int32_t width, int32_t height) { + if (c->width != width || c->height != height) { + c->width = width; + c->height = height; + c->changed_proj = true; + } +} + void camera_reset(camera* c) { camera_set_pitch(c, 0.0); camera_set_yaw(c, 0.0); camera_set_roll(c, 0.0); + camera_set_fov(c, 32.2673416137695); camera_calculate_forward(c); - camera_set_position(c, &(vec3){ 0.0, 0.0f, 0.0f}); + camera_set_position(c, &((vec3){ 0.0, 0.0f, 0.0f})); camera_update(c); } @@ -176,7 +185,7 @@ void camera_move(camera* c, vec2d* move) { vec3_add(view_point, c->forward, interest); camera_set_view_point(c, &view_point); - camera_set_interest_point(c, &interest); + camera_set_interest(c, &interest); } } @@ -192,13 +201,13 @@ void camera_rotate(camera* c, vec2d* rotate) { vec3 interest; vec3_add(c->view_point, c->forward, interest); - camera_set_interest_point(c, &interest); + camera_set_interest(c, &interest); } } void camera_roll(camera* c, double_t roll) { if (roll != 0.0f) - camera_set_roll(c, camera_get_roll(c) + roll); + camera_set_roll(c, -camera_get_roll(c) - roll); } void camera_set(camera* c, vec3* view_point, vec3* interest, @@ -212,20 +221,16 @@ void camera_set(camera* c, vec3* view_point, vec3* interest, _int = *interest; _roll = roll; _fov = fov; - while (_roll > 180.0) - _roll -= 360.0; - while (_roll < -180.0) - _roll += 360.0; mat4 cam; mat4_translate(trans->x, trans->y, trans->z, &cam); - mat4_rot(&cam, rot->x, rot->y, rot->z, &cam); + mat4_rotate_mult(&cam, rot->x, rot->y, rot->z, &cam); mat4_scale_rot(&cam, scale->x, scale->y, scale->z, &cam); mat4_mult_vec3_trans(&cam, &_vp, &_vp); mat4_mult_vec3_trans(&cam, &_int, &_int); camera_set_view_point(c, &_vp); - camera_set_interest_point(c, &_int); + camera_set_interest(c, &_int); camera_set_roll(c, _roll); camera_set_fov(c, _fov); } @@ -234,7 +239,7 @@ void camera_set_position(camera* c, vec3* pos) { vec3 interest; vec3_add(*pos, c->forward, interest); camera_set_view_point(c, pos); - camera_set_interest_point(c, &interest); + camera_set_interest(c, &interest); } void camera_update(camera* c) { @@ -246,12 +251,10 @@ void camera_update(camera* c) { if (c->changed_proj || c->changed_view) { mat4_mult(&c->view, &c->projection, &c->view_projection); + mat4_inverse(&c->view_projection, &c->inv_view_projection); c->changed_proj = false; - c->changed_view = false; - c->updated = true; + //c->changed_view = false; } - else - c->updated = false; } void camera_dispose(camera* c) { @@ -259,42 +262,66 @@ void camera_dispose(camera* c) { } static void camera_calculate_forward(camera* c) { - c->forward.x = (float_t)(cos(c->pitch * DEG_TO_RAD) * cos(c->yaw * DEG_TO_RAD)); + c->forward.x = (float_t)(cos(c->pitch * DEG_TO_RAD) * sin(c->yaw * DEG_TO_RAD)); c->forward.y = (float_t)sin(c->pitch * DEG_TO_RAD); - c->forward.z = (float_t)(cos(c->pitch * DEG_TO_RAD) * sin(c->yaw * DEG_TO_RAD)); + c->forward.z = (float_t)(cos(c->pitch * DEG_TO_RAD) * -cos(c->yaw * DEG_TO_RAD)); } static void camera_calculate_projection(camera* c) { - double_t tan_fov = tan(c->fov * 0.5); - - double_t max_d = c->max_distance; - double_t min_d = c->min_distance; - - double_t x = 1.0 / (c->aspect * tan_fov); - double_t y = 1.0 / tan_fov; - double_t d = -(2.0 * max_d * min_d) / (max_d - min_d); - double_t e = -(max_d + min_d) / (max_d - min_d); - - c->projection.row0 = (vec4){ (float_t)x, 0.0f, 0.0f, 0.0f }; - c->projection.row1 = (vec4){ 0.0f, (float_t)y, 0.0f, 0.0f }; - c->projection.row2 = (vec4){ 0.0f, 0.0f, (float_t)e, -1.0f }; - c->projection.row3 = (vec4){ 0.0f, 0.0f, (float_t)d, 0.0f }; - + mat4_persp(c->fov_rad, c->aspect, c->min_distance, c->max_distance, &c->projection); mat4_inverse(&c->projection, &c->inv_projection); + + float_t fov_correct_height = (float_t)(((double_t)c->height * 0.5) / tan(c->fov_rad * 0.5)); + float_t height = (float_t)c->height * 0.5f; + float_t width = (float_t)c->height * (float_t)c->aspect * 0.5f; + + c->field_1E4.x = fov_correct_height; + c->field_1E4.y = 0.0f; + c->field_1E4.z = -width; + vec3_normalize(c->field_1E4, c->field_1E4); + c->field_1F0.x = -fov_correct_height; + c->field_1F0.y = 0.0f; + c->field_1F0.z = -width; + vec3_normalize(c->field_1F0, c->field_1F0); + c->field_1FC.x = 0.0f; + c->field_1FC.y = fov_correct_height; + c->field_1FC.z = -height; + vec3_normalize(c->field_1FC, c->field_1FC); + c->field_208.x = 0.0f; + c->field_208.y = -fov_correct_height; + c->field_208.z = -height; + vec3_normalize(c->field_208, c->field_208); } static void camera_calculate_view(camera* c) { vec3 dist; vec3_sub(c->view_point, c->interest, dist); - c->rotation.x = atan2f(-dist.y, sqrtf(dist.x * dist.x + dist.z * dist.z)); - c->rotation.y = atan2f(dist.x, dist.z); - c->rotation.z = (float_t)(c->roll * DEG_TO_RAD); + + vec3 rotation; + rotation.x = atan2f(-dist.y, sqrtf(dist.x * dist.x + dist.z * dist.z)); + rotation.y = atan2f(dist.x, dist.z); + rotation.z = (float_t)(c->roll * DEG_TO_RAD); + + c->rotation = rotation; + vec3_negate(rotation, rotation); + + vec3 view_point; + vec3_negate(c->view_point, view_point); + c->view = mat4_identity; - mat4_rot_z(&c->view, -c->rotation.z, &c->view); - mat4_rot_x(&c->view, -c->rotation.x, &c->view); - mat4_rot_y(&c->view, -c->rotation.y, &c->view); - mat4_translate_mult(&c->view, -c->view_point.x, -c->view_point.y, -c->view_point.z, &c->view); + mat4_rot_z(&c->view, rotation.z, &c->view); + mat4_rot_x(&c->view, rotation.x, &c->view); + mat4_rot_y(&c->view, rotation.y, &c->view); + mat4_translate_mult(&c->view, view_point.x, view_point.y, view_point.z, &c->view); + mat4_inverse(&c->view, &c->inv_view); mat3_from_mat4(&c->view, &c->view_mat3); mat3_inverse(&c->view_mat3, &c->inv_view_mat3); + + if (fabs(c->rotation.x * RAD_TO_DEG - c->pitch) > 0.01 + || fabs(-c->rotation.y * RAD_TO_DEG - c->yaw) > 0.01) { + c->pitch = c->rotation.x * RAD_TO_DEG; + c->yaw = -c->rotation.y * RAD_TO_DEG; + camera_calculate_forward(c); + } } diff --git a/src/CRE/camera.h b/src/CRE/camera.h index 4f38a2b0..b7b6b2eb 100644 --- a/src/CRE/camera.h +++ b/src/CRE/camera.h @@ -11,30 +11,37 @@ typedef struct camera { mat4 view; - mat4 projection; - mat4 view_projection; - mat4 inv_projection; mat4 inv_view; + mat4 projection; + mat4 inv_projection; + mat4 view_projection; + mat4 inv_view_projection; mat3 view_mat3; mat3 inv_view_mat3; vec3 forward; vec3 rotation; vec3 view_point; vec3 interest; + int32_t width; + int32_t height; + vec3 field_1E4; + vec3 field_1F0; + vec3 field_1FC; + vec3 field_208; double_t yaw; double_t pitch; double_t roll; double_t aspect; double_t fov; + double_t fov_rad; double_t max_distance; double_t min_distance; - bool changed_proj; bool changed_view; - bool updated; + bool changed_proj; } camera; extern camera* camera_init(); -extern void camera_initialize(camera* c, double_t aspect, double_t fov); +extern void camera_initialize(camera* c, double_t aspect, int32_t width, int32_t height); extern double_t camera_get_min_distance(camera* c); extern void camera_set_min_distance(camera* c, double_t value); extern double_t camera_get_max_distance(camera* c); @@ -51,8 +58,10 @@ extern double_t camera_get_roll(camera* c); extern void camera_set_roll(camera* c, double_t value); extern void camera_get_view_point(camera* c, vec3* value); extern void camera_set_view_point(camera* c, vec3* value); -extern void camera_get_interest_point(camera* c, vec3* value); -extern void camera_set_interest_point(camera* c, vec3* value); +extern void camera_get_interest(camera* c, vec3* value); +extern void camera_set_interest(camera* c, vec3* value); +extern void camera_get_res(camera* c, int32_t* width, int32_t* height); +extern void camera_set_res(camera* c, int32_t width, int32_t height); extern void camera_reset(camera* c); extern void camera_move(camera* c, vec2d* move); extern void camera_rotate(camera* c, vec2d* rotate); diff --git a/src/CRE/data.c b/src/CRE/data.c new file mode 100644 index 00000000..05cfbe7d --- /dev/null +++ b/src/CRE/data.c @@ -0,0 +1,777 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "data.h" +#include "../KKdLib/io/path.h" +#include "../KKdLib/io/stream.h" +#include "../KKdLib/str_utils.h" + +vector_func(data_struct_file) +vector_func(data_struct_directory) +vector_func(data_struct_path) + +data_struct data_list[DATA_MAX]; + +static char default_config[] = "#AFT\n\n\n"; + +static void data_free_inner(data_struct* ds); +static void data_load_inner(stream* s); +#if defined(CRE_DEV) +static void data_load_glitter_list(data_struct* ds, char* path); +#endif + +void data_struct_init() { + for (data_type i = DATA_AFT; i < DATA_MAX; i++) { + memset(&data_list[i], 0, sizeof(data_struct)); + data_list[i].type = i; + } +} + +void data_struct_load(char* path) { + stream s; + io_open(&s, path, "rb"); + if (s.io.stream) + data_load_inner(&s); + else { + io_free(&s); + io_mopen(&s, default_config, 7); + data_load_inner(&s); + } + io_free(&s); +} + +void data_struct_wload(wchar_t* path) { + stream s; + io_wopen(&s, path, L"rb"); + if (s.io.stream) + data_load_inner(&s); + else { + io_free(&s); + io_mopen(&s, default_config, 7); + data_load_inner(&s); + } + io_free(&s); +} + +void data_struct_get_directory_files(data_struct* ds, char* dir, vector_data_struct_file* data_files) { + vector_data_struct_file_clear(data_files, data_struct_file_free); + + size_t dir_len = utf8_length(dir); + if (dir_len < 3 || memcmp(dir, "rom", 3)) + return; + + if (dir_len != 3) { + dir += 4; + dir_len -= 4; + } + else { + dir += 3; + dir_len = 0; + } + + size_t max_len = 0; + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) + if (max_len < j->path.length) + max_len = j->path.length; + + char* temp = force_malloc(max_len + dir_len + 2); + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) { + char* path = string_data(&j->path); + size_t path_len = j->path.length; + + memcpy(temp, path, path_len); + memcpy(&temp[path_len], "\\", 2); + if (dir_len) + memcpy(&temp[path_len + 1], dir, dir_len + 1); + + vector_string files = vector_empty(string); + path_get_files(&files, temp); + for (string* l = files.begin; l != files.end; l++) { + char* l_str = string_data(l); + size_t len = l->length; + bool found = false; + for (data_struct_file* i = data_files->begin; i != data_files->end; i++) + if (!memcmp(l_str, string_data(&i->name), min(len, i->name.length) + 1)) { + found = true; + break; + } + + if (found) + continue; + + data_struct_file f; + string_init(&f.path, temp); + f.name = *l; + *l = string_empty; + vector_data_struct_file_push_back(data_files, &f); + } + vector_string_free(&files, string_free); + } + + free(temp); +} + +bool data_struct_load_file(data_struct* ds, void* data, char* dir, char* file, + bool (*load_func)(void* data, char* path, char* file, uint32_t hash)) { + size_t dir_len = utf8_length(dir); + if (dir_len < 3 || memcmp(dir, "rom", 3)) + return false; + + if (dir_len != 3) { + dir += 4; + dir_len -= 4; + } + else { + dir += 3; + dir_len = 0; + } + + size_t max_len = 0; + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) + if (max_len < j->path.length) + max_len = j->path.length; + + char* temp = force_malloc(max_len + dir_len + 2); + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) { + char* path = string_data(&j->path); + size_t path_len = j->path.length; + + memcpy(temp, path, path_len); + memcpy(&temp[path_len], "\\", 2); + if (dir_len) + memcpy(&temp[path_len + 1], dir, dir_len + 1); + + vector_string files = vector_empty(string); + path_get_files(&files, temp); + + bool ret = false; + for (string* l = files.begin; l != files.end; l++) { + if (str_utils_compare(string_data(l), file)) + continue; + + char* l_str = string_data(l); + char* t = strrchr(l_str, '.'); + size_t l_len = l->length; + if (t) + l_len = t - l_str - 1; + + uint32_t h = hash_murmurhash(l_str, l_len, 0, false, false); + ret = load_func(data, temp, l_str, h); + break; + } + vector_string_free(&files, string_free); + + if (ret) { + free(temp); + return true; + } + } + + free(temp); + return false; +} + +bool data_struct_load_file_by_hash(data_struct* ds, void* data, char* dir, uint32_t hash, + bool (*load_func)(void* data, char* path, char* file, uint32_t hash)) { + size_t dir_len = utf8_length(dir); + if (dir_len < 3 || memcmp(dir, "rom", 3)) + return false; + + if (dir_len != 3) { + dir += 4; + dir_len -= 4; + } + else { + dir += 3; + dir_len = 0; + } + + size_t max_len = 0; + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) + if (max_len < j->path.length) + max_len = j->path.length; + + char* temp = force_malloc(max_len + dir_len + 2); + for (data_struct_path* i = ds->data_paths.begin; i != ds->data_paths.end; i++) + for (data_struct_directory* j = i->data.begin; j != i->data.end; j++) { + char* path = string_data(&j->path); + size_t path_len = j->path.length; + + memcpy(temp, path, path_len); + memcpy(&temp[path_len], "\\", 2); + if (dir_len) + memcpy(&temp[path_len + 1], dir, dir_len + 1); + + vector_string files = vector_empty(string); + path_get_files(&files, temp); + + vector_uint32_t files_murmurhash = vector_empty(uint32_t); + vector_uint32_t_reserve(&files_murmurhash, files.end - files.begin); + for (string* l = files.begin; l != files.end; l++) { + char* t = strrchr(string_data(l), '.'); + size_t t_len = l->length; + if (t) + t_len = t - string_data(l); + t = string_data(l); + + uint32_t h = hash_murmurhash(t, t_len, 0, false, false); + vector_uint32_t_push_back(&files_murmurhash, &h); + } + + bool ret = false; + for (uint32_t* l = files_murmurhash.begin; l != files_murmurhash.end; l++) + if (*l == hash) { + string* file = &files.begin[l - files_murmurhash.begin]; + ret = load_func(data, temp, string_data(file), hash); + break; + } + vector_string_free(&files, string_free); + vector_uint32_t_free(&files_murmurhash, 0); + + if (ret) { + free(temp); + return true; + } + } + + free(temp); + return false; +} + +void data_struct_free() { + if (data_list[DATA_AFT].ready) { + data_struct* ds = &data_list[DATA_AFT]; + data_ft* d = &ds->data_ft; + + auth_3d_database_free(&d->auth_3d_db); + bone_database_free(&d->bone_data); + motion_database_free(&d->mot_db); + object_database_free(&d->obj_db); + stage_database_free(&d->stage_data); + texture_database_free(&d->tex_db); + + auth_3d_database_file_free(&d->base_auth_3d_db); + motion_database_free(&d->base_mot_db); + object_database_free(&d->base_obj_db); + stage_database_free(&d->base_stage_data); + texture_database_free(&d->base_tex_db); + } +#if defined(CRE_DEV) + if (data_list[DATA_F2BE].ready) { + data_struct* ds = &data_list[DATA_F2BE]; + data_f2* d = &ds->data_f2; + } + + if (data_list[DATA_F2LE].ready) { + data_struct* ds = &data_list[DATA_F2LE]; + data_f2* d = &ds->data_f2; + } + + if (data_list[DATA_FT].ready) { + data_struct* ds = &data_list[DATA_FT]; + data_ft* d = &ds->data_ft; + } + + if (data_list[DATA_M39].ready) { + data_struct* ds = &data_list[DATA_M39]; + data_ft* d = &ds->data_ft; + } + + if (data_list[DATA_VRFL].ready) { + data_struct* ds = &data_list[DATA_VRFL]; + data_x* d = &ds->data_x; + + bone_database_free(&d->bone_data); + } + + if (data_list[DATA_X].ready) { + data_struct* ds = &data_list[DATA_X]; + data_x* d = &ds->data_x; + + bone_database_free(&d->bone_data); + } + + if (data_list[DATA_XHD].ready) { + data_struct* ds = &data_list[DATA_XHD]; + data_x* d = &ds->data_x; + + bone_database_free(&d->bone_data); + } +#endif + + for (data_type i = DATA_AFT; i < DATA_MAX; i++) + data_free_inner(&data_list[i]); +} + +void data_struct_directory_free(data_struct_directory* data_dir) { + string_free(&data_dir->path); + string_free(&data_dir->name); +} + +void data_struct_path_free(data_struct_path* data_path) { + string_free(&data_path->path); + vector_data_struct_directory_free(&data_path->data, data_struct_directory_free); +} + +void data_struct_file_free(data_struct_file* file) { + string_free(&file->path); + string_free(&file->name); +} + +static void data_free_inner(data_struct* ds) { + vector_data_struct_path_free(&ds->data_paths, data_struct_path_free); + +#if defined(CRE_DEV) + vector_string_free(&ds->glitter_list_names, string_free); + switch (ds->type) { + case DATA_F2LE: + case DATA_F2BE: + case DATA_VRFL: + case DATA_X: + case DATA_XHD: + vector_uint32_t_free(&ds->glitter_list_murmurhash, 0); + break; + case DATA_AFT: + case DATA_FT: + case DATA_M39: + vector_uint64_t_free(&ds->glitter_list_fnv1a64m, 0); + break; + } +#endif + ds->ready = false; +} + +static void data_load_inner(stream* s) { + size_t length = s->length; + void* data = force_malloc(length); + io_read(s, data, length); + + char* buf; + char** lines; + size_t count; + if (!str_utils_text_file_parse(data, length, &buf, &lines, &count)) { + free(data); + return; + } + free(data); + + for (size_t i = 0; i < count; i++) { + char* s = lines[i]; + data_struct* ds + = 0; + char* main_rom = "rom"; + char* add_data_rom = "rom"; + char* add_data = ""; + if (!str_utils_compare(s, "#AFT")) { + ds = &data_list[DATA_AFT]; + add_data = "mdata"; + } +#if defined(CRE_DEV) + else if (!str_utils_compare(s, "#F2BE")) { + ds = &data_list[DATA_F2BE]; + add_data = "dlc"; + } + else if (!str_utils_compare(s, "#F2LE")) { + ds = &data_list[DATA_F2LE]; + add_data = "dlc"; + } + else if (!str_utils_compare(s, "#FT")) { + ds = &data_list[DATA_FT]; + add_data = "mdata"; + } + else if (!str_utils_compare(s, "#M39")) { + ds = &data_list[DATA_M39]; + add_data = "rom_switch_dlc"; + } + else if (!str_utils_compare(s, "#VRFL")) { + ds = &data_list[DATA_VRFL]; + main_rom = "cnt_rom"; + add_data_rom = ""; + } + else if (!str_utils_compare(s, "#X")) { + ds = &data_list[DATA_X]; + main_rom = "cnt_rom"; + add_data_rom = ""; + } + else if (!str_utils_compare(s, "#XHD")) { + ds = &data_list[DATA_XHD]; + main_rom = "cnt_rom"; + add_data_rom = ""; + } +#endif + else + continue; + + data_free_inner(ds); + +#if defined(CRE_DEV) + if (i + 2 >= count) + continue; + + char* data_paths = lines[i + 1]; + char* glitter_list = lines[i + 2]; + i++; + + if (!str_utils_check_ends_with(glitter_list, ".glitter.txt")) + continue; + + data_load_glitter_list(ds, glitter_list); +#else + char* data_paths; + if (i + 1 < count) + data_paths = lines[i + 1]; + else if (i < count) + data_paths = "."; + else + continue; + i++; +#endif + + char* t = data_paths; + size_t count = 1; + while (t = strchr(t, ';')) { + *t++ = 0; + count++; + } + + size_t max_len = 0; + t = data_paths; + for (size_t j = 0; j < count; j++) { + size_t len = utf8_length(t); + if (max_len < len) + max_len = len; + t += len + 1; + } + + size_t main_rom_len = utf8_length(main_rom); + size_t add_data_len = utf8_length(add_data); + size_t add_data_rom_len = utf8_length(add_data_rom); + + char* main_rom_path = force_malloc(max_len + main_rom_len + 3); + if (!main_rom_path) { + data_free_inner(ds); + continue; + } + + char* add_data_rom_path = force_malloc(max_len + add_data_len + 3); + if (!add_data_rom_path) { + free(main_rom_path); + data_free_inner(ds); + continue; + } + + ssize_t* t_len = force_malloc_s(ssize_t, count); + if (!t_len) { + free(main_rom_path); + free(add_data_rom_path); + data_free_inner(ds); + continue; + } + + t = data_paths; + for (size_t j = 0; j < count; j++) + t += (t_len[j] = utf8_length(t)) + 1; + + vector_data_struct_path_reserve(&ds->data_paths, count); + for (size_t j = 0; j < count; j++) { + data_struct_path data_path; + t -= t_len[count - j - 1] + 1; + string_init_length(&data_path.path, t, t_len[count - j - 1]); + data_path.data = vector_empty(data_struct_directory); + vector_data_struct_path_push_back(&ds->data_paths, &data_path); + } + free(t_len); + + for (data_struct_path* j = ds->data_paths.begin; j != ds->data_paths.end; j++) { + size_t data_path_length = j->path.length; + if (!main_rom_len) + memcpy(main_rom_path, string_data(&j->path), data_path_length); + else if (data_path_length) { + memcpy(main_rom_path, string_data(&j->path), data_path_length); + main_rom_path[data_path_length] = '\\'; + memcpy(&main_rom_path[data_path_length + 1], main_rom, main_rom_len + 1); + } + else + memcpy(main_rom_path, main_rom, main_rom_len + 1); + + if (!add_data_len) + memcpy(add_data_rom_path, string_data(&j->path), data_path_length); + else if (data_path_length) { + memcpy(add_data_rom_path, string_data(&j->path), data_path_length); + add_data_rom_path[data_path_length] = '\\'; + memcpy(&add_data_rom_path[data_path_length + 1], add_data, add_data_len + 1); + } + else + memcpy(add_data_rom_path, add_data, add_data_len + 1); + + size_t main_rom_path_len = utf8_length(main_rom_path); + if (main_rom_path_len && main_rom_path[main_rom_path_len - 1] == '\\') { + main_rom_path[main_rom_path_len - 1] = 0; + main_rom_path_len--; + } + + size_t add_data_rom_path_len = utf8_length(add_data_rom_path); + if (add_data_rom_path_len && add_data_rom_path[add_data_rom_path_len - 1] == '\\') { + add_data_rom_path[add_data_rom_path_len - 1] = 0; + add_data_rom_path_len--; + } + + vector_string data_directories = vector_empty(string); + path_get_directories(&data_directories, add_data_rom_path, &main_rom_path, 1); + + max_len = 0; + for (string* k = data_directories.begin; k != data_directories.end; k++) { + size_t len = k->length; + if (max_len < len) + max_len = len; + } + + char* data_dir_path_temp = force_malloc(add_data_rom_path_len + max_len + add_data_rom_len + 3); + if (data_dir_path_temp) { + vector_data_struct_directory_reserve(&j->data, + data_directories.end - data_directories.begin + 1); + memcpy(data_dir_path_temp, add_data_rom_path, add_data_rom_path_len); + data_dir_path_temp[add_data_rom_path_len] = '\\'; + for (string* k = data_directories.end - 1; k != data_directories.begin - 1; k--) { + memcpy(&data_dir_path_temp[add_data_rom_path_len + 1], string_data(k), k->length + 1); + if (add_data_rom_len) { + data_dir_path_temp[add_data_rom_path_len + 1 + k->length] = '\\'; + memcpy(&data_dir_path_temp[add_data_rom_path_len + 1 + k->length + 1], + add_data_rom, add_data_rom_len + 1); + } + + data_struct_directory data_dir; + string_init(&data_dir.path, data_dir_path_temp); + data_dir.name = *k; + vector_data_struct_directory_push_back(&j->data, &data_dir); + } + vector_string_free(&data_directories, 0); + } + else { + vector_data_struct_directory_reserve(&j->data, 1); + vector_string_free(&data_directories, string_free); + } + free(data_dir_path_temp); + + data_struct_directory data_dir; + string_init(&data_dir.path, main_rom_path); + data_dir.name = string_empty; + vector_data_struct_directory_push_back(&j->data, &data_dir); + free(data_dir_path_temp); + } + free(main_rom_path); + free(add_data_rom_path); + ds->ready = true; + } + free(buf); + free(lines); + + if (data_list[DATA_AFT].ready) { + data_struct* ds = &data_list[DATA_AFT]; + data_ft* d = &ds->data_ft; + + auth_3d_database_file* base_auth_3d_db = &d->base_auth_3d_db; + auth_3d_database_file_init(base_auth_3d_db); + data_struct_load_file(ds, base_auth_3d_db, "rom\\auth_3d\\", + "auth_3d_db.bin", auth_3d_database_file_load_file); + + auth_3d_database_file mdata_auth_3d_db; + auth_3d_database_file_init(&mdata_auth_3d_db); + data_struct_load_file(ds, &mdata_auth_3d_db, "rom\\auth_3d\\", + "mdata_auth_3d_db.bin", auth_3d_database_file_load_file); + + auth_3d_database* auth_3d_db = &d->auth_3d_db; + auth_3d_database_init(auth_3d_db); + auth_3d_database_merge_mdata(auth_3d_db, base_auth_3d_db, &mdata_auth_3d_db); + auth_3d_database_file_free(&mdata_auth_3d_db); + + bone_database* bone_data = &d->bone_data; + bone_database_init(bone_data); + bone_data->modern = false; + data_struct_load_file(ds, bone_data, "rom\\", + "bone_data.bin", bone_database_load_file); + + motion_database* base_mot_db = &d->base_mot_db; + motion_database_init(base_mot_db); + data_struct_load_file(ds, base_mot_db, "rom\\rob\\", + "mot_db.farc", motion_database_load_file); + + motion_database mdata_mot_db; + motion_database_init(&mdata_mot_db); + data_struct_load_file(ds, &mdata_mot_db, "rom\\rob\\", + "mdata_mot_db.farc", motion_database_load_file); + + motion_database* mot_db = &d->mot_db; + motion_database_init(mot_db); + motion_database_merge_mdata(mot_db, base_mot_db, &mdata_mot_db); + motion_database_free(&mdata_mot_db); + + object_database* base_obj_db = &d->base_obj_db; + object_database_init(base_obj_db); + base_obj_db->modern = false; + data_struct_load_file(ds, base_obj_db, "rom\\objset\\", + "obj_db.bin", object_database_load_file); + + object_database mdata_obj_db; + object_database_init(&mdata_obj_db); + mdata_obj_db.modern = false; + data_struct_load_file(ds, &mdata_obj_db, "rom\\objset\\", + "mdata_obj_db.bin", object_database_load_file); + + object_database* obj_db = &d->obj_db; + object_database_init(obj_db); + object_database_merge_mdata(obj_db, base_obj_db, &mdata_obj_db); + object_database_free(&mdata_obj_db); + + stage_database* base_stage_data = &d->base_stage_data; + stage_database_init(base_stage_data); + base_stage_data->modern = false; + data_struct_load_file(ds, base_stage_data, "rom\\", + "stage_data.bin", stage_database_load_file); + + stage_database mdata_stage_data; + stage_database_init(&mdata_stage_data); + mdata_stage_data.modern = false; + data_struct_load_file(ds, &mdata_stage_data, "rom\\", + "mdata_stage_data.bin", stage_database_load_file); + + stage_database* stage_data = &d->stage_data; + stage_database_init(stage_data); + stage_database_merge_mdata(stage_data, base_stage_data, &mdata_stage_data); + stage_database_free(&mdata_stage_data); + + texture_database* base_tex_db = &d->base_tex_db; + texture_database_init(base_tex_db); + base_tex_db->modern = false; + data_struct_load_file(ds, base_tex_db, "rom\\objset\\", + "tex_db.bin", texture_database_load_file); + + texture_database mdata_tex_db; + texture_database_init(&mdata_tex_db); + mdata_tex_db.modern = false; + data_struct_load_file(ds, &mdata_tex_db, "rom\\objset\\", + "mdata_tex_db.bin", texture_database_load_file); + + texture_database* tex_db = &d->tex_db; + texture_database_init(tex_db); + texture_database_merge_mdata(tex_db, base_tex_db, &mdata_tex_db); + texture_database_free(&mdata_tex_db); + } + +#if defined(CRE_DEV) + if (data_list[DATA_F2BE].ready) { + data_struct* ds = &data_list[DATA_F2BE]; + } + + if (data_list[DATA_F2LE].ready) { + data_struct* ds = &data_list[DATA_F2LE]; + } + + if (data_list[DATA_FT].ready) { + data_struct* ds = &data_list[DATA_FT]; + } + + if (data_list[DATA_M39].ready) { + data_struct* ds = &data_list[DATA_M39]; + } + + if (data_list[DATA_VRFL].ready) { + data_struct* ds = &data_list[DATA_VRFL]; + data_f2* d = &ds->data_f2; + + bone_database* bone_data = &d->bone_data; + bone_database_init(bone_data); + bone_data->modern = true; + data_struct_load_file(ds, bone_data, "rom\\", + "bone_data.bon", bone_database_load_file); + } + + if (data_list[DATA_X].ready) { + data_struct* ds = &data_list[DATA_X]; + data_f2* d = &ds->data_f2; + + bone_database* bone_data = &d->bone_data; + bone_database_init(bone_data); + bone_data->modern = true; + data_struct_load_file(ds, bone_data, "rom\\", + "bone_data.bon", bone_database_load_file); + } + + if (data_list[DATA_XHD].ready) { + data_struct* ds = &data_list[DATA_XHD]; + data_f2* d = &ds->data_f2; + + bone_database* bone_data = &d->bone_data; + bone_database_init(bone_data); + bone_data->modern = true; + data_struct_load_file(ds, bone_data, "rom\\", + "bone_data.bon", bone_database_load_file); + } +#endif +} + +#if defined(CRE_DEV) +static void data_load_glitter_list(data_struct* ds, char* path) { + stream s; + io_open(&s, path, "rb"); + size_t length = s.length; + uint8_t* data = force_malloc(length); + io_read(&s, data, length); + io_free(&s); + + char* buf; + char** lines; + size_t count; + if (str_utils_text_file_parse(data, length, &buf, &lines, &count)) { + for (size_t i = 0; i < count; i++) { + char* t = strstr(lines[i], "#(?)"); + if (t) + *t = 0; + } + + vector_string_reserve(&ds->glitter_list_names, count); + for (size_t i = 0; i < count; i++) { + size_t len = utf8_length(lines[i]); + string s; + string_init_length(&s, lines[i], min(len, 0x7F)); + vector_string_push_back(&ds->glitter_list_names, &s); + } + + switch (ds->type) { + case DATA_F2LE: + case DATA_F2BE: + case DATA_VRFL: + case DATA_X: + case DATA_XHD: + vector_uint32_t_reserve(&ds->glitter_list_murmurhash, count); + for (size_t i = 0; i < count; i++) { + size_t len = ds->glitter_list_names.begin[i].length; + uint32_t hash = hash_murmurhash(lines[i], len, 0, false, false); + vector_uint32_t_push_back(&ds->glitter_list_murmurhash, &hash); + } + break; + case DATA_AFT: + case DATA_FT: + case DATA_M39: + vector_uint64_t_reserve(&ds->glitter_list_fnv1a64m, count); + for (size_t i = 0; i < count; i++) { + size_t len = ds->glitter_list_names.begin[i].length; + uint64_t hash = hash_fnv1a64m(lines[i], len); + vector_uint64_t_push_back(&ds->glitter_list_fnv1a64m, &hash); + } + break; + } + + free(buf); + free(lines); + } + free(data); +} +#endif diff --git a/src/CRE/data.h b/src/CRE/data.h new file mode 100644 index 00000000..83887ffb --- /dev/null +++ b/src/CRE/data.h @@ -0,0 +1,120 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/database/auth_3d.h" +#include "../KKdLib/database/bone.h" +#include "../KKdLib/database/motion.h" +#include "../KKdLib/database/object.h" +#include "../KKdLib/database/stage.h" +#include "../KKdLib/database/texture.h" +#include "../KKdLib/hash.h" +#include "../KKdLib/string.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/vector.h" + +typedef enum data_type { + DATA_AFT = 0, +#if defined(CRE_DEV) || defined(CLOUD_DEV) + DATA_F2LE, + DATA_F2BE, + DATA_FT, + DATA_M39, + DATA_VRFL, + DATA_X, + DATA_XHD, +#endif + DATA_MAX, +} data_type; + +typedef struct data_struct_file { + string path; + string name; +} data_struct_file; + +vector(data_struct_file) + +typedef struct data_struct_directory { + string path; + string name; +} data_struct_directory; + +vector(data_struct_directory) + +typedef struct data_struct_path { + string path; + vector_data_struct_directory data; +} data_struct_path; + +vector(data_struct_path) + +#if defined(CRE_DEV) || defined(CLOUD_DEV) +typedef struct data_f2 { + bone_database bone_data; +} data_f2; +#endif + +typedef struct data_ft { + auth_3d_database auth_3d_db; + bone_database bone_data; + motion_database mot_db; + object_database obj_db; + stage_database stage_data; + texture_database tex_db; + + auth_3d_database_file base_auth_3d_db; + motion_database base_mot_db; + object_database base_obj_db; + stage_database base_stage_data; + texture_database base_tex_db; +} data_ft; + +#if defined(CRE_DEV) || defined(CLOUD_DEV) +typedef struct data_x { + bone_database bone_data; +} data_x; +#endif + +typedef struct data_struct { + data_type type; + bool ready; + vector_data_struct_path data_paths; +#if defined(CRE_DEV) || defined(CLOUD_DEV) + vector_string glitter_list_names; + union { + vector_uint64_t glitter_list_fnv1a64m; + vector_uint32_t glitter_list_murmurhash; + }; +#endif + union { +#if defined(CRE_DEV) || defined(CLOUD_DEV) + data_f2 data_f2; +#endif + data_ft data_ft; +#if defined(CRE_DEV) || defined(CLOUD_DEV) + data_x data_x; +#endif + }; +} data_struct; + +extern data_struct data_list[]; + +#define DATA_LOAD_FILE_FUNC(f) + +extern void data_struct_init(); +extern void data_struct_load(char* path); +extern void data_struct_wload(wchar_t* path); +extern void data_struct_get_directory_files(data_struct* c, char* dir, vector_data_struct_file* data_files); +extern bool data_struct_load_file(data_struct* c, void* data, char* dir, char* file, + bool (*load_func)(void* data, char* path, char* file, uint32_t hash)); +extern bool data_struct_load_file_by_hash(data_struct* c, void* data, char* dir, uint32_t hash, + bool (*load_func)(void* data, char* path, char* file, uint32_t hash)); +extern void data_struct_free(); + +extern void data_struct_directory_free(data_struct_directory* data_dir); +extern void data_struct_path_free(data_struct_path* data_path); +extern void data_struct_file_free(data_struct_file* file); diff --git a/src/CRE/dof.c b/src/CRE/dof.c deleted file mode 100644 index 0f4dd657..00000000 --- a/src/CRE/dof.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "dof.h" - -static const dof_debug dof_debug_default = { - .flags = 0, - .distance_to_focus = 10.0f, - .focal_length = 40.0f, - .f_number = 1.4f, - .f2 = { - .distance_to_focus = 10.0f, - .focus_range = 1.0f, - .fuzzing_range = 0.5f, - .ratio = 1.0f, - }, -}; - -static const dof_pv dof_pv_default = { - .enable = false, - .f2 = { - .distance_to_focus = 10.0f, - .focus_range = 1.0f, - .fuzzing_range = 0.5f, - .ratio = 1.0f, - }, -}; - -dof_struct* dof_init() { - dof_struct* d = force_malloc(sizeof(dof_struct)); - return d; -} - -void dof_initialize(dof_struct* d, dof_debug* debug, dof_pv* pv) { - if (debug) - d->debug = *debug; - else - d->debug = dof_debug_default; - - if (pv) - d->pv = *pv; - else - d->pv = dof_pv_default; -} - -void dof_get_dof_debug(dof_struct* d, dof_debug* debug) { - if (debug) - *debug = d->debug; -} - -void dof_set_dof_debug(dof_struct* d, dof_debug* debug) { - if (debug) - d->debug = *debug; - else - d->debug = dof_debug_default; -} - -void dof_get_dof_pv(dof_struct* d, dof_pv* pv) { - if (pv) - *pv = d->pv; -} - -void dof_set_dof_pv(dof_struct* d, dof_pv* pv) { - if (pv) - d->pv = *pv; - else - d->pv = dof_pv_default; -} - -void dof_dispose(dof_struct* d) { - free(d); -} diff --git a/src/CRE/dof.h b/src/CRE/dof.h deleted file mode 100644 index 7658db19..00000000 --- a/src/CRE/dof.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/mat.h" -#include "../KKdLib/vec.h" - -typedef enum dof_debug_flags { - DOF_DEBUG_USE_UI_PARAMS = 0x1, - DOF_DEBUG_ENABLE_DOF = 0x2, - DOF_DEBUG_ENABLE_PHYS_DOF = 0x4, - DOF_DEBUG_AUTO_FOCUS = 0x8, -} dof_debug_flags; - -typedef struct dof_f2 { - float_t distance_to_focus; - float_t focus_range; - float_t fuzzing_range; - float_t ratio; -} dof_f2; - -typedef struct dof_debug { - dof_debug_flags flags; - float_t distance_to_focus; - float_t focal_length; - float_t f_number; - dof_f2 f2; -} dof_debug; - -typedef struct dof_pv { - bool enable; - dof_f2 f2; -} dof_pv; - -typedef struct dof_struct { - dof_debug debug; - dof_pv pv; -} dof_struct; - -extern dof_struct* dof_init(); -extern void dof_initialize(dof_struct* d, dof_debug* debug, dof_pv* pv); -extern void dof_dispose(dof_struct* d); diff --git a/src/CRE/draw_object.c b/src/CRE/draw_object.c new file mode 100644 index 00000000..56d6f438 --- /dev/null +++ b/src/CRE/draw_object.c @@ -0,0 +1,1722 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "draw_object.h" +#include "light_param/light.h" +#include "shader_ft.h" +#include "static_var.h" +#include "texture.h" + +#define enable_vertex_attrib_array(index) \ +glEnableVertexAttribArray(index); \ +draw->vertex_attrib_array[index] = true + +static bool draw_object_blend_set(render_context* rctx, + draw_object* draw, object_material_shader_lighting_type lighting_type); +static void draw_object_chara_color_fog_set(render_context* rctx, + draw_object* draw, bool disable_fog); +static void draw_object_material_reset_default(object_material_data* mat_data); +static void draw_object_material_reset_reflect(); +static void draw_object_material_set_default(render_context* rctx, + draw_object* draw, bool use_shader); +static void draw_object_material_set_parameter(render_context* rctx, + object_material_data* mat_data); +static void draw_object_material_set_reflect(render_context* rctx, draw_object* draw); +static void draw_object_material_set_uniform(render_context* rctx, + object_material_data* mat_data, bool disable_color_l); +static void draw_object_vertex_attrib_reset_default(draw_object* draw); +static void draw_object_vertex_attrib_reset_default_compressed(draw_object* draw); +static void draw_object_vertex_attrib_reset_reflect(draw_object* draw); +static void draw_object_vertex_attrib_reset_reflect_compressed(draw_object* draw); +static void draw_object_vertex_attrib_set_default(draw_object* draw); +static void draw_object_vertex_attrib_set_default_compressed(draw_object* draw); +static void draw_object_vertex_attrib_set_reflect(draw_object* draw); +static void draw_object_vertex_attrib_set_reflect_compressed(draw_object* draw); + +void draw_object_draw(render_context* rctx, draw_object* draw, mat4* model, + void(*draw_object_func)(render_context* rctx, draw_object* draw), int32_t show_vector) { + if (draw->mats) { + mat4u* mats = draw->mats; + mat4 mat; + for (int32_t i = 0; i < draw->mat_count; i++, mats++) { + mat4u_to_mat4_transpose(mats, &mat); + shader_buffer_set_ptr_array(&shaders_ft, (size_t)i * 3, 3, (vec4*)&mat); + } + uniform_value[U_BONE_MAT] = 1; + } + else { + for (int32_t i = 0; i < SHADER_MAX_PROGRAM_BUFFER_PARAMETERS / 3; i++) + shader_buffer_set_ptr_array(&shaders_ft, (size_t)i * 3, 3, (vec4*)&mat4_identity); + uniform_value[U_BONE_MAT] = 0; + } + + mat4 mat; + if (draw->mesh->flags & OBJECT_MESH_BILLBOARD) + model_mat_face_camera_view(&rctx->camera->view, model, &mat); + else if (draw->mesh->flags & OBJECT_MESH_BILLBOARD_Y_AXIS) + model_mat_face_camera_position(&rctx->camera->view, model, &mat); + else + mat = *model; + draw_object_model_mat_load(rctx, &mat); + + if (!show_vector) + draw_object_func(rctx, draw); + uniform_value[U_BONE_MAT] = 0; +} + +void draw_object_draw_default(render_context* rctx, draw_object* draw) { + if (draw->set_blend_color) { + vec4 blend_color; + vec4u_to_vec4(draw->blend_color, blend_color); + shader_env_vert_set_ptr(&shaders_ft, 3, &blend_color); + shader_env_vert_set_ptr(&shaders_ft, 4, (vec4*)&vec4_null); + } + + if (!draw->draw_object_func) + draw_object_vertex_attrib_set_default(draw); + + draw_object_material_set_default(rctx, draw, rctx->draw_state.shader); + if (!draw->instances_count) + object_sub_mesh_draw(rctx, + draw->sub_mesh->primitive_type, + draw->sub_mesh->indices_count, + draw->sub_mesh->first_index, + draw->sub_mesh->last_index, + draw->sub_mesh->index_format, + draw->sub_mesh->indices_offset); + else + for (int32_t i = 0; i < draw->instances_count; i++) { + mat4 mat; + mat4_transpose(&draw->instances_mat[i], &mat); + glVertexAttrib4fv(12, (const GLfloat*)&mat.row0); + glVertexAttrib4fv(13, (const GLfloat*)&mat.row1); + glVertexAttrib4fv(14, (const GLfloat*)&mat.row2); + glVertexAttrib4fv(15, (const GLfloat*)&mat.row3); + object_sub_mesh_draw(rctx, + draw->sub_mesh->primitive_type, + draw->sub_mesh->indices_count, + draw->sub_mesh->first_index, + draw->sub_mesh->last_index, + draw->sub_mesh->index_format, + draw->sub_mesh->indices_offset); + } + + draw_object_material_reset_default(draw->material); + if (!draw->draw_object_func) + draw_object_vertex_attrib_reset_default(draw); + + if (draw->set_blend_color) { + shader_env_vert_set_ptr(&shaders_ft, 3, (vec4*)&vec4_identity); + shader_env_vert_set_ptr(&shaders_ft, 4, (vec4*)&vec4_null); + } + + rctx->draw_state.stats.object_draw_count++; +} + +void draw_object_draw_sss(render_context* rctx, draw_object* draw) { + object_material_blend_flags blend_flags = draw->material->material.blend_flags; + uniform_value[U_ALPHA_TEST] = (!blend_flags.flag_28 && (draw->blend_color.w < 1.0f + || (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through + || draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) + || blend_flags.punch_through) ? 1 : 0; + + bool aniso = false; + object_material_data* material = draw->material; + switch (material->material.shader_index) { + case SHADER_FT_SKIN: + uniform_value[U26] = 1; + break; + case SHADER_FT_CLOTH: + uniform_value[U26] = 1; + if (rctx->draw_pass.npr_param || material->material.ambient.w >= 1.0f + || (material->material.shader_flags.aniso_direction & 0x03) != OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL) + aniso = true; + break; + case SHADER_FT_TIGHTS: + uniform_value[U26] = 1; + if (rctx->draw_pass.npr_param) + aniso = true; + break; + case SHADER_FT_EYEBALL: + uniform_value[U26] = 0; + return; + } + + vec3 sss_param; + if (!aniso) { + uniform_value[U37] = 1; + sss_param = *(vec3*)&rctx->draw_pass.sss_data.param; + } + else { + uniform_value[U37] = 0; + sss_param = vec3_null; + } + + shader_env_frag_set(&shaders_ft, 25, sss_param.x, sss_param.y, sss_param.z, 0.5f); + draw_object_draw_default(rctx, draw); +} + +void draw_object_draw_reflect(render_context* rctx, draw_object* draw) { + object_material_data* material = draw->material; + draw_object_vertex_attrib_set_reflect(draw); + object_material_shader_lighting_type lighting_type = + object_material_shader_get_lighting_type(&material->material.shader_flags); + bool disable_fog = draw_object_blend_set(rctx, draw, lighting_type); + draw_object_chara_color_fog_set(rctx, draw, disable_fog); + draw_object_material_set_reflect(rctx, draw); + + object_sub_mesh* sub_mesh = draw->sub_mesh; + if (sub_mesh->index_format != OBJECT_INDEX_U8) + object_sub_mesh_draw(rctx, + sub_mesh->primitive_type, + sub_mesh->indices_count, + sub_mesh->first_index, + sub_mesh->last_index, + sub_mesh->index_format, + sub_mesh->indices_offset); + + draw_object_material_reset_reflect(); + draw_object_vertex_attrib_reset_reflect(draw); + uniform_value_reset(); + + rctx->draw_state.stats.object_reflect_draw_count++; +} + +void draw_object_draw_reflect_type_2(render_context* rctx, draw_object* draw) { + draw_object_vertex_attrib_set_reflect(draw); + draw_object_material_set_reflect(rctx, draw); + + object_sub_mesh* sub_mesh = draw->sub_mesh; + if (sub_mesh->index_format != OBJECT_INDEX_U8) + object_sub_mesh_draw(rctx, + sub_mesh->primitive_type, + sub_mesh->indices_count, + sub_mesh->first_index, + sub_mesh->last_index, + sub_mesh->index_format, + sub_mesh->indices_offset); + + draw_object_material_reset_reflect(); + draw_object_vertex_attrib_reset_reflect(draw); + + rctx->draw_state.stats.object_reflect_draw_count++; +} + +void draw_object_draw_shadow(render_context* rctx, draw_object* draw) { + object_material_blend_flags blend_flags = draw->material->material.blend_flags; + if (!blend_flags.flag_28 && (draw->blend_color.w < 1.0f + || (blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through + || draw->sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) + || blend_flags.punch_through) { + uniform_value[U_ALPHA_TEST] = 1; + draw_object_draw_translucent(rctx, draw); + } + else { + uniform_value[U_ALPHA_TEST] = 0; + draw_object_draw_translucent(rctx, draw); + } +} + +void draw_object_draw_translucent(render_context* rctx, draw_object* draw) { + object_material_data* material = draw->material; + GLuint* textures = draw->textures; + if (rctx->draw_state.shader_index != -1) { + vec4 emission; + vec4u_to_vec4(material->material.emission, emission); + shader_state_material_set_emission_ptr(&shaders_ft, false, &emission); + draw_object_material_set_uniform(rctx, material, 0); + if (material->material.blend_flags.alpha_texture) + uniform_value[U_TEXTURE_COUNT] = 0; + shader_set(&shaders_ft, rctx->draw_state.shader_index); + } + + draw_object_vertex_attrib_set_default(draw); + if (draw->material->material.blend_flags.double_sided) + gl_state_disable_cull_face(); + + GLuint tex_id = -1; + int32_t tex_index = 0; + if (material->material.blend_flags.alpha_texture) { + object_material_texture* mat_tex = material->material.textures; + uint32_t texture_id = -1; + uint32_t texture_index = -1; + if (~material->material.flags & OBJECT_MATERIAL_TRANSPARENCY) { + for (int32_t i = 0; i < 8; i++, mat_tex++) + if (mat_tex->texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) { + texture_id = mat_tex->texture_id; + texture_index = mat_tex->texture_index; + break; + } + tex_index = 0; + } + else { + for (int32_t i = 0; i < 8; i++, mat_tex++) + if (mat_tex->texture_flags.type == OBJECT_MATERIAL_TEXTURE_TRANSPARENCY) { + if (mat_tex->sampler_flags.flag_29) { + texture_id = mat_tex->texture_id; + texture_index = mat_tex->texture_index; + } + break; + } + tex_index = 4; + } + + if (texture_id != -1) { + for (int32_t j = 0; j < draw->texture_pattern_count; j++) + if (draw->texture_pattern_array[j].src == texture_id) { + texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst); + if (tex) + tex_id = tex->texture; + break; + } + + if (tex_id == -1) + tex_id = textures[mat_tex->texture_index]; + + if (tex_id == -1) + tex_id = 0; + + gl_state_active_bind_texture_2d(tex_index, tex_id); + } + } + + object_sub_mesh* sub_mesh = draw->sub_mesh; + if (sub_mesh->index_format != OBJECT_INDEX_U8) + object_sub_mesh_draw(rctx, + sub_mesh->primitive_type, + sub_mesh->indices_count, + sub_mesh->first_index, + sub_mesh->last_index, + sub_mesh->index_format, + sub_mesh->indices_offset); + + if (tex_id != -1) + gl_state_active_bind_texture_2d(tex_index, 0); + + gl_state_enable_cull_face(); + draw_object_vertex_attrib_reset_default(draw); + + if (rctx->draw_state.shader_index != -1) + uniform_value_reset(); + + rctx->draw_state.stats.object_translucent_draw_count++; +} + +inline void draw_object_model_mat_load(render_context* rctx, mat4* mat) { + shader_state_matrix_set_modelview_separate(&shaders_ft, 0, mat, &rctx->view_mat, true); + shader_state_matrix_set_program(&shaders_ft, 6, mat); +} + +inline void model_mat_face_camera_position(mat4* view, mat4* src, mat4* dst) { + vec3 trans; + mat4_mult_vec3_inv(view, (vec3*)&view->row3, &trans); + vec3_negate(trans, trans); + + vec3 dir; + vec3_sub(trans, *(vec3*)&src->row3, dir); + vec3_normalize(dir, dir); + + vec3 x_rot; + vec3 y_rot; + vec3 z_rot; + + y_rot = *(vec3*)&src->row1; + vec3_cross(y_rot, dir, x_rot); + vec3_normalize(x_rot, x_rot); + vec3_cross(x_rot, y_rot, z_rot); + + *(vec3*)&dst->row0 = x_rot; + *(vec3*)&dst->row1 = y_rot; + *(vec3*)&dst->row2 = z_rot; + *(vec3*)&dst->row3 = *(vec3*)&src->row3; + dst->row0.w = 0.0f; + dst->row1.w = 0.0f; + dst->row2.w = 0.0f; + dst->row3.w = 1.0f; +} + +inline void model_mat_face_camera_view(mat4* view, mat4* src, mat4* dst) { + mat3 mat; + mat3_from_mat4(view, &mat); + mat3_inverse(&mat, &mat); + mat4_from_mat3(&mat, dst); + mat4_mult(dst, src, dst); +} + +void object_sub_mesh_draw(render_context* rctx, object_primitive_type primitive_type, + uint32_t count, uint16_t start, uint16_t end, object_index_format index_format, size_t indices) { + GLenum mesh_draw_mode[] = { + [OBJECT_PRIMITIVE_POINTS ] = GL_ZERO, //GL_POINTS, + [OBJECT_PRIMITIVE_LINES ] = GL_LINES, + [OBJECT_PRIMITIVE_LINE_STRIP ] = GL_LINE_STRIP, + [OBJECT_PRIMITIVE_LINE_LOOP ] = GL_LINE_LOOP, + [OBJECT_PRIMITIVE_TRIANGLES ] = GL_TRIANGLES, + [OBJECT_PRIMITIVE_TRIANGLE_STRIP] = GL_TRIANGLE_STRIP, + [OBJECT_PRIMITIVE_TRIANGLE_FAN ] = GL_TRIANGLE_FAN, + [OBJECT_PRIMITIVE_QUADS ] = GL_ZERO, //GL_QUADS, + [OBJECT_PRIMITIVE_QUAD_STRIP ] = GL_ZERO, //GL_QUAD_STRIP, + [OBJECT_PRIMITIVE_POLYGON ] = GL_ZERO, //GL_POLYGON, + }; + + GLenum mesh_indices_type[] = { + [OBJECT_INDEX_U8 ] = GL_ZERO, + [OBJECT_INDEX_U16] = GL_UNSIGNED_SHORT, + [OBJECT_INDEX_U32] = GL_UNSIGNED_INT, + }; + + if (primitive_type == OBJECT_PRIMITIVE_TRIANGLE_STRIP && index_format == OBJECT_INDEX_U16) { + gl_state_enable_primitive_restart(); + glPrimitiveRestartIndex(0xFFFF); + shader_draw_range_elements(&shaders_ft, GL_TRIANGLE_STRIP, + start, end, count, GL_UNSIGNED_SHORT, (void*)indices); + gl_state_disable_primitive_restart(); + } + else + shader_draw_elements(&shaders_ft, mesh_draw_mode[primitive_type], + count, mesh_indices_type[index_format], (void*)indices); + + rctx->draw_state.stats.draw_count += count; + if (primitive_type == OBJECT_PRIMITIVE_TRIANGLES) + rctx->draw_state.stats.draw_triangle_count += count / 3; + else if (primitive_type == OBJECT_PRIMITIVE_TRIANGLE_STRIP) + rctx->draw_state.stats.draw_triangle_count += count - 2; +} + +static bool draw_object_blend_set(render_context* rctx, draw_object* draw, object_material_shader_lighting_type lighting_type) { + GLenum blend_factor_table[] = { + [OBJECT_MATERIAL_BLEND_ZERO] = GL_ZERO, + [OBJECT_MATERIAL_BLEND_ONE] = GL_ONE, + [OBJECT_MATERIAL_BLEND_SRC_COLOR] = GL_SRC_COLOR, + [OBJECT_MATERIAL_BLEND_INVERSE_SRC_COLOR] = GL_ONE_MINUS_SRC_COLOR, + [OBJECT_MATERIAL_BLEND_SRC_ALPHA] = GL_SRC_ALPHA, + [OBJECT_MATERIAL_BLEND_INVERSE_SRC_ALPHA] = GL_ONE_MINUS_SRC_ALPHA, + [OBJECT_MATERIAL_BLEND_DST_ALPHA] = GL_DST_ALPHA, + [OBJECT_MATERIAL_BLEND_INVERSE_DST_ALPHA] = GL_ONE_MINUS_DST_ALPHA, + [OBJECT_MATERIAL_BLEND_DST_COLOR] = GL_DST_COLOR, + [OBJECT_MATERIAL_BLEND_INVERSE_DST_COLOR] = GL_ONE_MINUS_DST_COLOR, + [OBJECT_MATERIAL_BLEND_ALPHA_SATURATE] = GL_SRC_ALPHA_SATURATE, + [11] = GL_ZERO, + [12] = GL_ZERO, + [13] = GL_ZERO, + [14] = GL_ZERO, + [15] = GL_ZERO, + }; + + object_material_data* material = draw->material; + object_material_blend_flags blend_flags = material->material.blend_flags; + if ((!blend_flags.alpha_texture && !blend_flags.alpha_material) || blend_flags.punch_through) + return false; + + GLenum src_blend_factor = blend_factor_table[blend_flags.src_blend_factor & 0xF]; + GLenum dst_blend_factor = blend_factor_table[blend_flags.dst_blend_factor & 0xF]; + if (draw->chara_color) { + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR]; + vec4 specular; + light_get_specular(chara_color, &specular); + if (specular.w >= 4.0f && light_get_type(chara_color) == LIGHT_PARALLEL + && (src_blend_factor != GL_ONE || dst_blend_factor)) { + int32_t shader_index = rctx->draw_state.shader_index; + if (rctx->draw_state.shader_index == -1) { + shader_index = material->material.shader_index; + if (shader_index == SHADER_FT_BLINN) { + if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT) + shader_index = SHADER_FT_CONSTANT; + if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT) + shader_index = SHADER_FT_LAMBERT; + } + } + + switch (shader_index) { + case SHADER_FT_ITEM: + case SHADER_FT_SKIN: + case SHADER_FT_HAIR: + case SHADER_FT_CLOTH: + case SHADER_FT_TIGHTS: + case SHADER_FT_GLASEYE: + src_blend_factor = GL_SRC_ALPHA; + dst_blend_factor = GL_ONE_MINUS_SRC_ALPHA; + break; + } + } + } + gl_state_set_blend_func(src_blend_factor, dst_blend_factor); + return dst_blend_factor == GL_ONE; +} + +static void draw_object_chara_color_fog_set(render_context* rctx, draw_object* draw, bool disable_fog) { + uniform_value[U_CHARA_COLOR] = 0; + if (draw->chara_color) { + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_data* chara_color = &set->lights[LIGHT_CHARA_COLOR]; + vec4 specular; + light_get_specular(chara_color, &specular); + if (specular.w > 0.0f && light_get_type(chara_color) == LIGHT_PARALLEL) + uniform_value[U_CHARA_COLOR] = 1; + } + + object_material_blend_flags blend_flags = draw->material->material.blend_flags; + if (!blend_flags.no_fog && !disable_fog) { + if (blend_flags.has_fog_height) + uniform_value[U_FOG_HEIGHT] = 2 + blend_flags.fog_height; + else + uniform_value[U_FOG_HEIGHT] = 1; + uniform_value[U_FOG] = rctx->draw_state.fog_height ? 2 : 1; + } +} + +static void draw_object_material_reset_default(object_material_data* mat_data) { + if (mat_data) { + gl_state_enable_cull_face(); + object_material_blend_flags blend_flags = mat_data->material.blend_flags; + if ((blend_flags.alpha_texture || blend_flags.alpha_material) && !blend_flags.punch_through) + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + uniform_value_reset(); +} + +static void draw_object_material_reset_reflect() { + gl_state_active_bind_texture_2d(0, 0); + gl_state_enable_cull_face(); + uniform_value_reset(); +} + +static void draw_object_material_set_default(render_context* rctx, draw_object* draw, bool use_shader) { + GLuint* textures = draw->textures; + object_material_data* material = draw->material; + object_material_shader_lighting_type lighting_type = + object_material_shader_get_lighting_type(&material->material.shader_flags); + bool disable_fog = draw_object_blend_set(rctx, draw, lighting_type); + draw_object_material_set_uniform(rctx, material, false); + if (!rctx->draw_state.light) + uniform_value[U_LIGHT_0] = 0; + else if (draw->self_shadow) + uniform_value[U_LIGHT_0] = draw->self_shadow ? 1 : 1; + else + uniform_value[U_LIGHT_0] = draw->sub_mesh->flags & OBJECT_SUB_MESH_RECIEVE_SHADOW ? 1 : 0; + uniform_value[U_SHADOW] = 0; + uniform_value[U_SELF_SHADOW] = rctx->draw_state.self_shadow ? 1 : 0; + + object_material_texture* mat_tex = material->material.textures; + uniform_value[U_SHADOW] = draw->shadow > SHADOW_CHARA; + for (int32_t i = 0, j = 0; i < 8; i++, mat_tex++) { + if (mat_tex->texture_id == -1) + continue; + + GLuint tex_id = -1; + uint32_t texture_id = mat_tex->texture_id; + for (int32_t j = 0; j < draw->texture_pattern_count; j++) + if (draw->texture_pattern_array[j].src == texture_id) { + texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst); + if (tex) + tex_id = tex->texture; + break; + } + + if (tex_id == -1) + tex_id = textures[mat_tex->texture_index]; + + if (tex_id == -1) + continue; + + int32_t tex_index = object_material_texture_type_get_texture_index(mat_tex->texture_flags.type, j); + if (tex_index < 0) + continue; + + object_material_texture_type tex_type = mat_tex->texture_flags.type; + if (tex_type == OBJECT_MATERIAL_TEXTURE_COLOR) + j++; + + if (mat_tex->sampler_flags.flag_29) { + switch (tex_type) { + case OBJECT_MATERIAL_TEXTURE_NORMAL: + uniform_value[U_NORMAL] = 0; + break; + case OBJECT_MATERIAL_TEXTURE_SPECULAR: + uniform_value[U_SPECULAR] = 0; + break; + case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY: + uniform_value[U_TRANSLUCENCY] = 0; + break; + case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY: + uniform_value[U_TRANSPARENCY] = 0; + break; + } + continue; + } + + if (tex_type == OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_CUBE) + gl_state_active_bind_texture_cube_map(tex_index, tex_id); + else { + gl_state_active_bind_texture_2d(tex_index, tex_id); + + GLenum wrap_s = 0; + if (mat_tex->sampler_flags.mirror_u) + wrap_s = GL_MIRRORED_REPEAT; + else if (mat_tex->sampler_flags.repeat_u) + wrap_s = GL_REPEAT; + + GLenum wrap_t = 0; + if (mat_tex->sampler_flags.mirror_v) + wrap_t = GL_MIRRORED_REPEAT; + else if (mat_tex->sampler_flags.repeat_v) + wrap_t = GL_REPEAT; + + if (wrap_s) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s); + if (wrap_t) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t); + } + + if (material->material.shader_index == SHADER_FT_SKY) { + uniform_name uni_type = U_TEX_0_TYPE; + if (tex_index == 1) + uni_type = U_TEX_1_TYPE; + + texture* tex = texture_storage_get_texture(mat_tex->texture_id); + if (!tex) + uniform_value[uni_type] = 1; + else if (tex->internal_format == GL_COMPRESSED_RED_RGTC1_EXT) + uniform_value[uni_type] = 3; + else if (tex->internal_format == GL_COMPRESSED_RED_GREEN_RGTC2_EXT) + uniform_value[uni_type] = 2; + else + uniform_value[uni_type] = 1; + } + + int32_t texture_blend = object_material_texture_get_blend(mat_tex); + if (tex_index == 0 || tex_index == 1) + uniform_value[U_TEXTURE_BLEND] = texture_blend; + } + + if (material->material.blend_flags.double_sided) { + gl_state_disable_cull_face(); + if (!material->material.blend_flags.normal_direction_light) + uniform_value[U0B] = 1; + } + + vec4 ambient; + *(vec3*)&ambient = *(vec3*)&material->material.ambient; + if (rctx->draw_pass.sss_data.enable) + ambient.w = material->material.ambient.w; + else + ambient.w = 1.0f; + + vec4 diffuse; + vec4 emission; + vec4u_to_vec4(material->material.diffuse, diffuse); + vec4u_to_vec4(material->material.emission, emission); + draw_object_chara_color_fog_set(rctx, draw, disable_fog); + shader_state_material_set_ambient_ptr(&shaders_ft, false, &ambient); + shader_state_material_set_diffuse_ptr(&shaders_ft, false, &diffuse); + shader_state_material_set_emission_ptr(&shaders_ft, false, &emission); + + float_t line_light; + if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_PHONG) { + vec4 specular; + vec4u_to_vec4(material->material.specular, specular); + shader_state_material_set_specular_ptr(&shaders_ft, false, &specular); + + float_t luma; + vec3_dot(*(vec3*)&specular, ((vec3) {0.30f, 0.59f, 0.11f }), luma); + if (luma >= 0.0099999998f || draw->texture_color_coeff.w >= 0.1f) + uniform_value[U_SPECULAR_IBL] = 1; + else + uniform_value[U_SPECULAR_IBL] = 0; + + if (!material->material.shader_flags.fresnel) + uniform_value[U_TRANSLUCENCY] = 0; + + line_light = (float_t)material->material.shader_flags.line_light * (float_t)(1.0 / 9.0); + } + else + line_light = 0.0; + + if (!use_shader) + shader_set(&shaders_ft, SHADER_FT_SIMPLE); + else if (rctx->draw_state.shader_index != -1) + shader_set(&shaders_ft, rctx->draw_state.shader_index); + else if (material->material.shader_index != -1) { + if (material->material.shader_index != SHADER_FT_BLINN) + shader_set(&shaders_ft, material->material.shader_index); + else if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT) + shader_set(&shaders_ft, SHADER_FT_LAMBERT); + else if (lighting_type == OBJECT_MATERIAL_SHADER_LIGHTING_PHONG) + shader_set(&shaders_ft, SHADER_FT_BLINN); + else + shader_set(&shaders_ft, SHADER_FT_CONSTANT); + } + else + shader_set(&shaders_ft, SHADER_FT_CONSTANT); + + if (lighting_type != OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT) { + float_t shininess; + if (material->material.shader_index == SHADER_FT_EYEBALL) + shininess = 10.0f; + else { + shininess = (material->material.shininess - 16.0f) * (float_t)(1.0 / 112.0); + shininess = max(shininess, 0.0f); + } + shader_state_material_set_shininess(&shaders_ft, false, shininess, 0.0f, 0.0f, 1.0f); + + float_t fresnel = (float_t)material->material.shader_flags.fresnel; + if (fresnel > 9.0) + fresnel = 9.0; + else if (fresnel == 0.0f) + fresnel = rctx->draw_state.fresnel; + fresnel = (fresnel - 1.0f) * (0.12f * 0.82f); + + shader_local_vert_set(&shaders_ft, 0, fresnel, 0.18f, line_light, 0.0f); + shader_local_frag_set(&shaders_ft, 9, fresnel, 0.18f, line_light, 0.0f); + + shininess = max(material->material.shininess, 1.0f); + shader_local_vert_set(&shaders_ft, 1, shininess, 0.0f, 0.0f, 0.0f); + shader_local_frag_set(&shaders_ft, 3, shininess, 0.0f, 0.0f, 0.0f); + + switch (material->material.shader_index) { + case SHADER_FT_SKIN: { + vec4 texture_color_coeff; + vec4 texture_color_offset; + vec4 texture_specular_coeff; + vec4 texture_specular_offset; + vec4u_to_vec4(draw->texture_color_coeff, texture_color_coeff); + vec4u_to_vec4(draw->texture_color_offset, texture_color_offset); + vec4u_to_vec4(draw->texture_specular_coeff, texture_specular_coeff); + vec4u_to_vec4(draw->texture_specular_offset, texture_specular_offset); + + texture_color_coeff.w *= 0.015f; + texture_specular_coeff.w *= 0.015f; + + shader_local_frag_set_ptr(&shaders_ft, 5, &texture_color_coeff); + shader_local_frag_set_ptr(&shaders_ft, 6, &texture_color_offset); + shader_local_frag_set_ptr(&shaders_ft, 7, &texture_specular_coeff); + shader_local_frag_set_ptr(&shaders_ft, 8, &texture_specular_offset); + } break; + case SHADER_FT_HAIR: + case SHADER_FT_CLOTH: + case SHADER_FT_TIGHTS: + shader_local_frag_set(&shaders_ft, 5, 1.0f - draw->texture_color_coeff.w * 0.4f, + 0.0f, 0.0f, draw->texture_color_coeff.w * 0.02f); + break; + } + } + + draw_object_material_set_parameter(rctx, material); +} + +static void draw_object_material_set_parameter(render_context* rctx, object_material_data* mat_data) { + float_t bump_depth; + float_t intensity; + float_t reflect_uv_scale; + float_t refract_uv_scale; + float_t inv_bump_depth; + if (rctx->draw_state.use_global_material) { + bump_depth = rctx->draw_state.bump_depth; + intensity = rctx->draw_state.intensity; + reflect_uv_scale = rctx->draw_state.reflect_uv_scale; + refract_uv_scale = rctx->draw_state.refract_uv_scale; + inv_bump_depth = (1.0f - rctx->draw_state.bump_depth) * 64.0f + 1.0f; + + vec4 specular; + vec4_to_vec4u(mat_data->material.specular, specular); + specular.w = rctx->draw_state.specular_alpha; + shader_state_material_set_specular_ptr(&shaders_ft, false, &specular); + } + else { + bump_depth = mat_data->material.bump_depth; + reflect_uv_scale = 0.1f; + intensity = mat_data->material.intensity; + refract_uv_scale = 0.1f; + inv_bump_depth = (1.0f - bump_depth) * 256.0f + 1.0f; + } + + intensity = max(intensity, 1.0f); + + shader_local_vert_set(&shaders_ft, 2, inv_bump_depth, bump_depth, 0.0f, 0.0f); + shader_local_frag_set(&shaders_ft, 0, inv_bump_depth, bump_depth, 0.0f, 0.0f); + + shader_local_frag_set(&shaders_ft, 1, intensity, intensity, intensity * 25.5f, 1.0f); + shader_local_frag_set(&shaders_ft, 2, + reflect_uv_scale, reflect_uv_scale, refract_uv_scale, refract_uv_scale); + + vec4 specular; + shader_env_vert_get_ptr(&shaders_ft, 17, &specular); + vec3_mult(*(vec3*)&specular, *(vec3*)&mat_data->material.specular, *(vec3*)&specular); + shader_env_vert_set_ptr(&shaders_ft, 18, &specular); +} + +static void draw_object_material_set_reflect(render_context* rctx, draw_object* draw) { + object_material_data* material = draw->material; + GLuint* textures = draw->textures; + if (material->material.blend_flags.double_sided) + gl_state_disable_cull_face(); + + object_material_texture* mat_tex = material->material.textures; + for (int32_t i = 0; i < 1; i++, mat_tex++) { + uint32_t texture_id = mat_tex->texture_id; + if (mat_tex->texture_id == -1) + break; + + GLuint tex_id = -1; + for (int32_t j = 0; j < draw->texture_pattern_count; j++) + if (draw->texture_pattern_array[j].src == texture_id) { + texture* tex = texture_storage_get_texture(draw->texture_pattern_array[j].dst); + if (tex) + tex_id = tex->texture; + break; + } + + if (tex_id == -1) + tex_id = textures[mat_tex->texture_index]; + + if (tex_id == -1) + tex_id = 0; + + gl_state_active_bind_texture_2d(i, tex_id); + + GLenum wrap_s = 0; + if (mat_tex->sampler_flags.mirror_u) + wrap_s = GL_MIRRORED_REPEAT; + else if (mat_tex->sampler_flags.repeat_u) + wrap_s = GL_REPEAT; + + GLenum wrap_t = 0; + if (mat_tex->sampler_flags.mirror_v) + wrap_t = GL_MIRRORED_REPEAT; + else if (mat_tex->sampler_flags.repeat_v) + wrap_t = GL_REPEAT; + + if (wrap_s) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s); + if (wrap_t) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t); + } + + vec4 ambient; + vec4 diffuse; + vec4 emission; + vec4 specular; + if (material->material.shader_index == -1) { + ambient = vec4_identity; + vec4u_to_vec4(material->material.diffuse, diffuse); + emission = vec4_identity; + vec4u_to_vec4(material->material.specular, specular); + } + else { + vec4u_to_vec4(material->material.ambient, ambient); + vec4u_to_vec4(material->material.diffuse, diffuse); + vec4u_to_vec4(material->material.emission, emission); + vec4u_to_vec4(material->material.specular, specular); + } + + draw_object_material_set_uniform(rctx, material, true); + shader_set(&shaders_ft, rctx->draw_state.shader_index); + shader_state_material_set_ambient_ptr(&shaders_ft, false, &ambient); + shader_state_material_set_diffuse_ptr(&shaders_ft, false, &diffuse); + shader_state_material_set_emission_ptr(&shaders_ft, false, &emission); + shader_state_material_set_specular_ptr(&shaders_ft, false, &specular); + draw_object_material_set_parameter(rctx, draw->material); +} + +static void draw_object_material_set_uniform(render_context* rctx, object_material_data* mat_data, bool disable_color_l) { + object_material_flags flags = mat_data->material.flags; + object_material_shader_flags shader_flags = mat_data->material.shader_flags; + + if (disable_color_l) { + if (flags & OBJECT_MATERIAL_COLOR) + flags &= ~OBJECT_MATERIAL_COLOR_L1; + flags &= ~OBJECT_MATERIAL_COLOR_L2; + } + + int32_t v4 = 0; + if (flags & OBJECT_MATERIAL_COLOR) { + if (~flags & OBJECT_MATERIAL_COLOR_L2) + if (flags & OBJECT_MATERIAL_COLOR_L1) { + uniform_value[U_TEXTURE_COUNT] = 2; + v4 = 3; + } + else { + uniform_value[U_TEXTURE_COUNT] = 1; + v4 = 1; + } + } + else if (flags & OBJECT_MATERIAL_COLOR_L1 && ~flags & OBJECT_MATERIAL_COLOR_L2) { + uniform_value[U_TEXTURE_COUNT] = 1; + v4 = 1; + } + else + uniform_value[U_TEXTURE_COUNT] = 0; + + if (flags & OBJECT_MATERIAL_NORMAL) + uniform_value[U_NORMAL] = 1; + if (flags & OBJECT_MATERIAL_SPECULAR) + uniform_value[U_SPECULAR] = 1; + if (flags & OBJECT_MATERIAL_TRANSPARENCY) { + uniform_value[U_TRANSPARENCY] = 1; + v4 |= 2; + } + if (flags & OBJECT_MATERIAL_TRANSLUCENCY) { + uniform_value[U_TRANSLUCENCY] = 1; + v4 |= 2; + } + if (flags & OBJECT_MATERIAL_OVERRIDE_IBL) + uniform_value[U_ENV_MAP] = 1; + + if ((shader_flags.aniso_direction & 0x03) != OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL) + uniform_value[U_ANISO] = shader_flags.aniso_direction & 0x03; + + if (v4 == 1) + uniform_value[U45] = 0; + else if (v4 == 2 || v4 == 3) + uniform_value[U45] = 1; +} + +static void draw_object_vertex_attrib_reset_default(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + if (mesh->compressed) { + draw_object_vertex_attrib_reset_default_compressed(draw); + return; + } + + for (int32_t i = 0; i < 16; i++) { + if (draw->vertex_attrib_array[i]) + glDisableVertexAttribArray(i); + draw->vertex_attrib_array[i] = false; + } + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + uniform_value[U_BONE_MAT] = 0; + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 0; + uniform_value[U_MORPH_COLOR] = 0; + } + uniform_value[U_INSTANCE] = 0; + + gl_state_bind_element_array_buffer(0); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity); + gl_state_active_texture(0); +} + +static void draw_object_vertex_attrib_reset_default_compressed(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + for (int32_t i = 0; i < 16; i++) { + if (draw->vertex_attrib_array[i]) + glDisableVertexAttribArray(i); + draw->vertex_attrib_array[i] = false; + } + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + uniform_value[U_BONE_MAT] = 0; + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 0; + uniform_value[U_MORPH_COLOR] = 0; + } + uniform_value[U_INSTANCE] = 0; + + gl_state_bind_element_array_buffer(0); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity); + gl_state_active_texture(0); +} + +static void draw_object_vertex_attrib_reset_reflect(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + if (mesh->compressed) { + draw_object_vertex_attrib_reset_reflect_compressed(draw); + return; + } + + for (int32_t i = 0; i < 16; i++) { + if (draw->vertex_attrib_array[i]) + glDisableVertexAttribArray(i); + draw->vertex_attrib_array[i] = false; + } + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + uniform_value[U_BONE_MAT] = 0; + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 0; + uniform_value[U_MORPH_COLOR] = 0; + } + + gl_state_bind_element_array_buffer(0); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + gl_state_active_texture(0); +} + +inline static void draw_object_vertex_attrib_reset_reflect_compressed(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + for (int32_t i = 0; i < 16; i++) { + if (draw->vertex_attrib_array[i]) + glDisableVertexAttribArray(i); + draw->vertex_attrib_array[i] = false; + } + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + uniform_value[U_BONE_MAT] = 0; + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 0; + uniform_value[U_MORPH_COLOR] = 0; + } + + gl_state_bind_element_array_buffer(0); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + gl_state_active_texture(0); +} + +static void draw_object_vertex_attrib_set_default(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_sub_mesh* sub_mesh = draw->sub_mesh; + GLsizei vertex_size = (GLsizei)mesh->vertex_size; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + if (mesh->compressed) { + draw_object_vertex_attrib_set_default_compressed(draw); + return; + } + + gl_state_bind_array_buffer(draw->array_buffer); + + size_t offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(2); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(6); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BINORMAL) + offset += 12; + + bool texcoord_mat_set[4] = { false }; + object_material_data* material = draw->material; + for (int32_t i = 0, j = 0, l = 0; i < 4; i++) { + if (material->material.textures[i].texture_id == -1) + continue; + + int32_t texcoord_index = object_material_texture_type_get_texcoord_index( + material->material.textures[i].texture_flags.type, j); + if (texcoord_index < 0) + continue; + + if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + j++; + + if (vertex_flags & (OBJECT_VERTEX_TEXCOORD0 << sub_mesh->texcoord_indices[l])) { + enable_vertex_attrib_array(8 + texcoord_index); + glVertexAttribPointer(8 + texcoord_index, 2, GL_FLOAT, GL_FALSE, + vertex_size, (void*)(offset + 8ULL * sub_mesh->texcoord_indices[l])); + } + l++; + + if (texcoord_mat_set[texcoord_index]) + continue; + + int32_t texture_id = material->material.textures[i].texture_id; + + mat4 mat; + mat4u_to_mat4(&material->material.textures[i].tex_coord_mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat); + if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + for (int32_t k = 0; k < draw->texture_transform_count; k++) + if (draw->texture_transform_array[k].id == texture_id) { + mat4u_to_mat4(&draw->texture_transform_array[k].mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat); + texcoord_mat_set[texcoord_index] = true; + break; + } + } + + for (int32_t i = 0; i < 4; i++) + if (!draw->vertex_attrib_array[8 + i]) + glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 8; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + enable_vertex_attrib_array(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_COLOR1) + offset += 16; + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) { + uniform_value[U_BONE_MAT] = 1; + + enable_vertex_attrib_array(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + + enable_vertex_attrib_array(15); + glVertexAttribPointer(15, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else { + glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (vertex_flags & OBJECT_VERTEX_UNKNOWN) { + enable_vertex_attrib_array(7); + glVertexAttribPointer(7, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(7, 0.0f, 0.0f, 0.0f, 1.0f); + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 1; + + gl_state_bind_array_buffer(draw->morph_array_buffer); + + offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(10); + glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(11); + glVertexAttribPointer(11, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(12); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BINORMAL) + offset += 12; + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(13); + glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) { + enable_vertex_attrib_array(14); + glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 8; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + uniform_value[U_MORPH_COLOR] = 1; + + enable_vertex_attrib_array(5); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_COLOR1) + offset += 16; + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + offset += 32; + + if (vertex_flags & OBJECT_VERTEX_UNKNOWN) + offset += 16; + + shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f); + } + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(draw->element_array_buffer); + + if (draw->instances_count) + uniform_value[U_INSTANCE] = 1; +} + +inline static void draw_object_vertex_attrib_set_default_compressed(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_sub_mesh* sub_mesh = draw->sub_mesh; + GLsizei vertex_size = (GLsizei)mesh->vertex_size; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + gl_state_bind_array_buffer(draw->array_buffer); + + size_t offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(2); + glVertexAttribPointer(2, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(6); + glVertexAttribPointer(6, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(6, 0.0f, 0.0f, 0.0f, 1.0f); + + bool texcoord_mat_set[4] = { false }; + object_material_data* material = draw->material; + for (int32_t i = 0, j = 0, l = 0; i < 4; i++) { + if (material->material.textures[i].texture_id == -1) + continue; + + int32_t texcoord_index = object_material_texture_type_get_texcoord_index( + material->material.textures[i].texture_flags.type, j); + if (texcoord_index < 0) + continue; + + if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + j++; + + if (!strcmp(mesh->name, "body_MZ")) + printf(""); + if (!strcmp(mesh->name, "kao_MZ")) + printf(""); + if (!strcmp(mesh->name, "MZ_ami1") && !strcmp(material->material.name, "test_YZ_frame_2s")) + printf(""); + + if (vertex_flags & (OBJECT_VERTEX_TEXCOORD0 << sub_mesh->texcoord_indices[l])) { + enable_vertex_attrib_array(8 + texcoord_index); + glVertexAttribPointer(8 + texcoord_index, 2, GL_HALF_FLOAT, GL_FALSE, + vertex_size, (void*)(offset + 4ULL * sub_mesh->texcoord_indices[l])); + } + l++; + + if (texcoord_mat_set[texcoord_index]) + continue; + + int32_t texture_id = material->material.textures[i].texture_id; + + mat4 mat; + mat4u_to_mat4(&material->material.textures[i].tex_coord_mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat); + if (material->material.textures[i].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + for (int32_t k = 0; k < draw->texture_transform_count; k++) + if (draw->texture_transform_array[k].id == texture_id) { + mat4u_to_mat4(&draw->texture_transform_array[k].mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, texcoord_index, &mat); + texcoord_mat_set[texcoord_index] = true; + break; + } + } + + for (int32_t i = 0; i < 4; i++) + if (!draw->vertex_attrib_array[8 + i]) + glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 4; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + enable_vertex_attrib_array(3); + glVertexAttribPointer(3, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) { + uniform_value[U_BONE_MAT] = 1; + + enable_vertex_attrib_array(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + + enable_vertex_attrib_array(15); + glVertexAttribPointer(15, 4, GL_UNSIGNED_BYTE, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else { + glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 1; + + gl_state_bind_array_buffer(draw->morph_array_buffer); + + offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(10); + glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(11); + glVertexAttribPointer(11, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(12); + glVertexAttribPointer(12, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(13); + glVertexAttribPointer(13, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else + glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) { + enable_vertex_attrib_array(14); + glVertexAttribPointer(14, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else + glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 4; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + uniform_value[U_MORPH_COLOR] = 1; + + enable_vertex_attrib_array(5); + glVertexAttribPointer(5, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + offset += 12; + + shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f); + } + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(draw->element_array_buffer); + + if (draw->instances_count) + uniform_value[U_INSTANCE] = 1; +} + +static void draw_object_vertex_attrib_set_reflect(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_sub_mesh* sub_mesh = draw->sub_mesh; + GLsizei vertex_size = (GLsizei)mesh->vertex_size; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + if (mesh->compressed) { + draw_object_vertex_attrib_set_reflect_compressed(draw); + return; + } + + gl_state_bind_array_buffer(draw->array_buffer); + + size_t offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(2); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) + offset += 16; + + if (vertex_flags & OBJECT_VERTEX_BINORMAL) + offset += 12; + + object_material_data* material = draw->material; + if (material->material.textures[0].texture_id != -1) { + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, + vertex_size, (void*)(offset + 8ULL * sub_mesh->texcoord_indices[0])); + } + else + glVertexAttrib4f(8, 0.0f, 0.0f, 0.0f, 1.0f); + + int32_t texture_id = material->material.textures[0].texture_id; + + mat4 mat; + mat4u_to_mat4(&material->material.textures[0].tex_coord_mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, 0, &mat); + if (material->material.textures[0].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + for (int32_t j = 0; j < draw->texture_transform_count; j++) + if (draw->texture_transform_array[j].id == texture_id) { + mat4u_to_mat4(&draw->texture_transform_array[j].mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, 0, &mat); + break; + } + } + + for (int32_t i = 1; i < 4; i++) + glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 8; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + enable_vertex_attrib_array(3); + glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_COLOR1) + offset += 16; + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) { + uniform_value[U_BONE_MAT] = 1; + + enable_vertex_attrib_array(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + + enable_vertex_attrib_array(15); + glVertexAttribPointer(15, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else { + glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (vertex_flags & OBJECT_VERTEX_UNKNOWN) + offset += 16; + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 1; + + gl_state_bind_array_buffer(draw->morph_array_buffer); + + offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(10); + glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(11); + glVertexAttribPointer(11, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(12); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BINORMAL) + offset += 12; + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(13); + glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) { + enable_vertex_attrib_array(14); + glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 8; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 8; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + uniform_value[U_MORPH_COLOR] = 1; + + enable_vertex_attrib_array(5); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 16; + } + else + glVertexAttrib4f(5, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_COLOR1) + offset += 16; + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + offset += 32; + + if (vertex_flags & OBJECT_VERTEX_UNKNOWN) + offset += 16; + + shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f); + } + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(draw->element_array_buffer); +} + +inline static void draw_object_vertex_attrib_set_reflect_compressed(draw_object* draw) { + object_mesh* mesh = draw->mesh; + object_sub_mesh* sub_mesh = draw->sub_mesh; + GLsizei vertex_size = (GLsizei)mesh->vertex_size; + object_vertex_flags vertex_flags = mesh->vertex_flags; + + gl_state_bind_array_buffer(draw->array_buffer); + + size_t offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(0, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(2); + glVertexAttribPointer(2, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(2, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) + offset += 8; + + object_material_data* material = draw->material; + if (material->material.textures[0].texture_id != -1) { + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(8); + glVertexAttribPointer(8, 2, GL_HALF_FLOAT, GL_FALSE, + vertex_size, (void*)(offset + 4ULL * sub_mesh->texcoord_indices[0])); + } + else + glVertexAttrib4f(8, 0.0f, 0.0f, 0.0f, 1.0f); + + int32_t texture_id = material->material.textures[0].texture_id; + + mat4 mat; + mat4u_to_mat4(&material->material.textures[0].tex_coord_mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, 0, &mat); + if (material->material.textures[0].texture_flags.type == OBJECT_MATERIAL_TEXTURE_COLOR) + for (int32_t j = 0; j < draw->texture_transform_count; j++) + if (draw->texture_transform_array[j].id == texture_id) { + mat4u_to_mat4(&draw->texture_transform_array[j].mat, &mat); + shader_state_matrix_set_texture(&shaders_ft, 0, &mat); + break; + } + } + + for (int32_t i = 1; i < 4; i++) + glVertexAttrib4f(8 + i, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 4; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + enable_vertex_attrib_array(3); + glVertexAttribPointer(3, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) { + uniform_value[U_BONE_MAT] = 1; + + enable_vertex_attrib_array(1); + glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + + enable_vertex_attrib_array(15); + glVertexAttribPointer(15, 4, GL_UNSIGNED_BYTE, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else { + glVertexAttrib4f(1, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(15, 0.0f, 0.0f, 0.0f, 1.0f); + } + + if (draw->morph_array_buffer) { + uniform_value[U_MORPH] = 1; + + gl_state_bind_array_buffer(draw->morph_array_buffer); + + offset = 0; + if (vertex_flags & OBJECT_VERTEX_POSITION) { + enable_vertex_attrib_array(10); + glVertexAttribPointer(10, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 12; + } + else + glVertexAttrib4f(10, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_NORMAL) { + enable_vertex_attrib_array(11); + glVertexAttribPointer(11, 3, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(11, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TANGENT) { + enable_vertex_attrib_array(12); + glVertexAttribPointer(12, 4, GL_SHORT, GL_TRUE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(12, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD0) { + enable_vertex_attrib_array(13); + glVertexAttribPointer(13, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else + glVertexAttrib4f(13, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD1) { + enable_vertex_attrib_array(14); + glVertexAttribPointer(14, 2, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 4; + } + else + glVertexAttrib4f(14, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_TEXCOORD2) + offset += 4; + if (vertex_flags & OBJECT_VERTEX_TEXCOORD3) + offset += 4; + + if (vertex_flags & OBJECT_VERTEX_COLOR0) { + uniform_value[U_MORPH_COLOR] = 1; + + enable_vertex_attrib_array(5); + glVertexAttribPointer(5, 4, GL_HALF_FLOAT, GL_FALSE, vertex_size, (void*)offset); + offset += 8; + } + else + glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 1.0f); + + if (vertex_flags & OBJECT_VERTEX_BONE_DATA) + offset += 12; + + shader_env_vert_set(&shaders_ft, 13, draw->morph_value, 1.0f - draw->morph_value, 0.0f, 0.0f); + } + gl_state_bind_array_buffer(0); + + gl_state_bind_element_array_buffer(draw->element_array_buffer); +} diff --git a/src/CRE/draw_object.h b/src/CRE/draw_object.h new file mode 100644 index 00000000..0292986f --- /dev/null +++ b/src/CRE/draw_object.h @@ -0,0 +1,35 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/vector.h" +#include "object.h" +#include "render_context.h" + +typedef struct texture_data_struct { + int32_t field_0; + vec3 texture_color_coeff; + vec3 texture_color_offset; + vec3 texture_specular_coeff; + vec3 texture_specular_offset; +} texture_data_struct; + +extern void draw_object_draw(render_context* rctx, draw_object* draw, mat4* model, + void(*draw_object_func)(render_context* rctx, draw_object* draw), int32_t show_vector); +extern void draw_object_draw_default(render_context* rctx, draw_object* draw); +extern void draw_object_draw_sss(render_context* rctx, draw_object* draw); +extern void draw_object_draw_reflect(render_context* rctx, draw_object* draw); +extern void draw_object_draw_reflect_type_2(render_context* rctx, draw_object* draw); +extern void draw_object_draw_shadow(render_context* rctx, draw_object* draw); +extern void draw_object_draw_translucent(render_context* rctx, draw_object* draw); +extern void draw_object_model_mat_load(render_context* rctx, mat4* mat); +extern void model_mat_face_camera_position(mat4* view, mat4* src, mat4* dst); +extern void model_mat_face_camera_view(mat4* view, mat4* src, mat4* dst); +extern void object_sub_mesh_draw(render_context* rctx, object_primitive_type primitive_type, + uint32_t count, uint16_t start, uint16_t end, object_index_format index_format, size_t indices); diff --git a/src/CRE/draw_pass.c b/src/CRE/draw_pass.c index 5af67f94..648bea3e 100644 --- a/src/CRE/draw_pass.c +++ b/src/CRE/draw_pass.c @@ -4,35 +4,17 @@ */ #include "draw_pass.h" +#include "Glitter/glitter.h" +#include "Glitter/particle_manager.h" +#include "light_param/fog.h" +#include "light_param/light.h" +#include "gl_state.h" #include "post_process.h" #include "render_texture.h" -#include "texture.h" -#include "time.h" +#include "shader_ft.h" +#include "shader_glsl.h" #include "static_var.h" - -typedef enum reflect_blur_filter_mode { - REFLECT_BLUR_FILTER_4 = 0x00, - REFLECT_BLUR_FILTER_9 = 0x01, - REFLECT_BLUR_FILTER_16 = 0x02, - REFLECT_BLUR_FILTER_32 = 0x03, -} reflect_blur_filter_mode; - -typedef enum draw_pass_type { - DRAW_PASS_SHADOW = 0x00, - DRAW_PASS_SSS_SKIN = 0x01, - DRAW_PASS_TYPE_2 = 0x02, - DRAW_PASS_REFLECT = 0x03, - DRAW_PASS_REFRACT = 0x04, - DRAW_PASS_PREPROCESS = 0x05, - DRAW_PASS_TYPE_6 = 0x06, - DRAW_PASS_TYPE_7 = 0x07, - DRAW_PASS_3D = 0x08, - DRAW_PASS_SHOW_VECTOR = 0x09, - DRAW_PASS_POST_PROCESS = 0x0A, - DRAW_PASS_SPRITE = 0x0B, - DRAW_PASS_TYPE_12 = 0x0C, - DRAW_PASS_MAX = 0x0D, -} draw_pass_type; +#include "texture.h" typedef struct draw_preprocess { int32_t field_0; @@ -53,173 +35,1004 @@ typedef struct list_draw_preprocess { size_t size; } list_draw_preprocess; +typedef struct texture_param { + GLint width; + GLint height; +} texture_param; -typedef struct draw_pass { - bool enable[DRAW_PASS_MAX]; - //shadow* shadow_ptr; - bool reflect; - bool refract; - int32_t reflect_blur_num; - reflect_blur_filter_mode reflect_blur_filter; - //post_process_struct* post_process; - char wait_for_gpu; - double_t cpu_time[13]; - double_t gpu_time[13]; - time_struct time; - char shadow; - bool opaque_z_sort; - bool alpha_z_sort; - bool draw_pass_3d[3]; - char field_11F; - char field_120; - char field_121; - int32_t reflect_type; - char field_128; - int tex_index[11]; - render_texture field_158[8]; - GLsizei width; - GLsizei height; - GLuint field_2E0; - GLuint field_2E4; - char field_2E8; - char field_2E9; - int field_2EC; - float_t field_2F0; - float_t field_2F4; - char field_2F8; - //list_draw_preprocess preprocess; - texture* field_310; - int field_318; - bool field_31C; - bool field_31D; - bool reflect_object; - bool field_31F; - bool field_320; - bool field_321; -} draw_pass; - -draw_pass draw_pass_data; - +static void blur_filter_apply(GLuint tex_0, GLuint tex_1, blur_filter_mode filter); static void draw_pass_begin(draw_pass* a1); +static void draw_pass_shadow(render_context* rctx, draw_pass* a1); +static void draw_pass_shadow_filter(render_texture* a1, render_texture* a2, + render_texture* a3, float_t sigma, float_t far_texel_offset, bool enable_lit_proj); +static bool draw_pass_shadow_litproj(render_context* rctx, light_proj* litproj); +static void draw_pass_sss(render_context* rctx, draw_pass* a1); +static void draw_pass_sss_contour(render_context* rctx, post_process_struct* pp); +static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1); +static void draw_pass_reflect(render_context* rctx, draw_pass* a1); +static void draw_pass_refract(render_context* rctx, draw_pass* a1); +static void draw_pass_preprocess(render_context* rctx, draw_pass* a1); +static void draw_pass_3d(render_context* rctx, draw_pass* a1); +static int32_t draw_pass_3d_get_translucent_count(render_context* rctx); +static void draw_pass_3d_shadow_reset(render_context* rctx); +static void draw_pass_3d_shadow_set(shadow* shad, render_context* rctx); +static void draw_pass_show_vector(render_context* rctx, draw_pass* a1); +static void draw_pass_post_process(render_context* rctx, draw_pass* a1); +static void draw_pass_sprite(render_context* rctx, draw_pass* a1); static void draw_pass_end(draw_pass* pass, draw_pass_type type); +static void draw_pass_3d_grid(render_context* rctx); +static void draw_pass_set_camera(camera* cam); +static void texture_params_get(GLuint tex_0, texture_param* tex_0_param, + GLuint tex_1, texture_param* tex_1_param, GLuint tex_2, texture_param* tex_2_param); +static void texture_params_restore(texture_param* tex_0_param, + texture_param* tex_1_param, texture_param* tex_2_param); -/*void draw_pass_init() -{ - memset(draw_pass_data.cpu_time, 0, sizeof(draw_pass_data.cpu_time)); - memset(draw_pass_data.gpu_time, 0, sizeof(draw_pass_data.gpu_time)); - time_struct_init(&draw_pass_data.time); - `eh vector constructor iterator'( - draw_pass_data.field_158, - 48i64, - 8, - (void(__fastcall*)(void*))render_texture_init); - draw_pass_data.field_300 = 0i64; - draw_pass_data.field_308 = 0i64; - draw_pass_data.field_300 = sub_140500860(&draw_pass_data.field_300, 0i64, 0i64); - atexit(draw_pass_free); -}*/ +extern bool draw_grid_3d; +extern shader_glsl grid_shader; +extern GLuint grid_vbo; +extern const size_t grid_vertex_count; +extern vec3 back3d_color; -void draw_pass_main() { - for (draw_pass_type i = DRAW_PASS_SHADOW; i <= DRAW_PASS_TYPE_12; i++) { - draw_pass_data.cpu_time[i] = 0.0; - draw_pass_data.gpu_time[i] = 0.0; - if (!draw_pass_data.enable[i]) { +void draw_pass_main(render_context* rctx) { + static const int32_t ibl_texture_index[] = { + 9, 10, 11, 12, 13 + }; + + for (int32_t i = 0; i < 5; i++) + gl_state_active_bind_texture_cube_map(ibl_texture_index[i], rctx->ibl_tex[i]); + + camera* cam = rctx->camera; + + GPM_VAL->cam_projection = cam->projection; + GPM_VAL->cam_view = cam->view; + GPM_VAL->cam_inv_view = cam->inv_view; + GPM_VAL->cam_inv_view_mat3 = cam->inv_view_mat3; + GPM_VAL->cam_view_point = cam->view_point; + GPM_VAL->cam_rotation_y = cam->rotation.y; + GPM_VAL->rctx = rctx; + + glitter_particle_manager_calc_draw(GPM_VAL); + shader_env_frag_set(&shaders_ft, 0, + 1.0f / (float_t)rctx->post_process.render_width, + 1.0f / (float_t)rctx->post_process.render_height, + (float_t)rctx->post_process.render_width, + (float_t)rctx->post_process.render_height); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + for (draw_pass_type i = DRAW_PASS_SHADOW; i < DRAW_PASS_MAX; i++) { + rctx->draw_pass.cpu_time[i] = 0.0; + rctx->draw_pass.gpu_time[i] = 0.0; + if (!rctx->draw_pass.enable[i]) { glGetError(); continue; } - draw_pass_begin(&draw_pass_data); + draw_pass_begin(&rctx->draw_pass); switch (i) { case DRAW_PASS_SHADOW: - //draw_pass_shadow(&draw_pass_data); + draw_pass_shadow(rctx, &rctx->draw_pass); break; - case DRAW_PASS_SSS_SKIN: - //draw_pass_sss_skin(&draw_pass_data); + case DRAW_PASS_SSS: + draw_pass_sss(rctx, &rctx->draw_pass); break; case DRAW_PASS_REFLECT: - //draw_pass_reflect(&draw_pass_data); + draw_pass_reflect(rctx, &rctx->draw_pass); break; case DRAW_PASS_REFRACT: - //draw_pass_refract(&draw_pass_data); + draw_pass_refract(rctx, &rctx->draw_pass); break; case DRAW_PASS_PREPROCESS: - //draw_pass_preprocess(); - break; - case DRAW_PASS_TYPE_6: - //sub_140501470(&draw_pass_data); + draw_pass_preprocess(rctx, &rctx->draw_pass); break; + case DRAW_PASS_TYPE_6: { + render_texture_bind(&rctx->post_process.render_texture, 0); + vec4 color; + *(vec3*)&color = back3d_color; + color.w = 1.0f; + glClearBufferfv(GL_COLOR, 0, (GLfloat*)&color); + //sub_140501470(rctx, &rctx->draw_pass); + } break; case DRAW_PASS_TYPE_7: - //sub_140501600(&draw_pass_data); + //sub_140501600(rctx, &rctx->draw_pass); break; case DRAW_PASS_3D: - //draw_pass_3d(&draw_pass_data); + draw_pass_3d(rctx, &rctx->draw_pass); break; case DRAW_PASS_SHOW_VECTOR: - //draw_pass_show_vector(&draw_pass_data); + draw_pass_show_vector(rctx, &rctx->draw_pass); break; case DRAW_PASS_POST_PROCESS: - //draw_pass_post_process(&draw_pass_data); + draw_pass_post_process(rctx, &rctx->draw_pass); break; case DRAW_PASS_SPRITE: - //draw_pass_sprite(&draw_pass_data); + draw_pass_sprite(rctx, &rctx->draw_pass); break; } - draw_pass_end(&draw_pass_data, i); + draw_pass_end(&rctx->draw_pass, i); glGetError(); } + gl_state_bind_vertex_array(0); } -/*void draw_pass_free() -{ - list_struc_125* v0; // rdi - list_struc_125* v1; // rsi - list_struc_125* v2; // rbx - char v3; // [rsp+40h] [rbp+8h] BYREF - char v4; // [rsp+48h] [rbp+10h] BYREF - char v5; // [rsp+50h] [rbp+18h] BYREF - char v6; // [rsp+58h] [rbp+20h] BYREF - - v0 = draw_pass_data.field_300->next; - draw_pass_data.field_300->next = draw_pass_data.field_300; - draw_pass_data.field_300->prev = draw_pass_data.field_300; - v1 = draw_pass_data.field_300; - draw_pass_data.field_308 = 0i64; - if (v0 != draw_pass_data.field_300) - { - do - { - v2 = v0->next; - sub_1405005A0(&v3); - nullsub_151(&v3, v0); - sub_1405005A0(&v4); - nullsub_151(&v4, &v0->prev); - sub_1405005A0(&v5); - nullsub_152(&v5, &v0->value); - sub_1405005A0(&v6); - j_free_2(v0); - v1 = draw_pass_data.field_300; - v0 = v2; - } while (v2 != draw_pass_data.field_300); - } - sub_1405005A0(&v3); - nullsub_151(&v3, v1); - sub_1405005A0(&v3); - nullsub_151(&v3, &v1->prev); - sub_1405005A0(&v3); - j_free_2(v1); - `eh vector destructor iterator'( - draw_pass_data.field_158, - 48i64, - 8, - (void(__fastcall*)(void*))render_texture_free_0); -}*/ - inline static void draw_pass_begin(draw_pass* a1) { if (a1->wait_for_gpu) glFinish(); time_struct_get_timestamp(&a1->time); } +static void draw_pass_shadow(render_context* rctx, draw_pass* a1) { + rctx->view_mat = rctx->camera->view; + if (light_proj_set(rctx->litproj, rctx)) { + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_OPAQUE, 0, 0, true, -1); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSPARENT, 0, 0, true, -1); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT, 0, 0, true, -1); + + rctx->draw_state.shader_index = -1; + uniform_value[U0A] = 0; + draw_pass_shadow_filter(&rctx->litproj->shadow_texture[0], + &rctx->litproj->shadow_texture[1], 0, 1.5f, 0.0099999998f, true); + + if (draw_pass_shadow_litproj(rctx, rctx->litproj)) { + draw_pass_set_camera(rctx->camera); + for (light_set_id i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_data_set(&rctx->light_set_data[i], &rctx->face, i); + gl_state_bind_vertex_array(rctx->vao); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_OPAQUE, 0, 0, true, -1); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSPARENT, 0, 0, true, -1); + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT, 1); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl_state_enable_blend(); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT, 0, 0, true, -1); + gl_state_disable_blend(); + rctx->draw_state.shader_index = -1; + gl_state_bind_framebuffer(0); + } + } + + bool v3 = false; + int32_t v10[2]; + for (int32_t i = 0; i < 2; i++) { + v10[i] = draw_task_get_count(rctx, DRAW_OBJECT_SHADOW_CHARA + i); + if (v10[i]) + v3 = true; + } + + shadow* shad = a1->shadow_ptr; + if (a1->shadow && v3) { + int32_t v11[2]; + v11[0] = shad->field_200[0]; + v11[1] = shad->field_200[1]; + shad->field_158[0] = &shad->field_8[0]; + shad->field_158[1] = &shad->field_8[1]; + shad->field_158[2] = &shad->field_8[2]; + + draw_object_type v8 = DRAW_OBJECT_SHADOW_OBJECT_CHARA; + for (int32_t i = 0, j = 0; i < 2; i++, v8++) { + if (!v10[i]) + continue; + + int32_t index = v11[i]; + + texture* tex = shad->field_158[0]->color_texture; + render_texture_bind(shad->field_158[0], 0); + glViewport(0, 0, tex->width, tex->height); + glScissor(0, 0, tex->width, tex->height); + gl_state_enable_depth_test(); + gl_state_enable_scissor_test(); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClearDepthf(1.0f); + if (!j) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else if (shad->field_2F5) + glClear(GL_COLOR_BUFFER_BIT); + glScissor(1, 1, tex->width - 2, tex->height - 2); + + float_t v15 = 0.0f; + float_t v16 = shad->field_170 * shad->field_174; + vec3* interest; + vec3* view_point; + if (shad->field_2F5) { + v15 = -0.5f; + if (index) + v15 = 0.5f; + + interest = &shad->interest[index]; + view_point = &shad->view_point[index]; + } + else { + interest = &shad->interest_shared; + view_point = &shad->view_point_shared; + } + + mat4 temp; + mat4_translate(v15, 0.0f, 0.0f, &temp); + + mat4 proj; + mat4_ortho(-v16, v16, -v16, v16, shad->z_near, shad->z_far, &proj); + mat4_mult(&proj, &temp, &proj); + shader_state_matrix_set_projection(&shaders_ft, &proj, false); + + vec3 up = (vec3){ 0.0f, 1.0f, 0.0f }; + vec3 dir; + float_t length; + vec3_sub(*interest, *view_point, dir); + vec3_length_squared(dir, length); + if (length <= 0.000001f) { + up.x = 0.0f; + up.y = 0.0f; + if (dir.z < 0.0f) + up.z = 1.0f; + else + up.z = -1.0f; + } + + mat4_look_at(view_point, interest, &up, &rctx->view_mat); + + rctx->draw_state.shader_index = SHADER_FT_SIL; + uniform_value[U0A] = 0; + + gl_state_bind_vertex_array(rctx->vao); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_SHADOW_CHARA + v11[i], 0, 0, 1, -1); + if (draw_task_get_count(rctx, DRAW_OBJECT_SHADOW_OBJECT_CHARA + v11[i]) > 0) { + glColorMask(a1->field_2F8 != 0 ? GL_TRUE : GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + draw_task_draw_objects_by_type(rctx, v8, 0, 0, true, -1); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + gl_state_disable_depth_test(); + gl_state_disable_scissor_test(); + + rctx->draw_state.shader_index = -1; + if (j == shad->field_2EC - 1) { + draw_pass_shadow_filter(&shad->field_8[3], &shad->field_8[4], shad->field_158[0], + shad->field_2DC, shad->field_2E0 / (shad->field_208 * 2.0f), false); + + GLuint v5 = shad->field_8[5].color_texture->texture; + GLuint v6 = shad->field_8[6].color_texture->texture; + GLuint v7 = shad->field_8[3].color_texture->texture; + if (v5 && v6 && v7) { + texture_param tex_params[3]; + texture_params_get(v5, &tex_params[0], v7, &tex_params[1], v6, &tex_params[2]); + render_texture_bind(&shad->field_8[6], 0); + uniform_value[U_ESM_FILTER] = 0; + shader_set(&shaders_ft, SHADER_FT_ESMFILT); + shader_local_frag_set(&shaders_ft, 0, 1.0f / (float_t)tex_params[1].width, + 1.0f / (float_t)tex_params[1].height, 0.0f, 0.0f); + gl_state_active_bind_texture_2d(0, v7); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + + render_texture_bind(&shad->field_8[5], 0); + uniform_value[U_ESM_FILTER] = 1; + shader_set(&shaders_ft, SHADER_FT_ESMFILT); + shader_local_frag_set(&shaders_ft, 0, 0.75f / (float_t)tex_params[2].width, + 0.75f / (float_t)tex_params[2].height, 0.0f, 0.0f); + gl_state_active_bind_texture_2d(0, v6); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + texture_params_restore(&tex_params[0], &tex_params[1], &tex_params[2]); + } + } + + render_texture* rend_tex = shad->field_158[1 + index]; + render_texture_bind(rend_tex, 0); + + GLuint v11 = shad->field_158[1 + index]->color_texture->texture; + GLuint v12 = shad->field_158[0]->color_texture->texture; + if (v11 && v12) { + texture_param tex_params[3]; + texture_params_get(v11, &tex_params[0], v12, &tex_params[1], 0, 0); + uniform_value[U_IMAGE_FILTER] = 5; + shader_set(&shaders_ft, SHADER_FT_IMGFILT); + shader_local_frag_set_ptr(&shaders_ft, 0, (vec4*)&vec4_identity); + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 1, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 2, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 3, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 4, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 5, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 6, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 7, (mat4*)&mat4_identity); + gl_state_active_bind_texture_2d(0, v12); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + texture_params_restore(&tex_params[0], &tex_params[1], 0); + } + + render_texture_bind(rend_tex, 0); + if (shad->blur_filter_enable[index]) + for (int32_t i = 0; i < shad->near_blur; i++) + blur_filter_apply(rend_tex->color_texture->texture, + rend_tex->color_texture->texture, shad->blur_filter); + else { + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + gl_state_bind_framebuffer(0); + gl_state_bind_texture_2d(rend_tex->color_texture->texture); + glGenerateMipmap(GL_TEXTURE_2D); + gl_state_bind_texture_2d(0); + j++; + } + } + else { + shad->field_158[0] = &shad->field_8[0]; + shad->field_158[1] = &shad->field_8[1]; + shad->field_158[2] = &shad->field_8[2]; + + for (int32_t i = 1; i < 3; i++) + for (int32_t j = 0; j < 4; j++) { + render_texture_bind(shad->field_158[i], j); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + } + gl_state_bind_framebuffer(0); +} + +static void draw_pass_shadow_filter(render_texture* a1, render_texture* a2, + render_texture* a3, float_t sigma, float_t far_texel_offset, bool enable_lit_proj) { + GLuint v7 = a1->color_texture->texture; + GLuint v9 = a2->color_texture->texture; + GLuint v11 = v7; + if (a3) + v11 = a3->depth_texture->texture; + + if (!v7 || !v9 || !v11) + return; + + texture_param tex_params[2]; + texture_params_get(v7, &tex_params[0], v9, &tex_params[1], 0, 0); + if (tex_params[0].width != tex_params[1].width + || tex_params[0].height != tex_params[1].height) + return; + + vec4 v15[2]; + double_t v6 = 1.0 / (sqrt(M_PI * 2.0) * sigma); + double_t v8 = -1.0 / (2.0 * sigma * sigma); + for (int32_t i = 0; i < 8; i++) + ((float_t*)v15)[i] = (float_t)(exp((double_t)((ssize_t)i * i) * v8) * v6); + + render_texture_bind(a2, 0); + uniform_value[U_LIGHT_PROJ] = enable_lit_proj ? 1 : 0; + shader_set(&shaders_ft, SHADER_FT_ESMGAUSS); + shader_local_frag_set(&shaders_ft, 0, 1.0f / (float_t)tex_params[0].width, 0.0f, 0.0f, 0.0f); + shader_local_frag_set_ptr(&shaders_ft, 1, &v15[0]); + shader_local_frag_set_ptr(&shaders_ft, 2, &v15[1]); + shader_local_frag_set(&shaders_ft, 3, far_texel_offset, far_texel_offset, 0.0f, 0.0f); + + gl_state_active_bind_texture_2d(0, v11); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, v11); + if (a3) + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, + (GLint[]) { GL_RED, GL_RED, GL_RED, GL_ONE }); + gl_state_active_bind_texture_2d(0, v11); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + + render_texture_bind(a1, 0); + shader_local_frag_set(&shaders_ft, 0, 0.0f, 1.0f / (float_t)tex_params[0].height, 0.0f, 0.0f); + shader_local_frag_set_ptr(&shaders_ft, 1, &v15[0]); + shader_local_frag_set_ptr(&shaders_ft, 2, &v15[1]); + shader_local_frag_set(&shaders_ft, 3, far_texel_offset, far_texel_offset, 0.0f, 0.0f); + gl_state_active_bind_texture_2d(0, v9); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + shader_unbind(); + texture_params_restore(&tex_params[0], &tex_params[1], 0); +} + +static bool draw_pass_shadow_litproj(render_context* rctx, light_proj* litproj) { + if (!litproj) + return false; + + texture* tex = texture_storage_get_texture(litproj->texture_id); + if (!tex) + return false; + + render_texture_bind(&litproj->draw_texture, 0); + + glViewport(0, 0, litproj->draw_texture.color_texture->width, + litproj->draw_texture.color_texture->height); + gl_state_enable_depth_test(); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClearDepthf(1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (!light_proj_set_mat(rctx, true)) { + gl_state_bind_framebuffer(0); + return false; + } + + rctx->draw_state.shader_index = SHADER_FT_LITPROJ; + gl_state_active_bind_texture_2d(17, tex->texture); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&vec4_null); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + gl_state_active_bind_texture_2d(18, litproj->shadow_texture[0].color_texture->texture); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&vec4_null); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + gl_state_active_texture(0); + return true; +} + +static void draw_pass_sss(render_context* rctx, draw_pass* a1) { + sss_data_struct* sss = &a1->sss_data; + if (!sss->init) + return; + + if (!sss->enable) { + shader_env_frag_set(&shaders_ft, 25, 0.0f, 0.0f, 0.0f, 0.0f); + return; + } + + rctx->view_mat = rctx->camera->view; + post_process_struct* pp = &rctx->post_process; + //if (pp->render_width > 1280.0) + // sss->npr_contour = false; + + if (sss->npr_contour) { + render_texture_bind(&pp->render_texture, 0); + glViewport(0, 0, pp->render_width, pp->render_height); + } + else { + render_texture_bind(&sss->textures[0], 0); + glViewport(0, 0, 640, 360); + } + + glClearColor(sss->param.x, sss->param.y, sss->param.z, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + draw_pass_set_camera(rctx->camera); + for (light_set_id i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_data_set(&rctx->light_set_data[i], &rctx->face, i); + + if (a1->shadow) + draw_pass_3d_shadow_set(a1->shadow_ptr, rctx); + else + draw_pass_3d_shadow_reset(rctx); + + rctx->draw_state.shader_index = SHADER_FT_SSS_SKIN; + gl_state_bind_vertex_array(rctx->vao); + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_SSS, 0, 0, 1, -1); + gl_state_disable_depth_test(); + rctx->draw_state.shader_index = -1; + draw_pass_3d_shadow_reset(rctx); + uniform_value[U_NPR] = 0; + + if (a1->npr_param == 1) { + if (sss->enable && sss->npr_contour) { + uniform_value[U_NPR] = 1; + draw_pass_sss_contour(rctx, pp); + } + else if (a1->npr) { + render_texture_bind(&pp->render_texture, 0); + glViewport(0, 0, pp->render_width, pp->render_height); + glClear(GL_DEPTH_BUFFER_BIT); + rctx->draw_state.shader_index = SHADER_FT_SSS_SKIN; + gl_state_bind_vertex_array(rctx->vao); + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_SSS, 1, 0, 1, -1); + gl_state_disable_depth_test(); + rctx->draw_state.shader_index = -1; + gl_state_bind_framebuffer(0); + uniform_value[U_NPR] = 1; + draw_pass_sss_contour(rctx, pp); + } + } + draw_pass_sss_filter(rctx, sss); + gl_state_bind_framebuffer(0); +} + +static void draw_pass_sss_contour(render_context* rctx, post_process_struct* pp) { + render_texture_bind(&pp->sss_contour_texture, 0); + shader_state_matrix_set_modelview(&shaders_ft, 0, (mat4*)&mat4_identity, false); + shader_state_matrix_set_projection(&shaders_ft, (mat4*)&mat4_identity, true); + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_ALWAYS); + gl_state_set_depth_mask(GL_TRUE); + glViewport(0, 0, pp->render_width, pp->render_height); + gl_state_active_bind_texture_2d(0, pp->render_texture.color_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl_state_active_bind_texture_2d(1, pp->render_texture.depth_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl_state_active_texture(0); + shader_set(&shaders_ft, SHADER_FT_CONTOUR); + + camera* cam = rctx->camera; + float_t v3 = 1.0f / tanf((float_t)(cam->fov_rad * 0.5)); + + vec3 direction; + vec3_sub(cam->interest, cam->view_point, direction); + vec3_normalize(direction, direction); + float_t length; + vec3_length(direction, length); + float_t v7 = direction.y; + if (length != 0.0) + v7 /= length; + + float_t v9 = fabsf(v7) - 0.1f; + if (v9 < 0.0f) + v9 = 0.0f; + + shader_local_frag_set(&shaders_ft, 4, v9 * 0.004f + 0.0027f, 0.003f, v3 * 0.35f, 0.0008f); + render_texture_draw_params(&shaders_ft, pp->render_width, pp->render_height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); +} + +static void draw_pass_sss_filter(render_context* rctx, sss_data_struct* a1) { + double_t a5[3]; + double_t a6[3]; + double_t a7[3]; + double_t a8[3]; + a5[0] = 0.4; + a5[1] = 0.3; + a5[2] = 0.3; + a6[0] = 1.0; + a6[1] = 2.0; + a6[2] = 5.0; + a7[0] = 0.2; + a7[1] = 0.4; + a7[2] = 1.2; + a8[0] = 0.3; + a8[1] = 0.7; + a8[2] = 2.0; + vec3 interest = rctx->camera->interest; + vec3 view_point = rctx->camera->view_point; + + vec3 v46[2]; + v46[0] = vec3_null; + v46[1] = vec3_null; + float_t v14[2]; + for (int32_t i = 0; i < 2; i++) { + v46[i] = interest; + v14[i] = 999999.0; + /*rob_chara_data_struct_bone_data* v16 = sub_1405320F0(i); + if (chara_check_index(v13) && sub_140531F50(v13) && v16) { + mat4* v17 = rob_chara_data_struct_bone_data_get_mats_mat(v16, 0); + if (v17) { + v46[i] = *(vec3*)&v17->row3; + vec3 dist; + vec3_sub(view_point, *(vec3*)&v17->row3, dist); + vec3_length(dist, v14[i]); + } + }*/ + } + + vec3 v24; + if (v14[0] > v14[1]) { + v24 = v46[1]; + v46[0] = v46[1]; + } + else + v24 = v46[0]; + + float_t length; + vec3 dist; + vec3_sub(interest, v24, dist); + vec3_length(dist, length); + if (length > 1.25) + interest = v46[0]; + + float_t v29; + vec3_sub(view_point, interest, interest); + vec3_length(interest, v29); + if (v29 < 0.25f) + v29 = 0.25f; + float_t v31 = tanf((float_t)(rctx->camera->fov_rad * 0.5)) * 5.0f; + if (v31 < 0.25f) + v31 = 0.25f; + float_t v32 = v31 * v29; + float_t v33 = 0.6f; + float_t v34 = 1.0f / clamp(v32, 0.25f, 100.0f); + if (v34 < 0.145) { + float_t v36 = v34 - 0.02f; + if (v34 < 0.0f) + v36 = 0.0f; + v33 = (v36 * 8.0f) * 0.6f; + } + + shader_env_frag_set(&shaders_ft, 25, v33, 0.0f, 0.0f, 0.0f); + + shader_state_matrix_set_projection(&shaders_ft, (mat4*)&mat4_identity, false); + shader_state_matrix_set_modelview(&shaders_ft, 0, (mat4*)&mat4_identity, true); + + gl_state_active_texture(0); + if (a1->npr_contour) { + render_texture_bind(a1->textures, 0); + glViewport(0, 0, 640, 360); + post_process_struct* pp = &rctx->post_process; + gl_state_bind_texture_2d(pp->render_texture.color_texture->texture); + uniform_value[U_REDUCE] = 0; + shader_set(&shaders_ft, SHADER_FT_REDUCE); + + shader_state_matrix_set_texture(&shaders_ft, 0, (mat4*)&mat4_identity); + render_texture_draw_params(&shaders_ft, 640, 360, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f); + } + render_texture_bind(&a1->textures[2], 0); + glViewport(0, 0, 320, 180); + gl_state_bind_texture_2d(a1->textures[0].color_texture->texture); + uniform_value[U_SSS_FILTER] = 0; + shader_set(&shaders_ft, SHADER_FT_SSS_FILT); + render_texture_draw_params(&shaders_ft, 640, 360, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f); + render_texture_bind(&a1->textures[1], 0); + uniform_value[U_SSS_FILTER] = 3; + shader_set(&shaders_ft, SHADER_FT_SSS_FILT); + shader_local_frag_set(&shaders_ft, 1, 5.0f, 0.0f, 0.0f, 0.0f); + float_t params[144]; + for (int32_t i = 0; i < 144; i += 4) + *(vec4u*)¶ms[i] = vec4u_null; + + for (int32_t i = 0; i < 3; i++) { + float_t* v20 = params; + double_t v56[3]; + v56[0] = *a6; + v56[1] = a7[i]; + v56[2] = *a8; + double_t v38 = *a5; + for (int32_t j = 0; j < 3; j++, v20++) { + double_t v54[6]; + double_t v22 = 0.0; + double_t v23 = 0.0; + double_t v24 = 1.0 / (v34 * v56[j]); + for (int32_t k = 0; k < 6; k++) { + v54[k] = exp((v24 * v24) * (v23 * v23) * -0.5); + v22 += v54[k]; + v23 += 1.0; + } + + size_t v26 = 0; + double_t v27 = 1.0 / v22; + for (int32_t k = 0; k < 6; k++) + v54[k] *= v27; + + float_t* v35 = v20; + for (int32_t v33 = 0, v34 = 0; v33 < 6; v33++, v34 += 6, v35 += 24) { + double_t v37 = v54[v33] * v38; + float_t* v39 = v35; + float_t* v50 = ¶ms[4 * v34 + j]; + for (int32_t v36 = 0; v36 < 6; v36++) + v50[v36 * 4] += (float_t)(v37 * v54[v36]); + } + } + } + shader_local_frag_set_ptr_array(&shaders_ft, 4, 36, (vec4*)params); + glViewport(0, 0, 320, 180); + gl_state_bind_texture_2d(a1->textures[2].color_texture->texture); + render_texture_draw_params(&shaders_ft, 320, 180, 1.0f, 1.0f, 0.96f, 1.0f, 0.0f); + gl_state_bind_texture_2d(0); +} + + +static void draw_pass_reflect(render_context* rctx, draw_pass* a1) { +} + +static void draw_pass_refract(render_context* rctx, draw_pass* a1) { +} + +static void draw_pass_preprocess(render_context* rctx, draw_pass* a1) { +} + +static void draw_pass_3d(render_context* rctx, draw_pass* a1) { + rctx->view_mat = rctx->camera->view; + render_texture_bind(&rctx->post_process.render_texture, 0); + glViewport(0, 0, rctx->post_process.render_width, rctx->post_process.render_height); + draw_pass_set_camera(rctx->camera); + if (!a1->sss_data.enable || !a1->sss_data.npr_contour || draw_pass_3d_get_translucent_count(rctx)) + glClear(GL_DEPTH_BUFFER_BIT); + + gl_state_bind_vertex_array(rctx->vao); + + for (light_set_id i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_data_set(&rctx->light_set_data[i], &rctx->face, i); + for (fog_id i = FOG_DEPTH; i < FOG_MAX; i++) + fog_data_set(&rctx->fog_data[i], i); + + if (a1->shadow) + draw_pass_3d_shadow_set(a1->shadow_ptr, rctx); + else + draw_pass_3d_shadow_reset(rctx); + + if (a1->enable[DRAW_PASS_REFLECT] && a1->reflect && a1->reflect_texture.color_texture) { + gl_state_active_bind_texture_2d(15, a1->reflect_texture.color_texture->texture); + uniform_value[U_WATER_REFLECT] = 1; + } + else + uniform_value[U_WATER_REFLECT] = 0; + + if (a1->sss_texture) + gl_state_active_bind_texture_2d(14, a1->sss_texture->texture); + + gl_state_active_bind_texture_2d(16, a1->sss_data.textures[1].color_texture->texture); + gl_state_active_texture(0); + + if (a1->alpha_z_sort) { + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT, 1); + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT_NO_SHADOW, 2); + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_22, 1); + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_25, 1); + draw_task_sort(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_28, 1); + } + + if (a1->opaque_z_sort) + draw_task_sort(rctx, DRAW_OBJECT_OPAQUE, 0); + + if (a1->draw_pass_3d[DRAW_PASS_3D_OPAQUE]) { + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_OPAQUE, 0, 0, 1, -1); + gl_state_disable_depth_test(); + } + + glitter_particle_manager_draw(GPM_VAL, DRAW_PASS_3D_OPAQUE); + + if (draw_grid_3d) + draw_pass_3d_grid(rctx); + + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + if (a1->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT]) + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSPARENT, 0, 0, 1, -1); + /*if (rctx->draw_pass.field_120) + draw_task_draw_objects_by_type(DRAW_OBJECT_TYPE_7, 0, 0, 1, -1);*/ + + //post_process_draw_lens_flare(a1->post_process); + //draw_stars(); + + draw_task_draw_objects_by_type_translucent(rctx, + a1->draw_pass_3d[DRAW_PASS_3D_OPAQUE], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT], + DRAW_OBJECT_OPAQUE_TYPE_26, + DRAW_OBJECT_TRANSPARENT_TYPE_27, + DRAW_OBJECT_TRANSLUCENT_TYPE_28); + + //draw_snow_particle(); + //draw_rain(); + //draw_leaf_particle(); + //draw_particle(); + gl_state_disable_depth_test(); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + glitter_particle_manager_draw(GPM_VAL, DRAW_PASS_3D_TRANSPARENT); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + if (a1->npr_param == 1) { + gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + + if (a1->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT]) { + gl_state_enable_blend(); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl_state_set_depth_mask(GL_FALSE); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT_NO_SHADOW, 0, 0, 1, -1); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT, 0, 0, 1, -1); + gl_state_disable_blend(); + } + + gl_state_set_depth_mask(GL_TRUE); + draw_task_draw_objects_by_type_translucent(rctx, + a1->draw_pass_3d[DRAW_PASS_3D_OPAQUE], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT], + DRAW_OBJECT_OPAQUE_TYPE_23, + DRAW_OBJECT_TRANSPARENT_TYPE_24, + DRAW_OBJECT_TRANSLUCENT_TYPE_25); + gl_state_disable_depth_test(); + + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + glitter_particle_manager_draw(GPM_VAL, DRAW_PASS_3D_TRANSLUCENT); + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + draw_task_draw_objects_by_type_translucent(rctx, + a1->draw_pass_3d[DRAW_PASS_3D_OPAQUE], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT], + a1->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT], + DRAW_OBJECT_OPAQUE_TYPE_20, + DRAW_OBJECT_TRANSPARENT_TYPE_21, + DRAW_OBJECT_TRANSLUCENT_TYPE_22); + + if (a1->sss_texture) + gl_state_active_bind_texture_2d(14, 0); + + gl_state_disable_depth_test(); + + if (a1->enable[DRAW_PASS_REFLECT] && a1->reflect) + gl_state_active_bind_texture_2d(15, 0); + /*if (a1->shadow) + draw_pass_3d_shadow_reset();*/ + shader_unbind(); +} + +static int32_t draw_pass_3d_get_translucent_count(render_context* rctx) { + int32_t count = 0; + count += draw_task_get_count(rctx, DRAW_OBJECT_OPAQUE_TYPE_20); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_21); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_22); + count += draw_task_get_count(rctx, DRAW_OBJECT_OPAQUE_TYPE_23); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_24); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_25); + count += draw_task_get_count(rctx, DRAW_OBJECT_OPAQUE_TYPE_26); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_27); + count += draw_task_get_count(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_28); + return count; +} + +static void draw_pass_3d_shadow_reset(render_context* rctx) { + gl_state_active_bind_texture_2d(6, 0); + gl_state_active_bind_texture_2d(7, 0); + shader_state_matrix_set_texture(&shaders_ft, 6, (mat4*)&mat4_identity); + shader_state_matrix_set_texture(&shaders_ft, 7, (mat4*)&mat4_identity); + rctx->draw_state.self_shadow = false; + rctx->draw_state.light = false; +} + +static void draw_pass_3d_shadow_set(shadow* shad, render_context* rctx) { + if (shad->self_shadow && shad->field_2EC > 0) { + gl_state_active_bind_texture_2d(19, shad->field_8[3].color_texture->texture); + gl_state_active_bind_texture_2d(20, shad->field_8[5].color_texture->texture); + gl_state_active_texture(0); + shader_env_frag_set(&shaders_ft, 23, + ((shad->field_2D8 * shad->field_208) * 2.0f) * 1.442695f, 0.0f, 0.0f, 0.0f); + rctx->draw_state.self_shadow = true; + } + else + rctx->draw_state.self_shadow = false; + + if (shad->field_2EC > 0) { + rctx->draw_state.light = true; + uniform_value[U_LIGHT_1] = shad->field_2EC > 1 ? 1 : 0; + + float_t v7 = shad->field_170 * shad->field_174; + for (int32_t i = 0; i < 2; i++) { + float_t v6 = 0.0f; + vec3* interest; + vec3* view_point; + if (shad->field_2F5) { + v6 = -0.5f; + if (i) + v6 = 0.5f; + + interest = &shad->interest[i]; + view_point = &shad->view_point[i]; + } + else { + interest = &shad->interest_shared; + view_point = &shad->view_point_shared; + } + + vec3 up = (vec3){ 0.0f, 1.0f, 0.0f }; + vec3 dir; + float_t length; + vec3_sub(*interest, *view_point, dir); + vec3_length_squared(dir, length); + if (length <= 0.000001f) { + up.x = 0.0f; + up.y = 0.0f; + if (dir.z < 0.0f) + up.z = 1.0f; + else + up.z = -1.0f; + } + + mat4 temp; + mat4_translate(0.5f, 0.5f, 0.5f, &temp); + mat4_scale_rot(&temp, 0.5f, 0.5f, 0.5f, &temp); + mat4_translate_mult(&temp, v6, 0.0f, 0.0f, &temp); + + mat4 proj; + mat4_ortho(-v7, v7, -v7, v7, shad->z_near, shad->z_far, &proj); + mat4_mult(&proj, &temp, &proj); + + mat4 view; + mat4_look_at(view_point, interest, &up, &view); + mat4_mult(&view, &proj, &view); + shader_state_matrix_set_texture(&shaders_ft, 6ULL + i, &view); + } + + for (int32_t i = 0, j = 0; i < 2; i++) { + if (!shad->field_2F0[i]) + continue; + + gl_state_active_bind_texture_2d(6 + j, shad->field_158[1 + i]->color_texture->texture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); + j++; + } + gl_state_active_texture(0); + + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_data* data = &set->lights[LIGHT_SHADOW]; + + vec4 ambient; + if (light_get_type(data) == LIGHT_PARALLEL) + light_get_ambient(data, &ambient); + else { + ambient.x = shad->ambient; + ambient.y = shad->ambient; + ambient.z = shad->ambient; + } + + shader_env_frag_set(&shaders_ft, 12, ambient.x, ambient.y, ambient.z, 1.0f); + shader_env_frag_set(&shaders_ft, 13, 1.0f - ambient.x, 1.0f - ambient.y, 1.0f - ambient.z, 0.0f); + } + else { + rctx->draw_state.light = false; + + for (int32_t i = 0; i < 2; i++) + gl_state_active_bind_texture_2d(6 + i, shad->field_158[1 + i]->color_texture->texture); + gl_state_active_texture(0); + + shader_env_frag_set_ptr(&shaders_ft, 12, (vec4*)&vec4_identity); + shader_env_frag_set_ptr(&shaders_ft, 13, (vec4*)&vec4_null); + } +} + +static void draw_pass_show_vector(render_context* rctx, draw_pass* a1) { + if (!a1->show_vector_flags) + return; + + rctx->view_mat = rctx->camera->view; + render_texture_bind(&rctx->post_process.render_texture, 0); + glViewport(0, 0, rctx->post_process.render_width, rctx->post_process.render_height); + draw_pass_set_camera(rctx->camera); + + shader_env_vert_set(&shaders_ft, 20, a1->show_vector_length, a1->show_vector_z_offset, 0.0f, 0.0f); + for (int32_t i = 1; i < 4; i++) { + if (~a1->show_vector_flags & (1 << (i - 1))) + continue; + + if (a1->draw_pass_3d[DRAW_PASS_3D_OPAQUE]) + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_OPAQUE, 0, i, 1, -1); + if (a1->draw_pass_3d[DRAW_PASS_3D_TRANSPARENT]) + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSPARENT, 0, i, 1, -1); + if (a1->draw_pass_3d[DRAW_PASS_3D_TRANSLUCENT]) { + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT_NO_SHADOW, 0, i, 1, -1); + draw_task_draw_objects_by_type(rctx, DRAW_OBJECT_TRANSLUCENT, 0, i, 1, -1); + } + } +} + +static void draw_pass_post_process(render_context* rctx, draw_pass* a1) { + texture* light_proj_tex = 0; + light_proj* litproj = rctx->litproj; + if (litproj && litproj->enable) { + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + if (light_get_type(&set->lights[LIGHT_PROJECTION]) == LIGHT_SPOT + && texture_storage_get_texture(litproj->texture_id)) + light_proj_tex = litproj->draw_texture.color_texture; + } + + post_process_apply(&rctx->post_process, rctx->camera, light_proj_tex, a1->npr_param); +} + +static void draw_pass_sprite(render_context* rctx, draw_pass* a1) { +} + inline static void draw_pass_end(draw_pass* pass, draw_pass_type type) { pass->cpu_time[type] = time_struct_calc_time(&pass->time); if (pass->wait_for_gpu) { @@ -230,4 +1043,171 @@ inline static void draw_pass_end(draw_pass* pass, draw_pass_type type) { } else pass->gpu_time[type] = 0; -} \ No newline at end of file +} + +static void draw_pass_3d_grid(render_context* rctx) { + gl_state_enable_blend(); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl_state_set_blend_equation(GL_FUNC_ADD); + gl_state_enable_depth_test(); + gl_state_set_depth_func(GL_LEQUAL); + gl_state_set_depth_mask(GL_TRUE); + + shader_glsl_use(&grid_shader); + shader_glsl_set_mat4(&grid_shader, "vp", GL_FALSE, rctx->camera->view_projection); + gl_state_bind_array_buffer(grid_vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, + sizeof(float_t) * 3, (void*)0); // Pos + glEnableVertexAttribArray(1); + glVertexAttribIPointer(1, 1, GL_INT, + sizeof(float_t) * 3, (void*)(sizeof(float_t) * 2)); // Color + gl_state_bind_array_buffer(0); + glDrawArrays(GL_LINES, 0, (GLsizei)grid_vertex_count); + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + shader_glsl_use(0); + + gl_state_disable_depth_test(); + gl_state_set_depth_mask(GL_FALSE); + gl_state_disable_blend(); +} + +static void draw_pass_set_camera(camera* cam) { + shader_state_matrix_set_modelview(&shaders_ft, 0, &cam->view, false); + shader_state_matrix_set_projection(&shaders_ft, &cam->projection, true); + shader_state_matrix_set_program(&shaders_ft, 5, &cam->view); + + shader_env_frag_set(&shaders_ft, 20, + (float_t)(0.5 / (cam->fov_rad * cam->aspect)), + (float_t)(0.5 / cam->fov_rad), + 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 32, + (float_t)(cam->max_distance / (cam->max_distance - cam->min_distance)), + (float_t)(-(cam->max_distance * cam->min_distance) / (cam->max_distance - cam->min_distance)), + 0.0f, 0.0f); +} + +static void texture_params_get(GLuint tex_0, texture_param* tex_0_param, + GLuint tex_1, texture_param* tex_1_param, GLuint tex_2, texture_param* tex_2_param) { + gl_state_disable_depth_test(); + if (tex_0_param) { + tex_0_param->width = 0; + tex_0_param->height = 0; + if (tex_0) { + gl_state_bind_texture_2d(tex_0); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_0_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_0_param->height); + } + } + + if (tex_1_param) { + tex_1_param->width = 0; + tex_1_param->height = 0; + if (tex_1) { + gl_state_bind_texture_2d(tex_1); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_1_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_1_param->height); + } + } + + if (tex_2_param) { + tex_2_param->width = 0; + tex_2_param->height = 0; + if (tex_2) { + gl_state_bind_texture_2d(tex_2); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex_2_param->width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex_2_param->height); + } + } + gl_state_bind_texture_2d(0); + + if (tex_0_param) { + mat4 mat; + mat4_ortho(0.0f, (float_t)tex_0_param->width, + 0.0f, (float_t)tex_0_param->height, -1.0f, 1.0f, &mat); + shader_state_matrix_set_projection(&shaders_ft, &mat, false); + shader_state_matrix_set_modelview(&shaders_ft, 0, (mat4*)&mat4_identity, true); + glViewport(0, 0, tex_0_param->width, tex_0_param->height); + } +} + +static void texture_params_restore(texture_param* tex_0_param, + texture_param* tex_1_param, texture_param* tex_2_param) { + for (int32_t i = 0; i < 4; i++) + gl_state_active_bind_texture_2d(i, 0); +} + +static void blur_filter_apply(GLuint tex_0, GLuint tex_1, blur_filter_mode filter) { + if (!tex_0 || !tex_1) + return; + + texture_param tex_params[2]; + texture_params_get(tex_0, &tex_params[0], tex_1, &tex_params[1], 0, 0); + uniform_value[U_IMAGE_FILTER] = filter == BLUR_FILTER_32 ? 1 : 0; + shader_set(&shaders_ft, SHADER_FT_IMGFILT); + + float_t scale = filter == BLUR_FILTER_32 ? (float_t)(1.0 / 8.0) : (float_t)(1.0 / 4.0); + shader_local_frag_set(&shaders_ft, 0, scale, scale, scale, scale); + shader_local_frag_set(&shaders_ft, 1, 0.0f, 0.0f, 0.0f, 0.0f); + float_t w = 1.0f / (float_t)tex_params[1].width; + float_t h = 1.0f / (float_t)tex_params[1].height; + switch (filter) { + case BLUR_FILTER_4: { + mat4 m[4]; + mat4_translate( 1.0f * w, 0.0f * h, 0.0f, &m[0]); + mat4_translate( 0.0f * w, 1.0f * h, 0.0f, &m[1]); + mat4_translate( 1.0f * w, -1.0f * h, 0.0f, &m[2]); + mat4_translate( 0.0f * w, -1.0f * h, 0.0f, &m[3]); + shader_state_matrix_set_texture(&shaders_ft, 0, &m[0]); + shader_state_matrix_set_texture(&shaders_ft, 1, &m[1]); + shader_state_matrix_set_texture(&shaders_ft, 2, &m[2]); + shader_state_matrix_set_texture(&shaders_ft, 3, &m[3]); + } break; + case BLUR_FILTER_9: { + mat4 m[4]; + mat4_translate(-0.5f * w, 0.5f * h, 0.0f, &m[0]); + mat4_translate( 0.5f * w, 0.5f * h, 0.0f, &m[1]); + mat4_translate(-0.5f * w, -0.5f * h, 0.0f, &m[2]); + mat4_translate( 0.5f * w, -0.5f * h, 0.0f, &m[3]); + shader_state_matrix_set_texture(&shaders_ft, 0, &m[0]); + shader_state_matrix_set_texture(&shaders_ft, 1, &m[1]); + shader_state_matrix_set_texture(&shaders_ft, 2, &m[2]); + shader_state_matrix_set_texture(&shaders_ft, 3, &m[3]); + } break; + case BLUR_FILTER_16: { + mat4 m[4]; + mat4_translate( 0.5f * w, -1.5f * h, 0.0f, &m[0]); + mat4_translate(-1.5f * w, 0.5f * h, 0.0f, &m[1]); + mat4_translate( 1.5f * w, -0.5f * h, 0.0f, &m[2]); + mat4_translate(-0.5f * w, 1.5f * h, 0.0f, &m[3]); + shader_state_matrix_set_texture(&shaders_ft, 0, &m[0]); + shader_state_matrix_set_texture(&shaders_ft, 1, &m[1]); + shader_state_matrix_set_texture(&shaders_ft, 2, &m[2]); + shader_state_matrix_set_texture(&shaders_ft, 3, &m[3]); + } break; + case BLUR_FILTER_32: { + mat4 m[8]; + mat4_translate( 3.5f * w, -3.5f * h, 0.0f, &m[0]); + mat4_translate(-1.5f * w, -3.5f * h, 0.0f, &m[1]); + mat4_translate( 1.5f * w, -1.5f * h, 0.0f, &m[2]); + mat4_translate(-3.5f * w, -1.5f * h, 0.0f, &m[3]); + mat4_translate( 3.5f * w, 1.5f * h, 0.0f, &m[4]); + mat4_translate( 1.5f * w, 1.5f * h, 0.0f, &m[5]); + mat4_translate( 1.5f * w, 3.5f * h, 0.0f, &m[6]); + mat4_translate(-3.5f * w, 3.5f * h, 0.0f, &m[7]); + shader_state_matrix_set_texture(&shaders_ft, 0, &m[0]); + shader_state_matrix_set_texture(&shaders_ft, 1, &m[1]); + shader_state_matrix_set_texture(&shaders_ft, 2, &m[2]); + shader_state_matrix_set_texture(&shaders_ft, 3, &m[3]); + shader_state_matrix_set_texture(&shaders_ft, 4, &m[4]); + shader_state_matrix_set_texture(&shaders_ft, 5, &m[5]); + shader_state_matrix_set_texture(&shaders_ft, 6, &m[6]); + shader_state_matrix_set_texture(&shaders_ft, 7, &m[7]); + } break; + } + gl_state_active_bind_texture_2d(0, tex_1); + shader_state_matrix_set_mvp(&shaders_ft, (mat4*)&mat4_identity); + render_texture_draw_custom(&shaders_ft); + texture_params_restore(&tex_params[0], &tex_params[1], 0); +} diff --git a/src/CRE/draw_pass.h b/src/CRE/draw_pass.h index f0815a33..d05f694e 100644 --- a/src/CRE/draw_pass.h +++ b/src/CRE/draw_pass.h @@ -8,36 +8,6 @@ #include "../KKdLib/default.h" #include "../KKdLib/mat.h" #include "../KKdLib/vec.h" +#include "draw_task.h" -typedef enum draw_object_type { - DRAW_OBJECT_OPAQUE = 0x00, - DRAW_OBJECT_TRANSLUCENT = 0x01, - DRAW_OBJECT_TRANSLUCENT_NO_SHADOW = 0x02, - DRAW_OBJECT_TRANSPARENT = 0x03, - DRAW_OBJECT_SHADOW_CHARA = 0x04, - DRAW_OBJECT_SHADOW_STAGE = 0x05, - DRAW_OBJECT_TYPE_6 = 0x06, - DRAW_OBJECT_TYPE_7 = 0x07, - DRAW_OBJECT_SHADOW_OBJECT_CHARA = 0x08, - DRAW_OBJECT_SHADOW_OBJECT_STAGE = 0x09, - DRAW_OBJECT_REFLECT_CHARA_OPAQUE = 0x0A, - DRAW_OBJECT_REFLECT_CHARA_TRANSLUCENT = 0x0B, - DRAW_OBJECT_REFLECT_CHARA_TRANSPARENT = 0x0C, - DRAW_OBJECT_REFLECT_OPAQUE = 0x0D, - DRAW_OBJECT_REFLECT_TRANSLUCENT = 0x0E, - DRAW_OBJECT_REFLECT_TRANSPARENT = 0x0F, - DRAW_OBJECT_REFRACT_OPAQUE = 0x10, - DRAW_OBJECT_REFRACT_TRANSLUCENT = 0x11, - DRAW_OBJECT_REFRACT_TRANSPARENT = 0x12, - DRAW_OBJECT_HRC = 0x13, - DRAW_OBJECT_OPAQUE_TYPE_20 = 0x14, - DRAW_OBJECT_TRANSPARENT_TYPE_21 = 0x15, - DRAW_OBJECT_TRANSLUCENT_TYPE_22 = 0x16, - DRAW_OBJECT_OPAQUE_TYPE_23 = 0x17, - DRAW_OBJECT_TRANSPARENT_TYPE_24 = 0x18, - DRAW_OBJECT_TRANSLUCENT_TYPE_25 = 0x19, - DRAW_OBJECT_OPAQUE_TYPE_26 = 0x1A, - DRAW_OBJECT_TRANSPARENT_TYPE_27 = 0x1B, - DRAW_OBJECT_TRANSLUCENT_TYPE_28 = 0x1C, - DRAW_OBJECT_RIPPLE = 0x1D, -} draw_object_type; +extern void draw_pass_main(render_context* rctx); diff --git a/src/CRE/draw_primitive.c b/src/CRE/draw_primitive.c new file mode 100644 index 00000000..d4daff1d --- /dev/null +++ b/src/CRE/draw_primitive.c @@ -0,0 +1,6 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "draw_object.h" diff --git a/src/CRE/draw_primitive.h b/src/CRE/draw_primitive.h new file mode 100644 index 00000000..89873b4c --- /dev/null +++ b/src/CRE/draw_primitive.h @@ -0,0 +1,12 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/vector.h" +#include "gl_state.h" diff --git a/src/CRE/draw_task.c b/src/CRE/draw_task.c new file mode 100644 index 00000000..2fdcb268 --- /dev/null +++ b/src/CRE/draw_task.c @@ -0,0 +1,966 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "draw_task.h" +#include "camera.h" +#include "fbo.h" +#include "post_process.h" +#include "shader_ft.h" + +static void draw_task_add(render_context* rctx, draw_object_type type, draw_task* task); +static void draw_task_object_init(draw_task* task, object_data* object_data, mat4* mat, + float_t bounding_radius, object_sub_mesh* sub_mesh, object_mesh* mesh, object_material_data* material, + uint32_t* textures, int32_t mat_count, mat4u* mats, GLuint array_buffer, + GLuint element_array_buffer, vec4* blend_color, int32_t morph_array_buffer, + int32_t instances_count, mat4* instances_mat, void(*draw_object_func)(draw_object*)); +static void draw_task_object_translucent_init(draw_task* task, mat4* mat, + draw_task_object_translucent* object); +static int32_t draw_task_translucent_sort_count_layers(render_context* rctx, + int32_t* alpha_array, draw_object_type opaque, + draw_object_type transparent, draw_object_type translucent); +static void draw_task_translucent_sort_has_objects(render_context* rctx, bool* arr, draw_object_type type); + +void draw_task_draw_objects_by_type(render_context* rctx, draw_object_type type, + int32_t a2, int32_t show_vector, bool a4, int32_t alpha) { + if (draw_task_get_count(rctx, type) <= 0) + return; + + int32_t alpha_test = 0; + float_t min_alpha = 1.0f; + bool reflect = uniform_value[U_REFLECT] == 1; + void(*draw_object_func)(render_context* rctx, draw_object* draw) = draw_object_draw_default; + + for (int32_t i = 0; i < 6; i++) + gl_state_active_bind_texture_2d(i, 0); + gl_state_active_texture(0); + gl_state_set_blend_func(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + uniform_value_reset(); + gl_state_get(); + + switch (type) { + case DRAW_OBJECT_TRANSLUCENT: + case DRAW_OBJECT_TRANSLUCENT_NO_SHADOW: + case DRAW_OBJECT_TRANSLUCENT_TYPE_22: + case DRAW_OBJECT_TRANSLUCENT_TYPE_25: + case DRAW_OBJECT_TRANSLUCENT_TYPE_28: + if (a2) + draw_object_func = draw_object_draw_translucent; + else + gl_state_set_depth_mask(GL_FALSE); + min_alpha = 0.0; + break; + case DRAW_OBJECT_TRANSPARENT: + case DRAW_OBJECT_TRANSPARENT_TYPE_21: + case DRAW_OBJECT_TRANSPARENT_TYPE_24: + case DRAW_OBJECT_TRANSPARENT_TYPE_27: + alpha_test = 1; + min_alpha = 0.1f; + break; + case DRAW_OBJECT_SHADOW_CHARA: + case DRAW_OBJECT_SHADOW_STAGE: + case DRAW_OBJECT_SHADOW_OBJECT_CHARA: + case DRAW_OBJECT_SHADOW_OBJECT_STAGE: + draw_object_func = draw_object_draw_shadow; + min_alpha = 0.5f; + break; + case DRAW_OBJECT_TYPE_6: + draw_object_func = draw_object_draw_translucent; + gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + rctx->draw_state.shader_index = SHADER_FT_SIL; + break; + case DRAW_OBJECT_TYPE_7: + draw_object_func = draw_object_draw_translucent; + gl_state_set_color_mask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + rctx->draw_state.shader_index = SHADER_FT_SIL; + alpha_test = 1; + min_alpha = 0.0f; + break; + case DRAW_OBJECT_REFLECT_CHARA_OPAQUE: + gl_state_set_cull_face_mode(GL_FRONT); + if (reflect) + draw_object_func = draw_object_draw_reflect; + else if (rctx->draw_pass.reflect_type == 2) + draw_object_func = draw_object_draw_reflect_type_2; + break; + case DRAW_OBJECT_REFLECT_CHARA_TRANSLUCENT: + gl_state_set_cull_face_mode(GL_FRONT); + if (reflect) + draw_object_func = draw_object_draw_reflect; + else if (rctx->draw_pass.reflect_type == 2) + draw_object_func = draw_object_draw_reflect_type_2; + min_alpha = 0.0f; + break; + case DRAW_OBJECT_REFLECT_CHARA_TRANSPARENT: + gl_state_set_cull_face_mode(GL_FRONT); + alpha_test = 1; + min_alpha = 0.1f; + if (reflect) + draw_object_func = draw_object_draw_reflect; + else { + if (rctx->draw_pass.reflect_type == 2) + draw_object_func = draw_object_draw_reflect_type_2; + } + break; + case DRAW_OBJECT_REFLECT_OPAQUE: + alpha_test = 1; + if (!a4) + draw_object_func = draw_object_draw_reflect_type_2; + break; + case DRAW_OBJECT_REFLECT_TRANSLUCENT: + case DRAW_OBJECT_REFRACT_TRANSLUCENT: + gl_state_set_depth_mask(GL_FALSE); + min_alpha = 0.0f; + break; + case DRAW_OBJECT_REFLECT_TRANSPARENT: + case DRAW_OBJECT_REFRACT_TRANSPARENT: + alpha_test = 1; + min_alpha = 0.1f; + break; + case DRAW_OBJECT_SSS: + draw_object_func = draw_object_draw_sss; + break; + case DRAW_OBJECT_RIPPLE: + draw_object_func = draw_object_draw_translucent; + break; + default: + break; + } + shader_env_frag_set(&shaders_ft, 21, 0.0f, 0.0f, 0.0f, min_alpha); + uniform_value[U_ALPHA_TEST] = alpha_test; + + vector_ptr_draw_task* vec = &rctx->object_data.draw_task_array[type]; + if (alpha < 0) + for (draw_task** i = vec->begin; i != vec->end; i++) { + draw_task* task = *i; + switch (task->type) { + case DRAW_TASK_TYPE_OBJECT: { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + draw_object_draw(rctx, &task->data.object, + &mat, draw_object_func, show_vector); + } break; + case DRAW_TASK_TYPE_PRIMITIVE: { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + draw_object_model_mat_load(rctx, &mat); + //draw_primitive_draw(&task->data.primitive); + } break; + case DRAW_TASK_TYPE_PREPROCESS: { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + draw_object_model_mat_load(rctx, &mat); + task->data.preprocess.func(rctx, task->data.preprocess.data); + } break; + case DRAW_TASK_TYPE_OBJECT_TRANSLUCENT: { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + for (int32_t j = 0; j < task->data.object_translucent.count; j++) + draw_object_draw(rctx, task->data.object_translucent.objects[j], + &mat, draw_object_func, show_vector); + } break; + } + } + else + for (draw_task** i = vec->begin; i != vec->end; i++) { + draw_task* task = *i; + switch (task->type) { + case DRAW_TASK_TYPE_OBJECT: { + int32_t a = (int32_t)(task->data.object.blend_color.w * 255.0f); + a = clamp(a, 0, 255); + if (a == alpha) { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + draw_object_draw(rctx, &task->data.object, + &mat, draw_object_func, show_vector); + } + } break; + case DRAW_TASK_TYPE_OBJECT_TRANSLUCENT: { + mat4 mat; + mat4u_to_mat4(&task->mat, &mat); + for (int32_t j = 0; j < task->data.object_translucent.count; j++) { + draw_object* object = task->data.object_translucent.objects[j]; + int32_t a = (int32_t)(object->blend_color.w * 255.0f); + a = clamp(a, 0, 255); + if (a == alpha) + draw_object_draw(rctx, object, + &mat, draw_object_func, show_vector); + } + } break; + } + } + + switch (type) { + case DRAW_OBJECT_TRANSLUCENT: + case DRAW_OBJECT_TRANSLUCENT_NO_SHADOW: + case DRAW_OBJECT_REFLECT_TRANSLUCENT: + case DRAW_OBJECT_REFRACT_TRANSLUCENT: + case DRAW_OBJECT_TRANSLUCENT_TYPE_22: + case DRAW_OBJECT_TRANSLUCENT_TYPE_25: + case DRAW_OBJECT_TRANSLUCENT_TYPE_28: + if (!a2) + gl_state_set_depth_mask(GL_TRUE); + break; + case DRAW_OBJECT_TYPE_6: + case DRAW_OBJECT_TYPE_7: + rctx->draw_state.shader_index = -1; + gl_state_set_color_mask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + break; + case DRAW_OBJECT_REFLECT_CHARA_OPAQUE: + case DRAW_OBJECT_REFLECT_CHARA_TRANSLUCENT: + case DRAW_OBJECT_REFLECT_CHARA_TRANSPARENT: + case DRAW_OBJECT_TRANSPARENT_TYPE_21: + case DRAW_OBJECT_TRANSPARENT_TYPE_24: + case DRAW_OBJECT_TRANSPARENT_TYPE_27: + gl_state_set_cull_face_mode(GL_BACK); + break; + } + + uniform_value_reset(); + shader_unbind(); + gl_state_set_blend_func(GL_ONE, GL_ZERO); +} + +void draw_task_draw_objects_by_type_translucent(render_context* rctx, bool opaque_enable, + bool transparent_enable, bool translucent_enable, draw_object_type opaque, + draw_object_type transparent, draw_object_type translucent) { + if (draw_task_get_count(rctx, opaque) <= 0) + return; + else if (draw_task_get_count(rctx, transparent) <= 0) + return; + else if (draw_task_get_count(rctx, translucent) <= 0) + return; + + int32_t alpha_array[256]; + int32_t count = draw_task_translucent_sort_count_layers(rctx, + alpha_array, opaque, transparent, translucent); + for (int32_t i = 0; i < count; i++) { + int32_t alpha = alpha_array[i]; + fbo_blit(rctx->post_process.render_texture.fbos[0], + rctx->post_process.alpha_layer_texture.fbos[0], + 0, 0, rctx->post_process.render_width, rctx->post_process.render_height, + 0, 0, rctx->post_process.render_width, rctx->post_process.render_height, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_LINEAR); + + if (opaque_enable && draw_task_get_count(rctx, opaque)) + draw_task_draw_objects_by_type(rctx, opaque, 0, 0, 1, alpha); + if (transparent_enable && draw_task_get_count(rctx, transparent)) + draw_task_draw_objects_by_type(rctx, transparent, 0, 0, 1, alpha); + if (translucent_enable && draw_task_get_count(rctx, translucent)) { + gl_state_enable_blend(); + draw_task_draw_objects_by_type(rctx, translucent, 0, 0, 1, alpha); + gl_state_disable_blend(); + } + + render_texture_bind(&rctx->post_process.buf_texture, 0); + render_texture_shader_set_glsl(&rctx->post_process.alpha_layer_shader); + gl_state_active_bind_texture_2d(0, rctx->post_process.alpha_layer_texture.color_texture->texture); + gl_state_active_bind_texture_2d(1, rctx->post_process.render_texture.color_texture->texture); + glUniform1f(0, (float_t)(alpha * (1.0 / 255.0))); + render_texture_draw_custom_glsl(); + + fbo_blit(rctx->post_process.buf_texture.fbos[0], + rctx->post_process.render_texture.fbos[0], + 0, 0, rctx->post_process.render_width, rctx->post_process.render_height, + 0, 0, rctx->post_process.render_width, rctx->post_process.render_height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + } +} + +inline int32_t draw_task_get_count(render_context* rctx, draw_object_type type) { + return (int32_t)(rctx->object_data.draw_task_array[type].end + - rctx->object_data.draw_task_array[type].begin); +} + +bool draw_task_add_draw_object(render_context* rctx, object* obj, + object_mesh_vertex_buffer* obj_vertex_buf, object_mesh_index_buffer* obj_index_buf, mat4* mat, + uint32_t* textures, vec4* blend_color, mat4* bone_mat, object* object_morph, + object_mesh_vertex_buffer* obj_morph_vertex_buf, int32_t instances_count, + mat4* instances_mat, void(*draw_object_func)(draw_object*), bool enable_bone_mat) { + object_data* object_data = &rctx->object_data; + draw_task_flags draw_task_flags = object_data->draw_task_flags; + + if (object_data->object_culling && !instances_count && !bone_mat && (!obj + || !object_bounding_sphere_check_visibility(&obj->bounding_sphere, object_data, rctx->camera, mat))) { + object_data->culled.objects++; + return false; + } + object_data->passed.objects++; + + for (int32_t i = 0; i < obj->meshes_count; i++) { + object_mesh* mesh = &obj->meshes[i]; + object_mesh* mesh_morph = 0; + if (obj_vertex_buf && obj_morph_vertex_buf) { + if (object_mesh_vertex_buffer_get_size(&obj_vertex_buf[i]) + != object_mesh_vertex_buffer_get_size(&obj_morph_vertex_buf[i])) + continue; + + if (object_morph && i < object_morph->meshes_count) + mesh_morph = &object_morph->meshes[i]; + } + + if (object_data->object_culling && !instances_count && !bone_mat + && !object_bounding_sphere_check_visibility(&mesh->bounding_sphere, object_data, rctx->camera, mat) + && (!mesh_morph || !object_bounding_sphere_check_visibility( + &mesh_morph->bounding_sphere, object_data, rctx->camera, mat))) { + object_data->culled.meshes++; + continue; + } + object_data->passed.meshes++; + + draw_object* translucent_priority[40]; + int32_t translucent_priority_count = 0; + + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; + object_sub_mesh* sub_mesh_morph = 0; + if (sub_mesh->flags & OBJECT_SUB_MESH_FLAG_8) + continue; + + if (object_data->object_culling && !instances_count && !bone_mat) { + int32_t v32 = object_bounding_sphere_check_visibility( + &sub_mesh->bounding_sphere, object_data, rctx->camera, mat); + if (v32 != 2 || (~mesh->flags & OBJECT_MESH_BILLBOARD && + ~mesh->flags & OBJECT_MESH_BILLBOARD_Y_AXIS)) { + if (v32 == 2) { + if (object_data->object_bounding_sphere_check_func) + v32 = 1; + else + v32 = object_axis_aligned_bounding_box_check_visibility( + &sub_mesh->axis_aligned_bounding_box, rctx->camera, mat); + } + + if (!v32) { + if (!mesh_morph || j >= mesh_morph->sub_meshes_count) { + object_data->culled.sub_meshes++; + continue; + } + + sub_mesh_morph = &mesh_morph->sub_meshes[j]; + if (!sub_mesh_morph) { + object_data->culled.sub_meshes++; + continue; + } + + v32 = object_bounding_sphere_check_visibility( + &sub_mesh_morph->bounding_sphere, object_data, rctx->camera, mat); + if (v32 == 2) { + if (object_data->object_bounding_sphere_check_func) + v32 = 1; + else + v32 = object_axis_aligned_bounding_box_check_visibility( + &sub_mesh_morph->axis_aligned_bounding_box, rctx->camera, mat); + } + + if (!v32) { + object_data->culled.sub_meshes++; + continue; + } + } + } + } + object_data->passed.sub_meshes++; + + int32_t bone_indices_count = sub_mesh->bone_indices_count; + uint16_t* bone_indices = sub_mesh->bone_indices; + + mat4u* mats; + if (bone_indices_count && enable_bone_mat) { + mats = object_data_buffer_add_mat4(&rctx->object_data.buffer, bone_indices_count); + if (bone_mat) + for (int32_t k = 0; k < bone_indices_count; k++) + mat4_to_mat4u(&bone_mat[*bone_indices++], &mats[k]); + else + for (int32_t k = 0; k < bone_indices_count; k++) + mat4_to_mat4u((mat4*)&mat4_identity, &mats[k]); + } + else { + mats = 0; + bone_indices_count = 0; + } + + object_material_data* material = &obj->materials[sub_mesh->material_index]; + draw_task* task = object_data_buffer_add_draw_task(&rctx->object_data.buffer, DRAW_TASK_TYPE_OBJECT); + if (!task) + continue; + + GLuint morph_array_buffer = 0; + if (obj_morph_vertex_buf) + morph_array_buffer = object_mesh_vertex_buffer_get_buffer(&obj_morph_vertex_buf[i]); + + GLuint element_array_buffer = 0; + if (obj_index_buf) + element_array_buffer = obj_index_buf[i]; + + GLuint array_buffer = 0; + if (obj_vertex_buf) + array_buffer = object_mesh_vertex_buffer_get_buffer(&obj_vertex_buf[i]); + + draw_task_object_init( + task, + object_data, + mat, + obj->bounding_sphere.radius, + sub_mesh, + mesh, + material, + textures, + bone_indices_count, + mats, + array_buffer, + element_array_buffer, + blend_color, + morph_array_buffer, + instances_count, + instances_mat, + draw_object_func); + + if (draw_task_flags & DRAW_TASK_SHADOW_OBJECT) { + draw_task_add(rctx, DRAW_OBJECT_SHADOW_OBJECT_CHARA + object_data->shadow_type, task); + if (draw_task_flags & DRAW_TASK_RIPPLE) + draw_task_add(rctx, DRAW_OBJECT_RIPPLE, task); + continue; + } + + object_material_blend_flags blend_flags = material->material.blend_flags; + if (draw_task_flags & (DRAW_TASK_10000 | DRAW_TASK_20000 | DRAW_TASK_40000) + && task->data.object.blend_color.w < 1.0f) { + if (~draw_task_flags | DRAW_TASK_NO_TRANSLUCENCY) { + if (blend_flags.flag_28 || (blend_flags.punch_through + || !(blend_flags.alpha_texture | blend_flags.alpha_material)) + && ~sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) { + if (!blend_flags.punch_through) { + if (draw_task_flags & DRAW_TASK_10000) + draw_task_add(rctx, DRAW_OBJECT_OPAQUE_TYPE_20, task); + else if (draw_task_flags & DRAW_TASK_20000) + draw_task_add(rctx, DRAW_OBJECT_OPAQUE_TYPE_23, task); + else + draw_task_add(rctx, DRAW_OBJECT_OPAQUE_TYPE_26, task); + } + else { + if (draw_task_flags & DRAW_TASK_10000) + draw_task_add(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_21, task); + else if (draw_task_flags & DRAW_TASK_20000) + draw_task_add(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_24, task); + else + draw_task_add(rctx, DRAW_OBJECT_TRANSPARENT_TYPE_27, task); + } + + if (draw_task_flags & DRAW_TASK_SSS) + draw_task_add(rctx, DRAW_OBJECT_SSS, task); + } + + if (draw_task_flags & DRAW_TASK_10000) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_22, task); + else if (draw_task_flags & DRAW_TASK_20000) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_25, task); + else + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_28, task); + } + } + else { + if (blend_flags.flag_28 || task->data.object.blend_color.w >= 1.0f + && (blend_flags.punch_through || !(blend_flags.alpha_texture | blend_flags.alpha_material)) + && ~sub_mesh->flags & OBJECT_SUB_MESH_TRANSPARENT) { + if (draw_task_flags & DRAW_TASK_SHADOW) + draw_task_add(rctx, DRAW_OBJECT_SHADOW_CHARA + object_data->shadow_type, task); + + if (draw_task_flags & DRAW_TASK_SSS) + draw_task_add(rctx, DRAW_OBJECT_SSS, task); + + if (material->material.blend_flags.punch_through) { + if (~draw_task_flags & DRAW_TASK_NO_TRANSLUCENCY) + draw_task_add(rctx, DRAW_OBJECT_TRANSPARENT, task); + + if (draw_task_flags & DRAW_TASK_CHARA_REFLECT) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_CHARA_OPAQUE, task); + + if (draw_task_flags & DRAW_TASK_REFLECT) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_OPAQUE, task); + + if (draw_task_flags & DRAW_TASK_REFRACT) + draw_task_add(rctx, DRAW_OBJECT_REFRACT_TRANSPARENT, task); + } + else { + if (~draw_task_flags & DRAW_TASK_NO_TRANSLUCENCY) + draw_task_add(rctx, DRAW_OBJECT_OPAQUE, task); + + if (draw_task_flags & DRAW_TASK_20) + draw_task_add(rctx, DRAW_OBJECT_TYPE_6, task); + + if (draw_task_flags & DRAW_TASK_CHARA_REFLECT) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_CHARA_OPAQUE, task); + + if (draw_task_flags & DRAW_TASK_REFLECT) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_OPAQUE, task); + + if (draw_task_flags & DRAW_TASK_REFRACT) + draw_task_add(rctx, DRAW_OBJECT_REFRACT_OPAQUE, task); + } + + if (draw_task_flags & DRAW_TASK_RIPPLE) + draw_task_add(rctx, DRAW_OBJECT_RIPPLE, task); + continue; + } + else if (~draw_task_flags & DRAW_TASK_NO_TRANSLUCENCY) { + if (!blend_flags.translucent_priority) + if (mesh->flags & OBJECT_MESH_TRANSLUCENT_NO_SHADOW + || draw_task_flags & DRAW_TASK_TRANSLUCENT_NO_SHADOW) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_NO_SHADOW, task); + else + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT, task); + else if (translucent_priority_count < 40) + translucent_priority[translucent_priority_count++] = &task->data.object; + } + } + + if (draw_task_flags & DRAW_TASK_SHADOW) + draw_task_add(rctx, DRAW_OBJECT_SHADOW_CHARA + object_data->shadow_type, task); + if (draw_task_flags & DRAW_TASK_40) + draw_task_add(rctx, DRAW_OBJECT_TYPE_7, task); + if (draw_task_flags & DRAW_TASK_CHARA_REFLECT) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_CHARA_OPAQUE, task); + if (draw_task_flags & DRAW_TASK_REFLECT) { + if (rctx->draw_pass.reflect_type != 2) + draw_task_add(rctx, DRAW_OBJECT_REFLECT_OPAQUE, task); + else + draw_task_add(rctx, DRAW_OBJECT_REFLECT_TRANSLUCENT, task); + } + if (draw_task_flags & DRAW_TASK_REFRACT) + draw_task_add(rctx, DRAW_OBJECT_REFRACT_TRANSLUCENT, task); + if (draw_task_flags & DRAW_TASK_RIPPLE) + draw_task_add(rctx, DRAW_OBJECT_RIPPLE, task); + } + + if (!translucent_priority_count) + continue; + + draw_task_object_translucent object_translucent; + object_translucent.count = 0; + for (int32_t j = 62; j; j--) + for (int32_t k = 0; k < translucent_priority_count; k++) { + draw_object* object = translucent_priority[k]; + if (object->material->material.blend_flags.translucent_priority != j) + continue; + + object_translucent.objects[object_translucent.count] = object; + object_translucent.count++; + } + + draw_task* task = object_data_buffer_add_draw_task(&rctx->object_data.buffer, + DRAW_TASK_TYPE_OBJECT_TRANSLUCENT); + if (!task) + continue; + + draw_task_object_translucent_init(task, mat, &object_translucent); + if (draw_task_flags & DRAW_TASK_10000) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_22, task); + else if (draw_task_flags & DRAW_TASK_20000) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_25, task); + else if (draw_task_flags & DRAW_TASK_40000) + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT_TYPE_28, task); + else + draw_task_add(rctx, DRAW_OBJECT_TRANSLUCENT, task); + } + return true; +} + +bool draw_task_add_draw_object_by_object_info(render_context* rctx, mat4* mat, + object_info obj_info, vec4* blend_color, mat4* bone_mat, int32_t instances_count, + mat4* instances_mat, void(*draw_object_func)(draw_object*), bool enable_bone_mat) { + if (obj_info.id == -1 && obj_info.set_id == -1) + return false; + + object_data* object_data = &rctx->object_data; + + object* obj = object_storage_get_object(obj_info); + if (!obj) + return false; + + uint32_t* textures = object_storage_get_textures(obj_info.set_id); + object_mesh_vertex_buffer* obj_vertex_buffer = object_storage_get_object_mesh_vertex_buffer(obj_info); + object_mesh_index_buffer* obj_index_buffer = object_storage_get_object_mesh_index_buffer(obj_info); + + object* obj_morph = 0; + object_mesh_vertex_buffer* obj_morph_vertex_buffer = 0; + if (object_data->morph.object.set_id != -1) { + obj_morph = object_storage_get_object(object_data->morph.object); + obj_morph_vertex_buffer = object_storage_get_object_mesh_vertex_buffer(object_data->morph.object); + } + + return draw_task_add_draw_object(rctx, + obj, + obj_vertex_buffer, + obj_index_buffer, + mat, + textures, + blend_color, + bone_mat, + obj_morph, + obj_morph_vertex_buffer, + instances_count, + instances_mat, + draw_object_func, + enable_bone_mat); +} + +inline bool draw_task_add_draw_object_by_object_info_alpha(render_context* rctx, mat4* mat, + object_info obj_info, float_t alpha) { + vec4 blend_color = vec4_identity; + blend_color.w = alpha; + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, &blend_color, 0, 0, 0, 0, false); +} + +inline bool draw_task_add_draw_object_by_object_info_alpha_bone_mat(render_context* rctx, mat4* mat, + object_info obj_info, float_t alpha, mat4* bone_mat) { + vec4 blend_color = vec4_identity; + blend_color.w = alpha; + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, &blend_color, bone_mat, 0, 0, 0, true); +} + +inline bool draw_task_add_draw_object_by_object_info_bone_mat(render_context* rctx, mat4* mat, + object_info obj_info, mat4* bone_mat) { + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, 0, bone_mat, 0, 0, 0, true); +} + +inline bool draw_task_add_draw_object_by_object_info_color(render_context* rctx, mat4* mat, + object_info obj_info, float_t r, float_t g, float_t b, float_t a) { + vec4 blend_color; + blend_color.x = r; + blend_color.y = g; + blend_color.z = b; + blend_color.w = a; + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, &blend_color, 0, 0, 0, 0, false); +} + +inline bool draw_task_add_draw_object_by_object_info_color_vec4(render_context* rctx, mat4* mat, + object_info obj_info, vec4* blend_color) { + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, blend_color, 0, 0, 0, 0, false); +} + +void draw_task_add_draw_object_by_object_info_object_skin(render_context* rctx, object_info obj_info, + vector_texture_pattern_struct* texture_pattern, texture_data_struct* texture_data, float_t alpha, + mat4* matrices, mat4* ex_data_matrices, mat4* mat, mat4* global_mat) { + object_skin* skin = object_storage_get_object_skin(obj_info); + if (!skin) + return; + + object_skin_set_matrix_buffer(skin, matrices, ex_data_matrices, rctx->matrix_buffer, mat, global_mat); + + vec4 texture_color_coeff; + vec4 texture_color_offset; + vec4 texture_specular_coeff; + vec4 texture_specular_offset; + object_data* object_data = &rctx->object_data; + if (texture_data && !texture_data->field_0) { + vec4 value; + object_data_get_texture_color_coeff(object_data, &texture_color_coeff); + vec3_mult(texture_data->texture_color_coeff, *(vec3*)&texture_color_coeff, *(vec3*)&value); + value.w = 0.0f; + object_data_set_texture_color_coeff(object_data, &value); + + object_data_get_texture_color_offset(object_data, &texture_color_offset); + *(vec3*)&value = texture_data->texture_color_offset; + value.w = 0.0f; + object_data_set_texture_color_offset(object_data, &value); + + object_data_get_texture_specular_coeff(object_data, &texture_specular_coeff); + vec3_mult(texture_data->texture_specular_coeff, *(vec3*)&texture_specular_coeff, *(vec3*)&value); + value.w = 0.0f; + object_data_set_texture_specular_coeff(object_data, &value); + + object_data_get_texture_specular_offset(object_data, &texture_specular_offset); + *(vec3*)&value = texture_data->texture_specular_offset; + value.w = 0.0f; + object_data_set_texture_specular_offset(object_data, &value); + } + + size_t texture_pattern_count = texture_pattern ? texture_pattern->end - texture_pattern->begin : 0; + if (texture_pattern && texture_pattern_count) + object_data_set_texture_pattern(object_data, (int32_t)texture_pattern_count, texture_pattern->begin); + + if (fabsf(alpha - 1.0f) > 0.000001f) + draw_task_add_draw_object_by_object_info_alpha_bone_mat(rctx, global_mat, obj_info, alpha, rctx->matrix_buffer); + else + draw_task_add_draw_object_by_object_info_bone_mat(rctx, global_mat, obj_info, rctx->matrix_buffer); + + if (texture_pattern && texture_pattern_count) + object_data_set_texture_pattern(object_data, 0, 0); + + if (texture_data && !texture_data->field_0) { + object_data_set_texture_color_coeff(object_data, &texture_color_coeff); + object_data_set_texture_color_offset(object_data, &texture_color_offset); + object_data_set_texture_specular_coeff(object_data, &texture_specular_coeff); + object_data_set_texture_specular_offset(object_data, &texture_specular_offset); + } +} + +inline bool draw_task_add_draw_object_by_object_info_opaque(render_context* rctx, mat4* mat, + object_info obj_info) { + return draw_task_add_draw_object_by_object_info(rctx, + mat, obj_info, (vec4*)&vec4_identity, 0, 0, 0, 0, false); +} + +void draw_task_sort(render_context* rctx, draw_object_type type, int32_t compare_func) { + vector_ptr_draw_task* vec = &rctx->object_data.draw_task_array[type]; + if (vec->end - vec->begin < 1) + return; + + mat4 mat; + vec3 center; + object_data* object_data = &rctx->object_data; + for (draw_task** i = vec->begin; i != vec->end; i++) { + draw_task* task = *i; + mat4u_to_mat4(&task->mat, &mat); + mat4_get_translation(&mat, ¢er); + if (task->type == DRAW_TASK_TYPE_OBJECT) { + obj_mesh_flags mesh_flags = task->data.object.mesh->flags; + if (mesh_flags & OBJECT_MESH_BILLBOARD) { + model_mat_face_camera_view(&rctx->camera->view, &mat, &mat);} + else if (mesh_flags & OBJECT_MESH_BILLBOARD_Y_AXIS) + model_mat_face_camera_position(&rctx->camera->view, &mat, &mat); + else { + object_sub_mesh* sub_mesh = task->data.object.sub_mesh; + if (task->data.object.mat_count <= 0 || !sub_mesh->bone_indices_count) + mat4_mult_vec3_trans(&mat, &sub_mesh->bounding_sphere.center, ¢er); + else { + vec3 center_sum = vec3_null; + for (int32_t j = 0; j < sub_mesh->bone_indices_count; j++) { + center = sub_mesh->bounding_sphere.center; + mat4u_to_mat4(&task->data.object.mats[j], &mat); + mat4_mult_vec3_trans(&mat, ¢er, ¢er); + vec3_add(center_sum, center, center_sum); + } + vec3_mult_scalar(center_sum, 1.0f / (float_t)sub_mesh->bone_indices_count, center); + } + } + task->bounding_radius = task->data.object.mesh->bounding_sphere.radius; + } + + //mat4_mult_vec3_trans(&rctx->camera->view, ¢er, ¢er); + //task->depth = center.z; + task->depth = rctx->camera->view_point.z - center.z; + } + + switch (compare_func) { + case 0: + for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) + for (draw_task** j = i + 1; j != vec->end; j++) + if ((*i)->depth > (*j)->depth) { + draw_task* temp = *i; + *i = *j; + *j = temp; + } + break; + case 1: + for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) + for (draw_task** j = i + 1; j != vec->end; j++) + if ((*i)->depth < (*j)->depth) { + draw_task* temp = *i; + *i = *j; + *j = temp; + } + break; + case 2: + for (draw_task** i = vec->begin; i != &vec->end[-1]; i++) + for (draw_task** j = i + 1; j != vec->end; j++) + if ((*i)->bounding_radius < (*j)->bounding_radius) { + draw_task* temp = *i; + *i = *j; + *j = temp; + } + break; + } +} + +int32_t object_axis_aligned_bounding_box_check_visibility( + object_axis_aligned_bounding_box* aabb, camera* cam, mat4* mat) { + vec3 size; + vec3 points[8]; + vec3_xor(aabb->size, ((vec3){ 0.0f, 0.0f, 0.0f }), size); + vec3_add(aabb->center, size, points[0]); + vec3_xor(aabb->size, ((vec3){ -0.0f, -0.0f, -0.0f }), size); + vec3_add(aabb->center, size, points[1]); + vec3_xor(aabb->size, ((vec3){ -0.0f, 0.0f, 0.0f }), size); + vec3_add(aabb->center, size, points[2]); + vec3_xor(aabb->size, ((vec3){ 0.0f, -0.0f, -0.0f }), size); + vec3_add(aabb->center, size, points[3]); + vec3_xor(aabb->size, ((vec3){ 0.0f, -0.0f, 0.0f }), size); + vec3_add(aabb->center, size, points[4]); + vec3_xor(aabb->size, ((vec3){ -0.0f, 0.0f, -0.0f }), size); + vec3_add(aabb->center, size, points[5]); + vec3_xor(aabb->size, ((vec3){ 0.0f, 0.0f, -0.0f }), size); + vec3_add(aabb->center, size, points[6]); + vec3_xor(aabb->size, ((vec3){ -0.0f, -0.0f, 0.0f }), size); + vec3_add(aabb->center, size, points[7]); + + mat4 view_mat; + mat4_mult(mat, &cam->view, &view_mat); + for (int32_t i = 0; i < 8; i++) + mat4_mult_vec3_trans(&view_mat, &points[i], &points[i]); + + vec4 v2[6]; + *(vec3*)&v2[0] = (vec3){ 0.0f, 0.0f, -1.0f }; + v2[0].w = (float_t)-cam->min_distance; + *(vec3*)&v2[1] = cam->field_1E4; + v2[1].w = 0.0f; + *(vec3*)&v2[2] = cam->field_1F0; + v2[2].w = 0.0f; + *(vec3*)&v2[3] = cam->field_1FC; + v2[3].w = 0.0f; + *(vec3*)&v2[4] = cam->field_208; + v2[4].w = 0.0f; + *(vec3*)&v2[5] = (vec3){ 0.0f, 0.0f, 1.0f }; + v2[5].w = (float_t)cam->max_distance; + + for (int32_t i = 0; i < 6; i++) + for (int32_t j = 0; j < 8; j++) { + float_t v34 = 0.0f; + vec3_dot(*(vec3*)&v2[i], points[j], v34); + v34 += v2[i].w; + if (v34 > 0.0f) + break; + + if (j == 7) + return 0; + } + return 1; +} + +int32_t object_bounding_sphere_check_visibility(object_bounding_sphere* sphere, + object_data* object_data, camera* cam, mat4* mat) { + if (object_data->object_bounding_sphere_check_func) + return object_data->object_bounding_sphere_check_func(sphere); + + vec3 center; + mat4_mult_vec3_trans(mat, &sphere->center, ¢er); + mat4_mult_vec3_trans(&cam->view, ¢er, ¢er); + float_t radius = mat4_get_max_scale(mat) * sphere->radius; + + double_t min_depth = (double_t)center.z - (double_t)radius; + double_t max_depth = (double_t)center.z + (double_t)radius; + if (-cam->min_distance < min_depth || -cam->max_distance > max_depth) + return 0; + + float_t v5; + vec3_dot(cam->field_1E4, center, v5); + if (v5 < -radius) + return 0; + + float_t v6; + vec3_dot(cam->field_1F0, center, v6); + if (v6 < -radius) + return 0; + + float_t v7; + vec3_dot(cam->field_1FC, center, v7); + if (v7 < -radius) + return 0; + + float_t v8; + vec3_dot(cam->field_208, center, v8); + if (v8 < -radius) + return 0; + + if (-cam->min_distance >= max_depth && -cam->max_distance <= min_depth + && v5 >= radius && v6 >= radius && v7 >= radius && v8 >= radius) + return 1; + return 2; +} + +inline static void draw_task_add(render_context* rctx, draw_object_type type, draw_task* task) { + vector_ptr_draw_task_push_back(&rctx->object_data.draw_task_array[type], &task); +} + +inline static void draw_task_object_init(draw_task* task, object_data* object_data, mat4* mat, + float_t bounding_radius, object_sub_mesh* sub_mesh, object_mesh* mesh, object_material_data* material, + uint32_t* textures, int32_t mat_count, mat4u* mats, GLuint array_buffer, + GLuint element_array_buffer, vec4* blend_color, int32_t morph_array_buffer, + int32_t instances_count, mat4* instances_mat, void(*draw_object_func)(draw_object*)) { + task->type = DRAW_TASK_TYPE_OBJECT; + mat4_to_mat4u(mat, &task->mat); + task->bounding_radius = bounding_radius; + task->data.object.mesh = mesh; + task->data.object.morph_value = object_data->morph.value; + task->data.object.material = material; + task->data.object.sub_mesh = sub_mesh; + task->data.object.textures = textures; + task->data.object.mat_count = mat_count; + task->data.object.mats = mats; + task->data.object.array_buffer = array_buffer; + task->data.object.element_array_buffer = element_array_buffer; + task->data.object.morph_array_buffer = morph_array_buffer; + + draw_object* draw = &task->data.object; + draw->texture_pattern_count = object_data->texture_pattern_count; + for (int32_t i = 0; i < object_data->texture_pattern_count && i < TEXTURE_PATTERN_COUNT; i++) + draw->texture_pattern_array[i] = object_data->texture_pattern_array[i]; + + draw->texture_transform_count = object_data->texture_transform_count; + for (int32_t i = 0; i < object_data->texture_transform_count && i < TEXTURE_TRANSFORM_COUNT; i++) + draw->texture_transform_array[i] = object_data->texture_transform_array[i]; + + if (blend_color) { + draw->set_blend_color = true; + vec4_to_vec4u(*blend_color, draw->blend_color); + } + else { + draw->set_blend_color = false; + draw->blend_color = vec4u_identity; + } + + draw->chara_color = object_data->chara_color; + draw->self_shadow = object_data->draw_task_flags & (DRAW_TASK_8 | DRAW_TASK_4) ? 1 : 0; + draw->shadow = object_data->shadow_type; + vec4_to_vec4u(object_data->texture_color_coeff, draw->texture_color_coeff); + draw->texture_color_coeff.w = object_data->wet_param; + vec4_to_vec4u(object_data->texture_color_offset, draw->texture_color_offset); + vec4_to_vec4u(object_data->texture_specular_coeff, draw->texture_specular_coeff); + vec4_to_vec4u(object_data->texture_specular_offset, draw->texture_specular_offset); + draw->instances_count = instances_count; + draw->instances_mat = instances_mat; + draw->draw_object_func = draw_object_func; +} + +inline static void draw_task_object_translucent_init(draw_task* task, mat4* mat, + draw_task_object_translucent* object) { + task->type = DRAW_TASK_TYPE_OBJECT_TRANSLUCENT; + mat4_to_mat4u(mat, &task->mat); + task->data.object_translucent = *object; +} + +inline static int32_t draw_task_translucent_sort_count_layers(render_context* rctx, + int32_t* alpha_array, draw_object_type opaque, + draw_object_type transparent, draw_object_type translucent) { + bool arr[256] = { 0 }; + + draw_task_translucent_sort_has_objects(rctx, arr, opaque); + draw_task_translucent_sort_has_objects(rctx, arr, transparent); + draw_task_translucent_sort_has_objects(rctx, arr, translucent); + + int32_t count = 0; + for (int32_t i = 0xFF; i >= 1; i--) + if (arr[i]) { + count++; + *alpha_array++ = i; + } + return count; +} + +inline static void draw_task_translucent_sort_has_objects(render_context* rctx, bool* arr, draw_object_type type) { + vector_ptr_draw_task* vec = &rctx->object_data.draw_task_array[type]; + for (draw_task** i = vec->begin; i != vec->end; i++) { + draw_task* task = *i; + if (task->type != DRAW_TASK_TYPE_OBJECT) + continue; + + int32_t alpha = (int32_t)(task->data.object.blend_color.w * 255.0f); + alpha = clamp(alpha, 0, 255); + arr[alpha] = true; + } +} diff --git a/src/CRE/draw_task.h b/src/CRE/draw_task.h new file mode 100644 index 00000000..5837711d --- /dev/null +++ b/src/CRE/draw_task.h @@ -0,0 +1,47 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/vec.h" +#include "draw_object.h" +#include "draw_primitive.h" + +extern void draw_task_draw_objects_by_type(render_context* rctx, draw_object_type type, + int32_t a2, int32_t a3, bool a4, int32_t alpha); +extern void draw_task_draw_objects_by_type_translucent(render_context* rctx, bool opaque_enable, + bool transparent_enable, bool translucent_enable, draw_object_type opaque, + draw_object_type transparent, draw_object_type translucent); +extern int32_t draw_task_get_count(render_context* rctx, draw_object_type type); +extern bool draw_task_add_draw_object(render_context* rctx, object* obj, + object_mesh_vertex_buffer* obj_vertex_buf, object_mesh_index_buffer* obj_index_buf, mat4* mat, + uint32_t* textures, vec4* blend_color, mat4* bone_mat, object* object_morph, + object_mesh_vertex_buffer* obj_morph_vertex_buf, int32_t instances_count, + mat4* instances_mat, void(*draw_object_func)(draw_object*), bool enable_bone_mat); +extern bool draw_task_add_draw_object_by_object_info(render_context* rctx, mat4* mat, + object_info obj_info, vec4* blend_color, mat4* bone_mat, int32_t instances_count, + mat4* instances_mat, void(*draw_object_func)(draw_object*), bool enable_bone_mat); +extern bool draw_task_add_draw_object_by_object_info_alpha(render_context* rctx, mat4* mat, + object_info obj_info, float_t alpha); +extern bool draw_task_add_draw_object_by_object_info_alpha_bone_mat(render_context* rctx, mat4* mat, + object_info obj_info, float_t alpha, mat4* bone_mat); +extern bool draw_task_add_draw_object_by_object_info_bone_mat(render_context* rctx, mat4* mat, + object_info obj_info, mat4* bone_mat); +extern bool draw_task_add_draw_object_by_object_info_color(render_context* rctx, mat4* mat, + object_info obj_info, float_t r, float_t g, float_t b, float_t a); +extern bool draw_task_add_draw_object_by_object_info_color_vec4(render_context* rctx, mat4* mat, + object_info obj_info, vec4* blend_color); +extern void draw_task_add_draw_object_by_object_info_object_skin(render_context* rctx, object_info obj_info, + vector_texture_pattern_struct* texture_pattern, texture_data_struct* texture_data, float_t alpha, + mat4* matrices, mat4* ex_data_matrices, mat4* mat, mat4* global_mat); +extern bool draw_task_add_draw_object_by_object_info_opaque(render_context* rctx, mat4* mat, + object_info obj_info); +extern void draw_task_sort(render_context* rctx, draw_object_type type, int32_t compare_func); +extern int32_t object_axis_aligned_bounding_box_check_visibility( + object_axis_aligned_bounding_box* aabb, camera* cam, mat4* mat); +extern int32_t object_bounding_sphere_check_visibility(object_bounding_sphere* sphere, + object_data* object_data, camera* cam, mat4* mat); diff --git a/src/CRE/fbo.c b/src/CRE/fbo.c index 406ede53..1fc0fa12 100644 --- a/src/CRE/fbo.c +++ b/src/CRE/fbo.c @@ -4,6 +4,7 @@ */ #include "fbo.h" +#include "gl_state.h" void fbo_init(fbo_struct* fbo, int32_t width, int32_t height, GLuint* color_textures, int32_t count, GLuint depth_texture) { @@ -49,3 +50,13 @@ void fbo_free(fbo_struct* fbo) { glDeleteFramebuffers(1, &fbo->fbo); free(fbo->textures); } + +inline void fbo_blit(GLuint src_fbo, GLuint dst_fbo, + GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, + GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter) { + gl_state_bind_framebuffer(dst_fbo); + glBindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo); + glBlitFramebuffer(src_x0, src_y0, src_x1, src_y1, + dst_x0, dst_y0, dst_x1, dst_y1, mask, filter); +} diff --git a/src/CRE/fbo.h b/src/CRE/fbo.h index 44b26022..30a647ad 100644 --- a/src/CRE/fbo.h +++ b/src/CRE/fbo.h @@ -23,3 +23,6 @@ typedef struct fbo_struct { extern void fbo_init(fbo_struct* fbo, int32_t width, int32_t height, GLuint* color_textures, int32_t count, GLuint depth_texture); extern void fbo_free(fbo_struct* fbo); +extern void fbo_blit(GLuint src_fbo, GLuint dst_fbo, + GLint src_x0, GLint src_y0, GLint src_x1, GLint src_y1, + GLint dst_x0, GLint dst_y0, GLint dst_x1, GLint dst_y1, GLbitfield mask, GLenum filter); diff --git a/src/CRE/fbo_hdr.c b/src/CRE/fbo_hdr.c deleted file mode 100644 index 139d1a26..00000000 --- a/src/CRE/fbo_hdr.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "fbo_hdr.h" -#include "fbo_helper.h" - -static void fbo_hdr_bind_fbo(fbo_hdr* hfbo, vec2i* res); - -fbo_hdr* fbo_hdr_init() { - fbo_hdr* hfbo = force_malloc(sizeof(fbo_hdr)); - glGenSamplers(1, &hfbo->sampler); - return hfbo; -} - -void fbo_hdr_initialize(fbo_hdr* hfbo, vec2i* res, int32_t vao, shader_glsl* fxaa_shader) { - if (!hfbo) - return; - - hfbo->vao = vao; - hfbo->fxaa_shader = fxaa_shader; - fbo_hdr_bind_fbo(hfbo, res); -} - -void fbo_hdr_resize(fbo_hdr* hfbo, vec2i* res) { - if (!hfbo) - return; - - fbo_hdr_bind_fbo(hfbo, res); -} - -void fbo_hdr_draw_fxaa(fbo_hdr* hfbo, int32_t preset) { - if (!hfbo) - return; - - gl_state_bind_framebuffer(hfbo->buf.fbos[0]); - shader_glsl_use(&hfbo->fxaa_shader[clamp(preset, 3, 5) - 3]); - gl_state_active_bind_texture_2d(0, hfbo->color.color_texture->texture); - gl_state_bind_sampler(0, hfbo->sampler); - gl_state_bind_vertex_array(hfbo->vao); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - fbo_helper_blit(hfbo->buf.fbos[0], GL_COLOR_ATTACHMENT0, - hfbo->color.fbos[0], GL_COLOR_ATTACHMENT0, - 0, 0, hfbo->width, hfbo->height, - 0, 0, hfbo->width, hfbo->height, GL_COLOR_BUFFER_BIT, GL_LINEAR); -} - -void fbo_hdr_set_fbo_begin(fbo_hdr* hfbo) { - gl_state_bind_framebuffer(hfbo->buf.fbos[0]); -} - -void fbo_hdr_set_fbo_end(fbo_hdr* hfbo) { - fbo_helper_blit(hfbo->buf.fbos[0], GL_COLOR_ATTACHMENT0, - hfbo->color.fbos[0], GL_COLOR_ATTACHMENT0, - 0, 0, hfbo->width, hfbo->height, - 0, 0, hfbo->width, hfbo->height, GL_COLOR_BUFFER_BIT, GL_LINEAR); -} - -void fbo_hdr_dispose(fbo_hdr* hfbo) { - if (!hfbo) - return; - - render_texture_free(&hfbo->color); - render_texture_free(&hfbo->back_2d); - render_texture_free(&hfbo->buf); - free(hfbo); -} - -static void fbo_hdr_bind_fbo(fbo_hdr* hfbo, vec2i* res) { - hfbo->width = max(res->x, 1); - hfbo->height = max(res->y, 1); - - render_texture_init(&hfbo->color, hfbo->width, hfbo->height, 0, GL_R11F_G11F_B10F, GL_DEPTH24_STENCIL8); - render_texture_init(&hfbo->back_2d, hfbo->width, hfbo->height, 0, GL_R11F_G11F_B10F, 0); - render_texture_init(&hfbo->buf, hfbo->width, hfbo->height, 0, GL_R11F_G11F_B10F, 0); - - glSamplerParameteri(hfbo->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(hfbo->sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(hfbo->sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(hfbo->sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} diff --git a/src/CRE/fbo_hdr.h b/src/CRE/fbo_hdr.h deleted file mode 100644 index f3fe55a3..00000000 --- a/src/CRE/fbo_hdr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/vec.h" -#include "shader_glsl.h" -#include "fbo.h" -#include "render_texture.h" - -typedef struct fbo_hdr { - int32_t width; - int32_t height; - render_texture color; - render_texture back_2d; - render_texture buf; - GLuint sampler; - GLuint vao; - shader_glsl* fxaa_shader; - bool fxaa; -} fbo_hdr; - -extern fbo_hdr* fbo_hdr_init(); -extern void fbo_hdr_initialize(fbo_hdr* hfbo, vec2i* res, int32_t vao, shader_glsl* fxaa_shader); -extern void fbo_hdr_resize(fbo_hdr* hfbo, vec2i* res); -extern void fbo_hdr_draw_fxaa(fbo_hdr* hfbo, int32_t preset); -extern void fbo_hdr_set_fbo_begin(fbo_hdr* hfbo); -extern void fbo_hdr_set_fbo_end(fbo_hdr* hfbo); -extern void fbo_hdr_dispose(fbo_hdr* hfbo); diff --git a/src/CRE/fbo_helper.c b/src/CRE/fbo_helper.c deleted file mode 100644 index 180e8aa5..00000000 --- a/src/CRE/fbo_helper.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "fbo_helper.h" - -void fbo_helper_blit(int32_t src_fbo, GLenum src_mode, int32_t dst_fbo, GLenum dst_mode, - int32_t src_x0, int32_t src_y0, int32_t src_x1, int32_t src_y1, - int32_t dst_x0, int32_t dst_y0, int32_t dst_x1, int32_t dst_y1, GLbitfield mask, GLenum filter) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo); - glReadBuffer(src_mode); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo); - glDrawBuffer(dst_mode); - glBlitFramebuffer(src_x0, src_y0, src_x1, src_y1, - dst_x0, dst_y0, dst_x1, dst_y1, mask, filter); -} - -void fbo_helper_gen_texture_image(int32_t tex, int32_t width, int32_t height, - GLenum internal_format, GLenum format, GLenum type, int32_t attachment) { - gl_state_bind_texture_2d(tex); - glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, type, 0); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (attachment >= 0 && attachment <= 15) - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachment, tex, 0); - else if (attachment == 16) - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, tex, 0); -} - -void fbo_helper_get_error_code() { - GLenum code = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (code != GL_FRAMEBUFFER_COMPLETE) - printf("Framebuffer error: %04X\n", code); -} \ No newline at end of file diff --git a/src/CRE/fbo_helper.h b/src/CRE/fbo_helper.h deleted file mode 100644 index 66f815ab..00000000 --- a/src/CRE/fbo_helper.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "gl_state.h" -#include "static_var.h" -#include - -extern void fbo_helper_blit(int32_t src_fbo, GLenum src_mode, int32_t dst_fbo, GLenum dst_mode, - int32_t src_x0, int32_t src_y0, int32_t src_x1, int32_t src_y1, - int32_t dst_x0, int32_t dst_y0, int32_t dst_x1, int32_t dst_y1, GLbitfield mask, GLenum filter); -extern void fbo_helper_gen_texture_image(int32_t tex, int32_t width, int32_t height, - GLenum internal_format, GLenum format, GLenum type, int32_t attachment); -extern void fbo_helper_get_error_code(); diff --git a/src/CRE/fbo_pp.c b/src/CRE/fbo_pp.c deleted file mode 100644 index 24cee7df..00000000 --- a/src/CRE/fbo_pp.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "fbo_pp.h" -#include "fbo_helper.h" -#include "../KKdLib/half_t.h" -#include "shader_aft.h" - -const GLenum fbo_pp_s_attachments[] = { - GL_COLOR_ATTACHMENT0, -}; - -extern shader_set_data shaders_aft; - -static void fbo_pp_bind_fbo(fbo_pp* pfbo, vec2i* res); - -fbo_pp* fbo_pp_init() { - fbo_pp* pfbo = force_malloc(sizeof(fbo_pp)); - glGenFramebuffers(11, pfbo->fbo); - glGenTextures(10, pfbo->tex); - glGenTextures(1, &pfbo->exposure_history); - glGenTextures(1, &pfbo->tone_map); - return pfbo; -} - -void fbo_pp_initialize(fbo_pp* pfbo, vec2i* res, int32_t vao, shader_glsl* b_shader) { - if (!pfbo) - return; - - pfbo->vao = vao; - pfbo->exposure_history_counter = 0; - pfbo->b_shader = b_shader; - - shader_glsl_set_vec2_array(&pfbo->b_shader[4], "direction", 6, ((vec2[]) { - { 1.0f / 128.0f, 0.0f }, - { 2.0f / 128.0f, 0.0f }, - { 3.0f / 128.0f, 0.0f }, - { 4.0f / 128.0f, 0.0f }, - { 5.0f / 128.0f, 0.0f }, - { 6.0f / 128.0f, 0.0f }, - })); - shader_glsl_set_vec2_array(&pfbo->b_shader[5], "direction", 6, ((vec2[]) { - { 1.0f / 64.0f, 0.0f }, - { 2.0f / 64.0f, 0.0f }, - { 3.0f / 64.0f, 0.0f }, - { 4.0f / 64.0f, 0.0f }, - { 5.0f / 64.0f, 0.0f }, - { 6.0f / 64.0f, 0.0f }, - })); - shader_glsl_set_vec2_array(&pfbo->b_shader[6], "direction", 6, ((vec2[]) { - { 1.0f / 32.0f, 0.0f}, - { 2.0f / 32.0f, 0.0f }, - { 3.0f / 32.0f, 0.0f }, - { 4.0f / 32.0f, 0.0f }, - { 5.0f / 32.0f, 0.0f }, - { 6.0f / 32.0f, 0.0f }, - })); - shader_glsl_set_vec2_array(&pfbo->b_shader[7], "direction", 6, ((vec2[]) { - { 0.0f, 1.0f / 72.0f }, - { 0.0f, 2.0f / 72.0f }, - { 0.0f, 3.0f / 72.0f }, - { 0.0f, 4.0f / 72.0f }, - { 0.0f, 5.0f / 72.0f }, - { 0.0f, 6.0f / 72.0f }, - })); - shader_glsl_set_vec2_array(&pfbo->b_shader[8], "direction", 6, ((vec2[]) { - { 0.0f, 1.0f / 36.0f }, - { 0.0f, 2.0f / 36.0f }, - { 0.0f, 3.0f / 36.0f }, - { 0.0f, 4.0f / 36.0f }, - { 0.0f, 5.0f / 36.0f }, - { 0.0f, 6.0f / 36.0f }, - })); - shader_glsl_set_vec2_array(&pfbo->b_shader[9], "direction", 6, ((vec2[]) { - { 0.0f, 1.0f / 18.0f }, - { 0.0f, 2.0f / 18.0f }, - { 0.0f, 3.0f / 18.0f }, - { 0.0f, 4.0f / 18.0f }, - { 0.0f, 5.0f / 18.0f }, - { 0.0f, 6.0f / 18.0f }, - })); - shader_glsl_set_vec4_value(&pfbo->b_shader[10], "res", - 256.0f, 144.0f, 1.0f / 256.0f, 1.0f / 144.0f); - - glGenFramebuffers(11, pfbo->fbo); - glGenTextures(11, pfbo->tex); - - gl_state_bind_framebuffer(pfbo->fbo[0]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[0], 256, 144, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[1]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[1], 128, 72, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[2]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[2], 128, 72, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[3]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[3], 64, 36, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[4]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[4], 64, 36, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[5]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[5], 32, 18, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[6]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[6], 32, 18, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[7]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[7], 8, 8, GL_R32F, GL_RED, GL_FLOAT, 0); - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, (GLint[]) { GL_RED, GL_RED, GL_RED, GL_ONE }); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[8]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[8], 256, 144, - GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, 0); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[9]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->exposure_history, 32, 1, GL_R32F, GL_RED, GL_FLOAT, 0); - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, (GLint[]){ GL_RED, GL_RED, GL_RED, GL_ONE }); - fbo_helper_get_error_code(); - - gl_state_bind_framebuffer(pfbo->fbo[10]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(pfbo->tex[9], 1, 1, GL_R32F, GL_RED, GL_FLOAT, 0); - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, (GLint[]) { GL_RED, GL_RED, GL_RED, GL_ONE }); - fbo_helper_get_error_code(); - gl_state_bind_texture_2d(0); - - fbo_pp_bind_fbo(pfbo, res); -} - -void fbo_pp_resize(fbo_pp* pfbo, vec2i* res) { - if (!pfbo) - return; - - fbo_pp_bind_fbo(pfbo, res); -} - -void fbo_pp_tone_map_set(fbo_pp* pfbo, vec2* tone_map_data, int32_t count) { - gl_state_bind_texture_2d(0); - glBindTexture(GL_TEXTURE_1D, pfbo->tone_map); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RG16F, count, 0, GL_RG, GL_FLOAT, tone_map_data); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteriv(GL_TEXTURE_1D, GL_TEXTURE_SWIZZLE_RGBA, (GLint[]) { GL_RED, GL_RED, GL_RED, GL_GREEN }); - glBindTexture(GL_TEXTURE_1D, 0); -} - -void fbo_pp_draw(fbo_pp* pfbo, tone_map* tm, - texture* in_tex, texture* light_proj_tex, texture* back_2d_tex, - void* out_fbo, void(*out_fbo_func_begin)(void*), void(*out_fbo_func_end)(void*)) { - gl_state_bind_vertex_array(pfbo->vao); - int i = 0; - if (pfbo->count_down > 0) { - shader_glsl_use(&pfbo->b_shader[0]); - for (; i < pfbo->count_down; i++) { - glViewport(0, 0, pfbo->res_down[i].x, pfbo->res_down[i].y); // 0 - gl_state_bind_framebuffer(pfbo->fbo_down[i]); - gl_state_active_bind_texture_2d(0, i == 0 ? in_tex->texture : pfbo->tex_down[i - 1]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - } - i--; - } - - glViewport(0, 0, 256, 144); // 1 - gl_state_bind_framebuffer(pfbo->fbo[0]); - shader_glsl_use(&pfbo->b_shader[1]); - gl_state_active_bind_texture_2d(0, pfbo->count_down > 0 ? pfbo->tex_down[i] : in_tex->target); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 128, 72); // 2 - gl_state_bind_framebuffer(pfbo->fbo[1]); - shader_glsl_use(&pfbo->b_shader[2]); - gl_state_active_bind_texture_2d(0, pfbo->tex[0]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 64, 36); // 3 - gl_state_bind_framebuffer(pfbo->fbo[3]); - shader_glsl_use(&pfbo->b_shader[2]); - gl_state_active_bind_texture_2d(0, pfbo->tex[1]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 32, 18); // 4 - gl_state_bind_framebuffer(pfbo->fbo[5]); - shader_glsl_use(&pfbo->b_shader[2]); - gl_state_active_bind_texture_2d(0, pfbo->tex[3]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 8, 8); // 5 - gl_state_bind_framebuffer(pfbo->fbo[7]); - shader_glsl_use(&pfbo->b_shader[3]); - gl_state_active_bind_texture_2d(0, pfbo->tex[5]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 128, 72); // 6 - gl_state_bind_framebuffer(pfbo->fbo[2]); - shader_glsl_use(&pfbo->b_shader[4]); - gl_state_active_bind_texture_2d(0, pfbo->tex[1]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 64, 36); // 7 - gl_state_bind_framebuffer(pfbo->fbo[4]); - shader_glsl_use(&pfbo->b_shader[5]); - gl_state_active_bind_texture_2d(0, pfbo->tex[3]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 32, 18); // 8 - gl_state_bind_framebuffer(pfbo->fbo[6]); - shader_glsl_use(&pfbo->b_shader[6]); - gl_state_active_bind_texture_2d(0, pfbo->tex[5]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 128, 72); // 9 - gl_state_bind_framebuffer(pfbo->fbo[1]); - shader_glsl_use(&pfbo->b_shader[7]); - gl_state_active_bind_texture_2d(0, pfbo->tex[2]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 64, 36); // 10 - gl_state_bind_framebuffer(pfbo->fbo[3]); - shader_glsl_use(&pfbo->b_shader[8]); - gl_state_active_bind_texture_2d(0, pfbo->tex[4]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 32, 18); // 11 - gl_state_bind_framebuffer(pfbo->fbo[5]); - shader_glsl_use(&pfbo->b_shader[9]); - gl_state_active_bind_texture_2d(0, pfbo->tex[6]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 256, 144); // 12 - gl_state_bind_framebuffer(pfbo->fbo[8]); - shader_glsl_use(&pfbo->b_shader[10]); - gl_state_active_bind_texture_2d(0, pfbo->tex[0]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 256, 144); // 13 - gl_state_bind_framebuffer(pfbo->fbo[0]); - shader_glsl_use(&pfbo->b_shader[11]); - gl_state_active_bind_texture_2d(0, pfbo->tex[8]); - gl_state_active_bind_texture_2d(1, pfbo->tex[1]); - gl_state_active_bind_texture_2d(2, pfbo->tex[3]); - gl_state_active_bind_texture_2d(3, pfbo->tex[5]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(pfbo->exposure_history_counter, 0, 1, 1); // 14 - gl_state_bind_framebuffer(pfbo->fbo[9]); - shader_glsl_use(&pfbo->b_shader[12]); - gl_state_active_bind_texture_2d(0, pfbo->tex[7]); - gl_state_active_bind_texture_2d(1, pfbo->tex[3]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glViewport(0, 0, 1, 1); // 15 - gl_state_bind_framebuffer(pfbo->fbo[10]); - shader_glsl_use(&pfbo->b_shader[13]); - gl_state_active_bind_texture_2d(0, pfbo->exposure_history); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - mat4 lens_flare_mat = mat4_identity; - mat4 lens_shaft_mat = mat4_identity; - mat4_scale_mult(&lens_flare_mat, 1.0f, (float_t)pfbo->res.y / (float_t)pfbo->res.x, 1.0, &lens_flare_mat); - mat4_scale_mult(&lens_shaft_mat, 1.0f, (float_t)pfbo->res.y / (float_t)pfbo->res.x, 1.0, &lens_shaft_mat); - - uniform_value[U16] = 0; - uniform_value[U_TONE_MAP] = tm->tone_map_method; - uniform_value[U_FLARE] = 0; - uniform_value[U_SCENE_FADE] = tm->scene_fade_alpha > 0.009999999f ? 1 : 0; - uniform_value[U_AET_BACK] = 0; - uniform_value[U_LIGHT_PROJ] = 0; - uniform_value[U_NPR] = 0; - uniform_value[U25] = 0; - - glViewport(0, 0, pfbo->res.x, pfbo->res.y); // 16 - out_fbo_func_begin(out_fbo); - shader_set(&shaders_aft, SHADER_AFT_TONEMAP); - shader_state_matrix_set_mvp_separate(&shaders_aft, - (mat4*)&mat4_identity, (mat4*)&mat4_identity, (mat4*)&mat4_identity); - shader_state_matrix_set_texture(&shaders_aft, 4, &lens_flare_mat); - shader_state_matrix_set_texture(&shaders_aft, 5, &lens_shaft_mat); - shader_local_vert_set_ptr(&shaders_aft, 1, &tm->data.p_exposure); - shader_local_frag_set_ptr(&shaders_aft, 1, &tm->data.p_flare_coef); - shader_local_frag_set_ptr(&shaders_aft, 2, &tm->data.p_fade_color); - shader_local_frag_set_ptr(&shaders_aft, 4, &tm->data.p_tone_scale); - shader_local_frag_set_ptr(&shaders_aft, 5, &tm->data.p_tone_offset); - shader_local_frag_set_ptr(&shaders_aft, 6, &tm->data.p_fade_func); - shader_local_frag_set_ptr(&shaders_aft, 7, &tm->data.p_inv_tone); - gl_state_active_bind_texture_2d(0, in_tex->texture); - gl_state_active_bind_texture_2d(1, pfbo->tex[0]); - gl_state_active_bind_texture_2d(2, 0); - gl_state_active_texture(2); - glBindTexture(GL_TEXTURE_1D, pfbo->tone_map); - gl_state_active_bind_texture_2d(3, pfbo->tex[9]); - if (uniform_value[U_LIGHT_PROJ]) - gl_state_active_bind_texture_2d(6, light_proj_tex->target); - else if (uniform_value[U_AET_BACK]) - gl_state_active_bind_texture_2d(6, back_2d_tex->target); - shader_draw_arrays(&shaders_aft, GL_TRIANGLE_STRIP, 0, 3); - gl_state_active_texture(2); - glBindTexture(GL_TEXTURE_1D, 0); - out_fbo_func_end(out_fbo); - - pfbo->exposure_history_counter++; - pfbo->exposure_history_counter %= 32; -} - -void fbo_pp_dispose(fbo_pp* pfbo) { - if (!pfbo) - return; - - glDeleteFramebuffers(pfbo->full_count_down, pfbo->fbo_down); - glDeleteTextures(pfbo->full_count_down, pfbo->tex_down); - glDeleteFramebuffers(11, pfbo->fbo); - glDeleteTextures(10, pfbo->tex); - glGenTextures(1, &pfbo->exposure_history); - glGenTextures(1, &pfbo->tone_map); - free(pfbo->fbo_down); - free(pfbo->tex_down); - free(pfbo->res_down); - free(pfbo); -} - -static void fbo_pp_bind_fbo(fbo_pp* pfbo, vec2i* res) { - - pfbo->res.x = res->x > 1 ? res->x : 1; - pfbo->res.y = res->y > 1 ? res->y : 1; - - int i = 0; - vec2i r = pfbo->res; - while (r.x > 512 && r.y > 288) { - r.x /= 2; - r.y /= 2; - i++; - } - - if (i < pfbo->full_count_down) - pfbo->full_count_down = pfbo->count_down; - else - pfbo->full_count_down = i; - - int32_t* fbo_down = pfbo->fbo_down; - int32_t* tex_down = pfbo->tex_down; - vec2i* res_down = pfbo->res_down; - - if (!fbo_down) - fbo_down = force_malloc_s(int32_t, i); - else if (pfbo->count_down < i) { - void* temp = force_malloc_s(int32_t, i); - memcpy(temp, fbo_down, sizeof(int32_t) * pfbo->count_down); - free(fbo_down); - fbo_down = temp; - } - - if (!tex_down) - tex_down = force_malloc_s(int32_t, i); - else if (pfbo->count_down < i) { - void* temp = force_malloc_s(int32_t, i); - memcpy(temp, tex_down, sizeof(int32_t) * pfbo->count_down); - free(tex_down); - tex_down = temp; - } - - if (!res_down) - res_down = force_malloc_s(vec2i, i); - else if (pfbo->count_down < i) { - void* temp = force_malloc_s(vec2i, i); - memcpy(temp, res_down, sizeof(vec2i) * pfbo->count_down); - free(res_down); - res_down = temp; - } - - pfbo->count_down = i; - - for (i = 0; i < pfbo->count_down; i++) { - if (fbo_down[i] == 0) - glGenFramebuffers(1, &fbo_down[i]); - if (tex_down[i] == 0) - glGenTextures(1, &tex_down[i]); - } - - i = 0; - r = pfbo->res; - while (r.x > 512 && r.y > 288) { - res_down[i].x = r.x /= 2; - res_down[i].y = r.y /= 2; - i++; - } - - for (i = 0; i < pfbo->count_down; i++) { - gl_state_bind_framebuffer(fbo_down[i]); - glDrawBuffers(1, fbo_pp_s_attachments); - fbo_helper_gen_texture_image(tex_down[i], res_down[i].x, res_down[i].y, - GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 0); - fbo_helper_get_error_code(); - } - - gl_state_bind_framebuffer(0); - - pfbo->fbo_down = fbo_down; - pfbo->tex_down = tex_down; - pfbo->res_down = res_down; -} diff --git a/src/CRE/fbo_pp.h b/src/CRE/fbo_pp.h deleted file mode 100644 index 2fc2d03b..00000000 --- a/src/CRE/fbo_pp.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/vec.h" -#include "post_process.h" -#include "shader_glsl.h" -#include "texture.h" - -typedef struct fbo_pp { - int32_t vao; - int32_t fbo[11]; - int32_t tex[11]; - int32_t exposure_history; - shader_glsl* b_shader; - vec2i res; - int32_t* fbo_down; - int32_t* tex_down; - vec2i* res_down; - int32_t count_down; - int32_t full_count_down; - GLuint tone_map; - int32_t exposure_history_counter; -} fbo_pp; - -extern const GLenum fbo_pp_s_attachments[]; - -extern fbo_pp* fbo_pp_init(); -extern void fbo_pp_initialize(fbo_pp* pfbo, vec2i* res, int32_t vao, shader_glsl* b_shader); -extern void fbo_pp_resize(fbo_pp* pfbo, vec2i* res); -extern void fbo_pp_tone_map_set(fbo_pp* pfbo, vec2* tone_map_data, int32_t count); -extern void fbo_pp_draw(fbo_pp* pfbo, tone_map* tm, - texture* in_tex, texture* light_proj_tex, texture* back_2d_tex, - void* out_fbo, void(*out_fbo_func_begin)(void*), void(*out_fbo_func_end)(void*)); -extern void fbo_pp_dispose(fbo_pp* pfbo); diff --git a/src/CRE/fbo_render.c b/src/CRE/fbo_render.c deleted file mode 100644 index d6e2baaf..00000000 --- a/src/CRE/fbo_render.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "fbo_render.h" -#include "fbo_helper.h" - -extern int32_t sv_samples; - -const GLenum fbo_render_attachments[] = { - GL_COLOR_ATTACHMENT0, -}; - -static void fbo_render_bind_fbo(fbo_render* rfbo, vec2i* res); - -fbo_render* fbo_render_init() { - fbo_render* rfbo = force_malloc(sizeof(fbo_render)); - return rfbo; -} - -void fbo_render_initialize(fbo_render* rfbo, vec2i* res, - int32_t vao, shader_glsl* c_shader, shader_glsl* d_shader) { - if (!rfbo) - return; - - rfbo->vao = vao; - rfbo->c_shader = c_shader; - rfbo->d_shader = d_shader; - fbo_render_bind_fbo(rfbo, res); -} - -void fbo_render_resize(fbo_render* rfbo, vec2i* res) { - if (!rfbo) - return; - - fbo_render_bind_fbo(rfbo, res); -} - -void fbo_render_draw(fbo_render* rfbo, bool depth) { - if (!rfbo) - return; - - gl_state_disable_blend(); - if (depth) { - shader_glsl_use(rfbo->d_shader); - gl_state_active_bind_texture_2d(0, rfbo->tex.color_texture->texture); - gl_state_active_bind_texture_2d(1, rfbo->tex.depth_texture->texture); - gl_state_enable_depth_test(); - gl_state_set_depth_func(GL_ALWAYS); - gl_state_set_depth_mask(GL_TRUE); - gl_state_bind_vertex_array(rfbo->vao); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - gl_state_disable_depth_test(); - gl_state_set_depth_mask(GL_FALSE); - } - else { - shader_glsl_use(rfbo->c_shader); - gl_state_active_bind_texture_2d(0, rfbo->tex.color_texture->texture); - gl_state_bind_vertex_array(rfbo->vao); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - } -} - -void fbo_render_dispose(fbo_render* rfbo) { - if (!rfbo) - return; - - render_texture_free(&rfbo->tex); - free(rfbo); -} - -static void fbo_render_bind_fbo(fbo_render* rfbo, vec2i* res) { - rfbo->res.x = res->x > 1 ? res->x : 1; - rfbo->res.y = res->y > 1 ? res->y : 1; - render_texture_init(&rfbo->tex, rfbo->res.x, rfbo->res.y, 0, GL_RGBA16F, GL_DEPTH24_STENCIL8); -} diff --git a/src/CRE/fbo_render.h b/src/CRE/fbo_render.h deleted file mode 100644 index 82c32550..00000000 --- a/src/CRE/fbo_render.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/vec.h" -#include "render_texture.h" -#include "shader_glsl.h" - -typedef struct fbo_render { - int32_t vao; - render_texture tex; - shader_glsl* c_shader; - shader_glsl* d_shader; - vec2i res; -} fbo_render; - -extern const GLenum fbo_render_attachments[]; - -extern fbo_render* fbo_render_init(); -extern void fbo_render_initialize(fbo_render* rfbo, vec2i* res, - int32_t vao, shader_glsl* c_shader, shader_glsl* d_shader); -extern void fbo_render_resize(fbo_render* rfbo, vec2i* res); -extern void fbo_render_draw(fbo_render* rfbo, bool depth); -extern void fbo_render_dispose(fbo_render* rfbo); diff --git a/src/CRE/gl_state.c b/src/CRE/gl_state.c index 13a2405b..51e67fad 100644 --- a/src/CRE/gl_state.c +++ b/src/CRE/gl_state.c @@ -5,47 +5,15 @@ #include "gl_state.h" -struct gl_state_struct { - GLuint program; - GLenum active_texture; - GLuint active_texture_index; - GLuint texture_binding_2d[32]; - GLuint texture_binding_cube_map[32]; - GLuint sampler_binding[32]; - GLboolean blend; - GLenum blend_src_rgb; - GLenum blend_src_alpha; - GLenum blend_dst_rgb; - GLenum blend_dst_alpha; - GLenum blend_mode_rgb; - GLenum blend_mode_alpha; - GLuint framebuffer_binding; - GLuint vertex_array_binding; - GLuint array_buffer_binding; - GLuint element_array_buffer_binding; - GLuint uniform_buffer_index; - GLuint uniform_buffer_binding[14]; - GLintptr uniform_buffer_offset[14]; - GLsizeiptr uniform_buffer_size[14]; - GLuint shader_storage_buffer_index; - GLuint shader_storage_buffer_binding[14]; - GLintptr shader_storage_buffer_offset[14]; - GLsizeiptr shader_storage_buffer_size[14]; - GLboolean color_mask[4]; - GLboolean cull_face; - GLenum cull_face_mode; - GLboolean depth_test; - GLenum depth_func; - GLboolean depth_mask; - GLenum polygon_front_face_mode; - GLenum polygon_back_face_mode; - GLboolean stencil_test; - GLuint stencil_mask; -} gl_state; +gl_state_struct gl_state; inline void gl_state_active_bind_texture_2d(int32_t index, GLuint texture) { if (gl_state.texture_binding_2d[index] != texture) { - gl_state_active_texture(index); + if (gl_state.active_texture_index != index) { + glActiveTexture((GLenum)(GL_TEXTURE0 + index)); + gl_state.active_texture = (GLenum)(GL_TEXTURE0 + index); + gl_state.active_texture_index = (GLuint)index; + } glBindTexture(GL_TEXTURE_2D, texture); gl_state.texture_binding_2d[index] = texture; } @@ -53,7 +21,11 @@ inline void gl_state_active_bind_texture_2d(int32_t index, GLuint texture) { inline void gl_state_active_bind_texture_cube_map(int32_t index, GLuint texture) { if (gl_state.texture_binding_cube_map[index] != texture) { - gl_state_active_texture(index); + if (gl_state.active_texture_index != index) { + glActiveTexture((GLenum)(GL_TEXTURE0 + index)); + gl_state.active_texture = (GLenum)(GL_TEXTURE0 + index); + gl_state.active_texture_index = (GLuint)index; + } glBindTexture(GL_TEXTURE_CUBE_MAP, texture); gl_state.texture_binding_cube_map[index] = texture; } @@ -81,6 +53,20 @@ inline void gl_state_bind_vertex_array(GLuint array) { } } +inline void gl_state_bind_array_buffer(GLuint buffer) { + if (gl_state.array_buffer_binding != buffer) { + glBindBuffer(GL_ARRAY_BUFFER, buffer); + gl_state.array_buffer_binding = buffer; + } +} + +inline void gl_state_bind_element_array_buffer(GLuint buffer) { + if (gl_state.element_array_buffer_binding != buffer) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); + gl_state.element_array_buffer_binding = buffer; + } +} + inline void gl_state_bind_uniform_buffer(GLuint buffer) { if (gl_state.uniform_buffer_binding[gl_state.uniform_buffer_index] != buffer) { glBindBuffer(GL_UNIFORM_BUFFER, buffer); @@ -94,6 +80,7 @@ inline void gl_state_bind_uniform_buffer_base(GLuint index, GLuint buffer) { gl_state.uniform_buffer_binding[index] = buffer; gl_state.uniform_buffer_offset[index] = 0; gl_state.uniform_buffer_size[index] = -1; + gl_state.uniform_buffer_index = index; } } @@ -136,6 +123,7 @@ inline void gl_state_bind_shader_storage_buffer_range(GLuint index, gl_state.shader_storage_buffer_binding[index] = buffer; gl_state.shader_storage_buffer_offset[index] = offset; gl_state.shader_storage_buffer_size[index] = size; + gl_state.shader_storage_buffer_index = index; } } @@ -209,8 +197,22 @@ inline void gl_state_disable_depth_test() { } } +inline void gl_state_disable_primitive_restart() { + if (!gl_state.primitive_restart) { + glDisable(GL_PRIMITIVE_RESTART); + gl_state.primitive_restart = GL_FALSE; + } +} + +inline void gl_state_disable_scissor_test() { + if (gl_state.scissor_test) { + glDisable(GL_SCISSOR_TEST); + gl_state.scissor_test = GL_FALSE; + } +} + inline void gl_state_disable_stencil_test() { - if (gl_state.cull_face) { + if (gl_state.stencil_test) { glDisable(GL_STENCIL_TEST); gl_state.stencil_test = GL_FALSE; } @@ -237,8 +239,22 @@ inline void gl_state_enable_depth_test() { } } +inline void gl_state_enable_primitive_restart() { + if (!gl_state.primitive_restart) { + glEnable(GL_PRIMITIVE_RESTART); + gl_state.primitive_restart = GL_TRUE; + } +} + +inline void gl_state_enable_scissor_test() { + if (!gl_state.scissor_test) { + glEnable(GL_SCISSOR_TEST); + gl_state.scissor_test = GL_TRUE; + } +} + inline void gl_state_enable_stencil_test() { - if (!gl_state.cull_face) { + if (!gl_state.stencil_test) { glEnable(GL_STENCIL_TEST); gl_state.stencil_test = GL_TRUE; } @@ -294,12 +310,11 @@ void gl_state_get() { glGetIntegerv(GL_CULL_FACE_MODE, (GLint*)&gl_state.cull_face_mode); glGetBooleanv(GL_DEPTH_TEST, &gl_state.depth_test); glGetIntegerv(GL_DEPTH_FUNC, (GLint*)&gl_state.depth_func); - glGetBooleanv(GL_DEPTH_WRITEMASK, &gl_state.cull_face); - glGetBooleanv(GL_CULL_FACE, &gl_state.depth_mask); + glGetBooleanv(GL_DEPTH_WRITEMASK, &gl_state.depth_mask); + glGetBooleanv(GL_PRIMITIVE_RESTART, &gl_state.primitive_restart); + glGetBooleanv(GL_SCISSOR_TEST, &gl_state.scissor_test); glGetBooleanv(GL_STENCIL_TEST, &gl_state.stencil_test); glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint*)&gl_state.stencil_mask); - glGetBooleanv(GL_CULL_FACE, &gl_state.cull_face); - glGetBooleanv(GL_CULL_FACE, &gl_state.cull_face); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); gl_state.polygon_front_face_mode = GL_FILL; @@ -318,12 +333,12 @@ inline GLuint gl_state_get_program() { inline void gl_state_set_blend_func(GLenum src, GLenum dst) { if (gl_state.blend_src_rgb != src || gl_state.blend_dst_rgb != dst - || gl_state.blend_src_alpha != GL_SRC_ALPHA || gl_state.blend_dst_alpha != GL_ONE_MINUS_SRC_ALPHA) { - glBlendFuncSeparate(src, dst, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + || gl_state.blend_src_alpha != GL_ONE_MINUS_DST_ALPHA || gl_state.blend_dst_alpha != GL_ONE) { + glBlendFuncSeparate(src, dst, GL_ONE_MINUS_DST_ALPHA, GL_ONE); gl_state.blend_src_rgb = src; gl_state.blend_dst_rgb = dst; - gl_state.blend_src_alpha = GL_SRC_ALPHA; - gl_state.blend_dst_alpha = GL_ONE_MINUS_SRC_ALPHA; + gl_state.blend_src_alpha = GL_ONE_MINUS_DST_ALPHA; + gl_state.blend_dst_alpha = GL_ONE; } } @@ -419,7 +434,7 @@ inline void gl_state_set_polygon_mode(GLenum face, GLenum mode) { } } -extern void gl_state_set_stencil_mask(GLuint mask) { +inline void gl_state_set_stencil_mask(GLuint mask) { if (gl_state.stencil_mask != mask) { glStencilMask(mask); gl_state.stencil_mask = mask; diff --git a/src/CRE/gl_state.h b/src/CRE/gl_state.h index b3e3024f..856034a1 100644 --- a/src/CRE/gl_state.h +++ b/src/CRE/gl_state.h @@ -8,11 +8,55 @@ #include "../KKdLib/default.h" #include +typedef struct gl_state_struct { + GLuint program; + GLenum active_texture; + GLuint active_texture_index; + GLuint texture_binding_2d[32]; + GLuint texture_binding_cube_map[32]; + GLuint sampler_binding[32]; + GLboolean blend; + GLenum blend_src_rgb; + GLenum blend_src_alpha; + GLenum blend_dst_rgb; + GLenum blend_dst_alpha; + GLenum blend_mode_rgb; + GLenum blend_mode_alpha; + GLuint framebuffer_binding; + GLuint vertex_array_binding; + GLuint array_buffer_binding; + GLuint element_array_buffer_binding; + GLuint uniform_buffer_index; + GLuint uniform_buffer_binding[14]; + GLintptr uniform_buffer_offset[14]; + GLsizeiptr uniform_buffer_size[14]; + GLuint shader_storage_buffer_index; + GLuint shader_storage_buffer_binding[14]; + GLintptr shader_storage_buffer_offset[14]; + GLsizeiptr shader_storage_buffer_size[14]; + GLboolean color_mask[4]; + GLboolean cull_face; + GLenum cull_face_mode; + GLboolean depth_test; + GLenum depth_func; + GLboolean depth_mask; + GLenum polygon_front_face_mode; + GLenum polygon_back_face_mode; + GLboolean primitive_restart; + GLboolean scissor_test; + GLboolean stencil_test; + GLuint stencil_mask; +} gl_state_struct; + +extern gl_state_struct gl_state; + extern void gl_state_active_bind_texture_2d(int32_t index, GLuint texture); extern void gl_state_active_bind_texture_cube_map(int32_t index, GLuint texture); extern void gl_state_active_texture(size_t index); extern void gl_state_bind_framebuffer(GLuint framebuffer); extern void gl_state_bind_vertex_array(GLuint array); +extern void gl_state_bind_array_buffer(GLuint buffer); +extern void gl_state_bind_element_array_buffer(GLuint buffer); extern void gl_state_bind_uniform_buffer(GLuint buffer); extern void gl_state_bind_uniform_buffer_base(GLuint index, GLuint buffer); extern void gl_state_bind_uniform_buffer_range(GLuint index, @@ -34,10 +78,14 @@ extern bool gl_state_check_sampler_binding(int32_t index, GLuint sampler); extern void gl_state_disable_blend(); extern void gl_state_disable_cull_face(); extern void gl_state_disable_depth_test(); +extern void gl_state_disable_primitive_restart(); +extern void gl_state_disable_scissor_test(); extern void gl_state_disable_stencil_test(); extern void gl_state_enable_blend(); extern void gl_state_enable_cull_face(); extern void gl_state_enable_depth_test(); +extern void gl_state_enable_primitive_restart(); +extern void gl_state_enable_scissor_test(); extern void gl_state_enable_stencil_test(); extern void gl_state_get(); extern void gl_state_get_all_gl_errors(); diff --git a/src/CRE/hash.c b/src/CRE/hash.c index 561b7d16..ce4680b1 100644 --- a/src/CRE/hash.c +++ b/src/CRE/hash.c @@ -16,7 +16,7 @@ inline hash hash_utf16(wchar_t* data) { inline hash hash_data(void* data, size_t length) { hash hash; - hash.f = hash_fnv1a64(data, length); + hash.f = hash_fnv1a64m(data, length); hash.m = hash_murmurhash(data, length, 0, false, false); return hash; } diff --git a/src/KKdLib/moti.c b/src/CRE/interpolation/motion.c similarity index 67% rename from src/KKdLib/moti.c rename to src/CRE/interpolation/motion.c index c2086664..a2099d67 100644 --- a/src/KKdLib/moti.c +++ b/src/CRE/interpolation/motion.c @@ -3,16 +3,16 @@ GitHub/GitLab: korenkonder */ -#include "moti.h" -#include "interpolation.h" +#include "motion.h" +#include "../../KKdLib/interpolation.h" -static void moti_interpolate(moti* interp); +static void motion_interpolation_interpolate(motion_interpolation* interp); -moti* kft2_array_to_moti(kft2* array, size_t length, float_t interpolation_framerate, float_t requested_framerate) { - if (!array || !length) - return 0; +void kft2_array_to_motion_interpolation(motion_interpolation* interp, + kft2* array, size_t length, float_t interpolation_framerate, float_t requested_framerate) { + if (!interp) + return; - moti* interp = force_malloc(sizeof(moti)); interp->time = 0.0f; interp->array = array; interp->length = length; @@ -22,80 +22,81 @@ moti* kft2_array_to_moti(kft2* array, size_t length, float_t interpolation_frame interp->requested_framerate = requested_framerate; interp->value = 0.0f; interp->first_key = interp->last_key = 0; - moti_reset(interp); + motion_interpolation_reset(interp); if (array && length) { interp->first_key = array; interp->last_key = array + length - 1; } - return interp; } -inline void moti_set_interpolation_framerate(moti* interp, float_t interpolation_framerate) { +inline void motion_interpolation_set_interpolation_framerate(motion_interpolation* interp, + float_t interpolation_framerate) { interp->interpolation_framerate = interpolation_framerate; interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; } -inline void moti_set_requested_framerate(moti* interp, float_t requested_framerate) { +inline void motion_interpolation_set_requested_framerate(motion_interpolation* interp, + float_t requested_framerate) { interp->requested_framerate = requested_framerate; interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; } -inline void moti_update(moti* interp) { +inline void motion_interpolation_update(motion_interpolation* interp) { interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; } -inline void moti_reset(moti* interp) { +inline void motion_interpolation_reset(motion_interpolation* interp) { interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; interp->frame = 0.0f; interp->time = interp->frame / interp->requested_framerate; } -float_t moti_set_time(moti* interp, float_t time) { +float_t motion_interpolation_set_time(motion_interpolation* interp, float_t time) { if (!interp || !interp->array || !interp->length) return 0.0f; interp->frame = time * interp->interpolation_framerate; interp->time = time; - moti_interpolate(interp); + motion_interpolation_interpolate(interp); return interp->value; } -float_t moti_set_frame(moti* interp, float_t frame) { +float_t motion_interpolation_set_frame(motion_interpolation* interp, float_t frame) { if (!interp || !interp->array || !interp->length) return 0.0f; interp->frame = frame * interp->delta_frame; interp->time = frame / interp->requested_framerate; - moti_interpolate(interp); + motion_interpolation_interpolate(interp); return interp->value; } -float_t moti_add_time(moti* interp, float_t time) { +float_t motion_interpolation_add_time(motion_interpolation* interp, float_t time) { if (!interp || !interp->array || !interp->length) return 0.0f; interp->frame = time * interp->interpolation_framerate; interp->time += time; - moti_interpolate(interp); + motion_interpolation_interpolate(interp); return interp->value; } -float_t moti_next_frame(moti* interp) { +float_t motion_interpolation_next_frame(motion_interpolation* interp) { if (!interp || !interp->array || !interp->length) return 0.0f; interp->frame += interp->delta_frame; interp->time = interp->frame / interp->interpolation_framerate; - moti_interpolate(interp); + motion_interpolation_interpolate(interp); return interp->value; } -static void moti_interpolate(moti* interp) { +static void motion_interpolation_interpolate(motion_interpolation* interp) { float_t frame = interp->frame; kft2* keys = interp->array; diff --git a/src/CRE/interpolation/motion.h b/src/CRE/interpolation/motion.h new file mode 100644 index 00000000..f93f071d --- /dev/null +++ b/src/CRE/interpolation/motion.h @@ -0,0 +1,38 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/kf.h" + +typedef struct moti { + kft2* array; + size_t length; + + float_t frame; + float_t time; + float_t value; + float_t delta_frame; + float_t interpolation_framerate; + float_t requested_framerate; + + kft2* first_key; + kft2* last_key; +} motion_interpolation; + +extern void kft2_array_to_motion_interpolation(motion_interpolation* interp, + kft2* array, size_t length, float_t interpolation_framerate, float_t requested_framerate); +extern void motion_interpolation_set_interpolation_framerate(motion_interpolation* interp, + float_t interpolation_framerate); +extern void motion_interpolation_set_requested_framerate(motion_interpolation* interp, + float_t requested_framerate); +extern void motion_interpolation_update(motion_interpolation* interp); +extern void motion_interpolation_reset(motion_interpolation* interp); +extern float_t motion_interpolation_set_time(motion_interpolation* interp, float_t time); +extern float_t motion_interpolation_set_frame(motion_interpolation* interp, float_t frame); +extern float_t motion_interpolation_add_time(motion_interpolation* interp, float_t time); +extern float_t motion_interpolation_next_frame(motion_interpolation* interp); + diff --git a/src/CRE/light_param.c b/src/CRE/light_param.c new file mode 100644 index 00000000..0251b4c4 --- /dev/null +++ b/src/CRE/light_param.c @@ -0,0 +1,369 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "light_param.h" +#include "../KKdLib/str_utils.h" + +vector_func(light_param_data) + +typedef struct light_param_storage { + bool pv; + union { + uint64_t hash; + uint32_t pv_id; + }; + int32_t count; + union { + light_param_data data; + light_param_set set; + }; +} light_param_storage; + +vector(light_param_storage) + +static void light_param_set_load_farc_file(light_param_set* set, farc_file* ff); + +vector_func(light_param_storage) + +vector_light_param_storage light_param_storage_data; + +void light_param_data_init(light_param_data* light_param) { + memset(light_param, 0, sizeof(light_param_data)); + light_param_light_init(&light_param->light); + light_param_fog_init(&light_param->fog); + light_param_glow_init(&light_param->glow); + light_param_ibl_init(&light_param->ibl); + light_param_wind_init(&light_param->wind); + light_param_face_init(&light_param->face); +} + +void light_param_data_load(light_param_data* light_param, data_struct* data, char* name) { + char buf[_MAX_PATH]; + + light_param->id = 0; + + sprintf_s(buf, sizeof(buf), "light_%s.txt", name); + data_struct_load_file(data, &light_param->light, "rom\\light_param\\", buf, light_param_light_load_file); + + sprintf_s(buf, sizeof(buf), "fog_%s.txt", name); + data_struct_load_file(data, &light_param->fog, "rom\\light_param\\", buf, light_param_fog_load_file); + + sprintf_s(buf, sizeof(buf), "glow_%s.txt", name); + data_struct_load_file(data, &light_param->glow, "rom\\light_param\\", buf, light_param_glow_load_file); + + sprintf_s(buf, sizeof(buf), "%s.ibl", name); + data_struct_load_file(data, &light_param->ibl, "rom\\ibl\\", buf, light_param_ibl_load_file); + + sprintf_s(buf, sizeof(buf), "wind_%s.txt", name); + data_struct_load_file(data, &light_param->wind, "rom\\light_param\\", buf, light_param_wind_load_file); + + sprintf_s(buf, sizeof(buf), "face_%s.txt", name); + data_struct_load_file(data, &light_param->face, "rom\\light_param\\", buf, light_param_face_load_file); +} + +void light_param_data_free(light_param_data* light_param) { + light_param_light_free(&light_param->light); + light_param_fog_free(&light_param->fog); + light_param_glow_free(&light_param->glow); + light_param_ibl_free(&light_param->ibl); + light_param_wind_free(&light_param->wind); + light_param_face_free(&light_param->face); +} + +void light_param_set_init(light_param_set* set) { + memset(set, 0, sizeof(light_param_set)); +} + +void light_param_set_load(light_param_set* set, data_struct* data, int32_t pv_id) { + char buf[_MAX_PATH]; + sprintf_s(buf, sizeof(buf), "light_pv%03d.farc", pv_id); + + farc f; + farc_init(&f); + if (!data_struct_load_file(data, &f, "rom\\light_param\\", buf, farc_load_file)) + return; + + for (farc_file* i = f.files.begin; i != f.files.end; i++) + light_param_set_load_farc_file(set, i); + farc_free(&f); +} + +void light_param_set_free(light_param_set* set) { + vector_light_param_data_free(set, light_param_data_free); +} + +char* light_param_get_string(char* name) { + size_t length = utf8_length(name); + if (str_utils_compare_length(name, length, "STG", 3)) + return 0; + + name += 3; + length -= 3; + + char* str = force_malloc(length + 1); + for (size_t i = 0; i < length; i++) { + char c = name[i]; + if (c > 0x40 && c < 0x5B) + c += 0x20; + str[i] = c; + } + str[length] = 0; + return str; +} + +inline void light_param_storage_init() { + light_param_storage_data = vector_empty(light_param_storage); +} + +inline void light_param_storage_append_light_param_data(char* name) { + uint64_t hash = hash_fnv1a64m(name, utf8_length(name)); + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (!i->pv && i->hash == hash) { + i->count++; + return; + } +} + +inline void light_param_storage_append_light_param_set(int32_t pv_id) { + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (i->pv && i->pv_id == pv_id) { + i->count++; + return; + } +} + +inline void light_param_storage_load_light_param_data(data_struct* data, char* name) { + light_param_data light_param; + light_param_data_init(&light_param); + light_param_data_load(&light_param, data, name); + light_param_storage_insert_light_param_data(&light_param, name); +} + +inline void light_param_storage_load_light_param_set(data_struct* data, int32_t pv_id) { + light_param_set light_param; + light_param_set_init(&light_param); + light_param_set_load(&light_param, data, pv_id); + light_param_storage_insert_light_param_set(&light_param, pv_id); +} + +inline void light_param_storage_insert_light_param_data(light_param_data* data, char* name) { + uint64_t hash = hash_fnv1a64m(name, utf8_length(name)); + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (!i->pv && i->hash == hash) { + light_param_data_free(&i->data); + i->count++; + i->data = *data; + return; + } + + light_param_storage* lit_param_set_storage = + vector_light_param_storage_reserve_back(&light_param_storage_data); + lit_param_set_storage->pv = false; + lit_param_set_storage->hash = hash; + lit_param_set_storage->count = 1; + lit_param_set_storage->data = *data; +} + +inline void light_param_storage_insert_light_param_set(light_param_set* set, int32_t pv_id) { + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (i->pv && i->pv_id == pv_id) { + light_param_set_free(&i->set); + i->count++; + i->set = *set; + return; + } + + light_param_storage* lit_param_set_storage = vector_light_param_storage_reserve_back(&light_param_storage_data); + lit_param_set_storage->pv = true; + lit_param_set_storage->pv_id = pv_id; + lit_param_set_storage->count = 1; + lit_param_set_storage->set = *set; +} + +inline light_param_data* light_param_storage_get_light_param_data(char* name) { + uint64_t hash = hash_fnv1a64m(name, utf8_length(name)); + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (!i->pv && i->hash == hash) + return &i->data; + return 0; +} + +inline light_param_set* light_param_storage_get_light_param_set(int32_t pv_id) { + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (i->pv && i->pv_id == pv_id) + return &i->set; + return 0; +} + +inline void light_param_storage_delete_light_param_data(char* name) { + uint64_t hash = hash_fnv1a64m(name, utf8_length(name)); + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (!i->pv && i->hash == hash) { + i->count--; + if (i->count > 0) + break; + + light_param_set_free(&i->set); + + vector_light_param_storage_erase(&light_param_storage_data, + i - light_param_storage_data.begin, 0); + break; + } +} + +inline void light_param_storage_delete_light_param_set(int32_t pv_id) { + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (i->pv && i->pv_id == pv_id) { + i->count--; + if (i->count > 0) + break; + + light_param_set_free(&i->set); + + vector_light_param_storage_erase(&light_param_storage_data, + i - light_param_storage_data.begin, 0); + break; + } +} + +inline void light_param_storage_free() { + for (light_param_storage* i = light_param_storage_data.begin; + i != light_param_storage_data.end; i++) + if (!i->pv) + light_param_data_free(&i->data); + else + light_param_set_free(&i->set); + vector_light_param_storage_free(&light_param_storage_data, 0); +} + +static void light_param_set_load_farc_file(light_param_set* set, farc_file* ff) { + char* name = string_data(&ff->name); + size_t name_len = utf8_length(name); + + int32_t type = 0; + if (!str_utils_compare_length(name, name_len, "light", 5) && name[5] == '_') { + type = 1; + name += 6; + name_len -= 6; + } + else if (!str_utils_compare_length(name, name_len, "fog", 3) && name[3] == '_') { + type = 2; + name += 4; + name_len -= 4; + } + else if (!str_utils_compare_length(name, name_len, "glow", 4) && name[4] == '_') { + type = 3; + name += 5; + name_len -= 5; + } + else if (!str_utils_compare_length(name, name_len, "wind", 4) && name[4] == '_') { + type = 4; + name += 5; + name_len -= 5; + } + else if (!str_utils_compare_length(name, name_len, "face", 4) && name[4] == '_') { + type = 5; + name += 5; + name_len -= 5; + } + else + return; + + char buf[0x100]; + char* b = buf; + char* n = name; + size_t s = 0; + do { + char c = *n++; + if (c == '_' || c == '.') + break; + else if (!c) + return; + + *b++ = c; + s++; + } while (*n); + *b++ = 0; + + b = buf; + if (s < 5 || b[0] != 'p' || b[1] != 'v' || b[2] < '0' && b[2] > '9' + || b[3] < '0' && b[3] > '9' || b[4] < '0' && b[4] > '9') + return; + + int32_t pv_id = (b[2] - '0') * 100; + pv_id += (b[3] - '0') * 10; + pv_id += b[4] - '0'; + + s = 0; + do { + char c = *n++; + if (c == '_' || c == '.') + break; + else if (!c) + return; + + *b++ = c; + s++; + } while (*n); + *b++ = 0; + + b = buf; + if (s != 4 || b[0] != 'c' || b[1] < '0' && b[1] > '9' + || b[2] < '0' && b[2] > '9' || b[3] < '0' && b[3] > '9') + return; + + int32_t cut = (b[1] - '0') * 100; + cut += (b[2] - '0') * 10; + cut += b[3] - '0'; + + light_param_data* data = 0; + for (data = set->begin; data != set->end; data++) + if (data->id == cut) + break; + + if (data == set->end) { + data = vector_light_param_data_reserve_back(set); + data->id = cut; + } + + if (type == 1) { + if (data->light.ready) + light_param_light_free(&data->light); + light_param_light_init(&data->light); + light_param_light_mread(&data->light, ff->data, ff->size); + } + else if (type == 2) { + if (data->fog.ready) + light_param_fog_free(&data->fog); + light_param_fog_init(&data->fog); + light_param_fog_mread(&data->fog, ff->data, ff->size); + } + else if (type == 3) { + if (data->glow.ready) + light_param_glow_free(&data->glow); + light_param_glow_init(&data->glow); + light_param_glow_mread(&data->glow, ff->data, ff->size); + } + else if (type == 4) { + if (data->wind.ready) + light_param_wind_free(&data->wind); + light_param_wind_init(&data->wind); + light_param_wind_mread(&data->wind, ff->data, ff->size); + } + else if (type == 5) { + if (data->face.ready) + light_param_face_free(&data->face); + light_param_face_init(&data->face); + light_param_face_mread(&data->face, ff->data, ff->size); + } +} diff --git a/src/CRE/light_param.h b/src/CRE/light_param.h new file mode 100644 index 00000000..4a8839f7 --- /dev/null +++ b/src/CRE/light_param.h @@ -0,0 +1,55 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/farc.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/vector.h" +#include "../KKdLib/light_param/face.h" +#include "../KKdLib/light_param/fog.h" +#include "../KKdLib/light_param/glow.h" +#include "../KKdLib/light_param/ibl.h" +#include "../KKdLib/light_param/light.h" +#include "../KKdLib/light_param/wind.h" +#include "data.h" + +typedef struct light_param_data { + int32_t id; + light_param_light light; + light_param_fog fog; + light_param_glow glow; + light_param_ibl ibl; + light_param_wind wind; + light_param_face face; +} light_param_data; + +vector(light_param_data) + +typedef struct vector_light_param_data light_param_set; + +extern void light_param_data_init(light_param_data* light_param); +extern void light_param_data_load(light_param_data* light_param, data_struct* data, char* name); +extern void light_param_data_free(light_param_data* light_param); + +extern void light_param_set_init(light_param_set* set); +extern void light_param_set_load(light_param_set* set, data_struct* data, int32_t pv_id); +extern void light_param_set_free(light_param_set* set); + +extern char* light_param_get_string(char* name); + +extern void light_param_storage_init(); +extern void light_param_storage_append_light_param_data(char* name); +extern void light_param_storage_append_light_param_set(int32_t pv_id); +extern void light_param_storage_load_light_param_data(data_struct* data, char* name); +extern void light_param_storage_load_light_param_set(data_struct* data, int32_t pv_id); +extern void light_param_storage_insert_light_param_data(light_param_data* data, char* name); +extern void light_param_storage_insert_light_param_set(light_param_set* set, int32_t pv_id); +extern light_param_data* light_param_storage_get_light_param_data(char* name); +extern light_param_set* light_param_storage_get_light_param_set(int32_t pv_id); +extern void light_param_storage_delete_light_param_data(char* name); +extern void light_param_storage_delete_light_param_set(int32_t pv_id); +extern void light_param_storage_free(); diff --git a/src/CRE/light_param/face.c b/src/CRE/light_param/face.c new file mode 100644 index 00000000..2cc326e4 --- /dev/null +++ b/src/CRE/light_param/face.c @@ -0,0 +1,45 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "face.h" + +void face_init(face* face) { + face->offset = 1.0f; + face->scale = 0.35f; + face->position = vec3_null; + face->direction = vec3_null; +} + +inline float_t face_get_offset(face* face) { + return face->offset; +} + +inline void face_set_offset(face* face, float_t value) { + face->scale = value; +} + +inline float_t face_get_scale(face* face) { + return face->scale; +} + +inline void face_set_scale(face* face, float_t value) { + face->scale = value; +} + +inline void face_get_position(face* face, vec3* value) { + *value = face->position; +} + +inline void face_set_position(face* face, vec3* value) { + face->position = *value; +} + +inline void face_get_direction(face* face, vec3* value) { + *value = face->direction; +} + +inline void face_set_direction(face* face, vec3* value) { + face->direction = *value; +} diff --git a/src/CRE/light_param/face.h b/src/CRE/light_param/face.h new file mode 100644 index 00000000..34f38429 --- /dev/null +++ b/src/CRE/light_param/face.h @@ -0,0 +1,28 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/light_param/face.h" +#include "../../KKdLib/vec.h" +#include "../static_var.h" + +typedef struct face { + float_t offset; + float_t scale; + vec3 position; + vec3 direction; +} face; + +extern void face_init(face* face); +extern float_t face_get_offset(face* face); +extern void face_set_offset(face* face, float_t value); +extern float_t face_get_scale(face* face); +extern void face_set_scale(face* face, float_t value); +extern void face_get_position(face* face, vec3* value); +extern void face_set_position(face* face, vec3* value); +extern void face_get_direction(face* face, vec3* value); +extern void face_set_direction(face* face, vec3* value); diff --git a/src/CRE/light_param/fog.c b/src/CRE/light_param/fog.c new file mode 100644 index 00000000..935bc383 --- /dev/null +++ b/src/CRE/light_param/fog.c @@ -0,0 +1,105 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "fog.h" +#include "../shader_ft.h" + +void fog_init(fog* fog) { + fog->type = FOG_NONE; + fog->density = 0.0f; + fog->start = 20.0f; + fog->end = 1000.0f; + fog->index = 0; + fog->color = (vec4){ 1.0f, 1.0f, 1.0f, 0.0f }; +} + +inline fog_type fog_get_type(fog* fog) { + return fog->type; +} + +inline void fog_set_type(fog* fog, fog_type value) { + fog->type = value; +} + +inline float_t fog_get_density(fog* fog) { + return fog->density; +} + +inline void fog_set_density(fog* fog, float_t value) { + fog->density = value; +} + +inline float_t fog_get_start(fog* fog) { + return fog->start; +} + +inline void fog_set_start(fog* fog, float_t value) { + fog->start = value; +} + +inline float_t fog_get_end(fog* fog) { + return fog->end; +} + +inline void fog_set_end(fog* fog, float_t value) { + fog->end = value; +} + +inline int32_t fog_get_index(fog* fog) { + return fog->index; +} + +inline void fog_set_index(fog* fog, int32_t value) { + fog->index = value; +} + +inline void fog_get_color(fog* fog, vec4* value) { + *value = fog->color; +} + +inline void fog_set_color(fog* fog, vec4* value) { + fog->color = *value; +} + +void fog_data_set(fog* fog, fog_id id) { + fog_type type = fog_get_type(fog); + if (type == FOG_NONE) + return; + + float_t density = fog_get_density(fog); + float_t start = fog_get_start(fog); + float_t end = fog_get_end(fog); + if (start >= end) + start = end - 0.0099999998f; + + vec4 params; + params.x = density; + params.y = start; + params.z = end; + params.w = 1.0f / (end - start); + + switch (id) { + case FOG_DEPTH: { + vec4 color; + fog_get_color(fog, &color); + shader_env_vert_set_ptr(&shaders_ft, 29, &color); + shader_env_frag_set_ptr(&shaders_ft, 4, &color); + + vec4_mult_scalar(color, (float_t)(1.0 / 8.0), color); + shader_state_fog_set_color_ptr(&shaders_ft, &color); + shader_state_fog_set_params_ptr(&shaders_ft, ¶ms); + } break; + case FOG_HEIGHT: { + vec4 color; + fog_get_color(fog, &color); + shader_env_vert_set_ptr(&shaders_ft, 30, &color); + shader_env_frag_set_ptr(&shaders_ft, 11, &color); + shader_env_vert_set_ptr(&shaders_ft, 14, ¶ms); + } break; + case FOG_BUMP: { + shader_env_vert_set_ptr(&shaders_ft, 19, ¶ms); + } break; + } +} diff --git a/src/CRE/light_param/fog.h b/src/CRE/light_param/fog.h new file mode 100644 index 00000000..69345b15 --- /dev/null +++ b/src/CRE/light_param/fog.h @@ -0,0 +1,35 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/light_param/fog.h" +#include "../../KKdLib/vec.h" +#include "../static_var.h" + +typedef struct fog { + fog_type type; + float_t density; + float_t start; + float_t end; + int32_t index; + vec4 color; +} fog; + +extern void fog_init(fog* fog); +extern fog_type fog_get_type(fog* fog); +extern void fog_set_type(fog* fog, fog_type value); +extern float_t fog_get_density(fog* fog); +extern void fog_set_density(fog* fog, float_t value); +extern float_t fog_get_start(fog* fog); +extern void fog_set_start(fog* fog, float_t value); +extern float_t fog_get_end(fog* fog); +extern void fog_set_end(fog* fog, float_t value); +extern int32_t fog_get_index(fog* fog); +extern void fog_set_index(fog* fog, int32_t value); +extern void fog_get_color(fog* fog, vec4* value); +extern void fog_set_color(fog* fog, vec4* value); +extern void fog_data_set(fog* fog, fog_id id); diff --git a/src/CRE/light_param/light.c b/src/CRE/light_param/light.c new file mode 100644 index 00000000..0d0bdebc --- /dev/null +++ b/src/CRE/light_param/light.c @@ -0,0 +1,450 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "light.h" +#include "../../KKdLib/mat.h" +#include "../shader_ft.h" + +extern bool light_chara_ambient; +extern vec4 npr_spec_color; + +static void light_get_direction_from_position(vec4* pos_dir, light_data* light, bool force); + +void light_set_init(light_set* set) { + for (light_id i = LIGHT_CHARA; i <= LIGHT_PROJECTION; i++) { + light_data* light = &set->lights[i]; + light_set_type(light, LIGHT_OFF); + light_set_ambient(light, &((vec4) { 0.0f, 0.0, 0.0f, 1.0f })); + light_set_diffuse(light, &((vec4) { 1.0f, 1.0, 1.0f, 0.0f })); + light_set_specular(light, &((vec4) { 1.0f, 1.0f, 1.0f, 0.0f })); + light_set_position(light, &((vec3) { 0.0f, 1.0f, 1.0f })); + light_set_spot_direction(light, &((vec3) { 0.0f, 0.0f, -1.0f })); + light_set_spot_exponent(light, 0.0f); + light_set_spot_cutoff(light, 45.0f); + light_set_constant(light, 1.0f); + light_set_linear(light, 0.0f); + light_set_quadratic(light, 0.0f); + light_set_ibl_specular(light, &((vec4) { 0.0f, 0.0f, 0.0f, 0.0f })); + light_set_ibl_back(light, &((vec4) { 0.0f, 0.0f, 0.0f, 0.0f })); + light_set_ibl_direction(light, &((vec4) { 0.0f, 0.0f, 0.0f, 0.0f })); + light_set_tone_curve(light, &((vec3) { 0.0f, 0.0f, 0.0f })); + } + light_set_set_ambient_intensity(set, &((vec4) { 0.2f, 0.2f, 0.2f, 1.0f })); + light_set_diffuse(&set->lights[LIGHT_CHARA], &((vec4) { 1.0f, 1.0f, 1.0f, 1.0f })); + light_set_specular(&set->lights[LIGHT_CHARA], &((vec4) { 1.0f, 1.0f, 1.0f, 1.0f })); + light_set_set_irradiance(set, (mat4*)&mat4_identity, (mat4*)&mat4_identity, (mat4*)&mat4_identity); +} + +inline light_type light_get_type(light_data* light) { + return light->type; +} + +inline void light_set_type(light_data* light, light_type value) { + light->type = value; + if (value < LIGHT_POINT) + light->position.w = 0.0f; + else + light->position.w = 1.0f; +} + +inline void light_get_ambient(light_data* light, vec4* value) { + *value = light->ambient; +} + +inline void light_set_ambient(light_data* light, vec4* value) { + light->ambient = *value; +} + +inline void light_get_diffuse(light_data* light, vec4* value) { + *value = light->diffuse; +} + +inline void light_set_diffuse(light_data* light, vec4* value) { + light->diffuse = *value; +} + +inline void light_get_specular(light_data* light, vec4* value) { + *value = light->specular; +} + +inline void light_set_specular(light_data* light, vec4* value) { + light->specular = *value; +} + +inline void light_get_position(light_data* light, vec3* value) { + *value = *(vec3*)&light->position; +} + +inline void light_set_position(light_data* light, vec3* value) { + *(vec3*)&light->position = *value; +} + +inline void light_get_position_vec4(light_data* light, vec4* value) { + *value = light->position; +} + +inline void light_set_position_vec4(light_data* light, vec4* value) { + light->position = *value; +} + +inline void light_get_spot_direction(light_data* light, vec3* value) { + *value = light->spot_direction; +} + +inline void light_set_spot_direction(light_data* light, vec3* value) { + light->spot_direction = *value; +} + +inline float_t light_get_spot_exponent(light_data* light) { + return light->spot_exponent; +} + +inline void light_set_spot_exponent(light_data* light, float_t value) { + light->spot_exponent = value; +} + +inline float_t light_get_spot_cutoff(light_data* light) { + return light->spot_cutoff; +} + +inline void light_set_spot_cutoff(light_data* light, float_t value) { + light->spot_cutoff = value; +} + +inline float_t light_get_constant(light_data* light) { + return light->constant; +} + +inline void light_set_constant(light_data* light, float_t value) { + light->constant = value; +} + +inline float_t light_get_linear(light_data* light) { + return light->linear; +} + +inline void light_set_linear(light_data* light, float_t value) { + light->linear = value; +} + +inline float_t light_get_quadratic(light_data* light) { + return light->quadratic; +} + +inline void light_set_quadratic(light_data* light, float_t value) { + light->quadratic = value; +} + +inline void light_get_attenuation(light_data* light, vec3* value) { + value->x = light->constant; + value->y = light->linear; + value->z = light->quadratic; +} + +inline void light_set_attenuation(light_data* light, vec3* value) { + light->constant = value->x; + light->linear = value->y; + light->quadratic = value->z; +} + +inline void light_get_ibl_specular(light_data* light, vec4* value) { + *value = light->ibl_specular; +} + +inline void light_set_ibl_specular(light_data* light, vec4* value) { + light->ibl_specular = *value; +} + +inline void light_get_ibl_back(light_data* light, vec4* value) { + *value = light->ibl_back; +} + +inline void light_set_ibl_back(light_data* light, vec4* value) { + light->ibl_back = *value; +} + +inline void light_get_ibl_direction(light_data* light, vec4* value) { + *value = light->ibl_direction; +} + +inline void light_set_ibl_direction(light_data* light, vec4* value) { + light->ibl_direction = *value; +} + +inline void light_get_tone_curve(light_data* light, vec3* value) { + *value = light->tone_curve; +} + +inline void light_set_tone_curve(light_data* light, vec3* value) { + light->tone_curve = *value; +} + +inline void light_get_clip_plane(light_data* light, bool value[4]) { + value[0] = light->clip_plane[0]; + value[1] = light->clip_plane[1]; + value[2] = light->clip_plane[2]; + value[3] = light->clip_plane[3]; +} + +inline void light_set_clip_plane(light_data* light, bool value[4]) { + light->clip_plane[0] = value[0]; + light->clip_plane[1] = value[1]; + light->clip_plane[2] = value[2]; + light->clip_plane[3] = value[3]; +} + +inline void light_set_get_ambient_intensity(light_set* set, vec4* value) { + *value = set->ambient_intensity; +} + +inline void light_set_set_ambient_intensity(light_set* set, vec4* value) { + set->ambient_intensity = *value; +} + +inline void light_set_get_irradiance(light_set* set, mat4* r, mat4* g, mat4* b) { + *r = set->irradiance_r; + *g = set->irradiance_g; + *b = set->irradiance_b; +} + +inline void light_set_get_irradiance_ptr(light_set* set, mat4** r, mat4** g, mat4** b) { + *r = &set->irradiance_r; + *g = &set->irradiance_g; + *b = &set->irradiance_b; +} + +inline void light_set_set_irradiance(light_set* set, mat4* r, mat4* g, mat4* b) { + set->irradiance_r = *r; + set->irradiance_g = *g; + set->irradiance_b = *b; +} + +void light_set_data_set(light_set* set, face* face, light_set_id id) { + vec4 ambient_intensity; + light_set_get_ambient_intensity(set, &ambient_intensity); + shader_state_lightmodel_set_ambient_ptr(&shaders_ft, false, &ambient_intensity); + + for (light_id i = LIGHT_CHARA; i <= LIGHT_PROJECTION; i++) { + light_data* light = &set->lights[i]; + if (light_chara_ambient || i != LIGHT_CHARA) + shader_state_light_set_ambient_ptr(&shaders_ft, i, &light->ambient); + else + shader_state_light_set_ambient(&shaders_ft, i, 0.0f, 0.0f, 0.0f, 1.0f); + shader_state_light_set_diffuse_ptr(&shaders_ft, i, &light->diffuse); + shader_state_light_set_specular_ptr(&shaders_ft, i, &light->specular); + + vec4 light_direction = light->position; + light_get_direction_from_position(&light_direction, light, 0); + shader_state_light_set_position_ptr(&shaders_ft, i, &light_direction); + + shader_state_light_set_attenuation(&shaders_ft, i, + light->constant, light->linear, light->quadratic, light->spot_exponent); + + vec3 spot_direction = light->spot_direction; + shader_state_light_set_spot_direction(&shaders_ft, i, + spot_direction.x, spot_direction.y, spot_direction.z, light->spot_cutoff); + } + + const float_t spec_coef = (float_t)(1.0 / (1.0 - cos(18.0 * DEG_TO_RAD))); + const float_t luce_coef = (float_t)(1.0 / (1.0 - cos(45.0 * DEG_TO_RAD))); + + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 position; + vec4 ibl_specular; + vec4 ibl_back; + vec4 ibl_direction; + vec4 temp; + light_get_position_vec4(&set->lights[LIGHT_CHARA], &position); + light_get_direction_from_position(&position, &set->lights[LIGHT_CHARA], 0); + light_get_ibl_specular(&set->lights[LIGHT_CHARA], &ibl_specular); + light_get_ibl_back(&set->lights[LIGHT_CHARA], &ibl_back); + light_get_diffuse(&set->lights[LIGHT_CHARA], &diffuse); + light_get_specular(&set->lights[LIGHT_CHARA], &specular); + + shader_env_vert_set_ptr(&shaders_ft, 5, &position); + shader_env_frag_set_ptr(&shaders_ft, 5, &position); + + vec4_mult(diffuse, ibl_specular, temp); + shader_env_vert_set_ptr(&shaders_ft, 6, &temp); + shader_env_frag_set_ptr(&shaders_ft, 6, &temp); + + vec4_mult(specular, ibl_specular, temp); + vec4_mult_scalar(temp, spec_coef, temp); + shader_env_vert_set_ptr(&shaders_ft, 7, &temp); + shader_env_frag_set_ptr(&shaders_ft, 7, &temp); + + vec4_mult_scalar(ibl_specular, luce_coef, temp); + shader_env_vert_set_ptr(&shaders_ft, 8, &temp); + shader_env_frag_set_ptr(&shaders_ft, 8, &temp); + + vec4_mult(specular, ibl_back, temp); + vec4_mult_scalar(temp, spec_coef, temp); + shader_env_vert_set_ptr(&shaders_ft, 9, &temp); + shader_env_frag_set_ptr(&shaders_ft, 9, &temp); + + light_get_position_vec4(&set->lights[LIGHT_STAGE], &position); + light_get_direction_from_position(&position, &set->lights[LIGHT_STAGE], 0); + light_get_ibl_specular(&set->lights[LIGHT_STAGE], &ibl_specular); + light_get_diffuse(&set->lights[LIGHT_STAGE], &diffuse); + light_get_specular(&set->lights[LIGHT_STAGE], &specular); + + shader_env_vert_set_ptr(&shaders_ft, 10, &position); + shader_env_frag_set_ptr(&shaders_ft, 14, &position); + + vec4_mult(diffuse, ibl_specular, temp); + shader_env_vert_set_ptr(&shaders_ft, 11, &temp); + shader_env_frag_set_ptr(&shaders_ft, 16, &temp); + + vec4_mult(specular, ibl_specular, temp); + vec4_mult_scalar(temp, spec_coef, temp); + shader_env_vert_set_ptr(&shaders_ft, 12, &temp); + shader_env_frag_set_ptr(&shaders_ft, 17, &temp); + + mat4* irradiance_r; + mat4* irradiance_g; + mat4* irradiance_b; + light_set_get_irradiance_ptr(set, &irradiance_r, &irradiance_g, &irradiance_b); + shader_state_matrix_set_program(&shaders_ft, 0, irradiance_r); + shader_state_matrix_set_program(&shaders_ft, 1, irradiance_g); + shader_state_matrix_set_program(&shaders_ft, 2, irradiance_b); + + float_t offset = face_get_offset(face); + float_t v28 = (float_t)(1.0 - exp(offset * -0.44999999)) * 2.0f; + offset = max(offset, 0.0f); + shader_env_vert_set(&shaders_ft, 0x11, v28 * 0.1f, offset * 0.06f, 1.0, 1.0); + + if (light_get_type(&set->lights[LIGHT_CHARA_COLOR]) == LIGHT_PARALLEL) { + light_get_ambient(&set->lights[LIGHT_CHARA_COLOR], &ambient); + light_get_diffuse(&set->lights[LIGHT_CHARA_COLOR], &diffuse); + light_get_specular(&set->lights[LIGHT_CHARA_COLOR], &specular); + if (specular.w > 1.0) + specular.w = 1.0; + shader_env_frag_set_ptr(&shaders_ft, 33, &ambient); + shader_env_frag_set_ptr(&shaders_ft, 34, &diffuse); + shader_env_frag_set_ptr(&shaders_ft, 35, &specular); + } + else { + shader_env_frag_set_ptr(&shaders_ft, 33, (vec4*)&vec4_null); + shader_env_frag_set_ptr(&shaders_ft, 34, (vec4*)&vec4_null); + shader_env_frag_set_ptr(&shaders_ft, 35, (vec4*)&vec4_null); + } + + if (light_get_type(&set->lights[LIGHT_TONE_CURVE]) == LIGHT_PARALLEL) { + uniform_value[U_TONE_CURVE] = 1; + light_get_position_vec4(&set->lights[LIGHT_TONE_CURVE], &position); + light_get_direction_from_position(&position, &set->lights[LIGHT_TONE_CURVE], 0); + light_get_ambient(&set->lights[LIGHT_TONE_CURVE], &ambient); + light_get_diffuse(&set->lights[LIGHT_TONE_CURVE], &diffuse); + light_get_specular(&set->lights[LIGHT_TONE_CURVE], &specular); + vec3 tone_curve; + light_get_tone_curve(&set->lights[LIGHT_TONE_CURVE], &tone_curve); + tone_curve.y = min(tone_curve.y, 1.0f) - tone_curve.x; + if (tone_curve.y > 0.0f) + tone_curve.y = 1.0f / tone_curve.y; + else + tone_curve.y = 0.0f; + + shader_env_frag_set_ptr(&shaders_ft, 36, &position); + shader_env_frag_set_ptr(&shaders_ft, 37, &ambient); + shader_env_frag_set_ptr(&shaders_ft, 38, &diffuse); + shader_env_frag_set_ptr(&shaders_ft, 39, &specular); + shader_env_frag_set(&shaders_ft, 40, tone_curve.x, tone_curve.y, tone_curve.z, 0.0f); + } + else { + uniform_value[U_TONE_CURVE] = 0; + shader_env_frag_set(&shaders_ft, 36, 0.0f, 1.0f, 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 37, 0.0f, 0.0f, 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 38, 0.0f, 0.0f, 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 39, 0.0f, 0.0f, 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 40, 0.0f, 0.0f, 0.0f, 0.0f); + } + + light_get_position_vec4(&set->lights[LIGHT_CHARA], &position); + if (fabs(position.x) <= 0.000001f && fabs(position.z) <= 0.000001f && fabs(position.z) <= 0.000001f) + position = (vec4){ 0.0f, 1.0f, 0.0f, 1.0f }; + else { + float_t length; + vec3_length(*(vec3*)&position, length); + if (length != 0.0f) + vec3_mult_scalar(*(vec3*)&position, 1.0f / length, *(vec3*)&position); + } + + shader_env_vert_set(&shaders_ft, 15, position.x, position.y, position.z, 1.0f); + shader_env_vert_set(&shaders_ft, 16, -position.x, -position.y, -position.z, 1.0f); + + if (light_get_type(&set->lights[LIGHT_REFLECT]) == LIGHT_SPOT) { + vec4 spot_direction; + light_get_spot_direction(&set->lights[LIGHT_REFLECT], (vec3*)&spot_direction); + vec3_negate(*(vec3*)&spot_direction, *(vec3*)&spot_direction); + light_get_direction_from_position(&spot_direction, &set->lights[LIGHT_REFLECT], 1); + light_get_position_vec4(&set->lights[LIGHT_REFLECT], &position); + vec3_dot(*(vec3*)&position, *(vec3*)&spot_direction, spot_direction.w); + + shader_env_vert_set_ptr(&shaders_ft, 28, &spot_direction); + shader_env_frag_set_ptr(&shaders_ft, 22, &spot_direction); + } + else if (light_get_type(&set->lights[LIGHT_REFLECT]) == LIGHT_POINT) { + shader_env_vert_set(&shaders_ft, 28, 0.0f, -1.0f, 0.0f, 9999.0f); + shader_env_frag_set(&shaders_ft, 22, 0.0f, -1.0f, 0.0f, 9999.0f); + } + else { + shader_env_vert_set(&shaders_ft, 28, 0.0f, -1.0f, 0.0f, 0.0f); + shader_env_frag_set(&shaders_ft, 22, 0.0f, -1.0f, 0.0f, 0.0f); + } + + mat4 v63 = mat4_identity; + mat4 v64 = mat4_identity; + + light_get_ibl_direction(&set->lights[LIGHT_CHARA], &ibl_direction); + light_get_position_vec4(&set->lights[LIGHT_CHARA], &position); + + float_t length; + vec3_length(*(vec3*)&ibl_direction, length); + if (length >= 0.000001f) { + vec3_mult_scalar(*(vec3*)&ibl_direction, 1.0f / length, *(vec3*)&ibl_direction); + + vec3_length(*(vec3*)&position, length); + if (length >= 0.000001f) { + vec3_mult_scalar(*(vec3*)&position, 1.0f / length, *(vec3*)&position); + + vec3 axis; + vec3_cross(*(vec3*)&ibl_direction, *(vec3*)&position, axis) + + vec3_length(axis, length); + + float_t v52; + vec3_dot(*(vec3*)&position, *(vec3*)&ibl_direction, v52); + + float_t angle = fabsf(atan2f(length, v52)); + if (angle >= 0.01f && angle <= 3.131592653589793f) { + if (length != 0.0f) + vec3_mult_scalar(axis, 1.0f / length, axis); + + mat4_from_axis_angle(&axis, -angle, &v63); + mat4_from_axis_angle(&axis, -angle, &v64); + } + } + } + + mat4_transpose(&v63, &v63); + shader_env_frag_set_ptr(&shaders_ft, 26, &v63.row0); + shader_env_frag_set_ptr(&shaders_ft, 27, &v63.row1); + shader_env_frag_set_ptr(&shaders_ft, 28, &v63.row2); + shader_env_frag_set_ptr(&shaders_ft, 42, &npr_spec_color); +} + +static void light_get_direction_from_position(vec4* pos_dir, light_data* light, bool force) { + if (force || light_get_type(light) == LIGHT_PARALLEL) { + float_t length; + vec3_length(*(vec3*)pos_dir, length); + if (length <= 0.000001) + *(vec3*)pos_dir = (vec3){ 0.0f, 1.0f, 0.0f }; + else + vec3_mult_scalar(*(vec3*)pos_dir, 1.0f / length, *(vec3*)pos_dir); + pos_dir->w = 0.0f; + } +} diff --git a/src/CRE/light_param/light.h b/src/CRE/light_param/light.h new file mode 100644 index 00000000..8ffcd7ab --- /dev/null +++ b/src/CRE/light_param/light.h @@ -0,0 +1,83 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/light_param/light.h" +#include "../../KKdLib/vec.h" +#include "../static_var.h" +#include "face.h" + +typedef struct light_data { + light_type type; + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 position; + vec3 spot_direction; + float_t spot_exponent; + float_t spot_cutoff; + float_t constant; + float_t linear; + float_t quadratic; + vec4 ibl_specular; + vec4 ibl_back; + vec4 ibl_direction; + vec3 tone_curve; + bool clip_plane[4]; +} light_data; + +typedef struct light_set { + light_data lights[LIGHT_MAX]; + vec4 ambient_intensity; + mat4 irradiance_r; + mat4 irradiance_g; + mat4 irradiance_b; +} light_set; + +extern void light_set_init(light_set* set); +extern light_type light_get_type(light_data* light); +extern void light_set_type(light_data* light, light_type value); +extern void light_get_ambient(light_data* light, vec4* value); +extern void light_set_ambient(light_data* light, vec4* value); +extern void light_get_diffuse(light_data* light, vec4* value); +extern void light_set_diffuse(light_data* light, vec4* value); +extern void light_get_specular(light_data* light, vec4* value); +extern void light_set_specular(light_data* light, vec4* value); +extern void light_get_position(light_data* light, vec3* value); +extern void light_set_position(light_data* light, vec3* value); +extern void light_get_position_vec4(light_data* light, vec4* value); +extern void light_set_position_vec4(light_data* light, vec4* value); +extern void light_get_spot_direction(light_data* light, vec3* value); +extern void light_set_spot_direction(light_data* light, vec3* value); +extern float_t light_get_spot_exponent(light_data* light); +extern void light_set_spot_exponent(light_data* light, float_t value); +extern float_t light_get_spot_cutoff(light_data* light); +extern void light_set_spot_cutoff(light_data* light, float_t value); +extern float_t light_get_constant(light_data* light); +extern void light_set_constant(light_data* light, float_t value); +extern float_t light_get_linear(light_data* light); +extern void light_set_linear(light_data* light, float_t value); +extern float_t light_get_quadratic(light_data* light); +extern void light_set_quadratic(light_data* light, float_t value); +extern void light_get_attenuation(light_data* light, vec3* value); +extern void light_set_attenuation(light_data* light, vec3* value); +extern void light_get_ibl_specular(light_data* light, vec4* value); +extern void light_set_ibl_specular(light_data* light, vec4* value); +extern void light_get_ibl_back(light_data* light, vec4* value); +extern void light_set_ibl_back(light_data* light, vec4* value); +extern void light_get_ibl_direction(light_data* light, vec4* value); +extern void light_set_ibl_direction(light_data* light, vec4* value); +extern void light_get_tone_curve(light_data* light, vec3* value); +extern void light_set_tone_curve(light_data* light, vec3* value); +extern void light_get_clip_plane(light_data* light, bool value[4]); +extern void light_set_clip_plane(light_data* light, bool value[4]); +extern void light_set_get_ambient_intensity(light_set* set, vec4* value); +extern void light_set_set_ambient_intensity(light_set* set, vec4* value); +extern void light_set_get_irradiance(light_set* set, mat4* r, mat4* g, mat4* b); +extern void light_set_get_irradiance_ptr(light_set* set, mat4** r, mat4** g, mat4** b); +extern void light_set_set_irradiance(light_set* set, mat4* r, mat4* g, mat4* b); +extern void light_set_data_set(light_set* set, face* face, light_set_id id); diff --git a/src/CRE/light_param/wind.c b/src/CRE/light_param/wind.c new file mode 100644 index 00000000..f1ad1b4a --- /dev/null +++ b/src/CRE/light_param/wind.c @@ -0,0 +1,103 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "wind.h" + +static float_t wind_apply_spc(wind* wind, float_t frame); + +wind* wind_init() { + wind* w = force_malloc(sizeof(wind)); + w->count = 16; + return w; +} + +float_t wind_get_scale(wind* w) { + return w->scale; +} + +void wind_set_scale(wind* w, float_t value) { + w->scale = value; +} + +float_t wind_get_cycle(wind* w) { + return w->cycle; +} + +void wind_set_cycle(wind* w, float_t value) { + w->cycle = value; +} + +void wind_get_rot(wind* w, vec2* value) { + value->x = w->rot_y; + value->y = w->rot_z; +} + +void wind_set_rot(wind* w, vec2* value) { + w->rot_y = value->x; + w->rot_z = value->y; +} + +float_t wind_get_rot_y(wind* w) { + return w->rot_y; +} + +void wind_set_rot_y(wind* w, float_t value) { + w->rot_y = value; +} + +float_t wind_get_rot_z(wind* w) { + return w->rot_z; +} + +void wind_set_rot_z(wind* w, float_t value) { + w->rot_z = value; +} + +float_t wind_get_bias(wind* w) { + return w->bias; +} + +void wind_set_bias(wind* w, float_t value) { + w->bias = value; +} + +void wind_reset(wind* w) { + w->strength = 0.0f; + w->frame = 0.0f; +} + +void wind_update(wind* w) { + float_t value = wind_apply_spc(w, w->cycle * w->frame) * w->scale; + mat4 mat = mat4_identity; + mat4_rotate_y_mult(&mat, w->rot_y * DEG_TO_RAD_FLOAT, &mat); + mat4_rotate_z_mult(&mat, w->rot_z * DEG_TO_RAD_FLOAT, &mat); + vec3 wind_direction = vec3_identity; + wind_direction.x = value; + mat4_mult_vec3(&mat, &wind_direction, &wind_direction); + vec3_mult_scalar(wind_direction, w->strength, w->wind_direction); + if (w->strength >= 1.0f) + w->strength = 1.0f; + else + w->strength = w->strength + (float_t)(1.0 / 60.0); + + w->frame += get_delta_frame(); + if (w->frame > 65535.0f) + w->frame = 0.0f; +} + +void wind_free(wind* w) { + free(w); +} + +static float_t wind_apply_spc(wind* wind, float_t frame) { + size_t count = wind->count; + float_t value = 0.0f; + wind_spc* spc = wind->spc; + for (size_t i = 0; i < count; i++, spc++) { + float_t power = (float_t)(1 << (int32_t)i) * frame; + value += cosf(power) * spc->cos + sinf(power) * spc->sin; + } + return value + wind->bias; +} diff --git a/src/CRE/light_param/wind.h b/src/CRE/light_param/wind.h new file mode 100644 index 00000000..8fe415c7 --- /dev/null +++ b/src/CRE/light_param/wind.h @@ -0,0 +1,46 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/light_param/wind.h" +#include "../../KKdLib/vec.h" +#include "../static_var.h" + +typedef struct wind_spc { + float_t cos; + float_t sin; +} wind_spc; + +typedef struct wind { + float_t scale; + float_t cycle; + float_t rot_y; + float_t rot_z; + float_t bias; + size_t count; + wind_spc spc[16]; + vec3 wind_direction; + float_t frame; + float_t strength; +} wind; + +extern wind* wind_init(); +extern float_t wind_get_scale(wind* w); +extern void wind_set_scale(wind* w, float_t value); +extern float_t wind_get_cycle(wind* w); +extern void wind_set_cycle(wind* w, float_t value); +extern void wind_get_rot(wind* w, vec2* value); +extern void wind_set_rot(wind* w, vec2* value); +extern float_t wind_get_rot_y(wind* w); +extern void wind_set_rot_y(wind* w, float_t value); +extern float_t wind_get_rot_z(wind* w); +extern void wind_set_rot_z(wind* w, float_t value); +extern float_t wind_get_bias(wind* w); +extern void wind_set_bias(wind* w, float_t value); +extern void wind_reset(wind* w); +extern void wind_update(wind* w); +extern void wind_free(wind* w); diff --git a/src/CRE/lock.c b/src/CRE/lock.c index deec2d44..53108e86 100644 --- a/src/CRE/lock.c +++ b/src/CRE/lock.c @@ -18,3 +18,33 @@ inline void lock_free(lock* l) { DeleteCriticalSection(&l->cs); l->init = FALSE; } + +inline bool lock_data_init(lock_data* ld, lock* l, + void* data, void(*free_func)(void* data)) { + if (ld->lock_free && ld->lock_free != free_func) { + lock* lock = ld->lock; + lock_lock(lock); + ld->lock_free(ld->lock_data); + lock_unlock(lock); + + if (ld->lock_free) + return false; + } + else if (ld->lock_free) + ld->lock_free(ld->lock_data); + + ld->lock = l; + ld->lock_data = data; + ld->lock_free = free_func; + return true; +} + +inline bool lock_data_free(lock_data* ld, void(*free_func)(void* data)) { + if (ld->lock_free != free_func) + return false; + + ld->lock = 0; + ld->lock_data = 0; + ld->lock_free = 0; + return true; +} \ No newline at end of file diff --git a/src/CRE/lock.h b/src/CRE/lock.h index 728de758..53abc3bd 100644 --- a/src/CRE/lock.h +++ b/src/CRE/lock.h @@ -9,13 +9,22 @@ typedef struct lock { CRITICAL_SECTION cs; - BOOL init; + bool init; } lock; +typedef struct lock_data { + lock* lock; + void* lock_data; + void(*lock_free)(void* data); +} lock_data; + #define lock_lock(val) \ -if ((val)->init) { \ +if ((val) && (val)->init) { \ EnterCriticalSection(&(val)->cs) +#define lock_trylock(val) \ +if ((val) && (val)->init && TryEnterCriticalSection(&(val)->cs)) { + #define lock_unlock(val) \ LeaveCriticalSection(&(val)->cs); \ } @@ -23,3 +32,7 @@ LeaveCriticalSection(&(val)->cs); \ extern void lock_init(lock* l); extern bool lock_check_init(lock* l); extern void lock_free(lock* l); + +extern bool lock_data_init(lock_data* ld, lock* l, + void* data, void(*free_func)(void* data)); +extern bool lock_data_free(lock_data* ld, void(*free_func)(void* data)); diff --git a/src/CRE/object.c b/src/CRE/object.c new file mode 100644 index 00000000..f3689717 --- /dev/null +++ b/src/CRE/object.c @@ -0,0 +1,1533 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "object.h" +#include "data.h" +#include "gl_state.h" +#include "shader_ft.h" +#include "../KKdLib/str_utils.h" + +typedef obj object_file; +typedef obj_material_data object_material_data_file; +typedef obj_material object_material_file; +typedef obj_material_texture object_material_texture_file; +typedef obj_mesh object_mesh_file; +typedef obj_set object_set_file; +typedef obj_skin object_skin_file; +typedef obj_skin_block object_skin_block_file; +typedef obj_skin_block_cloth object_skin_block_cloth_file; +typedef obj_skin_block_constraint object_skin_block_constraint_file; +typedef obj_skin_block_constraint_attach_point object_skin_block_constraint_attach_point_file; +typedef obj_skin_block_constraint_direction object_skin_block_constraint_direction_file; +typedef obj_skin_block_constraint_distance object_skin_block_constraint_distance_file; +typedef obj_skin_block_constraint_orientation object_skin_block_constraint_orientation_file; +typedef obj_skin_block_constraint_position object_skin_block_constraint_position_file; +typedef obj_skin_block_constraint_up_vector object_skin_block_constraint_up_vector_file; +typedef obj_skin_block_expression object_skin_block_expression_file; +typedef obj_skin_block_motion object_skin_block_motion_file; +typedef obj_skin_block_node object_skin_block_node_file; +typedef obj_skin_block_osage object_skin_block_osage_file; +typedef obj_skin_bone object_skin_bone_file; +typedef obj_skin_ex_data object_skin_ex_data_file; +typedef obj_skin_osage_node object_skin_osage_node_file; +typedef obj_skin_osage_sibling_info object_skin_osage_sibling_info_file; +typedef obj_skin_motion_node object_skin_motion_node_file; +typedef obj_sub_mesh object_sub_mesh_file; +typedef obj_vertex_data object_vertex_data_file; + +typedef struct object_storage { + uint32_t set_id; + int32_t count; + object_set set; +} object_storage; + +vector(object_storage) + +static bool object_mesh_index_buffer_load(object_mesh_index_buffer* buffer, object_mesh* mesh); +static GLuint object_mesh_index_buffer_load_data(size_t size, void* data); +static void object_mesh_index_buffer_free(object_mesh_index_buffer* buffer); +static bool object_mesh_vertex_buffer_load(object_mesh_vertex_buffer* buffer, object_mesh* mesh); +static bool object_mesh_vertex_buffer_load_data(object_mesh_vertex_buffer* buffer, + size_t size, void* data, int32_t count); +static void object_mesh_vertex_buffer_free(object_mesh_vertex_buffer* buffer); +static bool object_set_index_buffer_load(object_set* set); +static void object_set_index_buffer_free(object_set* set); +static bool object_set_vertex_buffer_load(object_set* set); +static void object_set_vertex_buffer_free(object_set* set); +static void object_skin_block_constraint_attach_point_load( + object_skin_block_constraint_attach_point* attach_point, + object_skin_block_constraint_attach_point_file* attach_point_file); +static void object_skin_block_constraint_up_vector_load( + object_skin_block_constraint_up_vector* up_vector, + object_skin_block_constraint_up_vector_file* up_vector_file); +static void object_skin_block_node_load(object_skin_block_node* node, + object_skin_block_node_file* node_file); +static void object_skin_block_node_free(object_skin_block_node* node); +static size_t object_vertex_flags_get_vertex_size(object_vertex_flags flags); +static size_t object_vertex_flags_get_vertex_size_comp(object_vertex_flags flags); +static bool object_set_load_file(void* data, char* path, char* file, uint32_t hash); +static bool object_set_load_file_modern(void* data, char* path, char* file, uint32_t hash); + +vector_func(object_storage) + +vector_object_storage object_storage_data; + +void object_set_init(object_set* set) { + if (!set) + return; + + memset(set, 0, sizeof(object_set)); +} + +void object_set_load(object_set* set, obj_set* obj_set_file, txp_set* txp_set_file, + texture_database* tex_db, string* name, uint32_t id, bool compressed) { + if (!set || !obj_set_file || !txp_set_file || !tex_db || !name) + return; + + bool is_x = obj_set_file->is_x; + set->is_x = is_x; + set->texture_ids_count = obj_set_file->texture_ids_count; + set->texture_ids = force_malloc_s(uint32_t, obj_set_file->texture_ids_count); + memcpy(set->texture_ids, obj_set_file->texture_ids, obj_set_file->texture_ids_count * sizeof(uint32_t)); + + set->texture_names_count = obj_set_file->texture_ids_count; + set->texture_names = force_malloc_s(string, obj_set_file->texture_ids_count); + if (tex_db->ready) + for (int32_t i = 0; i < set->texture_names_count; i++) { + int32_t texture_id = set->texture_ids[i]; + string* name = &set->texture_names[i]; + *name = string_empty; + + for (texture_info* j = tex_db->texture.begin; j != tex_db->texture.end; j++) + if (j->id == texture_id) { + string_copy(&j->name, name); + break; + } + + if (!name->length) { + char buf[0x100]; + int32_t len = sprintf_s(buf, sizeof(buf), "TEXTURE_%d", i); + string_init_length(name, buf, len); + } + } + else + for (int32_t i = 0; i < set->texture_names_count; i++) { + string* name = &set->texture_names[i]; + + char buf[0x100]; + int32_t len = sprintf_s(buf, sizeof(buf), "TEXTURE_%d", i); + string_init_length(name, buf, len); + } + + string_copy(name, &set->name); + set->id = id; + + int32_t objects_count = obj_set_file->objects_count; + set->objects_count = objects_count; + set->objects = force_malloc_s(object, objects_count); + for (int32_t i = 0; i < objects_count; i++) { + object* obj = &set->objects[i]; + object_file* obj_file = &obj_set_file->objects[i]; + obj->bounding_sphere.center = obj_file->bounding_sphere.center; + obj->bounding_sphere.radius = obj_file->bounding_sphere.radius; + + int32_t meshes_count = obj_file->meshes_count; + obj->meshes_count = meshes_count; + obj->meshes = force_malloc_s(object_mesh, meshes_count); + for (int32_t j = 0; j < meshes_count; j++) { + object_mesh* mesh = &obj->meshes[j]; + object_mesh_file* mesh_file = &obj_file->meshes[j]; + + mesh->bounding_sphere.center = mesh_file->bounding_sphere.center; + mesh->bounding_sphere.radius = mesh_file->bounding_sphere.radius; + + int32_t sub_meshes_count = mesh_file->sub_meshes_count; + mesh->sub_meshes_count = sub_meshes_count; + mesh->sub_meshes = force_malloc_s(object_sub_mesh, sub_meshes_count); + for (int32_t k = 0; k < sub_meshes_count; k++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[k]; + object_sub_mesh_file* sub_mesh_file = &mesh_file->sub_meshes[k]; + + sub_mesh->bounding_sphere.center = sub_mesh_file->bounding_sphere.center; + sub_mesh->bounding_sphere.radius = sub_mesh_file->bounding_sphere.radius; + sub_mesh->material_index = sub_mesh_file->material_index; + memcpy(sub_mesh->texcoord_indices, sub_mesh_file->texcoord_indices, + sizeof(sub_mesh_file->texcoord_indices)); + + sub_mesh->bone_indices_count = sub_mesh_file->bone_indices_count; + sub_mesh->bone_indices = force_malloc_s(uint16_t, sub_mesh_file->bone_indices_count); + memcpy(sub_mesh->bone_indices, sub_mesh_file->bone_indices, + sub_mesh_file->bone_indices_count * sizeof(uint16_t)); + sub_mesh->bones_per_vertex = sub_mesh_file->bones_per_vertex; + sub_mesh->primitive_type = sub_mesh_file->primitive_type; + sub_mesh->index_format = sub_mesh_file->index_format; + sub_mesh->flags = sub_mesh_file->flags; + + bool u16 = sub_mesh_file->index_format == OBJ_INDEX_U16; + vec3 _min = (vec3){ 9999999.0f, 9999999.0f, 9999999.0f }; + vec3 _max = (vec3){ -100000000.0f, -100000000.0f, -100000000.0f }; + + uint32_t* indices = (uint32_t*)sub_mesh_file->indices; + int32_t indices_count = sub_mesh_file->indices_count; + object_vertex_data_file* vertex = mesh_file->vertex; + if (u16) + for (int32_t l = 0; l < indices_count; l++) { + if (indices[l] == 0xFFFFFFFF) + continue; + + vec3 pos = vertex[indices[l]].position; + vec3_min(_min, pos, _min); + vec3_max(_max, pos, _max); + } + else + for (int32_t l = 0; l < indices_count; l++) { + vec3 pos = vertex[indices[l]].position; + vec3_min(_min, pos, _min); + vec3_max(_max, pos, _max); + } + + vec3 center; + vec3 size; + vec3_add(_max, _min, center); + vec3_mult_scalar(center, 0.5f, center); + vec3_sub(_max, center, size); + sub_mesh->axis_aligned_bounding_box.center = center; + sub_mesh->axis_aligned_bounding_box.size = size; + + sub_mesh->indices_count = indices_count; + sub_mesh->first_index = 0; + sub_mesh->last_index = 0; + sub_mesh->indices_offset = 0; + if (u16) { + uint16_t first_index = 0xFFFF; + uint16_t last_index = 0; + for (int32_t i = 0; i < indices_count; i++) { + uint16_t index = (uint16_t)indices[i]; + if (index == 0xFFFF) + continue; + + if (index < first_index) + first_index = index; + if (index > last_index) + last_index = index; + } + + sub_mesh->first_index = first_index; + sub_mesh->last_index = last_index; + } + } + + mesh->compressed = compressed; + + size_t vertex_size; + if (!compressed) + vertex_size = object_vertex_flags_get_vertex_size(mesh_file->vertex_flags); + else + vertex_size = object_vertex_flags_get_vertex_size_comp(mesh_file->vertex_flags); + + void* vertex = force_malloc(vertex_size * mesh_file->vertex_count); + if (vertex) { + object_vertex_flags flags = mesh_file->vertex_flags; + object_vertex_data_file* vertex_file = mesh_file->vertex; + int32_t vertex_count = mesh_file->vertex_count; + size_t d = (size_t)vertex; + if (!compressed) { + for (int32_t i = 0; i < vertex_count; i++) { + if (flags & OBJECT_VERTEX_POSITION) { + *(vec3*)d = vertex_file[i].position; + d += 12; + } + + if (flags & OBJECT_VERTEX_NORMAL) { + *(vec3*)d = vertex_file[i].normal; + d += 12; + } + + if (flags & OBJECT_VERTEX_TANGENT) { + *(vec4u*)d = vertex_file[i].tangent; + d += 16; + } + + if (flags & OBJECT_VERTEX_BINORMAL) { + *(vec3*)d = vertex_file[i].binormal; + d += 12; + } + + if (flags & OBJECT_VERTEX_TEXCOORD0) { + *(vec2*)d = vertex_file[i].texcoord0; + d += 8; + } + + if (flags & OBJECT_VERTEX_TEXCOORD1) { + *(vec2*)d = vertex_file[i].texcoord1; + d += 8; + } + + if (flags & OBJECT_VERTEX_TEXCOORD2) { + *(vec2*)d = vertex_file[i].texcoord2; + d += 8; + } + + if (flags & OBJECT_VERTEX_TEXCOORD3) { + *(vec2*)d = vertex_file[i].texcoord3; + d += 8; + } + + if (flags & OBJECT_VERTEX_COLOR0) { + *(vec4u*)d = vertex_file[i].color0; + d += 16; + } + + if (flags & OBJECT_VERTEX_COLOR1) { + *(vec4u*)d = vertex_file[i].color1; + d += 16; + } + + if (flags & OBJECT_VERTEX_BONE_DATA) { + *(vec4u*)d = vertex_file[i].bone_weight; + d += 16; + *(vec4iu*)d = vertex_file[i].bone_index; + d += 16; + } + + if (flags & OBJECT_VERTEX_UNKNOWN) { + *(vec4u*)d = vertex_file[i].unknown; + d += 16; + } + } + } + else { + for (int32_t i = 0; i < vertex_count; i++) { + if (flags & OBJECT_VERTEX_POSITION) { + *(vec3*)d = vertex_file[i].position; + d += 12; + } + + if (flags & OBJECT_VERTEX_NORMAL) { + vec3 normal; + vec3_mult_scalar(vertex_file[i].normal, 32727.0f, normal); + vec3_to_vec3i16(normal, *(vec3i16*)d); + *(int16_t*)(d + 6) = 0; + d += 8; + } + + if (flags & OBJECT_VERTEX_TANGENT) { + vec4 tangent; + vec4u_to_vec4(vertex_file[i].tangent, tangent); + vec4_mult_scalar(tangent, 32727.0f, tangent); + vec4_to_vec4i16(tangent, *(vec4i16*)d); + d += 8; + } + + if (flags & OBJECT_VERTEX_TEXCOORD0) { + vec2_to_vec2h(vertex_file[i].texcoord0, *(vec2h*)d); + d += 4; + } + + if (flags & OBJECT_VERTEX_TEXCOORD1) { + vec2_to_vec2h(vertex_file[i].texcoord1, *(vec2h*)d); + d += 4; + } + + if (flags & OBJECT_VERTEX_TEXCOORD2) { + vec2_to_vec2h(vertex_file[i].texcoord2, *(vec2h*)d); + d += 4; + } + + if (flags & OBJECT_VERTEX_TEXCOORD3) { + vec2_to_vec2h(vertex_file[i].texcoord3, *(vec2h*)d); + d += 4; + } + + if (flags & OBJECT_VERTEX_COLOR0) { + vec4 color0; + vec4u_to_vec4(vertex_file[i].color0, color0); + vec4_to_vec4h(color0, *(vec4h*)d); + d += 8; + } + + if (flags & OBJECT_VERTEX_BONE_DATA) { + vec4 bone_weight; + vec4u_to_vec4(vertex_file[i].bone_weight, bone_weight); + vec4_mult_scalar(bone_weight, 65535.0f, bone_weight); + vec4_to_vec4u16(bone_weight, *(vec4u16*)d); + d += 8; + + vec4i bone_index; + vec4iu_to_vec4i(vertex_file[i].bone_index, bone_index); + vec4i_to_vec4u8(bone_index, *(vec4u8*)d); + d += 4; + } + } + } + + mesh->vertex = vertex; + mesh->vertex_count = mesh_file->vertex_count; + mesh->vertex_size = (int32_t)vertex_size; + } + else { + mesh->vertex = 0; + mesh->vertex_count = 0; + mesh->vertex_size = 0; + } + + size_t indices_count = 0; + for (int32_t k = 0; k < mesh->sub_meshes_count; k++) + if (mesh_file->sub_meshes[k].index_format == OBJ_INDEX_U16) + indices_count += mesh_file->sub_meshes[k].indices_count; + + if (indices_count) { + uint16_t* indices = force_malloc_s(uint16_t, indices_count); + size_t offset = 0; + for (int32_t k = 0; k < mesh->sub_meshes_count; k++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[k]; + object_sub_mesh_file* sub_mesh_file = &mesh_file->sub_meshes[k]; + if (sub_mesh->index_format != OBJ_INDEX_U16) + continue; + + int32_t sub_mesh_indices_count = sub_mesh_file->indices_count; + uint32_t* sub_mesh_indices = sub_mesh_file->indices; + for (int32_t l = 0; l < sub_mesh_indices_count; l++) + indices[offset + l] = (uint16_t)sub_mesh_indices[l]; + sub_mesh->indices_offset = (int32_t)(sizeof(uint16_t) * offset); + offset += sub_mesh_file->indices_count; + } + mesh->indices = indices; + mesh->indices_count = (int32_t)indices_count; + } + else { + mesh->indices = 0; + mesh->indices_count = 0; + } + + mesh->vertex_flags = mesh_file->vertex_flags; + mesh->flags = mesh_file->flags; + memcpy(mesh->name, mesh_file->name, sizeof(mesh_file->name)); + mesh->name[sizeof(mesh->name) - 1] = 0; + } + + int32_t materials_count = obj_file->materials_count; + obj->materials_count = materials_count; + obj->materials = force_malloc_s(object_material_data, materials_count); + for (int32_t j = 0; j < materials_count; j++) { + obj->materials[j].textures_count = obj_file->materials[j].textures_count; + + object_material* material = &obj->materials[j].material; + object_material_file* material_file = &obj_file->materials[j].material; + + material->flags = material_file->flags; + material->shader_index = shader_get_index_by_name(&shaders_ft, material_file->shader_name); + memcpy(&material->shader_flags, &material_file->shader_flags, + sizeof(material_file->shader_flags)); + + for (int32_t k = 0; k < 8; k++) { + object_material_texture* textures = &material->textures[k]; + object_material_texture_file* textures_file = &material_file->textures[k]; + + memcpy(&textures->sampler_flags, &textures_file->sampler_flags, + sizeof(textures_file->sampler_flags)); + textures->texture_id = -1; + textures->texture_index = -1; + memcpy(&textures->texture_flags, &textures_file->texture_flags, + sizeof(textures_file->texture_flags)); + memcpy(&textures->shader_name, &textures_file->shader_name, + sizeof(textures_file->shader_name)); + textures->weight = textures_file->weight; + textures->tex_coord_mat = textures_file->tex_coord_mat; + + uint32_t* texture_ids = set->texture_ids; + int32_t texture_ids_count = set->texture_ids_count; + for (int32_t l = 0; l < texture_ids_count; l++) { + if (texture_ids[l] == textures_file->texture_id) { + textures->texture_id = textures_file->texture_id; + textures->texture_index = l; + break; + } + } + } + + material->diffuse = material_file->diffuse; + material->ambient = material_file->ambient; + material->specular = material_file->specular; + material->emission = material_file->emission; + memcpy(&material->blend_flags, &material_file->blend_flags, + sizeof(material_file->blend_flags)); + material->shininess = material_file->shininess; + material->intensity = material_file->intensity; + material->reserved_sphere.center = material_file->reserved_sphere.center; + material->reserved_sphere.radius = material_file->reserved_sphere.radius; + memcpy(material->name, material_file->name, sizeof(material_file->name) - 1); + material->name[sizeof(material->name) - 1] = 0; + material->bump_depth = material_file->bump_depth; + } + + obj->flags = obj_file->flags; + string_copy(&obj_file->name, &obj->name); + obj->id = obj_file->id; + + if (!obj_file->skin_init) { + memset(&obj->skin, 0, sizeof(object_skin)); + obj->skin_init = false; + continue; + } + + object_skin* skin = &obj->skin; + object_skin_file* skin_file = &obj_file->skin; + + int32_t bones_count = skin_file->bones_count; + skin->bones_count = bones_count; + skin->bones = force_malloc_s(object_skin_bone, bones_count); + for (int32_t j = 0; j < bones_count; j++) { + object_skin_bone* bone = &skin->bones[j]; + object_skin_bone_file* bone_file = &skin_file->bones[j]; + + bone->id = bone_file->id; + bone->inv_bind_pose_mat = bone_file->inv_bind_pose_mat; + string_copy(&bone_file->name, &bone->name); + bone->parent = bone_file->parent; + } + obj->skin_init = true; + + if (!skin_file->ex_data_init) { + memset(&skin->ex_data, 0, sizeof(object_skin_ex_data)); + skin->ex_data_init = false; + continue; + } + + object_skin_ex_data* ex_data = &skin->ex_data; + object_skin_ex_data_file* ex_data_file = &skin_file->ex_data; + + int32_t osage_nodes_count = ex_data_file->osage_nodes_count; + ex_data->osage_nodes_count = osage_nodes_count; + ex_data->osage_nodes = force_malloc_s(object_skin_osage_node, osage_nodes_count); + for (int32_t j = 0; j < osage_nodes_count; j++) { + object_skin_osage_node* node = &ex_data->osage_nodes[j]; + object_skin_osage_node_file* node_file = &ex_data_file->osage_nodes[j]; + + node->name_index = node_file->name_index; + node->length = node_file->length; + node->rotation = node_file->rotation; + } + + int32_t bone_names_count = ex_data_file->bone_names_count; + + size_t buf_size = 0; + char** bone_names_file_ptr = ex_data_file->bone_names; + for (int32_t i = 0; i < bone_names_count; i++) + buf_size += utf8_length(*bone_names_file_ptr++) + 1; + + ex_data->bone_names_buf = force_malloc(buf_size); + ex_data->bone_names = force_malloc_s(char*, buf_size + 1); + ex_data->bone_names_count = bone_names_count; + + bone_names_file_ptr = ex_data_file->bone_names; + char* bone_names_buf = ex_data->bone_names_buf; + char** bone_names_ptr = ex_data->bone_names; + for (int32_t i = 0; i < bone_names_count; i++) { + *bone_names_ptr++ = bone_names_buf; + size_t len = utf8_length(*bone_names_file_ptr); + memcpy(bone_names_buf, *bone_names_file_ptr++, len); + bone_names_buf[len] = 0; + bone_names_buf += len + 1; + } + *bone_names_ptr = 0; + + int32_t blocks_count = ex_data_file->blocks_count; + ex_data->blocks_count = blocks_count; + ex_data->blocks = force_malloc_s(object_skin_block, blocks_count); + for (int32_t j = 0; j < blocks_count; j++) { + object_skin_block* block = &ex_data->blocks[j]; + object_skin_block_file* block_file = &ex_data_file->blocks[j]; + + switch (block_file->type) { + case OBJ_SKIN_BLOCK_CLOTH: { + block->type = OBJECT_SKIN_BLOCK_CLOTH; + + object_skin_block_cloth* cloth = &block->cloth; + object_skin_block_cloth_file* cloth_file = &block_file->cloth; + + } break; + case OBJ_SKIN_BLOCK_CONSTRAINT: { + block->type = OBJECT_SKIN_BLOCK_CONSTRAINT; + + object_skin_block_constraint* constraint = &block->constraint; + object_skin_block_constraint_file* constraint_file = &block_file->constraint; + + switch (constraint_file->type) { + case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: + object_skin_block_node_load(&constraint->base, &constraint_file->base); + constraint->coupling = constraint_file->coupling; + constraint->name_index = constraint_file->name_index; + string_copy(&constraint_file->source_node_name, &constraint->source_node_name); + + constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DIRECTION; + + object_skin_block_constraint_direction* direction = &constraint->direction; + object_skin_block_constraint_direction_file* direction_file + = &constraint_file->direction; + + object_skin_block_constraint_up_vector_load( + &direction->up_vector, &direction_file->up_vector); + direction->align_axis = direction_file->align_axis; + direction->target_offset = direction_file->target_offset; + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: + object_skin_block_node_load(&constraint->base, &constraint_file->base); + constraint->coupling = constraint_file->coupling; + constraint->name_index = constraint_file->name_index; + string_copy(&constraint_file->source_node_name, &constraint->source_node_name); + + constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DISTANCE; + + object_skin_block_constraint_distance* distance = &constraint->distance; + object_skin_block_constraint_distance_file* distance_file + = &constraint_file->distance; + + object_skin_block_constraint_up_vector_load( + &distance->up_vector, &distance_file->up_vector); + distance->distance = distance_file->distance; + object_skin_block_constraint_attach_point_load( + &distance->constrained_object, &distance_file->constrained_object); + object_skin_block_constraint_attach_point_load( + &distance->constraining_object, &distance_file->constraining_object); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: + object_skin_block_node_load(&constraint->base, &constraint_file->base); + constraint->coupling = constraint_file->coupling; + constraint->name_index = constraint_file->name_index; + string_copy(&constraint_file->source_node_name, &constraint->source_node_name); + + constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_ORIENTATION; + + object_skin_block_constraint_orientation* orientation = &constraint->orientation; + object_skin_block_constraint_orientation_file* orientation_file + = &constraint_file->orientation; + + orientation->offset = orientation_file->offset; + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: + object_skin_block_node_load(&constraint->base, &constraint_file->base); + constraint->coupling = constraint_file->coupling; + constraint->name_index = constraint_file->name_index; + string_copy(&constraint_file->source_node_name, &constraint->source_node_name); + + constraint->type = OBJECT_SKIN_BLOCK_CONSTRAINT_POSITION; + + object_skin_block_constraint_position* position = &constraint->position; + object_skin_block_constraint_position_file* position_file + = &constraint_file->position; + + object_skin_block_constraint_up_vector_load( + &position->up_vector, &position_file->up_vector); + string_copy(&position_file->up_vector.name, &position->up_vector.name); + object_skin_block_constraint_attach_point_load( + &position->constrained_object, &position_file->constrained_object); + object_skin_block_constraint_attach_point_load( + &position->constraining_object, &position_file->constraining_object); + break; + default: + memset(block, 0, sizeof(object_skin_block)); + break; + } + + } break; + case OBJ_SKIN_BLOCK_EXPRESSION: { + block->type = OBJECT_SKIN_BLOCK_EXPRESSION; + + object_skin_block_expression* expression = &block->expression; + object_skin_block_expression_file* expression_file = &block_file->expression; + + object_skin_block_node_load(&expression->base, &expression_file->base); + + expression->name_index = expression_file->name_index; + int32_t expressions_count = min(expression_file->expressions_count, 9); + expression->expressions_count = expressions_count; + for (int32_t k = 0; k < expressions_count; k++) + string_copy(&expression_file->expressions[k], &expression->expressions[k]); + + for (int32_t k = expressions_count; k < 9; k++) + expression->expressions[k] = string_empty; + + } break; + case OBJ_SKIN_BLOCK_MOTION: { + block->type = OBJECT_SKIN_BLOCK_MOTION; + + object_skin_block_motion* motion = &block->motion; + object_skin_block_motion_file* motion_file = &block_file->motion; + + object_skin_block_node_load(&motion->base, &motion_file->base); + + int32_t nodes_count = motion_file->nodes_count; + if (!is_x) + motion->name_index = motion_file->name_index; + else + string_copy(&motion_file->name, &motion->name); + motion->nodes_count = nodes_count; + motion->nodes = force_malloc_s(object_skin_motion_node, nodes_count); + for (int32_t k = 0; k < nodes_count; k++) { + object_skin_motion_node* node = &motion->nodes[j]; + object_skin_motion_node_file* node_file = &motion_file->nodes[j]; + + node->name_index = node_file->name_index; + node->transformation = node_file->transformation; + } + + } break; + case OBJ_SKIN_BLOCK_OSAGE: { + block->type = OBJECT_SKIN_BLOCK_OSAGE; + + object_skin_block_osage* osage = &block->osage; + object_skin_block_osage_file* osage_file = &block_file->osage; + + object_skin_block_node_load(&osage->base, &osage_file->base); + osage->start_index = osage_file->start_index; + osage->count = osage_file->count; + + int32_t nodes_count = osage_file->nodes_count; + osage->nodes_count = nodes_count; + osage->nodes = force_malloc_s(object_skin_osage_node, nodes_count); + for (int32_t k = 0; k < nodes_count; k++) { + object_skin_osage_node* node = &osage->nodes[j]; + object_skin_osage_node_file* node_file = &osage_file->nodes[j]; + + node->name_index = node_file->name_index; + node->length = node_file->length; + node->rotation = node_file->rotation; + } + + osage->external_name_index = osage_file->external_name_index; + osage->name_index = osage->name_index; + string_copy(&osage_file->motion_node_name, &osage->motion_node_name); + } break; + default: + memset(block, 0, sizeof(object_skin_block)); + break; + } + } + + int32_t osage_sibling_infos_count = ex_data_file->osage_sibling_infos_count; + ex_data->osage_sibling_infos_count = osage_sibling_infos_count; + ex_data->osage_sibling_infos = force_malloc_s( + object_skin_osage_sibling_info, osage_sibling_infos_count); + for (int32_t j = 0; j < osage_sibling_infos_count; j++) { + object_skin_osage_sibling_info* osage_sibling_info = &ex_data->osage_sibling_infos[j]; + object_skin_osage_sibling_info_file* osage_sibling_info_file = &ex_data_file->osage_sibling_infos[j]; + + osage_sibling_info->name_index = osage_sibling_info_file->name_index; + osage_sibling_info->sibling_name_index = osage_sibling_info_file->sibling_name_index; + osage_sibling_info->distance = osage_sibling_info_file->distance; + } + skin->ex_data_init = true; + } + + int32_t textures_count = (int32_t)(txp_set_file->end - txp_set_file->begin); + set->textures_count = textures_count; + set->textures = force_malloc_s(GLuint, textures_count); + texture_txp_set_load(txp_set_file, &set->texture_data, set->texture_ids); + if (set->texture_ids) + for (int32_t i = 0; i < textures_count; i++) + if (set->texture_data[i]) + set->textures[i] = set->texture_data[i]->texture; + else + set->textures[i] = 0; + + object_set_vertex_buffer_load(set); + object_set_index_buffer_load(set); +} + +bool object_set_load_db_entry(object_set_info** set_info, + void* data, object_database* obj_db, char* name) { + if (!object_database_get_object_set_info(obj_db, name, set_info)) + return false; + + size_t temp[2]; + temp[0] = (size_t)data; + temp[1] = (size_t)*set_info; + return data_struct_load_file(data, temp, "rom\\objset\\", + string_data(&(*set_info)->archive_file_name), object_set_load_file); +} + +bool object_set_load_by_db_entry(object_set_info* set_info, + void* data, object_database* obj_db) { + size_t temp[2]; + temp[0] = (size_t)data; + temp[1] = (size_t)set_info; + return data_struct_load_file(data, temp, "rom\\objset\\", + string_data(&set_info->archive_file_name), object_set_load_file); +} + +bool object_set_load_by_db_index(object_set_info** set_info, + void* data, object_database* obj_db, uint32_t set_id) { + if (!object_database_get_object_set_info_by_set_id(obj_db, set_id, set_info)) + return false; + + size_t temp[2]; + temp[0] = (size_t)data; + temp[1] = (size_t)*set_info; + return data_struct_load_file(data, temp, "rom\\objset\\", + string_data(&(*set_info)->archive_file_name), object_set_load_file); +} + +bool object_set_load_by_hash(void* data, + object_database* obj_db, texture_database* tex_db, uint32_t hash) { + size_t temp[2]; + temp[0] = (size_t)obj_db; + temp[1] = (size_t)tex_db; + return data_struct_load_file_by_hash(data, temp, "rom\\objset\\", + hash, object_set_load_file_modern); +} + +void object_set_free(object_set* set) { + if (!set) + return; + + string_free(&set->name); + + bool is_x = set->is_x; + for (int32_t i = 0; i < set->objects_count; i++) { + object* obj = &set->objects[i]; + for (int32_t j = 0; j < obj->skin.bones_count; j++) + string_free(&obj->skin.bones[j].name); + free(obj->skin.bones); + obj->skin.bones_count = 0; + + for (int32_t j = 0; j < obj->skin.ex_data.blocks_count; j++) { + object_skin_block* block = &obj->skin.ex_data.blocks[j]; + switch (block->type) { + case OBJ_SKIN_BLOCK_CLOTH: { + object_skin_block_cloth* cloth = &block->cloth; + string_free(&cloth->mesh_name); + string_free(&cloth->backface_mesh_name); + + for (uint32_t k = 0; k < cloth->count; k++) { + object_skin_block_cloth_field_1C* sub = &cloth->field_1C[k]; + string_free(&sub->sub_data_0.bone_name); + string_free(&sub->sub_data_1.bone_name); + string_free(&sub->sub_data_2.bone_name); + string_free(&sub->sub_data_3.bone_name); + } + free(cloth->field_1C); + free(cloth->field_20); + free(cloth->field_24); + free(cloth->field_28); + cloth->count = 0; + } break; + case OBJ_SKIN_BLOCK_CONSTRAINT: { + object_skin_block_constraint* constraint = &block->constraint; + object_skin_block_node_free(&constraint->base); + string_free(&constraint->source_node_name); + } break; + case OBJ_SKIN_BLOCK_EXPRESSION: { + object_skin_block_expression* expression = &block->expression; + object_skin_block_node_free(&expression->base); + for (int32_t k = 0; k < 9; k++) + string_free(&expression->expressions[k]); + expression->expressions_count = 0; + } break; + case OBJ_SKIN_BLOCK_MOTION: { + object_skin_block_motion* motion = &block->motion; + object_skin_block_node_free(&motion->base); + if (is_x) + string_free(&motion->name); + free(motion->nodes); + motion->nodes_count = 0; + } break; + case OBJ_SKIN_BLOCK_OSAGE: { + object_skin_block_osage* osage = &block->osage; + object_skin_block_node_free(&osage->base); + free(osage->nodes); + osage->nodes_count = 0; + } break; + } + } + free(obj->skin.ex_data.blocks); + obj->skin.ex_data.blocks_count = 0; + + free(obj->skin.ex_data.osage_nodes); + obj->skin.ex_data.osage_nodes_count = 0; + + free(obj->skin.ex_data.bone_names_buf); + free(obj->skin.ex_data.bone_names); + obj->skin.ex_data.bone_names_count = 0; + + free(obj->skin.ex_data.osage_sibling_infos); + obj->skin.ex_data.osage_sibling_infos_count = 0; + + if (obj->meshes) + for (int32_t j = 0; j < obj->meshes_count; j++) { + object_mesh* mesh = &obj->meshes[j]; + if (mesh->sub_meshes) + for (int32_t k = 0; k < mesh->sub_meshes_count; k++) { + object_sub_mesh* sub_mesh = &mesh->sub_meshes[k]; + free(sub_mesh->bone_indices); + sub_mesh->bone_indices_count = 0; + } + free(mesh->vertex); + mesh->vertex_count = 0; + free(mesh->indices); + mesh->indices_count = 0; + free(mesh->sub_meshes); + mesh->sub_meshes_count = 0; + } + free(obj->meshes); + obj->meshes_count = 0; + free(obj->materials); + obj->materials_count = 0; + string_free(&obj->name); + } + free(set->objects); + set->objects_count = 0; + free(set->texture_ids); + set->texture_ids_count = 0; + for (int32_t i = 0; i < set->texture_names_count; i++) + string_free(&set->texture_names[i]); + free(set->texture_names); + set->texture_names_count = 0; + + free(set->textures); + set->textures_count = 0; + free(set->texture_data); + + object_set_vertex_buffer_free(set); + object_set_index_buffer_free(set); +} + +inline object_material_shader_lighting_type object_material_shader_get_lighting_type( + object_material_shader_flags* flags) { + if (!flags->lambert_shading && !flags->phong_shading) + return OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT; + else if (!flags->phong_shading) + return OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT; + else + return OBJECT_MATERIAL_SHADER_LIGHTING_PHONG; +} + +inline int32_t object_material_texture_get_blend(object_material_texture* tex) { + switch (tex->sampler_flags.blend) { + case 4: + return 2; + case 6: + return 1; + case 16: + return 3; + default: + return 0; + } +} + +inline int32_t object_material_texture_type_get_texcoord_index( + object_material_texture_type type, int32_t index) { + switch (type) { + case OBJECT_MATERIAL_TEXTURE_COLOR: + case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD + if (index < 2) + return index; + case OBJECT_MATERIAL_TEXTURE_NORMAL: + case OBJECT_MATERIAL_TEXTURE_SPECULAR: + return 0; + case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY: + case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY: + return 1; + } + return -1; +} + +inline int32_t object_material_texture_type_get_texture_index( + object_material_texture_type type, int32_t base_index) { + switch (type) { + case OBJECT_MATERIAL_TEXTURE_COLOR: + case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // XHD + if (base_index < 2) + return base_index; + case OBJECT_MATERIAL_TEXTURE_NORMAL: + return 2; + case OBJECT_MATERIAL_TEXTURE_SPECULAR: + return 3; + case OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY: + return 1; + case OBJECT_MATERIAL_TEXTURE_TRANSPARENCY: + return 4; + //case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE: // AFT + case OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_CUBE: + return 5; + } + return -1; +} + +inline GLuint object_mesh_vertex_buffer_get_buffer(object_mesh_vertex_buffer* buffer) { + if (buffer->index < buffer->count) + return buffer->buffers[buffer->index]; + else + return 0; +} + +inline int32_t object_mesh_vertex_buffer_get_size(object_mesh_vertex_buffer* buffer) { + if (!buffer->buffers[0]) + return 0; + + int32_t size = 0; + gl_state_bind_array_buffer(buffer->buffers[0]); + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); + gl_state_bind_array_buffer(buffer->buffers[0]); + return size; +} + +void object_skin_set_matrix_buffer(object_skin* s, mat4* matrices, + mat4* ex_data_matrices, mat4* matrix_buffer, mat4* mat, mat4* global_mat) { + if (!s->bones_count) + return; + + if (mat) + for (int32_t i = 0; i < s->bones_count; i++) { + mat4 temp; + int32_t bone_id = s->bones[i].id; + if (bone_id & 0x8000) + if (ex_data_matrices) + mat4_mult(mat, &ex_data_matrices[bone_id & 0x7FFF], &temp); + else + temp = *mat; + else + mat4_mult(mat, &matrices[bone_id], &temp); + + mat4_mult(&temp, global_mat, &temp); + + mat4 inv_bind_pose_mat; + mat4u_to_mat4(&s->bones[i].inv_bind_pose_mat, &inv_bind_pose_mat); + mat4_mult(&inv_bind_pose_mat, &temp, &matrix_buffer[i]); + } + else + for (int32_t i = 0; i < s->bones_count; i++) { + mat4 temp; + int32_t bone_id = s->bones[i].id; + if (bone_id & 0x8000) + if (ex_data_matrices) + temp = ex_data_matrices[bone_id & 0x7FFF]; + else + temp = mat4_identity; + else + temp = matrices[bone_id]; + + mat4_mult(&temp, global_mat, &temp); + + mat4 inv_bind_pose_mat; + mat4u_to_mat4(&s->bones[i].inv_bind_pose_mat, &inv_bind_pose_mat); + mat4_mult(&inv_bind_pose_mat, &temp, &matrix_buffer[i]); + } +} + +inline void object_storage_init() { + object_storage_data = vector_empty(object_storage); +} + +inline void object_storage_append_object_set(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) { + i->count++; + return; + } +} + +inline void object_storage_insert_object_set(object_set* set, uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) { + object_set_free(&i->set); + i->count++; + i->set = *set; + return; + } + + object_storage* obj_set_storage = vector_object_storage_reserve_back(&object_storage_data); + obj_set_storage->set_id = set_id; + obj_set_storage->count = 1; + obj_set_storage->set = *set; +} + +inline object* object_storage_get_object(object_info obj_info) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == obj_info.set_id) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].id == obj_info.id) + return &set->objects[j]; + return 0; + } + return 0; +} + +inline object_mesh* object_storage_get_object_mesh(object_info obj_info, char* mesh_name) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == obj_info.set_id) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].id == obj_info.id) { + object* obj = &set->objects[j]; + for (int32_t k = 0; k < obj->meshes_count; k++) + if (!str_utils_compare(obj->meshes[k].name, mesh_name)) + return &obj->meshes[k]; + return 0; + } + return 0; + } + return 0; +} + +inline object_mesh* object_storage_get_object_mesh_by_index(object_info obj_info, int32_t index) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == obj_info.set_id) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].id == obj_info.id) { + object* obj = &set->objects[j]; + if (index > -1 && index < obj->meshes_count) + return &obj->meshes[index]; + return 0; + } + return 0; + } + return 0; +} + +inline int32_t object_storage_get_object_mesh_index(object_info obj_info, char* mesh_name) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == obj_info.set_id) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].id == obj_info.id) { + object* obj = &set->objects[j]; + for (int32_t k = 0; k < obj->meshes_count; k++) + if (!str_utils_compare(obj->meshes[k].name, mesh_name)) + return k; + return -1; + } + return -1; + } + return -1; +} + +inline object_set* object_storage_get_object_set(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) + return &i->set; + return 0; +} + +inline ssize_t object_storage_get_object_set_count() { + return object_storage_data.end - object_storage_data.begin; +} + +inline object_set* object_storage_get_object_set_by_index(ssize_t index) { + if (index >= 0 && index < object_storage_data.end - object_storage_data.begin) + return &object_storage_data.begin[index].set; + return 0; +} + +inline ssize_t object_storage_get_object_set_index(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) + return i - object_storage_data.begin; + return -1; +} + +inline object_skin* object_storage_get_object_skin(object_info obj_info) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == obj_info.set_id) { + object_set* set = &i->set; + for (int32_t j = 0; j < set->objects_count; j++) + if (set->objects[j].id == obj_info.id) + return set->objects[j].skin_init ? &set->objects[j].skin : 0; + return 0; + } + return 0; +} + +inline object_index_buffer* object_storage_get_object_index_buffers(uint32_t set_id) { + object_set* set = object_storage_get_object_set(set_id); + if (!set || !set->index_buffers) + return 0; + + return set->index_buffers; +} + +inline object_mesh_index_buffer* object_storage_get_object_mesh_index_buffer(object_info obj_info) { + object_set* set = object_storage_get_object_set(obj_info.set_id); + if (!set || !set->index_buffers) + return 0; + + for (int32_t i = 0; i < set->objects_count; i++) + if (set->objects[i].id == obj_info.id) + return set->index_buffers[i].meshes; + + return 0; +} + +inline object_vertex_buffer* object_storage_get_object_vertex_buffers(uint32_t set_id) { + object_set* set = object_storage_get_object_set(set_id); + if (!set || !set->vertex_buffers) + return 0; + + return set->vertex_buffers; +} + +inline object_mesh_vertex_buffer* object_storage_get_object_mesh_vertex_buffer(object_info obj_info) { + object_set* set = object_storage_get_object_set(obj_info.set_id); + if (!set || !set->vertex_buffers) + return 0; + + for (int32_t i = 0; i < set->objects_count; i++) + if (set->objects[i].id == obj_info.id) + return set->vertex_buffers[i].meshes; + + return 0; +} + +inline GLuint* object_storage_get_textures(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) + return i->set.textures; + return 0; +} + +inline uint32_t* object_storage_get_texture_ids(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) + return i->set.texture_ids; + return 0; +} + +inline void object_storage_delete_object_set(uint32_t set_id) { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + if (i->set_id == set_id) { + i->count--; + if (i->count > 0) + break; + + object_set* set = &i->set; + for (int32_t j = 0; j < set->texture_ids_count; j++) + texture_storage_delete_texture(set->texture_ids[j]); + object_set_free(set); + + vector_object_storage_erase(&object_storage_data, + i - object_storage_data.begin, 0); + break; + } +} + +inline void object_storage_free() { + for (object_storage* i = object_storage_data.begin; i != object_storage_data.end; i++) + object_set_free(&i->set); + vector_object_storage_free(&object_storage_data, 0); +} + +static bool object_mesh_index_buffer_load(object_mesh_index_buffer* buffer, object_mesh* mesh) { + if (!mesh->indices_count || !mesh->vertex) { + *buffer = 0; + return true; + } + + *buffer = object_mesh_index_buffer_load_data(sizeof(uint16_t) * mesh->indices_count, mesh->indices); + return true; +} + +static GLuint object_mesh_index_buffer_load_data(size_t size, void* data) { + if (!size) + return 0; + + GLuint buffer = 0; + glGenBuffers(1, &buffer); + gl_state_bind_element_array_buffer(buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW); + gl_state_bind_element_array_buffer(0); + return buffer; +} + +static void object_mesh_index_buffer_free(object_mesh_index_buffer* buffer) { + glDeleteBuffers(1, (GLuint*)buffer); +} + +static bool object_mesh_vertex_buffer_load(object_mesh_vertex_buffer* buffer, object_mesh* mesh) { + if (!mesh->vertex_size || !mesh->vertex_count || !mesh->vertex) + return false; + + return object_mesh_vertex_buffer_load_data(buffer, (size_t)mesh->vertex_size * mesh->vertex_count, + mesh->vertex, mesh->flags & OBJECT_MESH_FLAG_1 ? 2 : 1); +} + +static bool object_mesh_vertex_buffer_load_data(object_mesh_vertex_buffer* buffer, + size_t size, void* data, int32_t count) { + if (!size || count > 3) + return false; + + buffer->count = count; + + glGenBuffers(count, buffer->buffers); + for (int32_t i = 0; i < count; i++) { + gl_state_bind_array_buffer(buffer->buffers[i]); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW); + } + gl_state_bind_array_buffer(0); + return true; +} + +static void object_mesh_vertex_buffer_free(object_mesh_vertex_buffer* buffer) { + glDeleteBuffers(buffer->count, buffer->buffers); +} + +static bool object_set_index_buffer_load(object_set* set) { + set->index_buffers_count = set->objects_count; + set->index_buffers = force_malloc_s(object_index_buffer, set->objects_count); + if (!set->index_buffers) + return false; + + for (int32_t i = 0; i < set->objects_count; i++) { + object* obj = &set->objects[i]; + object_index_buffer* buffer = &set->index_buffers[i]; + + buffer->meshes_count = obj->meshes_count; + buffer->meshes = force_malloc_s(object_mesh_index_buffer, obj->meshes_count); + if (!buffer->meshes) + return false; + + for (int32_t j = 0; j < buffer->meshes_count; j++) + if (!object_mesh_index_buffer_load(&buffer->meshes[j], &obj->meshes[j])) + return false; + } + return true; +} + +static void object_set_index_buffer_free(object_set* set) { + if (!set->index_buffers) + return; + + for (int32_t i = 0; i < set->index_buffers_count; i++) { + object_index_buffer* buffer = &set->index_buffers[i]; + if (buffer->meshes) + for (int32_t j = 0; j < buffer->meshes_count; j++) + object_mesh_index_buffer_free(&buffer->meshes[j]); + free(buffer->meshes); + } + free(set->index_buffers); + set->index_buffers_count = 0; +} + +static bool object_set_vertex_buffer_load(object_set* set) { + set->vertex_buffers_count = set->objects_count; + set->vertex_buffers = force_malloc_s(object_vertex_buffer, set->objects_count); + if (!set->vertex_buffers) + return false; + + for (int32_t i = 0; i < set->objects_count; i++) { + object* obj = &set->objects[i]; + object_vertex_buffer* buffer = &set->vertex_buffers[i]; + + buffer->meshes_count = obj->meshes_count; + buffer->meshes = force_malloc_s(object_mesh_vertex_buffer, obj->meshes_count); + if (!buffer->meshes) + return false; + + for (int32_t j = 0; j < buffer->meshes_count; j++) + if (!object_mesh_vertex_buffer_load(&buffer->meshes[j], &obj->meshes[j])) + return false; + } + return true; +} + +static void object_set_vertex_buffer_free(object_set* set) { + if (!set->vertex_buffers) + return; + + for (int32_t i = 0; i < set->vertex_buffers_count; i++) { + object_vertex_buffer* buffer = &set->vertex_buffers[i]; + if (buffer->meshes) + for (int32_t j = 0; j < buffer->meshes_count; j++) + object_mesh_vertex_buffer_free(&buffer->meshes[j]); + free(buffer->meshes); + } + free(set->vertex_buffers); + set->vertex_buffers_count = 0; +} + +inline static void object_skin_block_constraint_attach_point_load( + object_skin_block_constraint_attach_point* attach_point, + object_skin_block_constraint_attach_point_file* attach_point_file) { + attach_point->affected_by_orientation = attach_point_file->affected_by_orientation; + attach_point->affected_by_scaling = attach_point_file->affected_by_scaling; + attach_point->offset = attach_point_file->offset; +} +inline static void object_skin_block_constraint_up_vector_load( + object_skin_block_constraint_up_vector* up_vector, + object_skin_block_constraint_up_vector_file* up_vector_file) { + up_vector->active = up_vector_file->active; + up_vector->roll = up_vector_file->roll; + up_vector->affected_axis = up_vector_file->affected_axis; + up_vector->point_at = up_vector_file->point_at; + string_copy(&up_vector_file->name, &up_vector->name); +} + + +inline static void object_skin_block_node_load(object_skin_block_node* node, + object_skin_block_node_file* node_file) { + string_copy(&node_file->parent_name, &node->parent_name); + node->position = node_file->position; + node->rotation = node_file->rotation; + node->scale = node_file->scale; +} + +inline static void object_skin_block_node_free(object_skin_block_node* node) { + string_free(&node->parent_name); +} + +inline static size_t object_vertex_flags_get_vertex_size(object_vertex_flags flags) { + size_t size = 0; + if (flags & OBJECT_VERTEX_POSITION) + size += 12; + if (flags & OBJECT_VERTEX_NORMAL) + size += 12; + if (flags & OBJECT_VERTEX_TANGENT) + size += 16; + if (flags & OBJECT_VERTEX_BINORMAL) + size += 12; + if (flags & OBJECT_VERTEX_TEXCOORD0) + size += 8; + if (flags & OBJECT_VERTEX_TEXCOORD1) + size += 8; + if (flags & OBJECT_VERTEX_TEXCOORD2) + size += 8; + if (flags & OBJECT_VERTEX_TEXCOORD3) + size += 8; + if (flags & OBJECT_VERTEX_COLOR0) + size += 16; + if (flags & OBJECT_VERTEX_COLOR1) + size += 16; + if (flags & OBJECT_VERTEX_BONE_DATA) + size += 32; + if (flags & OBJECT_VERTEX_UNKNOWN) + size += 16; + return size; +} + +inline static size_t object_vertex_flags_get_vertex_size_comp(object_vertex_flags flags) { + size_t size = 0; + if (flags & OBJECT_VERTEX_POSITION) + size += 12; + if (flags & OBJECT_VERTEX_NORMAL) + size += 8; + if (flags & OBJECT_VERTEX_TANGENT) + size += 8; + if (flags & OBJECT_VERTEX_TEXCOORD0) + size += 4; + if (flags & OBJECT_VERTEX_TEXCOORD1) + size += 4; + if (flags & OBJECT_VERTEX_TEXCOORD2) + size += 4; + if (flags & OBJECT_VERTEX_TEXCOORD3) + size += 4; + if (flags & OBJECT_VERTEX_COLOR0) + size += 8; + if (flags & OBJECT_VERTEX_BONE_DATA) + size += 12; + return size; +} + +static bool object_set_load_file(void* data, char* path, char* file, uint32_t hash) { + data_struct* ds = (void*)((size_t*)data)[0]; + data_ft* d = &ds->data_ft; + + object_set_info* set_info = (void*)((size_t*)data)[1]; + + farc f; + farc_init(&f); + if (!farc_load_file(&f, path, file, hash)) + return false; + + farc_file* obj = farc_read_file(&f, string_data(&set_info->object_file_name)); + farc_file* tex = farc_read_file(&f, string_data(&set_info->texture_file_name)); + + if (obj && tex) { + obj_set obj_set; + obj_init(&obj_set); + obj_mread(&obj_set, obj->data, obj->size, false); + + txp_set txp_set; + txp_set_init(&txp_set); + txp_set_unpack_file(&txp_set, tex->data, false); + + if (obj_set.ready) { + object_set object_set; + object_set_init(&object_set); + object_set_load(&object_set, &obj_set, &txp_set, &d->tex_db, &set_info->name, set_info->id, true); + object_storage_insert_object_set(&object_set, set_info->id); + } + + obj_free(&obj_set); + txp_set_free(&txp_set); + } + farc_free(&f); + return true; +} + +static bool object_set_load_file_modern(void* data, char* path, char* file, uint32_t hash) { + object_database* obj_db = (void*)((size_t*)data)[0]; + texture_database* tex_db = (void*)((size_t*)data)[1]; + + farc f; + farc_init(&f); + if (!farc_load_file(&f, path, file, hash)) + return false; + + char buf[0x100]; + size_t file_len = utf8_length(file); + if (file_len >= 0x100) { + farc_free(&f); + return false; + } + + memcpy(buf, file, file_len); + char* ext = buf + file_len - 5; + + memcpy(ext, ".osd", 5); + farc_file* osd = farc_read_file(&f, buf); + + memcpy(ext, ".txd", 5); + farc_file* txd = farc_read_file(&f, buf); + + memcpy(ext, ".osi", 5); + farc_file* osi = farc_read_file(&f, buf); + + memcpy(ext, ".txi", 5); + farc_file* txi = farc_read_file(&f, buf); + + if (osd && txd && osi && txi) { + obj_set obj_set; + obj_init(&obj_set); + obj_mread(&obj_set, osd->data, osd->size, true); + + txp_set txp_set; + txp_set_init(&txp_set); + txp_set_unpack_file_modern(&txp_set, txd->data, txd->size); + + object_database_mread(obj_db, osi->data, osi->size, true); + texture_database_mread(tex_db, txi->data, txi->size, true); + + string* name = 0; + if (obj_db->ready) + for (object_set_info* m = obj_db->object_set.begin; m != obj_db->object_set.end; m++) + if (m->id == hash) { + name = &m->name; + break; + } + + if (name && obj_set.ready) { + object_set object_set; + object_set_init(&object_set); + object_set_load(&object_set, &obj_set, &txp_set, tex_db, name, hash, true); + object_storage_insert_object_set(&object_set, hash); + } + + obj_free(&obj_set); + txp_set_free(&txp_set); + } + farc_free(&f); + return true; +} diff --git a/src/CRE/object.h b/src/CRE/object.h new file mode 100644 index 00000000..f04a1bd9 --- /dev/null +++ b/src/CRE/object.h @@ -0,0 +1,625 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/database/object.h" +#include "../KKdLib/database/texture.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/obj.h" +#include "../KKdLib/string.h" +#include "../KKdLib/vec.h" +#include "static_var.h" +#include "texture.h" + +typedef enum object_index_format { + OBJECT_INDEX_U8 = 0x00, + OBJECT_INDEX_U16 = 0x01, + OBJECT_INDEX_U32 = 0x02, +} object_index_format; + +typedef enum object_material_aniso_direction { + OBJECT_MATERIAL_ANISO_DIRECTION_NORMAL = 0, + OBJECT_MATERIAL_ANISO_DIRECTION_U = 1, + OBJECT_MATERIAL_ANISO_DIRECTION_V = 2, + OBJECT_MATERIAL_ANISO_DIRECTION_RADIAL = 3, +} object_material_aniso_direction; + +typedef enum object_material_blend_factor { + OBJECT_MATERIAL_BLEND_ZERO = 0, + OBJECT_MATERIAL_BLEND_ONE = 1, + OBJECT_MATERIAL_BLEND_SRC_COLOR = 2, + OBJECT_MATERIAL_BLEND_INVERSE_SRC_COLOR = 3, + OBJECT_MATERIAL_BLEND_SRC_ALPHA = 4, + OBJECT_MATERIAL_BLEND_INVERSE_SRC_ALPHA = 5, + OBJECT_MATERIAL_BLEND_DST_ALPHA = 6, + OBJECT_MATERIAL_BLEND_INVERSE_DST_ALPHA = 7, + OBJECT_MATERIAL_BLEND_DST_COLOR = 8, + OBJECT_MATERIAL_BLEND_INVERSE_DST_COLOR = 9, + OBJECT_MATERIAL_BLEND_ALPHA_SATURATE = 10, +} object_material_blend_factor; + +typedef enum object_material_bump_map_type { + OBJECT_MATERIAL_BUMP_MAP_NONE = 0, + OBJECT_MATERIAL_BUMP_MAP_DOT = 1, + OBJECT_MATERIAL_BUMP_MAP_ENV = 2, +} object_material_bump_map_type; + +typedef enum object_material_color_source_type { + OBJECT_MATERIAL_COLOR_SOURCE_MATERIAL_COLOR = 0, + OBJECT_MATERIAL_COLOR_SOURCE_VERTEX_COLOR = 1, + OBJECT_MATERIAL_COLOR_SOURCE_VERTEX_MORPH = 2, +} object_material_color_source_type; + +typedef enum object_material_flags { + OBJECT_MATERIAL_COLOR = 0x0001, + OBJECT_MATERIAL_COLOR_ALPHA = 0x0002, + OBJECT_MATERIAL_COLOR_L1 = 0x0004, + OBJECT_MATERIAL_COLOR_L1_ALPHA = 0x0008, + OBJECT_MATERIAL_COLOR_L2 = 0x0010, + OBJECT_MATERIAL_COLOR_L2_ALPHA = 0x0020, + OBJECT_MATERIAL_TRANSPARENCY = 0x0040, + OBJECT_MATERIAL_SPECULAR = 0x0080, + OBJECT_MATERIAL_NORMAL = 0x0100, + OBJECT_MATERIAL_NORMALALT = 0x0200, + OBJECT_MATERIAL_ENVIRONMENT = 0x0400, + OBJECT_MATERIAL_COLOR_L3 = 0x0800, + OBJECT_MATERIAL_COLOR_L3_ALPHA = 0x1000, + OBJECT_MATERIAL_TRANSLUCENCY = 0x2000, + OBJECT_MATERIAL_FLAG_14 = 0x4000, + OBJECT_MATERIAL_OVERRIDE_IBL = 0x8000, +} object_material_flags; + +typedef enum object_material_specular_quality { + OBJECT_MATERIAL_SPECULAR_QUALITY_LOW = 0, + OBJECT_MATERIAL_SPECULAR_QUALITY_HIGH = 1, +} object_material_specular_quality; + +typedef enum object_material_texture_type { + OBJECT_MATERIAL_TEXTURE_NONE = 0x00, + OBJECT_MATERIAL_TEXTURE_COLOR = 0x01, + OBJECT_MATERIAL_TEXTURE_NORMAL = 0x02, + OBJECT_MATERIAL_TEXTURE_SPECULAR = 0x03, + OBJECT_MATERIAL_TEXTURE_HEIGHT = 0x04, + OBJECT_MATERIAL_TEXTURE_REFLECTION = 0x05, + OBJECT_MATERIAL_TEXTURE_TRANSLUCENCY = 0x06, + OBJECT_MATERIAL_TEXTURE_TRANSPARENCY = 0x07, + OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE = 0x08, + OBJECT_MATERIAL_TEXTURE_ENVIRONMENT_CUBE = 0x09, +} object_material_texture_type; + +typedef enum object_material_texture_coordinate_translation_type { + OBJECT_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_NONE = 0x00, + OBJECT_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_UV = 0x01, + OBJECT_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_SPHERE = 0x02, + OBJECT_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_CUBE = 0x03 +} object_material_texture_coordinate_translation_type; + +typedef enum object_material_shader_lighting_type { + OBJECT_MATERIAL_SHADER_LIGHTING_LAMBERT = 0x0, + OBJECT_MATERIAL_SHADER_LIGHTING_CONSTANT = 0x1, + OBJECT_MATERIAL_SHADER_LIGHTING_PHONG = 0x2, +} object_material_shader_lighting_type; + +typedef enum object_material_vertex_translation_type { + OBJECT_MATERIAL_VERTEX_TRANSLATION_DEFAULT = 0, + OBJECT_MATERIAL_VERTEX_TRANSLATION_ENVELOPE = 1, + OBJECT_MATERIAL_VERTEX_TRANSLATION_MORPHING = 2, +} object_material_vertex_translation_type; + +typedef enum object_mesh_flags { + OBJECT_MESH_FLAG_1 = 0x01, + OBJECT_MESH_BILLBOARD_Y_AXIS = 0x02, + OBJECT_MESH_TRANSLUCENT_NO_SHADOW = 0x04, + OBJECT_MESH_BILLBOARD = 0x08, +} object_mesh_flags; + +typedef enum object_primitive_type { + OBJECT_PRIMITIVE_POINTS = 0x00, + OBJECT_PRIMITIVE_LINES = 0x01, + OBJECT_PRIMITIVE_LINE_STRIP = 0x02, + OBJECT_PRIMITIVE_LINE_LOOP = 0x03, + OBJECT_PRIMITIVE_TRIANGLES = 0x04, + OBJECT_PRIMITIVE_TRIANGLE_STRIP = 0x05, + OBJECT_PRIMITIVE_TRIANGLE_FAN = 0x06, + OBJECT_PRIMITIVE_QUADS = 0x07, + OBJECT_PRIMITIVE_QUAD_STRIP = 0x08, + OBJECT_PRIMITIVE_POLYGON = 0x09, +} object_primitive_type; + +typedef enum object_skin_block_constraint_type { + OBJECT_SKIN_BLOCK_CONSTRAINT_NONE = 0, + OBJECT_SKIN_BLOCK_CONSTRAINT_DIRECTION, + OBJECT_SKIN_BLOCK_CONSTRAINT_DISTANCE, + OBJECT_SKIN_BLOCK_CONSTRAINT_ORIENTATION, + OBJECT_SKIN_BLOCK_CONSTRAINT_POSITION, +} object_skin_block_constraint_type; + +typedef enum object_skin_block_constraint_coupling { + OBJECT_SKIN_BLOCK_CONSTRAINT_COUPLING_RIGID = 0x01, + OBJECT_SKIN_BLOCK_CONSTRAINT_COUPLING_SOFT = 0x03, +} object_skin_block_constraint_coupling; + +typedef enum object_skin_block_type { + OBJECT_SKIN_BLOCK_NONE = 0, + OBJECT_SKIN_BLOCK_CLOTH, + OBJECT_SKIN_BLOCK_CONSTRAINT, + OBJECT_SKIN_BLOCK_EXPRESSION, + OBJECT_SKIN_BLOCK_MOTION, + OBJECT_SKIN_BLOCK_OSAGE, +} object_skin_block_type; + +typedef enum object_sub_mesh_flags { + OBJECT_SUB_MESH_RECIEVE_SHADOW = 0x01, + OBJECT_SUB_MESH_CAST_SHADOW = 0x02, + OBJECT_SUB_MESH_TRANSPARENT = 0x04, + OBJECT_SUB_MESH_FLAG_8 = 0x08, + OBJECT_SUB_MESH_FLAG_10 = 0x10, + OBJECT_SUB_MESH_FLAG_20 = 0x20, + OBJECT_SUB_MESH_FLAG_40 = 0x40, + OBJECT_SUB_MESH_FLAG_80 = 0x80, +} object_sub_mesh_flags; + +typedef enum object_vertex_flags { + OBJECT_VERTEX_NONE = 0x000, + OBJECT_VERTEX_POSITION = 0x001, + OBJECT_VERTEX_NORMAL = 0x002, + OBJECT_VERTEX_TANGENT = 0x004, + OBJECT_VERTEX_BINORMAL = 0x008, + OBJECT_VERTEX_TEXCOORD0 = 0x010, + OBJECT_VERTEX_TEXCOORD1 = 0x020, + OBJECT_VERTEX_TEXCOORD2 = 0x040, + OBJECT_VERTEX_TEXCOORD3 = 0x080, + OBJECT_VERTEX_COLOR0 = 0x100, + OBJECT_VERTEX_COLOR1 = 0x200, + OBJECT_VERTEX_BONE_DATA = 0x400, + OBJECT_VERTEX_UNKNOWN = 0x800, +} object_vertex_flags; + +typedef struct object_axis_aligned_bounding_box { + vec3 center; + vec3 size; +} object_axis_aligned_bounding_box; + +typedef struct object_bounding_box { + vec3 center; + vec3 size; +} object_bounding_box; + +typedef struct object_bounding_sphere { + vec3 center; + float_t radius; +} object_bounding_sphere; + +typedef struct object_material_blend_flags { + uint32_t alpha_texture : 1; + uint32_t alpha_material : 1; + uint32_t punch_through : 1; + uint32_t double_sided : 1; + uint32_t normal_direction_light : 1; + object_material_blend_factor src_blend_factor : 4; + object_material_blend_factor dst_blend_factor : 4; + uint32_t blend_operation : 3; + uint32_t z_bias : 4; + uint32_t no_fog : 1; + uint32_t translucent_priority : 6; + uint32_t has_fog_height : 1; + uint32_t flag_28 : 1; + uint32_t fog_height : 1; + uint32_t flag_30 : 1; + uint32_t flag_31 : 1; +} object_material_blend_flags; + +typedef struct object_material_shader_flags { + object_material_vertex_translation_type vertex_translation_type : 2; + object_material_color_source_type color_source_type : 2; + uint32_t lambert_shading : 1; + uint32_t phong_shading : 1; + uint32_t per_pixel_shading : 1; + uint32_t double_shading : 1; + object_material_bump_map_type bump_map_type : 2; + uint32_t fresnel : 4; + uint32_t line_light : 4; + uint32_t recieve_shadow : 1; + uint32_t cast_shadow : 1; + object_material_specular_quality specular_quality : 1; + object_material_aniso_direction aniso_direction : 2; +} object_material_shader_flags; + +typedef struct object_material_texture_sampler_flags { + uint32_t repeat_u : 1; + uint32_t repeat_v : 1; + uint32_t mirror_u : 1; + uint32_t mirror_v : 1; + uint32_t ignore_alpha : 1; + uint32_t blend : 5; + uint32_t alpha_blend : 5; + uint32_t border : 1; + uint32_t clamp_to_edge : 1; + uint32_t filter : 3; + uint32_t mip_map : 2; + uint32_t mip_map_bias : 7; + uint32_t flag_29 : 1; + uint32_t anisotropic_filter : 2; +} object_material_texture_sampler_flags; + +typedef struct object_material_texture_texture_flags { + uint32_t type : 4; + uint32_t tex_coord_index : 4; + uint32_t tex_coord_trans_type : 3; +} object_material_texture_texture_flags; + +typedef struct object_material_texture { + object_material_texture_sampler_flags sampler_flags; + uint32_t texture_id; + int32_t texture_index; + object_material_texture_texture_flags texture_flags; + char shader_name[8]; + float_t weight; + mat4u tex_coord_mat; +} object_material_texture; + +typedef struct object_material { + object_material_flags flags; + int32_t shader_index; + object_material_shader_flags shader_flags; + object_material_texture textures[8]; + vec4u diffuse; + vec4u ambient; + vec4u specular; + vec4u emission; + object_material_blend_flags blend_flags; + float_t shininess; + float_t intensity; + object_bounding_sphere reserved_sphere; + char name[64]; + float_t bump_depth; +} object_material; + +typedef struct object_material_data { + uint32_t textures_count; + object_material material; +} object_material_data; + +typedef struct object_sub_mesh { + object_bounding_sphere bounding_sphere; + uint32_t material_index; + uint8_t texcoord_indices[8]; + uint16_t* bone_indices; + int32_t bone_indices_count; + uint32_t bones_per_vertex; + object_primitive_type primitive_type; + object_index_format index_format; + int32_t indices_count; + object_sub_mesh_flags flags; + object_axis_aligned_bounding_box axis_aligned_bounding_box; + uint16_t first_index; + uint16_t last_index; + uint32_t indices_offset; +} object_sub_mesh; + +typedef struct object_mesh { + object_bounding_sphere bounding_sphere; + object_sub_mesh* sub_meshes; + int32_t sub_meshes_count; + bool compressed; + void* vertex; + int32_t vertex_count; + int32_t vertex_size; + uint16_t* indices; + int32_t indices_count; + object_vertex_flags vertex_flags; + object_mesh_flags flags; + char name[0x40]; +} object_mesh; + +typedef struct object_skin_block_cloth_field_1C_sub { + string bone_name; + float_t weight; + uint32_t matrix_index; + uint32_t field_0C; +} object_skin_block_cloth_field_1C_sub; + +typedef struct object_skin_block_cloth_field_1C { + float_t field_00; + float_t field_04; + float_t field_08; + float_t field_0C; + float_t field_10; + float_t field_14; + float_t field_18; + uint32_t field_1C; + uint32_t field_20; + uint32_t field_24; + object_skin_block_cloth_field_1C_sub sub_data_0; + object_skin_block_cloth_field_1C_sub sub_data_1; + object_skin_block_cloth_field_1C_sub sub_data_2; + object_skin_block_cloth_field_1C_sub sub_data_3; +} object_skin_block_cloth_field_1C; + +typedef struct object_skin_block_cloth_field_20_sub { + uint32_t field_00; + float_t field_04; + float_t field_08; + float_t field_0C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + float_t field_24; + float_t field_28; +} object_skin_block_cloth_field_20_sub; + +typedef struct object_skin_block_cloth_field_20 { + object_skin_block_cloth_field_20_sub sub_data_0; + object_skin_block_cloth_field_20_sub sub_data_1; + object_skin_block_cloth_field_20_sub sub_data_2; + object_skin_block_cloth_field_20_sub sub_data_3; + object_skin_block_cloth_field_20_sub sub_data_4; + object_skin_block_cloth_field_20_sub sub_data_5; + object_skin_block_cloth_field_20_sub sub_data_6; + object_skin_block_cloth_field_20_sub sub_data_7; + object_skin_block_cloth_field_20_sub sub_data_8; + object_skin_block_cloth_field_20_sub sub_data_9; +} object_skin_block_cloth_field_20; + +typedef struct object_skin_block_node { + string parent_name; + vec3 position; + vec3 rotation; + vec3 scale; +} object_skin_block_node; + +typedef struct object_skin_block_cloth { + string mesh_name; + string backface_mesh_name; + uint32_t field_08; + uint32_t count; + uint32_t field_10; + uint32_t field_14; + mat4u field_18[32]; + object_skin_block_cloth_field_1C* field_1C; + object_skin_block_cloth_field_20* field_20; + uint16_t* field_24; + uint32_t field_24_count; + uint16_t* field_28; + uint32_t field_28_count; + uint32_t field_2C; + uint32_t field_30; +} object_skin_block_cloth; + +typedef struct object_skin_block_constraint_attach_point { + bool affected_by_orientation; + bool affected_by_scaling; + vec3 offset; +} object_skin_block_constraint_attach_point; + +typedef struct object_skin_block_constraint_up_vector { + bool active; + float_t roll; + vec3 affected_axis; + vec3 point_at; + string name; +} object_skin_block_constraint_up_vector; + +typedef struct object_skin_block_constraint_direction { + object_skin_block_constraint_up_vector up_vector; + vec3 align_axis; + vec3 target_offset; +} object_skin_block_constraint_direction; + +typedef struct object_skin_block_constraint_distance { + object_skin_block_constraint_up_vector up_vector; + float_t distance; + object_skin_block_constraint_attach_point constrained_object; + object_skin_block_constraint_attach_point constraining_object; +} object_skin_block_constraint_distance; + +typedef struct object_skin_block_constraint_orientation { + vec3 offset; +} object_skin_block_constraint_orientation; + +typedef struct object_skin_block_constraint_position { + object_skin_block_constraint_up_vector up_vector; + object_skin_block_constraint_attach_point constrained_object; + object_skin_block_constraint_attach_point constraining_object; +} object_skin_block_constraint_position; + +typedef struct object_skin_block_constraint { + object_skin_block_node base; + object_skin_block_constraint_coupling coupling; + uint32_t name_index; + string source_node_name; + object_skin_block_constraint_type type; + union { + object_skin_block_constraint_direction direction; + object_skin_block_constraint_distance distance; + object_skin_block_constraint_orientation orientation; + object_skin_block_constraint_position position; + }; +} object_skin_block_constraint; + +typedef struct object_skin_block_expression { + object_skin_block_node base; + uint32_t name_index; + int32_t expressions_count; + string expressions[9]; +} object_skin_block_expression; + +typedef struct object_skin_motion_node { + uint32_t name_index; + mat4u transformation; +} object_skin_motion_node; + +typedef struct object_skin_block_motion { + object_skin_block_node base; + union { + string name; + uint32_t name_index; + }; + object_skin_motion_node* nodes; + int32_t nodes_count; +} object_skin_block_motion; + +typedef struct object_skin_osage_node { + uint32_t name_index; + float_t length; + vec3 rotation; + uint32_t sibling_name_index; + float_t sibling_max_distance; +} object_skin_osage_node; + +typedef struct object_skin_block_osage { + object_skin_block_node base; + int32_t start_index; + int32_t count; + object_skin_osage_node* nodes; + int32_t nodes_count; + uint32_t external_name_index; + uint32_t name_index; + string motion_node_name; +} object_skin_block_osage; + +typedef struct object_skin_block { + object_skin_block_type type; + union { + object_skin_block_node base; + object_skin_block_cloth cloth; + object_skin_block_constraint constraint; + object_skin_block_expression expression; + object_skin_block_motion motion; + object_skin_block_osage osage; + }; +} object_skin_block; + +typedef struct object_skin_osage_sibling_info { + uint32_t name_index; + uint32_t sibling_name_index; + float_t distance; +} object_skin_osage_sibling_info; + +typedef struct object_skin_ex_data { + object_skin_osage_node* osage_nodes; + int32_t osage_nodes_count; + object_skin_block* blocks; + int32_t blocks_count; + char* bone_names_buf; + char** bone_names; + int32_t bone_names_count; + object_skin_osage_sibling_info* osage_sibling_infos; + int32_t osage_sibling_infos_count; +} object_skin_ex_data; + +typedef struct object_skin_bone { + uint32_t id; + mat4u inv_bind_pose_mat; + string name; + uint32_t parent; +} object_skin_bone; + +typedef struct object_skin { + object_skin_bone* bones; + int32_t bones_count; + object_skin_ex_data ex_data; + bool ex_data_init; +} object_skin; + +typedef struct object { + object_bounding_sphere bounding_sphere; + object_mesh* meshes; + int32_t meshes_count; + object_material_data* materials; + int32_t materials_count; + uint8_t flags; + object_skin skin; + bool skin_init; + string name; + uint32_t id; +} object; + +typedef GLint object_mesh_index_buffer; + +typedef struct object_mesh_vertex_buffer { + int32_t count; + GLint buffers[3]; + int32_t index; +} object_mesh_vertex_buffer; + +typedef struct object_index_buffer { + int32_t meshes_count; + object_mesh_index_buffer* meshes; +} object_index_buffer; + +typedef struct object_vertex_buffer { + int32_t meshes_count; + object_mesh_vertex_buffer* meshes; +} object_vertex_buffer; + +typedef struct object_set { + string name; + uint32_t id; + object* objects; + int32_t objects_count; + uint32_t* texture_ids; + int32_t texture_ids_count; + string* texture_names; + int32_t texture_names_count; + uint32_t* textures; + int32_t textures_count; + texture** texture_data; + object_vertex_buffer* vertex_buffers; + int32_t vertex_buffers_count; + object_index_buffer* index_buffers; + int32_t index_buffers_count; + bool is_x; +} object_set; + +extern void object_set_init(object_set* set); +extern void object_set_load(object_set* set, obj_set* obj_set_file, txp_set* txp_set_file, + texture_database* tex_db, string* name, uint32_t id, bool compressed); +extern bool object_set_load_db_entry(object_set_info** set_info, + void* data, object_database* obj_db, char* name); +extern bool object_set_load_by_db_entry(object_set_info* set_info, + void* data, object_database* obj_db); +extern bool object_set_load_by_db_index(object_set_info** set_info, + void* data, object_database* obj_db, uint32_t set_id); +extern bool object_set_load_by_hash(void* data, + object_database* obj_db, texture_database* tex_db, uint32_t hash); +extern void object_set_free(object_set* set); + +extern object_material_shader_lighting_type object_material_shader_get_lighting_type( + object_material_shader_flags* flags); +extern int32_t object_material_texture_get_blend(object_material_texture* tex); +extern int32_t object_material_texture_type_get_texcoord_index( + object_material_texture_type type, int32_t index); +extern int32_t object_material_texture_type_get_texture_index( + object_material_texture_type type, int32_t base_index); +extern GLuint object_mesh_vertex_buffer_get_buffer(object_mesh_vertex_buffer* buffer); +extern int32_t object_mesh_vertex_buffer_get_size(object_mesh_vertex_buffer* buffer); +extern void object_skin_set_matrix_buffer(object_skin* s, mat4* matrices, + mat4* ex_data_matrices, mat4* matrix_buffer, mat4* global_mat, mat4* mat); + +extern void object_storage_init(); +extern void object_storage_append_object_set(uint32_t set_id); +extern void object_storage_insert_object_set(object_set* set, uint32_t set_id); +extern object* object_storage_get_object(object_info obj_info); +extern object_mesh* object_storage_get_object_mesh(object_info obj_info, char* mesh_name); +extern object_mesh* object_storage_get_object_mesh_by_index(object_info obj_info, int32_t index); +extern int32_t object_storage_get_object_mesh_index(object_info obj_info, char* mesh_name); +extern object_set* object_storage_get_object_set(uint32_t set_id); +extern ssize_t object_storage_get_object_set_count(); +extern object_set* object_storage_get_object_set_by_index(ssize_t index); +extern ssize_t object_storage_get_object_set_index(uint32_t set_id); +extern object_skin* object_storage_get_object_skin(object_info obj_info); +extern object_index_buffer* object_storage_get_object_index_buffers(uint32_t set_id); +extern object_mesh_index_buffer* object_storage_get_object_mesh_index_buffer(object_info obj_info); +extern object_vertex_buffer* object_storage_get_object_vertex_buffers(uint32_t set_id); +extern object_mesh_vertex_buffer* object_storage_get_object_mesh_vertex_buffer(object_info obj_info); +extern GLuint* object_storage_get_textures(uint32_t set_id); +extern uint32_t* object_storage_get_texture_ids(uint32_t set_id); +extern void object_storage_delete_object_set(uint32_t set_id); +extern void object_storage_free(); diff --git a/src/CRE/post_process.c b/src/CRE/post_process.c index a4e0a5cc..a9a79073 100644 --- a/src/CRE/post_process.c +++ b/src/CRE/post_process.c @@ -4,526 +4,307 @@ */ #include "post_process.h" +#include "fbo.h" +#include "gl_state.h" +#include "render_texture.h" +#include "shader_ft.h" #include "static_var.h" +#include "texture.h" -static void radius_calculate(radius* rad); -static void radius_calculate_gaussian_kernel(float_t* gaussian_kernel, - float_t radius, int32_t stride, int32_t offset); -static void tone_map_calculate_data(tone_map* tm); -static void tone_map_calculate_tex(tone_map* tm); +void post_process_init(post_process_struct* pp) { + static const char* alpha_layer_vert_shader = + "#version 430 core\n" + "out VertexData {\n" + " vec2 texcoord;\n" + "} result;\n" + "\n" + "void main() {\n" + " gl_Position.x = -1.0 + float(gl_VertexID / 2) * 4.0;\n" + " gl_Position.y = 1.0 - float(gl_VertexID % 2) * 4.0;\n" + " gl_Position.z = 0.0;\n" + " gl_Position.w = 1.0;\n" + " result.texcoord = gl_Position.xy * 0.5 + 0.5;\n" + "}\n"; -radius* radius_init() { - radius* rad = force_malloc(sizeof(radius)); - return rad; + static const char* alpha_layer_frag_shader = + "#version 430\n" + "layout(binding = 0) uniform sampler2D g_layerd_color;\n" + "layout(binding = 1) uniform sampler2D g_base_color;\n" + "\n" + "layout(location = 0) uniform float g_opacity;\n" + "\n" + "in VertexData{\n" + " vec2 texcoord;\n" + "}frg;\n" + "\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "void main(){\n" + " vec4 cl = textureLod(g_layerd_color, frg.texcoord, 0.f);\n" + " vec4 cb = textureLod(g_base_color, frg.texcoord, 0.f);\n" + " result = mix(cb, cl, g_opacity.x);\n" + "}\n"; + + memset(pp, 0, sizeof(post_process_struct)); + pp->aa = post_process_aa_init(); + pp->blur = post_process_blur_init(); + pp->dof = post_process_dof_init(); + pp->exposure = post_process_exposure_init(); + pp->tone_map = post_process_tone_map_init(); + + glGenSamplers(2, pp->samplers); + glSamplerParameteri(pp->samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glSamplerParameteri(pp->samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glSamplerParameteri(pp->samplers[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glSamplerParameteri(pp->samplers[0], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glSamplerParameteri(pp->samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glSamplerParameteri(pp->samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glSamplerParameteri(pp->samplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glSamplerParameteri(pp->samplers[1], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + + shader_glsl_param param; + memset(¶m, 0, sizeof(shader_glsl_param)); + param.name = "Alpha Layer"; + shader_glsl_load_string(&pp->alpha_layer_shader, + (char*)alpha_layer_vert_shader, (char*)alpha_layer_frag_shader, 0, ¶m); + post_process_reset(pp); } -void radius_initialize(radius* rad, vec3* rgb) { - rad->rgb = *rgb; - radius_calculate(rad); -} +void post_process_apply(post_process_struct* pp, camera* cam, texture* light_proj_tex, int32_t npr_param) { + fbo_blit(pp->render_texture.fbos[0], + pp->pre_texture.fbos[0], + 0, 0, pp->render_width, pp->render_height, + 0, 0, pp->render_width, pp->render_height, GL_COLOR_BUFFER_BIT, GL_LINEAR); -vec3* radius_get(radius* rad) { - return &rad->rgb; -} + for (int32_t i = 0; i < 8; i++) + gl_state_bind_sampler(i, 0); -void radius_set(radius* rad, vec3* value) { - vec3 temp; - temp.x = clamp(value->x, 0.0f, 3.0f); - temp.y = clamp(value->y, 0.0f, 3.0f); - temp.z = clamp(value->z, 0.0f, 3.0f); - if (temp.x != rad->rgb.x || temp.y != rad->rgb.y || temp.z != rad->rgb.z) { - rad->rgb = temp; - radius_calculate(rad); + post_process_apply_dof(pp->dof, &pp->render_texture, pp->samplers, cam); + + shader_state_matrix_set_mvp_separate(&shaders_ft, + (mat4*)&mat4_identity, (mat4*)&mat4_identity, (mat4*)&mat4_identity); + + post_process_get_blur(pp->blur, &pp->render_texture); + post_process_get_exposure(pp->exposure, + pp->blur->tex[4].color_texture->texture, pp->blur->tex[2].color_texture->texture); + post_process_apply_tone_map(pp->tone_map, &pp->render_texture, light_proj_tex, 0, + &pp->render_texture, &pp->buf_texture, &pp->sss_contour_texture, + pp->blur->tex[0].color_texture->texture, + pp->exposure->exposure.color_texture->texture, npr_param); + if (pp->mlaa) + post_process_apply_mlaa(pp->aa, &pp->render_texture, + &pp->buf_texture, pp->samplers, pp->parent_bone_node); + + for (int32_t i = 0; i < 16; i++) { + if (!pp->render_textures_data[i]) + continue; + + render_texture_bind(&pp->render_textures[i], 0); + + texture* t = pp->render_textures_data[i]; + if (pp->render_width > t->width * 2ULL || pp->render_height > t->height * 2ULL) + uniform_value[U_REDUCE] = 1; + else + uniform_value[U_REDUCE] = 0; + + glViewport(0, 0, t->width, t->height); + gl_state_active_bind_texture_2d(0, pp->render_texture.color_texture->texture); + gl_state_bind_sampler(0, pp->samplers[0]); + shader_set(&shaders_ft, SHADER_FT_REDUCE); + render_texture_draw_params(&shaders_ft, pp->render_width, + pp->render_height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); } -} -void radius_dispose(radius* rad) { - free(rad); -} - -intensity* intensity_init() { - intensity* inten = force_malloc(sizeof(radius)); - return inten; -} - -void intensity_initialize(intensity* inten, vec3* rgb) { - inten->rgb.x = clamp(rgb->x, 0.0f, 2.0f); - inten->rgb.y = clamp(rgb->y, 0.0f, 2.0f); - inten->rgb.z = clamp(rgb->z, 0.0f, 2.0f); - inten->val = inten->rgb; - inten->update = true; -} - -vec3* intensity_get(intensity* inten) { - return &inten->rgb; -} - -void intensity_set(intensity* inten, vec3* value) { - vec3 temp; - temp.x = clamp(value->x, 0.0f, 2.0f); - temp.y = clamp(value->y, 0.0f, 2.0f); - temp.z = clamp(value->z, 0.0f, 2.0f); - if (temp.x != inten->rgb.x || temp.y != inten->rgb.y || temp.z != inten->rgb.z) { - inten->rgb = temp; - inten->val = inten->rgb; - inten->update = true; + render_texture_bind(&pp->screen_texture, 0); + glViewport(pp->screen_x_offset, pp->screen_y_offset, pp->sprite_width, pp->sprite_height); + if (pp->ssaa) { + gl_state_active_bind_texture_2d(0, pp->render_texture.color_texture->texture); + gl_state_bind_sampler(0, pp->samplers[0]); + uniform_value[U01] = pp->parent_bone_node ? 1 : 0; + uniform_value[U_REDUCE] = 0; + shader_set(&shaders_ft, SHADER_FT_REDUCE); + render_texture_draw_params(&shaders_ft, pp->render_width, + pp->render_height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + uniform_value[U01] = 0; } -} + else { + gl_state_active_bind_texture_2d(0, pp->render_texture.color_texture->texture); + if (pp->mag_filter == POST_PROCESS_MAG_FILTER_NEAREST) + gl_state_bind_sampler(0, pp->samplers[1]); + else + gl_state_bind_sampler(0, pp->samplers[0]); -void intensity_dispose(intensity* inten) { - free(inten); -} - -tone_map* tone_map_init() { - tone_map* tm = force_malloc(sizeof(tone_map)); - return tm; -} - -void tone_map_initialize(tone_map* tm, float_t exposure, bool auto_exposure, - float_t gamma, int32_t saturate_power, float_t saturate_coeff, - vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, - vec3* tone_trans_start, vec3* tone_trans_end, int32_t tone_map_method) { - tone_map_initialize_rate(tm, exposure, auto_exposure, 1.0f, - gamma, saturate_power, saturate_coeff, scene_fade_color, scene_fade_alpha, scene_fade_blend_func, - tone_trans_start, tone_trans_end, tone_map_method); -} - -void tone_map_initialize_rate(tone_map* tm, float_t exposure, bool auto_exposure, - float_t gamma, float_t gamma_rate, int32_t saturate_power, float_t saturate_coeff, - vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, - vec3* tone_trans_start, vec3* tone_trans_end, int32_t tone_map_method) { - tm->exposure = clamp(exposure, 0.0f, 4.0f); - tm->auto_exposure = auto_exposure; - tm->gamma = clamp(gamma, 0.2f, 2.2f); - tm->gamma_rate = clamp(gamma_rate, 0.5f, 2.0f); - tm->saturate_power = clamp(saturate_power, 1, 6); - tm->saturate_coeff = clamp(saturate_coeff, 0.0f, 1.0f); - tm->scene_fade_color.x = clamp(scene_fade_color->x, 0.0f, 1.0f); - tm->scene_fade_color.y = clamp(scene_fade_color->y, 0.0f, 1.0f); - tm->scene_fade_color.z = clamp(scene_fade_color->z, 0.0f, 1.0f); - tm->scene_fade_alpha = clamp(scene_fade_alpha, 0.0f, 1.0f); - tm->scene_fade_blend_func = clamp(scene_fade_blend_func, 0, 2); - tm->tone_trans_start.x = clamp(tone_trans_start->x, 0.0f, 1.0f); - tm->tone_trans_start.y = clamp(tone_trans_start->y, 0.0f, 1.0f); - tm->tone_trans_start.z = clamp(tone_trans_start->z, 0.0f, 1.0f); - tm->tone_trans_end.x = clamp(tone_trans_end->x, 0.0f, 1.0f); - tm->tone_trans_end.y = clamp(tone_trans_end->y, 0.0f, 1.0f); - tm->tone_trans_end.z = clamp(tone_trans_end->z, 0.0f, 1.0f); - tm->tone_map_method = clamp(tone_map_method, 0, 2); - tm->update_tex = false; - tone_map_calculate_data(tm); - tone_map_calculate_tex(tm); -} - -float_t tone_map_get_exposure(tone_map* tm) { - return tm->exposure; -} - -void tone_map_set_exposure(tone_map* tm, float_t value) { - value = clamp(value, 0.0f, 4.0f); - if (value != tm->exposure) { - tm->exposure = value; - tone_map_calculate_data(tm); - } -} - -bool tone_map_get_auto_exposure(tone_map* tm) { - return tm->auto_exposure; -} - -void tone_map_set_auto_exposure(tone_map* tm, bool value) { - if (value != tm->auto_exposure) { - tm->auto_exposure = value; - tone_map_calculate_data(tm); - } -} - -float_t tone_map_get_gamma(tone_map* tm) { - return tm->gamma; -} - -void tone_map_set_gamma(tone_map* tm, float_t value) { - value = clamp(value, 0.2f, 2.2f); - if (value != tm->gamma) { - tm->gamma = value; - tone_map_calculate_data(tm); - tone_map_calculate_tex(tm); - } -} - -float_t tone_map_get_gamma_rate(tone_map* tm) { - return tm->gamma_rate; -} - -void tone_map_set_gamma_rate(tone_map* tm, float_t value) { - value = clamp(value, 0.5f, 2.0f); - if (value != tm->gamma_rate) { - tm->gamma_rate = value; - tone_map_calculate_tex(tm); - } -} - -int32_t tone_map_get_saturate_power(tone_map* tm) { - return tm->saturate_power; -} - -void tone_map_set_saturate_power(tone_map* tm, int32_t value) { - value = clamp(value, 1, 6); - if (value != tm->saturate_power) { - tm->saturate_power = value; - tone_map_calculate_tex(tm); - } -} - -float_t tone_map_get_saturate_coeff(tone_map* tm) { - return tm->saturate_coeff; -} - -void tone_map_set_saturate_coeff(tone_map* tm, float_t value) { - value = clamp(value, 0.0f, 1.0f); - if (value != tm->saturate_coeff) { - tm->saturate_coeff = value; - tone_map_calculate_tex(tm); - } -} - -vec3* tone_map_get_scene_fade_color(tone_map* tm) { - return &tm->scene_fade_color; -} - -void tone_map_set_scene_fade_color(tone_map* tm, vec3* value) { - vec3 temp; - temp.x = clamp(value->x, 0.0f, 1.0f); - temp.y = clamp(value->y, 0.0f, 1.0f); - temp.z = clamp(value->z, 0.0f, 1.0f); - if (temp.x != tm->scene_fade_color.x - || temp.y != tm->scene_fade_color.y - || temp.z != tm->scene_fade_color.z) { - tm->scene_fade_color = temp; - tone_map_calculate_data(tm); - } -} - -float_t tone_map_get_scene_fade_alpha(tone_map* tm) { - return tm->scene_fade_alpha; -} - -void tone_map_set_scene_fade_alpha(tone_map* tm, float_t value) { - value = clamp(value, 0.0f, 1.0f); - if (value != tm->scene_fade_alpha) { - tm->scene_fade_alpha = value; - tone_map_calculate_data(tm); - } -} - -int32_t tone_map_get_scene_fade_blend_func(tone_map* tm) { - return tm->scene_fade_blend_func; -} - -void tone_map_set_scene_fade_blend_func(tone_map* tm, int32_t value) { - value = clamp(value, 0, 2); - if (value != tm->scene_fade_blend_func) { - tm->scene_fade_blend_func = value; - tone_map_calculate_data(tm); - } -} - -vec3* tone_map_get_tone_trans_start(tone_map* tm) { - return &tm->tone_trans_start; -} - -void tone_map_set_tone_trans_start(tone_map* tm, vec3* value) { - vec3 temp; - temp.x = clamp(value->x, 0.0f, 1.0f); - temp.y = clamp(value->y, 0.0f, 1.0f); - temp.z = clamp(value->z, 0.0f, 1.0f); - if (temp.x != tm->tone_trans_start.x - || temp.y != tm->tone_trans_start.y - || temp.z != tm->tone_trans_start.z) { - tm->tone_trans_start = temp; - tone_map_calculate_data(tm); - } -} - -vec3* tone_map_get_tone_trans_end(tone_map* tm) { - return &tm->tone_trans_end; -} - -void tone_map_set_tone_trans_end(tone_map* tm, vec3* value) { - vec3 temp; - temp.x = clamp(value->x, 0.009999999776f, 1.0f); - temp.y = clamp(value->y, 0.009999999776f, 1.0f); - temp.z = clamp(value->z, 0.009999999776f, 1.0f); - if (temp.x != tm->tone_trans_end.x - || temp.y != tm->tone_trans_end.y - || temp.z != tm->tone_trans_end.z) { - tm->tone_trans_end = temp; - tone_map_calculate_data(tm); - } -} - -int32_t tone_map_get_tone_map_method(tone_map* tm) { - return tm->tone_map_method; -} - -void tone_map_set_tone_map_method(tone_map* tm, int32_t value) { - value = clamp(value, 0, 2); - if (value != tm->tone_map_method) { - tm->tone_map_method = value; - tone_map_calculate_data(tm); - } -} - -void tone_map_dispose(tone_map* tm) { - free(tm); -} - -static void radius_calculate(radius* rad) { - float_t radius_scale = 0.8f; - vec3 radius = rad->rgb; - rad->update = true; - radius_calculate_gaussian_kernel((float_t*)rad->val, radius.x * radius_scale, 3, 0); - radius_calculate_gaussian_kernel((float_t*)rad->val, radius.y * radius_scale, 3, 1); - radius_calculate_gaussian_kernel((float_t*)rad->val, radius.z * radius_scale, 3, 2); -} - -static void radius_calculate_gaussian_kernel(float_t* gaussian_kernel, - float_t radius, int32_t stride, int32_t offset) { - if (stride < 1) - stride = 1; - if (offset < 0) - offset = 0; - - gaussian_kernel[0 * stride + offset] = 1.0f; - for (int32_t i = 1; i < GAUSSIAN_KERNEL_SIZE; i++) - gaussian_kernel[i * stride + offset] = 0.0f; - double_t temp_gaussian_kernel[GAUSSIAN_KERNEL_SIZE]; - double_t s = radius ; - s = -1.0 / (2.0 * s * s); - double_t sum = 0.5; - temp_gaussian_kernel[0] = 1.0; - for (size_t i = 1; i < GAUSSIAN_KERNEL_SIZE; i++) - sum += temp_gaussian_kernel[i] = exp(i * i * s); - - sum = 0.5 / sum; - for (size_t i = 0; i < GAUSSIAN_KERNEL_SIZE; i++) - gaussian_kernel[i * stride + offset] = (float_t)(temp_gaussian_kernel[i] * sum); -} - -static void tone_map_calculate_data(tone_map* tm) { - vec3 tone_trans, tone_trans_scale, tone_trans_offset; - vec3_sub(tm->tone_trans_end, tm->tone_trans_start, tone_trans); - vec3_rcp(tone_trans, tone_trans_scale); - vec3_mult(tone_trans_scale, tm->tone_trans_start, tone_trans_offset); - vec3_negate(tone_trans_offset, tone_trans_offset); - - tone_map_data* v = &tm->data; - v->p_exposure.x = tm->exposure; - v->p_exposure.y = 0.0625f; - v->p_exposure.z = tm->exposure * 0.5f; - v->p_exposure.w = tm->auto_exposure ? 1.0f : 0.0f; - v->p_fade_color.x = tm->scene_fade_color.x; - v->p_fade_color.y = tm->scene_fade_color.y; - v->p_fade_color.z = tm->scene_fade_color.z; - v->p_fade_color.w = tm->scene_fade_alpha; - if (tm->scene_fade_blend_func == 1 || tm->scene_fade_blend_func == 2) - vec3_mult_scalar(*(vec3*)&v->p_fade_color, v->p_fade_color.w, *(vec3*)&v->p_fade_color); - v->p_tone_scale.x = tone_trans_scale.x; - v->p_tone_scale.y = tone_trans_scale.y; - v->p_tone_scale.z = tone_trans_scale.z; - v->p_tone_offset.x = tone_trans_offset.x; - v->p_tone_offset.y = tone_trans_offset.y; - v->p_tone_offset.z = tone_trans_offset.z; - v->p_fade_func.x = (float_t)tm->scene_fade_blend_func; - v->p_inv_tone.x = tm->gamma > 0.0f ? 2.0f / (tm->gamma * 3.0f) : 0.0f; -} - -static void tone_map_calculate_tex(tone_map* tm) { - const float_t tone_map_scale = 1.0f / TONE_MAP_SAT_GAMMA_SAMPLES; - const int32_t tone_map_size = 16 * TONE_MAP_SAT_GAMMA_SAMPLES; - - int32_t i, j; - int32_t saturate_power; - float_t saturate_coeff; - - tm->update_tex = true; - vec2* tex = tm->tex; - float_t gamma_power, gamma, saturation; - gamma_power = tm->gamma * tm->gamma_rate * 1.5f; - saturate_power = tm->saturate_power; - saturate_coeff = tm->saturate_coeff; - - tex[0].x = 0.0f; - tex[0].y = 0.0f; - for (i = 1; i < tone_map_size; i++) { - gamma = powf(1.0f - expf(-i * tone_map_scale), gamma_power); - saturation = gamma * 2.0f - 1.0f; - for (j = 0; j < saturate_power; j++) { - saturation *= saturation; - saturation *= saturation; - saturation *= saturation; - saturation *= saturation; + switch (pp->mag_filter) { + case POST_PROCESS_MAG_FILTER_NEAREST: + case POST_PROCESS_MAG_FILTER_BILINEAR: + case POST_PROCESS_MAG_FILTER_SHARPEN_5_TAP: + case POST_PROCESS_MAG_FILTER_SHARPEN_4_TAP: + case POST_PROCESS_MAG_FILTER_CONE_4_TAP: + case POST_PROCESS_MAG_FILTER_CONE_2_TAP: + uniform_value[U_MAGNIFY] = pp->mag_filter; + break; + default: + uniform_value[U_MAGNIFY] = 0; + break; } - tex[i].x = gamma; - tex[i].y = gamma * saturate_coeff - * ((float_t)TONE_MAP_SAT_GAMMA_SAMPLES / (float_t)i) * (1.0f - saturation); + shader_set(&shaders_ft, SHADER_FT_MAGNIFY); + render_texture_draw_params(&shaders_ft, pp->render_width, + pp->render_height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + } + shader_unbind(); + + for (int32_t i = 0; i < 8; i++) + gl_state_bind_sampler(i, 0); + + fbo_blit(pp->screen_texture.fbos[0], pp->post_texture.fbos[0], + pp->screen_x_offset, pp->screen_y_offset, pp->sprite_width, pp->sprite_height, + 0, 0, pp->render_width, pp->render_height, GL_COLOR_BUFFER_BIT, GL_LINEAR); +} + +void post_process_init_fbo(post_process_struct* pp, int32_t render_width, int32_t render_height, + int32_t sprite_width, int32_t sprite_height, int32_t screen_width, int32_t screen_height) { + if (pp->render_width == render_width && pp->render_height == render_height + && pp->screen_width == screen_width && pp->screen_height == screen_height) + return; + + if (pp->render_width != render_width || pp->render_height != render_height) { + post_process_aa_init_fbo(pp->aa, render_width, render_height); + post_process_blur_init_fbo(pp->blur, render_width, render_height); + post_process_dof_init_fbo(pp->dof, render_width, render_height); + post_process_exposure_init_fbo(pp->exposure); + post_process_tone_map_init_fbo(pp->tone_map); + render_texture_init(&pp->render_texture, render_width, + render_height, 0, GL_RGBA16F, GL_DEPTH24_STENCIL8); + render_texture_init(&pp->buf_texture, render_width, + render_height, 0, GL_RGBA16F, 0); + render_texture_init(&pp->sss_contour_texture, render_width, + render_height, 0, GL_RGBA16F, GL_DEPTH24_STENCIL8); + render_texture_init(&pp->pre_texture, render_width, + render_height, 0, GL_RGBA16F, 0); + render_texture_init(&pp->post_texture, render_width, + render_height, 0, GL_RGBA16F, 0); + render_texture_init(&pp->fbo_texture, render_width, + render_height, 0, GL_RGBA16F, 0); + render_texture_init(&pp->alpha_layer_texture, render_width, + render_height, 0, GL_RGBA16F, GL_DEPTH24_STENCIL8); + gl_state_bind_texture_2d(pp->render_texture.depth_texture->texture); + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, + (GLint[]) { GL_RED, GL_RED, GL_RED, GL_ONE }); + gl_state_bind_texture_2d(pp->sss_contour_texture.depth_texture->texture); + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, + (GLint[]) { GL_RED, GL_RED, GL_RED, GL_ONE }); + gl_state_bind_texture_2d(0); + pp->render_width = render_width; + pp->render_height = render_height; + } + + pp->sprite_width = sprite_width; + pp->sprite_height = sprite_height; + + pp->screen_x_offset = (screen_width - sprite_width) / 2 + (screen_width - sprite_width) % 2; + pp->screen_y_offset = (screen_height - sprite_height) / 2 + (screen_height - sprite_height) % 2; + + if (pp->screen_width != screen_width || pp->screen_height != screen_height) { + render_texture_init(&pp->screen_texture, screen_width, + screen_height, 0, GL_R11F_G11F_B10F, 0); + pp->screen_width = screen_width; + pp->screen_height = screen_height; } } -#include "render_texture.h" -#include "texture.h" -#include "post_process/dof.h" +int32_t post_process_movie_texture_set(post_process_struct* pp, texture* movie_texture) { + if (!movie_texture) + return -1; -typedef struct struc_187 { - texture* field_0; - render_texture field_8; - int field_38; -} struc_187; + int32_t index = 0; + while (pp->movie_textures_data[index]) + if (++index >= 1) + return -1; -typedef struct struc_186 { - struc_187 field_0[4]; - char field_100; -} struc_186; + pp->movie_textures_data[index] = movie_texture; + render_texture_set_color_depth_textures(&pp->movie_textures[index], + movie_texture->texture, 0, 0, false); + return index; +} -typedef struct struc_188 { - vec4 field_0[8]; - float_t field_80; - GLuint field_84[3]; - GLuint field_90[3]; -} struc_188; +void post_process_movie_texture_free(post_process_struct* pp, texture* movie_texture) { + if (!movie_texture) + return; -typedef struct struc_198 { - fbo_struct fbo; - GLuint program; - GLuint sampler; - GLuint vao; -} struc_198; + int32_t index = 0; + while (pp->movie_textures_data[index] != movie_texture) + if (++index >= 1) + return; -typedef struct post_process_struct { - int field_0; - int field_4; - int ssaa; - int taa; - int mlaa; - int field_14; - int field_18; - int field_1C; - int field_20; - int field_24; - render_texture field_28[5]; - render_texture field_118[3]; - texture* field_1A8[3]; - render_texture field_1C0; - int* field_1F0; - render_texture field_1F8; - render_texture field_228[5]; - texture* field_318[5]; - render_texture field_340; - int field_370; - int field_374; - render_texture field_378; - GLuint field_3A8; - int field_3AC; - texture* exposure_history; - render_texture field_3B8; - render_texture field_3E8; - GLuint tonemap_lut_texture; - int field_41C; - render_texture field_420[2]; - GLuint field_480; - int field_484; - render_texture* field_488; - int field_490; - GLuint field_494[3]; - GLuint field_4A0[3]; - int field_4AC[3]; - int field_4B8[3]; - int field_4C4; - GLuint lens_flare_texture; - GLuint lens_shaft_texture; - int lens_ghost_texture; - int lens_flare_count; - int width; - int height; - int render_width; - int render_height; - int field_4E8[5]; - int field_4FC[5]; - int field_510[5]; - int field_524[5]; - float_t field_538; - float_t field_53C; - int32_t reduce_width[5]; - int32_t reduce_height[5]; - int taa_texture_selector; - int taa_texture; - float taa_blend; - vec3 view_point; - vec3 interest; - vec3 view_point_prev; - vec3 interest_prev; - mat4 field_5A4; - mat4 field_5E4; - int field_624; - int field_628; - char fast_change_happened; - char field_62D; - char field_62E; - char field_62F; - int screen_x_offset; - int screen_y_offset; - int screen_width; - int screen_height; - int update_lut; - int field_644; - struc_188 field_648[6]; - int exposure_history_counter; - int field_9F4; - vec3 lens_flare_pos; - float lens_shaft_scale; - float_t lens_shaft_inv_scale; - float field_A0C; - float field_A10; - float field_A14; - int16_t* field_A18[15]; - int field_A90; - int field_A94; - render_texture field_A98[16]; - __int64 field_D98; - render_texture field_DA0[1]; - int field_DD0; - int field_DD4; - post_process_dof* dof; - texture* field_DE0; - struc_198* field_DE8; - int32_t saturate_select; - int32_t scene_fade_select; - int32_t tone_trans_select; - float saturate_coeff[2]; - float scene_fade_color[6]; - float scene_fade_alpha[2]; - int32_t scene_fade_blend_func[2]; - float tone_trans_scale[6]; - float tone_trans_offset[6]; - float tone_trans_start[6]; - float tone_trans_end[6]; - int tone_map; - float_t exposure; - float_t exposure_rate; - int32_t auto_exposure; - float_t gamma; - float_t gamma_rate; - int32_t saturate_power; - int32_t mag_filter; - float_t fade_alpha; - int field_EB0; - float_t lens_flare; - float_t lens_shaft; - float_t lens_ghost; - vec3 radius; - vec3 intensity; - int field_ED8; - int field_EDC; - struc_186 field_EE0[6]; -} post_process_struct; + pp->movie_textures_data[index] = 0; + render_texture_free(&pp->movie_textures[index]); +} + +int32_t post_process_render_texture_set(post_process_struct* pp, texture* render_texture, bool task_photo) { + if (!render_texture) + return -1; + + int32_t index = 0; + if (task_photo) + index = 15; + else + while (pp->render_textures_data[index]) + if (++index >= 15) + return -1; + + pp->render_textures_data[index] = render_texture; + render_texture_set_color_depth_textures(&pp->render_textures[index], + render_texture->texture, 0, 0, false); + return index; +} + +void post_process_render_texture_free(post_process_struct* pp, texture* render_texture, bool task_photo) { + if (!render_texture) + return; + + int32_t index = 0; + if (task_photo) + index = 15; + else + while (pp->render_textures_data[index] != render_texture) + if (++index >= 15) + return; + + pp->render_textures_data[index] = 0; + render_texture_free(&pp->render_textures[index]); +} + +void post_process_reset(post_process_struct* pp) { + pp->mlaa = true; + pp->mag_filter = POST_PROCESS_MAG_FILTER_BILINEAR; + post_process_dof_initialize_data(pp->dof, 0, 0); + post_process_blur_initialize_data(pp->blur, + &((vec3) { 2.0f, 2.0f, 2.0f }), &((vec3) { 1.0f, 1.0f, 1.0f })); + post_process_tone_map_initialize_data(pp->tone_map, 2.0f, true, + 1.0f, 1, 1.0f, &((vec3) { 0.0f, 0.0f, 0.0f }), 0.0f, 0, + &((vec3) { 0.0f, 0.0f, 0.0f }), &((vec3) { 1.0f, 1.0f, 1.0f }), + TONE_MAP_YCC_EXPONENT); +} + +void post_process_free(post_process_struct* pp) { + post_process_aa_dispose(pp->aa); + post_process_blur_dispose(pp->blur); + post_process_dof_dispose(pp->dof); + post_process_exposure_dispose(pp->exposure); + post_process_tone_map_dispose(pp->tone_map); + render_texture_free(&pp->render_texture); + render_texture_free(&pp->buf_texture); + render_texture_free(&pp->sss_contour_texture); + render_texture_free(&pp->pre_texture); + render_texture_free(&pp->post_texture); + render_texture_free(&pp->fbo_texture); + render_texture_free(&pp->alpha_layer_texture); + render_texture_free(&pp->screen_texture); + shader_glsl_free(&pp->alpha_layer_shader); + + if (pp->samplers[0]) { + glDeleteSamplers(2, pp->samplers); + pp->samplers[0] = 0; + } +} diff --git a/src/CRE/post_process.h b/src/CRE/post_process.h index 7aacbadc..16d52b34 100644 --- a/src/CRE/post_process.h +++ b/src/CRE/post_process.h @@ -7,94 +7,64 @@ #include "../KKdLib/default.h" #include "../KKdLib/vec.h" +#include "post_process/aa.h" +#include "post_process/blur.h" +#include "post_process/dof.h" +#include "post_process/exposure.h" +#include "post_process/tone_map.h" +#include "camera.h" -#define GAUSSIAN_KERNEL_SIZE 7 +typedef enum post_process_mag_filter_type { + POST_PROCESS_MAG_FILTER_NEAREST = 0, + POST_PROCESS_MAG_FILTER_BILINEAR = 1, + POST_PROCESS_MAG_FILTER_SHARPEN_5_TAP = 2, + POST_PROCESS_MAG_FILTER_SHARPEN_4_TAP = 3, + POST_PROCESS_MAG_FILTER_CONE_4_TAP = 4, + POST_PROCESS_MAG_FILTER_CONE_2_TAP = 5, + POST_PROCESS_MAG_FILTER_MAX = 6, +} post_process_mag_filter_type; -typedef struct radius { - vec3 val[GAUSSIAN_KERNEL_SIZE]; - vec3 rgb; - bool update; -} radius; +typedef struct post_process_struct { + bool ssaa; + bool mlaa; + int32_t parent_bone_node; + render_texture render_texture; + render_texture buf_texture; + render_texture sss_contour_texture; + render_texture pre_texture; + render_texture post_texture; + render_texture fbo_texture; + render_texture alpha_layer_texture; + render_texture screen_texture; + texture* render_textures_data[16]; + render_texture render_textures[16]; + texture* movie_textures_data[1]; + render_texture movie_textures[1]; + post_process_aa* aa; + post_process_blur* blur; + post_process_dof* dof; + post_process_exposure* exposure; + post_process_tone_map* tone_map; + GLuint samplers[2]; + shader_glsl alpha_layer_shader; + int32_t render_width; + int32_t render_height; + int32_t sprite_width; + int32_t sprite_height; + int32_t screen_x_offset; + int32_t screen_y_offset; + int32_t screen_width; + int32_t screen_height; + post_process_mag_filter_type mag_filter; +} post_process_struct; -typedef struct intensity { - vec3 val; - vec3 rgb; - bool update; -} intensity; - -#define TONE_MAP_SAT_GAMMA_SAMPLES 32 - -typedef struct tone_map_data { - vec4 p_exposure; - vec4 p_flare_coef; - vec4 p_fade_color; - vec4 p_tone_scale; - vec4 p_tone_offset; - vec4 p_fade_func; - vec4 p_inv_tone; -} tone_map_data; - -typedef struct tone_map { - vec2 tex[16 * TONE_MAP_SAT_GAMMA_SAMPLES]; - tone_map_data data; - float_t exposure; - bool auto_exposure; - float_t gamma; - float_t gamma_rate; - int32_t saturate_power; - float_t saturate_coeff; - vec3 scene_fade_color; - float_t scene_fade_alpha; - int32_t scene_fade_blend_func; - vec3 tone_trans_start; - vec3 tone_trans_end; - int32_t tone_map_method; - bool update_tex; -} tone_map; - -extern radius* radius_init(); -extern void radius_initialize(radius* rad, vec3* rgb); -extern vec3* radius_get(radius* rad); -extern void radius_set(radius* rad, vec3* value); -extern void radius_dispose(radius* rad); - -extern intensity* intensity_init(); -extern void intensity_initialize(intensity* inten, vec3* rgb); -extern vec3* intensity_get(intensity* inten); -extern void intensity_set(intensity* inten, vec3* value); -extern void intensity_dispose(intensity* inten); - -extern tone_map* tone_map_init(); -extern void tone_map_initialize(tone_map* tm, float_t exposure, bool auto_exposure, - float_t gamma, int32_t saturate_power, float_t saturate_coeff, - vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, - vec3* tone_trans_start, vec3* tone_trans_end, int32_t tone_map_method); -extern void tone_map_initialize_rate(tone_map* tm, float_t exposure, bool auto_exposure, - float_t gamma, float_t gamma_rate, int32_t saturate_power, float_t saturate_coeff, - vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, - vec3* tone_trans_start, vec3* tone_trans_end, int32_t tone_map_method); -extern float_t tone_map_get_exposure(tone_map* tm); -extern void tone_map_set_exposure(tone_map* tm, float_t value); -extern bool tone_map_get_auto_exposure(tone_map* tm); -extern void tone_map_set_auto_exposure(tone_map* tm, bool value); -extern float_t tone_map_get_gamma(tone_map* tmsg); -extern void tone_map_set_gamma(tone_map* tmsg, float_t value); -extern float_t tone_map_get_gamma_rate(tone_map* tmsg); -extern void tone_map_set_gamma_rate(tone_map* tmsg, float_t value); -extern int32_t tone_map_get_saturate_power(tone_map* tmsg); -extern void tone_map_set_saturate_power(tone_map* tmsg, int32_t value); -extern float_t tone_map_get_saturate_coeff(tone_map* tmsg); -extern void tone_map_set_saturate_coeff(tone_map* tmsg, float_t value); -extern vec3* tone_map_get_scene_fade_color(tone_map* tm); -extern void tone_map_set_scene_fade_color(tone_map* tm, vec3* value); -extern float_t tone_map_get_scene_fade_alpha(tone_map* tm); -extern void tone_map_set_scene_fade_alpha(tone_map* tm, float_t value); -extern int32_t tone_map_get_scene_fade_blend_func(tone_map* tm); -extern void tone_map_set_scene_fade_blend_func(tone_map* tm, int32_t value); -extern vec3* tone_map_get_tone_trans_start(tone_map* tm); -extern void tone_map_set_tone_trans_start(tone_map* tm, vec3* value); -extern vec3* tone_map_get_tone_trans_end(tone_map* tm); -extern void tone_map_set_tone_trans_end(tone_map* tm, vec3* value); -extern int32_t tone_map_get_tone_map_method(tone_map* tm); -extern void tone_map_set_tone_map_method(tone_map* tm, int32_t value); -extern void tone_map_dispose(tone_map* tm); +extern void post_process_init(post_process_struct* pp); +extern void post_process_apply(post_process_struct* pp, camera* cam, texture* light_proj_tex, int32_t npr_param); +extern void post_process_init_fbo(post_process_struct* pp, int32_t render_width, int32_t render_height, + int32_t sprite_width, int32_t sprite_height, int32_t screen_width, int32_t screen_height); +extern void post_process_reset(post_process_struct* pp); +extern int32_t post_process_movie_texture_set(post_process_struct* pp, texture* movie_texture); +extern void post_process_movie_texture_free(post_process_struct* pp, texture* movie_texture); +extern int32_t post_process_render_texture_set(post_process_struct* pp, texture* render_texture, bool task_photo); +extern void post_process_render_texture_free(post_process_struct* pp, texture* render_texture, bool task_photo); +extern void post_process_free(post_process_struct* pp); diff --git a/src/CRE/post_process/aa.c b/src/CRE/post_process/aa.c new file mode 100644 index 00000000..ef82873b --- /dev/null +++ b/src/CRE/post_process/aa.c @@ -0,0 +1,268 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "aa.h" +#include "../fbo.h" +#include "../gl_state.h" +#include "../post_process.h" +#include "../shader_ft.h" + +static void post_process_aa_free_fbo(post_process_aa* exp); +static void post_process_aa_generate_area_texture(post_process_aa* aa); +static void post_process_aa_calculate_area_texture_data(uint8_t* a1, int32_t a2, int32_t a3); +static void post_process_aa_calculate_area_texture_data_sub(float_t* a1, + float_t* a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6); +static float_t post_process_aa_calculate_area_texture_data_sub_sub(int32_t a1, int32_t a2); + +post_process_aa* post_process_aa_init() { + post_process_aa* aa = force_malloc(sizeof(post_process_aa)); + post_process_aa_generate_area_texture(aa); + return aa; +} + +void post_process_apply_mlaa(post_process_aa* aa, render_texture* rt, + render_texture* buf_rt, GLuint* samplers, int32_t a4) { + render_texture_bind(aa->mlaa_buffer, 0); + gl_state_active_bind_texture_2d(0, rt->color_texture->texture); + gl_state_bind_sampler(0, samplers[1]); + uniform_value[U_MLAA] = 0; + shader_set(&shaders_ft, SHADER_FT_MLAA); + render_texture_draw_params(&shaders_ft, aa->width, aa->height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + render_texture_bind(&aa->mlaa_buffer[1], 0); + gl_state_active_bind_texture_2d(0, aa->mlaa_buffer[0].color_texture->texture); + gl_state_active_bind_texture_2d(1, aa->mlaa_area_texture); + gl_state_bind_sampler(0, samplers[0]); + gl_state_bind_sampler(1, samplers[1]); + uniform_value[U20] = 2; + uniform_value[U_MLAA] = 1; + shader_set(&shaders_ft, SHADER_FT_MLAA); + render_texture_draw_params(&shaders_ft, aa->width, aa->height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + render_texture_bind(buf_rt, 0); + gl_state_active_bind_texture_2d(0, rt->color_texture->texture); + gl_state_active_bind_texture_2d(1, aa->mlaa_buffer[1].color_texture->texture); + gl_state_bind_sampler(0, samplers[1]); + uniform_value[U_MLAA] = 2; + uniform_value[U01] = a4 ? 1 : 0; + shader_set(&shaders_ft, SHADER_FT_MLAA); + render_texture_draw_params(&shaders_ft, aa->width, aa->height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + uniform_value[U01] = 0; + gl_state_active_bind_texture_2d(0, 0); + gl_state_active_bind_texture_2d(1, 0); + + fbo_blit(buf_rt->fbos[0], rt->fbos[0], + 0, 0, rt->color_texture->width, rt->color_texture->height, + 0, 0, buf_rt->color_texture->width, buf_rt->color_texture->height, GL_COLOR_BUFFER_BIT, GL_LINEAR); +} + +void post_process_aa_init_fbo(post_process_aa* aa, + int32_t width, int32_t height) { + if (!aa || (aa->width == width && aa->height == height)) + return; + + aa->width = width > 1 ? width : 1; + aa->height = height > 1 ? height : 1; + + render_texture_init(&aa->mlaa_buffer[0], aa->width, aa->height, 0, GL_RGBA8, 0); + render_texture_init(&aa->mlaa_buffer[1], aa->width, aa->height, 0, GL_RGBA8, 0); +} + +void post_process_aa_dispose(post_process_aa* exp) { + if (!exp) + return; + + post_process_aa_free_fbo(exp); + free(exp); +} + +static void post_process_aa_free_fbo(post_process_aa* aa) { + render_texture_free(&aa->mlaa_buffer[0]); + render_texture_free(&aa->mlaa_buffer[1]); + glDeleteTextures(1, &aa->mlaa_area_texture); +} + +static void post_process_aa_generate_area_texture(post_process_aa* aa) { + uint8_t pixels[35 * 35 * 2]; + for (int32_t i = 0; i < 5; i++) + for (int32_t j = 0; j < 5; j++) + post_process_aa_calculate_area_texture_data(pixels, j, i); + + glGenTextures(1, &aa->mlaa_area_texture); + gl_state_bind_texture_2d(aa->mlaa_area_texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, 35, 35, 0, GL_RG, GL_UNSIGNED_BYTE, pixels); + gl_state_bind_texture_2d(0); +} + +static void post_process_aa_calculate_area_texture_data(uint8_t* a1, int32_t a2, int32_t a3) { + uint8_t* v7 = &a1[7 * 7 * 10 * a3 + 14 * a2]; + for (int32_t i = 0; i < 7; i++) { + for (int32_t j = 0; j < 7; j++) { + float_t v11 = 0.0f; + float_t v12 = 0.0f; + post_process_aa_calculate_area_texture_data_sub(&v11, &v12, a2, a3, j, i); + v7[0] = (uint8_t)(v11 * 255.89999f); + v7[1] = (uint8_t)(v12 * 255.89999f); + v7 += 2; + } + v7 += 28 * 2; + } +} +static void post_process_aa_calculate_area_texture_data_sub(float_t* a2, + float_t* a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7) { + float_t v8 = 0.0f; + float_t v10 = 0.0f; + int32_t v11 = a6 + a7 + 1; + v11 = min(v11, 7); + + int32_t v12; + if (((a6 + a7 + 1) & 1) != 0) + v12 = (a6 + a7) / 2 + 1; + else + v12 = (a6 + a7 + 1) / 2; + + float_t v14; + int32_t v15; + switch (a5) { + case 0: + if (a4 == 1) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v11); + else if (a4 == 3) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v11); + break; + case 1: + if (a4 == 0) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v11); + else if (a4 == 1) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 >= v12) + v10 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v10 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v10 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12) * 2.0f; + } + } + else if (a4 == 3 || a4 == 4) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 < v12) + v8 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v10 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v8 = v10 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12); + } + } + break; + case 3: + if (a4 == 0) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v11); + else if (a4 == 1 || a4 == 4) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 < v12) + v10 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v8 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v8 = v10 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12); + } + } + else if (a4 == 3) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 < v12) + v8 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v8 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v8 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12) * 2.0f; + } + } + break; + case 4: + if (a4 == 1) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 < v12) + v10 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v8 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v8 = v10 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12); + } + } + else if (a4 == 3) { + if (((a6 + a7 + 1) & 1) == 0) { + v14 = -0.5f / (float_t)v12; + if (a6 < v12) + v8 = ((float_t)(a6 * 2 + 1) * v14 + 1.0f) * 0.5f; + else + v10 = ((float_t)(a7 * 2 + 1) * v14 + 1.0f) * 0.5f; + } + else { + v15 = v12 - 1; + if (a6 < v15) + v8 = post_process_aa_calculate_area_texture_data_sub_sub(a6, v12); + else if (a7 < v15) + v10 = post_process_aa_calculate_area_texture_data_sub_sub(a7, v12); + else + v8 = v10 = post_process_aa_calculate_area_texture_data_sub_sub(v15, v12); + } + } + break; + } + + *a2 = v8; + *a3 = v10; + return; +} + +static float_t post_process_aa_calculate_area_texture_data_sub_sub(int32_t a1, int32_t a2) { + float_t v2 = -0.5f / ((float_t)a2 - 0.5f); + float_t v3 = (float_t)a1 * v2 + 0.5f; + if (a1 >= a2 - 1) + return (v3 * 0.5f) * 0.5f; + else + return ((float_t)(a1 + 1) * v2 + v3 + 0.5f) * 0.5f; +} diff --git a/src/CRE/post_process/aa.h b/src/CRE/post_process/aa.h new file mode 100644 index 00000000..5de729fa --- /dev/null +++ b/src/CRE/post_process/aa.h @@ -0,0 +1,24 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/vec.h" +#include "../shared.h" +#include "../render_texture.h" + +typedef struct post_process_aa { + int32_t width; + int32_t height; + render_texture mlaa_buffer[2]; + GLuint mlaa_area_texture; +} post_process_aa; + +extern post_process_aa* post_process_aa_init(); +extern void post_process_apply_mlaa(post_process_aa* aa, render_texture* rt, + render_texture* buf_rt, GLuint* samplers, int32_t a4); +extern void post_process_aa_init_fbo(post_process_aa* aa, int32_t width, int32_t height); +extern void post_process_aa_dispose(post_process_aa* aa); diff --git a/src/CRE/post_process/blur.c b/src/CRE/post_process/blur.c new file mode 100644 index 00000000..e9482bbe --- /dev/null +++ b/src/CRE/post_process/blur.c @@ -0,0 +1,338 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "blur.h" +#include "../fbo.h" +#include "../gl_state.h" +#include "../post_process.h" +#include "../shader_ft.h" + +static void post_process_blur_free_fbo(post_process_blur* blur); +static void post_process_blur_radius_calculate(post_process_blur* blur); +static void post_process_blur_radius_calculate_gaussian_kernel(float_t* gaussian_kernel, + float_t radius, int32_t stride, int32_t offset); + +post_process_blur* post_process_blur_init() { + post_process_blur* blur = force_malloc(sizeof(post_process_blur)); + return blur; +} + +void post_process_get_blur(post_process_blur* blur, render_texture* rt) { + if (!blur) + return; + + uniform_value[U01] = 0; + + int32_t i = 0; + if (blur->count_down > 0) { + uniform_value[U_REDUCE] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + for (; i < blur->count_down; i++) { + glViewport(0, 0, blur->width_down[i], blur->height_down[i]); + render_texture_bind(&blur->tex_down[i], 0); + gl_state_active_bind_texture_2d(0, i + ? blur->tex_down[i - 1].color_texture->texture + : rt->color_texture->texture); + render_texture_draw_params(&shaders_ft, + blur->width_down[i], blur->height_down[i], 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + } + i--; + } + + uniform_value[U_REDUCE] = 3; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + shader_local_frag_set(&shaders_ft, 2, 1.1f, 1.1f, 1.1f, 0.0f); + + glViewport(0, 0, 256, 144); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->count_down > 0 + ? blur->tex_down[i].color_texture->texture + : rt->color_texture->texture); + render_texture_draw_params(&shaders_ft, blur->width, blur->height, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + uniform_value[U_GAUSS] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_GAUSS); + + glViewport(0, 0, 256, 144); + render_texture_bind(&blur->tex[5], 0); + gl_state_active_bind_texture_2d(0, blur->tex[0].color_texture->texture); + render_texture_draw_params(&shaders_ft, 256, 144, + 1.0f, blur->data.intensity.x * 0.5f, blur->data.intensity.y * 0.5f, blur->data.intensity.z * 0.5f, 1.0f); + + uniform_value[U_REDUCE] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + + glViewport(0, 0, 128, 72); + render_texture_bind(&blur->tex[1], 0); + gl_state_active_bind_texture_2d(0, blur->tex[0].color_texture->texture); + render_texture_draw_params(&shaders_ft, 256, 144, 0.75f, 1.0f, 1.0f, 1.0f, 1.0f); + + uniform_value[U_REDUCE] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + + glViewport(0, 0, 64, 36); + render_texture_bind(&blur->tex[2], 0); + gl_state_active_bind_texture_2d(0, blur->tex[1].color_texture->texture); + render_texture_draw_params(&shaders_ft, 128, 72, 0.75f, 1.0f, 1.0f, 1.0f, 1.0f); + + uniform_value[U_REDUCE] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + + glViewport(0, 0, 32, 18); + render_texture_bind(&blur->tex[3], 0); + gl_state_active_bind_texture_2d(0, blur->tex[2].color_texture->texture); + render_texture_draw_params(&shaders_ft, 64, 36, 0.75f, 1.0f, 1.0f, 1.0f, 1.0f); + + uniform_value[U_EXPOSURE] = 0; + render_texture_shader_set(&shaders_ft, SHADER_FT_EXPOSURE); + + glViewport(0, 0, 8, 8); + render_texture_bind(&blur->tex[4], 0); + gl_state_active_bind_texture_2d(0, blur->tex[3].color_texture->texture); + render_texture_draw_params(&shaders_ft, 32, 18, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + vec3 intensity = blur->data.intensity; + vec3* gauss = blur->data.gauss; + + vec3 v[POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE]; + for (int32_t i = 0; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++) + vec3_mult(gauss[i], intensity, v[i]); + + uniform_value[U_GAUSS] = 0; + render_texture_shader_set(&shaders_ft, SHADER_FT_GAUSS); + shader_local_frag_set(&shaders_ft, 1, 1.0f, 0.0f, 1.0f, 0.0f); + for (int32_t i = 0; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++) + shader_local_frag_set(&shaders_ft, 4ULL + i, v[i].x, v[i].y, v[i].z, 0.0f); + + glViewport(0, 0, 128, 72); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[1].color_texture->texture); + render_texture_draw_params(&shaders_ft, 128, 72, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[1].fbos[0], + 0, 0, 128, 72, + 0, 0, 128, 72, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + glViewport(0, 0, 64, 36); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[2].color_texture->texture); + render_texture_draw_params(&shaders_ft, 64, 36, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[2].fbos[0], + 0, 0, 64, 36, + 0, 0, 64, 36, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + glViewport(0, 0, 32, 18); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[3].color_texture->texture); + render_texture_draw_params(&shaders_ft, 32, 18, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[3].fbos[0], + 0, 0, 32, 18, + 0, 0, 32, 18, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + shader_local_frag_set(&shaders_ft, 1, 0.0f, 1.0f, 0.0f, 1.0f); + + glViewport(0, 0, 128, 72); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[1].color_texture->texture); + render_texture_draw_params(&shaders_ft, 128, 72, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[1].fbos[0], + 0, 0, 128, 72, + 0, 0, 128, 72, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + + glViewport(0, 0, 64, 36); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[2].color_texture->texture); + render_texture_draw_params(&shaders_ft, 64, 36, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[2].fbos[0], + 0, 0, 64, 36, + 0, 0, 64, 36, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + glViewport(0, 0, 32, 18); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[3].color_texture->texture); + render_texture_draw_params(&shaders_ft, 32, 18, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + fbo_blit(blur->tex[0].fbos[0], blur->tex[3].fbos[0], + 0, 0, 32, 18, + 0, 0, 32, 18, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + uniform_value[U_REDUCE] = 7; + render_texture_shader_set(&shaders_ft, SHADER_FT_REDUCE); + + glViewport(0, 0, 256, 144); + render_texture_bind(&blur->tex[0], 0); + gl_state_active_bind_texture_2d(0, blur->tex[5].color_texture->texture); + gl_state_active_bind_texture_2d(1, blur->tex[1].color_texture->texture); + gl_state_active_bind_texture_2d(2, blur->tex[2].color_texture->texture); + gl_state_active_bind_texture_2d(3, blur->tex[3].color_texture->texture); + render_texture_draw_params(&shaders_ft, 32, 18, 0.25f, 0.15f, 0.25f, 0.25f, 0.25f); + +} + +void post_process_blur_init_fbo(post_process_blur* blur, + int32_t width, int32_t height) { + if (!blur || (blur->width == width && blur->height == height)) + return; + + if (!blur->tex[0].color_texture) + render_texture_init(&blur->tex[0], 256, 144, 0, GL_RGBA16F, 0); + if (!blur->tex[1].color_texture) + render_texture_init(&blur->tex[1], 128, 72, 0, GL_RGBA16F, 0); + if (!blur->tex[2].color_texture) + render_texture_init(&blur->tex[2], 64, 36, 0, GL_RGBA16F, 0); + if (!blur->tex[3].color_texture) + render_texture_init(&blur->tex[3], 32, 18, 0, GL_RGBA16F, 0); + if (!blur->tex[4].color_texture) + render_texture_init(&blur->tex[4], 8, 8, 0, GL_R32F, 0); + if (!blur->tex[5].color_texture) + render_texture_init(&blur->tex[5], 256, 144, 0, GL_RGBA16F, 0); + + blur->width = width > 1 ? width : 1; + blur->height = height > 1 ? height : 1; + + int32_t i = 0; + width = blur->width; + height = blur->height; + while (width > 512 && height > 288) { + width /= 2; + height /= 2; + i++; + } + + render_texture* tex_down = blur->tex_down; + int32_t* width_down = blur->width_down; + int32_t* height_down = blur->height_down; + + if (!tex_down) + tex_down = force_malloc_s(render_texture, i); + else if (blur->count_down < i) { + void* temp = force_malloc_s(render_texture, i); + memcpy(temp, tex_down, sizeof(render_texture) * blur->count_down); + free(tex_down); + tex_down = temp; + } + + if (!width_down) + width_down = force_malloc_s(int32_t, i); + else if (blur->count_down < i) { + void* temp = force_malloc_s(int32_t, i); + memcpy(temp, width_down, sizeof(int32_t) * blur->count_down); + free(width_down); + width_down = temp; + } + + if (!height_down) + height_down = force_malloc_s(int32_t, i); + else if (blur->count_down < i) { + void* temp = force_malloc_s(int32_t, i); + memcpy(temp, height_down, sizeof(int32_t) * blur->count_down); + free(height_down); + height_down = temp; + } + + blur->count_down = i; + + i = 0; + width = blur->width; + height = blur->height; + while (width > 512 && height > 288) { + width_down[i] = width /= 2; + height_down[i] = height /= 2; + i++; + } + + for (i = 0; i < blur->count_down; i++) + render_texture_init(&tex_down[i], width_down[i], height_down[i], 0, GL_RGBA16F, 0); + + gl_state_bind_framebuffer(0); + + blur->tex_down = tex_down; + blur->width_down = width_down; + blur->height_down = height_down; +} + +void post_process_blur_dispose(post_process_blur* blur) { + if (!blur) + return; + + post_process_blur_free_fbo(blur); + free(blur); +} + +static void post_process_blur_free_fbo(post_process_blur* blur) { + for (int32_t i = 0; i < blur->count_down; i++) + render_texture_free(&blur->tex_down[i]); + for (int32_t i = 0; i < 6; i++) + render_texture_free(&blur->tex[i]); + free(blur->tex_down); + free(blur->height_down); + free(blur->width_down); +} + +void post_process_blur_initialize_data(post_process_blur* blur, vec3* radius, vec3* intensity) { + blur->data.radius.x = clamp(radius->x, 0.0f, 3.0f); + blur->data.radius.y = clamp(radius->y, 0.0f, 3.0f); + blur->data.radius.z = clamp(radius->z, 0.0f, 3.0f); + blur->data.intensity.x = clamp(intensity->x, 0.0f, 2.0f); + blur->data.intensity.y = clamp(intensity->y, 0.0f, 2.0f); + blur->data.intensity.z = clamp(intensity->z, 0.0f, 2.0f); + post_process_blur_radius_calculate(blur); +} + +inline void post_process_blur_get_radius(post_process_blur* blur, vec3* value) { + *value = blur->data.radius; +} + +inline void post_process_blur_set_radius(post_process_blur* blur, vec3* value) { + vec3 temp; + temp.x = clamp(value->x, 0.0f, 3.0f); + temp.y = clamp(value->y, 0.0f, 3.0f); + temp.z = clamp(value->z, 0.0f, 3.0f); + if (temp.x != blur->data.radius.x || temp.y + != blur->data.radius.y || temp.z != blur->data.radius.z) { + blur->data.radius = temp; + post_process_blur_radius_calculate(blur); + } +} + +inline void post_process_blur_get_intensity(post_process_blur* blur, vec3* value) { + *value = blur->data.intensity; +} + +inline void post_process_blur_set_intensity(post_process_blur* blur, vec3* value) { + blur->data.intensity.x = clamp(value->x, 0.0f, 2.0f); + blur->data.intensity.y = clamp(value->y, 0.0f, 2.0f); + blur->data.intensity.z = clamp(value->z, 0.0f, 2.0f); +} + +static void post_process_blur_radius_calculate(post_process_blur* blur) { + float_t radius_scale = 0.8f; + vec3 radius = blur->data.radius; + post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.x * radius_scale, 3, 0); + post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.y * radius_scale, 3, 1); + post_process_blur_radius_calculate_gaussian_kernel((float_t*)blur->data.gauss, radius.z * radius_scale, 3, 2); +} + +static void post_process_blur_radius_calculate_gaussian_kernel(float_t* gaussian_kernel, + float_t radius, int32_t stride, int32_t offset) { + if (stride < 1) + stride = 1; + if (offset < 0) + offset = 0; + + gaussian_kernel[0 * stride + offset] = 1.0f; + for (int32_t i = 1; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++) + gaussian_kernel[i * stride + offset] = 0.0f; + double_t temp_gaussian_kernel[POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE]; + double_t s = radius; + s = -1.0 / (2.0 * s * s); + double_t sum = 0.5; + temp_gaussian_kernel[0] = 1.0; + for (size_t i = 1; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++) + sum += temp_gaussian_kernel[i] = exp(i * i * s); + + sum = 0.5 / sum; + for (size_t i = 0; i < POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE; i++) + gaussian_kernel[i * stride + offset] = (float_t)(temp_gaussian_kernel[i] * sum); +} diff --git a/src/CRE/post_process/blur.h b/src/CRE/post_process/blur.h new file mode 100644 index 00000000..f9d36df3 --- /dev/null +++ b/src/CRE/post_process/blur.h @@ -0,0 +1,42 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/vec.h" +#include "../shared.h" +#include "../render_texture.h" + +#define POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE 7 + +typedef struct post_process_blur_data { + vec3 gauss[POST_PROCESS_BLUR_GAUSSIAN_KERNEL_SIZE]; + vec3 radius; + vec3 intensity; +} post_process_blur_data; + +typedef struct post_process_blur { + post_process_blur_data data; + int32_t width; + int32_t height; + render_texture tex[6]; + int32_t* width_down; + int32_t* height_down; + render_texture* tex_down; + int32_t count_down; +} post_process_blur; + +extern post_process_blur* post_process_blur_init(); +extern void post_process_get_blur(post_process_blur* blur, render_texture* rt); +extern void post_process_blur_init_fbo(post_process_blur* blur, + int32_t width, int32_t height); +extern void post_process_blur_dispose(post_process_blur* blur); + +extern void post_process_blur_initialize_data(post_process_blur* blur, vec3* radius, vec3* intensity); +extern void post_process_blur_get_radius(post_process_blur* blur, vec3* value); +extern void post_process_blur_set_radius(post_process_blur* blur, vec3* value); +extern void post_process_blur_get_intensity(post_process_blur* blur, vec3* value); +extern void post_process_blur_set_intensity(post_process_blur* blur, vec3* value); diff --git a/src/CRE/post_process/dof.c b/src/CRE/post_process/dof.c index 6bce3d94..85a254d9 100644 --- a/src/CRE/post_process/dof.c +++ b/src/CRE/post_process/dof.c @@ -8,13 +8,19 @@ #include "../gl_state.h" #include "../camera.h" +typedef struct post_process_dof_shader_data { + vec4 g_depth_params; + vec4 g_spread_scale; + vec4 g_depth_params2; +} post_process_dof_shader_data; + static const char* dof_vert_shader = "#version 430\n" "out VertexData {\n" " vec2 texcoord;\n" "} result;\n" "\n" -"void main(){\n" +"void main() {\n" " gl_Position.x = -1.0 + float(gl_VertexID / 2) * 4.0;\n" " gl_Position.y = 1.0 - float(gl_VertexID % 2) * 4.0;\n" " gl_Position.z = 0.0;\n" @@ -197,7 +203,7 @@ static const char* dof_frag_shader_step_1 = "#else\n" "vec4 calculate_coc_pixel_from_value_in_zbuffer(const vec4 value_in_zbuffer) {\n" " return clamp_coc_pixel(abs(value_in_zbuffer * g_depth_params.z" - " + g_depth_params.w) * 1000.0 * TEST_SCALE);\n" +" + g_depth_params.w) * 1000.0 * TEST_SCALE);\n" " //Appropriate; converted to 1[m]=100[pixel]. @todo Appropriate\n" "}\n" "#endif\n" @@ -564,21 +570,44 @@ static const char* dof_frag_shader_step_5 = " result.rgb = max(tone_map(result.rgb, 1.0), vec3(0.0));\n" "}\n"; +static const dof_debug dof_debug_default = { + .flags = 0, + .distance_to_focus = 10.0f, + .focal_length = 40.0f, + .f_number = 1.4f, + .f2 = { + .distance_to_focus = 10.0f, + .focus_range = 1.0f, + .fuzzing_range = 0.5f, + .ratio = 1.0f, + }, +}; + +static const dof_pv dof_pv_default = { + .enable = false, + .f2 = { + .distance_to_focus = 10.0f, + .focus_range = 1.0f, + .fuzzing_range = 0.5f, + .ratio = 1.0f, + }, +}; + static void post_process_apply_dof_f2(post_process_dof* dof, render_texture* rt, - GLuint color_texture, GLuint depth_texture, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, float_t min_dist_to_focus, float_t max_dist_to_focus, float_t fov, float_t dist_to_focus, float_t focus_range, float_t fuzzing_range, float_t ratio); static void post_process_apply_dof_physical(post_process_dof* dof, render_texture* rt, - GLuint color_texture, GLuint depth_texture, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, float_t min_dist_to_focus, float_t max_dist_to_focus, float_t dist_to_focus, float_t focal_length, float_t fov, float_t f_number); static void post_process_apply_dof_steps_1_2(post_process_dof* dof, - GLuint depth_texture, bool f2); + GLuint* samplers, GLuint depth_texture, bool f2); static void post_process_apply_dof_step_3(post_process_dof* dof, - GLuint color_texture, GLuint depth_texture, bool f2); -static void post_process_apply_dof_step_4(post_process_dof* dof, bool f2); -static void post_process_apply_dof_step_5(post_process_dof* dof, - render_texture* rt, GLuint color_texture, GLuint depth_texture, bool f2); + GLuint* samplers, GLuint color_texture, GLuint depth_texture, bool f2); +static void post_process_apply_dof_step_4(post_process_dof* dof, GLuint* samplers, bool f2); +static void post_process_apply_dof_step_5(post_process_dof* dof, render_texture* rt, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, bool f2); static void post_process_dof_calculate_texcoords(vec2* data, float_t size); static void post_process_dof_free_fbo(post_process_dof* dof); static void post_process_dof_load_shaders(post_process_dof* dof); @@ -588,20 +617,23 @@ static void post_process_dof_update_data(post_process_dof* dof, float_t min_dist float_t max_dist, float_t fov, float_t dist, float_t focal_length, float_t f_number, float_t focus_range, float_t fuzzing_range, float_t ratio); -extern camera* cam; - -void post_process_dof_init(post_process_dof* dof) { - memset(dof, 0, sizeof(post_process_dof)); +post_process_dof* post_process_dof_init() { + post_process_dof* dof = force_malloc(sizeof(post_process_dof)); post_process_dof_load_shaders(dof); + return dof; } -void post_process_apply_dof(post_process_dof* dof, render_texture* rt, dof_struct* dof_data) { +void post_process_apply_dof(post_process_dof* dof, + render_texture* rt, GLuint* samplers, camera* cam) { + if (!dof) + return; + bool use_dof_f2 = false; - if (dof_data->debug.flags & DOF_DEBUG_USE_UI_PARAMS) { - if (dof_data->debug.flags & DOF_DEBUG_ENABLE_DOF) { - if (dof_data->debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF) { - float_t dist_to_focus = dof_data->debug.distance_to_focus; - if (dof_data->debug.flags & DOF_DEBUG_AUTO_FOCUS && false) { + if (dof->data.debug.flags & DOF_DEBUG_USE_UI_PARAMS) { + if (dof->data.debug.flags & DOF_DEBUG_ENABLE_DOF) { + if (dof->data.debug.flags & DOF_DEBUG_ENABLE_PHYS_DOF) { + float_t dist_to_focus = dof->data.debug.distance_to_focus; + if (dof->data.debug.flags & DOF_DEBUG_AUTO_FOCUS && false) { mat4 view_transpose; mat4_transpose(&cam->view, &view_transpose); vec3 chara_trans = vec3_null; @@ -610,46 +642,44 @@ void post_process_apply_dof(post_process_dof* dof, render_texture* rt, dof_struc } dist_to_focus = max(dist_to_focus, (float_t)cam->min_distance); - post_process_apply_dof_physical(dof, rt, + post_process_apply_dof_physical(dof, rt, samplers, rt->color_texture->texture, rt->depth_texture->texture, (float_t)cam->min_distance, (float_t)cam->max_distance, (float_t)cam->fov, dist_to_focus, - dof_data->debug.focal_length, dof_data->debug.f_number); + dof->data.debug.focal_length, dof->data.debug.f_number); } else { - float_t fuzzing_range = max(dof_data->debug.f2.fuzzing_range, 0.01f); - post_process_apply_dof_f2(dof, rt, + float_t fuzzing_range = max(dof->data.debug.f2.fuzzing_range, 0.01f); + post_process_apply_dof_f2(dof, rt, samplers, rt->color_texture->texture, rt->depth_texture->texture, (float_t)cam->min_distance, (float_t)cam->max_distance, (float_t)cam->fov, - dof_data->debug.f2.distance_to_focus, dof_data->debug.f2.focus_range, - fuzzing_range, dof_data->debug.f2.ratio); + dof->data.debug.f2.distance_to_focus, dof->data.debug.f2.focus_range, + fuzzing_range, dof->data.debug.f2.ratio); use_dof_f2 = true; } } } - else if (dof_data->pv.enable && dof_data->pv.f2.ratio > 0.0f) { - float_t fuzzing_range = max(dof_data->pv.f2.fuzzing_range, 0.01f); - post_process_apply_dof_f2(dof, rt, + else if (dof->data.pv.enable && dof->data.pv.f2.ratio > 0.0f) { + float_t fuzzing_range = max(dof->data.pv.f2.fuzzing_range, 0.01f); + post_process_apply_dof_f2(dof, rt, samplers, rt->color_texture->texture, rt->depth_texture->texture, (float_t)cam->min_distance, (float_t)cam->max_distance, (float_t)cam->fov, - dof_data->pv.f2.distance_to_focus, dof_data->pv.f2.focus_range, - fuzzing_range, dof_data->pv.f2.ratio); - dof_data->debug.flags |= DOF_DEBUG_ENABLE_DOF; - dof_data->debug.f2.distance_to_focus = dof_data->pv.f2.distance_to_focus; - dof_data->debug.f2.focus_range = dof_data->pv.f2.focus_range; - dof_data->debug.f2.fuzzing_range = dof_data->pv.f2.fuzzing_range; - dof_data->debug.f2.ratio = dof_data->pv.f2.ratio; + dof->data.pv.f2.distance_to_focus, dof->data.pv.f2.focus_range, + fuzzing_range, dof->data.pv.f2.ratio); + dof->data.debug.flags |= DOF_DEBUG_ENABLE_DOF; + dof->data.debug.f2.distance_to_focus = dof->data.pv.f2.distance_to_focus; + dof->data.debug.f2.focus_range = dof->data.pv.f2.focus_range; + dof->data.debug.f2.fuzzing_range = dof->data.pv.f2.fuzzing_range; + dof->data.debug.f2.ratio = dof->data.pv.f2.ratio; use_dof_f2 = true; } else - dof_data->debug.flags &= ~DOF_DEBUG_ENABLE_DOF; + dof->data.debug.flags &= ~DOF_DEBUG_ENABLE_DOF; } void post_process_dof_init_fbo(post_process_dof* dof, int32_t width, int32_t height) { - if (dof->width == width && dof->height == height) + if (!dof || (dof->width == width && dof->height == height)) return; - post_process_dof_free_fbo(dof); - dof->width = width; dof->height = height; int32_t w20 = max(width / 20, 1); @@ -674,19 +704,9 @@ void post_process_dof_init_fbo(post_process_dof* dof, int32_t width, int32_t hei glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, w2, h2); fbo_init(&dof->fbo[3], w2, h2, &dof->textures[4], 2, 0); - glGenSamplers(2, dof->samplers); - glSamplerParameteri(dof->samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(dof->samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(dof->samplers[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(dof->samplers[0], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(dof->samplers[1], GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glSamplerParameteri(dof->samplers[1], GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glSamplerParameteri(dof->samplers[1], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(dof->samplers[1], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glGenBuffers(2, dof->ubo); gl_state_bind_uniform_buffer(dof->ubo[0]); - glBufferData(GL_UNIFORM_BUFFER, sizeof(post_process_dof_data), 0, GL_STREAM_DRAW); + glBufferData(GL_UNIFORM_BUFFER, sizeof(post_process_dof_shader_data), 0, GL_STREAM_DRAW); uint8_t data[align_val(sizeof(vec2[49]), sizeof(vec4))]; memset(data, 0, sizeof(data)); @@ -696,17 +716,21 @@ void post_process_dof_init_fbo(post_process_dof* dof, int32_t width, int32_t hei glGenVertexArrays(1, &dof->vao); } -void post_process_dof_free(post_process_dof* dof) { +void post_process_dof_dispose(post_process_dof* dof) { + if (!dof) + return; + post_process_dof_free_fbo(dof); for (int32_t i = 0; i < 9; i++) { glDeleteProgram(dof->program[i]); dof->program[i] = 0; } + free(dof); } static void post_process_apply_dof_f2(post_process_dof* dof, render_texture* rt, - GLuint color_texture, GLuint depth_texture, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, float_t min_dist_to_focus, float_t max_dist_to_focus, float_t fov, float_t dist_to_focus, float_t focus_range, float_t fuzzing_range, float_t ratio) { gl_state_disable_blend(); @@ -715,10 +739,11 @@ static void post_process_apply_dof_f2(post_process_dof* dof, render_texture* rt, post_process_dof_update_data(dof, min_dist_to_focus, max_dist_to_focus, fov, dist_to_focus, 0.0f, 1.0f, focus_range, fuzzing_range, ratio); - post_process_apply_dof_steps_1_2(dof, depth_texture, true); - post_process_apply_dof_step_3(dof, color_texture, depth_texture, true); - post_process_apply_dof_step_4(dof, true); - post_process_apply_dof_step_5(dof, rt, color_texture, depth_texture, true); + gl_state_bind_vertex_array(dof->vao); + post_process_apply_dof_steps_1_2(dof, samplers, depth_texture, true); + post_process_apply_dof_step_3(dof, samplers, color_texture, depth_texture, true); + post_process_apply_dof_step_4(dof, samplers, true); + post_process_apply_dof_step_5(dof, rt, samplers, color_texture, depth_texture, true); gl_state_use_program(0); for (int32_t i = 0; i < 8; i++) { @@ -729,7 +754,7 @@ static void post_process_apply_dof_f2(post_process_dof* dof, render_texture* rt, } static void post_process_apply_dof_physical(post_process_dof* dof, render_texture* rt, - GLuint color_texture, GLuint depth_texture, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, float_t min_dist_to_focus, float_t max_dist_to_focus, float_t dist_to_focus, float_t focal_length, float_t fov, float_t f_number) { gl_state_disable_blend(); @@ -738,10 +763,11 @@ static void post_process_apply_dof_physical(post_process_dof* dof, render_textur post_process_dof_update_data(dof, min_dist_to_focus, max_dist_to_focus, fov, dist_to_focus, focal_length, f_number, 0.0f, 0.1f, 0.0f); - post_process_apply_dof_steps_1_2(dof, depth_texture, false); - post_process_apply_dof_step_3(dof, color_texture, depth_texture, false); - post_process_apply_dof_step_4(dof, false); - post_process_apply_dof_step_5(dof, rt, color_texture, depth_texture, false); + gl_state_bind_vertex_array(dof->vao); + post_process_apply_dof_steps_1_2(dof, samplers, depth_texture, false); + post_process_apply_dof_step_3(dof, samplers, color_texture, depth_texture, false); + post_process_apply_dof_step_4(dof, samplers, false); + post_process_apply_dof_step_5(dof, rt, samplers, color_texture, depth_texture, false); gl_state_use_program(0); for (int32_t i = 0; i < 8; i++) { @@ -752,7 +778,7 @@ static void post_process_apply_dof_physical(post_process_dof* dof, render_textur } static void post_process_apply_dof_steps_1_2(post_process_dof* dof, - GLuint depth_texture, bool f2) { + GLuint* samplers, GLuint depth_texture, bool f2) { gl_state_bind_framebuffer(dof->fbo[0].fbo); glViewport(0, 0, dof->fbo[0].width, dof->fbo[0].height); if (f2) @@ -761,21 +787,19 @@ static void post_process_apply_dof_steps_1_2(post_process_dof* dof, gl_state_use_program(dof->program[1]); gl_state_bind_uniform_buffer_base(0, dof->ubo[0]); gl_state_active_bind_texture_2d(0, depth_texture); - gl_state_bind_sampler(0, dof->samplers[1]); - gl_state_bind_vertex_array(dof->vao); + gl_state_bind_sampler(0, samplers[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); gl_state_bind_framebuffer(dof->fbo[1].fbo); glViewport(0, 0, dof->fbo[1].width, dof->fbo[1].height); gl_state_use_program(dof->program[0]); gl_state_active_bind_texture_2d(0, dof->textures[0]); - gl_state_bind_sampler(0, dof->samplers[1]); - gl_state_bind_vertex_array(dof->vao); + gl_state_bind_sampler(0, samplers[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } static void post_process_apply_dof_step_3(post_process_dof* dof, - GLuint color_texture, GLuint depth_texture, bool f2) { + GLuint* samplers, GLuint color_texture, GLuint depth_texture, bool f2) { gl_state_bind_framebuffer(dof->fbo[2].fbo); glViewport(0, 0, dof->fbo[2].width, dof->fbo[2].height); if (f2) @@ -784,16 +808,15 @@ static void post_process_apply_dof_step_3(post_process_dof* dof, gl_state_use_program(dof->program[2]); gl_state_bind_uniform_buffer_base(0, dof->ubo[0]); gl_state_active_bind_texture_2d(0, depth_texture); - gl_state_bind_sampler(0, dof->samplers[1]); + gl_state_bind_sampler(0, samplers[1]); gl_state_active_bind_texture_2d(1, color_texture); - gl_state_bind_sampler(1, dof->samplers[0]); + gl_state_bind_sampler(1, samplers[0]); gl_state_active_bind_texture_2d(2, dof->textures[1]); - gl_state_bind_sampler(2, dof->samplers[1]); - gl_state_bind_vertex_array(dof->vao); + gl_state_bind_sampler(2, samplers[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } -static void post_process_apply_dof_step_4(post_process_dof* dof, bool f2) { +static void post_process_apply_dof_step_4(post_process_dof* dof, GLuint* samplers, bool f2) { gl_state_bind_framebuffer(dof->fbo[3].fbo); glViewport(0, 0, dof->fbo[3].width, dof->fbo[3].height); if (f2) @@ -803,17 +826,16 @@ static void post_process_apply_dof_step_4(post_process_dof* dof, bool f2) { gl_state_bind_uniform_buffer_base(0, dof->ubo[0]); gl_state_bind_uniform_buffer_base(1, dof->ubo[1]); gl_state_active_bind_texture_2d(0, dof->textures[3]); - gl_state_bind_sampler(0, dof->samplers[1]); + gl_state_bind_sampler(0, samplers[1]); gl_state_active_bind_texture_2d(1, dof->textures[2]); - gl_state_bind_sampler(1, dof->samplers[1]); + gl_state_bind_sampler(1, samplers[1]); gl_state_active_bind_texture_2d(2, dof->textures[1]); - gl_state_bind_sampler(2, dof->samplers[1]); - gl_state_bind_vertex_array(dof->vao); + gl_state_bind_sampler(2, samplers[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } -static void post_process_apply_dof_step_5(post_process_dof* dof, - render_texture* rt, GLuint color_texture, GLuint depth_texture, bool f2) { +static void post_process_apply_dof_step_5(post_process_dof* dof, render_texture* rt, + GLuint* samplers, GLuint color_texture, GLuint depth_texture, bool f2) { render_texture_bind(rt, 0); glViewport(0, 0, dof->width, dof->height); if (f2) @@ -823,16 +845,15 @@ static void post_process_apply_dof_step_5(post_process_dof* dof, gl_state_bind_uniform_buffer_base(0, dof->ubo[0]); gl_state_bind_uniform_buffer_base(1, dof->ubo[1]); gl_state_active_bind_texture_2d(0, dof->textures[4]); - gl_state_bind_sampler(0, dof->samplers[1]); + gl_state_bind_sampler(0, samplers[1]); gl_state_active_bind_texture_2d(1, dof->textures[5]); - gl_state_bind_sampler(1, dof->samplers[1]); + gl_state_bind_sampler(1, samplers[1]); gl_state_active_bind_texture_2d(2, dof->textures[1]); - gl_state_bind_sampler(2, dof->samplers[1]); + gl_state_bind_sampler(2, samplers[1]); gl_state_active_bind_texture_2d(3, color_texture); - gl_state_bind_sampler(3, dof->samplers[1]); + gl_state_bind_sampler(3, samplers[1]); gl_state_active_bind_texture_2d(4, depth_texture); - gl_state_bind_sampler(4, dof->samplers[1]); - gl_state_bind_vertex_array(dof->vao); + gl_state_bind_sampler(4, samplers[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } @@ -900,11 +921,6 @@ static void post_process_dof_free_fbo(post_process_dof* dof) { dof->ubo[0] = 0; } - if (dof->samplers[0]) { - glDeleteSamplers(2, dof->samplers); - dof->samplers[0] = 0; - } - if (dof->textures[0]) { glDeleteTextures(6, dof->textures); dof->textures[0] = 0; @@ -1008,7 +1024,7 @@ static void post_process_dof_update_data(post_process_dof* dof, float_t min_dist fl = dist + 0.1f; fl *= fl * (1.0f / ((dist - fl) * f_number)); - post_process_dof_data data; + post_process_dof_shader_data data; data.g_depth_params.x = (min_dist - max_dist) / (min_dist * max_dist); data.g_depth_params.y = 1.0f / min_dist; data.g_depth_params.z = -dist * data.g_depth_params.x * fl; @@ -1023,5 +1039,34 @@ static void post_process_dof_update_data(post_process_dof* dof, float_t min_dist data.g_depth_params2.w = ratio * 8.0f; gl_state_bind_uniform_buffer(dof->ubo[0]); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(post_process_dof_data), &data); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(post_process_dof_shader_data), &data); +} + +void post_process_dof_initialize_data(post_process_dof* dof, dof_debug* debug, dof_pv* pv) { + post_process_dof_set_dof_debug(dof, debug); + post_process_dof_set_dof_pv(dof, pv); +} + +inline void post_process_dof_get_dof_debug(post_process_dof* dof, dof_debug* debug) { + if (debug) + *debug = dof->data.debug; +} + +inline void post_process_dof_set_dof_debug(post_process_dof* dof, dof_debug* debug) { + if (debug) + dof->data.debug = *debug; + else + dof->data.debug = dof_debug_default; +} + +inline void post_process_dof_get_dof_pv(post_process_dof* dof, dof_pv* pv) { + if (pv) + *pv = dof->data.pv; +} + +inline void post_process_dof_set_dof_pv(post_process_dof* dof, dof_pv* pv) { + if (pv) + dof->data.pv = *pv; + else + dof->data.pv = dof_pv_default; } diff --git a/src/CRE/post_process/dof.h b/src/CRE/post_process/dof.h index f26570f5..7808bcf9 100644 --- a/src/CRE/post_process/dof.h +++ b/src/CRE/post_process/dof.h @@ -7,29 +7,63 @@ #include "../../KKdLib/default.h" #include "../../KKdLib/vec.h" -#include "../shared.h" -#include "../dof.h" +#include "../camera.h" #include "../fbo.h" #include "../render_texture.h" +#include "../shared.h" + +typedef enum dof_debug_flags { + DOF_DEBUG_USE_UI_PARAMS = 0x1, + DOF_DEBUG_ENABLE_DOF = 0x2, + DOF_DEBUG_ENABLE_PHYS_DOF = 0x4, + DOF_DEBUG_AUTO_FOCUS = 0x8, +} dof_debug_flags; + +typedef struct dof_f2 { + float_t distance_to_focus; + float_t focus_range; + float_t fuzzing_range; + float_t ratio; +} dof_f2; + +typedef struct dof_debug { + dof_debug_flags flags; + float_t distance_to_focus; + float_t focal_length; + float_t f_number; + dof_f2 f2; +} dof_debug; + +typedef struct dof_pv { + bool enable; + dof_f2 f2; +} dof_pv; + +typedef struct post_process_dof_data { + dof_debug debug; + dof_pv pv; +} post_process_dof_data; typedef struct post_process_dof { + post_process_dof_data data; int32_t width; int32_t height; GLuint textures[6]; fbo_struct fbo[4]; - GLuint samplers[2]; GLuint vao; GLuint program[9]; GLuint ubo[2]; } post_process_dof; -typedef struct post_process_dof_data { - vec4 g_depth_params; - vec4 g_spread_scale; - vec4 g_depth_params2; -} post_process_dof_data; +extern post_process_dof* post_process_dof_init(); +extern void post_process_apply_dof(post_process_dof* dof, + render_texture* rt, GLuint* samplers, camera* cam); +extern void post_process_dof_init_fbo(post_process_dof* dof, + int32_t width, int32_t height); +extern void post_process_dof_dispose(post_process_dof* dof); -extern void post_process_dof_init(post_process_dof* dof); -extern void post_process_apply_dof(post_process_dof* dof, render_texture* rt, dof_struct* dof_data); -extern void post_process_dof_init_fbo(post_process_dof* dof, int32_t width, int32_t height); -extern void post_process_dof_free(post_process_dof* dof); +extern void post_process_dof_initialize_data(post_process_dof* dof, dof_debug* debug, dof_pv* pv); +extern void post_process_dof_get_dof_debug(post_process_dof* dof, dof_debug* debug); +extern void post_process_dof_set_dof_debug(post_process_dof* dof, dof_debug* debug); +extern void post_process_dof_get_dof_pv(post_process_dof* dof, dof_pv* pv); +extern void post_process_dof_set_dof_pv(post_process_dof* dof, dof_pv* pv); diff --git a/src/CRE/post_process/exposure.c b/src/CRE/post_process/exposure.c new file mode 100644 index 00000000..4f3c48b2 --- /dev/null +++ b/src/CRE/post_process/exposure.c @@ -0,0 +1,67 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "exposure.h" +#include "../fbo.h" +#include "../gl_state.h" +#include "../post_process.h" +#include "../shader_ft.h" + +static void post_process_exposure_free_fbo(post_process_exposure* exp); + +post_process_exposure* post_process_exposure_init() { + post_process_exposure* exp = force_malloc(sizeof(post_process_exposure)); + return exp; +} + +void post_process_get_exposure(post_process_exposure* exp, GLuint in_tex_0, GLuint in_tex_1) { + if (!exp) + return; + + uniform_value[U_EXPOSURE] = 1; + render_texture_shader_set(&shaders_ft, SHADER_FT_EXPOSURE); + + glViewport(exp->exposure_history_counter, 0, 1, 1); // 14 + render_texture_bind(&exp->exposure_history, 0); + gl_state_active_bind_texture_2d(0, in_tex_0); + gl_state_active_bind_texture_2d(1, in_tex_1); + render_texture_draw_params(&shaders_ft, 1, 1, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + uniform_value[U_EXPOSURE] = 2; + render_texture_shader_set(&shaders_ft, SHADER_FT_EXPOSURE); + + glViewport(0, 0, 1, 1); + render_texture_bind(&exp->exposure, 0); + gl_state_active_bind_texture_2d(0, exp->exposure_history.color_texture->texture); + render_texture_draw_params(&shaders_ft, 1, 1, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + + exp->exposure_history_counter++; + exp->exposure_history_counter %= 32; +} + +void post_process_exposure_init_fbo(post_process_exposure* exp) { + if (!exp) + return; + + exp->exposure_history_counter = 0; + + if (!exp->exposure_history.color_texture) + render_texture_init(&exp->exposure_history, 32, 1, 0, GL_R32F, 0); + if (!exp->exposure.color_texture) + render_texture_init(&exp->exposure, 1, 1, 0, GL_R32F, 0); +} + +void post_process_exposure_dispose(post_process_exposure* exp) { + if (!exp) + return; + + post_process_exposure_free_fbo(exp); + free(exp); +} + +static void post_process_exposure_free_fbo(post_process_exposure* exp) { + render_texture_free(&exp->exposure_history); + render_texture_free(&exp->exposure); +} diff --git a/src/CRE/post_process/exposure.h b/src/CRE/post_process/exposure.h new file mode 100644 index 00000000..1fec9943 --- /dev/null +++ b/src/CRE/post_process/exposure.h @@ -0,0 +1,22 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/vec.h" +#include "../shared.h" +#include "../render_texture.h" + +typedef struct post_process_exposure { + render_texture exposure_history; + render_texture exposure; + int32_t exposure_history_counter; +} post_process_exposure; + +extern post_process_exposure* post_process_exposure_init(); +extern void post_process_get_exposure(post_process_exposure* exp, GLuint in_tex_0, GLuint in_tex_1); +extern void post_process_exposure_init_fbo(post_process_exposure* exp); +extern void post_process_exposure_dispose(post_process_exposure* exp); diff --git a/src/CRE/post_process/tone_map.c b/src/CRE/post_process/tone_map.c new file mode 100644 index 00000000..f2427704 --- /dev/null +++ b/src/CRE/post_process/tone_map.c @@ -0,0 +1,435 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "tone_map.h" +#include "../fbo.h" +#include "../gl_state.h" +#include "../post_process.h" +#include "../shader_ft.h" + +static void post_process_tone_map_free_fbo(post_process_tone_map* tm); +static void post_process_tone_map_calculate_data(post_process_tone_map* tm); +static void post_process_tone_map_calculate_tex(post_process_tone_map* tm); + +post_process_tone_map* post_process_tone_map_init() { + post_process_tone_map* exp = force_malloc(sizeof(post_process_tone_map)); + return exp; +} + +void post_process_apply_tone_map(post_process_tone_map* tm, + render_texture* in_tex, texture* light_proj_tex, texture* back_2d_tex, + render_texture* rt, render_texture* buf_rt, render_texture* contour_rt, + GLuint in_tex_0, GLuint in_tex_1, int32_t npr_param) { + if (!tm) + return; + + if (tm->data.update) { + post_process_tone_map_calculate_data(tm); + tm->data.update = false; + } + + if (tm->data.update_tex) { + post_process_tone_map_calculate_tex(tm); + + glBindTexture(GL_TEXTURE_1D, tm->tone_map); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RG16F, + 16 * POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES, 0, GL_RG, GL_FLOAT, tm->data.tex); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteriv(GL_TEXTURE_1D, GL_TEXTURE_SWIZZLE_RGBA, (GLint[]) { GL_RED, GL_RED, GL_RED, GL_GREEN }); + glBindTexture(GL_TEXTURE_1D, 0); + tm->data.update_tex = false; + } + + mat4 lens_flare_mat; + mat4 lens_shaft_mat; + mat4_scale(1.0f, (float_t)rt->color_texture->height + / (float_t)rt->color_texture->width, 1.0f, &lens_flare_mat); + mat4_scale(1.0f, (float_t)rt->color_texture->height + / (float_t)rt->color_texture->width, 1.0f, &lens_shaft_mat); + + uniform_value[U16] = 0; + uniform_value[U_TONE_MAP] = (int32_t)tm->data.tone_map_method; + uniform_value[U_FLARE] = 0; + uniform_value[U_SCENE_FADE] = tm->data.scene_fade.w > 0.009999999f ? 1 : 0; + uniform_value[U_AET_BACK] = 0; + uniform_value[U_LIGHT_PROJ] = 0; + uniform_value[U_NPR] = 0; + uniform_value[U25] = 0; + + glViewport(0, 0, rt->color_texture->width, rt->color_texture->height); + render_texture_bind(buf_rt, 0); + shader_set(&shaders_ft, SHADER_FT_TONEMAP); + shader_state_matrix_set_texture(&shaders_ft, 4, &lens_flare_mat); + shader_state_matrix_set_texture(&shaders_ft, 5, &lens_shaft_mat); + shader_local_vert_set_ptr(&shaders_ft, 1, &tm->shader_data.p_exposure); + shader_local_frag_set_ptr(&shaders_ft, 1, &tm->shader_data.p_flare_coef); + shader_local_frag_set_ptr(&shaders_ft, 2, &tm->shader_data.p_fade_color); + shader_local_frag_set_ptr(&shaders_ft, 4, &tm->shader_data.p_tone_scale); + shader_local_frag_set_ptr(&shaders_ft, 5, &tm->shader_data.p_tone_offset); + shader_local_frag_set_ptr(&shaders_ft, 6, &tm->shader_data.p_fade_func); + shader_local_frag_set_ptr(&shaders_ft, 7, &tm->shader_data.p_inv_tone); + gl_state_active_bind_texture_2d(0, in_tex->color_texture->texture); + gl_state_active_bind_texture_2d(1, in_tex_0); + gl_state_active_bind_texture_2d(2, 0); + gl_state_active_texture(2); + glBindTexture(GL_TEXTURE_1D, tm->tone_map); + gl_state_active_bind_texture_2d(3, in_tex_1); + if (uniform_value[U_LIGHT_PROJ] && light_proj_tex) + gl_state_active_bind_texture_2d(6, light_proj_tex->texture); + else if (uniform_value[U_AET_BACK] && back_2d_tex) + gl_state_active_bind_texture_2d(6, back_2d_tex->texture); + if (npr_param == 1) { + gl_state_active_bind_texture_2d(16, contour_rt->color_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl_state_active_bind_texture_2d(17, contour_rt->depth_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl_state_active_bind_texture_2d(14, rt->depth_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + render_texture_draw_custom(&shaders_ft); + gl_state_active_texture(2); + glBindTexture(GL_TEXTURE_1D, 0); + uniform_value[U16] = 1; + + fbo_blit(buf_rt->fbos[0], rt->fbos[0], + 0, 0, buf_rt->color_texture->width, buf_rt->color_texture->height, + 0, 0, rt->color_texture->width, rt->color_texture->height, GL_COLOR_BUFFER_BIT, GL_LINEAR); +} + +void post_process_tone_map_init_fbo(post_process_tone_map* tm) { + if (!tm) + return; + + if (!tm->tone_map) + glGenTextures(1, &tm->tone_map); +} + +void post_process_tone_map_dispose(post_process_tone_map* tm) { + if (!tm) + return; + + post_process_tone_map_free_fbo(tm); + free(tm); +} + +static void post_process_tone_map_free_fbo(post_process_tone_map* tm) { + glDeleteTextures(1, &tm->tone_map); +} + +void post_process_tone_map_initialize_data(post_process_tone_map* tm, float_t exposure, bool auto_exposure, + float_t gamma, int32_t saturate_power, float_t saturate_coeff, + vec3* scene_fade, float_t scene_fade_alpha, int32_t scene_fade_blend_func, + vec3* tone_trans_start, vec3* tone_trans_end, tone_map_method tone_map_method) { + post_process_tone_map_initialize_rate(tm, exposure, auto_exposure, 1.0f, + gamma, saturate_power, saturate_coeff, scene_fade, scene_fade_alpha, scene_fade_blend_func, + tone_trans_start, tone_trans_end, tone_map_method); +} + +void post_process_tone_map_initialize_rate(post_process_tone_map* tm, float_t exposure, bool auto_exposure, + float_t gamma, float_t gamma_rate, int32_t saturate_power, float_t saturate_coeff, + vec3* scene_fade, float_t scene_fade_alpha, int32_t scene_fade_blend_func, + vec3* tone_trans_start, vec3* tone_trans_end, tone_map_method tone_map_method) { + tm->data.exposure = clamp(exposure, 0.0f, 4.0f); + tm->data.auto_exposure = auto_exposure; + tm->data.gamma = clamp(gamma, 0.2f, 2.2f); + tm->data.gamma_rate = clamp(gamma_rate, 0.5f, 2.0f); + tm->data.saturate_power = clamp(saturate_power, 1, 6); + tm->data.saturate_coeff = clamp(saturate_coeff, 0.0f, 1.0f); + tm->data.scene_fade.x = clamp(scene_fade->x, 0.0f, 1.0f); + tm->data.scene_fade.y = clamp(scene_fade->y, 0.0f, 1.0f); + tm->data.scene_fade.z = clamp(scene_fade->z, 0.0f, 1.0f); + tm->data.scene_fade.w = clamp(scene_fade_alpha, 0.0f, 1.0f); + tm->data.scene_fade_blend_func = clamp(scene_fade_blend_func, 0, 2); + tm->data.tone_trans_start.x = clamp(tone_trans_start->x, 0.0f, 1.0f); + tm->data.tone_trans_start.y = clamp(tone_trans_start->y, 0.0f, 1.0f); + tm->data.tone_trans_start.z = clamp(tone_trans_start->z, 0.0f, 1.0f); + tm->data.tone_trans_end.x = clamp(tone_trans_end->x, 0.0f, 1.0f); + tm->data.tone_trans_end.y = clamp(tone_trans_end->y, 0.0f, 1.0f); + tm->data.tone_trans_end.z = clamp(tone_trans_end->z, 0.0f, 1.0f); + tm->data.tone_map_method = clamp(tone_map_method, TONE_MAP_YCC_EXPONENT, TONE_MAP_RGB_LINEAR2); + tm->data.update_tex = false; + tm->data.update = true; + tm->data.update_tex = true; +} + +inline float_t post_process_tone_map_get_exposure(post_process_tone_map* tm) { + return tm->data.exposure; +} + +inline void post_process_tone_map_set_exposure(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.0f, 4.0f); + if (value != tm->data.exposure) { + tm->data.exposure = value; + tm->data.update = true; + tm->data.update_tex = true; + } +} + +inline bool post_process_tone_map_get_auto_exposure(post_process_tone_map* tm) { + return tm->data.auto_exposure; +} + +inline void post_process_tone_map_set_auto_exposure(post_process_tone_map* tm, bool value) { + if (value != tm->data.auto_exposure) { + tm->data.auto_exposure = value; + tm->data.update = true; + tm->data.update_tex = true; + } +} + +inline float_t post_process_tone_map_get_gamma(post_process_tone_map* tm) { + return tm->data.gamma; +} + +inline void post_process_tone_map_set_gamma(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.2f, 2.2f); + if (value != tm->data.gamma) { + tm->data.gamma = value; + tm->data.update = true; + tm->data.update_tex = true; + } +} + +inline float_t post_process_tone_map_get_gamma_rate(post_process_tone_map* tm) { + return tm->data.gamma_rate; +} + +inline void post_process_tone_map_set_gamma_rate(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.5f, 2.0f); + if (value != tm->data.gamma_rate) { + tm->data.gamma_rate = value; + tm->data.update_tex = true; + } +} + +inline int32_t post_process_tone_map_get_saturate_power(post_process_tone_map* tm) { + return tm->data.saturate_power; +} + +inline void post_process_tone_map_set_saturate_power(post_process_tone_map* tm, int32_t value) { + value = clamp(value, 1, 6); + if (value != tm->data.saturate_power) { + tm->data.saturate_power = value; + tm->data.update_tex = true; + } +} + +inline float_t post_process_tone_map_get_saturate_coeff(post_process_tone_map* tm) { + return tm->data.saturate_coeff; +} + +inline void post_process_tone_map_set_saturate_coeff(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.0f, 1.0f); + if (value != tm->data.saturate_coeff) { + tm->data.saturate_coeff = value; + tm->data.update_tex = true; + } +} + +inline void post_process_tone_map_get_scene_fade(post_process_tone_map* tm, vec4* value) { + *value = tm->data.scene_fade; +} + +inline void post_process_tone_map_set_scene_fade(post_process_tone_map* tm, vec4* value) { + vec4 temp; + temp.x = clamp(value->x, 0.0f, 1.0f); + temp.y = clamp(value->y, 0.0f, 1.0f); + temp.z = clamp(value->z, 0.0f, 1.0f); + temp.w = clamp(value->w, 0.0f, 1.0f); + if (temp.x != tm->data.scene_fade.x + || temp.y != tm->data.scene_fade.y + || temp.z != tm->data.scene_fade.z + || temp.w != tm->data.scene_fade.w) { + tm->data.scene_fade = temp; + tm->data.update = true; + } +} + +inline void post_process_tone_map_get_scene_fade_color(post_process_tone_map* tm, vec3* value) { + *value = *(vec3*)&tm->data.scene_fade; +} + +inline void post_process_tone_map_set_scene_fade_color(post_process_tone_map* tm, vec3* value) { + vec3 temp; + temp.x = clamp(value->x, 0.0f, 1.0f); + temp.y = clamp(value->y, 0.0f, 1.0f); + temp.z = clamp(value->z, 0.0f, 1.0f); + if (temp.x != tm->data.scene_fade.x + || temp.y != tm->data.scene_fade.y + || temp.z != tm->data.scene_fade.z) { + *(vec3*)&tm->data.scene_fade = temp; + tm->data.update = true; + } +} + +inline float_t post_process_tone_map_get_scene_fade_alpha(post_process_tone_map* tm) { + return tm->data.scene_fade.w; +} + +inline void post_process_tone_map_set_scene_fade_alpha(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.0f, 1.0f); + if (value != tm->data.scene_fade.w) { + tm->data.scene_fade.w = value; + tm->data.update = true; + } +} + +inline int32_t post_process_tone_map_get_scene_fade_blend_func(post_process_tone_map* tm) { + return tm->data.scene_fade_blend_func; +} + +inline void post_process_tone_map_set_scene_fade_blend_func(post_process_tone_map* tm, int32_t value) { + value = clamp(value, 0, 2); + if (value != tm->data.scene_fade_blend_func) { + tm->data.scene_fade_blend_func = value; + tm->data.update = true; + } +} + +inline void post_process_tone_map_get_tone_trans_start(post_process_tone_map* tm, vec3* value) { + *value = tm->data.tone_trans_start; +} + +inline void post_process_tone_map_set_tone_trans_start(post_process_tone_map* tm, vec3* value) { + vec3 temp; + temp.x = clamp(value->x, 0.0f, 1.0f); + temp.y = clamp(value->y, 0.0f, 1.0f); + temp.z = clamp(value->z, 0.0f, 1.0f); + if (temp.x != tm->data.tone_trans_start.x + || temp.y != tm->data.tone_trans_start.y + || temp.z != tm->data.tone_trans_start.z) { + tm->data.tone_trans_start = temp; + tm->data.update = true; + } +} + +inline void post_process_tone_map_get_tone_trans_end(post_process_tone_map* tm, vec3* value) { + *value = tm->data.tone_trans_end; +} + +inline void post_process_tone_map_set_tone_trans_end(post_process_tone_map* tm, vec3* value) { + vec3 temp; + temp.x = clamp(value->x, 0.009999999776f, 1.0f); + temp.y = clamp(value->y, 0.009999999776f, 1.0f); + temp.z = clamp(value->z, 0.009999999776f, 1.0f); + if (temp.x != tm->data.tone_trans_end.x + || temp.y != tm->data.tone_trans_end.y + || temp.z != tm->data.tone_trans_end.z) { + tm->data.tone_trans_end = temp; + tm->data.update = true; + } +} + +inline tone_map_method post_process_tone_map_get_tone_map_method(post_process_tone_map* tm) { + return tm->data.tone_map_method; +} + +inline void post_process_tone_map_set_tone_map_method(post_process_tone_map* tm, tone_map_method value) { + value = clamp(value, TONE_MAP_YCC_EXPONENT, TONE_MAP_RGB_LINEAR2); + if (value != tm->data.tone_map_method) { + tm->data.tone_map_method = value; + tm->data.update = true; + } +} + +inline float_t post_process_tone_map_get_lens_flare(post_process_tone_map* tm) { + return tm->data.lens_flare; +} + +inline void post_process_tone_map_set_lens_flare(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.0f, 1.0f); + if (value != tm->data.lens_flare) { + tm->data.lens_flare = value; + tm->data.update = true; + } +} + +inline float_t post_process_tone_map_get_lens_shaft(post_process_tone_map* tm) { + return tm->data.lens_shaft; +} + +inline void post_process_tone_map_set_lens_shaft(post_process_tone_map* tm, float_t value) { + value = clamp(value, 0.0f, 1.0f); + if (value != tm->data.lens_shaft) { + tm->data.lens_shaft = value; + tm->data.update = true; + } +} + +inline float_t post_process_tone_map_get_lens_ghost(post_process_tone_map* tm) { + return tm->data.lens_ghost; +} + +inline void post_process_tone_map_set_lens_ghost(post_process_tone_map* tm, float_t value) { + tm->data.lens_ghost = clamp(value, 0.0f, 1.0f); +} + +static void post_process_tone_map_calculate_data(post_process_tone_map* tm) { + vec3 tone_trans, tone_trans_scale, tone_trans_offset; + vec3_sub(tm->data.tone_trans_end, tm->data.tone_trans_start, tone_trans); + vec3_rcp(tone_trans, tone_trans_scale); + vec3_mult(tone_trans_scale, tm->data.tone_trans_start, tone_trans_offset); + vec3_negate(tone_trans_offset, tone_trans_offset); + + post_process_tone_map_shader_data* v = &tm->shader_data; + v->p_exposure.x = tm->data.exposure; + v->p_exposure.y = 0.0625f; + v->p_exposure.z = tm->data.exposure * 0.5f; + v->p_exposure.w = tm->data.auto_exposure ? 1.0f : 0.0f; + v->p_flare_coef.x = (tm->data.lens_flare * 2.0f) + * (tm->data.lens_flare_appear_power + tm->data.lens_flare_power); + v->p_flare_coef.y = tm->data.lens_shaft * 2.0f; + v->p_flare_coef.z = 0.0f; + v->p_flare_coef.w = 0.0f; + v->p_fade_color = tm->data.scene_fade; + if (tm->data.scene_fade_blend_func == 1 || tm->data.scene_fade_blend_func == 2) + vec3_mult_scalar(*(vec3*)&v->p_fade_color, v->p_fade_color.w, *(vec3*)&v->p_fade_color); + v->p_tone_scale.x = tone_trans_scale.x; + v->p_tone_scale.y = tone_trans_scale.y; + v->p_tone_scale.z = tone_trans_scale.z; + v->p_tone_offset.x = tone_trans_offset.x; + v->p_tone_offset.y = tone_trans_offset.y; + v->p_tone_offset.z = tone_trans_offset.z; + v->p_fade_func.x = (float_t)tm->data.scene_fade_blend_func; + v->p_inv_tone.x = tm->data.gamma > 0.0f ? 2.0f / (tm->data.gamma * 3.0f) : 0.0f; +} + +static void post_process_tone_map_calculate_tex(post_process_tone_map* tm) { + const float_t post_process_tone_map__scale = (float_t)(1.0 / (double_t)POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES); + const int32_t post_process_tone_map__size = 16 * POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES; + + int32_t i, j; + int32_t saturate_power; + float_t saturate_coeff; + + vec2* tex = tm->data.tex; + float_t gamma_power, gamma, saturation; + gamma_power = tm->data.gamma * tm->data.gamma_rate * 1.5f; + saturate_power = tm->data.saturate_power; + saturate_coeff = tm->data.saturate_coeff; + + tex[0].x = 0.0f; + tex[0].y = 0.0f; + for (i = 1; i < post_process_tone_map__size; i++) { + gamma = powf(1.0f - expf(-i * post_process_tone_map__scale), gamma_power); + saturation = gamma * 2.0f - 1.0f; + for (j = 0; j < saturate_power; j++) { + saturation *= saturation; + saturation *= saturation; + saturation *= saturation; + saturation *= saturation; + } + + tex[i].x = gamma; + tex[i].y = gamma * saturate_coeff + * ((float_t)POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES / (float_t)i) * (1.0f - saturation); + } +} diff --git a/src/CRE/post_process/tone_map.h b/src/CRE/post_process/tone_map.h new file mode 100644 index 00000000..d0ffb573 --- /dev/null +++ b/src/CRE/post_process/tone_map.h @@ -0,0 +1,101 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.h" +#include "../../KKdLib/light_param/glow.h" +#include "../../KKdLib/vec.h" +#include "../shared.h" +#include "../render_texture.h" + +#define POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES 32 + +typedef struct post_process_tone_map_shader_data { + vec4 p_exposure; + vec4 p_flare_coef; + vec4 p_fade_color; + vec4 p_tone_scale; + vec4 p_tone_offset; + vec4 p_fade_func; + vec4 p_inv_tone; +} post_process_tone_map_shader_data; + +typedef struct post_process_tone_map_data { + vec2 tex[16 * POST_PROCESS_TONE_MAP_SAT_GAMMA_SAMPLES]; + float_t exposure; + bool auto_exposure; + float_t gamma; + float_t gamma_rate; + int32_t saturate_power; + float_t saturate_coeff; + vec4 scene_fade; + int32_t scene_fade_blend_func; + vec3 tone_trans_start; + vec3 tone_trans_end; + tone_map_method tone_map_method; + float_t lens_flare; + float_t lens_shaft; + float_t lens_ghost; + float_t lens_flare_power; + float_t lens_flare_appear_power; + bool update; + bool update_tex; +} post_process_tone_map_data; + +typedef struct post_process_tone_map { + post_process_tone_map_data data; + post_process_tone_map_shader_data shader_data; + GLuint tone_map; +} post_process_tone_map; + +extern post_process_tone_map* post_process_tone_map_init(); +extern void post_process_apply_tone_map(post_process_tone_map* tm, + render_texture* in_tex, texture* light_proj_tex, texture* back_2d_tex, + render_texture* rt, render_texture* buf_rt, render_texture* contour_rt, + GLuint in_tex_0, GLuint in_tex_1, int32_t npr_param); +extern void post_process_tone_map_init_fbo(post_process_tone_map* tm); +extern void post_process_tone_map_dispose(post_process_tone_map* tm); + +extern void post_process_tone_map_initialize_data(post_process_tone_map* tm, float_t exposure, bool auto_exposure, + float_t gamma, int32_t saturate_power, float_t saturate_coeff, + vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, + vec3* tone_trans_start, vec3* tone_trans_end, tone_map_method tone_map_method); +extern void post_process_tone_map_initialize_rate(post_process_tone_map* tm, float_t exposure, bool auto_exposure, + float_t gamma, float_t gamma_rate, int32_t saturate_power, float_t saturate_coeff, + vec3* scene_fade_color, float_t scene_fade_alpha, int32_t scene_fade_blend_func, + vec3* tone_trans_start, vec3* tone_trans_end, tone_map_method tone_map_method); +extern float_t post_process_tone_map_get_exposure(post_process_tone_map* tm); +extern void post_process_tone_map_set_exposure(post_process_tone_map* tm, float_t value); +extern bool post_process_tone_map_get_auto_exposure(post_process_tone_map* tm); +extern void post_process_tone_map_set_auto_exposure(post_process_tone_map* tm, bool value); +extern float_t post_process_tone_map_get_gamma(post_process_tone_map* tm); +extern void post_process_tone_map_set_gamma(post_process_tone_map* tm, float_t value); +extern float_t post_process_tone_map_get_gamma_rate(post_process_tone_map* tm); +extern void post_process_tone_map_set_gamma_rate(post_process_tone_map* tm, float_t value); +extern int32_t post_process_tone_map_get_saturate_power(post_process_tone_map* tm); +extern void post_process_tone_map_set_saturate_power(post_process_tone_map* tm, int32_t value); +extern float_t post_process_tone_map_get_saturate_coeff(post_process_tone_map* tm); +extern void post_process_tone_map_set_saturate_coeff(post_process_tone_map* tm, float_t value); +extern void post_process_tone_map_get_scene_fade(post_process_tone_map* tm, vec4* value); +extern void post_process_tone_map_set_scene_fade(post_process_tone_map* tm, vec4* value); +extern void post_process_tone_map_get_scene_fade_color(post_process_tone_map* tm, vec3* value); +extern void post_process_tone_map_set_scene_fade_color(post_process_tone_map* tm, vec3* value); +extern float_t post_process_tone_map_get_scene_fade_alpha(post_process_tone_map* tm); +extern void post_process_tone_map_set_scene_fade_alpha(post_process_tone_map* tm, float_t value); +extern int32_t post_process_tone_map_get_scene_fade_blend_func(post_process_tone_map* tm); +extern void post_process_tone_map_set_scene_fade_blend_func(post_process_tone_map* tm, int32_t value); +extern void post_process_tone_map_get_tone_trans_start(post_process_tone_map* tm, vec3* value); +extern void post_process_tone_map_set_tone_trans_start(post_process_tone_map* tm, vec3* value); +extern void post_process_tone_map_get_tone_trans_end(post_process_tone_map* tm, vec3* value); +extern void post_process_tone_map_set_tone_trans_end(post_process_tone_map* tm, vec3* value); +extern tone_map_method post_process_tone_map_get_tone_map_method(post_process_tone_map* tm); +extern void post_process_tone_map_set_tone_map_method(post_process_tone_map* tm, tone_map_method value); +extern float_t post_process_tone_map_get_lens_flare(post_process_tone_map* tm); +extern void post_process_tone_map_set_lens_flare(post_process_tone_map* tm, float_t value); +extern float_t post_process_tone_map_get_lens_shaft(post_process_tone_map* tm); +extern void post_process_tone_map_set_lens_shaft(post_process_tone_map* tm, float_t value); +extern float_t post_process_tone_map_get_lens_ghost(post_process_tone_map* tm); +extern void post_process_tone_map_set_lens_ghost(post_process_tone_map* tm, float_t value); diff --git a/src/CRE/render_context.c b/src/CRE/render_context.c new file mode 100644 index 00000000..93f25a51 --- /dev/null +++ b/src/CRE/render_context.c @@ -0,0 +1,1172 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "render_context.h" +#include "draw_task.h" +#include "shader_ft.h" + +vector_func(texture_pattern_struct) +vector_func(texture_transform_struct) +vector_ptr_func(draw_task) + +static void draw_pass_init(draw_pass* draw_pass); +static void draw_pass_free(draw_pass* draw_pass); +static void draw_state_init(draw_state* draw_state); +static void draw_state_stats_update(draw_state* draw_state); + +static void object_data_init(object_data* data); +static void object_data_reset(object_data* data); +static void object_data_free(object_data* data); + +static void render_context_light_param_data_ibl_set_diffuse(light_param_ibl_diffuse* diffuse, int32_t level); +static void render_context_light_param_data_ibl_set_specular(light_param_ibl_specular* specular); + +static shadow* shadow_init(); +static void shadow_update_inner(shadow* shad, render_context* rctx); +static int32_t shadow_init_data(shadow* shad); +static void shadow_free(shadow* shad); + +static void sss_data_init(sss_data_struct* sss); +static void sss_data_free(sss_data_struct* sss); + +const texture_pattern_struct texture_pattern_struct_null = { -1, -1 }; + +static const GLfloat depth_clear = 1.0f; + +light_proj* light_proj_init(int32_t width, int32_t height) { + light_proj* litproj = force_malloc(sizeof(light_proj)); + render_texture_init(&litproj->shadow_texture[0], + 2048, 512, 0, GL_R32F, GL_DEPTH24_STENCIL8); + render_texture_init(&litproj->shadow_texture[1], + 2048, 512, 0, GL_R32F, GL_ZERO); + render_texture_init(&litproj->draw_texture, + width, height, 0, GL_RGBA8, GL_DEPTH24_STENCIL8); + return litproj; +} + +void light_proj_get_proj_mat(vec3* view_point, vec3* interest, float_t fov, mat4* mat) { + if (mat) { + mat4 temp; + mat4_translate(0.5f, 0.5f, 0.5f, &temp); + mat4_scale_rot(&temp, 0.5f, 0.5f, 0.5f, &temp); + + mat4 proj; + mat4_persp(fov, 4.0, 0.1000000014901161, 10.0, &proj); + mat4_mult(&proj, &temp, &proj); + + mat4 view; + mat4_look_at(view_point, interest, &((vec3) { 0.0f, 1.0f, 0.0f }), &view); + mat4_mult(&view, &proj, mat); + } + else { + mat4 proj; + mat4_persp(fov, 4.0, 0.1000000014901161, 10.0, &proj); + shader_state_matrix_set_projection(&shaders_ft, &proj, false); + + mat4 view; + mat4_look_at(view_point, interest, &((vec3) { 0.0f, 1.0f, 0.0f }), &view); + shader_state_matrix_set_modelview(&shaders_ft, 0, &view, true); + } +} + +void light_proj_resize(light_proj* litproj, int32_t width, int32_t height) { + if (!litproj) + return; + + render_texture_init(&litproj->draw_texture, + width, height, 0, GL_RGBA8, GL_DEPTH24_STENCIL8); +} + +bool light_proj_set(light_proj* litproj, render_context* rctx) { + if (!litproj) + return 0; + + render_texture_bind(&litproj->shadow_texture[0], 0); + glViewport(0, 0, 2048, 512); + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + glClearBufferfv(GL_COLOR, 0, (float_t*)&vec4_identity); + glClearBufferfv(GL_DEPTH, 0, &depth_clear); + + if (light_proj_set_mat(rctx, false)) { + rctx->draw_state.shader_index = SHADER_FT_SIL; + uniform_value[U0A] = 1; + return true; + } + else { + render_texture_bind(&litproj->draw_texture, 0); + glViewport(0, 0, litproj->draw_texture.color_texture->width, + litproj->draw_texture.color_texture->height); + gl_state_enable_depth_test(); + gl_state_set_depth_mask(GL_TRUE); + glClearBufferfv(GL_COLOR, 0, (float_t*)&vec4_identity); + glClearBufferfv(GL_DEPTH, 0, &depth_clear); + return false; + } +} + +bool light_proj_set_mat(render_context* rctx, bool set_mat) { + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_data* data = &set->lights[LIGHT_PROJECTION]; + if (light_get_type(data) != LIGHT_SPOT) + return false; + + vec3 position; + vec3 spot_direction; + light_get_position(data, &position); + light_get_spot_direction(data, &spot_direction); + + float_t length; + vec3_length_squared(spot_direction, length); + if (length <= 0.000001f) + return false; + + float_t spot_cutoff = light_get_spot_cutoff(data); + float_t fov = atanf(tanf(spot_cutoff * DEG_TO_RAD_FLOAT) * 0.25f) * (RAD_TO_DEG_FLOAT * 2.0f); + + vec3 interest; + vec3_add(position, spot_direction, interest); + if (set_mat) { + mat4 mat; + light_proj_get_proj_mat(&position, &interest, fov, &mat); + shader_env_vert_set_ptr_array(&shaders_ft, 24, 4, (vec4*)&mat); + } + else + light_proj_get_proj_mat(&position, &interest, fov, 0); + return true; +} + +void light_proj_free(light_proj* litproj) { + if (!litproj) + return; + + render_texture_free(&litproj->shadow_texture[0]); + render_texture_free(&litproj->shadow_texture[1]); + render_texture_free(&litproj->draw_texture); + free(litproj); +} + +inline draw_task* object_data_buffer_add_draw_task(object_data_buffer* buffer, draw_task_type type) { + if (!buffer->data) + return 0; + + int32_t size = align_val(sizeof(draw_task_type) + sizeof(mat4u) + sizeof(float_t) * 2, 0x08); + switch (type) { + case DRAW_TASK_TYPE_OBJECT: + size += sizeof(draw_object); + break; + case DRAW_TASK_TYPE_PRIMITIVE: + size += sizeof(draw_primitive); + break; + case DRAW_TASK_TYPE_PREPROCESS: + size += sizeof(draw_task_preprocess); + break; + case DRAW_TASK_TYPE_OBJECT_TRANSLUCENT: + size += sizeof(draw_task_object_translucent); + break; + default: + return 0; + } + + if (buffer->offset + size > buffer->size) + return 0; + + draw_task* task = (draw_task*)((size_t)buffer->data + buffer->offset); + buffer->offset += size; + if (buffer->max_offset < buffer->offset) + buffer->max_offset = buffer->offset; + return task; +} + +inline mat4u* object_data_buffer_add_mat4(object_data_buffer* buffer, int32_t count) { + if (!buffer->data) + return 0; + + int32_t size = sizeof(mat4u) * count; + if (buffer->offset + size > buffer->size) + return 0; + + mat4u* mats = (mat4u*)((size_t)buffer->data + buffer->offset); + buffer->offset += size; + if (buffer->max_offset < buffer->offset) + buffer->max_offset = buffer->offset; + return mats; +} + +inline void object_data_buffer_reset(object_data_buffer* buffer) { + buffer->offset = 0; +} + +inline bool object_data_get_chara_color(object_data* object_data) { + return object_data->chara_color; +} + +inline draw_task_flags object_data_get_draw_task_flags(object_data* object_data) { + return object_data->draw_task_flags; +} + +inline void object_data_get_morph(object_data* object_data, object_info* object, float_t* value) { + *value = object_data->morph.value; + *object = object_data->morph.object; +} + +inline shadow_type_enum object_data_get_shadow_type(object_data* object_data) { + return object_data->shadow_type; +} + +inline void object_data_get_texture_color_coeff(object_data* object_data, vec4* value) { + *value = object_data->texture_color_coeff; +} + +inline void object_data_get_texture_color_offset(object_data* object_data, vec4* value) { + *value = object_data->texture_color_offset; +} + +void object_data_get_texture_pattern(object_data* object_data, + int32_t* count, texture_pattern_struct* value) { + *count = object_data->texture_pattern_count; + + for (int32_t i = 0; i < *count; i++) + value[i] = object_data->texture_pattern_array[i]; +} + +inline void object_data_get_texture_specular_coeff(object_data* object_data, vec4* value) { + *value = object_data->texture_specular_coeff; +} + +inline void object_data_get_texture_specular_offset(object_data* object_data, vec4* value) { + *value = object_data->texture_specular_offset; +} + +void object_data_get_texture_transform(object_data* object_data, + int32_t* count, texture_transform_struct* value) { + *count = object_data->texture_transform_count; + + for (int32_t i = 0; i < *count; i++) + value[i] = object_data->texture_transform_array[i]; +} + +inline float_t object_data_get_wet_param(object_data* object_data) { + return object_data->wet_param; +} + +inline void object_data_set_chara_color(object_data* object_data, bool value) { + object_data->chara_color = value; +} + +inline void object_data_set_draw_task_flags(object_data* object_data, draw_task_flags flags) { + object_data->draw_task_flags = flags; +} + +inline void object_data_set_morph(object_data* object_data, object_info object, float_t value) { + object_data->morph.value = value; + object_data->morph.object = object; +} + +inline void object_data_set_shadow_type(object_data* object_data, shadow_type_enum type) { + if (type == SHADOW_CHARA || type == SHADOW_STAGE) + object_data->shadow_type = type; +} + +inline void object_data_set_texture_color_coeff(object_data* object_data, vec4* value) { + object_data->texture_color_coeff = *value; +} + +inline void object_data_set_texture_color_offset(object_data* object_data, vec4* value) { + object_data->texture_color_offset = *value; +} + +void object_data_set_texture_pattern(object_data* object_data, + int32_t count, texture_pattern_struct* value) { + if (count > TEXTURE_PATTERN_COUNT) + return; + + object_data->texture_pattern_count = count; + + if (count) + for (int32_t i = 0; i < count; i++) + object_data->texture_pattern_array[i] = value[i]; + else + for (int32_t i = 0; i < TEXTURE_PATTERN_COUNT; i++) + object_data->texture_pattern_array[i] = texture_pattern_struct_null; +} + +inline void object_data_set_texture_specular_coeff(object_data* object_data, vec4* value) { + object_data->texture_specular_coeff = *value; +} + +inline void object_data_set_texture_specular_offset(object_data* object_data, vec4* value) { + object_data->texture_specular_offset = *value; +} + +void object_data_set_texture_transform(object_data* object_data, + int32_t count, texture_transform_struct* value) { + if (count > TEXTURE_TRANSFORM_COUNT) + return; + + object_data->texture_transform_count = count; + + if (count) + for (int32_t i = 0; i < count; i++) + object_data->texture_transform_array[i] = value[i]; + else + for (int32_t i = count; i < TEXTURE_TRANSFORM_COUNT; i++) + object_data->texture_transform_array[i] = (texture_transform_struct){ -1, mat4u_identity }; +} + +inline void object_data_set_wet_param(object_data* object_data, float_t value) { + object_data->wet_param = value; +} + +inline render_context* render_context_init() { + render_context* rctx = force_malloc(sizeof(render_context)); + rctx->camera = camera_init(); + draw_pass_init(&rctx->draw_pass); + draw_state_init(&rctx->draw_state); + object_data_init(&rctx->object_data); + glGenVertexArrays(1, &rctx->vao); + glGenTextures(5, rctx->ibl_tex); + + face_init(&rctx->face); + for (fog_id i = FOG_DEPTH; i < FOG_MAX; i++) + fog_init(&rctx->fog_data[i]); + for (light_set_id i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) + light_set_init(&rctx->light_set_data[i]); + rctx->wind = wind_init(); + + post_process_init(&rctx->post_process); + return rctx; +} + +void render_context_light_param_data_light_set(render_context* rctx, light_param_light* light) { + for (light_set_id i = LIGHT_SET_MAIN; i < LIGHT_SET_MAX; i++) { + light_param_light_group* group = &light->group[i]; + light_set* set = &rctx->light_set_data[i]; + + for (light_id j = LIGHT_CHARA; j < LIGHT_MAX; j++) { + light_param_light_data* data = &group->data[j]; + light_data* light = &set->lights[j]; + + if (data->has_type) + light_set_type(light, data->type); + + if (data->has_ambient) { + vec4 ambient; + vec4u_to_vec4(data->ambient, ambient); + light_set_ambient(light, &ambient); + } + + if (data->has_diffuse) { + vec4 diffuse; + vec4u_to_vec4(data->diffuse, diffuse); + light_set_diffuse(light, &diffuse); + } + + if (data->has_specular) { + vec4 specular; + vec4u_to_vec4(data->specular, specular); + light_set_specular(light, &specular); + } + + if (data->has_position) + light_set_position(light, &data->position); + + if (data->has_spot_direction) + light_set_spot_direction(light, &data->spot_direction); + + if (data->has_spot_exponent) + light_set_spot_exponent(light, data->spot_exponent); + + if (data->has_spot_cutoff) + light_set_spot_cutoff(light, data->spot_cutoff); + + if (data->has_attenuation) + light_set_attenuation(light, &data->attenuation); + + light_set_clip_plane(light, data->clip_plane); + + if (data->has_tone_curve) + light_set_tone_curve(light, &data->tone_curve); + } + } +} + +void render_context_light_param_data_fog_set(render_context* rctx, light_param_fog* f) { + for (fog_id i = FOG_DEPTH; i < FOG_MAX; i++) { + light_param_fog_group* group = &f->group[i]; + fog* fog = &rctx->fog_data[i]; + + if (group->has_type) + fog_set_type(fog, group->type); + + if (group->has_density) + fog_set_density(fog, group->density); + + if (group->has_linear) { + fog_set_start(fog, group->linear_start); + fog_set_end(fog, group->linear_end); + } + + if (group->has_color) { + vec4 color; + vec4u_to_vec4(group->color, color); + fog_set_color(fog, &color); + } + } +} + +void render_context_light_param_data_glow_set(render_context* rctx, light_param_glow* glow) { + post_process_struct* pp = &rctx->post_process; + + post_process_blur* blur = pp->blur; + post_process_tone_map* tone_map = pp->tone_map; + + post_process_tone_map_set_auto_exposure(tone_map, true); + post_process_tone_map_set_tone_map_method(tone_map, TONE_MAP_YCC_EXPONENT); + post_process_tone_map_set_saturate_coeff(tone_map, 1.0f); + post_process_tone_map_set_scene_fade(tone_map, (vec4*)&vec4_null); + post_process_tone_map_set_scene_fade_blend_func(tone_map, 0); + post_process_tone_map_set_tone_trans_start(tone_map, (vec3*)&vec3_null); + post_process_tone_map_set_tone_trans_end(tone_map, (vec3*)&vec3_identity); + + if (glow->has_exposure) + post_process_tone_map_set_exposure(tone_map, glow->exposure); + + if (glow->has_gamma) + post_process_tone_map_set_gamma(tone_map, glow->gamma); + + if (glow->has_saturate_power) + post_process_tone_map_set_saturate_power(tone_map, glow->saturate_power); + + if (glow->has_saturate_coef) + post_process_tone_map_set_saturate_coeff(tone_map, glow->saturate_coef); + + if (glow->has_flare) { + post_process_tone_map_set_lens_flare(tone_map, glow->flare.x); + post_process_tone_map_set_lens_shaft(tone_map, glow->flare.x); + post_process_tone_map_set_lens_ghost(tone_map, glow->flare.x); + } + + if (glow->has_sigma) + post_process_blur_set_radius(blur, &glow->sigma); + + if (glow->has_intensity) + post_process_blur_set_intensity(blur, &glow->intensity); + + if (glow->has_auto_exposure) + post_process_tone_map_set_auto_exposure(tone_map, glow->auto_exposure); + + if (glow->has_tone_map_method) + post_process_tone_map_set_tone_map_method(tone_map, glow->tone_map_method); + + if (glow->has_fade_color) { + vec4 fade_color; + vec4u_to_vec4(glow->fade_color, fade_color); + post_process_tone_map_set_scene_fade(tone_map, &fade_color); + post_process_tone_map_set_scene_fade_blend_func(tone_map, glow->fade_color_blend_func); + } + + if (glow->has_tone_transform) { + post_process_tone_map_set_tone_trans_start(tone_map, &glow->tone_transform_start); + post_process_tone_map_set_tone_trans_end(tone_map, &glow->tone_transform_end); + } +} + +void render_context_light_param_data_ibl_set(render_context* rctx, light_param_ibl* ibl) { + if (!ibl->ready) + return; + + for (int32_t i = 0, j = -1; i < 5; i++, j++) { + gl_state_bind_texture_cube_map(rctx->ibl_tex[i]); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + if (i == 0) { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + render_context_light_param_data_ibl_set_diffuse(&ibl->diffuse[0], 0); + render_context_light_param_data_ibl_set_diffuse(&ibl->diffuse[1], 1); + } + else { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, ibl->specular[j].max_level); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_LOD_BIAS, 0.0f); + render_context_light_param_data_ibl_set_specular(&ibl->specular[j]); + } + } + gl_state_bind_texture_cube_map(0); + + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_set_set_irradiance(set, &ibl->diff_coef[1][0], &ibl->diff_coef[1][1], &ibl->diff_coef[1][2]); + + float_t len; + vec3 pos; + + light_data* l = &set->lights[LIGHT_CHARA]; + light_get_position(l, &pos); + vec3_length(pos, len); + if (fabsf(len - 1.0f) < 0.02f) + light_set_position_vec4(l, &ibl->lit_dir[0]); + + light_set_ibl_specular(l, &ibl->lit_col[0]); + light_set_ibl_back(l, &ibl->lit_col[2]); + light_set_ibl_direction(l, &ibl->lit_dir[0]); + + l = &set->lights[LIGHT_STAGE]; + light_get_position(l, &pos); + vec3_length(pos, len); + if (fabsf(len - 1.0f) < 0.02f) + light_set_position_vec4(l, &ibl->lit_dir[1]); + + light_set_ibl_specular(l, &ibl->lit_col[1]); + light_set_ibl_direction(l, &ibl->lit_dir[1]); +} + +void render_context_light_param_data_wind_set(render_context* rctx, light_param_wind* w) { + wind* wind = rctx->wind; + if (w->has_scale) + wind->scale = w->scale; + + if (w->has_cycle) + wind->cycle = w->cycle; + + if (w->has_rot) { + wind->rot_y = w->rot_y; + wind->rot_z = w->rot_z; + } + + if (w->has_bias) + wind->bias = w->bias; + + for (int32_t i = 0; i < 16; i++) + if (w->has_spc[i]) { + wind->spc[i].cos = w->spc[i].cos; + wind->spc[i].sin = w->spc[i].sin; + } +} + +void render_context_light_param_data_face_set(render_context* rctx, light_param_face* face) { + rctx->face.offset = face->offset; + rctx->face.scale = face->scale; + rctx->face.position = face->position; + rctx->face.direction = face->direction; +} + +void render_context_set_light_param(render_context* rctx, light_param_data* light_param) { + if (light_param->light.ready) + render_context_light_param_data_light_set(rctx, &light_param->light); + if (light_param->fog.ready) + render_context_light_param_data_fog_set(rctx, &light_param->fog); + if (light_param->glow.ready) + render_context_light_param_data_glow_set(rctx, &light_param->glow); + if (light_param->ibl.ready) + render_context_light_param_data_ibl_set(rctx, &light_param->ibl); + render_context_light_param_data_wind_set(rctx, &light_param->wind); + if (light_param->face.ready) + render_context_light_param_data_face_set(rctx, &light_param->face); +} + +inline void render_context_update(render_context* rctx) { + wind_update(rctx->wind); + draw_state_stats_update(&rctx->draw_state); + object_data_reset(&rctx->object_data); +} + +inline void render_context_free(render_context* rctx) { + camera_dispose(rctx->camera); + draw_pass_free(&rctx->draw_pass); + object_data_free(&rctx->object_data); + glDeleteVertexArrays(1, &rctx->vao); + glDeleteTextures(5, rctx->ibl_tex); + + wind_free(rctx->wind); + post_process_free(&rctx->post_process); + free(rctx); +} + +extern void shadow_update(shadow* shad, render_context* rctx) { + shadow_update_inner(shad, rctx); +} + +static void draw_pass_init(draw_pass* draw_pass) { + for (draw_pass_type i = DRAW_PASS_SHADOW; i < DRAW_PASS_MAX; i++) + draw_pass->enable[i] = true; + draw_pass->reflect = true; + draw_pass->refract = true; + draw_pass->shadow = true; + draw_pass->opaque_z_sort = true; + draw_pass->alpha_z_sort = true; + for (draw_pass_type i = DRAW_PASS_3D_OPAQUE; i < DRAW_PASS_3D_MAX; i++) + draw_pass->draw_pass_3d[i] = true; + memset(draw_pass->cpu_time, 0, sizeof(draw_pass->cpu_time)); + memset(draw_pass->gpu_time, 0, sizeof(draw_pass->gpu_time)); + time_struct_init(&draw_pass->time); + draw_pass->shadow_ptr = shadow_init(); + if (draw_pass->shadow_ptr) + shadow_init_data(draw_pass->shadow_ptr); + sss_data_init(&draw_pass->sss_data); +} + +static void draw_pass_free(draw_pass* draw_pass) { + render_texture_free(&draw_pass->reflect_texture); + shadow_free(draw_pass->shadow_ptr); + sss_data_free(&draw_pass->sss_data); +} + +static void draw_state_init(draw_state* draw_state) { + memset(draw_state, 0, sizeof(*draw_state)); + draw_state->self_shadow = false; + draw_state->field_45 = false; + draw_state->use_global_material = false; + draw_state->fog_height = false; + draw_state->ex_data_mat = false; + draw_state->shader = true; + draw_state->shader_index = -1; + draw_state->field_50 = -1; + draw_state->bump_depth = 1.0f; + draw_state->intensity = 1.0f; + draw_state->specular_alpha = 1.0f; + draw_state->reflect_uv_scale = 0.1f; + draw_state->refract_uv_scale = 0.1f; + draw_state->field_68 = 0; + draw_state->fresnel = 7.0f; +} + +static void draw_state_stats_update(draw_state* draw_state) { + draw_state->stats_prev = draw_state->stats; + memset(&draw_state->stats, 0, sizeof(draw_state_stats)); +} + +static void object_data_init(object_data* data) { + data->draw_task_flags = 0; + data->shadow_type = 0; + data->field_8 = 0; + data->field_C = 0; + data->field_230 = -1; + memset(&data->passed, 0, sizeof(object_data_culling_info)); + memset(&data->culled, 0, sizeof(object_data_culling_info)); + memset(&data->passed_prev, 0, sizeof(object_data_culling_info)); + memset(&data->culled_prev, 0, sizeof(object_data_culling_info)); + data->show_alpha_center = false; + data->show_mat_center = false; + data->object_culling = true; + data->object_sort = true; + data->chara_color = true; + data->morph.value = 0.0f; + data->morph.object = object_info_null; + data->object_bounding_sphere_check_func = 0; + + data->buffer.offset = 0; + data->buffer.max_offset = 0; + data->buffer.size = 0x300000; + data->buffer.data = force_malloc(0x300000); + + if (data->buffer.data) { + data->texture_pattern_count = 0; + memset(data->texture_pattern_array, 0, sizeof(data->texture_pattern_array)); + data->texture_transform_count = 0; + memset(data->texture_transform_array, 0, sizeof(data->texture_transform_array)); + data->texture_color_coeff = vec4_identity; + data->texture_color_offset = vec4_null; + data->texture_specular_coeff = vec4_identity; + data->texture_specular_offset = vec4_null; + data->wet_param = 0.0f; + for (draw_object_type i = DRAW_OBJECT_OPAQUE; i < DRAW_OBJECT_MAX; i++) + data->draw_task_array[i] = vector_ptr_empty(draw_task); + } +} + +static void object_data_reset(object_data* data) { + data->passed_prev = data->passed; + data->culled_prev = data->culled; + data->draw_task_flags = 0; + data->field_8 = 0; + data->field_C = 0; + memset(&data->passed, 0, sizeof(object_data_culling_info)); + memset(&data->culled, 0, sizeof(object_data_culling_info)); + + data->texture_pattern_count = 0; + memset(data->texture_pattern_array, 0, sizeof(data->texture_pattern_array)); + data->texture_transform_count = 0; + memset(data->texture_transform_array, 0, sizeof(data->texture_transform_array)); + data->texture_color_coeff = vec4_identity; + data->texture_color_offset = vec4_null; + data->texture_specular_coeff = vec4_identity; + data->texture_specular_offset = vec4_null; + + for (draw_object_type i = DRAW_OBJECT_OPAQUE; i < DRAW_OBJECT_MAX; i++) { + data->draw_task_array[i].end = data->draw_task_array[i].begin; + vector_ptr_draw_task_clear(&data->draw_task_array[i], 0); + } + object_data_buffer_reset(&data->buffer); +} + +static void object_data_free(object_data* data) { + for (draw_object_type i = DRAW_OBJECT_OPAQUE; i < DRAW_OBJECT_MAX; i++) { + data->draw_task_array[i].end = data->draw_task_array[i].begin; + vector_ptr_draw_task_free(&data->draw_task_array[i], 0); + } + free(data->buffer.data); +} + +inline static void render_context_light_param_data_ibl_set_diffuse(light_param_ibl_diffuse* diffuse, int32_t level) { + int32_t size = diffuse->size; + size_t data_size = size; + data_size = 4 * data_size * data_size; + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 0]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 1]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 2]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 3]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 4]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &diffuse->data[data_size * 5]); +} + +inline static void render_context_light_param_data_ibl_set_specular(light_param_ibl_specular* specular) { + int32_t size = specular->size; + int32_t max_level = specular->max_level; + for (int32_t i = 0; i <= max_level; i++, size /= 2) { + half_t* data = specular->data[i]; + size_t data_size = size; + data_size = 4 * data_size * data_size; + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 0]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 1]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 2]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 3]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 4]); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, i, GL_RGBA16F, + size, size, 0, GL_RGBA, GL_HALF_FLOAT, &data[data_size * 5]); + } +} + +static shadow* shadow_init() { + shadow* shad = force_malloc(sizeof(shadow)); + shad->field_170 = 1.2f; + shad->field_174 = 1.0f; + for (int32_t i = 0; i < 2; i++) { + shad->view_point[i] = vec3_identity; + shad->field_1C0[i] = 0.0f; + shad->field_1C8[i] = 0.0f; + shad->field_200[i] = i; + } + shad->view_mat[0] = mat4_identity; + shad->view_mat[1] = mat4_identity; + shad->blur_filter = BLUR_FILTER_9; + shad->near_blur = 1; + shad->field_2BC = 2; + shad->far_blur = 1; + shad->distance = 4.0f; + shad->field_2C4 = 0.4f; + shad->z_near = 0.1f; + shad->z_far = 20.0f; + shad->field_2D0 = 1.4f; + shad->field_2D4 = 10000.0f; + shad->field_2D8 = 80.0f; + shad->field_2DC = 2.0f; + shad->field_2E0 = 0.05f; + shad->ambient = 0.4f; + shad->field_2EC = 0; + shad->direction = (vec3){ 0.0f, -1.0f, -1.0f }; + vec3_mult_scalar(shad->direction, 1.0f / sqrtf(2.0f), shad->direction); + shad->field_2E8 = false; + shad->self_shadow = true; + shad->blur_filter_enable[0] = true; + shad->blur_filter_enable[1] = true; + shad->field_2F5 = false; + shad->field_208 = (shad->z_far - shad->z_near) * 0.5f; + return shad; +} + +static void shadow_update_inner(shadow* shad, render_context* rctx) { + if (!shad) + return; + + for (int32_t i = 0; i < 2; i++) + shad->field_2F0[i] = false; + + if (rctx->draw_pass.shadow) { + shad->view_mat[0] = rctx->camera->view; + shad->view_mat[1] = rctx->camera->inv_view; + + light_set* set = &rctx->light_set_data[LIGHT_SET_MAIN]; + light_data* data = &set->lights[LIGHT_CHARA]; + + vec3 direction; + float_t length; + light_get_position(data, &direction); + vec3_negate(direction, direction); + vec3_length(direction, length); + if (length < 0.000001) + shad->direction = (vec3){ 0.0f, 1.0f, 0.0f }; + else + vec3_mult_scalar(direction, 1.0f / length, shad->direction); + + for (int32_t i = 0; i < 2; i++) + if (draw_task_get_count(rctx, DRAW_OBJECT_SHADOW_CHARA + i)) + shad->field_2F0[i] = true; + } + + int32_t count = 0; + shad->field_2EC = 0; + for (int32_t i = 0; i < 2; i++) + if (shad->field_2F0[i] && shad->field_1D0[i].end - shad->field_1D0[i].begin > 0) { + shad->field_2EC++; + count += (int32_t)(shad->field_1D0[i].end - shad->field_1D0[i].begin); + } + else + shad->field_2F0[i] = false; + + if (count < 3) { + for (int32_t i = 0; i < 2; i++) { + vector_vec3* v5 = &shad->field_1D0[i]; + shad->field_1A8[i] = vec3_null; + shad->field_1C8[i] = 0.0f; + if (!shad->field_2F0[i] || !(v5->end - v5->begin)) + continue; + + vec3 v7 = vec3_null; + for (vec3* j = v5->begin; j != v5->end; j++) + vec3_add(v7, *j, v7); + + float_t v14 = (float_t)(int32_t)(v5->end - v5->begin); + if (v14 < 0.0f) + v14 += 1.8446744e19f; + vec3_mult_scalar(v7, 1.0f / v14, v7); + + float_t v15 = 0.0f; + vec3 direction = shad->direction; + for (vec3* j = v5->begin; j != v5->end; j++) { + vec3 v22; + vec3_sub(v7, *j, v22); + float_t v23; + vec3_dot(v22, direction, v23); + vec3 v25; + vec3_mult_scalar(direction, v23, v25); + vec3_sub(v25, v22, v25); + float_t v24; + vec3_length(v25, v24); + v24 -= 0.25f; + if (v24 < 0.0f) + v24 = 0.0f; + if (v15 < v24) + v15 = v24; + } + shad->field_1A8[i] = v7; + shad->field_1C8[i] = v15; + } + + if (shad->field_2EC > 0) { + vec3 view_point = vec3_null; + vec3 interest = vec3_null; + for (int32_t i = 0; i < 2; i++) { + if (!shad->field_2F0[i]) + continue; + + vec3 v11; + vec3_mult_scalar(shad->direction, shad->field_208, v11); + vec3_sub(shad->field_1A8[i], v11, v11); + vec3 v14; + vec3_sub(shad->view_point[i], v11, v14); + float_t v9; + vec3_length(v14, v9); + + vec3 v20; + vec3_sub(shad->interest[i], shad->field_1A8[i], v20); + float_t v12; + vec3_length(v20, v12); + if (v9 > 0.1f || v12 > 0.1f) { + shad->view_point[i] = v11; + shad->interest[i] = shad->field_1A8[i]; + } + + vec3_add(view_point, shad->view_point[i], view_point); + vec3_add(interest, shad->interest[i], interest); + } + + vec3_mult_scalar(view_point, 1.0f / shad->field_2EC, shad->view_point_shared); + vec3_mult_scalar(interest, 1.0f / shad->field_2EC, shad->interest_shared); + } + + float_t v2 = max(shad->field_1C8[0], shad->field_1C8[1]); + shad->field_2F5 = false; + shad->field_170 = v2 + 1.2f; + shad->field_200[0] = 0; + shad->field_200[1] = 1; + if (shad->field_2EC >= 2) { + vec3 v12; + vec3_sub(shad->field_1A8[0], shad->interest_shared, v12); + + vec3 v14; + vec3_sub(shad->field_1A8[1], shad->interest_shared, v14); + + float_t v15; + vec3_dot(v12, shad->direction, v15); + + vec3 v6; + vec3_mult_scalar(shad->direction, v15, v6); + vec3_sub(v6, v12, v6); + + float_t v16; + vec3_length(v6, v16); + v16 -= 0.25f; + if (v16 < 0.0f) + v16 = 0.0f; + + if (v16 > 1.2f) { + shad->field_170 = v2 + 2.4f; + shad->field_2F5 = true; + } + else + shad->field_170 = v2 + 1.2f + v16; + + float_t t3; + float_t t4; + vec3_dot(v12, shad->direction, t3); + vec3_dot(v14, shad->direction, t4); + if (t3 < t4) { + shad->field_200[1] = 0; + shad->field_200[0] = 1; + } + } + } + else { + vec3 v3; + vec3 v86; + if (shad->direction.y * shad->direction.y < 0.99f) { + vec3_cross(shad->direction, ((vec3){ 0.0f, 1.0f, 0.0f }), v86); + vec3_cross(v86, shad->direction, v3); + vec3_normalize(v3, v3); + vec3_normalize(v86, v86); + } + else { + v3 = (vec3){ 0.0f, 0.0f, 1.0f }; + v86 = (vec3){ 1.0f, 0.0f, 0.0f }; + } + + for (int32_t i = 0; i < 2; i++) { + vector_vec3* v18 = &shad->field_1D0[i]; + shad->field_1A8[i] = vec3_null; + shad->field_1C8[i] = 0.0; + if (!shad->field_2F0[i] || !(v18->end - v18->begin)) + continue; + + vec3 v22 = vec3_null; + for (vec3* j = v18->begin; j != v18->end; j++) + vec3_add(v22, *j, v22); + + int32_t v27 = (int32_t)(v18->end - v18->begin); + float_t v29 = (float_t)v27; + if (v27 < 0) + v29 += 1.8446744e19f; + + float_t v30 = 0.0f; + vec3 v31; + vec3_mult_scalar(v22, 1.0f / v29, v31); + + for (vec3* j = v18->begin; j != v18->end; j++) { + vec3 v34; + vec3_sub(v31, *j, v34); + float_t v38; + float_t v39; + vec3_dot(v34, v3, v38); + vec3_dot(v34, v86, v39); + v38 = fabsf(v38); + v39 = fabsf(v39); + if (v39 >= v38) + v38 = v39; + if (v30 < v38) + v30 = v38; + } + shad->field_1A8[i] = v31; + shad->field_1C8[i] = v30; + } + + if (shad->field_2EC > 0) { + for (int32_t i = 0; i < 2; i++) { + if (!shad->field_2F0[i]) + continue; + + float_t v51; + vec3 v52; + vec3 v53; + float_t v54; + vec3 v55; + vec3_mult_scalar(shad->direction, shad->field_208, v53); + vec3_sub(shad->field_1A8[i], v53, v53); + vec3_sub(shad->view_point[i], v53, v52); + vec3_length(v52, v51); + vec3_sub(shad->interest[i], shad->field_1A8[i], v55); + vec3_length(v55, v54); + if (v51 > 0.1f || v54 > 0.1f) { + shad->view_point[i] = v53; + shad->interest[i] = shad->field_1A8[i]; + } + } + + vec3 view_point = vec3_null; + vec3 interest = vec3_null; + int32_t count = 0;; + for (int32_t i = 0; i < 2; i++) { + int32_t c = (int32_t)(shad->field_1D0[i].end - shad->field_1D0[i].begin); + vec3 view_point_temp; + vec3 interest_temp; + vec3_mult_scalar(shad->view_point[i], (float_t)c, view_point_temp); + vec3_mult_scalar(shad->interest[i], (float_t)c, interest_temp); + vec3_add(view_point, view_point_temp, view_point); + vec3_add(interest, interest_temp, interest); + count += c; + } + + vec3_mult_scalar(view_point, 1.0f / (float_t)count, shad->view_point_shared); + vec3_mult_scalar(interest, 1.0f / (float_t)count, shad->interest_shared); + } + + float_t v2 = 0.0; + float_t v67 = max(shad->field_1C8[0], shad->field_1C8[1]); + shad->field_2F5 = false; + shad->field_170 = v67 + 1.2f; + shad->field_200[0] = 0; + shad->field_200[1] = 1; + if (shad->field_2EC >= 2) { + float_t v68 = 0.0; + float_t v69 = 0.0; + float_t v70 = 0.0; + for (int32_t i = 0; i < 2; i++) { + if (!shad->field_2F0[i]) + continue; + + vector_vec3* v72 = &shad->field_1D0[i]; + for (vec3* j = v72->begin; j != v72->end; j++) { + vec3 v74; + vec3_sub(*j, shad->interest_shared, v74); + + float_t v77; + vec3_dot(v74, v86, v77); + if (v77 < v2) + v2 = v77; + else if (v69 < v77) + v69 = v77; + + float_t v78; + vec3_dot(v74, v3, v78); + if (v78 < v68) + v68 = v78; + else if (v70 < v78) + v70 = v78; + } + } + + float_t v79 = -v2; + if (v79 < v69) + v79 = v69; + if (v79 < -v68) + v79 = -v68; + if (v79 < v70) + v79 = v70; + + if (v79 > v67 + 1.2f) { + shad->field_170 = v67 + 2.4f; + shad->field_2F5 = true; + } + else + shad->field_170 = v79 + 1.2f; + + vec3 interest_chara; + vec3 interest_stage; + float_t interest_chara_cos; + float_t interest_stage_cos; + vec3_sub(shad->field_1A8[0], shad->interest_shared, interest_chara); + vec3_dot(interest_chara, shad->direction, interest_chara_cos); + vec3_sub(shad->field_1A8[1], shad->interest_shared, interest_stage); + vec3_dot(interest_stage, shad->direction, interest_stage_cos); + if (interest_chara_cos < interest_stage_cos) { + shad->field_200[1] = 0; + shad->field_200[0] = 1; + } + } + } + + for (int32_t i = 0; i < 2; i++) + shad->field_1D0[i].end = shad->field_1D0[i].begin; +} + +static int32_t shadow_init_data(shadow* shad) { + typedef struct shadow_texture_init_params { + int32_t width; + int32_t height; + int32_t max_level; + GLenum color_format; + GLenum depth_format; + } shadow_texture_init_params; + + shadow_texture_init_params init_params[] = { + { 0x800, 0x800, 0, GL_RGBA8, GL_DEPTH24_STENCIL8 }, + { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { 0x800, 0x800, 0, GL_R32F, GL_ZERO }, + { 0x800, 0x800, 0, GL_R32F, GL_ZERO }, + { 0x200, 0x200, 0, GL_R32F, GL_ZERO }, + { 0x200, 0x200, 0, GL_R32F, GL_ZERO }, + }; + + shadow_texture_init_params* v3 = init_params; + for (int32_t i = 0; i < 7; i++, v3++) + if (render_texture_init(&shad->field_8[i], v3->width, v3->height, + v3->max_level, v3->color_format, v3->depth_format) < 0) + return -1; + + for (int32_t i = 0; i < 3; i++) { + gl_state_bind_texture_2d(shad->field_8[i].color_texture->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&vec4_identity); + } + gl_state_bind_texture_2d(0); + glGetError(); + return 0; +} + +static void shadow_free(shadow* shad) { + if (!shad) + return; + + for (int32_t i = 0; i < 7; i++) + render_texture_free(&shad->field_8[i]); + + for (int32_t i = 0; i < 2; i++) + vector_vec3_free(&shad->field_1D0[i], 0); + free(shad); +} + +static void sss_data_init(sss_data_struct* sss) { + memset(sss, 0, sizeof(sss_data_struct)); + sss->init = true; + sss->enable = true; + sss->npr_contour = true; + render_texture_init(&sss->textures[0], 640, 360, 0, GL_RGBA16F, GL_DEPTH24_STENCIL8); + render_texture_init(&sss->textures[1], 320, 180, 0, GL_RGBA16F, GL_ZERO); + render_texture_init(&sss->textures[2], 320, 180, 0, GL_RGBA16F, GL_ZERO); + render_texture_init(&sss->textures[3], 320, 180, 0, GL_RGBA16F, GL_ZERO); + sss->param = (vec4){ 0.0f, 0.0f, 0.0f, 1.0f }; +} + +static void sss_data_free(sss_data_struct* sss) { + render_texture_free(&sss->textures[0]); + render_texture_free(&sss->textures[1]); + render_texture_free(&sss->textures[2]); + render_texture_free(&sss->textures[3]); +} diff --git a/src/CRE/render_context.h b/src/CRE/render_context.h new file mode 100644 index 00000000..9c3aeba9 --- /dev/null +++ b/src/CRE/render_context.h @@ -0,0 +1,527 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/vector.h" +#include "light_param/face.h" +#include "light_param/fog.h" +#include "light_param/light.h" +#include "light_param/wind.h" +#include "camera.h" +#include "data.h" +#include "gl_state.h" +#include "light_param.h" +#include "object.h" +#include "post_process.h" +#include "render_texture.h" +#include "time.h" +#include "timer.h" +#include "static_var.h" + +#define MATRIX_BUFFER_COUNT 320 +#define TEXTURE_PATTERN_COUNT 24 +#define TEXTURE_TRANSFORM_COUNT 24 + +typedef enum draw_object_type { + DRAW_OBJECT_OPAQUE = 0x00, + DRAW_OBJECT_TRANSLUCENT = 0x01, + DRAW_OBJECT_TRANSLUCENT_NO_SHADOW = 0x02, + DRAW_OBJECT_TRANSPARENT = 0x03, + DRAW_OBJECT_SHADOW_CHARA = 0x04, + DRAW_OBJECT_SHADOW_STAGE = 0x05, + DRAW_OBJECT_TYPE_6 = 0x06, + DRAW_OBJECT_TYPE_7 = 0x07, + DRAW_OBJECT_SHADOW_OBJECT_CHARA = 0x08, + DRAW_OBJECT_SHADOW_OBJECT_STAGE = 0x09, + DRAW_OBJECT_REFLECT_CHARA_OPAQUE = 0x0A, + DRAW_OBJECT_REFLECT_CHARA_TRANSLUCENT = 0x0B, + DRAW_OBJECT_REFLECT_CHARA_TRANSPARENT = 0x0C, + DRAW_OBJECT_REFLECT_OPAQUE = 0x0D, + DRAW_OBJECT_REFLECT_TRANSLUCENT = 0x0E, + DRAW_OBJECT_REFLECT_TRANSPARENT = 0x0F, + DRAW_OBJECT_REFRACT_OPAQUE = 0x10, + DRAW_OBJECT_REFRACT_TRANSLUCENT = 0x11, + DRAW_OBJECT_REFRACT_TRANSPARENT = 0x12, + DRAW_OBJECT_SSS = 0x13, + DRAW_OBJECT_OPAQUE_TYPE_20 = 0x14, + DRAW_OBJECT_TRANSPARENT_TYPE_21 = 0x15, + DRAW_OBJECT_TRANSLUCENT_TYPE_22 = 0x16, + DRAW_OBJECT_OPAQUE_TYPE_23 = 0x17, + DRAW_OBJECT_TRANSPARENT_TYPE_24 = 0x18, + DRAW_OBJECT_TRANSLUCENT_TYPE_25 = 0x19, + DRAW_OBJECT_OPAQUE_TYPE_26 = 0x1A, + DRAW_OBJECT_TRANSPARENT_TYPE_27 = 0x1B, + DRAW_OBJECT_TRANSLUCENT_TYPE_28 = 0x1C, + DRAW_OBJECT_RIPPLE = 0x1D, + DRAW_OBJECT_MAX = 0x1E, +} draw_object_type; + +typedef enum draw_pass_type { + DRAW_PASS_SHADOW = 0x00, + DRAW_PASS_SSS = 0x01, + DRAW_PASS_TYPE_2 = 0x02, + DRAW_PASS_REFLECT = 0x03, + DRAW_PASS_REFRACT = 0x04, + DRAW_PASS_PREPROCESS = 0x05, + DRAW_PASS_TYPE_6 = 0x06, + DRAW_PASS_TYPE_7 = 0x07, + DRAW_PASS_3D = 0x08, + DRAW_PASS_SHOW_VECTOR = 0x09, + DRAW_PASS_POST_PROCESS = 0x0A, + DRAW_PASS_SPRITE = 0x0B, + DRAW_PASS_TYPE_12 = 0x0C, + DRAW_PASS_MAX = 0x0D, +} draw_pass_type; + +typedef enum draw_task_flags { + DRAW_TASK_SHADOW = 0x00000001, + DRAW_TASK_2 = 0x00000002, + DRAW_TASK_4 = 0x00000004, + DRAW_TASK_8 = 0x00000008, + DRAW_TASK_10 = 0x00000010, + DRAW_TASK_20 = 0x00000020, + DRAW_TASK_40 = 0x00000040, + DRAW_TASK_SHADOW_OBJECT = 0x00000080, + DRAW_TASK_CHARA_REFLECT = 0x00000100, + DRAW_TASK_REFLECT = 0x00000200, + DRAW_TASK_REFRACT = 0x00000400, + DRAW_TASK_800 = 0x00000800, + DRAW_TASK_TRANSLUCENT_NO_SHADOW = 0x00001000, + DRAW_TASK_SSS = 0x00002000, + DRAW_TASK_4000 = 0x00004000, + DRAW_TASK_8000 = 0x00008000, + DRAW_TASK_10000 = 0x00010000, + DRAW_TASK_20000 = 0x00020000, + DRAW_TASK_40000 = 0x00040000, + DRAW_TASK_80000 = 0x00080000, + DRAW_TASK_100000 = 0x00100000, + DRAW_TASK_200000 = 0x00200000, + DRAW_TASK_400000 = 0x00400000, + DRAW_TASK_800000 = 0x00800000, + DRAW_TASK_RIPPLE = 0x01000000, + DRAW_TASK_2000000 = 0x02000000, + DRAW_TASK_4000000 = 0x04000000, + DRAW_TASK_8000000 = 0x08000000, + DRAW_TASK_10000000 = 0x10000000, + DRAW_TASK_20000000 = 0x20000000, + DRAW_TASK_40000000 = 0x40000000, + DRAW_TASK_NO_TRANSLUCENCY = 0x80000000, +} draw_task_flags; + +typedef enum draw_task_type { + DRAW_TASK_TYPE_OBJECT = 0x00, + DRAW_TASK_TYPE_PRIMITIVE = 0x01, + DRAW_TASK_TYPE_PREPROCESS = 0x02, + DRAW_TASK_TYPE_OBJECT_TRANSLUCENT = 0x03, +} draw_task_type; + +typedef enum reflect_refract_resolution_mode { + REFLECT_REFRACT_RESOLUTION_256x256 = 0x00, + REFLECT_REFRACT_RESOLUTION_512x256 = 0x01, + REFLECT_REFRACT_RESOLUTION_512x512 = 0x02, +} reflect_refract_resolution_mode; + +typedef enum blur_filter_mode { + BLUR_FILTER_4 = 0x00, + BLUR_FILTER_9 = 0x01, + BLUR_FILTER_16 = 0x02, + BLUR_FILTER_32 = 0x03, +} blur_filter_mode; + +typedef enum shadow_type_enum { + SHADOW_CHARA = 0x00, + SHADOW_STAGE = 0x01, + SHADOW_MAX = 0x02, +} shadow_type_enum; + +typedef struct render_context render_context; +typedef struct shadow shadow; + +typedef struct draw_state_stats { + int32_t object_draw_count; + int32_t object_translucent_draw_count; + int32_t object_reflect_draw_count; + int32_t field_C; + int32_t field_10; + int32_t draw_count; + int32_t draw_triangle_count; + int32_t field_1C; +} draw_state_stats; + +typedef struct sss_data_struct { + bool init; + bool enable; + bool npr_contour; + render_texture textures[4]; + vec4 param; +} sss_data_struct; + +typedef struct draw_pass { + bool enable[DRAW_PASS_MAX]; + shadow* shadow_ptr; + bool reflect; + bool refract; + int32_t reflect_blur_num; + blur_filter_mode reflect_blur_filter; + bool wait_for_gpu; + double_t cpu_time[DRAW_PASS_MAX]; + double_t gpu_time[DRAW_PASS_MAX]; + time_struct time; + bool shadow; + bool opaque_z_sort; + bool alpha_z_sort; + bool draw_pass_3d[DRAW_PASS_3D_MAX]; + int32_t reflect_type; + render_texture reflect_texture; + int32_t show_vector_flags; + float_t show_vector_length; + float_t show_vector_z_offset; + bool field_2F8; + //vector_draw_preprocess preprocess; + texture* sss_texture; + int32_t npr_param; + bool npr; + sss_data_struct sss_data; +} draw_pass; + +typedef struct draw_state { + draw_state_stats stats; + draw_state_stats stats_prev; + bool wireframe; + bool wireframe_overlay; + bool light; + bool self_shadow; + bool field_45; + bool use_global_material; + bool fog_height; + bool ex_data_mat; + bool shader; + int32_t shader_index; + int32_t field_50; + float_t bump_depth; + float_t intensity; + float_t specular_alpha; + float_t reflect_uv_scale; + float_t refract_uv_scale; + int32_t field_68; + float_t fresnel; +} draw_state; + +typedef struct texture_pattern_struct { + int32_t src; + int32_t dst; +} texture_pattern_struct; + +vector(texture_pattern_struct) + +typedef struct texture_transform_struct { + int32_t id; + mat4u mat; +} texture_transform_struct; + +vector(texture_transform_struct) + +typedef struct draw_object draw_object; + +struct draw_object { + object_sub_mesh* sub_mesh; + object_mesh* mesh; + object_material_data* material; + uint32_t* textures; + int32_t mat_count; + mat4u* mats; + GLuint array_buffer; + GLuint element_array_buffer; + bool set_blend_color; + bool chara_color; + vec4u blend_color; + bool self_shadow; + shadow_type_enum shadow; + GLuint morph_array_buffer; + float_t morph_value; + int32_t texture_pattern_count; + texture_pattern_struct texture_pattern_array[TEXTURE_PATTERN_COUNT]; + vec4u texture_color_coeff; + vec4u texture_color_offset; + vec4u texture_specular_coeff; + vec4u texture_specular_offset; + int32_t texture_transform_count; + texture_transform_struct texture_transform_array[TEXTURE_TRANSFORM_COUNT]; + int32_t instances_count; + mat4* instances_mat; + void(*draw_object_func)(draw_object*); + bool vertex_attrib_array[16]; +}; + +typedef enum draw_primitive_type { + DRAW_PRIMITIVE_TEAPOT = 0x0, + DRAW_PRIMITIVE_TYPE_1 = 0x1, + DRAW_PRIMITIVE_CUBE = 0x2, + DRAW_PRIMITIVE_SPHERE = 0x3, + DRAW_PRIMITIVE_TYPE_4 = 0x4, + DRAW_PRIMITIVE_CONE = 0x5, + DRAW_PRIMITIVE_LINE = 0x6, + DRAW_PRIMITIVE_TYPE_7 = 0x7, +} draw_primitive_type; + +typedef struct draw_primitive_teapot { + float_t size; +} draw_primitive_teapot; + +typedef struct draw_primitive_type_1 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; +} draw_primitive_type_1; + +typedef struct draw_primitive_cube { + vec3 size; + bool wireframe; +} draw_primitive_cube; + +typedef struct draw_primitive_sphere { + float_t radius; + int32_t slices; + int32_t stacks; + bool wireframe; +} draw_primitive_sphere; + +typedef struct draw_primitive_type_4 { + int32_t field_0; + int32_t field_4; +} draw_primitive_type_4; + +typedef struct draw_primitive_cone { + float_t base; + float_t height; + int32_t slices; + int32_t stacks; + bool wireframe; +} draw_primitive_cone; + +typedef struct draw_primitive_line { + vec3 v0; + vec3 v1; +} draw_primitive_line; + +typedef struct draw_primitive_type_7 { + float_t size; +} draw_primitive_type_7; + +typedef union draw_primitive_union { + draw_primitive_teapot teapot; + draw_primitive_type_1 field_1; + draw_primitive_cube cube; + draw_primitive_sphere sphere; + draw_primitive_type_4 type_4; + draw_primitive_cone cone; + draw_primitive_line line; + draw_primitive_type_7 type_7; +} draw_primitive_union; + +typedef struct draw_primitive { + draw_primitive_type type; + bool fog; + vec4 color; + draw_primitive_union data; +} draw_primitive; + +typedef struct draw_task_preprocess { + void(*func)(render_context* rctx, void* data); + void* data; +} draw_task_preprocess; + +typedef struct draw_task_object_translucent { + int32_t count; + draw_object* objects[40]; +} draw_task_object_translucent; + +typedef union draw_task_union { + draw_object object; + draw_primitive primitive; + draw_task_preprocess preprocess; + draw_task_object_translucent object_translucent; +} draw_task_union; + +typedef struct draw_task { + draw_task_type type; + mat4u mat; + float_t depth; + float_t bounding_radius; + draw_task_union data; +} draw_task; + +typedef struct light_proj { + bool enable; + render_texture shadow_texture[2]; + render_texture draw_texture; + uint32_t texture_id; +} light_proj; + +typedef struct morph_struct { + object_info object; + float_t value; +} morph_struct; + +vector_ptr(draw_task) + +typedef struct object_data_buffer { + int32_t offset; + int32_t max_offset; + int32_t size; //0x300000 + void* data; +} object_data_buffer; + +typedef struct object_data_culling_info { + int32_t objects; + int32_t meshes; + int32_t sub_meshes; +} object_data_culling_info; + +typedef struct object_data { + draw_task_flags draw_task_flags; + shadow_type_enum shadow_type; + int32_t field_8; + int32_t field_C; + vector_ptr_draw_task draw_task_array[DRAW_OBJECT_MAX]; + object_data_culling_info passed; + object_data_culling_info culled; + object_data_culling_info passed_prev; + object_data_culling_info culled_prev; + int32_t field_230; + bool show_alpha_center; + bool show_mat_center; + bool object_culling; + bool object_sort; + bool chara_color; + object_data_buffer buffer; + morph_struct morph; + int32_t texture_pattern_count; + texture_pattern_struct texture_pattern_array[TEXTURE_PATTERN_COUNT]; + vec4 texture_color_coeff; + vec4 texture_color_offset; + vec4 texture_specular_coeff; + vec4 texture_specular_offset; + float_t wet_param; + int32_t texture_transform_count; + texture_transform_struct texture_transform_array[TEXTURE_TRANSFORM_COUNT]; + bool(*object_bounding_sphere_check_func)(object_bounding_sphere*); +} object_data; + +struct render_context { + camera* camera; + draw_state draw_state; + object_data object_data; + draw_pass draw_pass; + GLuint vao; + GLuint ibl_tex[5]; + + face face; + fog fog_data[FOG_MAX]; + light_proj* litproj; + light_set light_set_data[LIGHT_SET_MAX]; + wind* wind; + + void* stage; + data_struct* data; + post_process_struct post_process; + bool chara_reflect; + bool chara_refract; + + mat4 view_mat; + mat4 matrix_buffer[MATRIX_BUFFER_COUNT]; +}; + +struct shadow { + render_texture field_8[7]; + render_texture* field_158[3]; + float_t field_170; + float_t field_174; + vec3 view_point[2]; + vec3 interest[2]; + vec3 field_1A8[2]; + float_t field_1C0[2]; + float_t field_1C8[2]; + vector_vec3 field_1D0[2]; + int32_t field_200[2]; + float_t field_208; + vec3 direction; + vec3 view_point_shared; + vec3 interest_shared; + mat4 view_mat[2]; + int32_t near_blur; + blur_filter_mode blur_filter; + int32_t far_blur; + int32_t field_2BC; + float_t distance; + float_t field_2C4; + float_t z_near; + float_t z_far; + float_t field_2D0; + float_t field_2D4; + float_t field_2D8; + float_t field_2DC; + float_t field_2E0; + float_t ambient; + bool field_2E8; + int32_t field_2EC; + bool field_2F0[2]; + bool self_shadow; + bool blur_filter_enable[2]; + bool field_2F5; +}; + +extern const texture_pattern_struct texture_pattern_struct_null; + +extern light_proj* light_proj_init(int32_t width, int32_t height); +extern void light_proj_get_proj_mat(vec3* view_point, vec3* interest, float_t fov, mat4* mat); +extern void light_proj_resize(light_proj* litproj, int32_t width, int32_t height); +extern bool light_proj_set(light_proj* litproj, render_context* rctx); +extern bool light_proj_set_mat(render_context* rctx, bool set_mat); +extern void light_proj_free(light_proj* litproj); +extern draw_task* object_data_buffer_add_draw_task(object_data_buffer* buffer, draw_task_type type); +extern mat4u* object_data_buffer_add_mat4(object_data_buffer* buffer, int32_t count); +extern void object_data_buffer_reset(object_data_buffer* buffer); +extern bool object_data_get_chara_color(object_data* object_data); +extern draw_task_flags object_data_get_draw_task_flags(object_data* object_data); +extern void object_data_get_morph(object_data* object_data, object_info* object, float_t* value); +extern shadow_type_enum object_data_get_shadow_type(object_data* object_data); +extern void object_data_get_texture_color_coeff(object_data* object_data, vec4* value); +extern void object_data_get_texture_color_offset(object_data* object_data, vec4* value); +extern void object_data_get_texture_pattern(object_data* object_data, + int32_t* count, texture_pattern_struct* value); +extern void object_data_get_texture_specular_coeff(object_data* object_data, vec4* value); +extern void object_data_get_texture_specular_offset(object_data* object_data, vec4* value); +extern void object_data_get_texture_transform(object_data* object_data, + int32_t* count, texture_transform_struct* value); +extern float_t object_data_get_wet_param(object_data* object_data); +extern void object_data_set_chara_color(object_data* object_data, bool value); +extern void object_data_set_draw_task_flags(object_data* object_data, draw_task_flags flags); +extern void object_data_set_morph(object_data* object_data, object_info object, float_t value); +extern void object_data_set_shadow_type(object_data* object_data, shadow_type_enum type); +extern void object_data_set_texture_color_coeff(object_data* object_data, vec4* value); +extern void object_data_set_texture_color_offset(object_data* object_data, vec4* value); +extern void object_data_set_texture_pattern(object_data* object_data, + int32_t count, texture_pattern_struct* value); +extern void object_data_set_texture_specular_coeff(object_data* object_data, vec4* value); +extern void object_data_set_texture_specular_offset(object_data* object_data, vec4* value); +extern void object_data_set_texture_transform(object_data* object_data, + int32_t count, texture_transform_struct* value); +extern void object_data_set_wet_param(object_data* object_data, float_t value); +extern render_context* render_context_init(); +extern void render_context_light_param_data_light_set(render_context* rctx, light_param_light* light); +extern void render_context_light_param_data_fog_set(render_context* rctx, light_param_fog* f); +extern void render_context_light_param_data_glow_set(render_context* rctx, light_param_glow* glow); +extern void render_context_light_param_data_ibl_set(render_context* rctx, light_param_ibl* ibl); +extern void render_context_light_param_data_wind_set(render_context* rctx, light_param_wind* w); +extern void render_context_light_param_data_face_set(render_context* rctx, light_param_face* face); +extern void render_context_set_light_param(render_context* rctx, light_param_data* light_param); +extern void render_context_update(render_context* rctx); +extern void render_context_free(render_context* rctx); +extern void shadow_update(shadow* shad, render_context* rctx); \ No newline at end of file diff --git a/src/CRE/render_texture.c b/src/CRE/render_texture.c index 1aeba587..ce8d6345 100644 --- a/src/CRE/render_texture.c +++ b/src/CRE/render_texture.c @@ -7,6 +7,11 @@ #include "gl_state.h" #include "texture.h" +static shader_glsl render_texture_shader; +static int32_t render_texture_vao, render_texture_vbo; +static bool render_texture_data_initialized; +static uint32_t render_texture_counter; + static int32_t render_texture_framebuffer_init(render_texture* rt, int32_t max_level); static int32_t render_texture_framebuffer_set_texture(render_texture* rrt, GLuint color_texture, int32_t level, GLuint depth_texture, bool stencil); @@ -16,22 +21,20 @@ int32_t render_texture_init(render_texture* rt, int32_t width, int32_t height, if (max_level < 0) return -1; - if (rt->color_texture && rt->depth_texture - && rt->color_texture->width == width && rt->color_texture->height == height - && rt->color_texture->max_mipmap_level == max_level - && rt->color_texture->internal_format == color_format - && rt->depth_texture->internal_format == depth_format) + max_level = min(max_level, 15); + if (max_level < 0) return 0; render_texture_free(rt); GLuint color_texture; if (color_format) { - texture* color_tex = texture_load_tex_2d(color_format, width, height, max_level, 0, 0); - rt->color_texture = color_tex; - if (!color_tex) + rt->color_texture = texture_load_tex_2d(texture_make_id(0x23, render_texture_counter), + color_format, width, height, max_level, 0, 0); + if (!rt->color_texture) return -1; - color_texture = color_tex->texture; + render_texture_counter++; + color_texture = rt->color_texture->texture; if (color_format == GL_RGBA32F) { gl_state_bind_texture_2d(rt->color_texture->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -47,12 +50,13 @@ int32_t render_texture_init(render_texture* rt, int32_t width, int32_t height, GLuint depth_texture; bool stencil; if (depth_format) { - texture* depth_tex = texture_load_tex_2d(depth_format, width, height, 0, 0, 0); - rt->depth_texture = depth_tex; - if (!depth_tex) + rt->depth_texture = texture_load_tex_2d(texture_make_id(0x23, render_texture_counter), + depth_format, width, height, 0, 0, 0); + if (!rt->depth_texture) return -1; - depth_texture = depth_tex->texture; + render_texture_counter++; + depth_texture = rt->depth_texture->texture; stencil = depth_format == GL_DEPTH24_STENCIL8; } else { @@ -81,16 +85,71 @@ int32_t render_texture_bind(render_texture* rt, int32_t index) { return 0; } -void render_texture_free(render_texture* rt) { - if (rt->depth_texture) { - texture_dispose(rt->depth_texture); - rt->depth_texture = 0; - } +inline void render_texture_draw(render_texture* rt, bool depth) { + gl_state_active_bind_texture_2d(0, rt->color_texture->texture); + if (depth && rt->depth_texture->texture) + gl_state_active_bind_texture_2d(1, rt->depth_texture->texture); + gl_state_bind_vertex_array(render_texture_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + gl_state_bind_vertex_array(0); +} - if (rt->color_texture) { - texture_dispose(rt->color_texture); - rt->color_texture = 0; - } +inline void render_texture_draw_custom(shader_set_data* set) { + gl_state_bind_vertex_array(render_texture_vao); + shader_draw_arrays(set, GL_TRIANGLE_STRIP, 0, 3); + gl_state_bind_vertex_array(0); +} + +inline void render_texture_draw_custom_glsl() { + gl_state_bind_vertex_array(render_texture_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + gl_state_bind_vertex_array(0); +} + +void render_texture_draw_params(shader_set_data* set, int32_t width, int32_t height, + float_t scale, float_t param_x, float_t param_y, float_t param_z, float_t param_w) { + float_t w = (float_t)max(width, 1); + float_t h = (float_t)max(height, 1); + shader_local_vert_set(set, 0, scale / w, scale / h, w, h); + shader_local_frag_set(set, 0, scale / w, scale / h, w, h); + shader_local_vert_set(set, 3, param_x, param_y, param_z, param_w); + shader_local_frag_set(set, 3, param_x, param_y, param_z, param_w); + + gl_state_bind_vertex_array(render_texture_vao); + shader_draw_arrays(set, GL_TRIANGLE_STRIP, 0, 3); + gl_state_bind_vertex_array(0); +} + +int32_t render_texture_set_color_depth_textures(render_texture* rt, + GLuint color_texture, int32_t level, GLuint depth_texture, bool stencil) { + int32_t error = 0; + rt->max_level = level; + if (!rt->fbos[0]) + error = render_texture_framebuffer_init(rt, level); + render_texture_framebuffer_set_texture(rt, color_texture, level, depth_texture, stencil); + return error; +} + +inline void render_texture_shader_set(shader_set_data* set, uint32_t index) { + if (set && index) + shader_set(set, index); + else + shader_glsl_use(&render_texture_shader); +} + +inline void render_texture_shader_set_glsl(shader_glsl* shader) { + if (shader) + shader_glsl_use(shader); + else + shader_glsl_use(&render_texture_shader); +} + +void render_texture_free(render_texture* rt) { + if (rt->depth_texture) + texture_free(rt->depth_texture); + + if (rt->color_texture) + texture_free(rt->color_texture); if (rt->rbo) { glDeleteRenderbuffers(1, &rt->rbo); @@ -104,13 +163,95 @@ void render_texture_free(render_texture* rt) { if (rt->fbos) { glDeleteFramebuffers(rt->max_level + 1, rt->fbos); - free(rt->fbos); + memset(rt->fbos, 0, sizeof(int32_t) * (rt->max_level + 1ULL)); } } + +void render_texture_data_init() { + if (!render_texture_data_initialized) { + static const char* render_texture_vert_shader = + "#version 430 core\n" + "out VertexData {\n" + " vec2 texcoord;\n" + "} result;\n" + "\n" + "void main() {\n" + " gl_Position.x = -1.0 + float(gl_VertexID / 2) * 4.0;\n" + " gl_Position.y = 1.0 - float(gl_VertexID % 2) * 4.0;\n" + " gl_Position.z = 0.0;\n" + " gl_Position.w = 1.0;\n" + " result.texcoord = gl_Position.xy * 0.5 + 0.5;\n" + "}\n"; + + static const char* render_texture_frag_shader = + "#version 430 core\n" + "layout(location = 0) out vec4 result;\n" + "\n" + "in VertexData {\n" + " vec2 texcoord;\n" + "} frg;\n" + "\n" + "layout(binding = 0) uniform sampler2D g_color;\n" + "\n" + "void main() {\n" + " result = texture(g_color, frg.texcoord); \n" + "}\n"; + + shader_glsl_param param; + memset(¶m, 0, sizeof(shader_glsl_param)); + param.name = "Render Texture"; + shader_glsl_load_string(&render_texture_shader, + (char*)render_texture_vert_shader, (char*)render_texture_frag_shader, 0, ¶m); + + const float_t verts_quad[] = { + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -3.0f, 0.0f, -1.0f, + 3.0f, 1.0f, 2.0f, 1.0f, + }; + + glGenBuffers(1, &render_texture_vbo); + glGenVertexArrays(1, &render_texture_vao); + glBindBuffer(GL_ARRAY_BUFFER, render_texture_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(verts_quad), verts_quad, GL_STATIC_DRAW); + + gl_state_bind_vertex_array(render_texture_vao); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, (void*)0); // Pos + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); // Color0 + glVertexAttrib4f(4, 1.0f, 1.0f, 1.0f, 1.0f); // Color1 + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord0 + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord1 + glEnableVertexAttribArray(10); + glVertexAttribPointer(10, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord2 + glEnableVertexAttribArray(11); + glVertexAttribPointer(11, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord3 + glEnableVertexAttribArray(12); + glVertexAttribPointer(12, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord4 + glEnableVertexAttribArray(13); + glVertexAttribPointer(13, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord5 + glEnableVertexAttribArray(14); + glVertexAttribPointer(14, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord6 + glEnableVertexAttribArray(15); + glVertexAttribPointer(15, 2, GL_FLOAT, GL_FALSE, 16, (void*)8); // TexCoord7 + gl_state_bind_vertex_array(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + render_texture_data_initialized = true; + } +} + +void render_texture_data_free() { + shader_glsl_free(&render_texture_shader); + + glDeleteBuffers(1, &render_texture_vbo); + glDeleteVertexArrays(1, &render_texture_vao); + + render_texture_data_initialized = false; +} + static int32_t render_texture_framebuffer_init(render_texture* rt, int32_t max_level) { - rt->fbos = force_malloc_s(GLuint, max_level + 1ULL); - if (!rt->fbos) - return -1; glGenFramebuffers(max_level + 1, rt->fbos); return -(glGetError() != GL_ZERO); } diff --git a/src/CRE/render_texture.h b/src/CRE/render_texture.h index 2b7212f6..603a4d61 100644 --- a/src/CRE/render_texture.h +++ b/src/CRE/render_texture.h @@ -6,6 +6,8 @@ #pragma once #include "shared.h" +#include "shader.h" +#include "shader_glsl.h" #include "texture.h" typedef struct render_texture { @@ -13,12 +15,23 @@ typedef struct render_texture { texture* depth_texture; int32_t binding; int32_t max_level; - GLuint* fbos; + GLuint fbos[16]; GLuint rbo; GLuint field_2C; } render_texture; -int32_t render_texture_init(render_texture* rt, int32_t width, int32_t height, +extern int32_t render_texture_init(render_texture* rt, int32_t width, int32_t height, int32_t max_level, GLenum color_format, GLenum depth_format); -int32_t render_texture_bind(render_texture* rt, int32_t index); -void render_texture_free(render_texture* rt); +extern int32_t render_texture_bind(render_texture* rt, int32_t index); +extern void render_texture_draw(render_texture* rt, bool depth); +extern void render_texture_draw_custom(shader_set_data* set); +extern void render_texture_draw_custom_glsl(); +extern void render_texture_draw_params(shader_set_data* set, int32_t width, int32_t height, + float_t scale, float_t param_x, float_t param_y, float_t param_z, float_t param_w); +extern int32_t render_texture_set_color_depth_textures(render_texture* rt, + GLuint color_texture, int32_t level, GLuint depth_texture, bool stencil); +extern void render_texture_shader_set(shader_set_data* set, uint32_t index); +extern void render_texture_shader_set_glsl(shader_glsl* shader); +extern void render_texture_free(render_texture* rt); +extern void render_texture_data_init(); +extern void render_texture_data_free(); diff --git a/src/CRE/rob.c b/src/CRE/rob.c new file mode 100644 index 00000000..9a0c39aa --- /dev/null +++ b/src/CRE/rob.c @@ -0,0 +1,5963 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "rob.h" +#include "data.h" +#include "draw_task.h" +#include "../KKdLib/str_utils.h" + +vector_func(bone_data) +vector_func(bone_node) +vector_ptr_func(ex_constraint_block) +vector_ptr_func(ex_cloth_block) +vector_ptr_func(ex_expression_block) +vector_ptr_func(ex_osage_block) +vector_ptr_func(ex_node_block) +vector_func(ex_data_name_bone_index) +vector_func(mot_key_set) +vector_ptr_func(motion_blend_mot) +vector_func(osage_coli) +vector_func(pair_int32_t_ptr_rob_osage_node) +vector_func(pair_name_ex_osage_block) +vector_func(rob_osage_node) +vector_ptr_func(rob_osage_node) +vector_func(skin_param_osage_root_coli) +vector_func(struc_331) + +typedef struct motion_storage { + uint32_t set_id; + int32_t count; + mot_set set; +} motion_storage; + +typedef struct exp_func_op1 { + char* name; + float_t(*func)(float_t v1); +} exp_func_op1; + +typedef struct exp_func_op2 { + char* name; + float_t(*func)(float_t v1, float_t v2); +} exp_func_op2; + +typedef struct exp_func_op3 { + char* name; + float_t(*func)(float_t v1, float_t v2, float_t v3); +} exp_func_op3; + +vector(motion_storage) + +static bone_data* bone_data_init(bone_data* bone); +static float_t bone_data_limit_angle(float_t angle); +static void bone_data_mult_0(bone_data* a1, int32_t skeleton_select); +static void bone_data_mult_1(bone_data* a1, mat4* parent_mat, bone_data* a3, bool solve_ik); +static bool bone_data_mult_1_ik(bone_data* a1, bone_data* a2); +static void bone_data_mult_1_ik_hands(bone_data* a1, vec3* a2); +static void bone_data_mult_1_ik_hands_2(bone_data* a1, vec3* a2, float_t a3); +static void bone_data_mult_1_ik_legs(bone_data* a1, vec3* a2); +static bool bone_data_mult_1_exp_data(bone_data* a1, bone_node_expression_data* a2, bone_data* a3); +static void bone_data_mult_ik(bone_data* a1, int32_t skeleton_select); + +static float_t* bone_node_get_exp_data_component(bone_node* a1, + size_t index, ex_expression_block_stack_type* type); + +static void bone_data_parent_data_init(bone_data_parent* bone, + rob_chara_data_bone_data* rob_bone_data, bone_database* bone_data); +static void bone_data_parent_load_bone_database(bone_data_parent* bone, + vector_bone_database_bone* bones, vec3* common_translation, vec3* translation); +static void bone_data_parent_load_rob_chara_data(bone_data_parent* bone); +static void bone_data_parent_reset(bone_data_parent* bone); +static void bone_data_parent_free(bone_data_parent* bone); + +static void bone_node_expression_data_mat_set(bone_node_expression_data* data, + vec3* data_scale, mat4* ex_data_mat, mat4* mat); +static void bone_node_expression_data_reset_position_rotation(bone_node_expression_data* data); +static void bone_node_expression_data_reset_scale(bone_node_expression_data* data); +static void bone_node_expression_data_set_position_rotation(bone_node_expression_data* data, + float_t position_x, float_t position_y, float_t position_z, + float_t rotation_x, float_t rotation_y, float_t rotation_z); +static void bone_node_expression_data_set_position_rotation_vec3(bone_node_expression_data* data, + vec3* position, vec3* rotation); + +static ex_cloth_block* ex_cloth_block_init(); +static void ex_cloth_block_draw(ex_cloth_block* cls); +static void ex_cloth_block_reset(ex_cloth_block* cls); +static void ex_cloth_block_update(ex_cloth_block* cls); +static void ex_cloth_block_dispose(ex_cloth_block* cls); +static ex_constraint_block* ex_constraint_block_init(); +static void ex_constraint_block_init_data(ex_constraint_block* cns, rob_chara_data_item_equip_object* itm_eq_obj, + object_skin_block_constraint* cns_data, char* cns_data_name, bone_database* bone_data); +static void ex_constraint_block_data_set(ex_constraint_block* cns); +static void ex_constraint_block_draw(ex_constraint_block* cns); +static void ex_constraint_block_set_default_data(ex_constraint_block* cns); +static void ex_constraint_block_time_step(ex_constraint_block* cns); +static void ex_constraint_block_update(ex_constraint_block* cns); +static void ex_constraint_block_dispose(ex_constraint_block* cns); +static ex_expression_block* ex_expression_block_init(); +static void ex_expression_block_init_data(ex_expression_block* exp, + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_block_expression* exp_data, + char* exp_data_name, object_info a4, chara_index chara_index, bone_database* bone_data); +static void ex_expression_block_data_set(ex_expression_block* exp); +static void ex_expression_block_draw(ex_expression_block* exp); +static void ex_expression_block_set_default_data(ex_expression_block* exp); +static void ex_expression_block_time_step(ex_expression_block* exp); +static void ex_expression_block_update(ex_expression_block* exp); +static void ex_expression_block_dispose(ex_expression_block* exp); +static float_t ex_expression_block_stack_get_value(ex_expression_block_stack* stack); +static void ex_node_block_init_data(ex_node_block* node, bone_node* bone_node, + ex_node_type type, char* name, rob_chara_data_item_equip_object* itm_eq_obj); +static void ex_node_block_reset(ex_node_block* node); +static void ex_node_block_set_default_data(ex_node_block* node); +static void ex_node_block_free(ex_node_block* node); +static ex_osage_block* ex_osage_block_init(); +static void ex_osage_block_draw(ex_osage_block* osg); +static void ex_osage_block_init_data(ex_osage_block* osg, + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_block_osage* osg_data, + char* osg_data_name, object_skin_osage_node* osg_nodes, bone_node* bone_nodes, + bone_node* ex_data_bone_nodes, object_skin* skin); +static void sub_1405F3E10(ex_osage_block* osg, object_skin_block_osage* osg_data, + object_skin_osage_node* osg_nodes, vector_pair_int32_t_ptr_rob_osage_node* a4, + vector_pair_name_ex_osage_block* a5); +static void ex_osage_block_reset(ex_osage_block* osg); +static void ex_osage_block_set_wind_direction(ex_osage_block* osg); +static void ex_osage_block_update(ex_osage_block* osg); +static void ex_osage_block_dispose(ex_osage_block* osg); + +static float_t exp_abs(float_t v1); +static float_t exp_acos(float_t v1); +static float_t exp_add(float_t v1, float_t v2); +static float_t exp_and(float_t v1, float_t v2); +static float_t exp_asin(float_t v1); +static float_t exp_atan(float_t v1); +static float_t exp_av(float_t v1); +static float_t exp_ceil(float_t v1); +static float_t exp_cond(float_t v1, float_t v2, float_t v3); +static float_t exp_cos(float_t v1); +static float_t exp_div(float_t v1, float_t v2); +static float_t exp_eq(float_t v1, float_t v2); +static float_t exp_exp(float_t v1); +static float_t exp_floor(float_t v1); +static float_t exp_fmod(float_t v1, float_t v2); +static const exp_func_op1* exp_func_op1_find_func(string* name, const exp_func_op1* array); +static const exp_func_op2* exp_func_op2_find_func(string* name, const exp_func_op2* array); +static const exp_func_op3* exp_func_op3_find_func(string* name, const exp_func_op3* array); +static float_t exp_ge(float_t v1, float_t v2); +static float_t exp_gt(float_t v1, float_t v2); +static float_t exp_le(float_t v1, float_t v2); +static float_t exp_log(float_t v1); +static float_t exp_lt(float_t v1, float_t v2); +static float_t exp_max(float_t v1, float_t v2); +static float_t exp_min(float_t v1, float_t v2); +static float_t exp_mul(float_t v1, float_t v2); +static float_t exp_ne(float_t v1, float_t v2); +static float_t exp_neg(float_t v1); +static float_t exp_or(float_t v1, float_t v2); +static float_t exp_pow(float_t v1, float_t v2); +static float_t exp_rand(float_t v1, float_t v2, float_t v3); +static float_t exp_rand_0_1(float_t v1); +static float_t exp_round(float_t v1); +static float_t exp_sin(float_t v1); +static float_t exp_sqrt(float_t v1); +static float_t exp_sub(float_t v1, float_t v2); +static float_t exp_tan(float_t v1); + +static float_t get_osage_gravity_const(); + +static void mot_key_frame_interpolate(mot* a1, float_t frame, float_t* value, + mot_key_set* a4, uint32_t key_set_count, struc_369* a6); +static uint32_t mot_load_last_key_calc(uint16_t keys_count); +static bool mot_data_load_file(mot* a1, mot_data* a2); +static void mot_parent_get_key_set_count_by_bone_database_bones(mot_parent* a1, + vector_bone_database_bone* a2); +static void mot_parent_get_key_set_count(mot_parent* a1, size_t motion_bone_count, size_t ik_bone_count); +static void mot_parent_init_key_sets(mot_parent* a1, bone_database_skeleton_type type, + size_t motion_bone_count, size_t ik_bone_count); +static void mot_parent_interpolate(mot_parent* a1, float_t frame, + uint32_t key_set_offset, uint32_t key_set_count); +static mot_data* mot_parent_load_file(mot_parent* a1, int32_t motion_id, motion_database* mot_db); +static void mot_parent_reserve_key_sets(mot_parent* a1); +static motion_blend_mot* motion_blend_mot_init(); +static void motion_blend_mot_interpolate(motion_blend_mot* a1); +static void motion_blend_mot_load_bone_data(motion_blend_mot* a1, + rob_chara_data_bone_data* a2, bone_database* bone_data); +static bool motion_blend_mot_interpolate_get_reverse(int32_t* a1); +static void motion_blend_mot_load_file(motion_blend_mot* a1, int32_t motion_id, + bone_database* a3, motion_database* mot_db); +static void motion_blend_mot_mult_mat(motion_blend_mot* a1, mat4* mat); +static void motion_blend_mot_reset(motion_blend_mot* mot_blend_mot); +static void motion_blend_mot_dispose(motion_blend_mot* mot_blend_mot); + +static void osage_coli_set(osage_coli* osg_coli, + skin_param_osage_root_coli* skp_root_coli, mat4* mats); +static void osage_coli_ring_set(osage_coli* osg_coli, + vector_skin_param_osage_root_coli* vec_skp_root_coli, mat4* mats); + +static rob_chara_data_bone_data* rob_chara_data_bone_data_init(); +static void rob_chara_data_bone_data_calculate_bones(rob_chara_data_bone_data* rob_bone_data, + vector_bone_database_bone* bones); +static void rob_chara_data_bone_data_eyes_xrot_adjust(rob_chara_data_bone_data* rob_bone_data, + const struc_241* a2, eyes_adjust* a3); +static float_t rob_chara_data_bone_data_get_frame(rob_chara_data_bone_data* rob_bone_data); +static float_t rob_chara_data_bone_data_get_frame_count(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_get_ik_scale( + rob_chara_data_bone_data* rob_bone_data, bone_database* bone_data); +static mat4* rob_chara_data_bone_data_get_mat(rob_chara_data_bone_data* rob_bone_data, size_t index); +static bone_node* rob_chara_data_bone_data_get_node(rob_chara_data_bone_data* rob_bone_data, size_t index); +static void rob_chara_data_bone_data_ik_scale_calculate( + rob_chara_data_bone_data_ik_scale* ik_scale, vector_bone_data* vec_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_db); +static void rob_chara_data_bone_data_init_data(rob_chara_data_bone_data* rob_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_data); +static void rob_chara_data_bone_data_init_skeleton(rob_chara_data_bone_data* rob_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_data); +static void rob_chara_data_bone_data_interpolate(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_motion_blend_mot_free(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_motion_blend_mot_init(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_motion_blend_mot_list_free(rob_chara_data_bone_data* rob_bone_data, + size_t last_index); +static void rob_chara_data_bone_data_motion_blend_mot_list_init(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_motion_load(rob_chara_data_bone_data* rob_bone_data, + int32_t motion_id, int32_t index, bone_database* bone_data, motion_database* mot_db); +static void rob_chara_data_bone_data_reserve(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_set_frame(rob_chara_data_bone_data* rob_bone_data, float_t frame); +static void rob_chara_data_bone_data_reset(rob_chara_data_bone_data* rob_bone_data); +static void rob_chara_data_bone_data_set_mats(rob_chara_data_bone_data* rob_bone_data, + vector_bone_database_bone* bones); +static void rob_chara_data_bone_data_set_parent_mats(rob_chara_data_bone_data* rob_bone_data, + uint16_t* parent_indices); +static void rob_chara_data_bone_data_set_rotation_y(rob_chara_data_bone_data* rob_bone_data, float_t rotation_y); +static void rob_chara_data_bone_data_update(rob_chara_data_bone_data* rob_bone_data, mat4* mat); +static void rob_chara_data_bone_data_dispose(rob_chara_data_bone_data* rob_bone_data); + +static rob_chara_data_item_equip* rob_chara_data_item_equip_init(); +static void rob_chara_data_item_equip_draw( + rob_chara_data_item_equip* rob_item_equip, int32_t chara_id, render_context* rctx); +static void rob_chara_data_item_equip_get_parent_bone_nodes( + rob_chara_data_item_equip* rob_item_equip, bone_node* bone_nodes, bone_database* bone_data); +static void rob_chara_data_item_equip_load_object_info( + rob_chara_data_item_equip* rob_item_equip, object_info object_info, item_id id, bone_database* bone_data); +static void rob_chara_data_item_equip_object_init(rob_chara_data_item_equip_object* itm_eq_obj); +static void rob_chara_data_item_equip_object_clear_ex_data(rob_chara_data_item_equip_object* itm_eq_obj); +static void rob_chara_data_item_equip_object_draw( + rob_chara_data_item_equip_object* itm_eq_obj, mat4* mat, render_context* rctx); +static int32_t rob_chara_data_item_equip_object_get_bone_index( + rob_chara_data_item_equip_object* itm_eq_obj, char* name, bone_database* bone_data); +static bone_node* rob_chara_data_item_equip_object_get_bone_node( + rob_chara_data_item_equip_object* itm_eq_obj, int32_t bone_index); +static bone_node* rob_chara_data_item_equip_object_get_bone_node_by_name( + rob_chara_data_item_equip_object* itm_eq_obj, char* name, bone_database* bone_data); +static void rob_chara_data_item_equip_object_get_parent_bone_nodes( + rob_chara_data_item_equip_object* itm_eq_obj, bone_node* bone_nodes, bone_database* bone_data); +static void rob_chara_data_item_equip_object_init_data(rob_chara_data_item_equip_object* itm_eq_obj, size_t index); +static void rob_chara_data_item_equip_object_init_ex_data_bone_nodes( + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_ex_data* a2); +static void rob_chara_data_item_equip_object_load_ex_data(rob_chara_data_item_equip_object* itm_eq_obj, + object_skin_ex_data* ex_data, bone_database* bone_data); +static void rob_chara_data_item_equip_object_load_object_info_ex_data( + rob_chara_data_item_equip_object* itm_eq_obj, object_info object_info, + bone_node* bone_nodes, bone_database* bone_data); +static void rob_chara_data_item_equip_object_reset(rob_chara_data_item_equip_object* itm_eq_obj); +static void rob_chara_data_item_equip_object_free(rob_chara_data_item_equip_object* itm_eq_obj); +static void rob_chara_data_item_equip_reset(rob_chara_data_item_equip* rob_item_equip); +static void rob_chara_data_item_equip_dispose(rob_chara_data_item_equip* rob_item_equip); + +static bool rob_chara_data_check_for_ageageagain_module(chara_index chara_index, int32_t module_index); +static void rob_chara_data_load_default_motion(rob_chara_data* rob_chr_data, + bone_database* bone_data, motion_database* mot_db); +static void rob_chara_data_load_default_motion_sub(rob_chara_data* rob_chr_data, int32_t skeleton_select, + int32_t motion_id, bone_database* bone_data, motion_database* mot_db); +static void rob_chara_data_set_draw(rob_chara_data* rob_chr_data, item_id id, bool draw); + +static void rob_osage_init(rob_osage* rob_osg); +static void rob_osage_init_data(rob_osage* rob_osg, + object_skin_block_osage* osg_data, object_skin_osage_node* osg_nodes, + bone_node* ex_data_bone_nodes, object_skin* skin); +static rob_osage_node* rob_osage_get_node(rob_osage* rob_osg, size_t index); +static void rob_osage_node_init(rob_osage_node* node); +static void rob_osage_node_free(rob_osage_node* node); +static void rob_osage_set_coli(rob_osage* rob_osg, mat4* mats); +static void rob_osage_free(rob_osage* rob_osg); + +static void skin_param_init(skin_param* skp); + +vector_func(motion_storage) + +vector_motion_storage motion_storage_data; +rob_chara_data rob_chara_data_array[6]; +extern wind* wind_ptr; + +static const exp_func_op1 exp_func_op1_array[] = { + { "neg" , exp_neg }, + { "sin" , exp_sin }, + { "cos" , exp_cos }, + { "tan" , exp_tan }, + { "abs" , exp_abs }, + { "sqrt" , exp_sqrt }, + { "av" , exp_av }, + { "floor" , exp_floor }, + { "ceil" , exp_ceil }, + { "round" , exp_round }, + { "asin" , exp_asin }, + { "acos" , exp_acos }, + { "atan" , exp_atan }, + { "log" , exp_log }, + { "exp" , exp_exp }, + { "rand_0_1", exp_rand_0_1 }, + { 0 , 0 }, +}; + +static const exp_func_op2 exp_func_op2_array[] = { + { "+" , exp_add }, + { "-" , exp_sub }, + { "*" , exp_mul }, + { "/" , exp_div }, + { "%" , exp_fmod }, + { "==" , exp_eq }, + { ">" , exp_gt }, + { ">=" , exp_ge }, + { "<" , exp_lt }, + { "<=" , exp_le }, + { "!=" , exp_ne }, + { "&&" , exp_and }, + { "||" , exp_or }, + { "min" , exp_min }, + { "max" , exp_max }, + { "fmod", exp_fmod }, + { "pow" , exp_pow }, + { 0 , 0 }, +}; + +static const exp_func_op3 exp_func_op3_array[] = { + { "rand", exp_rand }, + { "cond", exp_cond }, + { 0 , 0 }, +}; + +static const struc_218 stru_140A24B50[] = { + { { 0.02f , -0.005f, 0.0f }, 0.09f , 0xAB, 0 }, + { { 0.17f , -0.02f , 0.03f }, 0.09f , 0x05, 1 }, + { { 0.17f , -0.02f , -0.03f }, 0.09f , 0x05, 1 }, + { { 0.0f , 0.02f , 0.0f }, 0.04f , 0x08, 0 }, + { { 0.005f, 0.0f , 0.08f }, 0.12f , 0x0A, 1 }, + { { 0.03f , 0.0f , 0.015f }, 0.055f, 0x8A, 1 }, + { { 0.15f , 0.0f , 0.01f }, 0.05f , 0x8A, 0 }, + { { 0.05f , 0.0f , 0.01f }, 0.05f , 0x8B, 0 }, + { { 0.17f , 0.0f , 0.015f }, 0.06f , 0x8B, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x8C, 1 }, + { { 0.03f , 0.0f , -0.015f }, 0.055f, 0x67, 1 }, + { { 0.15f , 0.0f , -0.01f }, 0.05f , 0x67, 0 }, + { { 0.05f , 0.0f , -0.01f }, 0.05f , 0x68, 0 }, + { { 0.17f , 0.0f , -0.015f }, 0.06f , 0x68, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x69, 1 }, + { { 0.04f , -0.02f , -0.02f }, 0.13f , 0xB3, 1 }, + { { 0.26f , -0.02f , -0.025f }, 0.09f , 0xB3, 0 }, + { { 0.08f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.28f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.03f , -0.02f , -0.01f }, 0.07f , 0xB5, 0 }, + { { 0.02f , -0.02f , -0.02f }, 0.035f, 0xB6, 0 }, + { { 0.04f , -0.02f , 0.02f }, 0.13f , 0xAD, 1 }, + { { 0.26f , -0.02f , 0.025f }, 0.09f , 0xAD, 0 }, + { { 0.09f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.28f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.03f , -0.02f , 0.01f }, 0.07f , 0xAF, 0 }, + { { 0.02f , -0.02f , 0.02f }, 0.035f, 0xB0, 0 }, +}; + +static const struc_218 stru_140A25090[] = { + { { -0.00391f, -0.08831f, 0.0f }, 0.09f , 0xAB, 0 }, + { { 0.17f , -0.02f , 0.03f }, 0.09f , 0x05, 1 }, + { { 0.17f , -0.02f , -0.03f }, 0.09f , 0x05, 1 }, + { { 0.0f , 0.02f , 0.0f }, 0.04f , 0x08, 0 }, + { { 0.05025f, 0.0f , -0.00181f }, 0.12f , 0x0A, 1 }, + { { 0.03f , 0.0f , 0.015f }, 0.055f, 0x8A, 1 }, + { { 0.15f , 0.0f , 0.01f }, 0.05f , 0x8A, 0 }, + { { 0.05f , 0.0f , 0.01f }, 0.05f , 0x8B, 0 }, + { { 0.17f , 0.0f , 0.015f }, 0.06f , 0x8B, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x8C, 1 }, + { { 0.03f , 0.0f , -0.015f }, 0.055f, 0x67, 1 }, + { { 0.15f , 0.0f , -0.01f }, 0.05f , 0x67, 0 }, + { { 0.05f , 0.0f , -0.01f }, 0.05f , 0x68, 0 }, + { { 0.17f , 0.0f , -0.015f }, 0.06f , 0x68, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x69, 1 }, + { { 0.04f , -0.02f , -0.02f }, 0.13f , 0xB3, 1 }, + { { 0.26f , -0.02f , -0.025f }, 0.09f , 0xB3, 0 }, + { { 0.08f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.28f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.03f , -0.02f , -0.01f }, 0.07f , 0xB5, 0 }, + { { 0.02f , -0.02f , -0.02f }, 0.035f, 0xB6, 0 }, + { { 0.04f , -0.02f , 0.02f }, 0.13f , 0xAD, 1 }, + { { 0.26f , -0.02f , 0.025f }, 0.09f , 0xAD, 0 }, + { { 0.08f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.28f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.03f , -0.02f , 0.01f }, 0.07f , 0xAF, 0 }, + { { 0.02f , -0.02f , 0.02f }, 0.035f, 0xB0, 0 }, +}; + +static const struc_218 stru_140A24E00[] = { + { { 0.02f , -0.005f, 0.0f }, 0.09f , 0xAB, 0 }, + { { 0.165f , -0.02f , 0.015f }, 0.105f, 0x05, 1 }, + { { 0.165f , -0.02f , -0.015f }, 0.105f, 0x05, 1 }, + { { 0.0f , 0.02f , 0.0f }, 0.04f , 0x08, 0 }, + { { 0.005f , 0.0f , 0.08f }, 0.12f , 0x0A, 1 }, + { { 0.03f , 0.0f , 0.015f }, 0.055f, 0x8A, 1 }, + { { 0.15f , 0.0f , 0.01f }, 0.05f , 0x8A, 0 }, + { { 0.05f , 0.0f , 0.01f }, 0.05f , 0x8B, 0 }, + { { 0.17f , 0.0f , 0.015f }, 0.06f , 0x8B, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x8C, 1 }, + { { 0.03f , 0.0f , -0.015f }, 0.055f, 0x67, 1 }, + { { 0.15f , 0.0f , -0.01f }, 0.05f , 0x67, 0 }, + { { 0.05f , 0.0f , -0.01f }, 0.05f , 0x68, 0 }, + { { 0.17f , 0.0f , -0.015f }, 0.06f , 0x68, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x69, 1 }, + { { 0.04f , -0.02f , -0.02f }, 0.13f , 0xB3, 1 }, + { { 0.26f , -0.02f , -0.025f }, 0.09f , 0xB3, 0 }, + { { 0.08f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.28f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.03f , -0.02f , -0.01f }, 0.07f , 0xB5, 0 }, + { { 0.02f , -0.02f , -0.02f }, 0.035f, 0xB6, 0 }, + { { 0.04f , -0.02f , 0.02f }, 0.13f , 0xAD, 1 }, + { { 0.26f , -0.02f , 0.025f }, 0.09f , 0xAD, 0 }, + { { 0.08f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.28f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.03f , -0.02f , 0.01f }, 0.07f , 0xAF, 0 }, + { { 0.02f , -0.02f , 0.02f }, 0.035f, 0xB0, 0 }, +}; + +static const struc_218 stru_140A25340[] = { + { { -0.00391f, -0.08831f, 0.0f }, 0.09f , 0xAB, 0 }, + { { 0.165f , -0.02f , 0.015f }, 0.105f, 0x05, 1 }, + { { 0.165f , -0.02f , -0.015f }, 0.105f, 0x05, 1 }, + { { 0.0f , 0.02f , 0.0f }, 0.04f , 0x08, 0 }, + { { 0.05025f, 0.0f , -0.00181f }, 0.12f , 0x0A, 1 }, + { { 0.03f , 0.0f , 0.015f }, 0.055f, 0x8A, 1 }, + { { 0.15f , 0.0f , 0.01f }, 0.05f , 0x8A, 0 }, + { { 0.05f , 0.0f , 0.01f }, 0.05f , 0x8B, 0 }, + { { 0.17f , 0.0f , 0.015f }, 0.06f , 0x8B, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x8C, 1 }, + { { 0.03f , 0.0f , -0.015f }, 0.055f, 0x67, 1 }, + { { 0.15f , 0.0f , -0.01f }, 0.05f , 0x67, 0 }, + { { 0.05f , 0.0f , -0.01f }, 0.05f , 0x68, 0 }, + { { 0.17f , 0.0f , -0.015f }, 0.06f , 0x68, 0 }, + { { 0.08f , 0.0f , 0.0f }, 0.07f , 0x69, 1 }, + { { 0.04f , -0.02f , -0.02f }, 0.13f , 0xB3, 1 }, + { { 0.26f , -0.02f , -0.025f }, 0.09f , 0xB3, 0 }, + { { 0.08f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.28f , 0.0f , -0.02f }, 0.09f , 0xB4, 0 }, + { { 0.03f , -0.02f , -0.01f }, 0.07f , 0xB5, 0 }, + { { 0.02f , -0.02f , -0.02f }, 0.035f, 0xB6, 0 }, + { { 0.04f , -0.02f , 0.02f }, 0.13f , 0xAD, 1 }, + { { 0.26f , -0.02f , 0.025f }, 0.09f , 0xAD, 0 }, + { { 0.08f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.28f , 0.0f , 0.02f }, 0.09f , 0xAE, 0 }, + { { 0.03f , -0.02f , 0.01f }, 0.07f , 0xAF, 0 }, + { { 0.02f , -0.02f , 0.02f }, 0.035f, 0xB0, 0 }, +}; + +static const chara_init_data chara_init_data_array[] = { + { + 0x0000, BONE_DATABASE_SKELETON_MIKU, + { 0x00F7, 0x0000 }, 1, + stru_140A24B50, stru_140A25090, + 1, 0, { 0x01, 0x01, 0x1E, 0x1D }, + { + { 0x00F7, 0x0000 }, + { 0x011D, 0x0000 }, + { 0x011E, 0x0000 }, + { 0x011F, 0x0000 }, + { 0x0120, 0x0000 }, + { 0x0121, 0x0000 }, + { 0x0122, 0x0000 }, + { 0x020F, 0x0000 }, + { 0x0251, 0x0000 }, + }, + { + { -1, -1 }, + { 0x0124, 0x0000 }, + { 0x0123, 0x0000 }, + { 0x0125, 0x0000 }, + { 0x0126, 0x0000 }, + { 0x0127, 0x0000 }, + { 0x0128, 0x0000 }, + { 0x0259, 0x0000 }, + { 0x0254, 0x0000 }, + { 0x0252, 0x0000 }, + { 0x0253, 0x0000 }, + { 0x0255, 0x0000 }, + { 0x0256, 0x0000 }, + { 0x0258, 0x0000 }, + { 0x0257, 0x0000 }, + }, + }, + { + 0x0107, BONE_DATABASE_SKELETON_RIN, + { 0x004A, 0x0107 }, 9, + stru_140A24B50, stru_140A25090, + 1, 0, { 0x02, 0x02, 0x01, 0x01 }, + { + { 0x004A, 0x0107 }, + { 0x004E, 0x0107 }, + { 0x004F, 0x0107 }, + { 0x0050, 0x0107 }, + { 0x0051, 0x0107 }, + { 0x0052, 0x0107 }, + { 0x0053, 0x0107 }, + { 0x00A6, 0x0107 }, + { 0x00C3, 0x0107 }, + }, + { + { -1, -1 }, + { 0x0055, 0x0107 }, + { 0x0054, 0x0107 }, + { 0x0056, 0x0107 }, + { 0x0057, 0x0107 }, + { 0x0058, 0x0107 }, + { 0x0059, 0x0107 }, + { 0x00CB, 0x0107 }, + { 0x00C6, 0x0107 }, + { 0x00C4, 0x0107 }, + { 0x00C5, 0x0107 }, + { 0x00C7, 0x0107 }, + { 0x00C8, 0x0107 }, + { 0x00CA, 0x0107 }, + { 0x00C9, 0x0107 }, + }, + }, + { + 0x0105, BONE_DATABASE_SKELETON_LEN, + { 0x0040, 0x0105 }, 5, + stru_140A24B50, stru_140A25090, + 0, 0, { 0x02, 0x03, 0x01, 0x01 }, + { + { 0x0040, 0x0105 }, + { 0x0041, 0x0105 }, + { 0x0042, 0x0105 }, + { 0x0043, 0x0105 }, + { 0x0044, 0x0105 }, + { 0x0045, 0x0105 }, + { 0x0046, 0x0105 }, + { 0x007F, 0x0105 }, + { 0x0098, 0x0105 }, + }, + { + { -1, -1 }, + { 0x0048, 0x0105 }, + { 0x0047, 0x0105 }, + { 0x0049, 0x0105 }, + { 0x004A, 0x0105 }, + { 0x004B, 0x0105 }, + { 0x004C, 0x0105 }, + { 0x00A0, 0x0105 }, + { 0x009B, 0x0105 }, + { 0x0099, 0x0105 }, + { 0x009A, 0x0105 }, + { 0x009C, 0x0105 }, + { 0x009D, 0x0105 }, + { 0x009F, 0x0105 }, + { 0x009E, 0x0105 }, + }, + }, + { + 0x0106, BONE_DATABASE_SKELETON_LUKA, + { 0x004C, 0x0106 }, 6, + stru_140A24E00, stru_140A25340, + 0, 0, { 0x01, 0x04, 0x01, 0x01 }, + { + { 0x004C, 0x0106 }, + { 0x004D, 0x0106 }, + { 0x004E, 0x0106 }, + { 0x004F, 0x0106 }, + { 0x0050, 0x0106 }, + { 0x0051, 0x0106 }, + { 0x0052, 0x0106 }, + { 0x008C, 0x0106 }, + { 0x00A1, 0x0106 }, + }, + { + { -1, -1 }, + { 0x0054, 0x0106 }, + { 0x0053, 0x0106 }, + { 0x0055, 0x0106 }, + { 0x0056, 0x0106 }, + { 0x0057, 0x0106 }, + { 0x0058, 0x0106 }, + { 0x00A9, 0x0106 }, + { 0x00A4, 0x0106 }, + { 0x00A2, 0x0106 }, + { 0x00A3, 0x0106 }, + { 0x00A5, 0x0106 }, + { 0x00A6, 0x0106 }, + { 0x00A8, 0x0106 }, + { 0x00A7, 0x0106 }, + }, + }, + { + 0x0108, BONE_DATABASE_SKELETON_NERU, + { 0x0019, 0x0108 }, 8, + stru_140A24B50, stru_140A25090, + 0, 0, { 0x02, 0x02, 0x02, 0x02 }, + { + { 0x0019, 0x0108 }, + { 0x001A, 0x0108 }, + { 0x001B, 0x0108 }, + { 0x001C, 0x0108 }, + { 0x001D, 0x0108 }, + { 0x001E, 0x0108 }, + { 0x001F, 0x0108 }, + { 0x002A, 0x0108 }, + { 0x002B, 0x0108 }, + }, + { + { -1, -1 }, + { 0x0021, 0x0108 }, + { 0x0020, 0x0108 }, + { 0x0022, 0x0108 }, + { 0x0023, 0x0108 }, + { 0x0024, 0x0108 }, + { 0x0025, 0x0108 }, + { 0x0033, 0x0108 }, + { 0x002E, 0x0108 }, + { 0x002C, 0x0108 }, + { 0x002D, 0x0108 }, + { 0x002F, 0x0108 }, + { 0x0030, 0x0108 }, + { 0x0032, 0x0108 }, + { 0x0031, 0x0108 }, + }, + }, + { + 0x0109, BONE_DATABASE_SKELETON_HAKU, + { 0x001F, 0x0109 }, 3, + stru_140A24E00, stru_140A25340, + 1, 0, { 0x01, 0x01, 0x02, 0x02 }, + { + { 0x001F, 0x0109 }, + { 0x0020, 0x0109 }, + { 0x0021, 0x0109 }, + { 0x0022, 0x0109 }, + { 0x0023, 0x0109 }, + { 0x0024, 0x0109 }, + { 0x0025, 0x0109 }, + { 0x0032, 0x0109 }, + { 0x0033, 0x0109 }, + }, + { + { -1, -1 }, + { 0x0027, 0x0109 }, + { 0x0026, 0x0109 }, + { 0x0028, 0x0109 }, + { 0x0029, 0x0109 }, + { 0x002A, 0x0109 }, + { 0x002B, 0x0109 }, + { 0x003B, 0x0109 }, + { 0x0036, 0x0109 }, + { 0x0034, 0x0109 }, + { 0x0035, 0x0109 }, + { 0x0037, 0x0109 }, + { 0x0038, 0x0109 }, + { 0x003A, 0x0109 }, + { 0x0039, 0x0109 }, + }, + }, + { + 0x010D, BONE_DATABASE_SKELETON_KAITO, + { 0x003C, 0x010D}, 4, + stru_140A24B50, stru_140A25090, + 0, 0, { 0x00, 0x00, 0x01, 0x01 }, + { + { 0x003C, 0x010D }, + { 0x0050, 0x010D }, + { 0x003D, 0x010D }, + { 0x003E, 0x010D }, + { 0x003F, 0x010D }, + { 0x0040, 0x010D }, + { 0x0041, 0x010D }, + { 0x006D, 0x010D }, + { 0x0077, 0x010D }, + }, + { + { -1, -1 }, + { 0x0044, 0x010D }, + { 0x0043, 0x010D }, + { 0x0045, 0x010D }, + { 0x0046, 0x010D }, + { 0x0047, 0x010D }, + { 0x0048, 0x010D }, + { 0x007F, 0x010D }, + { 0x007A, 0x010D }, + { 0x0078, 0x010D }, + { 0x0079, 0x010D }, + { 0x007B, 0x010D }, + { 0x007C, 0x010D }, + { 0x007E, 0x010D }, + { 0x007D, 0x010D }, + }, + }, + { + 0x010E, BONE_DATABASE_SKELETON_MEIKO, + { 0x0040, 0x010E }, 7, + stru_140A24E00, stru_140A25340, + 1, 0, { 0x00, 0x00, 0x01, 0x01 }, + { + { 0x0040, 0x010E }, + { 0x0041, 0x010E }, + { 0x0042, 0x010E }, + { 0x0043, 0x010E }, + { 0x0044, 0x010E }, + { 0x0045, 0x010E }, + { 0x0046, 0x010E }, + { 0x007B, 0x010E }, + { 0x0085, 0x010E }, + }, + { + { -1, -1 }, + { 0x0048, 0x010E }, + { 0x0047, 0x010E }, + { 0x0049, 0x010E }, + { 0x004A, 0x010E }, + { 0x004B, 0x010E }, + { 0x004C, 0x010E }, + { 0x008D, 0x010E }, + { 0x0088, 0x010E }, + { 0x0086, 0x010E }, + { 0x0087, 0x010E }, + { 0x0089, 0x010E }, + { 0x008A, 0x010E }, + { 0x008C, 0x010E }, + { 0x008B, 0x010E }, + }, + }, + { + 0x010F, BONE_DATABASE_SKELETON_SAKINE, + { 0x001A, 0x010F }, 10, + stru_140A24E00, stru_140A25340, + 1, 0, { 0x01, 0x01, 0x02, 0x02 }, + { + { 0x001A, 0x010F }, + { 0x001B, 0x010F }, + { 0x001C, 0x010F }, + { 0x001D, 0x010F }, + { 0x001E, 0x010F }, + { 0x001F, 0x010F }, + { 0x0020, 0x010F }, + { 0x0031, 0x010F }, + { 0x0033, 0x010F }, + }, + { + { -1, -1 }, + { 0x0022, 0x010F }, + { 0x0021, 0x010F }, + { 0x0023, 0x010F }, + { 0x0024, 0x010F }, + { 0x0025, 0x010F }, + { 0x0026, 0x010F }, + { 0x003B, 0x010F }, + { 0x0036, 0x010F }, + { 0x0034, 0x010F }, + { 0x0035, 0x010F }, + { 0x0037, 0x010F }, + { 0x0038, 0x010F }, + { 0x003A, 0x010F }, + { 0x0039, 0x010F }, + }, + }, + { + 0x063D, BONE_DATABASE_SKELETON_TETO, + { 0x0000, 0x063D }, 467, + stru_140A24B50, stru_140A25090, + 1, 0, { 0x01, 0x01, 0x02, 0x02 }, + { + { 0x0000, 0x063D }, + { 0x0001, 0x063D }, + { 0x0002, 0x063D }, + { 0x0003, 0x063D }, + { 0x0004, 0x063D }, + { 0x0005, 0x063D }, + { 0x0006, 0x063D }, + { 0x0012, 0x063D }, + { 0x0013, 0x063D }, + }, + { + { -1, -1 }, + { 0x0008, 0x063D }, + { 0x0007, 0x063D }, + { 0x0009, 0x063D }, + { 0x000A, 0x063D }, + { 0x000B, 0x063D }, + { 0x000C, 0x063D }, + { 0x001B, 0x063D }, + { 0x0016, 0x063D }, + { 0x0014, 0x063D }, + { 0x0015, 0x063D }, + { 0x0017, 0x063D }, + { 0x0018, 0x063D }, + { 0x001A, 0x063D }, + { 0x0019, 0x063D }, + }, + } +}; + +static const struc_241 chara_some_data_array[] = { + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0436332300305367f, 0.0610865242779255f, -0.0802851468324661f, 0.113446399569511f, + 0.0148999998345971f, -0.0212999992072582f, 0.0f, 1.0f, + 1.0f, -3.8f, 6.0f, -3.8f, + 6.0f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0750491619110107f, 0.104719758033752f, -0.0733038261532783f, 0.125663697719574f, + 0.033500000834465f, -0.0111999996006489f, 0.0f, 1.0f, + 1.0f, -5.5f, 10.0f, -5.5f, + 6.5f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0837758034467697f, 0.0855211317539215f, -0.104719758033752f, 0.120427720248699f, + 0.0166999995708466f, -0.00540000014007092f, 0.0f, 1.0f, + 1.0f, -6.5f, 6.0f, -6.0f, + 2.0f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0349065847694874f, 0.0698131695389748f, -0.0872664600610733f, 0.113446399569511f, + 0.011400000192225f, 0.00810000021010637f, 0.0f, 1.0f, + 1.0f, -3.5f, 6.0f, -3.5f, + 6.0f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0349065847694874f, 0.0733038261532783f, -0.0907571166753769f, 0.13962633907795f, + 0.0151000004261732f, -0.0439999997615814f, 0.0f, 1.0f, + 1.0f, -2.6f, 6.0f, -2.6f, + 6.0f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0523598790168762f, 0.122173048555851f, -0.0872664600610733f, 0.130899697542191f, + 0.0221999995410442f, -0.000199999994947575f, 0.0f, 1.0f, + 1.0f, -4.0f, 7.5f, -3.5f, + 6.0f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0733038261532783f, 0.101229101419449f, -0.0785398185253143f, 0.113446399569511f, + 0.025000000372529f, -0.0230999998748302f, 0.0f, 1.0f, + 1.0f, -4.0f, 6.0f, -3.8f, + 3.5f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0663225129246712f, 0.0593411959707737f, -0.0785398185253143f, 0.113446399569511f, + 0.0118000004440546f, -0.00510000018402934f, 0.0f, 1.0f, + 1.0f, -5.6f, 6.0f, -5.6f, + 5.5f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0645771846175194f, 0.0663225129246712f, -0.0698131695389748f, 0.113446399569511f, + 0.0229000002145767f, -0.0148999998345971f, 0.0f, 1.0f, + 1.0f, -5.0f, 4.0f, -5.0f, + 2.5f, + }, + { + -0.0610865242779255f, 0.104719758033752f, -0.0802851468324661f, 0.113446399569511f, + -0.0698131695389748f, 0.0698131695389748f, -0.113446399569511f, 0.122173048555851f, + 0.0137000000104308f, -0.00800000037997961f, 0.0f, 1.0f, + 1.0f, -5.5f, 6.0f, -5.0f, + 4.0f, + }, +}; + +static const skeleton_rotation_offset skeleton_rotation_offset_array[] = { + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 0, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 0, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, (float_t)(-M_PI * 2.0), 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 0, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { (float_t)M_PI, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 1, { (float_t)-M_PI, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 0, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { (float_t)M_PI, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 1, { (float_t)-M_PI, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 0, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 1, 1, 0, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, + { 0, 1, 1, { 0.0f, 0.0f, 0.0f }, }, +}; + +static const ex_node_block_vtbl ex_constraint_block_vftable = { + (void*)ex_constraint_block_dispose, + //(void*)sub_1405F35F0, + (void*)ex_constraint_block_set_default_data, + //(void*)sub_1405F4960, + (void*)ex_constraint_block_update, + //(void*)sub_1405F2440, + (void*)ex_constraint_block_draw, + (void*)ex_node_block_reset, + //(void*)sub_1405F2820, + //(void*)sub_1405F4610, + //(void*)sub_1405F4700, + //(void*)sub_1405F48E0, +}; + +static const ex_node_block_vtbl ex_expression_block_vftable = { + (void*)ex_expression_block_dispose, + //(void*)sub_1405F3610, + (void*)ex_expression_block_set_default_data, + //(void*)sub_1405F49A0, + (void*)ex_expression_block_update, + //(void*)sub_1405F2450, + (void*)ex_expression_block_draw, + (void*)ex_node_block_reset, + //(void*)sub_1405F2830, + //(void*)sub_1405F4620, + //(void*)sub_1405F4710, + //(void*)sub_1405F48E0, +}; + +static const ex_node_block_vtbl ex_osage_block_vftable = { + (void*)ex_osage_block_dispose, + //(void*)sub_1405F3640, + (void*)ex_node_block_set_default_data, + //(void*)sub_1405F49F0, + (void*)ex_osage_block_update, + //(void*)sub_1405F2470, + (void*)ex_osage_block_draw, + (void*)ex_osage_block_reset, + //(void*)sub_1405F2860, + //(void*)sub_1405F4640, + //(void*)sub_1405F4730, + //(void*)sub_1405F48F0, +}; + +static const ex_node_block_vtbl ex_cloth_block_vftable = { + (void*)ex_cloth_block_dispose, + //(void*)sub_1405F35B0, + (void*)ex_node_block_set_default_data, + //(void*)sub_1405F4950, + (void*)ex_cloth_block_update, + //(void*)sub_1405F2420, + (void*)ex_cloth_block_draw, + (void*)ex_cloth_block_reset, + //(void*)sub_1405F2810, + //(void*)sub_1405F45F0, + //(void*)sub_1405F46E0, + //(void*)sub_1405F48E0, +}; + +chara_init_data* chara_init_data_get(chara_index chara_index) { + if (chara_index >= CHARA_MIKU && chara_index <= CHARA_TETO) + return (chara_init_data*)&chara_init_data_array[chara_index]; + return 0; +} + +void motion_set_load_motion(uint32_t set, string* motion_name, motion_database* mot_db) { + if (motion_storage_get_motion_set(set)) { + motion_storage_append_mot_set(set); + return; + } + + motion_set_info* set_info = motion_database_get_motion_set_by_id(mot_db, set); + if (!set_info) + return; + + if (!motion_name) + motion_name = &set_info->name; + + string file; + string_init_length(&file, "mot_", 4); + string_add_length(&file, string_data(motion_name), motion_name->length); + string_add_length(&file, ".farc", 5); + + mot_set_farc msf; + mot_init(&msf); + data_struct_load_file(&data_list[DATA_AFT], &msf, + "rom\\rob\\", string_data(&file), mot_load_file); + if (msf.ready && msf.vec.end - msf.vec.begin > 0) { + motion_storage_insert_motion_set(&msf.vec.begin[0], set); + memset(&msf.vec.begin[0], 0, sizeof(mot_set)); + } + mot_free(&msf); + + string_free(&file); +} + +void motion_set_unload(uint32_t set) { + motion_storage_delete_motion_set(set); +} + +void rob_chara_data_init(rob_chara_data* rob_chr_data) { + rob_chr_data->bone_data = rob_chara_data_bone_data_init(); + rob_chr_data->item_equip = rob_chara_data_item_equip_init(); + rob_chara_pv_data_init(&rob_chr_data->pv_data); +} + +void rob_chara_data_calc(rob_chara_data* rob_chr_data) { + if (rob_chara_data_bone_data_get_frame(rob_chr_data->bone_data) < 0.0) + rob_chara_data_bone_data_set_frame(rob_chr_data->bone_data, 0.0); + + float_t frame = rob_chara_data_bone_data_get_frame(rob_chr_data->bone_data); + float_t frame_count = rob_chara_data_bone_data_get_frame_count(rob_chr_data->bone_data); + if (frame > frame_count) + rob_chara_data_bone_data_set_frame(rob_chr_data->bone_data, frame_count); + + mat4_get_translation(&rob_chr_data->bone_data->mats.begin[MOTION_BONE_KL_KOSI_ETC_WJ], + &rob_chr_data->item_equip->position); + //rob_chara_data_get_trans_scale(rob_chr_data, 0, &rob_chr_data->item_equip->position); + + if (!rob_chr_data->item_equip->field_D8) { + rob_chara_data_item_equip* rob_item_equip = rob_chr_data->item_equip; + for (int32_t i = rob_item_equip->first_item_equip_object; + i < rob_item_equip->max_item_equip_object; i++) { + rob_chara_data_item_equip_object* itm_eq_obj = &rob_item_equip->item_equip_object[i]; + + if (itm_eq_obj->field_B0 > 0) + itm_eq_obj->field_B0 = 0; + + for (ex_node_block** i = itm_eq_obj->node_blocks.begin; + i != itm_eq_obj->node_blocks.end; i++) + (*i)->vftable->set_default_data(*i); + + if (itm_eq_obj->field_1C8) + itm_eq_obj->field_1C8 = 0; + else { + for (ex_node_block** i = itm_eq_obj->node_blocks.begin; + i != itm_eq_obj->node_blocks.end; i++) + (*i)->vftable->update(*i); + } + } + } + + /*if (rob_chara_data_check_for_ageageagain_module(rob_chr_data->chara_index, rob_chr_data->module_index)) { + sub_140543520(rob_chr_data->chara_id, 1, rob_chr_data->item_equip->osage_phys_step); + sub_14054FC90(rob_chr_data, 1u, "j_tail_l_006_wj"); + sub_140543520(rob_chr_data->chara_id, 2, rob_chr_data->item_equip->osage_phys_step); + sub_14054FC90(rob_chr_data, 2u, "j_tail_r_006_wj"); + }*/ +} + +void rob_chara_data_draw(rob_chara_data* rob_chr_data, render_context* rctx) { + rob_chr_data->item_equip->texture_color_coeff = vec4u_identity; + rob_chr_data->item_equip->mat = mat4u_identity; + rob_chara_data_item_equip_draw(rob_chr_data->item_equip, rob_chr_data->chara_id, rctx); +} + +mat4* rob_chara_data_get_bone_data_mat(rob_chara_data* chara, size_t index) { + return rob_chara_data_bone_data_get_mat(chara->bone_data, index); +} + +float_t rob_chara_data_get_frame(rob_chara_data* rob_chr_data) { + return rob_chara_data_bone_data_get_frame(rob_chr_data->bone_data); +} + +float_t rob_chara_data_get_frame_count(rob_chara_data* rob_chr_data) { + return rob_chara_data_bone_data_get_frame_count(rob_chr_data->bone_data); +} + +void rob_chara_data_load_motion(rob_chara_data* rob_chr_data, int32_t motion_id, + int32_t index, bone_database* bone_data, motion_database* mot_db) { + rob_chara_data_bone_data_motion_load(rob_chr_data->bone_data, motion_id, index, bone_data, mot_db); +} + +void rob_chara_data_reload_items(rob_chara_data* rob_chr_data, + item_sub_data* sub_data, bone_database* bone_data) { + static const item_sub_id array0[] = { + ITEM_SUB_ZUJO, + ITEM_SUB_KAMI, + ITEM_SUB_HITAI, + ITEM_SUB_ME, + ITEM_SUB_MEGANE, + ITEM_SUB_MIMI, + ITEM_SUB_KUCHI, + ITEM_SUB_MAKI, + ITEM_SUB_KUBI, + ITEM_SUB_INNER, + ITEM_SUB_JOHA_MAE, + ITEM_SUB_JOHA_USHIRO, + ITEM_SUB_HADA, + ITEM_SUB_U_UDE, + ITEM_SUB_L_UDE, + ITEM_SUB_TE, + ITEM_SUB_BELT, + ITEM_SUB_ASI, + ITEM_SUB_SUNE, + ITEM_SUB_HEAD, + ITEM_SUB_MAX, + }; + + static const item_sub_id array1[] = { + ITEM_SUB_KATA, + ITEM_SUB_PANTS, + ITEM_SUB_MAX, + }; + + static const item_sub_id array2[] = { + ITEM_SUB_COSI, + ITEM_SUB_OUTER, + ITEM_SUB_MAX, + }; + + static const item_sub_id array3[] = { + ITEM_SUB_KUTSU, + ITEM_SUB_MAX + }; + + static const item_id array4[] = { + ITEM_ZUJO, + ITEM_KAMI, + ITEM_NONE, + ITEM_NONE, + ITEM_MEGANE, + ITEM_NONE, + ITEM_KUCHI, + ITEM_NONE, + ITEM_KUBI, + ITEM_NONE, + ITEM_OUTER, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + ITEM_JOHA_USHIRO, + ITEM_NONE, + ITEM_NONE, + ITEM_PANTS, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + ITEM_NONE, + }; + + rob_chara_data_item_equip* rob_item_equip = rob_chr_data->item_equip; + object_info base_face = chara_init_data_array[rob_chr_data->chara_index].base_face; + rob_chara_data_item_equip_load_object_info(rob_item_equip, base_face, ITEM_ATAMA, bone_data); + + for (int32_t i = 0; array0[i] != ITEM_SUB_MAX; i++) { + item_sub_id sub_id = array0[i]; + item_id id = array4[sub_id]; + + object_info obj_info = object_info_null; + int32_t no = sub_data->data[sub_id]; + if (sub_id == ITEM_SUB_HEAD) { + if (no == 981) + obj_info = (object_info){ 912, 3797 }; + } + else if (sub_id == ITEM_SUB_KAMI) { + if (id == ITEM_NONE) + continue; + + if (no == 500) + obj_info = (object_info){ 84, 6 }; + else if (no == 681) + obj_info = (object_info){ 913, 3796 }; + } + rob_chara_data_item_equip_load_object_info(rob_item_equip, obj_info, id, bone_data); + } + + for (int32_t i = 0; array1[i] != ITEM_SUB_MAX; i++) { + item_sub_id sub_id = array1[i]; + + object_info obj_info = object_info_null; + int32_t no = sub_data->data[sub_id]; + if (sub_id == ITEM_SUB_KATA) { + if (no == 301) + obj_info = (object_info){ 306, 953 }; + else if (no == 181) + obj_info = (object_info){ 915, 3794 }; + rob_chara_data_item_equip_load_object_info(rob_item_equip, obj_info, ITEM_ITEM09, bone_data); + } + } + + for (int32_t i = 0; array2[i] != ITEM_SUB_MAX; i++) { + item_sub_id sub_id = array2[i]; + item_id id = array4[sub_id]; + if (id == ITEM_NONE) + continue; + + object_info obj_info = object_info_null; + int32_t no = sub_data->data[sub_id]; + if (sub_id == ITEM_SUB_OUTER) + if (no == 1) + obj_info = (object_info){ 7, 4 }; + else if (no == 481) + obj_info = (object_info){ 914, 3795 }; + rob_chara_data_item_equip_load_object_info(rob_item_equip, obj_info, id, bone_data); + } +} + +void rob_chara_data_reset(rob_chara_data* rob_chr_data, rob_chara_pv_data* pv_data, + bone_database* bone_data, motion_database* mot_db) { + rob_chara_data_bone_data_reset(rob_chr_data->bone_data); + rob_chara_data_bone_data_init_data(rob_chr_data->bone_data, + BONE_DATABASE_SKELETON_COMMON, rob_chr_data->chara_init_data->skeleton_type, bone_data); + rob_chara_data_item_equip_get_parent_bone_nodes(rob_chr_data->item_equip, + rob_chara_data_bone_data_get_node(rob_chr_data->bone_data, 0), bone_data); + rob_chara_data_bone_data_eyes_xrot_adjust(rob_chr_data->bone_data, chara_some_data_array, &pv_data->eyes_adjust); + rob_chara_data_bone_data_get_ik_scale(rob_chr_data->bone_data, bone_data); + rob_chara_data_load_default_motion(rob_chr_data, bone_data, mot_db); + int32_t motion_id = 195; //rob_cmn_mottbl_get_motion_index(rob_chr_data, 0); + rob_chara_data_load_motion(rob_chr_data, motion_id, 0, bone_data, mot_db); + rob_chara_data_set_draw(rob_chr_data, ITEM_MAX, true); +} + +void rob_chara_data_set(rob_chara_data* rob_chr_data, int8_t chara_id, + chara_index chara_index, uint32_t module_index, rob_chara_pv_data* pv_data) { + rob_chr_data->chara_id = chara_id; + rob_chr_data->chara_index = chara_index; + rob_chr_data->module_index = module_index; + rob_chr_data->pv_data = *pv_data; + rob_chr_data->chara_init_data = chara_init_data_get(chara_index); +} + +void rob_chara_data_set_frame(rob_chara_data* rob_chr_data, float_t frame) { + rob_chara_data_bone_data_set_frame(rob_chr_data->bone_data, frame); + rob_chara_data_bone_data_interpolate(rob_chr_data->bone_data); + rob_chara_data_bone_data_update(rob_chr_data->bone_data, 0); +} + +void rob_chara_data_free(rob_chara_data* rob_chr_data) { + if (rob_chr_data->bone_data) + rob_chara_data_bone_data_dispose(rob_chr_data->bone_data); + + if (rob_chr_data->item_equip) + rob_chara_data_item_equip_dispose(rob_chr_data->item_equip); +} + +static bone_data* bone_data_init(bone_data* bone) { + memset(bone, 0, sizeof(bone_data)); + bone->eyes_xrot_adjust_neg = 1.0f; + bone->eyes_xrot_adjust_pos = 1.0f; + return bone; +} + +static float_t bone_data_limit_angle(float_t angle) { + bool neg; + if (angle < 0.0f) { + angle = -angle; + neg = true; + } + else + neg = false; + + angle = fmodf(angle + (float_t)M_PI, (float_t)(M_PI * 2.0)) - (float_t)M_PI; + if (neg) + return -angle; + else + return angle; +} + +static void bone_data_mult_0(bone_data* a1, int32_t skeleton_select) { + if (a1->flags != 0) + return; + + mat4 mat; + if (a1->has_parent) + mat = *a1->parent_mat; + else + mat = mat4_identity; + + if (a1->type == BONE_DATABASE_BONE_POSITION) { + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + a1->rot_mat[0] = mat4u_identity; + } + else if (a1->type == BONE_DATABASE_BONE_TYPE_1) { + mat4_mult_vec3_inv(&mat, &a1->trans, &a1->trans); + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + a1->rot_mat[0] = mat4u_identity; + } + else { + mat4 rot_mat; + if (a1->type == BONE_DATABASE_BONE_POSITION_ROTATION) { + mat4u_to_mat4(&a1->rot_mat[0], &rot_mat); + mat4_rotate_z_mult(&rot_mat, a1->rotation.z, &rot_mat); + } + else { + a1->trans = a1->base_translation[skeleton_select]; + mat4_rotate_z(a1->rotation.z, &rot_mat); + } + + mat4_rotate_y_mult(&rot_mat, a1->rotation.y, &rot_mat); + + if (a1->motion_bone_index == MOTION_BONE_KL_EYE_L + || a1->motion_bone_index == MOTION_BONE_KL_EYE_R) { + if (a1->rotation.x > 0.0) + a1->rotation.x *= a1->eyes_xrot_adjust_pos; + else if (a1->rotation.x < 0.0) + a1->rotation.x *= a1->eyes_xrot_adjust_neg; + } + + mat4_rotate_x_mult(&rot_mat, a1->rotation.x, &rot_mat); + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + mat4_mult(&rot_mat, &mat, &mat); + mat4_to_mat4u(&rot_mat, &a1->rot_mat[0]); + } + + *a1->node[0].mat = mat; + + bone_data_mult_ik(a1, skeleton_select); +} + +static void bone_data_mult_1(bone_data* a1, mat4* parent_mat, bone_data* a3, bool solve_ik) { + mat4 mat; + mat4 rot_mat; + if (a1->has_parent) + mat = *a1->parent_mat; + else + mat = *parent_mat; + + if (a1->type != BONE_DATABASE_BONE_TYPE_1 && a1->type != BONE_DATABASE_BONE_POSITION) { + if (a1->type != BONE_DATABASE_BONE_POSITION_ROTATION) + a1->trans = a1->base_translation[1]; + + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + if (solve_ik) { + a1->node[0].exp_data.rotation = vec3_null; + if (!a1->flags) { + mat4u_to_mat4(&a1->rot_mat[0], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[0].exp_data.rotation); + } + else if (bone_data_mult_1_exp_data(a1, &a1->node[0].exp_data, a3)) { + vec3 rotation = a1->node[0].exp_data.rotation; + mat4_rotate(rotation.x, rotation.y, rotation.z, &rot_mat); + mat4_to_mat4u(&rot_mat, &a1->rot_mat[0]); + } + else { + *a1->node[0].mat = mat; + + if (bone_data_mult_1_ik(a1, a3)) { + mat4_invrot_normalized(&mat, &rot_mat); + mat4_mult(a1->node[0].mat, &rot_mat, &rot_mat); + mat4_clear_trans(&rot_mat, &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[0].exp_data.rotation); + mat4_to_mat4u(&rot_mat, &a1->rot_mat[0]); + } + else + a1->rot_mat[0] = mat4u_identity; + } + } + + mat4u_to_mat4(&a1->rot_mat[0], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + } + else { + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + if (solve_ik) + a1->node[0].exp_data.rotation = vec3_null; + } + + *a1->node[0].mat = mat; + if (solve_ik) { + a1->node[0].exp_data.position = a1->trans; + bone_node_expression_data_reset_scale(&a1->node[0].exp_data); + } + + if (a1->type < BONE_DATABASE_BONE_HEAD_IK_ROTATION) + return; + + mat4u_to_mat4(&a1->rot_mat[1], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + *a1->node[1].mat = mat; + mat4_translate_mult(&mat, a1->ik_segment_length[1], 0.0f, 0.0f, &mat); + + if (a1->type == BONE_DATABASE_BONE_HEAD_IK_ROTATION) { + *a1->node[2].mat = mat; + if (!solve_ik) + return; + + a1->node[1].exp_data.position = vec3_null; + mat4u_to_mat4(&a1->rot_mat[1], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[1].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[1].exp_data); + bone_node_expression_data_set_position_rotation(&a1->node[2].exp_data, + a1->ik_segment_length[1], 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + else { + mat4u_to_mat4(&a1->rot_mat[2], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + *a1->node[2].mat = mat; + mat4_translate_mult(&mat, a1->ik_2nd_segment_length[1], 0.0f, 0.0f, &mat); + *a1->node[3].mat = mat; + if (!solve_ik) + return; + + a1->node[1].exp_data.position = vec3_null; + mat4u_to_mat4(&a1->rot_mat[1], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[1].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[1].exp_data); + a1->node[2].exp_data.position.x = a1->ik_segment_length[1]; + *(vec2*)&a1->node[2].exp_data.position.y = vec2_null; + mat4u_to_mat4(&a1->rot_mat[2], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[2].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[2].exp_data); + bone_node_expression_data_set_position_rotation(&a1->node[3].exp_data, + a1->ik_2nd_segment_length[1], 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } +} + +static bool bone_data_mult_1_ik(bone_data* a1, bone_data* a2) { + bone_node* v5; + vec3 v30; + + switch (a1->motion_bone_index) { + case MOTION_BONE_N_SKATA_L_WJ_CD_EX: + v5 = a2[MOTION_BONE_C_KATA_L].node; + mat4_get_translation(v5[2].mat, &v30); + bone_data_mult_1_ik_hands(a1, &v30); + break; + case MOTION_BONE_N_SKATA_R_WJ_CD_EX: + v5 = a2[MOTION_BONE_C_KATA_R].node; + mat4_get_translation(v5[2].mat, &v30); + bone_data_mult_1_ik_hands(a1, &v30); + break; + case MOTION_BONE_N_SKATA_B_L_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_L_EX].node; + mat4_get_translation(v5[0].mat, &v30); + bone_data_mult_1_ik_hands_2(a1, &v30, 0.333f); + break; + case MOTION_BONE_N_SKATA_B_R_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_R_EX].node; + mat4_get_translation(v5[0].mat, &v30); + bone_data_mult_1_ik_hands_2(a1, &v30, 0.333f); + break; + case MOTION_BONE_N_SKATA_C_L_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_L_EX].node; + mat4_get_translation(v5[0].mat, &v30); + bone_data_mult_1_ik_hands_2(a1, &v30, 0.5f); + break; + case MOTION_BONE_N_SKATA_C_R_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_R_EX].node; + mat4_get_translation(v5[0].mat, &v30); + bone_data_mult_1_ik_hands_2(a1, &v30, 0.5f); + break; + case MOTION_BONE_N_MOMO_A_L_WJ_CD_EX: + v5 = a2[MOTION_BONE_CL_MOMO_L].node; + mat4_get_translation(v5[2].mat, &v30); + mat4_mult_vec3_inv(a1->node[0].mat, &v30, &v30); + vec3_negate(v30, v30); + bone_data_mult_1_ik_legs(a1, &v30); + break; + case MOTION_BONE_N_MOMO_A_R_WJ_CD_EX: + v5 = a2[MOTION_BONE_CL_MOMO_R].node; + mat4_get_translation(v5[2].mat, &v30); + mat4_mult_vec3_inv(a1->node[0].mat, &v30, &v30); + vec3_negate(v30, v30); + bone_data_mult_1_ik_legs(a1, &v30); + break; + case MOTION_BONE_N_HARA_CD_EX: + v5 = a2[MOTION_BONE_KL_MUNE_B_WJ].node; + mat4_get_translation(v5[0].mat, &v30); + mat4_mult_vec3_inv(a1->node[0].mat, &v30, &v30); + bone_data_mult_1_ik_legs(a1, &v30); + break; + default: + return false; + } + return true; +} + +static void bone_data_mult_1_ik_hands(bone_data* a1, vec3* a2) { + vec3 v15; + mat4_mult_vec3_inv(a1->node[0].mat, a2, &v15); + + float_t len; + vec3_length_squared(v15, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v15, 1.0f / len, v15); + + vec3 v17; + v17.x = -v15.z * v15.x - v15.z; + v17.y = -v15.y * v15.z; + v17.z = v15.x * v15.x + v15.y * v15.y + v15.x; + vec3_length_squared(v17, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v17, 1.0f / len, v17); + + vec3 v16; + vec3_cross(v17, v15, v16); + + mat4 rot_mat = mat4_identity; + *(vec3*)&rot_mat.row0 = v15; + *(vec3*)&rot_mat.row1 = v16; + *(vec3*)&rot_mat.row2 = v17; + + mat4_mult(&rot_mat, a1->node[0].mat, a1->node[0].mat); +} + +static void bone_data_mult_1_ik_hands_2(bone_data* a1, vec3* a2, float_t a3) { + float_t len; + vec3 v8; + + mat4_mult_vec3_inv(a1->node[0].mat, a2, &v8); + v8.x = 0.0f; + vec3_length(v8, len); + if (len <= 0.000001f) + return; + + vec3_mult_scalar(v8, 1.0f / len, v8); + float_t angle = atan2f(v8.z, v8.y); + mat4_rotate_x_mult(a1->node[0].mat, angle * a3, a1->node[0].mat); +} + +static void bone_data_mult_1_ik_legs(bone_data* a1, vec3* a2) { + vec3 v9 = *a2; + + float_t len; + vec3_length_squared(v9, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v9, 1.0f / len, v9); + + vec3 v8; + v8.x = -v9.z * v9.x; + v8.y = -v9.z * v9.y - v9.z; + v8.z = v9.y * v9.y - v9.x * -v9.x + v9.y; + + vec3_length_squared(v8, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v8, 1.0f / len, v8); + + vec3 v10; + vec3_cross(v9, v8, v10); + + mat4 rot_mat = mat4_identity; + *(vec3*)&rot_mat.row0 = v10; + *(vec3*)&rot_mat.row1 = v9; + *(vec3*)&rot_mat.row2 = v8; + + mat4_mult(&rot_mat, a1->node[0].mat, a1->node[0].mat); +} + +static bool bone_data_mult_1_exp_data(bone_data* a1, bone_node_expression_data* a2, bone_data* a3) { + float_t v10; + bone_node* v11; + vec3 v15; + mat4 dst; + mat4 mat; + + bool ret = true; + switch (a1->motion_bone_index) { + case MOTION_BONE_N_EYE_L_WJ_EX: + a2->rotation.x = -a3[MOTION_BONE_KL_EYE_L].node[0].exp_data.rotation.x; + a2->rotation.y = a3[MOTION_BONE_KL_EYE_L].node[0].exp_data.rotation.y * (float_t)(-1.0 / 2.0); + break; + case MOTION_BONE_N_EYE_R_WJ_EX: + a2->rotation.x = -a3[MOTION_BONE_KL_EYE_R].node[0].exp_data.rotation.x; + a2->rotation.y = a3[MOTION_BONE_KL_EYE_R].node[0].exp_data.rotation.y * (float_t)(-1.0 / 2.0); + break; + case MOTION_BONE_N_KUBI_WJ_EX: + mat4u_to_mat4(&a3[MOTION_BONE_CL_KAO].rot_mat[0], &dst); + mat4u_to_mat4(&a3[MOTION_BONE_CL_KAO].rot_mat[1], &mat); + mat4_mult(&mat, &dst, &dst); + mat4_get_rotation(&dst, &v15); + v10 = v15.z; + if (v10 < (float_t)-M_PI_2) + v10 += (float_t)(M_PI * 2.0); + a2->rotation.y = (v10 - (float_t)M_PI_2) * 0.2f; + break; + case MOTION_BONE_N_HITO_L_EX: + case MOTION_BONE_N_HITO_R_EX: + a2->rotation.z = (float_t)(-9.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_KO_L_EX: + a2->rotation.x = (float_t)(-8.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(16.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_KUSU_L_EX: + case MOTION_BONE_N_KUSU_R_EX: + a2->rotation.z = (float_t)(9.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_NAKA_L_EX: + case MOTION_BONE_N_NAKA_R_EX: + a2->rotation.z = (float_t)(-1.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_OYA_L_EX: + a2->rotation.x = (float_t)(75.0 * DEG_TO_RAD); + a2->rotation.y = (float_t)(12.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(-24.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_STE_L_WJ_EX: + a2->rotation.x = a3[MOTION_BONE_KL_TE_L_WJ].node[0].exp_data.rotation.x; + break; + case MOTION_BONE_N_SUDE_L_WJ_EX: + case MOTION_BONE_N_SUDE_B_L_WJ_EX: + v11 = &a3[MOTION_BONE_KL_TE_L_WJ].node[0]; + a2->rotation.x = bone_data_limit_angle(v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_SUDE_R_WJ_EX: + case MOTION_BONE_N_SUDE_B_R_WJ_EX: + v11 = &a3[MOTION_BONE_KL_TE_R_WJ].node[0]; + a2->rotation.x = bone_data_limit_angle(v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_HIJI_L_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_C_KATA_L].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_UP_KATA_L_EX: + case MOTION_BONE_N_UP_KATA_R_EX: + break; + case MOTION_BONE_N_KO_R_EX: + a2->rotation.x = (float_t)(8.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(16.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_OYA_R_EX: + a2->rotation.x = (float_t)(-75.0 * DEG_TO_RAD); + a2->rotation.y = (float_t)(-12.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(-24.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_STE_R_WJ_EX: + a2->rotation.x = a3[MOTION_BONE_KL_TE_R_WJ].node[0].exp_data.rotation.x; + break; + case MOTION_BONE_N_HIJI_R_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_C_KATA_R].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_HIZA_L_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_CL_MOMO_L].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_HIZA_R_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_CL_MOMO_R].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_MOMO_B_L_WJ_EX: + case MOTION_BONE_N_MOMO_C_L_WJ_EX: + v11 = &a3[MOTION_BONE_CL_MOMO_L].node[0]; + a2->rotation.y = bone_data_limit_angle(v11->exp_data.rotation.y + + v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_MOMO_B_R_WJ_EX: + case MOTION_BONE_N_MOMO_C_R_WJ_EX: + v11 = &a3[MOTION_BONE_CL_MOMO_R].node[0]; + a2->rotation.y = bone_data_limit_angle(v11->exp_data.rotation.y + + v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_HARA_B_WJ_EX: + a2->rotation.y = a3[MOTION_BONE_CL_MUNE].node[0].exp_data.rotation.y * (float_t)(1.0 / 3.0) + + a3[MOTION_BONE_KL_KOSI_Y].node[0].exp_data.rotation.y * (float_t)(2.0 / 3.0); + break; + case MOTION_BONE_N_HARA_C_WJ_EX: + a2->rotation.y = a3[MOTION_BONE_CL_MUNE].node[0].exp_data.rotation.y * (float_t)(2.0 / 3.0) + + a3[MOTION_BONE_KL_KOSI_Y].node[0].exp_data.rotation.y * (float_t)(1.0 / 3.0); + break; + default: + ret = false; + break; + } + return ret; +} + +static void bone_data_mult_ik(bone_data* a1, int32_t skeleton_select) { + if (a1->type < BONE_DATABASE_BONE_HEAD_IK_ROTATION) + return; + + mat4 mat = *a1->node[0].mat; + + vec3 v30; + mat4_mult_vec3_inv(&mat, &a1->ik_target, &v30); + float_t v6; + float_t v8; + vec2_length_squared(*(vec2*)&v30, v6); + vec3_length_squared(v30, v8); + float_t v9 = sqrtf(v6); + float_t v10 = sqrtf(v8); + mat4 rot_mat; + if (v9 > 0.000001f && v8 > 0.000001f) { + mat4_rotate_z_sin_cos(v30.y / v9, v30.x / v9, &rot_mat); + mat4_rotate_y_mult_sin_cos(&rot_mat, -v30.z / v10, v9 / v10, &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + } + else + rot_mat = mat4_identity; + + if (a1->pole_target_mat) { + vec3 pole_target; + mat4_get_translation(a1->pole_target_mat, &pole_target); + mat4_mult_vec3_inv(&mat, &pole_target, &pole_target); + float_t pole_target_length; + vec2_length(*(vec2*)&pole_target.y, pole_target_length); + if (pole_target_length > 0.000001f) { + vec3_mult_scalar(pole_target, 1.0f / pole_target_length, pole_target); + float_t rot_cos = pole_target.y; + float_t rot_sin = pole_target.z; + mat4_rotate_x_mult_sin_cos(&mat, rot_sin, rot_cos, &mat); + mat4_rotate_x_mult_sin_cos(&rot_mat, rot_sin, rot_cos, &rot_mat); + } + } + + if (a1->type == BONE_DATABASE_BONE_HEAD_IK_ROTATION) { + mat4_to_mat4u(&rot_mat, &a1->rot_mat[1]); + *a1->node[1].mat = mat; + mat4_translate_mult(&mat, a1->ik_segment_length[skeleton_select], 0.0f, 0.0f, &mat); + *a1->node[2].mat = mat; + return; + } + + float_t ik_segment_length = a1->ik_segment_length[skeleton_select]; + float_t ik_2nd_segment_length = a1->ik_2nd_segment_length[skeleton_select]; + float_t rot_sin; + float_t rot_cos; + float_t rot_2nd_sin; + float_t rot_2nd_cos; + if (fabsf(v8) > 0.000001f) { + float_t v26 = a1->field_2E0; + if (v26 > 0.0001f) { + float_t v27 = (ik_segment_length + ik_2nd_segment_length) * v26; + if (v10 > v27) { + v10 = v27; + v8 = v27 * v27; + } + } + float_t v28 = (v8 - ik_2nd_segment_length * ik_2nd_segment_length) / ik_segment_length; + rot_cos = (v28 + ik_segment_length) / (2.0f * v10); + rot_2nd_cos = (v28 - ik_segment_length) / (2.0f * ik_2nd_segment_length); + + rot_cos = clamp(rot_cos, -1.0f, 1.0f); + rot_2nd_cos = clamp(rot_2nd_cos, -1.0f, 1.0f); + + rot_sin = sqrtf(1.0f - rot_cos * rot_cos); + rot_2nd_sin = sqrtf(1.0f - rot_2nd_cos * rot_2nd_cos); + if (a1->type == BONE_DATABASE_BONE_LEGS_IK_ROTATION) + rot_sin = -rot_sin; + else + rot_2nd_sin = -rot_2nd_sin; + + float_t arot_sin = asinf(rot_sin) * RAD_TO_DEG_FLOAT; + float_t arot_cos = acosf(rot_cos) * RAD_TO_DEG_FLOAT; + float_t arot_2nd_sin = asinf(rot_2nd_sin) * RAD_TO_DEG_FLOAT; + float_t arot_2nd_cos = acosf(rot_2nd_cos) * RAD_TO_DEG_FLOAT; + } + else { + rot_sin = 0.0f; + rot_cos = 1.0f; + rot_2nd_sin = 0.0f; + rot_2nd_cos = -1.0f; + } + + mat4_rotate_z_mult_sin_cos(&mat, rot_sin, rot_cos, &mat); + *a1->node[1].mat = mat; + mat4_rotate_z_mult_sin_cos(&rot_mat, rot_sin, rot_cos, &rot_mat); + mat4_to_mat4u(&rot_mat, &a1->rot_mat[1]); + mat4_translate_mult(&mat, ik_segment_length, 0.0f, 0.0f, &mat); + mat4_rotate_z_mult_sin_cos(&mat, rot_2nd_sin, rot_2nd_cos, &mat); + *a1->node[2].mat = mat; + mat4_rotate_z_sin_cos(rot_2nd_sin, rot_2nd_cos, &rot_mat); + mat4_to_mat4u(&rot_mat, &a1->rot_mat[2]); + mat4_translate_mult(&mat, ik_2nd_segment_length, 0.0f, 0.0f, &mat); + *a1->node[3].mat = mat; +} + +static vec3* bone_data_set_key_data(bone_data* data, vec3* keyframe_data, + bone_database_skeleton_type skeleton_type, bool get_data, bool reverse_x) { + bone_database_bone_type type = data->type; + if (type == BONE_DATABASE_BONE_POSITION_ROTATION) { + if (get_data) { + data->trans = *keyframe_data; + if (reverse_x) + data->trans.x = -data->trans.x; + } + keyframe_data++; + } + else if (type >= BONE_DATABASE_BONE_HEAD_IK_ROTATION + && type <= BONE_DATABASE_BONE_LEGS_IK_ROTATION) { + if (get_data) { + data->ik_target = *keyframe_data; + if (reverse_x) + data->ik_target.x = -data->ik_target.x; + } + keyframe_data++; + } + + if (get_data) { + if (type == BONE_DATABASE_BONE_TYPE_1 || type == BONE_DATABASE_BONE_POSITION) { + data->trans = *keyframe_data; + if (reverse_x) + data->trans.x = -data->trans.x; + } + else if (!data->flags) { + data->rotation = *keyframe_data; + if (reverse_x) { + const skeleton_rotation_offset* rot_off = skeleton_rotation_offset_array; + size_t index = data->motion_bone_index; + if (rot_off[index].x) + data->rotation.x = rot_off[index].rotation.x - data->rotation.x; + if (rot_off[index].y) + data->rotation.y = rot_off[index].rotation.y - data->rotation.y; + if (rot_off[index].z) + data->rotation.z = rot_off[index].rotation.z - data->rotation.z; + } + } + } + keyframe_data++; + return keyframe_data; +} + +static void bone_data_parent_data_init(bone_data_parent* bone, + rob_chara_data_bone_data* rob_bone_data, bone_database* bone_data) { + char* base_name = bone_database_skeleton_type_to_string(rob_bone_data->base_skeleton_type); + char* name = bone_database_skeleton_type_to_string(rob_bone_data->skeleton_type); + vector_bone_database_bone* common_bones = 0; + vector_vec3* common_translation = 0; + vector_vec3* translation = 0; + if (!bone_database_get_skeleton_bones(bone_data, base_name, &common_bones) + || !bone_database_get_skeleton_positions(bone_data, base_name, &common_translation) + || !bone_database_get_skeleton_positions(bone_data, name, &translation)) + return; + + bone->rob_bone_data = rob_bone_data; + bone_data_parent_load_rob_chara_data(bone); + bone_data_parent_load_bone_database(bone, common_bones, common_translation->begin, translation->begin); +} + +static void bone_data_parent_load_bone_database(bone_data_parent* bone, + vector_bone_database_bone* bones, vec3* common_translation, vec3* translation) { + rob_chara_data_bone_data* rob_bone_data = bone->rob_bone_data; + size_t chain_pos = 0; + size_t total_bone_count = 0; + size_t ik_bone_count = 0; + + bone_data* v16 = bone->bones.begin; + for (bone_database_bone* i = bones->begin; i != bones->end; i++, v16++) { + v16->motion_bone_index = (motion_bone_index)(i - bones->begin); + v16->type = i->type; + v16->mirror = i->mirror; + v16->parent = i->parent; + v16->flags = i->flags; + if (i->type >= BONE_DATABASE_BONE_POSITION_ROTATION) + v16->key_set_count = 6; + else + v16->key_set_count = 3; + v16->base_translation[0] = *common_translation++; + v16->base_translation[1] = *translation++; + v16->node = &rob_bone_data->nodes.begin[total_bone_count]; + v16->has_parent = i->has_parent; + if (i->has_parent) + v16->parent_mat = &rob_bone_data->mats.begin[i->parent]; + else + v16->parent_mat = 0; + + v16->pole_target_mat = 0; + switch (i->type) { + case BONE_DATABASE_BONE_ROTATION: + case BONE_DATABASE_BONE_TYPE_1: + case BONE_DATABASE_BONE_POSITION: + chain_pos++; + total_bone_count++; + break; + case BONE_DATABASE_BONE_POSITION_ROTATION: + chain_pos++; + ik_bone_count++; + total_bone_count++; + break; + case BONE_DATABASE_BONE_HEAD_IK_ROTATION: + v16->ik_segment_length[0] = (common_translation++)->x; + v16->ik_segment_length[1] = (translation++)->x; + + chain_pos += 2; + ik_bone_count++; + total_bone_count += 3; + break; + case BONE_DATABASE_BONE_ARM_IK_ROTATION: + case BONE_DATABASE_BONE_LEGS_IK_ROTATION: + v16->ik_segment_length[0] = (common_translation++)->x; + v16->ik_segment_length[1] = (translation++)->x; + v16->ik_2nd_segment_length[0] = (common_translation++)->x; + v16->ik_2nd_segment_length[1] = (translation++)->x; + + mat4* pole_target = 0; + if (i->pole_target) + pole_target = &rob_bone_data->mats.begin[i->pole_target]; + v16->pole_target_mat = pole_target; + + chain_pos += 3; + ik_bone_count++; + total_bone_count += 4; + break; + } + } +} + +static void bone_data_parent_load_bone_indices_from_mot(bone_data_parent* a1, + mot_data* a2, bone_database* a3, motion_database* mot_db) { + if (!a2) + return; + + vector_uint16_t* bone_indices = &a1->bone_indices; + vector_uint16_t_clear(bone_indices, 0); + + uint16_t key_set_count = (a2->info & 0x3FFF) - 1; + if (!key_set_count) + return; + + bone_database_skeleton_type skeleton_type = a1->rob_bone_data->base_skeleton_type; + char* skeleton_type_string = bone_database_skeleton_type_to_string(skeleton_type); + string* bone_names = mot_db->bone_name.begin; + + mot_bone_info* bone_info = a2->bone_info; + for (size_t key_set_offset= 0, i = 0; key_set_offset< key_set_count; i++) { + int32_t bone_index = bone_database_get_skeleton_bone_index(a3, + skeleton_type_string, string_data(&bone_names[bone_info[i].index])); + if (bone_index == -1) { + bone_index = bone_database_get_skeleton_bone_index(a3, + skeleton_type_string, string_data(&bone_names[bone_info[++i].index])); + if (bone_index == -1) + break; + } + *vector_uint16_t_reserve_back(bone_indices) = (uint16_t)bone_index; + + bone_data* v15 = &a1->bones.begin[bone_index]; + v15->key_set_offset = (int32_t)key_set_offset; + v15->frame = -1.0f; + if (v15->type >= BONE_DATABASE_BONE_POSITION_ROTATION) + key_set_offset+= 6; + else + key_set_offset+= 3; + } +} + +static void bone_data_parent_load_rob_chara_data(bone_data_parent* bone) { + rob_chara_data_bone_data* rob_bone_data = bone->rob_bone_data; + if (!rob_bone_data) + return; + + bone->motion_bone_count = rob_bone_data->motion_bone_count; + bone->ik_bone_count = rob_bone_data->ik_bone_count; + bone->chain_pos = rob_bone_data->chain_pos; + + size_t bones_size = rob_bone_data->motion_bone_count; + vector_bone_data_reserve(&bone->bones, bones_size); + bone->bones.end += bones_size; + + for (bone_data* i = bone->bones.begin; i != bone->bones.end; i++) + bone_data_init(i); + + bone->global_key_set_count = 6; + bone->bone_key_set_count = (uint32_t)((bone->motion_bone_count + bone->ik_bone_count) * 3); +} + +static float_t* bone_node_get_exp_data_component(bone_node* a1, + size_t index, ex_expression_block_stack_type* type) { + switch (index) { + case 0: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.position.x; + case 1: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.position.y; + case 2: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.position.z; + case 3: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN; + return &a1->exp_data.rotation.x; + case 4: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN; + return &a1->exp_data.rotation.y; + case 5: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN; + return &a1->exp_data.rotation.z; + case 6: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.scale.x; + case 7: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.scale.y; + case 8: + *type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + return &a1->exp_data.scale.z; + default: + return 0; + } +} + +static void bone_data_parent_reset(bone_data_parent* bone) { + bone->rob_bone_data = 0; + bone->motion_bone_count = 0; + bone->global_trans = vec3_null; + bone->global_rotation = vec3_null; + bone->ik_bone_count = 0; + bone->chain_pos = 0; + bone->bone_key_set_count = 0; + bone->global_key_set_count = 0; + bone->rotation_y = 0; + bone->bones.end = bone->bones.begin; + bone->bone_indices.end = bone->bone_indices.begin; +} + +static void bone_data_parent_free(bone_data_parent* bone) { + vector_uint16_t_free(&bone->bone_indices, 0); + vector_bone_data_free(&bone->bones, 0); +} + +static void bone_node_expression_data_mat_set(bone_node_expression_data* data, + vec3* data_scale, mat4* ex_data_mat, mat4* mat) { + vec3 position; + vec3_mult(data->position, *data_scale, position); + mat4_translate_mult( ex_data_mat, position.x, position.y, position.z, ex_data_mat); + vec3 rotation = data->rotation; + mat4_rotate_mult(ex_data_mat, rotation.x, rotation.y, rotation.z, ex_data_mat); + vec3_mult(data->scale, *data_scale, data->data_scale); + *mat = *ex_data_mat; + mat4_scale_rot(mat, data->data_scale.x, data->data_scale.y, data->data_scale.z, mat); +} + +static void bone_node_expression_data_reset_position_rotation(bone_node_expression_data* data) { + data->position = vec3_null; + data->rotation = vec3_null; + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static void bone_node_expression_data_reset_scale(bone_node_expression_data* data) { + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static void bone_node_expression_data_set_position_rotation(bone_node_expression_data* data, + float_t position_x, float_t position_y, float_t position_z, + float_t rotation_x, float_t rotation_y, float_t rotation_z) { + data->position.x = position_x; + data->position.y = position_y; + data->position.z = position_z; + data->rotation.x = rotation_x; + data->rotation.z = rotation_z; + data->rotation.y = rotation_y; + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static void bone_node_expression_data_set_position_rotation_vec3(bone_node_expression_data* data, + vec3* position, vec3* rotation) { + data->position = *position; + data->rotation = *rotation; + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static ex_cloth_block* ex_cloth_block_init() { + ex_cloth_block* cls = force_malloc(sizeof(ex_cloth_block)); + cls->base.vftable = &ex_cloth_block_vftable; + cls->base.parent_name = string_empty; + return cls; +} + +static void ex_cloth_block_draw(ex_cloth_block* cls) { + +} + +static void ex_cloth_block_reset(ex_cloth_block* cls) { + +} + +static void ex_cloth_block_update(ex_cloth_block* cls) { + +} + +static void ex_cloth_block_dispose(ex_cloth_block* cls) { + ex_node_block_free(&cls->base); + free(cls); +} + +static ex_constraint_block* ex_constraint_block_init() { + ex_constraint_block* cns = force_malloc(sizeof(ex_constraint_block)); + cns->base.vftable = &ex_constraint_block_vftable; + cns->base.parent_name = string_empty; + return cns; +} + +static void ex_constraint_block_init_data(ex_constraint_block* cns, rob_chara_data_item_equip_object* itm_eq_obj, + object_skin_block_constraint* cns_data, char* cns_data_name, bone_database* bone_data) { + bone_node* node = rob_chara_data_item_equip_object_get_bone_node_by_name( + itm_eq_obj, cns_data_name, bone_data); + ex_node_block_init_data(&cns->base, node, EX_CONSTRAINT, node->name, itm_eq_obj); + cns->cns_data = cns_data; + + cns->source_node_bone_node = rob_chara_data_item_equip_object_get_bone_node_by_name( + itm_eq_obj, string_data(&cns_data->source_node_name), bone_data); + + object_skin_block_constraint_type type = cns_data->type; + char* up_vector_name; + if (type == OBJECT_SKIN_BLOCK_CONSTRAINT_DIRECTION) { + cns->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DIRECTION; + up_vector_name = string_data(&cns_data->direction.up_vector.name); + } + else if (type == OBJECT_SKIN_BLOCK_CONSTRAINT_POSITION) { + cns->type = OBJECT_SKIN_BLOCK_CONSTRAINT_POSITION; + up_vector_name = string_data(&cns_data->position.up_vector.name); + } + else if (type == OBJECT_SKIN_BLOCK_CONSTRAINT_DISTANCE) { + cns->type = OBJECT_SKIN_BLOCK_CONSTRAINT_DISTANCE; + up_vector_name = string_data(&cns_data->distance.up_vector.name); + } + else { + cns->type = OBJECT_SKIN_BLOCK_CONSTRAINT_NONE; + if (type == OBJECT_SKIN_BLOCK_CONSTRAINT_ORIENTATION) + cns->type = OBJECT_SKIN_BLOCK_CONSTRAINT_ORIENTATION; + return; + } + + if (up_vector_name) + cns->direction_up_vector_bone_node = rob_chara_data_item_equip_object_get_bone_node_by_name( + itm_eq_obj, up_vector_name, bone_data); +} + +static void ex_constraint_block_data_set(ex_constraint_block* cns) { + if (!cns->base.bone_node) + return; + + bone_node* node = cns->base.bone_node; + bone_node_expression_data* exp_data = &node->exp_data; + bone_node* parent_node = cns->base.parent_bone_node; + vec3 data_scale = parent_node->exp_data.data_scale; + + mat4 mat; + mat4_inverse_normalized(parent_node->ex_data_mat, &mat); + mat4_mult(node->mat, &mat, &mat); + mat4_get_rotation(&mat, &node->exp_data.rotation); + mat4_get_translation(&mat, &exp_data->position); + if (fabsf(data_scale.x) > 0.000001f) + exp_data->position.x /= data_scale.x; + if (fabsf(data_scale.y) > 0.000001f) + exp_data->position.y /= data_scale.z; + if (fabsf(data_scale.z) > 0.000001f) + exp_data->position.z /= data_scale.z; + *node->ex_data_mat = *node->mat; + mat4_scale_rot(node->mat, data_scale.x, data_scale.y, data_scale.z, node->mat); + vec3_mult(exp_data->scale, data_scale, exp_data->data_scale); +} + +static void ex_constraint_block_draw(ex_constraint_block* cns) { + +} + +static void ex_constraint_block_set_default_data(ex_constraint_block* cns) { + if (cns->base.bone_node) { + bone_node_expression_data* exp_data = &cns->base.bone_node->exp_data; + object_skin_block_constraint* cns_data = cns->cns_data; + exp_data->position = cns_data->base.position; + exp_data->rotation = cns_data->base.rotation; + exp_data->scale = cns_data->base.scale; + } + cns->base.set_data = false; +} + +static void ex_constraint_block_time_step(ex_constraint_block* cns) { +} + +static void ex_constraint_block_update(ex_constraint_block* cns) { + if (!cns->base.parent_bone_node) + return; + + if (cns->base.set_data) + cns->base.set_data = false; + else { + ex_constraint_block_time_step(cns); + ex_constraint_block_data_set(cns); + cns->base.set_data = true; + } +} + +static void ex_constraint_block_dispose(ex_constraint_block* cns) { + ex_node_block_free(&cns->base); + free(cns); +} + +static ex_expression_block* ex_expression_block_init() { + ex_expression_block* exp = force_malloc(sizeof(ex_expression_block)); + exp->base.vftable = &ex_expression_block_vftable; + exp->base.parent_name = string_empty; + return exp; +} + +static void ex_expression_block_init_data(ex_expression_block* exp, + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_block_expression* exp_data, + char* exp_data_name, object_info a4, chara_index chara_index, bone_database* bone_data) { + ex_expression_block_stack* stack_buf[28]; + ex_expression_block_stack** stack_buf_val = stack_buf; + + bone_node* node = rob_chara_data_item_equip_object_get_bone_node_by_name( + itm_eq_obj, exp_data_name, bone_data); + ex_node_block_init_data(&exp->base, node, EX_EXPRESSION, node->name, itm_eq_obj); + + exp->exp_data = exp_data; + node->exp_data.position = exp_data->base.position; + node->exp_data.rotation = exp_data->base.rotation; + node->exp_data.scale = exp_data->base.scale; + exp->field_3D28 = 0; + + ex_expression_block_stack* stack_val = exp->stack_data; + for (int32_t i = 0; i < 9; i++) { + exp->values[i] = 0; + exp->expressions[i] = 0; + } + + for (int32_t i = 0; i < 9; i++) { + char* expression = string_data(&exp_data->expressions[i]); + if (!expression || str_utils_compare_length(expression, exp_data->expressions[i].length, "= ", 2)) + break; + + expression += 2; + + int32_t index = 0; + expression = str_utils_get_next_int32_t(expression, &index, ' '); + exp->values[i] = bone_node_get_exp_data_component(exp->base.bone_node, index, &exp->types[i]); + + while (expression) { + string v73; + expression = str_utils_get_next_string(expression, &v73, ' '); + if (!v73.length || !memcmp(string_data(&v73), "error", min(v73.length, 5)) && v73.length == 5) { + string_free(&v73); + break; + } + + if (*string_data(&v73) == 'n') { + stack_val->type = EX_EXPRESSION_BLOCK_STACK_NUMBER; + expression = str_utils_get_next_float_t(expression, &stack_val->number.value, ' '); + *stack_buf_val++ = stack_val; + } + else if (*string_data(&v73) == 'v') { + string func_str; + expression = str_utils_get_next_string(expression, &func_str, ' '); + stack_val->type = EX_EXPRESSION_BLOCK_STACK_VARIABLE; + int32_t v40 = *string_data(&func_str) - '0'; + if (v40 < 9) { + bone_node* v42 = rob_chara_data_item_equip_object_get_bone_node_by_name(itm_eq_obj, + string_data(&func_str) + 2, bone_data); + if (v42) + stack_val->var.value = bone_node_get_exp_data_component(v42, v40, &stack_val->type); + else { + stack_val->type = EX_EXPRESSION_BLOCK_STACK_NUMBER; + stack_val->number.value = 0.0f; + } + } + else + stack_val->var.value = &exp->frame; + *stack_buf_val++ = stack_val; + string_free(&func_str); + } + else if (*string_data(&v73) == 'f') { + string func_str; + expression = str_utils_get_next_string(expression, &func_str, ' '); + stack_val->type = EX_EXPRESSION_BLOCK_STACK_OP1; + stack_val->op1.v1 = stack_buf_val[-1]; + stack_val->op1.func = exp_func_op1_find_func(&func_str, exp_func_op1_array)->func; + stack_buf_val[-1] = stack_val; + string_free(&func_str); + } + else if (*string_data(&v73) == 'g') { + string func_str; + expression = str_utils_get_next_string(expression, &func_str, ' '); + stack_val->type = EX_EXPRESSION_BLOCK_STACK_OP2; + stack_val->op2.v1 = stack_buf_val[-2]; + stack_val->op2.v2 = stack_buf_val[-1]; + stack_val->op2.func = exp_func_op2_find_func(&func_str, exp_func_op2_array)->func; + stack_buf_val[-2] = stack_val; + stack_buf_val--; + string_free(&func_str); + } + else if (*string_data(&v73) == 'h') { + string func_str; + expression = str_utils_get_next_string(expression, &func_str, ' '); + stack_val->type = EX_EXPRESSION_BLOCK_STACK_OP3; + stack_val->op3.v1 = stack_buf_val[-3]; + stack_val->op3.v2 = stack_buf_val[-2]; + stack_val->op3.v3 = stack_buf_val[-1]; + stack_val->op3.func = exp_func_op3_find_func(&func_str, exp_func_op3_array)->func; + stack_buf_val[-3] = stack_val; + stack_buf_val -= 2; + string_free(&func_str); + } + string_free(&v73); + exp->expressions[i] = stack_buf_val[-1]; + stack_val++; + } + } + + if (chara_index >= CHARA_MIKU && chara_index <= CHARA_TETO) + exp->osage_phys_step = true; +} + +static void ex_expression_block_data_set(ex_expression_block* exp) { + bone_node* node = exp->base.bone_node; + bone_node* parent_node = exp->base.parent_bone_node; + bone_node_expression_data* data = &node->exp_data; + vec3 data_scale = exp->base.parent_bone_node->exp_data.data_scale; + mat4 ex_data_mat = *parent_node->ex_data_mat; + mat4 mat = mat4_identity; + bone_node_expression_data_mat_set(data, &data_scale, &ex_data_mat, &mat); + *node->mat = mat; + *node->ex_data_mat = ex_data_mat; +} + +static void ex_expression_block_draw(ex_expression_block* exp) { + +} + +static void ex_expression_block_set_default_data(ex_expression_block* exp) { + bone_node_expression_data* exp_data = &exp->base.bone_node->exp_data; + object_skin_block_expression* exp_exp_data = exp->exp_data; + exp_data->position = exp_exp_data->base.position; + exp_data->rotation = exp_exp_data->base.rotation; + exp_data->scale = exp_exp_data->base.scale; + exp->base.set_data = false; +} + +static void ex_expression_block_time_step(ex_expression_block* exp) { + float_t delta_frame = get_delta_frame(); + if (exp->osage_phys_step) + delta_frame *= exp->base.item_equip_object->item_equip->osage_phys_step; + float_t frame = exp->frame + delta_frame; + exp->frame = frame >= 65535.0f ? frame - 65535.0f : frame; + + if (exp->field_3D28) + exp->field_3D28(&exp->base.bone_node->exp_data); + else + for (int32_t i = 0; i < 9; i++) { + if (!exp->expressions[i]) + break; + + *exp->values[i] = ex_expression_block_stack_get_value(exp->expressions[i]); + if (exp->types[i] == EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN) + *exp->values[i] *= DEG_TO_RAD_FLOAT; + } +} + +static void ex_expression_block_update(ex_expression_block* exp) { + if (!exp->base.parent_bone_node) + return; + + if (exp->base.set_data) + exp->base.set_data = false; + else { + ex_expression_block_time_step(exp); + ex_expression_block_data_set(exp); + exp->base.set_data = true; + } +} + +static void ex_expression_block_dispose(ex_expression_block* exp) { + ex_node_block_free(&exp->base); + free(exp); +} + +static float_t ex_expression_block_stack_get_value(ex_expression_block_stack* stack) { + float_t value = 0.0f; + switch (stack->type) { + case EX_EXPRESSION_BLOCK_STACK_NUMBER: + value = stack->number.value; + break; + case EX_EXPRESSION_BLOCK_STACK_VARIABLE: + value = *stack->var.value; + break; + case EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN: + value = *stack->var_rad.value * RAD_TO_DEG_FLOAT; + break; + case EX_EXPRESSION_BLOCK_STACK_OP1: { + float_t v1 = ex_expression_block_stack_get_value(stack->op1.v1); + if (stack->op1.func) + value = stack->op1.func(v1); + } break; + case EX_EXPRESSION_BLOCK_STACK_OP2: { + float_t v1 = ex_expression_block_stack_get_value(stack->op2.v1); + float_t v2 = ex_expression_block_stack_get_value(stack->op2.v2); + if (stack->op2.func) + value = stack->op2.func(v1, v2); + } break; + case EX_EXPRESSION_BLOCK_STACK_OP3: { + float_t v1 = ex_expression_block_stack_get_value(stack->op1.v1); + float_t v2 = ex_expression_block_stack_get_value(stack->op2.v2); + float_t v3 = ex_expression_block_stack_get_value(stack->op3.v3); + if (stack->op3.func) + value = stack->op3.func(v1, v2, v3); + } break; + } + return value; +} + +static void ex_node_block_init_data(ex_node_block* node, bone_node* bone_node, + ex_node_type type, char* name, rob_chara_data_item_equip_object* itm_eq_obj) { + node->bone_node = bone_node; + node->type = type; + if (name) + node->name = name; + else + node->name = "(null)"; + node->parent_bone_node = 0; + node->item_equip_object = itm_eq_obj; +} + +static void ex_node_block_reset(ex_node_block* node) { + node->bone_node = 0; +} + +static void ex_node_block_set_default_data(ex_node_block* node) { + node->set_data = false; +} + +static void ex_node_block_free(ex_node_block* node) { + string_free(&node->parent_name); +} + +static ex_osage_block* ex_osage_block_init() { + ex_osage_block* osg = force_malloc(sizeof(ex_osage_block)); + osg->base.vftable = &ex_osage_block_vftable; + osg->base.parent_name = string_empty; + return osg; +} + +static void rob_osage_init(rob_osage* rob_osg) { + vector_rob_osage_node_clear(&rob_osg->nodes, rob_osage_node_free); + rob_osg->nodes.end = rob_osg->nodes.begin; + rob_osage_node_init(&rob_osg->node); + rob_osg->wind_direction = vec3_null; + rob_osg->wind_direction.z = 0; + rob_osg->field_1EB4 = 0.0f; + rob_osg->field_1EB8 = 0; + rob_osg->field_2A0 = true; + /*tree_295* v2 = &rob_osg->field_1F60; + sub_140216750(&rob_osg->field_1F60, rob_osg->field_1F60.head->parent); + v2->head->parent = v2->head; + v2->head->left = v2->head; + v2->head->right = v2->head; + rob_osg->field_1F60.size = 0;*/ + rob_osg->field_1F08 = 0.0; + rob_osg->field_1F0C = false; + rob_osg->field_1F0D = false; + rob_osg->field_1F0E = false; + rob_osg->ring.ring_rectangle_x = 0.0f; + rob_osg->ring.ring_rectangle_y = 0.0f; + rob_osg->ring.ring_rectangle_width = 0.0f; + rob_osg->ring.ring_rectangle_height = 0.0f; + rob_osg->ring.ring_height = -1000.0f; + rob_osg->ring.ring_out_height = -1000.0f; + rob_osg->ring.field_18 = 0; + rob_osg->ring.coli.end = rob_osg->ring.coli.begin; + rob_osg->ring.skp_root_coli.end = rob_osg->ring.skp_root_coli.begin; + rob_osg->field_1F0F = 0; + skin_param_init(&rob_osg->skin_param); + rob_osg->skin_param_ptr = &rob_osg->skin_param; + rob_osg->field_290 = -1; + rob_osg->field_298 = 0; + rob_osg->field_1F70 = 0; + rob_osg->field_2A4 = 0.0f; + rob_osg->field_2A1 = false; + rob_osg->field_1F78 = 0; + rob_osg->field_1F7C = vec3_null; + rob_osg->mats = 0; + rob_osg->mat = mat4u_null; +} + +static void rob_osage_init_data(rob_osage* rob_osg, + object_skin_block_osage* osg_data, object_skin_osage_node* osg_nodes, + bone_node* ex_data_bone_nodes, object_skin* skin) { + rob_osage_init(rob_osg); + bone_node_expression_data_set_position_rotation_vec3( + &rob_osg->exp_data, + &osg_data->base.position, + &osg_data->base.rotation); + vector_rob_osage_node* nodes = &rob_osg->nodes; + vector_rob_osage_node_clear(&rob_osg->nodes, 0); + vector_rob_osage_node_reserve(&rob_osg->nodes, osg_data->count + 1ULL); + rob_osg->nodes.end += osg_data->count + 1ULL; + + rob_osage_node* external = nodes->begin; + rob_osage_node_init(nodes->begin); + external->child_length = osg_nodes->length; + bone_node* external_bone_node = &ex_data_bone_nodes[osg_data->external_name_index & 0x7FFF]; + external->bone_node = external_bone_node; + external->bone_node_mat = external_bone_node->mat; + *external_bone_node->ex_data_mat = mat4_identity; + external->sibling_node = 0; + + bone_node* parent_bone_node = external->bone_node; + for (int32_t i = 0; i < osg_data->count; i++) { + object_skin_osage_node* v14 = &osg_nodes[i]; + rob_osage_node* node = &nodes->begin[i + 1]; + rob_osage_node_init(node); + node->length = v14[0].length; + if (i != osg_data->count - 1) + node->child_length = v14[1].length; + bone_node* node_bone_node = &ex_data_bone_nodes[v14->name_index & 0x7FFF]; + node->bone_node = node_bone_node; + node->bone_node_mat = node_bone_node->mat; + node_bone_node->parent = parent_bone_node; + parent_bone_node = node->bone_node; + } + + rob_osage_node_init(&rob_osg->node); + rob_osg->node.length = osg_nodes[osg_data->count - 1].length; + bone_node* v22 = &ex_data_bone_nodes[osg_data->name_index & 0x7FFF]; + rob_osg->node.bone_node = v22; + rob_osg->node.bone_node_mat = v22->mat; + v22->parent = parent_bone_node; + *rob_osg->node.bone_node->ex_data_mat = mat4_identity; + + object_skin_osage_node* v23 = osg_data->nodes; + for (int32_t i = 0; i < osg_data->count; i++) { + rob_osage_node* v26 = &nodes->begin[i + 1]; + vec3 v27 = vec3_null; + if (v23) + v27 = v23[i].rotation; + + mat4 mat; + mat4_rotate(v27.x, v27.y, v27.z, &mat); + v26->field_94 = vec3_null; + v26->field_94.x = v26->length; + mat4_mult_vec3(&mat, &v26->field_94, &v26->field_94); + + v26->mat = mat4u_null; + object_skin_bone* v36 = skin->bones; + for (int32_t j = 0; j < skin->bones_count; j++) + if (v36[j].id == osg_nodes->name_index) { + mat4 mat; + mat4u_to_mat4(&v36[j].inv_bind_pose_mat, &mat); + mat4_inverse_normalized(&mat, &mat); + mat4_to_mat4u(&mat, &v26->mat); + } + } + + rob_osage_node* v38 = &rob_osg->nodes.end[-1]; + if (!memcmp(&v38->mat, &mat4_null, sizeof(mat4))) { + mat4 mat; + mat4u_to_mat4(&v38->mat, &mat); + mat4_translate_mult(&mat, rob_osg->node.length, 0.0f, 0.0f, &mat); + mat4_to_mat4u(&mat, &rob_osg->node.mat); + } +} + +static void skin_param_hinge_limit(skin_param_hinge* hinge) { + hinge->ymin = max(hinge->ymin, -179.0f) * DEG_TO_RAD_FLOAT; + hinge->ymax = min(hinge->ymax, 179.0f) * DEG_TO_RAD_FLOAT; + hinge->zmin = max(hinge->zmin, -179.0f) * DEG_TO_RAD_FLOAT; + hinge->zmax = min(hinge->zmax, 179.0f) * DEG_TO_RAD_FLOAT; +} + +static void rob_osage_node_data_init(rob_osage_node_data* node_data) { + node_data->force = 0.0f; + node_data->boc.end = node_data->boc.begin; + node_data->skp_osg_node.coli_r = 0.0f; + node_data->skp_osg_node.weight = 1.0f; + node_data->skp_osg_node.inertial_cancel = 0.0f; + node_data->skp_osg_node.hinge = (skin_param_hinge){ -90.0f, 90.0f, -90.0f, 90.0f }; + skin_param_hinge_limit(&node_data->skp_osg_node.hinge); + node_data->normal_ref.field_0 = 0; + node_data->normal_ref.n = 0; + node_data->normal_ref.u = 0; + node_data->normal_ref.d = 0; + node_data->normal_ref.l = 0; + node_data->normal_ref.r = 0; + node_data->normal_ref.mat = mat4u_identity; +} + +static void ex_osage_block_draw(ex_osage_block* osg) { + +} + +static void ex_osage_block_init_data(ex_osage_block* osg, + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_block_osage* osg_data, + char* osg_data_name, object_skin_osage_node* osg_nodes, bone_node* bone_nodes, + bone_node* ex_data_bone_nodes, object_skin* skin) { + ex_node_block_init_data(&osg->base, + &ex_data_bone_nodes[osg_data->external_name_index & 0x7FFF], EX_OSAGE, osg_data_name, itm_eq_obj); + rob_osage_init_data(&osg->rob, osg_data, osg_nodes, ex_data_bone_nodes, skin); + osg->field_1FF8 &= ~2; + osg->mat = bone_nodes->mat; +} + +static void sub_1405F3E10(ex_osage_block* osg, object_skin_block_osage* osg_data, + object_skin_osage_node* osg_nodes, vector_pair_int32_t_ptr_rob_osage_node* a4, + vector_pair_name_ex_osage_block* a5) { + rob_osage* v5 = &osg->rob; + + rob_osage_node* v9 = rob_osage_get_node(&osg->rob, 0); + pair_int32_t_ptr_rob_osage_node* v38 + = vector_pair_int32_t_ptr_rob_osage_node_reserve_back(a4); + v38->key = osg_data->external_name_index; + v38->value = v9; + + for (size_t i = 0; i < osg_data->count; i++) { + v9 = rob_osage_get_node(v5, i); + v38 = vector_pair_int32_t_ptr_rob_osage_node_reserve_back(a4); + v38->key = osg_nodes[i].name_index; + v38->value = v9; + + if (v9->bone_node && v9->bone_node->name) { + pair_name_ex_osage_block* v39 = vector_pair_name_ex_osage_block_reserve_back(a5); + v39->name = v9->bone_node->name; + v39->block = osg; + } + } + + v9 = rob_osage_get_node(v5, osg_data->count + 1ULL); + v38 = vector_pair_int32_t_ptr_rob_osage_node_reserve_back(a4); + v38->key = osg_data->name_index; + v38->value = v9; + + if (v9->bone_node && v9->bone_node->name) { + pair_name_ex_osage_block* v39 = vector_pair_name_ex_osage_block_reserve_back(a5); + v39->name = v9->bone_node->name; + v39->block = osg; + } +} + +static void ex_osage_block_reset(ex_osage_block* osg) { + osg->index = 0; + rob_osage_init(&osg->rob); + osg->field_1FF8 &= ~3; + osg->mat = 0; + osg->osage_phys_step = 1.0f; + ex_node_block_reset(&osg->base); +} + +static void ex_osage_block_set_wind_direction(ex_osage_block* osg) { + vec3_mult_scalar(wind_ptr->wind_direction, + osg->base.item_equip_object->item_equip->wind_strength, + osg->rob.wind_direction); +} + +static void sub_14047F110(rob_osage* rob_osg, mat4* mat, vec3* data_scale, bool init_rot) { + vec3 position; + vec3_mult(rob_osg->exp_data.position, *data_scale, position); + mat4_translate_mult(mat, position.x, position.y, position.z, mat); + + vec3 rotation = rob_osg->exp_data.rotation; + mat4_rotate_mult(mat, rotation.x, rotation.y, rotation.z, mat); + + skin_param* skin_param = rob_osg->skin_param_ptr; + vec3 rot = rob_osg->skin_param_ptr->rot; + if (init_rot) + vec3_add(rot, skin_param->init_rot, rot); + mat4_rotate_mult(mat, rot.x, rot.y, rot.z, mat); +} + +static bool sub_140482FF0(mat4* a1, vec3* a2, skin_param_hinge* hinge, vec3* a4, int32_t* a5) { + bool clipped = false; + float_t y; + float_t z; + if (*a5 == 1) { + y = atan2f(-a2->z, a2->x); + z = atan2f(a2->y, sqrtf(a2->x * a2->x + a2->z * a2->z)); + if (hinge) { + clipped = false; + if (y > hinge->ymax) { + y = hinge->ymax; + clipped = true; + } + + if (y < hinge->ymin) { + y = hinge->ymin; + clipped = true; + } + + if (z > hinge->zmax) { + z = hinge->zmax; + clipped = true; + } + + if (z < hinge->zmin) { + z = hinge->zmin; + clipped = true; + } + } + mat4_rotate_y_mult(a1, y, a1); + mat4_rotate_z_mult(a1, z, a1); + } + else { + z = atan2f(a2->y, a2->x); + y = atan2f(-a2->z, sqrtf(a2->x * a2->x + a2->y * a2->y)); + if (hinge) { + clipped = false; + if (y > hinge->ymax) { + y = hinge->ymax; + clipped = true; + } + + if (y < hinge->ymin) { + y = hinge->ymin; + clipped = true; + } + + if (z > hinge->zmax) { + z = hinge->zmax; + clipped = true; + } + + if (z < hinge->zmin) { + z = hinge->zmin; + clipped = true; + } + } + mat4_rotate_z_mult(a1, z, a1); + mat4_rotate_y_mult(a1, y, a1); + } + + if (a4) { + a4->y = y; + a4->z = z; + } + return clipped; +} + +static void sub_14047EE90(rob_osage* rob_osg, mat4* mat) { + __int64*** v2 = (__int64***)rob_osg->field_1F70; + if (v2) { + __int64* v5 = **v2; + rob_osage_node* v6 = rob_osg->nodes.begin + 1; + if (v6 != rob_osg->nodes.end) { + rob_osage_node* v7 = rob_osg->nodes.begin; + do { + v7->length = *((float_t*)v5 + 4); + v7->trans = *(vec3*)((char*)v5 + 20); + v7->field_10 = *(vec3*)(v5 + 4); + v7->field_1C = *(vec3*)((char*)v5 + 44); + ++v6; + ++v7; + v5 = (__int64*)*v5; + } while (v6 != rob_osg->nodes.end); + } + rob_osg->field_1F70 = 0i64; + } + + rob_osage_node* v8 = rob_osg->nodes.begin + 1; + if (v8 != rob_osg->nodes.end) { + rob_osage_node* v9 = &rob_osg->nodes.begin[1]; + do { + mat4_mult_vec3(mat, &v9->field_AC, &v9->field_1C); + mat4_mult_vec3_trans(mat, &v9->field_A0, &v9->trans); + ++v8; + ++v9; + } while (v8 != rob_osg->nodes.end); + } + mat4_to_mat4u(rob_osg->mats, &rob_osg->mat); +} + +static void sub_1404803B0(rob_osage* rob_osg, mat4* mat, vec3* data_scale, bool a4) { + rob_osage_node* v6; // rdi + rob_osage_node* v7; // rbx + float_t v9; // xmm2_4 + skin_param* v15; // rax + float_t v16; // xmm0_4 + float_t v17; // xmm7_4 + bool v18; // cc + rob_osage_node* v19; // rbx + rob_osage_node* v20; // rsi + rob_osage_node* v29; // rbx + rob_osage_node* v30; // rsi + int* v31; // r14 + unsigned __int8 v32; // r13 + float_t v33; // xmm0_4 + float_t v34; // xmm2 + float_t v35; // xmm1_4 + bool v36; // r15 + rob_osage_node* v39; // rax + vec3 src; // [rsp+40h] [rbp-C0h] BYREF + vec3 v45; // [rsp+68h] [rbp-98h] BYREF + vec3 dst; // [rsp+78h] [rbp-88h] BYREF + mat4 v47; // [rsp+90h] [rbp-70h] BYREF + + v6 = rob_osg->nodes.end; + v7 = rob_osg->nodes.begin; + v9 = rob_osg->exp_data.position.y * data_scale->y; + v47 = *mat; + vec3_mult(rob_osg->exp_data.position, *data_scale, src); + mat4_mult_vec3_trans(&v47, &src, &dst); + v7->trans.x = dst.x; + v7->trans.y = dst.y; + v7->trans.z = dst.z; + if (rob_osg->field_1F0D && !rob_osg->field_1F0E) { + rob_osg->field_1F0E = true; + sub_14047EE90(rob_osg, mat); + } + + if (!rob_osg->field_1F0C) { + v15 = rob_osg->skin_param_ptr; + v16 = rob_osg->field_1F08; + rob_osg->field_1F0C = true; + v17 = v15->move_cancel; + if (v16 == 1.0) + v17 = v16; + v18 = v17 <= 0.0; + if (v17 < 0.0) { + v17 = v16; + v18 = v16 <= 0.0; + } + + if (!v18) { + v19 = rob_osg->nodes.begin + 1; + if (v19 != v6) { + v20 = rob_osg->nodes.begin + 1; + do { + mat4 mat; + mat4u_to_mat4(&rob_osg->mat, &mat); + mat4_mult_vec3_inv(&mat, &v20->trans, &dst); + mat4_mult_vec3_trans(&rob_osg->mats[0], &dst, &v45); + vec3_sub(v45, v20->trans, v45); + vec3_mult_scalar(v45, v17, v45); + vec3_add(v20->trans, v45, v20->trans); + ++v19; + ++v20; + } while (v19 != v6); + } + } + } + + if (a4) { + sub_14047F110(rob_osg, &v47, data_scale, false); + *rob_osg->nodes.begin->bone_node_mat = v47; + v29 = rob_osg->nodes.begin + 1; + if (v29 != v6) { + v30 = rob_osg->nodes.begin; + v31 = &rob_osg->field_1EB8; + do { + mat4_mult_vec3_inv(&v47, &v30[1].trans, &v45); + v32 = sub_140482FF0(&v47, &v45, &v30[1].data_ptr->skp_osg_node.hinge, &v30[1].field_B8, v31); + *v30[1].bone_node->ex_data_mat = v47; + v33 = v30[1].trans.y - v30->trans.y; + v34 = v30[1].trans.x; + v34 = (v34 - v30->trans.x) * (v34 - v30->trans.x) + + (v33 * v33) + + ((v30[1].trans.z - v30->trans.z) + * (v30[1].trans.z - v30->trans.z)); + v35 = data_scale->x * v29->length; + if (v34 >= (v35 * v35)) { + v35 = sqrtf(v34); + v36 = 0; + } + else { + v36 = 1; + } + mat4_translate_mult(&v47, v35, 0.0, 0.0, &v47); + if (v32 || v36) + mat4_get_translation(&v47, &v30[1].trans); + ++v29; + ++v30; + } while (v29 != v6); + rob_osg = rob_osg; + } + v39 = rob_osg->nodes.end; + if (rob_osg->nodes.begin != v39 && rob_osg->node.bone_node_mat) + mat4_translate_mult(v39[-1].bone_node->ex_data_mat, + data_scale->x * rob_osg->node.length, 0.0f, 0.0f, + rob_osg->node.bone_node->ex_data_mat); + } +} + +static void sub_140482300(vec3* a1, vec3* a2, vec3* a3, float_t osage_gravity_const, float_t weight) { + float_t v5; // xmm3_4 + float_t v6; // xmm2 + float_t v7; // xmm6_4 + float_t v8; // xmm0_4 + float_t v9; // xmm5_4 + float_t v10; // xmm1_4 + float_t v11; // xmm2 + float_t v12; // [rsp+4h] [rbp-3Ch] + float_t v13; // [rsp+4h] [rbp-3Ch] + + v5 = osage_gravity_const; + v7 = osage_gravity_const * weight; + v8 = a2->x - a3->x; + v12 = a2->y - a3->y; + v9 = a2->z - a3->z; + v6 = v12 * v12 + v8 * v8 + v9 * v9; + v10 = sqrtf(v6); + if (v10 > fabsf(osage_gravity_const)) + v5 = v12; + else { + v11 = v8 * v8 + osage_gravity_const * osage_gravity_const + v9 * v9; + v10 = sqrtf(v11); + } + v10 = 1.0f / v10; + v13 = v5 * v10; + a1->x = -v8 * v10 * v13 * v7; + a1->y = -v7 - v13 * v13 * v7; + a1->z = -v9 * v10 * v13 * v7; +} + +static void sub_140482F30(vec3* a1, vec3* a2, float_t a3) { + vec3 v5; + vec3_sub(*a1, *a2, v5); + + float_t length; + vec3_length_squared(v5, length); + if (length > (a3 * a3)) { + vec3_mult_scalar(v5, a3 / sqrtf(length), v5); + vec3_add(*a2, v5, *a1); + } +} + +static void sub_140482490(rob_osage_node* node, float_t* osage_phys_step, float_t* a3) { + if (*osage_phys_step != 1.0) { + vec3 v4; + vec3_sub(node->trans, node->field_10, v4); + + float_t length; + vec3_length(v4, length); + if (length != 0.0) + vec3_mult_scalar(v4, 1.0f / length, v4); + + vec3_mult_scalar(v4, *osage_phys_step * length, v4); + vec3_add(node->field_10, v4, node->trans); + } + sub_140482F30(&node->trans, &node[-1].trans, node->length * *a3); + + if (node->sibling_node) + sub_140482F30(&node->trans, &node->sibling_node->trans, node->distance); + +} + +static void sub_140482180(rob_osage_node* node, float_t* a2) { + float_t v2 = node->data_ptr->skp_osg_node.coli_r + *a2; + if (v2 <= node->trans.y) + return; + + node->trans.y = v2; + + vec3 v3; + vec3_sub(node->trans, node[-1].trans, v3); + + float_t length; + vec3_length_squared(v3, length); + if (length > 0.000001f) + vec3_mult_scalar(v3, 1.0f / sqrtf(length), v3); + vec3_mult_scalar(v3, node->length, v3); + vec3_add(node[-1].trans, v3, node->trans); + node->field_1C = vec3_null; + node->field_C8 += 1.0f; +} + +static void sub_14047C800(rob_osage* rob_osg, mat4* mat, vec3* data_scale, float_t osage_phys_step, bool a5, bool a6, bool a7) { + rob_osage_node* v7; // rax + rob_osage_node* v12; // rdi + float_t osage_gravity_const; // xmm0_4 + rob_osage_node* v17; // rcx + vec4 v18; // xmm1 + vec4 v19; // xmm2 + rob_osage_node* v20; // rbx + float_t v21; // xmm0_4 + rob_osage_node* v22; // rax + float_t v25; // xmm9_4 + rob_osage_node* v26; // rbx + bool v27; // r13 + float_t v28; // xmm12_4 + rob_osage_node* v30; // rsi + rob_osage_node_data* v31; // r15 + float_t v32; // xmm8_4 + float_t v33; // xmm5_4 + float_t v34; // xmm6_4 + float_t v35; // xmm7_4 + float_t v36; // xmm2_4 + float_t v38; // xmm2_4 + skin_param* v39; // rax + float_t v40; // xmm4_4 + float_t v41; // xmm3_4 + float_t v42; // xmm6_4 + float_t v43; // xmm7_4 + float_t v44; // xmm5_4 + float_t v45; // xmm0_4 + float_t v46; // xmm1_4 + float_t v47; // xmm3_4 + float_t v48; // xmm1_4 + float_t v49; // xmm2_4 + float_t v50; // xmm0_4 + float_t v51; // xmm1_4 + vec4 v52; // xmm2 + vec4 v53; // xmm3 + vec4 v54; // xmm4 + rob_osage_node* v55; // rbx + vec4 v56; // xmm5 + float_t v57; // xmm12_4 + float_t v58; // er12 + vec2 v59; // r13 + rob_osage_node* v60; // rsi + float_t v61; // eax + float_t v62; // eax + float_t v63; // eax + float_t v64; // xmm3_4 + float_t v65; // xmm4_4 + float_t v68; // xmm8_4 + rob_osage_node_data* v70; // rcx + float_t v71; // xmm0_4 + float_t v72; // xmm1_4 + float_t v73; // xmm0_4 + float_t v74; // xmm2_4 + rob_osage_node* v82; // rax + rob_osage_node* v83; // rdx + rob_osage_node* i; // rbx + rob_osage_node* v91; // rbx + float_t v92; // xmm4_4 + float_t v93; // xmm2_4 + float_t v94; // xmm1_4 + float_t v95; // xmm0_4 + float_t v96; // xmm3_4 + float_t v97; // xmm0_4 + rob_osage_node* v98; // rbx + rob_osage_node* v99; // rbx + rob_osage_node* v100; // rsi + int* v101; // r14 + unsigned __int8 v102; // r13 + float_t v103; // xmm0_4 + float_t v104; // xmm2 + float_t v105; // xmm1_4 + char v106; // r12 + rob_osage_node* v109; // rax + vec3 a1a; // [rsp+30h] [rbp-D0h] BYREF + vec3 v112; // [rsp+40h] [rbp-C0h] BYREF + vec3 src; // [rsp+50h] [rbp-B0h] BYREF + vec2 v114; // [rsp+60h] [rbp-A0h] + float_t v115; // [rsp+68h] [rbp-98h] + vec3 v116; // [rsp+70h] [rbp-90h] + vec3 v117; // [rsp+80h] [rbp-80h] + float_t a3a; // [rsp+90h] [rbp-70h] BYREF + vec3 v119; // [rsp+98h] [rbp-68h] BYREF + vec3 v120; // [rsp+B0h] [rbp-50h] + vec3 v126; // [rsp+E8h] [rbp-18h] BYREF + vec3 dst; // [rsp+100h] [rbp+0h] BYREF + vec3 v128; // [rsp+110h] [rbp+10h] BYREF + vec3 a2a; // [rsp+120h] [rbp+20h] BYREF + mat4 v130; // [rsp+130h] [rbp+30h] BYREF + mat4 v131; // [rsp+170h] [rbp+70h] BYREF + mat4 v132; // [rsp+1B0h] [rbp+B0h] BYREF + + v7 = rob_osg->nodes.end; + if (rob_osg->nodes.begin == v7) + return; + + sub_1404803B0(rob_osg, mat, data_scale, 0); + v12 = rob_osg->nodes.end; + osage_gravity_const = get_osage_gravity_const(); + v17 = rob_osg->nodes.begin; + v130 = *mat; + v18.x = rob_osg->exp_data.position.x; + v17->field_10 = v17->trans; + v20 = rob_osg->nodes.begin; + src.x = rob_osg->exp_data.position.x * data_scale->x; + src.y = rob_osg->exp_data.position.y * data_scale->y; + src.z = rob_osg->exp_data.position.z * data_scale->z; + mat4_mult_vec3_trans(&v130, &src, &dst); + v18.x = dst.y; + v20->trans.x = dst.x; + v21 = dst.z; + v20->trans.y = v18.x; + v20->trans.z = v21; + v22 = rob_osg->nodes.begin; + v18.x = v22->trans.y - v22->field_10.y; + v19.x = v22->trans.z - v22->field_10.z; + v22->field_1C.x = v22->trans.x - v22->field_10.x; + v22->field_1C.y = v18.x; + v22->field_1C.z = v19.x; + sub_14047F110(rob_osg, &v130, data_scale, 0); + *rob_osg->nodes.begin->bone_node_mat = v130; + *rob_osg->nodes.begin->bone_node->ex_data_mat = v130; + src = (vec3){ 1.0f, 0.0f, 0.0f }; + mat4_mult_vec3(&v130, &src, &v128); + v25 = data_scale->x; + a3a = data_scale->x; + if (!rob_osg->field_1F0D && osage_phys_step <= 0.0f) + return; + + v26 = rob_osg->nodes.begin + 1; + if (v26 != v12) { + v27 = a5; + v28 = 0.5f; + v30 = rob_osg->nodes.begin; + do { + v31 = v30[1].data_ptr; + a1a = vec3_null; + v32 = v31->skp_osg_node.weight; + if (!rob_osg->field_1F78) { + sub_140482300( + &a1a, + &v30[1].trans, + &v30->trans, + osage_gravity_const, + v31->skp_osg_node.weight); + + if (v26 == &v12[-1]) { + v35 = a1a.z; + v34 = a1a.y; + v33 = a1a.x; + } + else { + sub_140482300(&v112, &v30[1].trans, &v30[2].trans, osage_gravity_const, v32); + v33 = (a1a.x + v112.x) * v28; + v34 = (a1a.y + v112.y) * v28; + v35 = (a1a.z + v112.z) * v28; + } + } + else { + v33 = rob_osg->field_1F7C.x * (1.0f / v32); + v34 = rob_osg->field_1F7C.y * (1.0f / v32); + v35 = rob_osg->field_1F7C.z * (1.0f / v32); + } + v36 = v31->force; + v38 = v30[1].field_DC; + v39 = rob_osg->skin_param_ptr; + v40 = 1.0f - rob_osg->skin_param_ptr->air_res; + v41 = (1.0f - rob_osg->field_1EB4) * v40; + v42 = ((v34 + (v128.y * v36 * v38)) - (v30[1].field_1C.y * v41)) + (v30[1].field_D0.y * v32); + v43 = ((v35 + (v128.z * v36 * v38)) - (v30[1].field_1C.z * v41)) + (v30[1].field_D0.z * v32); + v44 = ((v33 + (v128.x * v36 * v38)) - (v30[1].field_1C.x * v41)) + (v30[1].field_D0.x * v32); + v126.y = v42; + v126.z = v43; + v126.x = v44; + if (!v27) { + v45 = v39->wind_afc; + v44 = v44 + (rob_osg->wind_direction.x * v45); + v42 = v42 + (rob_osg->wind_direction.y * v45); + v43 = v43 + (rob_osg->wind_direction.z * v45); + v126.x = v44; + v126.y = v42; + v126.z = v43; + } + + if (v39->stiffness > 0.0) { + v46 = v30[1].field_1C.z - v30->field_1C.z; + v47 = v30[1].field_1C.x - v30->field_1C.x; + v114.y = v30[1].field_1C.y - v30->field_1C.y; + v115 = v46; + v114.x = v47; + *(vec2*)&v116.x = v114; + v116.z = v46; + v44 = v44 - (v40 * v47); + v126.x = v44; + v126.y = v42 - (v114.y * v40); + v126.z = v43 - (v46 * v40); + } + v48 = v31->skp_osg_node.weight; + v117 = v126; + ++v26; + ++v30; + v49 = 1.0f / (v48 - (v48 - 1.0f) * v31->skp_osg_node.inertial_cancel); + v50 = v126.y * v49; + v51 = v126.z * v49; + v30->field_28.x = v49 * v44; + v30->field_28.y = v50; + v30->field_28.z = v51; + } while (v26 != v12); + } + + if (rob_osg->skin_param_ptr->stiffness > 0.0) { + v52 = v130.row0; + v53 = v130.row1; + v54 = v130.row2; + v55 = rob_osg->nodes.begin + 1; + v56 = v130.row3; + v131 = v130; + mat4_get_translation(&v130, &a1a); + if (v55 != v12) { + v58 = a1a.z; + v59 = *(vec2*)&a1a.x; + v60 = v55; + while (1) { + v61 = v60->field_94.x; + v132.row0 = v52; + v132.row1 = v53; + v132.row2 = v54; + v119.x = v61; + v62 = v60->field_94.y; + v132.row3 = v56; + v119.y = v62; + v63 = v60->field_94.z; + v119.z = v63; + mat4_mult_vec3_trans(&v132, &v119, &v128); + v68 = v60->field_1C.x + v60->field_28.x; + v64 = v60->field_1C.y + v60->field_28.y; + v65 = v60->field_1C.z + v60->field_28.z; + v126.x = v60->trans.x + v68; + v126.y = v60->trans.y + v64; + v126.z = v60->trans.z + v65; + sub_140482F30(&v126, &a1a, v25 * v55->length); + v70 = v60->data_ptr; + v71 = rob_osg->skin_param_ptr->stiffness; + v72 = v70->skp_osg_node.weight; + vec3_sub(v128, v126, v117); + vec3_mult_scalar(v117, v71, v117); + v120 = v117; + v73 = (v72 - 1.0f) * v70->skp_osg_node.inertial_cancel; + v74 = 1.0f / (v72 - v73); + v60->field_28.x += v117.x * v74; + v60->field_28.y += v117.y * v74; + v60->field_28.z += v117.z * v74; + v116.x = v60->trans.x + v117.x * v74 + v68; + v116.y = v60->trans.y + v117.y * v74 + v64; + v116.z = v60->trans.z + v117.z * v74 + v65; + v126 = v116; + mat4_mult_vec3_inv(&v131, &v116, &a2a); + sub_140482FF0(&v131, &a2a, 0, 0, &rob_osg->field_1EB8); + *(vec2*)&src.x = v59; + src.z = v58; + mat4_translate_mult( + &v131, + sqrtf((v59.x - v126.x) * (v59.x - v126.x) + + (v59.y - v126.y) * (v59.y - v126.y) + + (v58 - v126.z) * (v58 - v126.z)), + 0.0f, + 0.0f, &v131); + v59 = *(vec2*)&v126.x; + v58 = v126.z; + ++v55; + ++v60; + a1a = v126; + if (v55 == v12) + break; + v56 = v131.row3; + v54 = v131.row2; + v53 = v131.row1; + v57 = a1a.x; + v52 = v131.row0; + } + } + } + v82 = rob_osg->nodes.begin + 1; + if (v82 != v12) { + v83 = rob_osg->nodes.begin + 1; + do { + ++v82; + ++v83; + v83->field_10.x = v83->trans.x; + v83->field_10.y = v83->trans.y; + v83->field_10.z = v83->trans.z; + vec3_add(v83->field_1C, v83->field_28, v83->field_1C); + vec3_add(v83->trans, v83->field_1C, v83->trans); + } while (v82 != v12); + } + for (i = v12 - 2; i != rob_osg->nodes.begin; --i) + sub_140482F30(&i->trans, &i[1].trans, v25 * i->child_length); + + if (a6) { + v91 = rob_osg->nodes.begin; + v92 = v91->trans.x; + v93 = v91->data_ptr->skp_osg_node.coli_r; + v94 = rob_osg->ring.ring_rectangle_x - v93; + v95 = rob_osg->ring.ring_rectangle_y - v93; + if (v92 < v94 + || (v96 = v91->trans.z, v96 < v95) + || v92 >(v94 + rob_osg->ring.ring_rectangle_width + v93) + || v96 > (v95 + rob_osg->ring.ring_rectangle_height + v93)) + v97 = rob_osg->ring.ring_out_height; + else + v97 = rob_osg->ring.ring_height; + + v98 = v91 + 1; + for (v126.x = v97 + v93; v98 != v12; ++v98) { + sub_140482490(v98, &osage_phys_step, &a3a); + sub_140482180(v98, &v126.x); + } + } + + if (a7) { + v99 = rob_osg->nodes.begin + 1; + if (v99 != v12) { + v100 = rob_osg->nodes.begin; + v101 = &rob_osg->field_1EB8; + do { + mat4_mult_vec3_inv(&v130, &v100[1].trans, &a2a); + v102 = sub_140482FF0( + &v130, + &a2a, + &v100[1].data_ptr->skp_osg_node.hinge, + &v100[1].field_B8, + v101); + *v100[1].bone_node->ex_data_mat = v130; + v103 = v100[1].trans.y - v100->trans.y; + v104 = (((v100[1].trans.x - v100->trans.x) * (v100[1].trans.x - v100->trans.x)) + + (v103 * v103)) + ((v100[1].trans.z - v100->trans.z) + * (v100[1].trans.z - v100->trans.z)); + v105 = v25 * v99->length; + if (v104 >= (v105 * v105)) { + v105 = sqrtf(v104); + v106 = 0; + } + else + v106 = 1; + mat4_translate_mult(&v130, v105, 0.0f, 0.0f, &v130); + if (v102 || v106) + mat4_get_translation(&v130, &v100[1].trans); + ++v99; + ++v100; + } while (v99 != v12); + rob_osg = rob_osg; + } + v109 = rob_osg->nodes.end; + if (rob_osg->nodes.begin != v109 && rob_osg->node.bone_node_mat) { + mat4_translate_mult(v109[-1].bone_node->ex_data_mat, + v25 * rob_osg->node.length, 0.0f, 0.0f, + rob_osg->node.bone_node->ex_data_mat); + } + } + rob_osg->field_2A0 = false; +} + +static bool sub_140483DE0(vec3* a1, vec3* a2, vec3* a3, float_t radius) { + vec3 v5; + float_t length; + vec3_sub(*a2, *a3, v5); + vec3_length_squared(v5, length); + if (fabs(length) > 0.000001 && length < radius * radius) { + vec3_mult_scalar(v5, radius / sqrtf(length) - 1.0f, *a1); + return true; + } + return false; +} + +static bool sub_140484540(vec3* a1, vec3* a2, osage_coli* a3, float_t radius) { + vec3 v11; + vec3_sub(*a2, a3->bone0_pos, v11); + + float_t v17; + vec3_dot(v11, a3->bone_pos_diff, v17); + if (v17 < 0.0f) + return sub_140483DE0(a1, a2, &a3->bone0_pos, radius); + else if (fabsf(a3->bone_pos_diff_length_squared) <= 0.000001f) + return sub_140483DE0(a1, a2, &a3->bone0_pos, radius); + else if (v17 > a3->bone_pos_diff_length_squared) + return sub_140483DE0(a1, a2, &a3->bone1_pos, radius); + + float_t v20; + vec3_length_squared(v11, v20); + v20 += (v17 * v17) / a3->bone_pos_diff_length_squared; + if (v20 <= 0.000001f || v20 >= radius * radius) + return false; + + vec3 v29; + vec3_mult_scalar(a3->bone_pos_diff, v17 / a3->bone_pos_diff_length_squared, v29); + vec3_sub(v11, v29, v29); + vec3_mult_scalar(v29, radius / sqrtf(v20) - 1.0f, *a1); + return true; +} + +static bool sub_140484780(vec3* a1, vec3* a2, vec3* a3, vec3* a4, float_t radius) { + float v5; // xmm8_4 + float v6; // xmm8_4 + __int64 result; // rax + float_t v8; // xmm1_4 + float_t v9; // xmm2_4 + + float_t v3; + vec3_dot(*a2, *a4, v3); + float_t v4; + vec3_dot(*a3, *a4, v4); + v5 = v3 - v4 - radius; + if (v5 >= 0.0f) + return false; + + vec3_mult_scalar(*a4, -v5, *a1); + return true; +} + +static bool sub_140483EA0(vec3* a1, vec3* a2, osage_coli* a3, float_t radius) { + float v4; // xmm14_4 + float v6; // xmm0_4 + float v7; // xmm10_4 + float v8; // xmm2_4 + float v9; // xmm3_4 + bool v11; // r9 + vec4 v12; // xmm5 + float v13; // xmm6_4 + vec4 v14; // xmm8 + vec4 v15; // xmm0 + float_t v16; // xmm1_4 + float v17; // er11 + float v18; // r10^4 + vec4 v19; // xmm1 + float v20; // xmm15_4 + vec4 v21; // xmm11 + vec4 v22; // xmm7 + float v23; // xmm2_4 + float v24; // xmm3_4 + float v25; // xmm0_4 + float_t v26; // xmm14_4 + float v27; // xmm3_4 + vec4 v28; // xmm10 + float v29; // xmm2_4 + vec4 v30; // xmm0 + float v31; // xmm2_4 + float v32; // xmm1_4 + float v33; // xmm0_4 + float v34; // xmm10_4 + float v35; // xmm1_4 + float v36; // xmm1_4 + float v37; // xmm3_4 + vec4 v38; // xmm0 + float v39; // xmm2_4 + vec4 v40; // xmm0 + float v41; // xmm6_4 + vec4 v42; // xmm1 + float v43; // xmm6_4 + float v44; // xmm8_4 + float v45; // xmm2_4 + float v46; // xmm3_4 + vec4 v47; // xmm0 + vec2 v48; // rax + float v49; // edx + float v50; // xmm1_4 + vec2 v51; // [rsp+20h] [rbp-E0h] + vec2 v52; // [rsp+20h] [rbp-E0h] + float v53; // [rsp+28h] [rbp-D8h] + vec2 v54; // [rsp+30h] [rbp-D0h] + vec2 v55; // [rsp+30h] [rbp-D0h] + vec2 v56; // [rsp+40h] [rbp-C0h] + vec2 v57; // [rsp+40h] [rbp-C0h] + float v58; // [rsp+50h] [rbp-B0h] + float v59; // [rsp+54h] [rbp-ACh] + float v60; // [rsp+58h] [rbp-A8h] + float v61; // [rsp+5Ch] [rbp-A4h] + float v62; // [rsp+60h] [rbp-A0h] + vec3 a3a; // [rsp+70h] [rbp-90h] BYREF + + v4 = a3->bone_pos_diff_length; + v6 = fabs(a3->bone_pos_diff_length); + v7 = a3->bone0_pos.x; + v8 = a3->bone0_pos.y; + v9 = a3->bone0_pos.z; + a3a.x = v7; + a3a.y = v8; + a3a.z = v9; + if (v6 <= 0.000001) + return sub_140483DE0(a1, a2, &a3a, radius); + v11 = 0; + v14.x = a2->x; + v12.x = a2->x - a3->bone1_pos.x; + v61 = (v4 * 0.5) * (v4 * 0.5); + v13 = fsqrt((radius * radius) + v61); + v14.x = a2->x - v7; + v15 = v14; + v16 = a2->y - v8; + v17 = a2->z - v9; + v53 = a2->z - a3->bone1_pos.z; + v15.x = (v14.x * v14.x) + (v16 * v16); + v51.y = a2->y - a3->bone1_pos.y; + v56 = (vec2)__PAIR64__(LODWORD(v16), LODWORD(v14.x)); + v18 = v16; + v19 = v12; + v54 = v56; + v15.x = v15.x + (v17 * v17); + v51.x = v12.x; + v57 = v51; + v20 = _mm_sqrt_ps((__m128)v15).m128_f32[0]; + v19.x = ((v12.x * v12.x) + (v51.y * v51.y)) + (v53 * v53); + v21 = (vec4)_mm_sqrt_ps((__m128)v19); + if (fabs(v20) <= 0.000001 || fabs(v21.x) <= 0.000001) + return 0; + v22 = v21; + v22.x = v21.x + v20; + if ((v21.x + v20) < (v13 * 2.0)) { + v23 = a3->bone_pos_diff.y; + v24 = a3->bone_pos_diff.z; + v25 = 1.0 / v4; + v26 = a3->bone1_pos.x + v7; + v28 = (vec4)LODWORD(a2->x); + v52.x = v26; + v52.y = a3a.y + a3->bone1_pos.y; + v62 = a3->bone_pos_diff.x * v25; + *(vec2*)&a3a.x = v52; + v60 = v23 * v25; + v59 = v24 * v25; + a3a.z = a3a.z + a3->bone1_pos.z; + v27 = a2->z; + v28.x = v28.x - (v26 * 0.5); + v29 = a2->y; + a3a.x = v28.x; + v30 = v28; + a3a.y = v29 - (v52.y * 0.5); + v30.x = ((v28.x * v28.x) + (a3a.y * a3a.y)) + + ((v27 - (a3a.z * 0.5)) * (v27 - (a3a.z * 0.5))); + v31 = v27 - (a3a.z * 0.5); + v32 = _mm_sqrt_ps((__m128)v30).m128_f32[0]; + v58 = v32; + if (v32 == 0.0) { + v35 = a3a.y; + v34 = a3a.x; + } + else { + v33 = 1.0 / v32; + v34 = v28.x * (1.0 / v32); + v35 = a3a.y * (1.0 / v32); + v31 = v31 * v33; + } + v36 = ((v35 * v60) + (v62 * v34)) + (v31 * v59); + v37 = v36 * v36; + if ((v36 * v36) >= 1.0) + v37 = 1.0; + v22.x = v22.x * 0.5; + v38 = v22; + v38.x = (v22.x * v22.x) - v61; + if (v38.x < 0.0) + return 0; + v39 = _mm_sqrt_ps((__m128)v38).m128_f32[0]; + if (fabs(v39) <= 0.000001) + return 0; + v40 = (vec4)0x3F800000u; + v40.x = 1.0 - v37; + v41 = ((v13 / v22.x) - 1.0) * (v36 * v58); + v42 = (vec4)_mm_sqrt_ps((__m128)v40); + v42.x = (((v42.x * v58) * ((radius / v39) - 1.0)) + * ((v42.x * v58) * ((radius / v39) - 1.0))) + + (v41 * v41); + LODWORD(v43) = _mm_sqrt_ps((__m128)v42).m128_u32[0]; + if (v20 == 0.0) { + v44 = v54.x; + } + else { + v44 = v14.x * (1.0 / v20); + v18 = v54.y * (1.0 / v20); + v17 = v17 * (1.0 / v20); + } + v45 = v57.y; + v46 = v53; + if (v21.x == 0.0) { + v12 = (vec4)LODWORD(v57.x); + } + else { + v12.x = v12.x * (1.0 / v21.x); + v45 = v57.y * (1.0 / v21.x); + v46 = v53 * (1.0 / v21.x); + } + v12.x = v12.x + v44; + v47 = v12; + v48 = (vec2)__PAIR64__(v18 + v45, LODWORD(v12.x)); + v49 = v17 + v46; + v47.x = ((v12.x * v12.x) + ((v18 + v45) * (v18 + v45))) + + ((v17 + v46) * (v17 + v46)); + v50 = _mm_sqrt_ps((__m128)v47).m128_f32[0]; + if (v50 != 0.0) { + v12.x = v12.x * (1.0 / v50); + v55.x = v12.x; + v55.y = (v18 + v45) * (1.0 / v50); + v48 = v55; + v49 = (v17 + v46) * (1.0 / v50); + } + *(vec2*)&a3a.x = v48; + a3a.z = v49; + v11 = 1; + a1->x = v12.x * v43; + a1->y = v48.y * v43; + a1->z = v49 * v43; + } + return v11; +} + +int32_t sub_140485220(vec3* a1, float_t* radius, osage_coli* a3, float_t* a4) { + if (!a3) + return 0; + + int32_t v8 = 0; + while (a3->type) { + int32_t v11 = 0; + vec3 v31 = vec3_null; + switch (a3->type) { + case 1: + v11 = sub_140483DE0(&v31, a1, &a3->bone0_pos, a3->radius + *radius); + break; + case 2: + v11 = sub_140484540(&v31, a1, a3, a3->radius + *radius); + break; + case 3: + v11 = sub_140484780(&v31, a1, &a3->bone0_pos, &a3->bone1_pos, *radius); + break; + case 4: + v11 = sub_140483EA0(&v31, a1, a3, a3->radius + *radius); + break; + case 5: + v11 = sub_140483B30(&v31, a1, a3, *radius); + break; + } + + if (a4 && v11 > 0) { + if (a3->field_34 < *a4) + *a4 = a3->field_34; + } + a3++; + v8 += v11; + vec3_add(*a1, v31, *a1); + } + return v8; +} + +static int32_t sub_1404851C0(vec3* a1, float_t* a2, vector_osage_coli* a3, float_t* a4) { + if (a3->begin == a3->end || a3->end[-1].type) + return 0; + else + return sub_140485220(a1, a2, a3->begin, a4); +} + +static void sub_14047D8C0(rob_osage* rob_osg, mat4* mat, vec3* data_scale, float_t osage_phys_step, bool a5) { + float v9; // xmm10_4 + rob_osage_node* v16; // rax + float v17; // xmm4_4 + float v18; // xmm2_4 + float v19; // xmm1_4 + float v20; // xmm0_4 + float v21; // xmm3_4 + float v22; // xmm0_4 + float v23; // xmm9_4 + vector_rob_osage_node* v24; // r15 + rob_osage_node* v25; // rdi + rob_osage_node* v26; // rax + rob_osage_node* v27; // rsi + vec3 v28; + rob_osage_node* v30; // rbx + rob_osage_node* v35; + float v37; // xmm6_4 + bool v39; // al + mat4* v41; // rax + float v42; // xmm7_4 + float_t v44; // xmm2 + bool v45; // di + float_t v55; // xmm2 + rob_osage_node* v59; // rax + float_t v60; // [rsp+30h] [rbp-D0h] BYREF + vec3 src; // [rsp+40h] [rbp-C0h] BYREF + vec3 dst; // [rsp+50h] [rbp-B0h] BYREF + vec3 v63; // [rsp+60h] [rbp-A0h] BYREF + mat4 v64; // [rsp+70h] [rbp-90h] BYREF + + if (!rob_osg->field_1F0D && osage_phys_step <= 0.0f) + return; + + v9 = 0.0f; + if (osage_phys_step > 0.0f) + v9 = 1.0f / osage_phys_step; + + if (a5) + v64 = *rob_osg->nodes.begin[0].bone_node_mat; + else { + vec3_mult(rob_osg->exp_data.position, *data_scale, src); + v64 = *mat; + mat4_mult_vec3_trans(&v64, &src, &rob_osg->nodes.begin[0].trans); + sub_14047F110(rob_osg, &v64, data_scale, 0); + } + + v60 = -1000.0f; + if (a5) { + v16 = &rob_osg->nodes.begin[0]; + v17 = v16->trans.x; + v18 = v16->data_ptr->skp_osg_node.coli_r; + v19 = rob_osg->ring.ring_rectangle_x - v18; + v20 = rob_osg->ring.ring_rectangle_y - v18; + v21 = v16->trans.z; + if (v17 < v19 + || v21 < v20 + || v17 > (v19 + rob_osg->ring.ring_rectangle_width) + v18 + || v21 > (v20 + rob_osg->ring.ring_rectangle_height) + v18) + v22 = rob_osg->ring.ring_out_height; + else + v22 = rob_osg->ring.ring_height; + v60 = v22 + v18; + } + v23 = 0.2f; + if (osage_phys_step < 1.0) + v23 = 0.2f / (2.0f - osage_phys_step); + v24 = rob_osg->skin_param_ptr->colli_tgt_osg; + if (v24) { + v25 = rob_osg->nodes.begin + 1; + if (v25 != rob_osg->nodes.end) { + v26 = v24->end; + v27 = rob_osg->nodes.begin + 1; + do { + v28 = vec3_null; + v30 = v24->begin + 1; + dst = vec3_null; + if (v30 != v26) { + do { + sub_140483DE0( + &dst, + &v27->trans, + &v30->trans, + v27->data_ptr->skp_osg_node.coli_r + v30->data_ptr->skp_osg_node.coli_r); + v26 = v24->end; + ++v30; + } while (v30 != v26); + v28 = dst; + } + vec3_add(v28, v27->trans, v27->trans); + ++v25; + ++v27; + } while (v25 != rob_osg->nodes.end); + } + } + v35 = rob_osg->nodes.begin + 1; + if (v35 != rob_osg->nodes.end) { + do { + v37 = (1.0f - rob_osg->field_1EB4) * rob_osg->skin_param_ptr->friction; + if (a5) { + sub_140482490(v35, &osage_phys_step, &data_scale->x); + v35->field_C8 += (float_t)sub_1404851C0( + &v35->trans, + &v35->data_ptr->skp_osg_node.coli_r, + &rob_osg->ring.coli, + &v35->field_CC); + if (!rob_osg->field_1F0F) { + v35->field_C8 += (float_t)sub_140485180( + rob_osg->coli_ring, + &v35->trans, + &v35->data_ptr->skp_osg_node.coli_r); + v35->field_C8 += (float_t)sub_140485180( + rob_osg->coli, + &v35->trans, + &v35->data_ptr->skp_osg_node.coli_r); + } + sub_140482180(v35, &v60); + } + else + sub_140482F30(&v35->trans, &v35[-1].trans, v35->length * data_scale->x); + + mat4_mult_vec3_inv(&v64, &v35->trans, &v63); + v39 = sub_140482FF0(&v64, &v63, &v35->data_ptr->skp_osg_node.hinge, &v35->field_B8, &rob_osg->field_1EB8); + v35->bone_node->exp_data.data_scale = *data_scale; + *v35->bone_node->ex_data_mat = v64; + v41 = v35->bone_node_mat; + if (v41) + mat4_scale_rot(&v64, data_scale->x, data_scale->y, data_scale->z, v41); + v42 = v35->length * data_scale->x; + vec3 v43; + vec3_sub(v35->trans, v35[-1].trans, v43); + vec3_length_squared(v43, v44); + if (v44 >= (v42 * v42)) { + v42 = sqrtf(v44); + v45 = false; + } + else + v45 = true; + mat4_translate_mult(&v64, v42, 0.0, 0.0, &v64); + v35->field_C4 = v42; + if (v39 || v45) + mat4_get_translation(&v64, &v35->trans); + + vec3_sub(v35->trans, v35->field_10, v35->field_1C); + vec3_mult_scalar(v35->field_1C, v9, v35->field_1C); + if (v35->field_C8 > 0.0) { + if (v35->field_CC < v37) + v37 = v35->field_CC; + vec3_mult_scalar(v35->field_1C, v37, v35->field_1C); + } + vec3_length_squared(v35->field_1C, v55); + if (v55 > v23 * v23) + vec3_mult_scalar(v35->field_1C, v23 / sqrtf(v55), v35->field_1C); + + mat4_mult_vec3_inv(mat, &v35->trans, &v35->field_A0); + sub_1400B39E0(mat, &v35->field_1C, &v35->field_AC); + ++v35; + } while (v35 != rob_osg->nodes.end); + } + + v59 = rob_osg->nodes.end; + if (rob_osg->nodes.begin != v59 && rob_osg->node.bone_node_mat) { + mat4 v65 = *v59[-1].bone_node->ex_data_mat; + mat4_translate_mult(&v65, rob_osg->node.length * data_scale->x, 0.0, 0.0, &v65); + *rob_osg->node.bone_node->ex_data_mat = v65; + mat4_scale_rot(&v65, data_scale->x, data_scale->y, data_scale->z, &v65); + *rob_osg->node.bone_node_mat = v65; + rob_osg->node.bone_node->exp_data.data_scale = *data_scale; + } +} + +static void sub_14047C770(rob_osage* a1, mat4* a2, vec3* a3, float_t osage_phys_step, bool a5) { + sub_14047C800(a1, a2, a3, osage_phys_step, a5, 0, 0); + sub_14047D8C0(a1, a2, a3, osage_phys_step, true); + sub_140480260(a1, a2, a3, osage_phys_step, a5); +} + +static void ex_osage_block_update(ex_osage_block* osg) { + osg->field_1FF8 &= ~2; + if (osg->base.set_data) { + osg->base.set_data = false; + return; + } + + rob_chara_data_item_equip* v2 = osg->base.item_equip_object->item_equip; + float_t osage_phys_step = get_delta_frame() * v2->osage_phys_step; + //if (v2->field_940.begin != v2->field_940.end && v4->field_C) + // osage_phys_step = 1.0f; + bone_node* v6 = osg->base.parent_bone_node; + vec3 data_scale = v6->exp_data.data_scale; + vec3 scale = v6->exp_data.scale; + + mat4 mat; + mat4* v7; + if (scale.x != 1.0f || scale.y != 1.0f || scale.z != 1.0f) { + vec3_div(vec3_identity, scale, scale); + mat4_scale_rot(v6->ex_data_mat, scale.x, scale.y, scale.z, &mat); + v7 = &mat; + } + else + v7 = v6->ex_data_mat; + ex_osage_block_set_wind_direction(osg); + rob_osage_set_coli(&osg->rob, osg->mat); + sub_14047C770(&osg->rob, v7, &data_scale, osage_phys_step, false); +} + +static void ex_osage_block_dispose(ex_osage_block* osg) { + ex_osage_block_reset(osg); + rob_osage_free(&osg->rob); + ex_node_block_free(&osg->base); + free(osg); +} + +static float_t exp_abs(float_t v1) { + return fabsf(v1); +} + +static float_t exp_acos(float_t v1) { + return acosf(v1); +} + +static float_t exp_add(float_t v1, float_t v2) { + return v1 + v2; +} + +static float_t exp_and(float_t v1, float_t v2) { + return v1 != 0.0f && v2 != 0.0f ? 1.0f : 0.0f; +} + +static float_t exp_asin(float_t v1) { + return asinf(v1); +} + +static float_t exp_atan(float_t v1) { + return atanf(v1); +} + +static float_t exp_av(float_t v1) { + return v1 * 0.1f; +} + +static float_t exp_ceil(float_t v1) { + return ceilf(v1); +} + +static float_t exp_cond(float_t v1, float_t v2, float_t v3) { + return v1 != 0.0f ? v2 : v3; +} + +static float_t exp_cos(float_t v1) { + return cosf(v1); +} + +static float_t exp_div(float_t v1, float_t v2) { + return v1 / v2; +} + +static float_t exp_eq(float_t v1, float_t v2) { + return v1 == v2 ? 1.0f : 0.0f; +} + +static float_t exp_exp(float_t v1) { + return expf(v1); +} + +static float_t exp_floor(float_t v1) { + return floorf(v1); +} + +static float_t exp_fmod(float_t v1, float_t v2) { + return fmodf(v1, v2); +} + +static const exp_func_op1* exp_func_op1_find_func(string* name, const exp_func_op1* array) { + char* name_str = string_data(name); + while (array->name) { + if (!str_utils_compare(name_str, array->name)) + return array; + array++; + } + return 0; +} + +static const exp_func_op2* exp_func_op2_find_func(string* name, const exp_func_op2* array) { + char* name_str = string_data(name); + while (array->name) { + if (!str_utils_compare(name_str, array->name)) + return array; + array++; + } + return 0; +} + +static const exp_func_op3* exp_func_op3_find_func(string* name, const exp_func_op3* array) { + char* name_str = string_data(name); + while (array->name) { + if (!str_utils_compare(name_str, array->name)) + return array; + array++; + } + return 0; +} + +static float_t exp_ge(float_t v1, float_t v2) { + return v1 >= v2 ? 1.0f : 0.0f; +} + +static float_t exp_gt(float_t v1, float_t v2) { + return v1 > v2 ? 1.0f : 0.0f; +} + +static float_t exp_le(float_t v1, float_t v2) { + return v1 <= v2 ? 1.0f : 0.0f; +} + +static float_t exp_log(float_t v1) { + return logf(v1); +} + +static float_t exp_lt(float_t v1, float_t v2) { + return v1 < v2 ? 1.0f : 0.0f; +} + +static float_t exp_max(float_t v1, float_t v2) { + return max(v1, v2); +} + +static float_t exp_min(float_t v1, float_t v2) { + return min(v1, v2); +} + +static float_t exp_mul(float_t v1, float_t v2) { + return v1 * v2; +} + +static float_t exp_ne(float_t v1, float_t v2) { + return v1 != v2 ? 1.0f : 0.0f; +} + +static float_t exp_neg(float_t v1) { + return -v1; +} + +static float_t exp_or(float_t v1, float_t v2) { + return v1 != 0.0 || v2 != 0.0f ? 1.0f : 0.0f; +} + +static float_t exp_pow(float_t v1, float_t v2) { + return powf(v1, v2); +} + +static float_t exp_rand(float_t v1, float_t v2, float_t v3) { + return v1 != 0.0f ? v2 : v3; +} + +static float_t exp_rand_0_1(float_t v1) { + return 0.0f; +} + +static float_t exp_round(float_t v1) { + return roundf(v1); +} + +static float_t exp_sin(float_t v1) { + return sinf(v1); +} + +static float_t exp_sqrt(float_t v1) { + return sqrtf(v1); +} + +static float_t exp_sub(float_t v1, float_t v2) { + return v1 - v2; +} + +static float_t exp_tan(float_t v1) { + return tanf(v1); +} + +static float_t get_osage_gravity_const() { + return 0.00299444468691945f; +} + +static void mot_key_frame_interpolate(mot* a1, float_t frame, float_t* value, + mot_key_set* a4, uint32_t key_set_count, struc_369* a6) { + if (a6->field_0 == 4) { + int32_t frame_int = (int32_t)frame; + if (frame != -0.0f && (float_t)frame_int != frame) + frame = (float_t)(frame < 0.0f ? frame_int - 1 : frame_int); + } + + if (!key_set_count) + return; + + for (uint32_t i = key_set_count; i; i--, a4++, value++) { + mot_key_set_type type = a4->type; + float_t* values = a4->values; + if (type == MOT_KEY_SET_STATIC) { + *value = values[0]; + continue; + } + else if (type != MOT_KEY_SET_HERMITE && type != MOT_KEY_SET_HERMITE_TANGENT) { + *value = 0.0f; + continue; + } + + int32_t current_key = a4->current_key; + int32_t keys_count = a4->keys_count; + uint16_t* frames = a4->frames; + int32_t frame_int = (int32_t)frame; + size_t key_index; + if (current_key > keys_count + || (frame_int > a4->last_key + frames[current_key]) + || current_key > 0 && frame_int < frames[current_key - 1]) { + uint16_t* key = a4->frames; + size_t length = keys_count; + size_t temp; + while (length > 0) + if (frame_int < key[temp = length / 2]) + length /= 2; + else { + key += temp + 1; + length -= temp + 1; + } + key_index = key - frames; + } + else { + uint16_t* key = &frames[current_key]; + for (uint16_t* v17 = &frames[keys_count]; key != v17; key++) + if (frame_int < *key) + break; + key_index = key - frames; + } + + bool found = false; + if (key_index < keys_count) + for (; key_index < keys_count; key_index++) + if ((float_t)frames[key_index] >= frame) { + found = true; + break; + } + + if (found) { + float_t next_frame = (float_t)frames[key_index]; + if (fabsf(next_frame - frame) > 0.000001f && key_index > 0) { + float_t curr_frame = (float_t)frames[key_index - 1]; + float_t t = (frame - curr_frame) / (next_frame - curr_frame); + if (type == MOT_KEY_SET_HERMITE) { + values += key_index - 1; + float_t p1 = values[0]; + float_t p2 = values[1]; + *value = (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; + } + else { + values += key_index * 2 - 2; + float_t p1 = values[0]; + float_t p2 = values[2]; + float_t t1 = values[1]; + float_t t2 = values[3]; + *value = ((t - 1.0f) * t1 + t * t2) * (t - 1.0f) * (frame - curr_frame) + + (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; + } + a4->current_key = (int32_t)key_index; + continue; + } + } + + key_index--; + if (type == MOT_KEY_SET_HERMITE) + *value = values[key_index]; + else + *value = values[2 * key_index]; + a4->current_key = (int32_t)key_index; + } +} + +static uint32_t mot_load_last_key_calc(uint16_t keys_count) { + uint16_t v2 = keys_count >> 8; + uint32_t v3 = 16; + if (v2) { + v3 = 8; + keys_count = v2; + } + + if (keys_count >> 4) { + v3 -= 4; + keys_count >>= 4; + } + + if (keys_count >> 2) { + v3 -= 2; + keys_count >>= 2; + } + + if (keys_count & ~1) + keys_count = 2; + return v3 - keys_count; +} + +static bool mot_data_load_file(mot* a1, mot_data* a2) { + a1->frame_count = 0; + if (!a2) + return 0; + + uint16_t info = a2->info; + a1->frame_count = a2->frame_count; + + int32_t key_set_count = info & 0x3FFF; + bool skeleton_select = (info & 0x4000) != 0; + a1->key_set_count = key_set_count; + a1->field_4 = a2->info & 0x8000; + + mot_key_set_data* key_set_file = a2->key_set; + mot_key_set* key_set = a1->key_sets; + + for (int32_t i = 0; i < key_set_count; i++, key_set++, key_set_file++) { + key_set->type = key_set_file->type; + if (key_set->type == MOT_KEY_SET_STATIC) + key_set->values = key_set_file->values; + else if (key_set->type != MOT_KEY_SET_NONE) { + uint16_t keys_count = key_set_file->keys_count; + key_set->frames = key_set_file->frames; + key_set->values = key_set_file->values; + + key_set->keys_count = keys_count; + key_set->current_key = 0; + + uint16_t last_key = a1->frame_count; + if (keys_count > 1) { + if (keys_count > last_key) + keys_count = a1->frame_count; + last_key = (16 - mot_load_last_key_calc(keys_count)) * a1->frame_count / keys_count; + } + key_set->last_key = last_key; + } + } + return skeleton_select; +} + +static void mot_parent_get_key_set_count_by_bone_database_bones(mot_parent* a1, + vector_bone_database_bone* a2) { + size_t object_bone_count; + size_t motion_bone_count; + size_t total_bone_count; + size_t ik_bone_count; + size_t chain_pos; + bone_database_bones_calculate_count(a2, &object_bone_count, + &motion_bone_count, &total_bone_count, &ik_bone_count, &chain_pos); + mot_parent_get_key_set_count(a1, motion_bone_count, ik_bone_count); +} + +static void mot_parent_get_key_set_count(mot_parent* a1, size_t motion_bone_count, size_t ik_bone_count) { + a1->key_set_count = (motion_bone_count + ik_bone_count) * 3 + 16; +} + +static void mot_parent_init_key_sets(mot_parent* a1, bone_database_skeleton_type type, + size_t motion_bone_count, size_t ik_bone_count) { + mot_parent_get_key_set_count(a1, motion_bone_count, ik_bone_count); + mot_parent_reserve_key_sets(a1); + a1->skeleton_type = type; +} + +static void mot_parent_interpolate(mot_parent* a1, float_t frame, + uint32_t key_set_offset, uint32_t key_set_count) { + mot_key_frame_interpolate(&a1->mot, frame, + &a1->key_set_data.begin[key_set_offset], + &a1->key_set.begin[key_set_offset], key_set_count, &a1->field_68); +} + +static mot_data* mot_parent_load_file(mot_parent* a1, int32_t motion_id, motion_database* mot_db) { + if (a1->motion_id != motion_id) { + mot_data* mot_data = motion_storage_get_mot_data(motion_id, mot_db); + a1->mot_data = mot_data; + if (mot_data) { + a1->skeleton_select = mot_data_load_file(&a1->mot, mot_data); + a1->motion_id = motion_id; + } + else { + a1->skeleton_select = 0; + a1->motion_id = -1; + } + } + a1->frame = -1.0f; + a1->field_68.field_0 = 0; + a1->field_68.field_4 = 0.0f; + return a1->mot_data; +} + +static void mot_parent_reserve_key_sets(mot_parent* a1) { + vector_mot_key_set_reserve(&a1->key_set, a1->key_set_count); + a1->key_set.end += a1->key_set_count; + memset(a1->key_set.begin, 0, sizeof(mot_key_set) * a1->key_set_count); + + vector_float_t_reserve(&a1->key_set_data, a1->key_set_count); + a1->key_set_data.end += a1->key_set_count; + memset(a1->key_set_data.begin, 0, sizeof(float_t) * a1->key_set_count); + + a1->mot.key_sets = a1->key_set.begin; + a1->key_sets_ready = true; +} + +static void mot_parent_free(mot_parent* a1) { + vector_mot_key_set_free(&a1->key_set, 0); + vector_float_t_free(&a1->key_set_data, 0); +} + +static motion_blend_mot* motion_blend_mot_init() { + motion_blend_mot* mot_blend_mot = force_malloc(sizeof(motion_blend_mot)); + bone_data_parent_reset(&mot_blend_mot->bone_data); + mot_blend_mot->mot_data.key_set = vector_empty(mot_key_set); + mot_blend_mot->mot_data.key_set_data = vector_empty(float_t); + mot_blend_mot->mot_data.skeleton_type = BONE_DATABASE_SKELETON_NONE; + mot_blend_mot->mot_data.frame = -1.0f; + mot_blend_mot->mot_data.motion_id = -1; + mot_blend_mot->field_4F8.field_C0 = 1.0f; + mot_blend_mot->field_4F8.field_C4 = 1.0f; + return mot_blend_mot; +} + +static void motion_blend_mot_interpolate(motion_blend_mot* a1) { + vec3* keyframe_data = (vec3*)a1->mot_data.key_set_data.begin; + bool reverse = motion_blend_mot_interpolate_get_reverse(&a1->field_4F8.field_0); + float_t frame = a1->field_4A8.field_0.frame; + + bone_database_skeleton_type skeleton_type = a1->bone_data.rob_bone_data->base_skeleton_type; + bone_data* bones_data = a1->bone_data.bones.begin; + for (uint16_t* i = a1->bone_data.bone_indices.begin; i != a1->bone_data.bone_indices.end; i++) { + bone_data* data = &bones_data[*i]; + bool get_data = true; + if (reverse && data->mirror != 255) + data = &bones_data[data->mirror]; + + if (get_data && frame != data->frame) { + mot_parent_interpolate(&a1->mot_data, frame, data->key_set_offset, data->key_set_count); + data->frame = frame; + } + + keyframe_data = bone_data_set_key_data(data, keyframe_data, skeleton_type, get_data, reverse); + } + + uint32_t v15 = a1->bone_data.bone_key_set_count; + if (frame != a1->mot_data.frame) { + mot_parent_interpolate(&a1->mot_data, frame, v15, a1->bone_data.global_key_set_count); + a1->mot_data.frame = frame; + } + + keyframe_data = (vec3*)&a1->mot_data.key_set_data.begin[v15]; + vec3 global_trans = keyframe_data[0]; + vec3 global_rotation = keyframe_data[1]; + if (reverse) + vec3_negate(global_trans, global_trans); + a1->bone_data.global_trans = global_trans; + a1->bone_data.global_rotation = global_rotation; + + float_t rotation_y = a1->bone_data.rotation_y; + mat4 mat; + mat4_rotate_y(rotation_y, &mat); + mat4_translate_mult(&mat, global_trans.x, global_trans.y, global_trans.z, &mat); + mat4_rotate_mult(&mat, global_rotation.x, global_rotation.y, global_rotation.z, &mat); + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) + switch (i->type) { + case BONE_DATABASE_BONE_TYPE_1: + mat4_mult_vec3_trans(&mat, &i->trans, &i->trans); + break; + case BONE_DATABASE_BONE_POSITION_ROTATION: { + mat4 rot_mat; + mat4_clear_trans(&mat, &rot_mat); + mat4_to_mat4u(&rot_mat, &i->rot_mat[0]); + mat4_mult_vec3_trans(&mat, &i->trans, &i->trans); + } break; + case BONE_DATABASE_BONE_HEAD_IK_ROTATION: + case BONE_DATABASE_BONE_ARM_IK_ROTATION: + case BONE_DATABASE_BONE_LEGS_IK_ROTATION: + mat4_mult_vec3_trans(&mat, &i->ik_target, &i->ik_target); + break; + } +} + +static bool motion_blend_mot_interpolate_get_reverse(int32_t* a1) { + return (*a1 & 1) && (*a1 & 8) == 0 || !(*a1 & 1) && (*a1 & 8) != 0; +} + +static void motion_blend_mot_load_bone_data(motion_blend_mot* a1, + rob_chara_data_bone_data* a2, bone_database* bone_data) { + bone_data_parent_data_init(&a1->bone_data, a2, bone_data); + mot_parent_init_key_sets( + &a1->mot_data, + a1->bone_data.rob_bone_data->base_skeleton_type, + a1->bone_data.motion_bone_count, + a1->bone_data.ik_bone_count); +} + +static void motion_blend_mot_load_file(motion_blend_mot* a1, int32_t motion_id, + bone_database* type, motion_database* mot_db) { + mot_data* v6 = mot_parent_load_file(&a1->mot_data, motion_id, mot_db); + bone_data_parent* v7 = &a1->bone_data; + if (type) { + bone_data_parent_load_bone_indices_from_mot(v7, v6, type, mot_db); + vector_uint16_t* bone_indices = &a1->bone_data.bone_indices; + bone_data* bone = a1->bone_data.bones.begin; + for (uint16_t* i = bone_indices->begin; i != bone_indices->end; i++) + bone[*i].frame = -1.0f; + } + else { + rob_chara_data_bone_data* rob_bone_data = v7->rob_bone_data; + for (mat4* i = rob_bone_data->mats.begin; i != rob_bone_data->mats.end; i++) + *i = mat4_identity; + + for (mat4* i = rob_bone_data->mats2.begin; i != rob_bone_data->mats2.end; i++) + *i = mat4_identity; + + a1->bone_data.bone_indices.end = a1->bone_data.bone_indices.begin; + } + + a1->field_4F8.field_8C = false; + a1->field_4F8.field_4C = a1->field_4F8.mat; + a1->field_4F8.mat = mat4u_identity; +} + +static void motion_blend_mot_mult_mat(motion_blend_mot* a1, mat4* mat) { + if (mat) { + mat4_to_mat4u(mat, &a1->field_4F8.mat); + a1->field_4F8.field_8C = true; + } + else { + a1->field_4F8.mat = mat4u_identity; + a1->field_4F8.field_8C = false; + } + + mat4 m; + mat4u_to_mat4(&a1->field_4F8.mat, &m); + bone_data* v3 = a1->bone_data.bones.begin; + for (bone_data* v4 = a1->bone_data.bones.begin; v4 != a1->bone_data.bones.end; v4++) + bone_data_mult_1(v4, &m, v3, true); +} + +static void motion_blend_mot_reset(motion_blend_mot* mot_blend_mot) { + bone_data_parent_reset(&mot_blend_mot->bone_data); + mot_blend_mot->mot_data.key_sets_ready = 0; + mot_blend_mot->mot_data.skeleton_type = BONE_DATABASE_SKELETON_NONE; + mot_blend_mot->mot_data.frame = -1.0f; + mot_blend_mot->mot_data.key_set_count = 0; + mot_blend_mot->mot_data.mot_data = 0; + mot_blend_mot->mot_data.skeleton_select = 0; + mot_blend_mot->mot_data.field_68.field_0 = 0; + mot_blend_mot->mot_data.field_68.field_4 = 0.0f; + mot_blend_mot->mot_data.key_set.end = mot_blend_mot->mot_data.key_set.begin; + mot_blend_mot->mot_data.key_set_data.end = mot_blend_mot->mot_data.key_set_data.begin; + mot_blend_mot->mot_data.motion_id = -1; + mot_blend_mot->field_4A8.field_0.frame = 0.0f; + mot_blend_mot->field_4A8.field_0.field_8 = 1.0f; + mot_blend_mot->field_4A8.field_0.step = 1.0f; + mot_blend_mot->field_4A8.field_0.frame_count = 0; + mot_blend_mot->field_4A8.field_0.last_frame = -1.0f; + mot_blend_mot->field_4A8.field_0.field_14 = -1.0f; + mot_blend_mot->field_4A8.field_0.field_18 = -1; + mot_blend_mot->field_4A8.field_0.field_1C = -1; + mot_blend_mot->field_4A8.field_0.field_20 = 0; + mot_blend_mot->field_4A8.field_0.field_24 = -1.0f; + mot_blend_mot->field_4A8.field_0.field_28 = 0; + mot_blend_mot->field_4A8.field_0.field_2C = -1; + mot_blend_mot->field_4A8.field_30 = 0; + mot_blend_mot->field_4A8.field_34 = 0; + mot_blend_mot->field_4A8.field_38 = 0; + mot_blend_mot->field_4A8.field_40 = 0; + mot_blend_mot->field_4A8.field_48 = 0; + mot_blend_mot->field_4F8.field_0 = 0; + mot_blend_mot->field_4F8.field_8 = 0; + mot_blend_mot->field_4F8.mat = mat4u_identity; + mot_blend_mot->field_4F8.field_4C = mat4u_identity; + mot_blend_mot->field_4F8.field_8C = false; + mot_blend_mot->field_4F8.eyes_adjust = 0.0f; + mot_blend_mot->field_4F8.field_B8 = 0.0f; + mot_blend_mot->field_4F8.field_90 = vec3_identity; + mot_blend_mot->field_4F8.field_9C = vec3_identity; + mot_blend_mot->field_4F8.field_A8 = vec3_identity; + mot_blend_mot->field_4F8.field_BC = 0; + mot_blend_mot->field_4F8.field_BD = 0; + mot_blend_mot->field_4F8.field_C0 = 1.0f; + mot_blend_mot->field_4F8.field_C4 = 1.0f; + mot_blend_mot->field_4F8.field_C8 = vec3_null; +} + +static void motion_blend_mot_dispose(motion_blend_mot* mot_blend_mot) { + mot_parent_free(&mot_blend_mot->mot_data); + bone_data_parent_free(&mot_blend_mot->bone_data); + free(mot_blend_mot); +} + +static void osage_coli_set(osage_coli* osg_coli, + skin_param_osage_root_coli* skp_root_coli, mat4* mats) { + osage_coli* v4 = osg_coli; + skin_param_osage_root_coli* v6 = skp_root_coli; + osg_coli->type = 0; + if (skp_root_coli && mats && skp_root_coli->type) + while (v6->type) { + v4->type = v6->type; + v4->radius = v6->radius; + + mat4 mat = mats[v6->bone0_index]; + mat4_mult_vec3_trans(&mat, &v4->bone0_pos, &v4->bone0_pos); + + if (v6->type == 2 || v6->type == 4) { + mat = mats[v6->bone1_index]; + mat4_mult_vec3_trans(&mat, &v6->bone1_pos, &v4->bone1_pos); + vec3_sub(v4->bone1_pos, v4->bone0_pos, v4->bone_pos_diff); + + float_t length; + vec3_length_squared(v4->bone_pos_diff, length); + v4->bone_pos_diff_length_squared = length; + length = sqrtf(length); + v4->bone_pos_diff_length = length; + if (length < 0.01f) + v4->type = 1; + } + else if (v6->type == 3) + mat4_mult_vec3(&mat, &v4->bone1_pos, &v4->bone1_pos); + + v4++; + v6++; + } + v4->type = 0; +} + +static void osage_coli_ring_set(osage_coli* osg_coli, + vector_skin_param_osage_root_coli* vec_skp_root_coli, mat4* mats) { + if (vec_skp_root_coli->begin == vec_skp_root_coli->end) { + osg_coli->type = 0; + osg_coli->radius = 0.0f; + osg_coli->bone0_pos = vec3_null; + osg_coli->bone1_pos = vec3_null; + osg_coli->bone_pos_diff = vec3_null; + osg_coli->bone_pos_diff_length = 0.0f; + osg_coli->bone_pos_diff_length_squared = 0.0f; + osg_coli->field_34 = 1.0; + } + else + osage_coli_set(osg_coli, vec_skp_root_coli->begin, mats); +} + +static rob_chara_data_bone_data* rob_chara_data_bone_data_init() { + rob_chara_data_bone_data* rob_bone_data = force_malloc(sizeof(rob_chara_data_bone_data)); + rob_bone_data->base_skeleton_type = BONE_DATABASE_SKELETON_NONE; + rob_bone_data->skeleton_type = BONE_DATABASE_SKELETON_NONE; + rob_bone_data->ik_scale.ratio0 = 1.0f; + return rob_bone_data; +} + +static void rob_chara_data_bone_data_calculate_bones(rob_chara_data_bone_data* rob_bone_data, + vector_bone_database_bone* bones) { + bone_database_bones_calculate_count(bones, &rob_bone_data->object_bone_count, + &rob_bone_data->motion_bone_count, &rob_bone_data->total_bone_count, + &rob_bone_data->ik_bone_count, &rob_bone_data->chain_pos); +} + +static void rob_chara_data_bone_data_eyes_xrot_adjust(rob_chara_data_bone_data* rob_bone_data, + const struc_241* a2, eyes_adjust* a3) { + float_t v1_neg; + float_t v1_pos; + switch (a3->base_adjust) { + case EYES_BASE_ADJUST_DIRECTION: + default: + v1_neg = a2->field_34 * -(float_t)(1.0 / 3.8); + v1_pos = a2->field_38 * (float_t)(1.0 / 6.0); + break; + case EYES_BASE_ADJUST_CLEARANCE: + v1_neg = a2->field_3C * -(float_t)(1.0 / 3.8); + v1_pos = a2->field_40 * (float_t)(1.0 / 6.0); + break; + case EYES_BASE_ADJUST_OFF: + v1_neg = 1.0f; + v1_pos = 1.0f; + break; + } + + float_t v2_pos = 1.0f; + float_t v2_neg = 1.0f; + if (a3->xrot_adjust) { + v2_neg = a2->field_2C; + v2_pos = a2->field_30; + } + + if (a3->neg >= 0.0f && a3->pos >= 0.0f) { + v2_neg = a3->neg; + v2_pos = a3->pos; + } + + float_t eyes_xrot_adjust_neg = v1_neg * v2_neg; + float_t eyes_xrot_adjust_pos = v1_pos * v2_pos; + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) { + bone_data* data = (*i)->bone_data.bones.begin; + data[MOTION_BONE_KL_EYE_L].eyes_xrot_adjust_neg = eyes_xrot_adjust_neg; + data[MOTION_BONE_KL_EYE_L].eyes_xrot_adjust_pos = eyes_xrot_adjust_pos; + data[MOTION_BONE_KL_EYE_R].eyes_xrot_adjust_neg = eyes_xrot_adjust_neg; + data[MOTION_BONE_KL_EYE_R].eyes_xrot_adjust_pos = eyes_xrot_adjust_pos; + } +} + +static float_t rob_chara_data_bone_data_get_frame(rob_chara_data_bone_data* rob_bone_data) { + return rob_bone_data->motion_loaded.begin[0]->field_4A8.field_0.frame; +} + +static float_t rob_chara_data_bone_data_get_frame_count(rob_chara_data_bone_data* rob_bone_data) { + return (float_t)rob_bone_data->motion_loaded.begin[0]->mot_data.mot.frame_count; +} + +static void rob_chara_data_bone_data_get_ik_scale( + rob_chara_data_bone_data* rob_bone_data, bone_database* bone_data) { + if (rob_bone_data->motion_loaded.end - rob_bone_data->motion_loaded.begin < 0) + return; + + motion_blend_mot* v2 = rob_bone_data->motion_loaded.begin[0]; + rob_chara_data_bone_data_ik_scale_calculate(&rob_bone_data->ik_scale, &v2->bone_data.bones, + rob_bone_data->base_skeleton_type, rob_bone_data->skeleton_type, bone_data); + float_t ratio0 = rob_bone_data->ik_scale.ratio0; + v2->field_4F8.field_C0 = ratio0; + v2->field_4F8.field_C4 = ratio0; + v2->field_4F8.field_C8 = vec3_null; +} + +static mat4* rob_chara_data_bone_data_get_mat(rob_chara_data_bone_data* rob_bone_data, size_t index) { + bone_node* node = rob_chara_data_bone_data_get_node(rob_bone_data, index); + if (node) + return node->mat; + return 0; +} + +static bone_node* rob_chara_data_bone_data_get_node(rob_chara_data_bone_data* rob_bone_data, size_t index) { + if ((ssize_t)index < rob_bone_data->nodes.end - rob_bone_data->nodes.begin) + return &rob_bone_data->nodes.begin[index]; + return 0; +} + +static void rob_chara_data_bone_data_ik_scale_calculate( + rob_chara_data_bone_data_ik_scale* ik_scale, vector_bone_data* vec_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_db) { + char* base_name = bone_database_skeleton_type_to_string(base_skeleton_type); + char* name = bone_database_skeleton_type_to_string(skeleton_type); + float_t* base_heel_height = 0; + float_t* heel_height = 0; + if (!bone_database_get_skeleton_heel_height(bone_db, base_name, &base_heel_height) + || !bone_database_get_skeleton_heel_height(bone_db, name, &heel_height)) + return; + + bone_data* b_cl_mune = &vec_bone_data->begin[MOTION_BONE_CL_MUNE]; + bone_data* b_kl_kubi = &vec_bone_data->begin[MOTION_BONE_KL_KUBI]; + bone_data* b_c_kata_l = &vec_bone_data->begin[MOTION_BONE_C_KATA_L]; + bone_data* b_cl_momo_l = &vec_bone_data->begin[MOTION_BONE_CL_MOMO_L]; + + float_t base_height = fabsf(b_cl_momo_l->base_translation[0].y) + b_cl_momo_l->ik_segment_length[0] + + b_cl_momo_l->ik_2nd_segment_length[0] + *base_heel_height; + float_t height = fabsf(b_cl_momo_l->base_translation[1].y) + b_cl_momo_l->ik_segment_length[1] + + b_cl_momo_l->ik_2nd_segment_length[1] + *heel_height; + ik_scale->ratio0 = height / base_height; + ik_scale->ratio1 = (fabsf(b_kl_kubi->base_translation[1].y) + b_cl_mune->ik_segment_length[1]) + / (fabsf(b_kl_kubi->base_translation[0].y) + b_cl_mune->ik_segment_length[0]); + ik_scale->ratio2 = (b_c_kata_l->ik_segment_length[1] + b_c_kata_l->ik_2nd_segment_length[1]) + / (b_c_kata_l->ik_segment_length[0] + b_c_kata_l->ik_2nd_segment_length[0]); + ik_scale->ratio3 = (fabsf(b_kl_kubi->base_translation[1].y) + b_cl_mune->ik_segment_length[1] + height) + / (fabsf(b_kl_kubi->base_translation[0].y) + b_cl_mune->ik_segment_length[0] + base_height); +} + +static void rob_chara_data_bone_data_init_data(rob_chara_data_bone_data* rob_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_data) { + rob_chara_data_bone_data_init_skeleton(rob_bone_data, base_skeleton_type, skeleton_type, bone_data); + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) + motion_blend_mot_load_bone_data(*i, rob_bone_data, bone_data); +} + +static void rob_chara_data_bone_data_init_skeleton(rob_chara_data_bone_data* rob_bone_data, + bone_database_skeleton_type base_skeleton_type, + bone_database_skeleton_type skeleton_type, bone_database* bone_data) { + if (rob_bone_data->base_skeleton_type == base_skeleton_type + && rob_bone_data->skeleton_type == skeleton_type) + return; + + char* name = bone_database_skeleton_type_to_string(base_skeleton_type); + vector_bone_database_bone* bones = 0; + vector_uint16_t* parent_indices = 0; + if (!bone_database_get_skeleton_bones(bone_data, name, &bones) + || !bone_database_get_skeleton_parent_indices(bone_data, name, &parent_indices)) + return; + + rob_chara_data_bone_data_calculate_bones(rob_bone_data, bones); + rob_chara_data_bone_data_reserve(rob_bone_data); + rob_chara_data_bone_data_set_mats(rob_bone_data, bones); + rob_chara_data_bone_data_set_parent_mats(rob_bone_data, parent_indices->begin); + rob_bone_data->base_skeleton_type = base_skeleton_type; + rob_bone_data->skeleton_type = skeleton_type; +} + +static void rob_chara_data_bone_data_interpolate(rob_chara_data_bone_data* rob_bone_data) { + if (rob_bone_data->motion_loaded.end - rob_bone_data->motion_loaded.begin < 0) + return; + + for (motion_blend_mot** i = rob_bone_data->motion_loaded.begin; + i != rob_bone_data->motion_loaded.end; i++) + motion_blend_mot_interpolate(*i); +} + +static void rob_chara_data_bone_data_motion_blend_mot_free(rob_chara_data_bone_data* rob_bone_data) { + vector_size_t_clear(&rob_bone_data->motion_indices, 0); + vector_ptr_motion_blend_mot_clear(&rob_bone_data->motions, motion_blend_mot_dispose); +} + +static void rob_chara_data_bone_data_motion_blend_mot_init(rob_chara_data_bone_data* rob_bone_data) { + for (int32_t i = 0; i < 3; i++) { + *vector_ptr_motion_blend_mot_reserve_back(&rob_bone_data->motions) = motion_blend_mot_init(); + *vector_size_t_reserve_back(&rob_bone_data->motion_indices) = i; + } + rob_chara_data_bone_data_motion_blend_mot_list_init(rob_bone_data); +} + +static void rob_chara_data_bone_data_motion_blend_mot_list_free(rob_chara_data_bone_data* rob_bone_data, + size_t last_index) { + for (motion_blend_mot** i = &rob_bone_data->motion_loaded.end[-1]; + i - rob_bone_data->motion_loaded.begin > (ssize_t)last_index; i--) { + motion_blend_mot* type = rob_bone_data->motion_loaded.end[-1]; + if ((ssize_t)rob_bone_data->motion_loaded_indices.end[-1] + >= rob_bone_data->motions.end - rob_bone_data->motions.begin && type) + motion_blend_mot_dispose(type); + rob_bone_data->motion_loaded.end[-1] = 0; + vector_ptr_motion_blend_mot_pop_back(&rob_bone_data->motion_loaded, 0); + vector_size_t_pop_back(&rob_bone_data->motion_loaded_indices, 0); + } +} + +static void rob_chara_data_bone_data_motion_blend_mot_list_init(rob_chara_data_bone_data* rob_bone_data) { + size_t free_index = rob_bone_data->motion_indices.end[-1]; + vector_size_t_pop_back(&rob_bone_data->motion_indices, 0); + vector_ptr_motion_blend_mot_push_back(&rob_bone_data->motion_loaded, + &rob_bone_data->motions.begin[free_index]); + vector_size_t_push_back(&rob_bone_data->motion_loaded_indices, &free_index); +} + +static void rob_chara_data_bone_data_reserve(rob_chara_data_bone_data* rob_bone_data) { + size_t mats_size = rob_bone_data->object_bone_count; + vector_mat4_reserve(&rob_bone_data->mats, mats_size); + rob_bone_data->mats.end += mats_size; + + size_t mats2_size = rob_bone_data->total_bone_count - rob_bone_data->object_bone_count; + vector_mat4_reserve(&rob_bone_data->mats2, mats2_size); + rob_bone_data->mats2.end += mats2_size; + + size_t nodes_size = rob_bone_data->total_bone_count; + vector_bone_node_reserve(&rob_bone_data->nodes, nodes_size); + rob_bone_data->nodes.end += nodes_size; + + for (bone_node* i = rob_bone_data->nodes.begin; i != rob_bone_data->nodes.end; i++) { + i->name = 0; + i->mat = 0; + i->parent = 0; + i->exp_data.position = vec3_null; + i->exp_data.rotation = vec3_null; + i->exp_data.scale = vec3_identity; + i->exp_data.data_scale = vec3_identity; + i->ex_data_mat = 0; + } +} + +static void rob_chara_data_bone_data_motion_load(rob_chara_data_bone_data* rob_bone_data, + int32_t motion_id, int32_t index, bone_database* bone_data, motion_database* mot_db) { + if (rob_bone_data->motion_loaded.end - rob_bone_data->motion_loaded.begin < 1) + return; + + if (index == 1) { + rob_chara_data_bone_data_motion_blend_mot_list_free(rob_bone_data, 1); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.begin[0], motion_id, bone_data, mot_db); + return; + } + + if (index != 2) { + if (index == 3) + index = 0; + rob_chara_data_bone_data_motion_blend_mot_list_free(rob_bone_data, 1); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.begin[0], motion_id, bone_data, mot_db); + return; + } + + rob_chara_data_bone_data_motion_blend_mot_list_free(rob_bone_data, 2); + if (rob_bone_data->motion_indices.end - rob_bone_data->motion_indices.begin > 0) { + rob_chara_data_bone_data_motion_blend_mot_list_init(rob_bone_data); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.begin[0], motion_id, bone_data, mot_db); + return; + } + + motion_blend_mot* v16 = motion_blend_mot_init(); + motion_blend_mot_load_bone_data(v16, rob_bone_data, bone_data); + vector_ptr_motion_blend_mot_push_back(&rob_bone_data->motion_loaded, &v16); + *vector_size_t_reserve_back(&rob_bone_data->motion_loaded_indices) + = (size_t)(rob_bone_data->motions.end - rob_bone_data->motions.begin); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.begin[0], motion_id, bone_data, mot_db); +} + +static void rob_chara_data_bone_data_reset(rob_chara_data_bone_data* rob_bone_data) { + rob_bone_data->object_bone_count = 0; + rob_bone_data->motion_bone_count = 0; + rob_bone_data->total_bone_count = 0; + rob_bone_data->ik_bone_count = 0; + rob_bone_data->chain_pos = 0; + rob_bone_data->mats.end = rob_bone_data->mats.begin; + rob_bone_data->mats2.end = rob_bone_data->mats2.begin; + rob_bone_data->nodes.end = rob_bone_data->nodes.begin; + rob_bone_data->base_skeleton_type = BONE_DATABASE_SKELETON_NONE; + rob_bone_data->skeleton_type = BONE_DATABASE_SKELETON_NONE; + + if (rob_bone_data->motions.end - rob_bone_data->motions.begin == 3) { + rob_chara_data_bone_data_motion_blend_mot_list_free(rob_bone_data, 0); + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) + motion_blend_mot_reset(*i); + rob_chara_data_bone_data_motion_blend_mot_list_init(rob_bone_data); + } + else { + rob_chara_data_bone_data_motion_blend_mot_free(rob_bone_data); + rob_chara_data_bone_data_motion_blend_mot_init(rob_bone_data); + } +} + +static void sub_140414BC0(struc_346* a1, float_t frame) { + float_t v2 = a1->field_14; + a1->frame = frame; + a1->field_28 = false; + if (v2 >= 0.0f && (a1->field_18 == 2 && frame <= v2) || frame >= v2) + a1->field_14 = -1.0; +} + +static void rob_chara_data_bone_data_set_frame(rob_chara_data_bone_data* rob_bone_data, float_t frame) { + sub_140414BC0(&rob_bone_data->motion_loaded.begin[0]->field_4A8.field_0, frame); +} + +static void rob_chara_data_bone_data_set_mats(rob_chara_data_bone_data* rob_bone_data, + vector_bone_database_bone* bones) { + size_t chain_pos = 0; + size_t ik_bone_count = 0; + size_t total_bone_count = 0; + + mat4* mats = rob_bone_data->mats.begin; + mat4* mats2 = rob_bone_data->mats2.begin; + bone_node* nodes = rob_bone_data->nodes.begin; + for (bone_database_bone* i = bones->begin; i != bones->end; i++) + switch (i->type) { + case BONE_DATABASE_BONE_ROTATION: + case BONE_DATABASE_BONE_TYPE_1: + case BONE_DATABASE_BONE_POSITION: + (nodes++)->mat = mats++; + + chain_pos++; + total_bone_count++; + break; + case BONE_DATABASE_BONE_POSITION_ROTATION: + (nodes++)->mat = mats++; + + chain_pos++; + ik_bone_count++; + total_bone_count++; + break; + case BONE_DATABASE_BONE_HEAD_IK_ROTATION: + (nodes++)->mat = mats2++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats2++; + + chain_pos += 2; + ik_bone_count++; + total_bone_count += 3; + break; + case BONE_DATABASE_BONE_ARM_IK_ROTATION: + case BONE_DATABASE_BONE_LEGS_IK_ROTATION: + (nodes++)->mat = mats++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats2++; + + chain_pos += 3; + ik_bone_count++; + total_bone_count += 4; + break; + } + + for (bone_node* i = rob_bone_data->nodes.begin; i != rob_bone_data->nodes.end; i++) + i->ex_data_mat = i->mat; +} + +static void rob_chara_data_bone_data_set_parent_mats(rob_chara_data_bone_data* rob_bone_data, + uint16_t* parent_indices) { + if (rob_bone_data->nodes.end - rob_bone_data->nodes.begin < 1) + return; + + parent_indices++; + for (bone_node* i = &rob_bone_data->nodes.begin[1]; i != rob_bone_data->nodes.end; i++) + i->parent = &rob_bone_data->nodes.begin[*parent_indices++]; +} + +static void rob_chara_data_bone_data_set_rotation_y(rob_chara_data_bone_data* rob_bone_data, float_t rotation_y) { + rob_bone_data->motion_loaded.begin[0]->bone_data.rotation_y = rotation_y; +} + +static void rob_chara_data_bone_data_update(rob_chara_data_bone_data* rob_bone_data, mat4* mat) { + if (rob_bone_data->motion_loaded_indices.end - rob_bone_data->motion_loaded_indices.begin < 1) + return; + + for (motion_blend_mot** i = rob_bone_data->motion_loaded.begin; + i != rob_bone_data->motion_loaded.end; i++) { + if (!*i) + continue; + + motion_blend_mot* v5 = *i; + v5->field_4F8.field_8C = false; + v5->field_4F8.field_4C = v5->field_4F8.mat; + v5->field_4F8.mat = mat4u_identity; + int32_t skeleton_select = v5->mot_data.skeleton_select; + + for (bone_data* j = v5->bone_data.bones.begin; j != v5->bone_data.bones.end; j++) + bone_data_mult_0(j, skeleton_select); + + float_t ratio = rob_bone_data->ik_scale.ratio0; + bone_data* b_n_hara_cp = &v5->bone_data.bones.begin[MOTION_BONE_N_HARA_CP]; + bone_data* b_kg_hara_y = &v5->bone_data.bones.begin[MOTION_BONE_KG_HARA_Y]; + bone_data* b_kl_hara_xz = &v5->bone_data.bones.begin[MOTION_BONE_KL_HARA_XZ]; + bone_data* b_kl_hara_etc = &v5->bone_data.bones.begin[MOTION_BONE_KL_HARA_ETC]; + v5->field_4F8.field_90 = vec3_null; + + mat4 rot_mat; + mat4 mat; + mat4u_to_mat4(&b_n_hara_cp->rot_mat[0], &rot_mat); + mat4u_to_mat4(&b_kg_hara_y->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4u_to_mat4(&b_kl_hara_xz->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4u_to_mat4(&b_kl_hara_etc->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4_to_mat4u(&rot_mat, &b_n_hara_cp->rot_mat[0]); + b_kg_hara_y->rot_mat[0] = mat4u_identity; + b_kl_hara_xz->rot_mat[0] = mat4u_identity; + b_kl_hara_etc->rot_mat[0] = mat4u_identity; + + float_t v8 = v5->field_4F8.field_C0; + float_t v9 = v5->field_4F8.field_C4; + vec3 v10 = v5->field_4F8.field_C8; + v5->field_4F8.field_A8 = b_n_hara_cp->trans; + if (!v5->mot_data.skeleton_select) { + if (ratio != v9) { + b_n_hara_cp->trans.x = (b_n_hara_cp->trans.x - v10.x) * v9 + v10.x; + b_n_hara_cp->trans.z = (b_n_hara_cp->trans.z - v10.z) * v9 + v10.z; + } + b_n_hara_cp->trans.y = ((b_n_hara_cp->trans.y - v10.y) * v8) + v10.y; + } + else { + if (ratio != v9) { + v9 /= ratio; + b_n_hara_cp->trans.x = (b_n_hara_cp->trans.x - v10.x) * v9 + v10.x; + b_n_hara_cp->trans.z = (b_n_hara_cp->trans.z - v10.z) * v9 + v10.z; + } + + if (ratio != v8) { + v8 /= ratio; + b_n_hara_cp->trans.y = (b_n_hara_cp->trans.y - v10.y) * v8 + v10.y; + } + } + } + + motion_blend_mot_mult_mat(rob_bone_data->motion_loaded.begin[0], mat); +} + +static void rob_chara_data_bone_data_dispose(rob_chara_data_bone_data* rob_bone_data) { + vector_mat4_free(&rob_bone_data->mats, 0); + vector_mat4_free(&rob_bone_data->mats2, 0); + vector_bone_node_free(&rob_bone_data->nodes, 0); + vector_ptr_motion_blend_mot_free(&rob_bone_data->motions, motion_blend_mot_dispose); + vector_size_t_free(&rob_bone_data->motion_indices, 0); + vector_size_t_free(&rob_bone_data->motion_loaded_indices, 0); + for (motion_blend_mot** i = rob_bone_data->motion_loaded.begin; + i != rob_bone_data->motion_loaded.end; i++) + *i = 0; + vector_ptr_motion_blend_mot_free(&rob_bone_data->motion_loaded, 0); + free(rob_bone_data); +} + +static rob_chara_data_item_equip* rob_chara_data_item_equip_init() { + rob_chara_data_item_equip* rob_item_equip = force_malloc(sizeof(rob_chara_data_item_equip)); + rob_chara_data_item_equip_object* itm_eq_obj = force_malloc_s(rob_chara_data_item_equip_object, 31); + for (int32_t i = 0; i < 31; i++) + rob_chara_data_item_equip_object_init(&itm_eq_obj[i]); + rob_item_equip->item_equip_object = itm_eq_obj; + rob_item_equip->wind_strength = 1.0f; + rob_item_equip->chara_color = 1; + for (int32_t i = 0; i < 31; i++) + rob_item_equip->item_equip_object[i].item_equip = rob_item_equip; + rob_chara_data_item_equip_reset(rob_item_equip); + return rob_item_equip; +} + +static float_t sub_140512F60(rob_chara_data_item_equip* rob_item_equip) { + float_t v26; + float_t v27; + float_t v28; + + mat4* mats = rob_item_equip->matrices; + float_t v25 = 1.0f; + float_t* v2 = &v27; + float_t v3 = mats->row3.y; + v26 = mats->row3.x; + if (v3 >= 1.0f) + v2 = &v25; + v28 = mats->row3.z; + float_t v4 = mats[175].row3.x; + v27 = v3; + float_t v5 = *v2; + float_t v6 = mats[175].row3.y; + v26 = v4; + float_t* v7 = &v27; + float_t v8 = mats[175].row3.z; + v27 = v6; + if (v5 <= v6) + v7 = &v25; + float_t v9 = mats[181].row3.y; + v28 = v8; + float_t v10 = mats[181].row3.x; + v25 = v5; + float_t v11 = *v7; + v26 = v10; + float_t* v12 = &v27; + float_t v13 = mats[181].row3.z; + v27 = v9; + if (v11 <= v9) + v12 = &v25; + float_t v14 = mats[105].row3.y; + v28 = v13; + float_t v15 = mats[105].row3.x; + v25 = v11; + float_t v16 = *v12; + v26 = v15; + float_t*v17 = &v27; + float_t v18 = mats[105].row3.z; + v27 = v14; + if (v16 <= v14) + v17 = &v25; + float_t v19 = mats[140].row3.y; + v28 = v18; + float_t v20 = mats[140].row3.x; + v25 = v16; + float_t v21 = *v17; + v26 = v20; + float_t* v22 = &v27; + float_t v23 = mats[140].row3.z; + v25 = v21; + if (v21 <= v19) + v22 = &v25; + v27 = v19; + v28 = v23; + return *v22; +} + +static void rob_chara_data_item_equip_draw( + rob_chara_data_item_equip* rob_item_equip, int32_t chara_id, render_context* rctx) { + draw_task_flags v2 = 0; + if (rctx->chara_reflect) + v2 = DRAW_TASK_CHARA_REFLECT; + if (rctx->chara_refract) + v2 |= DRAW_TASK_REFRACT; + + object_data* object_data = &rctx->object_data; + shadow* shad = rctx->draw_pass.shadow_ptr; + if (rob_item_equip->shadow_type != -1) { + if (rob_item_equip->field_A0 & 4) { + shadow_type_enum shadow_type = rob_item_equip->shadow_type; + vec3 pos = rob_item_equip->position; + pos.y -= 0.2f; + vector_vec3_push_back(&shad->field_1D0[shadow_type], &pos); + + float_t v9; + if (sub_140512F60(rob_item_equip) <= -0.2f) + v9 = -0.5f; + else + v9 = 0.05f; + rctx->draw_pass.shadow_ptr->field_1C0[shadow_type] = v9; + object_data_set_shadow_type(object_data, shadow_type); + v2 |= DRAW_TASK_SHADOW; + } + + if (rob_item_equip->field_A0 & 1) + v2 |= DRAW_TASK_4; + } + object_data_set_draw_task_flags(object_data, v2); + object_data_set_chara_color(object_data, rob_item_equip->chara_color); + + vec4 v23; + object_data_get_texture_color_coeff(object_data, &v23); + + vec4 texture_color_coeff; + vec4u_to_vec4(rob_item_equip->texture_color_coeff, texture_color_coeff); + object_data_set_texture_color_coeff(object_data, &texture_color_coeff); + object_data_set_wet_param(object_data, rob_item_equip->wet); + //sub_140502FB0(rob_item_equip->field_F9); + //sub_140512C20(rob_item_equip); + //sub_1405421D0(chara_id, rctx->chara_reflect, rob_item_equip->chara_color); + + mat4 mat; + mat4u_to_mat4(&rob_item_equip->mat, &mat); + if (rob_item_equip->item_equip_range) + for (int32_t i = rob_item_equip->first_item_equip_object; + i < rob_item_equip->max_item_equip_object; i++) + rob_chara_data_item_equip_object_draw(&rob_item_equip->item_equip_object[i], &mat, rctx); + else { + for (int32_t i = 1; i < 31; i++) { + draw_task_flags v18 = 0; + if (rob_item_equip->field_18[i] == 0) { + if (rctx->chara_reflect) + v18 = DRAW_TASK_CHARA_REFLECT; + if (rctx->chara_refract) + v18 |= DRAW_TASK_REFRACT; + } + + draw_task_flags v19 = DRAW_TASK_4 | DRAW_TASK_SHADOW; + if (i == 8) + v19 = 0; + + if (!(rob_item_equip->field_A0 & 4)) + v19 &= ~DRAW_TASK_SHADOW; + + object_data_set_draw_task_flags(object_data, (draw_task_flags)(v18 | v19 | DRAW_TASK_SSS)); + rob_chara_data_item_equip_object_draw(&rob_item_equip->item_equip_object[i], &mat, rctx); + } + } + object_data_set_texture_color_coeff(object_data, &v23); + object_data_set_wet_param(object_data, 0.0f); + object_data_set_chara_color(object_data, 0); + object_data_set_draw_task_flags(object_data, 0); + object_data_set_shadow_type(object_data, SHADOW_CHARA); +} + +static void rob_chara_data_item_equip_get_parent_bone_nodes( + rob_chara_data_item_equip* rob_item_equip, bone_node* bone_nodes, bone_database* bone_data) { + rob_item_equip->bone_nodes = bone_nodes; + rob_item_equip->matrices = bone_nodes->mat; + for (int32_t i = rob_item_equip->first_item_equip_object; + i < rob_item_equip->max_item_equip_object; i++) + rob_chara_data_item_equip_object_get_parent_bone_nodes( + &rob_item_equip->item_equip_object[i], rob_item_equip->bone_nodes, bone_data); +} + +static void rob_chara_data_item_equip_load_object_info(rob_chara_data_item_equip* rob_item_equip, + object_info object_info, item_id id, bone_database* bone_data) { + if (id < ITEM_BODY || id > ITEM_ITEM16 || !rob_item_equip->bone_nodes) + return; + + rob_chara_data_item_equip_object_load_object_info_ex_data( + &rob_item_equip->item_equip_object[id], object_info, rob_item_equip->bone_nodes, bone_data); + rob_item_equip->item_equip_object[id].draw = true; +} + +static void rob_chara_data_item_equip_object_init(rob_chara_data_item_equip_object* itm_eq_obj) { + memset(itm_eq_obj, 0, sizeof(rob_chara_data_item_equip_object)); + bone_node_expression_data_reset_position_rotation(&itm_eq_obj->exp_data); + rob_chara_data_item_equip_object_init_data(itm_eq_obj, 0x12345678); +} + +static void rob_chara_data_item_equip_object_clear_ex_data(rob_chara_data_item_equip_object* itm_eq_obj) { + for (ex_osage_block** i = itm_eq_obj->osage_blocks.begin; + i != itm_eq_obj->osage_blocks.end; i++) { + (*i)->base.vftable->reset(&(*i)->base); + if (*i) + (*i)->base.vftable->dispose(&(*i)->base); + } + itm_eq_obj->osage_blocks.end = itm_eq_obj->osage_blocks.begin; + + for (ex_constraint_block** i = itm_eq_obj->constraint_blocks.begin; + i != itm_eq_obj->constraint_blocks.end; i++) { + (*i)->base.vftable->reset(&(*i)->base); + if (*i) + (*i)->base.vftable->dispose(&(*i)->base); + } + itm_eq_obj->constraint_blocks.end = itm_eq_obj->constraint_blocks.begin; + + for (ex_expression_block** i = itm_eq_obj->expression_blocks.begin; + i != itm_eq_obj->expression_blocks.end; i++) { + (*i)->base.vftable->reset(&(*i)->base); + if (*i) + (*i)->base.vftable->dispose(&(*i)->base); + } + itm_eq_obj->expression_blocks.end = itm_eq_obj->expression_blocks.begin; + + for (ex_cloth_block** i = itm_eq_obj->cloth_blocks.begin; + i != itm_eq_obj->cloth_blocks.end; i++) { + (*i)->base.vftable->reset(&(*i)->base); + if (*i) + (*i)->base.vftable->dispose(&(*i)->base); + } + itm_eq_obj->cloth_blocks.end = itm_eq_obj->cloth_blocks.begin; + + itm_eq_obj->node_blocks.end = itm_eq_obj->node_blocks.begin; +} + +static void rob_chara_data_item_equip_object_draw( + rob_chara_data_item_equip_object* itm_eq_obj, mat4* mat, render_context* rctx) { + if (itm_eq_obj->object_info.id == -1 && itm_eq_obj->object_info.set_id == -1) + return; + + object_data* object_data = &rctx->object_data; + draw_task_flags v2 = object_data_get_draw_task_flags(object_data); + draw_task_flags v4; + if (fabsf(itm_eq_obj->alpha - 1.0f) > 0.000001f) + v4 = v2 | itm_eq_obj->draw_task_flags; + else + v4 = v2 & ~(DRAW_TASK_40000 | DRAW_TASK_20000 | DRAW_TASK_10000); + object_data_set_draw_task_flags(object_data, v4); + if (itm_eq_obj->draw) { + draw_task_add_draw_object_by_object_info_object_skin(rctx, + itm_eq_obj->object_info, + &itm_eq_obj->texture_pattern, + &itm_eq_obj->texture_data, + itm_eq_obj->alpha, + itm_eq_obj->mat, + itm_eq_obj->field_F0.begin, + itm_eq_obj->field_A8, + mat); + + for (ex_node_block** i = itm_eq_obj->node_blocks.begin; + i != itm_eq_obj->node_blocks.end; i++) + (*i)->vftable->draw(*i); + } + object_data_set_draw_task_flags(object_data, v2); +} + +static int32_t rob_chara_data_item_equip_object_get_bone_index( + rob_chara_data_item_equip_object* itm_eq_obj, char* name, bone_database* bone_data) { + int32_t bone_index = bone_database_get_skeleton_motion_bone_index(bone_data, + bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON), name); + if (bone_index == -1) + for (ex_data_name_bone_index* i = itm_eq_obj->ex_bones.begin; i != itm_eq_obj->ex_bones.end; i++) + if (!str_utils_compare(name, i->name)) + return 0x8000 | i->bone_index; + return bone_index; +} + +static bone_node* rob_chara_data_item_equip_object_get_bone_node( + rob_chara_data_item_equip_object* itm_eq_obj, int32_t bone_index) { + if (!(bone_index & 0x8000)) + return &itm_eq_obj->bone_nodes[bone_index & 0x7FFF]; + else if ((bone_index & 0x7FFF) < (itm_eq_obj->ex_data_bone_nodes.end - itm_eq_obj->ex_data_bone_nodes.begin)) + return &itm_eq_obj->ex_data_bone_nodes.begin[bone_index & 0x7FFF]; + return 0; +} + +static bone_node* rob_chara_data_item_equip_object_get_bone_node_by_name( + rob_chara_data_item_equip_object* itm_eq_obj, char* name, bone_database* bone_data) { + return rob_chara_data_item_equip_object_get_bone_node(itm_eq_obj, + rob_chara_data_item_equip_object_get_bone_index(itm_eq_obj, name, bone_data)); +} + +static void rob_chara_data_item_equip_object_get_parent_bone_nodes( + rob_chara_data_item_equip_object* itm_eq_obj, bone_node* bone_nodes, bone_database* bone_data) { + + itm_eq_obj->bone_nodes = bone_nodes; + itm_eq_obj->mat = bone_nodes->mat; + for (ex_node_block** i = itm_eq_obj->node_blocks.begin; i != itm_eq_obj->node_blocks.end; i++) + (*i)->parent_bone_node = rob_chara_data_item_equip_object_get_bone_node_by_name( + itm_eq_obj, string_data(&(*i)->parent_name), bone_data); +} + +static void rob_chara_data_item_equip_object_init_data(rob_chara_data_item_equip_object* itm_eq_obj, size_t index) { + itm_eq_obj->index = index; + itm_eq_obj->object_info = object_info_null; + itm_eq_obj->field_14 = -1; + itm_eq_obj->mat = 0; + itm_eq_obj->texture_pattern.end = itm_eq_obj->texture_pattern.begin; + itm_eq_obj->texture_data.field_0 = -1; + itm_eq_obj->texture_data.texture_color_coeff = vec3_identity; + itm_eq_obj->texture_data.texture_color_offset = vec3_null; + itm_eq_obj->texture_data.texture_specular_coeff = vec3_identity; + itm_eq_obj->texture_data.texture_specular_offset = vec3_null; + itm_eq_obj->alpha = 1.0f; + itm_eq_obj->draw_task_flags = DRAW_TASK_10000; + itm_eq_obj->field_64 = 0; + itm_eq_obj->draw = true; + itm_eq_obj->field_A4 = 0; + itm_eq_obj->field_A8 = 0; + itm_eq_obj->bone_nodes = 0; + rob_chara_data_item_equip_object_clear_ex_data(itm_eq_obj); + itm_eq_obj->ex_data_bone_nodes.end = itm_eq_obj->ex_data_bone_nodes.begin; + itm_eq_obj->field_F0.end = itm_eq_obj->field_F0.begin; + itm_eq_obj->field_108.end = itm_eq_obj->field_108.begin; + for (ex_data_name_bone_index* i = itm_eq_obj->ex_bones.begin; i != itm_eq_obj->ex_bones.end; i++) + i->name = 0; + itm_eq_obj->ex_bones.end = itm_eq_obj->ex_bones.begin; + itm_eq_obj->field_1B8 = 0; + itm_eq_obj->field_1C8 = 0; + itm_eq_obj->field_1C0 = 0; +} + +static void rob_chara_data_item_equip_object_init_ex_data_bone_nodes( + rob_chara_data_item_equip_object* itm_eq_obj, object_skin_ex_data* a2) { + itm_eq_obj->ex_data_bone_nodes.end = itm_eq_obj->ex_data_bone_nodes.begin; + itm_eq_obj->field_F0.end = itm_eq_obj->field_F0.begin; + int32_t count = 40; + if (a2->bone_names_count > 40) + count = a2->bone_names_count; + + vector_bone_node_reserve(&itm_eq_obj->ex_data_bone_nodes, count); + itm_eq_obj->ex_data_bone_nodes.end += count; + vector_mat4_reserve(&itm_eq_obj->field_F0, count); + itm_eq_obj->field_F0.end += count; + vector_mat4_reserve(&itm_eq_obj->field_108, count); + itm_eq_obj->field_108.end += count; + + bone_node* v4 = itm_eq_obj->ex_data_bone_nodes.begin; + mat4* v5 = itm_eq_obj->field_F0.begin; + mat4* v8 = itm_eq_obj->field_108.begin; + for (int32_t v10 = 0; v10 < count; v10++) + v4[v10].mat = &v5[v10]; + + if (a2->bone_names) { + vector_ex_data_name_bone_index* v14 = &itm_eq_obj->ex_bones; + memset(v14->begin, 0, sizeof(ex_data_name_bone_index) * (v14->end - v14->begin)); + for (ex_data_name_bone_index* i = v14->begin; i != v14->end; ++i) + i->name = 0; + v14->end = v14->begin; + + for (int32_t i = 0; i < a2->bone_names_count; i++) { + bone_node* v38 = &v4[i]; + v38->name = a2->bone_names[i]; + v38->mat = &v5[i]; + *v38->mat = mat4_identity; + mat4_translate(0.0f, 0.0f, -1000.0f, v38->mat); + bone_node_expression_data_reset_position_rotation(&v38->exp_data); + v38->ex_data_mat = &v8[i]; + *v38->ex_data_mat = mat4_identity; + + ex_data_name_bone_index* v35 = vector_ex_data_name_bone_index_reserve_back(v14); + v35->name = a2->bone_names[i]; + v35->bone_index = i; + } + } +} + +static void rob_chara_data_item_equip_object_load_ex_data(rob_chara_data_item_equip_object* itm_eq_obj, + object_skin_ex_data* ex_data, bone_database* bone_data) { + if (!ex_data->blocks) + return; + + vector_pair_int32_t_ptr_rob_osage_node a4 + = vector_empty(pair_int32_t_ptr_rob_osage_node); + vector_pair_name_ex_osage_block a5 = vector_empty(pair_name_ex_osage_block); + rob_chara_data_item_equip_object_clear_ex_data(itm_eq_obj); + + size_t constraint_count = 0; + size_t expression_count = 0; + size_t osage_count = 0; + size_t cloth_count = 0; + char** bone_names_ptr = ex_data->bone_names; + object_skin_block* v4 = ex_data->blocks; + for (int32_t i = 0; i < ex_data->blocks_count; i++, v4++) { + ex_node_block* node; + if (v4->type == OBJECT_SKIN_BLOCK_CLOTH) { + if (cloth_count >= 0x08) + continue; + + ex_cloth_block* cls = ex_cloth_block_init(); + node = &cls->base; + vector_ptr_ex_cloth_block_push_back(&itm_eq_obj->cloth_blocks, &cls); + cls->index = cloth_count + osage_count; + cloth_count++; + continue; + } + else if (v4->type == OBJECT_SKIN_BLOCK_CONSTRAINT) { + if (constraint_count >= 0x40) + continue; + + ex_constraint_block* cns = ex_constraint_block_init(); + node = &cns->base; + vector_ptr_ex_constraint_block_push_back(&itm_eq_obj->constraint_blocks, &cns); + ex_constraint_block_init_data(cns, itm_eq_obj, &v4->constraint, + bone_names_ptr[v4->constraint.name_index & 0x7FFF], bone_data); + constraint_count++; + } + else if (v4->type == OBJECT_SKIN_BLOCK_EXPRESSION) { + if (expression_count >= 0x50) + continue; + + ex_expression_block* exp = ex_expression_block_init(); + node = &exp->base; + vector_ptr_ex_expression_block_push_back(&itm_eq_obj->expression_blocks, &exp); + ex_expression_block_init_data(exp, itm_eq_obj, &v4->expression, + bone_names_ptr[v4->expression.name_index & 0x7FFF], + itm_eq_obj->object_info, itm_eq_obj->index, bone_data); + expression_count++; + } + else if (v4->type == OBJECT_SKIN_BLOCK_OSAGE) { + if (osage_count >= 0x100) + continue; + + ex_osage_block* osg = ex_osage_block_init(); + node = &osg->base; + vector_ptr_ex_osage_block_push_back(&itm_eq_obj->osage_blocks, &osg); + ex_osage_block_init_data(osg, itm_eq_obj, &v4->osage, + bone_names_ptr[v4->constraint.name_index & 0x7FFF], + &itm_eq_obj->skin_ex_data->osage_nodes[v4->osage.start_index], + itm_eq_obj->bone_nodes, itm_eq_obj->ex_data_bone_nodes.begin, itm_eq_obj->skin); + sub_1405F3E10(osg, &v4->osage, &itm_eq_obj->skin_ex_data->osage_nodes[v4->osage.start_index], &a4, &a5); + osg->index = osage_count; + osage_count++; + } + else + continue; + + object_skin_block_node* v54 = &v4->base; + bone_node_expression_data exp_data; + exp_data.position = v54->position; + exp_data.rotation = v54->rotation; + exp_data.scale = v54->scale; + exp_data.data_scale = vec3_identity; + string_copy(&v54->parent_name, &node->parent_name); + + bone_node* parent_bone_node = rob_chara_data_item_equip_object_get_bone_node_by_name(itm_eq_obj, + string_data(&v54->parent_name), bone_data); + node->parent_bone_node = parent_bone_node; + if (node->bone_node) { + node->bone_node->exp_data = exp_data; + node->bone_node->parent = parent_bone_node; + } + vector_ptr_ex_node_block_push_back(&itm_eq_obj->node_blocks, &node); + } + + for (ex_node_block** i = itm_eq_obj->node_blocks.begin; i != itm_eq_obj->node_blocks.end; i++) { + ex_node_block* v86 = (*i)->parent_node; + if (v86) { + v86->field_5A = true; + if (v86->type == EX_OSAGE || v86->type == EX_CLOTH || !v86->field_58) + continue; + } + (*i)->field_58 = true; + } + vector_pair_int32_t_ptr_rob_osage_node_free(&a4, 0); + vector_pair_name_ex_osage_block_free(&a5, 0); +} + +static void rob_chara_data_item_equip_object_load_object_info_ex_data( + rob_chara_data_item_equip_object* itm_eq_obj, object_info object_info, + bone_node* bone_nodes, bone_database* bone_data) { + itm_eq_obj->object_info = object_info; + itm_eq_obj->bone_nodes = bone_nodes; + itm_eq_obj->mat = bone_nodes->mat; + itm_eq_obj->ex_data_bone_nodes.end = itm_eq_obj->ex_data_bone_nodes.begin; + for (ex_data_name_bone_index* i = itm_eq_obj->ex_bones.begin; + i != itm_eq_obj->ex_bones.end; i++) + i->name = 0; + + itm_eq_obj->ex_bones.end = itm_eq_obj->ex_bones.begin; + itm_eq_obj->field_F0.end = itm_eq_obj->field_F0.begin; + rob_chara_data_item_equip_object_clear_ex_data(itm_eq_obj); + object_skin* skin = object_storage_get_object_skin(itm_eq_obj->object_info); + if (!skin || !skin->ex_data_init) + return; + + itm_eq_obj->skin = skin; + itm_eq_obj->skin_ex_data = &skin->ex_data; + rob_chara_data_item_equip_object_init_ex_data_bone_nodes(itm_eq_obj, &skin->ex_data); + rob_chara_data_item_equip_object_load_ex_data(itm_eq_obj, &skin->ex_data, bone_data); +} + +static void rob_chara_data_item_equip_object_reset(rob_chara_data_item_equip_object* itm_eq_obj) { + rob_chara_data_item_equip_object_init_data(itm_eq_obj, 0xDEADBEEF); +} + +static void rob_chara_data_item_equip_object_free(rob_chara_data_item_equip_object* itm_eq_obj) { + rob_chara_data_item_equip_object_init_data(itm_eq_obj, 0xDDDDDDDD); + + if (itm_eq_obj->cloth_blocks.begin) + free(itm_eq_obj->cloth_blocks.begin); + itm_eq_obj->cloth_blocks = vector_ptr_empty(ex_cloth_block); + + if (itm_eq_obj->expression_blocks.begin) + free(itm_eq_obj->expression_blocks.begin); + itm_eq_obj->expression_blocks = vector_ptr_empty(ex_expression_block); + + if (itm_eq_obj->constraint_blocks.begin) + free(itm_eq_obj->constraint_blocks.begin); + itm_eq_obj->constraint_blocks = vector_ptr_empty(ex_constraint_block); + + if (itm_eq_obj->osage_blocks.begin) + free(itm_eq_obj->osage_blocks.begin); + itm_eq_obj->osage_blocks = vector_ptr_empty(ex_osage_block); + + if (itm_eq_obj->ex_bones.begin) + free(itm_eq_obj->ex_bones.begin); + itm_eq_obj->ex_bones = vector_empty(ex_data_name_bone_index); + + if (itm_eq_obj->field_108.begin) + free(itm_eq_obj->field_108.begin); + itm_eq_obj->field_108 = vector_empty(mat4); + + if (itm_eq_obj->field_F0.begin) + free(itm_eq_obj->field_F0.begin); + itm_eq_obj->field_F0 = vector_empty(mat4); + + if (itm_eq_obj->ex_data_bone_nodes.begin) + free(itm_eq_obj->ex_data_bone_nodes.begin); + itm_eq_obj->ex_data_bone_nodes = vector_empty(bone_node); + + if (itm_eq_obj->node_blocks.begin) + free(itm_eq_obj->node_blocks.begin); + itm_eq_obj->node_blocks = vector_ptr_empty(ex_node_block); + + if (itm_eq_obj->texture_pattern.begin) + free(itm_eq_obj->texture_pattern.begin); + itm_eq_obj->texture_pattern = vector_empty(texture_pattern_struct); + +} + +static void rob_chara_data_item_equip_reset(rob_chara_data_item_equip* rob_item_equip) { + rob_item_equip->bone_nodes = 0; + rob_item_equip->matrices = 0; + for (int32_t i = 0; i < 31; i++) + rob_chara_data_item_equip_object_reset(&rob_item_equip->item_equip_object[i]); + rob_item_equip->item_equip_range = false; + rob_item_equip->shadow_type = -1; + rob_item_equip->field_A0 = 5; + rob_item_equip->texture_pattern.end = rob_item_equip->texture_pattern.begin; + rob_item_equip->field_D0 = object_info_null; + rob_item_equip->field_D4 = -1; + rob_item_equip->field_D8 = false; + rob_item_equip->field_958 = false; + rob_item_equip->field_959 = false; + rob_item_equip->field_95A = false; + rob_item_equip->osage_phys_step = 0.0f; + rob_item_equip->field_93C = false; + rob_item_equip->first_item_equip_object = 1; + rob_item_equip->max_item_equip_object = 30; +} + +static void rob_chara_data_item_equip_dispose(rob_chara_data_item_equip* rob_item_equip) { + rob_chara_data_item_equip_reset(rob_item_equip); + rob_chara_data_item_equip_object* itm_eq_obj = rob_item_equip->item_equip_object; + for (int32_t i = 0; i < 31; i++) + rob_chara_data_item_equip_object_free(&itm_eq_obj[i]); + free(itm_eq_obj); + + if (rob_item_equip->texture_pattern.begin) + free(rob_item_equip->texture_pattern.begin); + rob_item_equip->texture_pattern = vector_empty(texture_pattern_struct); + free(rob_item_equip); +} + +static bool rob_chara_data_check_for_ageageagain_module(chara_index chara_index, int32_t module_index) { + return chara_index == CHARA_MIKU && module_index == 148; +} + +static void rob_chara_data_load_default_motion(rob_chara_data* rob_chr_data, + bone_database* bone_data, motion_database* mot_db) { + int32_t motion_id = 195; //rob_cmn_mottbl_get_motion_index(rob_chr_data, 0); + rob_chara_data_load_default_motion_sub(rob_chr_data, 1, motion_id, bone_data, mot_db); +} + +static void sub_14041C680(rob_chara_data_bone_data* rob_bone_data, bool a2) { + struc_308* v2 = &rob_bone_data->motion_loaded.begin[0]->field_4F8; + if (a2) + v2->field_0 |= 2; + else + v2->field_0 &= ~2; +} + +static void sub_14041C9D0(rob_chara_data_bone_data* rob_bone_data, bool a2) { + struc_308* v2 = &rob_bone_data->motion_loaded.begin[0]->field_4F8; + v2->field_8 = (uint8_t)(v2->field_0 & 1); + if (a2) + v2->field_0 |= 1; + else + v2->field_0 &= ~1; +} + +static void sub_14041D2D0(rob_chara_data_bone_data* rob_bone_data, bool a2) { + struc_308* v2 = &rob_bone_data->motion_loaded.begin[0]->field_4F8; + if (a2) + v2->field_0 |= 4; + else + v2->field_0 &= ~4; +} + +static void sub_14041BC40(rob_chara_data_bone_data* rob_bone_data, bool a2) { + struc_308* v2 = &rob_bone_data->motion_loaded.begin[0]->field_4F8; + if (a2) + v2->field_0 |= 8; + else + v2->field_0 &= ~8; +} + +static void sub_140414F00(struc_308* a1, float_t a2) { + a1->field_B8 = a1->eyes_adjust; + a1->eyes_adjust = a2; +} + +static void sub_14041D270(rob_chara_data_bone_data* rob_bone_data, float_t a2) { + sub_140414F00(&rob_bone_data->motion_loaded.begin[0]->field_4F8, a2); +} + +static void sub_14041D2A0(rob_chara_data_bone_data* rob_bone_data, float_t a2) { + rob_bone_data->motion_loaded.begin[0]->field_4F8.field_B8 = a2; +} + +/*static void sub_1403FBED0(motion_blend* hinge, float_t v47, float_t hinge, float_t init_rot) { + if (v47 < 0.0f) { + hinge->field_8 = false; + hinge->field_C = 0.0f; + hinge->field_10 = 0.0f; + hinge->field_14 = hinge; + hinge->field_18 = init_rot; + } + else { + hinge->field_8 = true; + hinge->field_C = v47; + hinge->field_10 = 0.0f; + hinge->field_14 = hinge; + hinge->field_18 = init_rot; + } +}*/ + +/*static void sub_140414C60(motion_blend_mot* hinge, float_t v47, float_t hinge, float_t init_rot) { + motion_blend* v4 = hinge->field_5D0; + if (v4) + sub_1403FBED0(v4, v47, hinge, init_rot); +} + +static void sub_14041BF80(rob_chara_data_bone_data* rob_bone_data, float_t v47, float_t hinge, float_t init_rot) { + sub_140414C60(rob_bone_data->motion_loaded.begin[0], v47, hinge, init_rot); +} + +static void sub_14041D310(rob_chara_data_bone_data* rob_bone_data) { + motion_blend* v1 = rob_bone_data->motion_loaded.begin[0]->field_5D0; + if (v1) + v1->vftable->field_10(v1); +} + +static void sub_140419820(rob_chara_data_bone_data* rob_bone_data, int32_t skeleton_select) { + sub_140412E10(rob_bone_data->motion_loaded.begin[0], skeleton_select); +}*/ + +static void rob_chara_data_load_default_motion_sub(rob_chara_data* rob_chr_data, int32_t skeleton_select, + int32_t motion_id, bone_database* bone_data, motion_database* mot_db) { + /*sub_14041BE50(rob_chr_data->bone_data, -1); + sub_14041BFC0(rob_chr_data->bone_data, -1); + sub_14041C260(rob_chr_data->bone_data, -1); + sub_14041D200(rob_chr_data->bone_data, -1); + sub_14041BDB0(rob_chr_data->bone_data, -1); + sub_14041BD20(rob_chr_data->bone_data, -1);*/ + rob_chara_data_bone_data_motion_load(rob_chr_data->bone_data, motion_id, 1, bone_data, mot_db); + rob_chara_data_bone_data_set_frame(rob_chr_data->bone_data, 0.0f); + sub_14041C680(rob_chr_data->bone_data, 0); + sub_14041C9D0(rob_chr_data->bone_data, 0); + sub_14041D2D0(rob_chr_data->bone_data, 0); + sub_14041BC40(rob_chr_data->bone_data, 0); + sub_14041D270(rob_chr_data->bone_data, 0.0f); + sub_14041D2A0(rob_chr_data->bone_data, 0.0f); + rob_chara_data_bone_data_set_rotation_y(rob_chr_data->bone_data, 0.0f); + //sub_14041BF80(rob_chr_data->bone_data, 0.0f, 1.0f, 1.0f); + //sub_14041D310(rob_chr_data->bone_data); + rob_chara_data_bone_data_interpolate(rob_chr_data->bone_data); + rob_chara_data_bone_data_update(rob_chr_data->bone_data, 0); + //sub_140419820(rob_chr_data->bone_data, skeleton_select); +} + +static void rob_chara_data_set_draw(rob_chara_data* rob_chr_data, item_id id, bool draw) { + if (id < ITEM_BODY) + return; + else if (id < ITEM_ITEM16) + rob_chr_data->item_equip->item_equip_object[id].draw = draw; + else if (id == ITEM_MAX) + for (int32_t i = ITEM_ATAMA; i <= ITEM_ITEM16; i++) { + rob_chr_data->item_equip->item_equip_object[i].draw = draw; + /*if (i == ITEM_ATAMA && rob_chara_data_check_for_ageageagain_module( + rob_chr_data->chara_index, rob_chr_data->module_index)) { + sub_140543780(rob_chr_data->chara_id, 1, draw); + sub_140543780(rob_chr_data->chara_id, 2, draw); + sub_1405430F0(rob_chr_data->chara_id, 1); + sub_1405430F0(rob_chr_data->chara_id, 2); + }*/ + } +} + +static rob_osage_node* rob_osage_get_node(rob_osage* rob_osg, + size_t index) { + if ((ssize_t)index < rob_osg->nodes.end - rob_osg->nodes.begin) + return &rob_osg->nodes.begin[index]; + else + return &rob_osg->node; +} + +static void rob_osage_node_init(rob_osage_node* node) { + node->length = 0.0f; + node->trans = vec3_null; + node->field_10 = vec3_null; + node->field_1C = vec3_null; + node->field_28 = vec3_null; + node->child_length = 0.0f; + node->bone_node = 0; + node->bone_node_mat = 0; + node->sibling_node = 0; + node->distance = 0.0f; + node->field_94 = vec3_null; + node->field_A0 = vec3_null; + node->field_AC = vec3_null; + node->field_B8 = vec3_null; + node->field_C4 = 0.0f; + node->field_C8 = 0.0f; + node->field_CC = 1.0f; + node->field_D0 = vec3_null; + node->field_DC = 1.0f; + rob_osage_node_data_init(&node->data); + node->data_ptr = &node->data; + node->field_198.end = node->field_198.begin; + vector_struc_331_reserve(&node->field_198, 3); + node->field_198.end += 3; + node->mat = mat4u_null; +} + +static void rob_osage_node_free(rob_osage_node* node) { + vector_struc_331_free(&node->field_198, 0); + vector_ptr_rob_osage_node* boc = &node->data.boc; + for (rob_osage_node** i = boc->begin; i != boc->end; i++) + *i = 0; + vector_ptr_rob_osage_node_free(&node->data.boc, 0); +} + +static void rob_osage_set_coli(rob_osage* rob_osg, mat4* mats) { + if (rob_osg->skin_param_ptr->coli.begin != rob_osg->skin_param_ptr->coli.end) + osage_coli_set(rob_osg->coli, rob_osg->skin_param_ptr->coli.begin, mats); + osage_coli_ring_set(rob_osg->coli_ring, &rob_osg->ring.skp_root_coli, mats); +} + +static void rob_osage_free(rob_osage* rob_osg) { + rob_osage_init(rob_osg); + //sub_14021BEF0(&rob_osg->field_1F60, rob_osg->field_1F60.head->left, rob_osg->field_1F60.head); + //j_free_2(rob_osg->field_1F60.head); + vector_skin_param_osage_root_coli_free(&rob_osg->ring.skp_root_coli, 0); + vector_osage_coli_free(&rob_osg->ring.coli, 0); + vector_skin_param_osage_root_coli_free(&rob_osg->skin_param.coli, 0); + rob_osage_node_free(&rob_osg->node); + vector_rob_osage_node_free(&rob_osg->nodes, rob_osage_node_free); +} + +static void skin_param_init(skin_param* skp) { + skp->coli.end = skp->coli.begin; + skp->friction = 1.0f; + skp->wind_afc = 0.0f; + skp->air_res = 1.0f; + skp->rot = vec3_null; + skp->init_rot = vec3_null; + skp->coli_type = 0; + skp->stiffness = 0.0f; + skp->move_cancel = -0.01f; + skp->coli_r = 0.0; + skp->hinge = (skin_param_hinge){ -90.0f, 90.0f, -90.0f, 90.0f }; + skin_param_hinge_limit(&skp->hinge); + skp->force = 0.0f; + skp->force_gain = 0.0f; + skp->colli_tgt_osg = 0; +} + +void rob_chara_data_array_init() { + for (int32_t i = 0; i < 6; i++) + rob_chara_data_init(&rob_chara_data_array[i]); +} + +rob_chara_data* rob_chara_data_array_get(int32_t chara_id) { + if (rob_chara_pv_data_array_check_chara_id(chara_id)) + return &rob_chara_data_array[chara_id]; + return 0; +} + +void rob_chara_data_array_free() { + for (int32_t i = 0; i < 6; i++) + rob_chara_data_free(&rob_chara_data_array[i]); +} + +void rob_chara_pv_data_init(rob_chara_pv_data* pv_data) { + memset(pv_data, 0, sizeof(rob_chara_pv_data)); + pv_data->index = 2; + pv_data->field_4 = 1; + pv_data->field_5 = 0; + pv_data->field_6 = 0; + pv_data->field_14 = 0x00; + pv_data->field_16 = 0xC9; + pv_data->field_74 = -1; + pv_data->field_78 = -1; + pv_data->field_7C = -1; + pv_data->field_80 = -1; + pv_data->field_84 = -1; + pv_data->field_88 = -1; + pv_data->field_8C = -1; + pv_data->field_90 = -1; + pv_data->field_94 = -1; + pv_data->field_98 = -1; + pv_data->field_9C = 1; + pv_data->eyes_adjust.base_adjust = EYES_BASE_ADJUST_DIRECTION; + pv_data->eyes_adjust.neg = -1.0f; + pv_data->eyes_adjust.pos = -1.0f; +} + +inline bool rob_chara_pv_data_array_check_chara_id(int32_t chara_id) { + //return rob_chara_pv_data_array[chara_id].index != -1; + return rob_chara_data_array[chara_id].chara_id != -1; +} + +inline void motion_storage_init() { + motion_storage_data = vector_empty(motion_storage); +} + +inline void motion_storage_append_mot_set(uint32_t set_id) { + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) + if (i->set_id == set_id) { + i->count++; + return; + } +} + +inline void motion_storage_insert_motion_set(mot_set* set, uint32_t set_id) { + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) + if (i->set_id == set_id) { + mot_set_free(&i->set); + i->count++; + i->set = *set; + return; + } + + motion_storage* mot_set_storage = vector_motion_storage_reserve_back(&motion_storage_data); + mot_set_storage->set_id = set_id; + mot_set_storage->count = 1; + mot_set_storage->set = *set; +} + +inline mot_set* motion_storage_get_motion_set(uint32_t set_id) { + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) + if (i->set_id == set_id) + return &i->set; + return 0; +} + +inline void motion_storage_delete_motion_set(uint32_t set_id) { + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) + if (i->set_id == set_id) { + i->count--; + if (i->count > 0) + break; + + mot_set_free(&i->set); + + vector_motion_storage_erase(&motion_storage_data, + i - motion_storage_data.begin, 0); + break; + } +} + +inline mot_data* motion_storage_get_mot_data(uint32_t motion_id, motion_database* mot_db) { + uint32_t set_id = -1; + size_t motion_index = -1; + vector_motion_set_info* motion_set = &mot_db->motion_set; + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) { + vector_motion_info* motion = &i->motion; + for (motion_info* j = motion->begin; j != motion->end; j++) + if (j->id == motion_id) { + set_id = i->id; + motion_index = j - motion->begin; + + break; + } + + if (set_id != -1) + break; + } + + if (set_id == -1) + return 0; + + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) + if (i->set_id == set_id) + return &i->set.vec.begin[motion_index]; + return 0; +} + +inline void motion_storage_free() { + for (motion_storage* i = motion_storage_data.begin; + i != motion_storage_data.end; i++) { + mot_set_free(&i->set); + } + vector_motion_storage_free(&motion_storage_data, 0); +} diff --git a/src/CRE/rob.h b/src/CRE/rob.h new file mode 100644 index 00000000..2b5b12a9 --- /dev/null +++ b/src/CRE/rob.h @@ -0,0 +1,1105 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/database/bone.h" +#include "../KKdLib/database/motion.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/mot.h" +#include "../KKdLib/vec.h" +#include "draw_object.h" +#include "object.h" +#include "static_var.h" + +typedef enum chara_index { + CHARA_MIKU = 0, + CHARA_RIN = 1, + CHARA_LEN = 2, + CHARA_LUKA = 3, + CHARA_NERU = 4, + CHARA_HAKU = 5, + CHARA_KAITO = 6, + CHARA_MEIKO = 7, + CHARA_SAKINE = 8, + CHARA_TETO = 9, + CHARA_MAX = 10, +} chara_index; + +typedef enum ex_expression_block_stack_type { + EX_EXPRESSION_BLOCK_STACK_NUMBER = 0x00, + EX_EXPRESSION_BLOCK_STACK_VARIABLE = 0x01, + EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN = 0x02, + EX_EXPRESSION_BLOCK_STACK_OP1 = 0x03, + EX_EXPRESSION_BLOCK_STACK_OP2 = 0x04, + EX_EXPRESSION_BLOCK_STACK_OP3 = 0x05, +} ex_expression_block_stack_type; + +typedef enum ex_node_type { + EX_NONE = 0x00, + EX_OSAGE = 0x01, + EX_EXPRESSION = 0x02, + EX_CONSTRAINT = 0x03, + EX_CLOTH = 0x04, +} ex_node_type; + +typedef enum eyes_base_adjust_type { + EYES_BASE_ADJUST_DIRECTION = 0, + EYES_BASE_ADJUST_CLEARANCE = 1, + EYES_BASE_ADJUST_OFF = 2, +} eyes_base_adjust_type; + +typedef enum item_id { + ITEM_NONE = -1, + ITEM_BODY = 0x00, + ITEM_ATAMA = 0x01, + ITEM_KATA_R = 0x02, + ITEM_MUNE = 0x03, + ITEM_KATA_L = 0x04, + ITEM_UDE_R = 0x05, + ITEM_SENAKA = 0x06, + ITEM_UDE_L = 0x07, + ITEM_HARA = 0x08, + ITEM_KOSI = 0x09, + ITEM_TE_R = 0x0A, + ITEM_TE_L = 0x0B, + ITEM_MOMO = 0x0C, + ITEM_SUNE = 0x0D, + ITEM_ASI = 0x0E, + ITEM_KAMI = 0x0F, + ITEM_OUTER = 0x10, + ITEM_PANTS = 0x11, + ITEM_ZUJO = 0x12, + ITEM_MEGANE = 0x13, + ITEM_KUBI = 0x14, + ITEM_JOHA_USHIRO = 0x15, + ITEM_KUCHI = 0x16, + ITEM_ITEM09 = 0x17, + ITEM_ITEM10 = 0x18, + ITEM_ITEM11 = 0x19, + ITEM_ITEM12 = 0x1A, + ITEM_ITEM13 = 0x1B, + ITEM_ITEM14 = 0x1C, + ITEM_ITEM15 = 0x1D, + ITEM_ITEM16 = 0x1E, + ITEM_MAX = 0x1F, +} item_id; + +typedef enum item_sub_id { + ITEM_SUB_NONE = -1, + ITEM_SUB_ZUJO = 0x00, + ITEM_SUB_KAMI = 0x01, + ITEM_SUB_HITAI = 0x02, + ITEM_SUB_ME = 0x03, + ITEM_SUB_MEGANE = 0x04, + ITEM_SUB_MIMI = 0x05, + ITEM_SUB_KUCHI = 0x06, + ITEM_SUB_MAKI = 0x07, + ITEM_SUB_KUBI = 0x08, + ITEM_SUB_INNER = 0x09, + ITEM_SUB_OUTER = 0x0A, + ITEM_SUB_JOHA_MAE = 0x0B, + ITEM_SUB_JOHA_USHIRO = 0x0C, + ITEM_SUB_HADA = 0x0D, + ITEM_SUB_KATA = 0x0E, + ITEM_SUB_U_UDE = 0x0F, + ITEM_SUB_L_UDE = 0x10, + ITEM_SUB_TE = 0x11, + ITEM_SUB_BELT = 0x12, + ITEM_SUB_COSI = 0x13, + ITEM_SUB_PANTS = 0x14, + ITEM_SUB_ASI = 0x15, + ITEM_SUB_SUNE = 0x16, + ITEM_SUB_KUTSU = 0x17, + ITEM_SUB_HEAD = 0x18, + ITEM_SUB_MAX = 0x19, +} item_sub_id; + +typedef enum motion_bone_index { + MOTION_BONE_NONE = -1, + MOTION_BONE_N_HARA_CP = 0x00, + MOTION_BONE_KG_HARA_Y = 0x01, + MOTION_BONE_KL_HARA_XZ = 0x02, + MOTION_BONE_KL_HARA_ETC = 0x03, + MOTION_BONE_N_HARA = 0x04, + MOTION_BONE_CL_MUNE = 0x05, + MOTION_BONE_N_MUNE_B = 0x06, + MOTION_BONE_KL_MUNE_B_WJ = 0x07, + MOTION_BONE_KL_KUBI = 0x08, + MOTION_BONE_N_KAO = 0x09, + MOTION_BONE_CL_KAO = 0x0A, + MOTION_BONE_FACE_ROOT = 0x0B, + MOTION_BONE_N_AGO = 0x0C, + MOTION_BONE_KL_AGO_WJ = 0x0D, + MOTION_BONE_N_TOOTH_UNDER = 0x0E, + MOTION_BONE_TL_TOOTH_UNDER_WJ = 0x0F, + MOTION_BONE_N_EYE_L = 0x10, + MOTION_BONE_KL_EYE_L = 0x11, + MOTION_BONE_N_EYE_L_WJ_EX = 0x12, + MOTION_BONE_KL_HIGHLIGHT_L_WJ = 0x13, + MOTION_BONE_N_EYE_R = 0x14, + MOTION_BONE_KL_EYE_R = 0x15, + MOTION_BONE_N_EYE_R_WJ_EX = 0x16, + MOTION_BONE_KL_HIGHLIGHT_R_WJ = 0x17, + MOTION_BONE_N_EYELID_L_A = 0x18, + MOTION_BONE_TL_EYELID_L_A_WJ = 0x19, + MOTION_BONE_N_EYELID_L_B = 0x1A, + MOTION_BONE_TL_EYELID_L_B_WJ = 0x1B, + MOTION_BONE_N_EYELID_R_A = 0x1C, + MOTION_BONE_TL_EYELID_R_A_WJ = 0x1D, + MOTION_BONE_N_EYELID_R_B = 0x1E, + MOTION_BONE_TL_EYELID_R_B_WJ = 0x1F, + MOTION_BONE_N_KUTI_D = 0x20, + MOTION_BONE_TL_KUTI_D_WJ = 0x21, + MOTION_BONE_N_KUTI_D_L = 0x22, + MOTION_BONE_TL_KUTI_D_L_WJ = 0x23, + MOTION_BONE_N_KUTI_D_R = 0x24, + MOTION_BONE_TL_KUTI_D_R_WJ = 0x25, + MOTION_BONE_N_KUTI_DS_L = 0x26, + MOTION_BONE_TL_KUTI_DS_L_WJ = 0x27, + MOTION_BONE_N_KUTI_DS_R = 0x28, + MOTION_BONE_TL_KUTI_DS_R_WJ = 0x29, + MOTION_BONE_N_KUTI_L = 0x2A, + MOTION_BONE_TL_KUTI_L_WJ = 0x2B, + MOTION_BONE_N_KUTI_M_L = 0x2C, + MOTION_BONE_TL_KUTI_M_L_WJ = 0x2D, + MOTION_BONE_N_KUTI_M_R = 0x2E, + MOTION_BONE_TL_KUTI_M_R_WJ = 0x2F, + MOTION_BONE_N_KUTI_R = 0x30, + MOTION_BONE_TL_KUTI_R_WJ = 0x31, + MOTION_BONE_N_KUTI_U = 0x32, + MOTION_BONE_TL_KUTI_U_WJ = 0x33, + MOTION_BONE_N_KUTI_U_L = 0x34, + MOTION_BONE_TL_KUTI_U_L_WJ = 0x35, + MOTION_BONE_N_KUTI_U_R = 0x36, + MOTION_BONE_TL_KUTI_U_R_WJ = 0x37, + MOTION_BONE_N_MABU_L_D_A = 0x38, + MOTION_BONE_TL_MABU_L_D_A_WJ = 0x39, + MOTION_BONE_N_MABU_L_D_B = 0x3A, + MOTION_BONE_TL_MABU_L_D_B_WJ = 0x3B, + MOTION_BONE_N_MABU_L_D_C = 0x3C, + MOTION_BONE_TL_MABU_L_D_C_WJ = 0x3D, + MOTION_BONE_N_MABU_L_U_A = 0x3E, + MOTION_BONE_TL_MABU_L_U_A_WJ = 0x3F, + MOTION_BONE_N_MABU_L_U_B = 0x40, + MOTION_BONE_TL_MABU_L_U_B_WJ = 0x41, + MOTION_BONE_N_EYELASHES_L = 0x42, + MOTION_BONE_TL_EYELASHES_L_WJ = 0x43, + MOTION_BONE_N_MABU_L_U_C = 0x44, + MOTION_BONE_TL_MABU_L_U_C_WJ = 0x45, + MOTION_BONE_N_MABU_R_D_A = 0x46, + MOTION_BONE_TL_MABU_R_D_A_WJ = 0x47, + MOTION_BONE_N_MABU_R_D_B = 0x48, + MOTION_BONE_TL_MABU_R_D_B_WJ = 0x49, + MOTION_BONE_N_MABU_R_D_C = 0x4A, + MOTION_BONE_TL_MABU_R_D_C_WJ = 0x4B, + MOTION_BONE_N_MABU_R_U_A = 0x4C, + MOTION_BONE_TL_MABU_R_U_A_WJ = 0x4D, + MOTION_BONE_N_MABU_R_U_B = 0x4E, + MOTION_BONE_TL_MABU_R_U_B_WJ = 0x4F, + MOTION_BONE_N_EYELASHES_R = 0x50, + MOTION_BONE_TL_EYELASHES_R_WJ = 0x51, + MOTION_BONE_N_MABU_R_U_C = 0x52, + MOTION_BONE_TL_MABU_R_U_C_WJ = 0x53, + MOTION_BONE_N_MAYU_L = 0x54, + MOTION_BONE_TL_MAYU_L_WJ = 0x55, + MOTION_BONE_N_MAYU_L_B = 0x56, + MOTION_BONE_TL_MAYU_L_B_WJ = 0x57, + MOTION_BONE_N_MAYU_L_C = 0x58, + MOTION_BONE_TL_MAYU_L_C_WJ = 0x59, + MOTION_BONE_N_MAYU_R = 0x5A, + MOTION_BONE_TL_MAYU_R_WJ = 0x5B, + MOTION_BONE_N_MAYU_R_B = 0x5C, + MOTION_BONE_TL_MAYU_R_B_WJ = 0x5D, + MOTION_BONE_N_MAYU_R_C = 0x5E, + MOTION_BONE_TL_MAYU_R_C_WJ = 0x5F, + MOTION_BONE_N_TOOTH_UPPER = 0x60, + MOTION_BONE_TL_TOOTH_UPPER_WJ = 0x61, + MOTION_BONE_N_KUBI_WJ_EX = 0x62, + MOTION_BONE_N_WAKI_L = 0x63, + MOTION_BONE_KL_WAKI_L_WJ = 0x64, + MOTION_BONE_TL_UP_KATA_L = 0x65, + MOTION_BONE_C_KATA_L = 0x66, + MOTION_BONE_KL_TE_L_WJ = 0x67, + MOTION_BONE_N_HITO_L_EX = 0x68, + MOTION_BONE_NL_HITO_L_WJ = 0x69, + MOTION_BONE_NL_HITO_B_L_WJ = 0x6A, + MOTION_BONE_NL_HITO_C_L_WJ = 0x6B, + MOTION_BONE_N_KO_L_EX = 0x6C, + MOTION_BONE_NL_KO_L_WJ = 0x6D, + MOTION_BONE_NL_KO_B_L_WJ = 0x6E, + MOTION_BONE_NL_KO_C_L_WJ = 0x6F, + MOTION_BONE_N_KUSU_L_EX = 0x70, + MOTION_BONE_NL_KUSU_L_WJ = 0x71, + MOTION_BONE_NL_KUSU_B_L_WJ = 0x72, + MOTION_BONE_NL_KUSU_C_L_WJ = 0x73, + MOTION_BONE_N_NAKA_L_EX = 0x74, + MOTION_BONE_NL_NAKA_L_WJ = 0x75, + MOTION_BONE_NL_NAKA_B_L_WJ = 0x76, + MOTION_BONE_NL_NAKA_C_L_WJ = 0x77, + MOTION_BONE_N_OYA_L_EX = 0x78, + MOTION_BONE_NL_OYA_L_WJ = 0x79, + MOTION_BONE_NL_OYA_B_L_WJ = 0x7A, + MOTION_BONE_NL_OYA_C_L_WJ = 0x7B, + MOTION_BONE_N_STE_L_WJ_EX = 0x7C, + MOTION_BONE_N_SUDE_L_WJ_EX = 0x7D, + MOTION_BONE_N_SUDE_B_L_WJ_EX = 0x7E, + MOTION_BONE_N_HIJI_L_WJ_EX = 0x7F, + MOTION_BONE_N_UP_KATA_L_EX = 0x80, + MOTION_BONE_N_SKATA_L_WJ_CD_EX = 0x81, + MOTION_BONE_N_SKATA_B_L_WJ_CD_CU_EX = 0x82, + MOTION_BONE_N_SKATA_C_L_WJ_CD_CU_EX = 0x83, + MOTION_BONE_N_WAKI_R = 0x84, + MOTION_BONE_KL_WAKI_R_WJ = 0x85, + MOTION_BONE_TL_UP_KATA_R = 0x86, + MOTION_BONE_C_KATA_R = 0x87, + MOTION_BONE_KL_TE_R_WJ = 0x88, + MOTION_BONE_N_HITO_R_EX = 0x89, + MOTION_BONE_NL_HITO_R_WJ = 0x8A, + MOTION_BONE_NL_HITO_B_R_WJ = 0x8B, + MOTION_BONE_NL_HITO_C_R_WJ = 0x8C, + MOTION_BONE_N_KO_R_EX = 0x8D, + MOTION_BONE_NL_KO_R_WJ = 0x8E, + MOTION_BONE_NL_KO_B_R_WJ = 0x8F, + MOTION_BONE_NL_KO_C_R_WJ = 0x90, + MOTION_BONE_N_KUSU_R_EX = 0x91, + MOTION_BONE_NL_KUSU_R_WJ = 0x92, + MOTION_BONE_NL_KUSU_B_R_WJ = 0x93, + MOTION_BONE_NL_KUSU_C_R_WJ = 0x94, + MOTION_BONE_N_NAKA_R_EX = 0x95, + MOTION_BONE_NL_NAKA_R_WJ = 0x96, + MOTION_BONE_NL_NAKA_B_R_WJ = 0x97, + MOTION_BONE_NL_NAKA_C_R_WJ = 0x98, + MOTION_BONE_N_OYA_R_EX = 0x99, + MOTION_BONE_NL_OYA_R_WJ = 0x9A, + MOTION_BONE_NL_OYA_B_R_WJ = 0x9B, + MOTION_BONE_NL_OYA_C_R_WJ = 0x9C, + MOTION_BONE_N_STE_R_WJ_EX = 0x9D, + MOTION_BONE_N_SUDE_R_WJ_EX = 0x9E, + MOTION_BONE_N_SUDE_B_R_WJ_EX = 0x9F, + MOTION_BONE_N_HIJI_R_WJ_EX = 0xA0, + MOTION_BONE_N_UP_KATA_R_EX = 0xA1, + MOTION_BONE_N_SKATA_R_WJ_CD_EX = 0xA2, + MOTION_BONE_N_SKATA_B_R_WJ_CD_CU_EX = 0xA3, + MOTION_BONE_N_SKATA_C_R_WJ_CD_CU_EX = 0xA4, + MOTION_BONE_KL_KOSI_Y = 0xA5, + MOTION_BONE_KL_KOSI_XZ = 0xA6, + MOTION_BONE_KL_KOSI_ETC_WJ = 0xA7, + MOTION_BONE_CL_MOMO_L = 0xA8, + MOTION_BONE_KL_ASI_L_WJ_CO = 0xA9, + MOTION_BONE_KL_TOE_L_WJ = 0xAA, + MOTION_BONE_N_HIZA_L_WJ_EX = 0xAB, + MOTION_BONE_CL_MOMO_R = 0xAC, + MOTION_BONE_KL_ASI_R_WJ_CO = 0xAD, + MOTION_BONE_KL_TOE_R_WJ = 0xAE, + MOTION_BONE_N_HIZA_R_WJ_EX = 0xAF, + MOTION_BONE_N_MOMO_A_L_WJ_CD_EX = 0xB0, + MOTION_BONE_N_MOMO_B_L_WJ_EX = 0xB1, + MOTION_BONE_N_MOMO_C_L_WJ_EX = 0xB2, + MOTION_BONE_N_MOMO_A_R_WJ_CD_EX = 0xB3, + MOTION_BONE_N_MOMO_B_R_WJ_EX = 0xB4, + MOTION_BONE_N_MOMO_C_R_WJ_EX = 0xB5, + MOTION_BONE_N_HARA_CD_EX = 0xB6, + MOTION_BONE_N_HARA_B_WJ_EX = 0xB7, + MOTION_BONE_N_HARA_C_WJ_EX = 0xB8, + MOTION_BONE_MAX = 0xB9, +} motion_bone_index; + +typedef struct bone_node bone_node; +typedef struct rob_chara_data_bone_data rob_chara_data_bone_data; + +typedef struct bone_node_expression_data { + vec3 position; + vec3 rotation; + vec3 scale; + vec3 data_scale; +} bone_node_expression_data; + +struct bone_node { + char* name; + mat4* mat; + bone_node* parent; + bone_node_expression_data exp_data; + mat4* ex_data_mat; +}; + +vector(bone_node) + +typedef struct struc_314 { + uint32_t* field_0; + size_t field_8; +} struc_314; + +typedef struct mot_key_set { + mot_key_set_type type; + int32_t keys_count; + int32_t current_key; + int32_t last_key; + uint16_t* frames; + float_t* values; +} mot_key_set; + +vector(mot_key_set) + +typedef union request_data_object_data { + struct { + int32_t zujo; + int32_t kami; + int32_t hitai; + int32_t me; + int32_t megane; + int32_t mimi; + int32_t kuchi; + int32_t maki; + int32_t kubi; + int32_t inner; + int32_t outer; + int32_t joha_mae; + int32_t joha_ushiro; + int32_t hada; + int32_t kata; + int32_t u_ude; + int32_t l_ude; + int32_t te; + int32_t belt; + int32_t cosi; + int32_t pants; + int32_t asi; + int32_t sune; + int32_t kutsu; + int32_t head; + }; + int32_t array[25]; +} request_data_object_data; + +typedef struct eyes_adjust { + bool xrot_adjust; + eyes_base_adjust_type base_adjust; + float_t neg; + float_t pos; +} eyes_adjust; + +typedef struct struc_313 { + vector_uint32_t bitfield; + size_t motion_bone_count; +} struc_313; + +typedef struct mot { + uint16_t key_set_count; + uint16_t frame_count; + uint16_t field_4; + mot_key_set* key_sets; +} mot; + +typedef struct struc_369 { + int32_t field_0; + float_t field_4; +} struc_369; + +typedef struct mot_parent { + bool key_sets_ready; + size_t key_set_count; + vector_mot_key_set key_set; + mot mot; + vector_float_t key_set_data; + mot_data* mot_data; + bone_database_skeleton_type skeleton_type; + int32_t skeleton_select; + int32_t motion_id; + float_t frame; + struc_369 field_68; +} mot_parent; + +typedef struct bone_data { + bone_database_bone_type type; + int32_t has_parent; + motion_bone_index motion_bone_index; + int32_t mirror; + int32_t parent; + int32_t flags; + int32_t key_set_offset; + int32_t key_set_count; + float_t frame; + vec3 base_translation[2]; + vec3 rotation; + vec3 ik_target; + vec3 trans; + mat4u rot_mat[3]; + vec3 trans_dup[2]; + mat4u rot_mat_dup[6]; + mat4* pole_target_mat; + mat4* parent_mat; + bone_node* node; + float_t ik_segment_length[2]; + float_t ik_2nd_segment_length[2]; + float_t field_2E0; + float_t eyes_xrot_adjust_neg; + float_t eyes_xrot_adjust_pos; +} bone_data; + +vector(bone_data) + +typedef struct bone_data_parent { + rob_chara_data_bone_data* rob_bone_data; + size_t motion_bone_count; + size_t ik_bone_count; + size_t chain_pos; + vector_bone_data bones; + vector_uint16_t bone_indices; + vec3 global_trans; + vec3 global_rotation; + uint32_t bone_key_set_count; + uint32_t global_key_set_count; + float_t rotation_y; +} bone_data_parent; + +typedef struct struc_346 { + float_t frame; + float_t step; + float_t field_8; + float_t frame_count; + float_t last_frame; + float_t field_14; + int32_t field_18; + int32_t field_1C; + float_t field_20; + float_t field_24; + bool field_28; + int32_t field_2C; +} struc_346; + +typedef struct struc_370 { + struc_346 field_0; + int32_t field_30; + bool field_34; + float_t field_38; + float_t* field_40; + float_t* field_48; +} struc_370; + +typedef struct struc_308 { + int32_t field_0; + int32_t field_4; + uint8_t field_8; + mat4u mat; + mat4u field_4C; + bool field_8C; + vec3 field_90; + vec3 field_9C; + vec3 field_A8; + float_t eyes_adjust; + float_t field_B8; + uint8_t field_BC; + uint8_t field_BD; + float_t field_C0; + float_t field_C4; + vec3 field_C8; +} struc_308; + +typedef struct motion_blend_mot { + bone_data_parent bone_data; + mot_parent mot_data; + struc_370 field_4A8; + struc_308 field_4F8; +} motion_blend_mot; + +vector_ptr(motion_blend_mot) + +typedef struct rob_chara_data_bone_data_ik_scale { + float_t ratio0; + float_t ratio1; + float_t ratio2; + float_t ratio3; +} rob_chara_data_bone_data_ik_scale; + +struct rob_chara_data_bone_data { + size_t object_bone_count; + size_t total_bone_count; + size_t motion_bone_count; + size_t ik_bone_count; + size_t chain_pos; + vector_mat4 mats; + vector_mat4 mats2; + vector_bone_node nodes; + bone_database_skeleton_type base_skeleton_type; + bone_database_skeleton_type skeleton_type; + vector_ptr_motion_blend_mot motions; + vector_size_t motion_indices; + vector_size_t motion_loaded_indices; + vector_ptr_motion_blend_mot motion_loaded; + rob_chara_data_bone_data_ik_scale ik_scale; +}; + +typedef struct struc_242 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; + int32_t field_10; + int32_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + int32_t field_28; +} struc_242; + +typedef struct rob_chara_pv_data { + int32_t index; + bool field_4; + bool field_5; + bool field_6; + vec3 field_8; + int16_t field_14; + int16_t field_16; + struc_242 field_18; + struc_242 field_44; + int32_t field_70; + int32_t field_74; + int32_t field_78; + int32_t field_7C; + int32_t field_80; + int32_t field_84; + int32_t field_88; + int32_t field_8C; + int32_t field_90; + int32_t field_94; + int32_t field_98; + int32_t field_9C; + bool field_A0; + int32_t shadow_type[4]; + eyes_adjust eyes_adjust; +} rob_chara_pv_data; + +typedef struct struc_218 { + vec3 bone_offset; + float_t scale; + int32_t bone_index; + int32_t field_14; +} struc_218; + +typedef struct struc_344 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; +} struc_344; + +typedef struct chara_init_data { + int32_t object_set; + bone_database_skeleton_type skeleton_type; + object_info base_face; + int32_t motion_set; + const struc_218* field_828; + const struc_218* field_830; + int32_t field_840; + int32_t field_844; + struc_344 field_848; + object_info head_objects[9]; + object_info face_objects[15]; +} chara_init_data; + +typedef struct struc_241 { + float_t field_0; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + float_t field_24; + float_t field_28; + float_t field_2C; + float_t field_30; + float_t field_34; + float_t field_38; + float_t field_3C; + float_t field_40; +} struc_241; + +typedef struct ex_node_block ex_node_block; +typedef struct rob_chara_data_item_equip_object rob_chara_data_item_equip_object; + +typedef struct ex_node_block_vtbl { + void(*dispose)(ex_node_block*); + //void(*field_8)(ex_node_block*); + void(*set_default_data)(ex_node_block*); + //void(*field_18)(ex_node_block*, int32_t, int32_t); + void(*update)(ex_node_block*); + //void(*field_28)(ex_node_block*); + void(*draw)(ex_node_block*); + void(*reset)(ex_node_block*); + //void(*field_40)(ex_node_block*); + //void(*field_48)(ex_node_block*); + //void(*field_50)(ex_node_block*); + //void(*field_58)(ex_node_block*); +} ex_node_block_vtbl; + +struct ex_node_block { + const ex_node_block_vtbl* vftable; + bone_node* bone_node; + ex_node_type type; + char* name; + bone_node* parent_bone_node; + string parent_name; + ex_node_block* parent_node; + rob_chara_data_item_equip_object* item_equip_object; + bool field_58; + bool set_data; + bool field_5A; +}; + +typedef struct ex_cloth_block { + ex_node_block base; + //rob_cloth rob; + object_skin_block_cloth* cloth_block; + mat4* field_2428; + size_t index; +} ex_cloth_block; + +typedef struct struc_331 { + int64_t field_0; + int64_t field_8; + int64_t field_10; +} struc_331; + +vector(struc_331) + +typedef struct rob_osage_node rob_osage_node; + +typedef struct rob_osage_node_data_normal_ref { + bool field_0; + rob_osage_node* n; + rob_osage_node* u; + rob_osage_node* d; + rob_osage_node* l; + rob_osage_node* r; + mat4u mat; +} rob_osage_node_data_normal_ref; + +typedef struct skin_param_hinge { + float_t ymin; + float_t ymax; + float_t zmin; + float_t zmax; +} skin_param_hinge; + +typedef struct skin_param_osage_node { + float_t coli_r; + float_t weight; + float_t inertial_cancel; + skin_param_hinge hinge; +} skin_param_osage_node; + +vector_ptr(rob_osage_node) + +typedef struct rob_osage_node_data { + float_t force; + vector_ptr_rob_osage_node boc; + rob_osage_node_data_normal_ref normal_ref; + skin_param_osage_node skp_osg_node; +} rob_osage_node_data; + +struct rob_osage_node { + float_t length; + vec3 trans; + vec3 field_10; + vec3 field_1C; + vec3 field_28; + float_t child_length; + bone_node* bone_node; + mat4* bone_node_mat; + mat4u mat; + rob_osage_node* sibling_node; + float_t distance; + vec3 field_94; + vec3 field_A0; + vec3 field_AC; + vec3 field_B8; + float_t field_C4; + float_t field_C8; + float_t field_CC; + vec3 field_D0; + float_t field_DC; + rob_osage_node_data* data_ptr; + rob_osage_node_data data; + int32_t field_194; + vector_struc_331 field_198; + int32_t field_1B0; + vec3 field_1B4; + vec3 field_1C0; + float_t field_1CC; +}; + +vector(rob_osage_node) + +typedef struct pair_int32_t_ptr_rob_osage_node { + int32_t key; + rob_osage_node* value; +} pair_int32_t_ptr_rob_osage_node; + +vector(pair_int32_t_ptr_rob_osage_node) + +typedef struct skin_param_osage_root_coli { + int32_t type; + int32_t bone0_index; + int32_t bone1_index; + float_t radius; + vec3 bone0_pos; + vec3 bone1_pos; +} skin_param_osage_root_coli; + +vector(skin_param_osage_root_coli) + +typedef struct skin_param { + vector_skin_param_osage_root_coli coli; + float_t friction; + float_t wind_afc; + float_t air_res; + vec3 rot; + vec3 init_rot; + int32_t coli_type; + float_t stiffness; + float_t move_cancel; + float_t coli_r; + skin_param_hinge hinge; + float_t force; + float_t force_gain; + vector_rob_osage_node* colli_tgt_osg; +} skin_param; + +typedef struct osage_coli { + int32_t type; + float_t radius; + vec3 bone0_pos; + vec3 bone1_pos; + vec3 bone_pos_diff; + float_t bone_pos_diff_length; + float_t bone_pos_diff_length_squared; + float_t field_34; +} osage_coli; + +vector(osage_coli) + +typedef struct osage_ring_data { + float_t ring_rectangle_x; + float_t ring_rectangle_y; + float_t ring_rectangle_width; + float_t ring_rectangle_height; + float_t ring_height; + float_t ring_out_height; + bool field_18; + vector_osage_coli coli; + vector_skin_param_osage_root_coli skp_root_coli; +} osage_ring_data; + +typedef struct rob_osage { + skin_param* skin_param_ptr; + bone_node_expression_data exp_data; + vector_rob_osage_node nodes; + rob_osage_node node; + skin_param skin_param; + int32_t field_290; + int64_t field_298; + bool field_2A0; + bool field_2A1; + float_t field_2A4; + osage_coli coli[64]; + osage_coli coli_ring[64]; + vec3 wind_direction; + float_t field_1EB4; + int32_t field_1EB8; + int32_t field_1EBC; + mat4* mats; + mat4u mat; + float_t field_1F08; + bool field_1F0C; + bool field_1F0D; + bool field_1F0E; + bool field_1F0F; + osage_ring_data ring; + //tree_295 field_1F60; + int64_t field_1F70; + bool field_1F78; + vec3 field_1F7C; +} rob_osage; + +typedef struct ex_osage_block { + ex_node_block base; + size_t index; + rob_osage rob; + mat4* mat; + int32_t field_1FF8; + float_t osage_phys_step; +} ex_osage_block; + +typedef struct pair_name_ex_osage_block { + char* name; + ex_osage_block* block; +} pair_name_ex_osage_block; + +vector(pair_name_ex_osage_block) + +typedef struct ex_constraint_block { + ex_node_block base; + object_skin_block_constraint_type type; + bone_node* source_node_bone_node; + bone_node* direction_up_vector_bone_node; + object_skin_block_constraint* cns_data; + int64_t field_80; +} ex_constraint_block; + +typedef struct ex_expression_block_stack ex_expression_block_stack; + +typedef struct ex_expression_block_stack_number { + float_t value; +} ex_expression_block_stack_number; + +typedef struct ex_expression_block_stack_variable { + float_t* value; +} ex_expression_block_stack_variable; + +typedef struct ex_expression_block_stack_variable_radian { + float_t* value; +} ex_expression_block_stack_variable_radian; + +typedef struct ex_expression_block_stack_op1 { + float_t(*func)(float_t v1); + ex_expression_block_stack* v1; +} ex_expression_block_stack_op1; + +typedef struct ex_expression_block_stack_op2 { + float_t(*func)(float_t v1, float_t v2); + ex_expression_block_stack* v1; + ex_expression_block_stack* v2; +} ex_expression_block_stack_op2; + +typedef struct ex_expression_block_stack_op3 { + float_t(*func)(float_t v1, float_t v2, float_t v3); + ex_expression_block_stack* v1; + ex_expression_block_stack* v2; + ex_expression_block_stack* v3; +} ex_expression_block_stack_op3; + +struct ex_expression_block_stack { + ex_expression_block_stack_type type; + union ex_expression_block_stack_union { + ex_expression_block_stack_number number; + ex_expression_block_stack_variable var; + ex_expression_block_stack_variable_radian var_rad; + ex_expression_block_stack_op1 op1; + ex_expression_block_stack_op2 op2; + ex_expression_block_stack_op3 op3; + }; +}; + +typedef struct ex_expression_block { + ex_node_block base; + float_t* values[9]; + ex_expression_block_stack_type types[9]; + ex_expression_block_stack* expressions[9]; + ex_expression_block_stack stack_data[384]; + object_skin_block_expression* exp_data; + bool field_3D20; + void(*field_3D28)(bone_node_expression_data*); + float_t frame; + bool osage_phys_step; +} ex_expression_block; + +vector_ptr(ex_constraint_block) +vector_ptr(ex_cloth_block) +vector_ptr(ex_expression_block) +vector_ptr(ex_osage_block) +vector_ptr(ex_node_block) + +typedef struct ex_data_name_bone_index { + char* name; + int32_t bone_index; +} ex_data_name_bone_index; + +vector(ex_data_name_bone_index) + +typedef struct rob_chara_data_item_equip rob_chara_data_item_equip; + +struct rob_chara_data_item_equip_object { + size_t index; + mat4* mat; + object_info object_info; + int32_t field_14; + vector_texture_pattern_struct texture_pattern; + texture_data_struct texture_data; + bool field_64; + bone_node_expression_data exp_data; + float_t alpha; + draw_task_flags draw_task_flags; + bool draw; + int32_t field_A4; + mat4* field_A8; + int32_t field_B0; + bone_node* bone_nodes; + vector_ptr_ex_node_block node_blocks; + vector_bone_node ex_data_bone_nodes; + vector_mat4 field_F0; + vector_mat4 field_108; + vector_ex_data_name_bone_index ex_bones; + int64_t field_138; + vector_ptr_ex_osage_block osage_blocks; + vector_ptr_ex_constraint_block constraint_blocks; + vector_ptr_ex_expression_block expression_blocks; + vector_ptr_ex_cloth_block cloth_blocks; + bool field_1B8; + int64_t field_1C0; + bool field_1C8; + object_skin_ex_data* skin_ex_data; + object_skin* skin; + rob_chara_data_item_equip* item_equip; +}; + +struct rob_chara_data_item_equip { + bone_node* bone_nodes; + mat4* matrices; + rob_chara_data_item_equip_object* item_equip_object; + int32_t field_18[31]; + bool item_equip_range; + int32_t first_item_equip_object; + int32_t max_item_equip_object; + int32_t field_A0; + shadow_type_enum shadow_type; + vec3 position; + int32_t eyes_adjust; + vector_texture_pattern_struct texture_pattern; + object_info field_D0; + int32_t field_D4; + bool field_D8; + int32_t field_DC; + vec4u texture_color_coeff; + float_t wet; + float_t wind_strength; + bool chara_color; + bool field_F9; + mat4u mat; + mat4u field_13C[30]; + int32_t field_8BC; + int32_t field_8C0; + int32_t field_8C4; + int32_t field_8C8; + int32_t field_8CC; + int32_t field_8D0; + int32_t field_8D4; + int32_t field_8D8; + int32_t field_8DC; + int32_t field_8E0; + int32_t field_8E4; + int32_t field_8E8; + int32_t field_8EC; + int32_t field_8F0; + int32_t field_8F4; + int32_t field_8F8; + int32_t field_8FC; + int64_t field_900; + int64_t field_908; + int64_t field_910; + int64_t field_918; + int64_t field_920; + int64_t field_928; + int64_t field_930; + float_t osage_phys_step; + bool field_93C; + //vector_struc_373 field_940; + bool field_958; + bool field_959; + bool field_95A; +}; + +typedef union item_sub_data { + struct { + int32_t zujo; + int32_t kami; + int32_t hitai; + int32_t me; + int32_t megane; + int32_t mimi; + int32_t kuchi; + int32_t maki; + int32_t kubi; + int32_t inner; + int32_t outer; + int32_t joha_mae; + int32_t joha_ushiro; + int32_t hada; + int32_t kata; + int32_t u_ude; + int32_t l_ude; + int32_t te; + int32_t belt; + int32_t cosi; + int32_t pants; + int32_t asi; + int32_t sune; + int32_t kutsu; + int32_t head; + }; + int32_t data[25]; +} item_sub_data; + +typedef struct rob_chara_data { + int8_t chara_id; + chara_index chara_index; + int32_t module_index; + rob_chara_data_bone_data* bone_data; + rob_chara_data_item_equip* item_equip; + chara_init_data* chara_init_data; + rob_chara_pv_data pv_data; +} rob_chara_data; + +typedef struct skeleton_rotation_offset { + bool x; + bool y; + bool z; + vec3 rotation; +} skeleton_rotation_offset; + +extern rob_chara_data rob_chara_data_array[]; + +extern chara_init_data* chara_init_data_get(chara_index chara_index); + +extern void motion_set_load_motion(uint32_t set, string* motion_name, motion_database* mot_db); +extern void motion_set_unload(uint32_t set); + +extern void rob_chara_data_init(rob_chara_data* rob_chr_data); +extern void rob_chara_data_calc(rob_chara_data* rob_chr_data); +extern void rob_chara_data_draw(rob_chara_data* rob_chr_data, render_context* rctx); +extern mat4* rob_chara_data_get_bone_data_mat(rob_chara_data* chara, size_t index); +extern float_t rob_chara_data_get_frame(rob_chara_data* rob_chr_data); +extern float_t rob_chara_data_get_frame_count(rob_chara_data* rob_chr_data); +extern void rob_chara_data_load_motion(rob_chara_data* rob_chr_data, int32_t motion_id, + int32_t index, bone_database* bone_data, motion_database* mot_db); +extern void rob_chara_data_reload_items(rob_chara_data* rob_chr_data, + item_sub_data* sub_data, bone_database* bone_data); +extern void rob_chara_data_reset(rob_chara_data* a1, rob_chara_pv_data* pv_data, + bone_database* bone_data, motion_database* mot_db); +extern void rob_chara_data_set(rob_chara_data* rob_chr_data, int8_t chara_id, + chara_index chara_index, uint32_t module_index, rob_chara_pv_data* pv_data); +extern void rob_chara_data_set_frame(rob_chara_data* rob_chr_data, float_t frame); +extern void rob_chara_data_free(rob_chara_data* rob_chr_data); + +extern void rob_chara_data_array_init(); +extern rob_chara_data* rob_chara_data_array_get(int32_t chara_id); +extern void rob_chara_data_array_free(); + +extern void rob_chara_pv_data_init(rob_chara_pv_data* pv_data); + +extern bool rob_chara_pv_data_array_check_chara_id(int32_t chara_id); + +extern void motion_storage_init(); +extern void motion_storage_append_mot_set(uint32_t set_id); +extern void motion_storage_insert_motion_set(mot_set* set, uint32_t set_id); +extern mot_set* motion_storage_get_motion_set(uint32_t set_id); +extern void motion_storage_delete_motion_set(uint32_t set_id); +extern mot_data* motion_storage_get_mot_data(uint32_t motion_id, motion_database* mot_db); +extern void motion_storage_free(); \ No newline at end of file diff --git a/src/CRE/shader.c b/src/CRE/shader.c index b66fda37..08bf8288 100644 --- a/src/CRE/shader.c +++ b/src/CRE/shader.c @@ -4,8 +4,8 @@ */ #include "shader.h" +#include "../KKdLib/io/path.h" #include "../KKdLib/hash.h" -#include "../KKdLib/io_path.h" #include "../KKdLib/str_utils.h" #include "gl_state.h" #include @@ -25,8 +25,6 @@ static bool shader_parse_define(char* data, int32_t num_uniform, const int32_t* vp_unival_max, const int32_t* fp_unival_max, int32_t* uniform_value, char** temp, size_t* temp_size); static char* shader_parse_include(char* data, farc* f); -static void shader_update_buffer(GLint ubo, - GLintptr offset, GLsizeiptr size, size_t data); static void shader_update_data(shader_set_data* set); vector(program_binary) @@ -72,7 +70,7 @@ int32_t shader_bind(shader* shader, uint32_t sub_index) { } gl_state_use_program(sub_shader->program[unival]); - glUniform1iv(shader_MAX_PROGRAM_LOCAL_PARAMETERS * 2, 16, uniform_val); + glUniform1iv(SHADER_MAX_PROGRAM_LOCAL_PARAMETERS * 2, 16, uniform_val); return 0; } @@ -88,6 +86,20 @@ inline void shader_draw_elements(shader_set_data* set, glDrawElements(mode, count, type, indices); } +inline void shader_draw_range_elements(shader_set_data* set, + GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) { + shader_update_data(set); + glDrawRangeElements(mode, start, end, count, type, indices); +} + +int32_t shader_get_index_by_name(shader_set_data* set, char* name) { + shader* shaders = set->shaders; + for (size_t i = 0; i < set->size; i++) + if (!str_utils_compare((char*)shaders[i].name, name)) + return (int32_t)shaders[i].index; + return -1; +} + void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load_cache, char* name, const shader_table** shaders_table, const size_t size, const shader_bind_func* bind_func_table, const size_t bind_func_table_size) { @@ -95,10 +107,10 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load return; bool shader_cache_changed = false; - farc* shader_cache_farc = 0; + farc shader_cache_farc; wchar_t temp_buf[MAX_PATH]; if (!ignore_cache && SUCCEEDED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA, 0, 0, temp_buf))) { - shader_cache_farc = farc_init(); + farc_init(&shader_cache_farc); wcscat_s(temp_buf, sizeof(temp_buf) / sizeof(wchar_t), L"\\CLOUD"); CreateDirectoryW(temp_buf, 0); @@ -108,8 +120,10 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load swprintf_s(buf, sizeof(buf) / sizeof(wchar_t), L"%ls.farc", temp_buf); if (path_wcheck_file_exists(buf) && !not_load_cache) - farc_wread(shader_cache_farc, buf, true, false); + farc_wread(&shader_cache_farc, buf, true, false); } + else + memset(&shader_cache_farc, 0, sizeof(farc)); GLsizei buffer_size = 0x20000; void* binary = force_malloc(buffer_size); @@ -176,8 +190,8 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load continue; } - uint64_t vert_file_name_cache = hash_fnv1a64(vert_file_buf, utf8_length(vert_file_buf)); - uint64_t frag_file_name_cache = hash_fnv1a64(frag_file_buf, utf8_length(frag_file_buf)); + uint64_t vert_file_name_cache = hash_fnv1a64m(vert_file_buf, utf8_length(vert_file_buf)); + uint64_t frag_file_name_cache = hash_fnv1a64m(frag_file_buf, utf8_length(frag_file_buf)); for (int32_t i = 0; i < 64; i += 8) if (((vert_file_name_cache >> i) & 0xFF) == 0) vert_file_name_cache |= 0xFFULL << i; @@ -188,7 +202,7 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load char shader_cache_file_name[MAX_PATH]; strcpy_s(shader_cache_file_name, sizeof(shader_cache_file_name), sub_table->vp); - if (strcmp(sub_table->vp, sub_table->fp)) { + if (str_utils_compare((char*)sub_table->vp, (char*)sub_table->fp)) { strcat_s(shader_cache_file_name, sizeof(shader_cache_file_name), "."); strcat_s(shader_cache_file_name, sizeof(shader_cache_file_name), sub_table->fp); } @@ -196,16 +210,16 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load vert_data = shader_parse_include(vert_data, f); frag_data = shader_parse_include(frag_data, f); - uint64_t vert_data_hash = hash_fnv1a64(vert_data, utf8_length(vert_data)); - uint64_t frag_data_hash = hash_fnv1a64(frag_data, utf8_length(frag_data)); + uint64_t vert_data_hash = hash_fnv1a64m(vert_data, utf8_length(vert_data)); + uint64_t frag_data_hash = hash_fnv1a64m(frag_data, utf8_length(frag_data)); - farc_file* shader_cache_file = farc_read_file(shader_cache_farc, shader_cache_file_name); + farc_file* shader_cache_file = farc_read_file(&shader_cache_farc, shader_cache_file_name); program_binary* bin = 0; if (!ignore_cache) { if (!shader_cache_file || !shader_cache_file->data) /*printf("data error: %s %s\n", vert_file_buf, frag_file_buf)*/; else if (vert_data_hash != ((uint64_t*)shader_cache_file->data)[0] - && frag_data_hash != ((uint64_t*)shader_cache_file->data)[1]) + || frag_data_hash != ((uint64_t*)shader_cache_file->data)[1]) /*printf("hash error: %s %s\n", vert_file_buf, frag_file_buf)*/; else bin = (program_binary*)&((uint64_t*)shader_cache_file->data)[2]; @@ -343,10 +357,7 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load if (!ignore_cache) { if (!shader_cache_file) { - farc_file temp; - memset(&temp, 0, sizeof(farc_file)); - vector_farc_file_push_back(&shader_cache_farc->files, &temp); - shader_cache_file = &shader_cache_farc->files.end[-1]; + shader_cache_file = vector_farc_file_reserve_back(&shader_cache_farc.files); string_init(&shader_cache_file->name, shader_cache_file_name); } else @@ -374,14 +385,14 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load bin_data += j->length; free((void*)j->binary); } - vector_program_binary_clear(&program_data_binary); + vector_program_binary_clear(&program_data_binary, 0); } free(vert_data); free(frag_data); } - vector_uint32_t_clear(&vec_vert); - vector_uint32_t_clear(&vec_frag); + vector_uint32_t_clear(&vec_vert, 0); + vector_uint32_t_clear(&vec_frag, 0); for (size_t j = 0; j < bind_func_table_size; j++) if (shader->index == bind_func_table[j].index) { @@ -389,18 +400,16 @@ void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load break; } } - vector_uint32_t_free(&vec_vert); - vector_uint32_t_free(&vec_frag); - vector_program_binary_free(&program_data_binary); + vector_uint32_t_free(&vec_vert, 0); + vector_uint32_t_free(&vec_frag, 0); + vector_program_binary_free(&program_data_binary, 0); free(binary); free(temp_vert); free(temp_frag); - if (shader_cache_farc) { - if (shader_cache_changed) - farc_wwrite(shader_cache_farc, temp_buf, FARC_COMPRESS_FArC, false); - farc_dispose(shader_cache_farc); - } + if (shader_cache_changed) + farc_wwrite(&shader_cache_farc, temp_buf, FARC_COMPRESS_FArC, false); + farc_free(&shader_cache_farc); memset(&set->data, 0, sizeof(set->data)); glGenBuffers(1, &set->data.state_ubo); @@ -471,7 +480,7 @@ void shader_free(shader_set_data* set) { } void shader_set(shader_set_data* set, uint32_t index) { - if (set && index && set->shaders) { + if (set && index && set->shaders && index != -1) { shader_env_frag_set(set, 0x18, (float_t)uniform_value[U_TEXTURE_BLEND], 0.0, 0.0, 0.0); shader* shader = &set->shaders[index]; @@ -496,13 +505,30 @@ inline void shader_unbind() { gl_state_bind_uniform_buffer_base(3, 0); } +inline void shader_buffer_get_ptr(shader_set_data* set, + size_t index, vec4* data) { + if (!set || index >= SHADER_MAX_PROGRAM_BUFFER_PARAMETERS || !data) + return; + + memcpy(data, &set->data.buffer.buffer[index], sizeof(vec4)); +} + +inline void shader_buffer_get_ptr_array(shader_set_data* set, + size_t index, size_t count, vec4* data) { + if (!set || index >= SHADER_MAX_PROGRAM_BUFFER_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_BUFFER_PARAMETERS || !data) + return; + + memcpy(data, &set->data.buffer.buffer[index], sizeof(vec4) * count); +} + inline void shader_local_frag_get(shader_set_data* set, size_t index, float_t* x, float_t* y, float_t* z, float_t* w) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !x || !y || !z || !w) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !x || !y || !z || !w) return; GLfloat temp[4]; - glGetUniformfv(gl_state_get_program(), (GLint)(index + shader_MAX_PROGRAM_LOCAL_PARAMETERS), temp); + glGetUniformfv(gl_state_get_program(), (GLint)(index + SHADER_MAX_PROGRAM_LOCAL_PARAMETERS), temp); *x = temp[0]; *y = temp[1]; *z = temp[2]; @@ -511,11 +537,11 @@ inline void shader_local_frag_get(shader_set_data* set, inline void shader_local_frag_get_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; GLfloat temp[4]; - glGetUniformfv(gl_state_get_program(), (GLint)(index + shader_MAX_PROGRAM_LOCAL_PARAMETERS), temp); + glGetUniformfv(gl_state_get_program(), (GLint)(index + SHADER_MAX_PROGRAM_LOCAL_PARAMETERS), temp); data->x = temp[0]; data->y = temp[1]; data->z = temp[2]; @@ -524,7 +550,7 @@ inline void shader_local_frag_get_ptr(shader_set_data* set, inline void shader_local_vert_get(shader_set_data* set, size_t index, float_t* x, float_t* y, float_t* z, float_t* w) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !x || !y || !z || !w) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !x || !y || !z || !w) return; GLfloat temp[4]; @@ -537,7 +563,7 @@ inline void shader_local_vert_get(shader_set_data* set, inline void shader_local_vert_get_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; GLfloat temp[4]; @@ -550,7 +576,7 @@ inline void shader_local_vert_get_ptr(shader_set_data* set, inline void shader_env_frag_get(shader_set_data* set, size_t index, float_t* x, float_t* y, float_t* z, float_t* w) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !x || !y || !z || !w) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !x || !y || !z || !w) return; vec4 data = set->data.env.frag[index]; @@ -562,7 +588,7 @@ inline void shader_env_frag_get(shader_set_data* set, inline void shader_env_frag_get_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; *data = set->data.env.frag[index]; @@ -570,7 +596,8 @@ inline void shader_env_frag_get_ptr(shader_set_data* set, inline void shader_env_frag_get_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; memcpy(data, &set->data.env.frag[index], sizeof(vec4) * count); @@ -578,7 +605,7 @@ inline void shader_env_frag_get_ptr_array(shader_set_data* set, inline void shader_env_vert_get(shader_set_data* set, size_t index, float_t* x, float_t* y, float_t* z, float_t* w) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !x || !y || !z || !w) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !x || !y || !z || !w) return; vec4 data = set->data.env.vert[index]; @@ -590,7 +617,7 @@ inline void shader_env_vert_get(shader_set_data* set, inline void shader_env_vert_get_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; *data = set->data.env.vert[index]; @@ -598,7 +625,8 @@ inline void shader_env_vert_get_ptr(shader_set_data* set, inline void shader_env_vert_get_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; memcpy(data, &set->data.env.vert[index], sizeof(vec4) * count); @@ -606,7 +634,7 @@ inline void shader_env_vert_get_ptr_array(shader_set_data* set, inline void shader_state_clip_get_plane(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_CLIP_PLANES || !data) + if (!set || index >= SHADER_MAX_CLIP_PLANES || !data) return; *data = set->data.state.clip[index].plane; @@ -638,7 +666,7 @@ inline void shader_state_fog_get_params(shader_set_data* set, inline void shader_state_light_get_ambient(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -646,7 +674,7 @@ inline void shader_state_light_get_ambient(shader_set_data* set, inline void shader_state_light_get_diffuse(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -654,7 +682,7 @@ inline void shader_state_light_get_diffuse(shader_set_data* set, inline void shader_state_light_get_specular(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -662,7 +690,7 @@ inline void shader_state_light_get_specular(shader_set_data* set, inline void shader_state_light_get_position(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -670,7 +698,7 @@ inline void shader_state_light_get_position(shader_set_data* set, inline void shader_state_light_get_attenuation(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -678,7 +706,7 @@ inline void shader_state_light_get_attenuation(shader_set_data* set, inline void shader_state_light_get_spot_direction(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -686,7 +714,7 @@ inline void shader_state_light_get_spot_direction(shader_set_data* set, inline void shader_state_light_get_half(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; *data = set->data.state.light[index].ambient; @@ -710,26 +738,32 @@ inline void shader_state_lightmodel_get_scene_color(shader_set_data* set, inline void shader_state_lightprod_get_ambient(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - *data = set->data.state.lightprod[back ? 1 : 0][index].specular; + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + *data = lightprod[index].ambient; } inline void shader_state_lightprod_get_diffuse(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - *data = set->data.state.lightprod[back ? 1 : 0][index].specular; + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + *data = lightprod[index].diffuse; } inline void shader_state_lightprod_get_specular(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - *data = set->data.state.lightprod[back ? 1 : 0][index].specular; + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + *data = lightprod[index].specular; } inline void shader_state_material_get_ambient(shader_set_data* set, @@ -774,7 +808,7 @@ inline void shader_state_material_get_shininess(shader_set_data* set, inline void shader_state_matrix_get_modelview(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_VERTEX_UNITS || !data) + if (!set || index >= SHADER_MAX_VERTEX_UNITS || !data) return; *data = set->data.state_matrix.modelview[index].mat; @@ -798,7 +832,7 @@ inline void shader_state_matrix_get_mvp(shader_set_data* set, inline void shader_state_matrix_get_texture(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_TEXTURE_COORDS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_COORDS || !data) return; *data = set->data.state_matrix.texture[index].mat; @@ -806,7 +840,7 @@ inline void shader_state_matrix_get_texture(shader_set_data* set, inline void shader_state_matrix_get_palette(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_PALETTE_MATRICES || !data) + if (!set || index >= SHADER_MAX_PALETTE_MATRICES || !data) return; *data = set->data.state_matrix.palette[index].mat; @@ -814,7 +848,7 @@ inline void shader_state_matrix_get_palette(shader_set_data* set, inline void shader_state_matrix_get_program(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_PROGRAM_MATRICES || !data) + if (!set || index >= SHADER_MAX_PROGRAM_MATRICES || !data) return; *data = set->data.state_matrix.program[index].mat; @@ -838,7 +872,7 @@ inline void shader_state_point_get_attenuation(shader_set_data* set, inline void shader_state_texgen_get_eye_s(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].eye_s; @@ -846,7 +880,7 @@ inline void shader_state_texgen_get_eye_s(shader_set_data* set, inline void shader_state_texgen_get_eye_t(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].eye_t; @@ -854,7 +888,7 @@ inline void shader_state_texgen_get_eye_t(shader_set_data* set, inline void shader_state_texgen_get_eye_r(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].eye_r; @@ -862,7 +896,7 @@ inline void shader_state_texgen_get_eye_r(shader_set_data* set, inline void shader_state_texgen_get_eye_q(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].eye_q; @@ -870,7 +904,7 @@ inline void shader_state_texgen_get_eye_q(shader_set_data* set, inline void shader_state_texgen_get_object_s(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].object_s; @@ -878,7 +912,7 @@ inline void shader_state_texgen_get_object_s(shader_set_data* set, inline void shader_state_texgen_get_object_t(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].object_t; @@ -886,7 +920,7 @@ inline void shader_state_texgen_get_object_t(shader_set_data* set, inline void shader_state_texgen_get_object_r(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].object_r; @@ -894,7 +928,7 @@ inline void shader_state_texgen_get_object_r(shader_set_data* set, inline void shader_state_texgen_get_object_q(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texgen[index].object_q; @@ -902,41 +936,66 @@ inline void shader_state_texgen_get_object_q(shader_set_data* set, inline void shader_state_texenv_get_color(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; *data = set->data.state.texenv[index].color; } -inline void shader_local_frag_set(shader_set_data* set, - size_t index, float_t x, float_t y, float_t z, float_t w) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS) +inline void shader_buffer_set_ptr(shader_set_data* set, + size_t index, vec4* data) { + if (!set || index >= SHADER_MAX_PROGRAM_BUFFER_PARAMETERS || !data) return; - glUniform4f((GLint)(index + shader_MAX_PROGRAM_LOCAL_PARAMETERS), x, y, z, w); + if (!memcmp(&set->data.buffer.buffer[index], data, sizeof(vec4))) + return; + + set->data.buffer.buffer[index] = *data; + set->data.buffer_update_data = true; +} + +inline void shader_buffer_set_ptr_array(shader_set_data* set, + size_t index, size_t count, vec4* data) { + if (!set || index >= SHADER_MAX_PROGRAM_BUFFER_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_BUFFER_PARAMETERS || !data) + return; + + if (!memcmp(&set->data.buffer.buffer[index], data, sizeof(vec4) * count)) + return; + + memcpy(&set->data.buffer.buffer[index], data, sizeof(vec4) * count); + set->data.buffer_update_data = true; +} + +inline void shader_local_frag_set(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS) + return; + + glUniform4f((GLint)(index + SHADER_MAX_PROGRAM_LOCAL_PARAMETERS), x, y, z, w); } inline void shader_local_frag_set_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; - glUniform4f((GLint)(index + shader_MAX_PROGRAM_LOCAL_PARAMETERS), data->x, data->y, data->z, data->w); + glUniform4f((GLint)(index + SHADER_MAX_PROGRAM_LOCAL_PARAMETERS), data->x, data->y, data->z, data->w); } inline void shader_local_frag_set_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS - || index + count > shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; - glUniform4fv((GLint)(index + shader_MAX_PROGRAM_LOCAL_PARAMETERS), + glUniform4fv((GLint)(index + SHADER_MAX_PROGRAM_LOCAL_PARAMETERS), (GLsizei)count, (const GLfloat*)data); } inline void shader_local_vert_set(shader_set_data* set, size_t index, float_t x, float_t y, float_t z, float_t w) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS) return; glUniform4f((GLint)index, x, y, z, w); @@ -944,7 +1003,7 @@ inline void shader_local_vert_set(shader_set_data* set, inline void shader_local_vert_set_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; glUniform4f((GLint)index, data->x, data->y, data->z, data->w); @@ -952,8 +1011,8 @@ inline void shader_local_vert_set_ptr(shader_set_data* set, inline void shader_local_vert_set_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_LOCAL_PARAMETERS - || index + count > shader_MAX_PROGRAM_LOCAL_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_LOCAL_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_LOCAL_PARAMETERS || !data) return; glUniform4fv((GLint)index, (GLsizei)count, (const GLfloat*)data); @@ -961,7 +1020,7 @@ inline void shader_local_vert_set_ptr_array(shader_set_data* set, inline void shader_env_frag_set(shader_set_data* set, size_t index, float_t x, float_t y, float_t z, float_t w) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS) return; vec4 data; @@ -973,40 +1032,37 @@ inline void shader_env_frag_set(shader_set_data* set, return; set->data.env.frag[index] = data; - set->data.env_update.frag[index] = true; - set->data.env_frag_update_data = true; + set->data.env_update_data = true; } inline void shader_env_frag_set_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; if (!memcmp(&set->data.env.frag[index], data, sizeof(vec4))) return; set->data.env.frag[index] = *data; - set->data.env_update.frag[index] = true; - set->data.env_frag_update_data = true; + set->data.env_update_data = true; } inline void shader_env_frag_set_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS - || index + count > shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; if (!memcmp(&set->data.env.frag[index], data, sizeof(vec4) * count)) return; memcpy(&set->data.env.frag[index], data, sizeof(vec4) * count); - memset(&set->data.env_update.frag[index], true, sizeof(bool) * count); - set->data.env_frag_update_data = true; + set->data.env_update_data = true; } inline void shader_env_vert_set(shader_set_data* set, size_t index, float_t x, float_t y, float_t z, float_t w) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS) return; vec4 data; @@ -1018,51 +1074,73 @@ inline void shader_env_vert_set(shader_set_data* set, return; set->data.env.vert[index] = data; - set->data.env_update.frag[index] = true; - set->data.env_vert_update_data = true; + set->data.env_update_data = true; } inline void shader_env_vert_set_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; if (!memcmp(&set->data.env.vert[index], data, sizeof(vec4))) return; set->data.env.vert[index] = *data; - set->data.env_update.vert[index] = true; - set->data.env_vert_update_data = true; + set->data.env_update_data = true; } inline void shader_env_vert_set_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data) { - if (!set || index >= shader_MAX_PROGRAM_ENV_PARAMETERS - || index + count > shader_MAX_PROGRAM_ENV_PARAMETERS || !data) + if (!set || index >= SHADER_MAX_PROGRAM_ENV_PARAMETERS + || index + count > SHADER_MAX_PROGRAM_ENV_PARAMETERS || !data) return; if (!memcmp(&set->data.env.vert[index], data, sizeof(vec4) * count)) return; memcpy(&set->data.env.vert[index], data, sizeof(vec4) * count); - memset(&set->data.env_update.vert[index], true, sizeof(bool) * count); - set->data.env_vert_update_data = true; + set->data.env_update_data = true; } inline void shader_state_clip_set_plane(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_CLIP_PLANES) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.clip[index].plane, &data, sizeof(vec4))) + return; + + set->data.state.clip[index].plane = data; + set->data.state_update_data = true; +} + +inline void shader_state_clip_set_plane_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_CLIP_PLANES || !data) + if (!set || index >= SHADER_MAX_CLIP_PLANES || !data) return; if (!memcmp(&set->data.state.clip[index].plane, data, sizeof(vec4))) return; set->data.state.clip[index].plane = *data; - set->data.state_update.clip[index].plane = true; set->data.state_update_data = true; } inline void shader_state_depth_set_range(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.depth.range, &data, sizeof(vec4))) + return; + + set->data.state.depth.range = data; + set->data.state_update_data = true; +} + +inline void shader_state_depth_set_range_ptr(shader_set_data* set, vec4* data) { if (!set || !data) return; @@ -1071,11 +1149,23 @@ inline void shader_state_depth_set_range(shader_set_data* set, return; set->data.state.depth.range = *data; - set->data.state_update.depth.range = true; set->data.state_update_data = true; } inline void shader_state_fog_set_color(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.fog.color, &data, sizeof(vec4))) + return; + + set->data.state.fog.color = data; + set->data.state_update_data = true; +} + +inline void shader_state_fog_set_color_ptr(shader_set_data* set, vec4* data) { if (!set || !data) return; @@ -1084,11 +1174,23 @@ inline void shader_state_fog_set_color(shader_set_data* set, return; set->data.state.fog.color = *data; - set->data.state_update.fog.color = true; set->data.state_update_data = true; } inline void shader_state_fog_set_params(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.fog.params, &data, sizeof(vec4))) + return; + + set->data.state.fog.params = data; + set->data.state_update_data = true; +} + +inline void shader_state_fog_set_params_ptr(shader_set_data* set, vec4* data) { if (!set || !data) return; @@ -1097,102 +1199,252 @@ inline void shader_state_fog_set_params(shader_set_data* set, return; set->data.state.fog.params = *data; - set->data.state_update.fog.params = true; set->data.state_update_data = true; } inline void shader_state_light_set_ambient(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].ambient, &data, sizeof(vec4))) + return; + + set->data.state.light[index].ambient = data; + set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[0].ambient, lightprod_front); + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[1].ambient, lightprod_back); + shader_state_lightprod_set_ambient_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_ambient_ptr(set, true, index, &lightprod_back); +} + +inline void shader_state_light_set_ambient_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].ambient, data, sizeof(vec4))) return; set->data.state.light[index].ambient = *data; - set->data.state_update.light[index].ambient = true; set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[0].ambient, lightprod_front); + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[1].ambient, lightprod_back); + shader_state_lightprod_set_ambient_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_ambient_ptr(set, true, index, &lightprod_back); } inline void shader_state_light_set_diffuse(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].diffuse, &data, sizeof(vec4))) + return; + + set->data.state.light[index].diffuse = data; + set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[0].diffuse, lightprod_front); + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[1].diffuse, lightprod_back); + shader_state_lightprod_set_diffuse_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_diffuse_ptr(set, true, index, &lightprod_back); +} + +inline void shader_state_light_set_diffuse_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].diffuse, data, sizeof(vec4))) return; set->data.state.light[index].diffuse = *data; - set->data.state_update.light[index].diffuse = true; set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[0].diffuse, lightprod_front); + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[1].diffuse, lightprod_back); + shader_state_lightprod_set_diffuse_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_diffuse_ptr(set, true, index, &lightprod_back); } inline void shader_state_light_set_specular(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].specular, &data, sizeof(vec4))) + return; + + set->data.state.light[index].specular = data; + set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[0].specular, lightprod_front); + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[1].specular, lightprod_back); + shader_state_lightprod_set_specular_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_specular_ptr(set, true, index, &lightprod_back); +} + +inline void shader_state_light_set_specular_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].specular, data, sizeof(vec4))) return; set->data.state.light[index].specular = *data; - set->data.state_update.light[index].specular = true; set->data.state_update_data = true; + + vec4 lightprod_front; + vec4 lightprod_back; + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[0].specular, lightprod_front); + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[1].specular, lightprod_back); + shader_state_lightprod_set_specular_ptr(set, false, index, &lightprod_front); + shader_state_lightprod_set_specular_ptr(set, true, index, &lightprod_back); } inline void shader_state_light_set_position(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].position, &data, sizeof(vec4))) + return; + + set->data.state.light[index].position = data; + set->data.state_update_data = true; +} + +inline void shader_state_light_set_position_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].position, data, sizeof(vec4))) return; set->data.state.light[index].position = *data; - set->data.state_update.light[index].position = true; set->data.state_update_data = true; } inline void shader_state_light_set_attenuation(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].attenuation, &data, sizeof(vec4))) + return; + + set->data.state.light[index].attenuation = data; + set->data.state_update_data = true; +} + +inline void shader_state_light_set_attenuation_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].attenuation, data, sizeof(vec4))) return; set->data.state.light[index].attenuation = *data; - set->data.state_update.light[index].attenuation = true; set->data.state_update_data = true; } inline void shader_state_light_set_spot_direction(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].spot_direction, &data, sizeof(vec4))) + return; + + set->data.state.light[index].spot_direction = data; + set->data.state_update_data = true; +} + +inline void shader_state_light_set_spot_direction_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].spot_direction, data, sizeof(vec4))) return; set->data.state.light[index].spot_direction = *data; - set->data.state_update.light[index].spot_direction = true; set->data.state_update_data = true; } inline void shader_state_light_set_half(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.light[index].half, &data, sizeof(vec4))) + return; + + set->data.state.light[index].half = data; + set->data.state_update_data = true; +} + +inline void shader_state_light_set_half_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; if (!memcmp(&set->data.state.light[index].half, data, sizeof(vec4))) return; set->data.state.light[index].half = *data; - set->data.state_update.light[index].half = true; set->data.state_update_data = true; } inline void shader_state_lightmodel_set_ambient(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.lightmodel[back ? 1 : 0].ambient, &data, sizeof(vec4))) + return; + + set->data.state.lightmodel[back ? 1 : 0].ambient = data; + set->data.state_update_data = true; +} + +inline void shader_state_lightmodel_set_ambient_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1201,11 +1453,23 @@ inline void shader_state_lightmodel_set_ambient(shader_set_data* set, return; set->data.state.lightmodel[back ? 1 : 0].ambient = *data; - set->data.state_update.lightmodel[back ? 1 : 0].ambient = true; set->data.state_update_data = true; } inline void shader_state_lightmodel_set_scene_color(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.lightmodel[back ? 1 : 0].scene_color, &data, sizeof(vec4))) + return; + + set->data.state.lightmodel[back ? 1 : 0].scene_color = data; + set->data.state_update_data = true; +} + +inline void shader_state_lightmodel_set_scene_color_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1214,50 +1478,123 @@ inline void shader_state_lightmodel_set_scene_color(shader_set_data* set, return; set->data.state.lightmodel[back ? 1 : 0].scene_color = *data; - set->data.state_update.lightmodel[back ? 1 : 0].scene_color = true; set->data.state_update_data = true; } inline void shader_state_lightprod_set_ambient(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + vec4 data = { x, y, z, w }; + if (!memcmp(&lightprod[index].ambient, &data, sizeof(vec4))) + return; + + lightprod[index].ambient = data; + set->data.state_update_data = true; +} + +inline void shader_state_lightprod_set_ambient_ptr(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - if (!memcmp(&set->data.state.lightprod[back ? 1 : 0][index].ambient, data, sizeof(vec4))) + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + if (!memcmp(&lightprod[index].ambient, data, sizeof(vec4))) return; - set->data.state.lightprod[back ? 1 : 0][index].ambient = *data; - set->data.state_update.lightprod[back ? 1 : 0][index].ambient = true; + lightprod[index].ambient = *data; set->data.state_update_data = true; } inline void shader_state_lightprod_set_diffuse(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + vec4 data = { x, y, z, w }; + if (!memcmp(&lightprod[index].diffuse, &data, sizeof(vec4))) + return; + + lightprod[index].diffuse = data; + set->data.state_update_data = true; +} + +inline void shader_state_lightprod_set_diffuse_ptr(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - if (!memcmp(&set->data.state.lightprod[back ? 1 : 0][index].specular, data, sizeof(vec4))) + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + if (!memcmp(&lightprod[index].diffuse, data, sizeof(vec4))) return; - set->data.state.lightprod[back ? 1 : 0][index].specular = *data; - set->data.state_update.lightprod[back ? 1 : 0][index].specular = true; + lightprod[index].diffuse = *data; set->data.state_update_data = true; } inline void shader_state_lightprod_set_specular(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_LIGHTS) + return; + + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + vec4 data = { x, y, z, w }; + if (!memcmp(&lightprod[index].specular, &data, sizeof(vec4))) + return; + + lightprod[index].specular = data; + set->data.state_update_data = true; +} + +inline void shader_state_lightprod_set_specular_ptr(shader_set_data* set, bool back, size_t index, vec4* data) { - if (!set || index >= shader_MAX_LIGHTS || !data) + if (!set || index >= SHADER_MAX_LIGHTS || !data) return; - if (!memcmp(&set->data.state.lightprod[back ? 1 : 0][index].specular, data, sizeof(vec4))) + shader_state_lightprod* lightprod = back + ? set->data.state.lightprod_back : set->data.state.lightprod_front; + + if (!memcmp(&lightprod[index].specular, data, sizeof(vec4))) return; - set->data.state.lightprod[back ? 1 : 0][index].specular = *data; - set->data.state_update.lightprod[back ? 1 : 0][index].specular = true; + lightprod[index].specular = *data; set->data.state_update_data = true; } inline void shader_state_material_set_ambient(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.material[back ? 1 : 0].ambient, &data, sizeof(vec4))) + return; + + set->data.state.material[back ? 1 : 0].ambient = data; + set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[back ? 1 : 0].ambient, lightprod); + shader_state_lightprod_set_ambient_ptr(set, back, index, &lightprod); + } +} + +inline void shader_state_material_set_ambient_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1266,11 +1603,37 @@ inline void shader_state_material_set_ambient(shader_set_data* set, return; set->data.state.material[back ? 1 : 0].ambient = *data; - set->data.state_update.material[back ? 1 : 0].ambient = true; set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].ambient, + set->data.state.material[back ? 1 : 0].ambient, lightprod); + shader_state_lightprod_set_ambient_ptr(set, back, index, &lightprod); + } } inline void shader_state_material_set_diffuse(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.material[back ? 1 : 0].diffuse, &data, sizeof(vec4))) + return; + + set->data.state.material[back ? 1 : 0].diffuse = data; + set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[back ? 1 : 0].diffuse, lightprod); + shader_state_lightprod_set_diffuse_ptr(set, back, index, &lightprod); + } +} + +inline void shader_state_material_set_diffuse_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1279,11 +1642,37 @@ inline void shader_state_material_set_diffuse(shader_set_data* set, return; set->data.state. material[back ? 1 : 0].diffuse = *data; - set->data.state_update. material[back ? 1 : 0].diffuse = true; set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].diffuse, + set->data.state.material[back ? 1 : 0].diffuse, lightprod); + shader_state_lightprod_set_diffuse_ptr(set, back, index, &lightprod); + } } inline void shader_state_material_set_specular(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.material[back ? 1 : 0].specular, &data, sizeof(vec4))) + return; + + set->data.state.material[back ? 1 : 0].specular = data; + set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[back ? 1 : 0].specular, lightprod); + shader_state_lightprod_set_specular_ptr(set, back, index, &lightprod); + } +} + +inline void shader_state_material_set_specular_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1292,11 +1681,30 @@ inline void shader_state_material_set_specular(shader_set_data* set, return; set->data.state.material[back ? 1 : 0].specular = *data; - set->data.state_update.material[back ? 1 : 0].specular = true; set->data.state_update_data = true; + + vec4 lightprod; + for (int32_t index = 0; index < SHADER_MAX_LIGHTS; index++) { + vec4_mult(set->data.state.light[index].specular, + set->data.state.material[back ? 1 : 0].specular, lightprod); + shader_state_lightprod_set_specular_ptr(set, back, index, &lightprod); + } } inline void shader_state_material_set_emission(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.material[back ? 1 : 0].emission, &data, sizeof(vec4))) + return; + + set->data.state.material[back ? 1 : 0].emission = data; + set->data.state_update_data = true; +} + +inline void shader_state_material_set_emission_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1305,11 +1713,23 @@ inline void shader_state_material_set_emission(shader_set_data* set, return; set->data.state.material[back ? 1 : 0].emission = *data; - set->data.state_update.material[back ? 1 : 0].emission = true; set->data.state_update_data = true; } inline void shader_state_material_set_shininess(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.material[back ? 1 : 0].shininess, &data, sizeof(vec4))) + return; + + set->data.state.material[back ? 1 : 0].shininess = data; + set->data.state_update_data = true; +} + +inline void shader_state_material_set_shininess_ptr(shader_set_data* set, bool back, vec4* data) { if (!set || !data) return; @@ -1318,17 +1738,15 @@ inline void shader_state_material_set_shininess(shader_set_data* set, return; set->data.state.material[back ? 1 : 0].shininess = *data; - set->data.state_update.material[back ? 1 : 0].shininess = true; set->data.state_update_data = true; } inline void shader_state_matrix_set_modelview(shader_set_data* set, size_t index, mat4* data, bool mult) { - if (!set || index >= shader_MAX_VERTEX_UNITS || !data) + if (!set || index >= SHADER_MAX_VERTEX_UNITS || !data) return; if (memcmp(&set->data.state_matrix.modelview[index].mat, data, sizeof(mat4))) { - mat4 mat; mat4 mat_inv; mat4 mat_trans; @@ -1342,11 +1760,10 @@ inline void shader_state_matrix_set_modelview(shader_set_data* set, set->data.state_matrix.modelview[index].inv = mat_inv; set->data.state_matrix.modelview[index].trans = mat_trans; set->data.state_matrix.modelview[index].invtrans = mat_invtrans; - set->data.state_matrix_update.modelview[index] = true; set->data.state_matrix_update_data = true; } - if (mult) { + if (mult && index == 0) { mat4 mat; mat4_mult(&set->data.state_matrix.modelview[0].mat, &set->data.state_matrix.projection.mat, &mat); @@ -1360,7 +1777,6 @@ inline void shader_state_matrix_set_projection(shader_set_data* set, return; if (memcmp(&set->data.state_matrix.projection.mat, data, sizeof(mat4))) { - mat4 mat; mat4 mat_inv; mat4 mat_trans; @@ -1374,7 +1790,6 @@ inline void shader_state_matrix_set_projection(shader_set_data* set, set->data.state_matrix.projection.inv = mat_inv; set->data.state_matrix.projection.trans = mat_trans; set->data.state_matrix.projection.invtrans = mat_invtrans; - set->data.state_matrix_update.projection = true; set->data.state_matrix_update_data = true; } @@ -1407,10 +1822,16 @@ inline void shader_state_matrix_set_mvp(shader_set_data* set, set->data.state_matrix.mvp.inv = mat_inv; set->data.state_matrix.mvp.trans = mat_trans; set->data.state_matrix.mvp.invtrans = mat_invtrans; - set->data.state_matrix_update.mvp = true; set->data.state_matrix_update_data = true; } +inline void shader_state_matrix_set_modelview_separate(shader_set_data* set, + size_t index, mat4* model, mat4* view, bool mult) { + mat4 mv; + mat4_mult(model, view, &mv); + shader_state_matrix_set_modelview(set, index, &mv, true); +} + inline void shader_state_matrix_set_mvp_separate(shader_set_data* set, mat4* model, mat4* view, mat4* projection) { mat4 mv; @@ -1421,7 +1842,7 @@ inline void shader_state_matrix_set_mvp_separate(shader_set_data* set, inline void shader_state_matrix_set_texture(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_TEXTURE_COORDS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_COORDS || !data) return; if (!memcmp(&set->data.state_matrix.texture[index].mat, data, sizeof(mat4))) @@ -1440,13 +1861,12 @@ inline void shader_state_matrix_set_texture(shader_set_data* set, set->data.state_matrix.texture[index].inv = mat_inv; set->data.state_matrix.texture[index].trans = mat_trans; set->data.state_matrix.texture[index].invtrans = mat_invtrans; - set->data.state_matrix_update.texture[index] = true; set->data.state_matrix_update_data = true; } inline void shader_state_matrix_set_palette(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_PALETTE_MATRICES || !data) + if (!set || index >= SHADER_MAX_PALETTE_MATRICES || !data) return; if (!memcmp(&set->data.state_matrix.palette[index].mat, data, sizeof(mat4))) @@ -1465,13 +1885,12 @@ inline void shader_state_matrix_set_palette(shader_set_data* set, set->data.state_matrix.palette[index].inv = mat_inv; set->data.state_matrix.palette[index].trans = mat_trans; set->data.state_matrix.palette[index].invtrans = mat_invtrans; - set->data.state_matrix_update.palette[index] = true; set->data.state_matrix_update_data = true; } inline void shader_state_matrix_set_program(shader_set_data* set, size_t index, mat4* data) { - if (!set || index >= shader_MAX_PROGRAM_MATRICES || !data) + if (!set || index >= SHADER_MAX_PROGRAM_MATRICES || !data) return; if (!memcmp(&set->data.state_matrix.program[index].mat, data, sizeof(mat4))) @@ -1490,11 +1909,23 @@ inline void shader_state_matrix_set_program(shader_set_data* set, set->data.state_matrix.program[index].inv = mat_inv; set->data.state_matrix.program[index].trans = mat_trans; set->data.state_matrix.program[index].invtrans = mat_invtrans; - set->data.state_matrix_update.program[index] = true; set->data.state_matrix_update_data = true; } inline void shader_state_point_set_size(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.point.size, &data, sizeof(vec4))) + return; + + set->data.state.point.size = data; + set->data.state_update_data = true; +} + +inline void shader_state_point_set_size_ptr(shader_set_data* set, vec4* data) { if (!set || !data) return; @@ -1503,11 +1934,23 @@ inline void shader_state_point_set_size(shader_set_data* set, return; set->data.state.point.size = *data; - set->data.state_update.point.size = true; set->data.state_update_data = true; } inline void shader_state_point_set_attenuation(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w) { + if (!set) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.point.attenuation, &data, sizeof(vec4))) + return; + + set->data.state.point.attenuation = data; + set->data.state_update_data = true; +} + +inline void shader_state_point_set_attenuation_ptr(shader_set_data* set, vec4* data) { if (!set || !data) return; @@ -1516,124 +1959,231 @@ inline void shader_state_point_set_attenuation(shader_set_data* set, return; set->data.state.point.attenuation = *data; - set->data.state_update.point.attenuation = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_eye_s(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].eye_s, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].eye_s = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_eye_s_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].eye_s, data, sizeof(vec4))) return; set->data.state.texgen[index].eye_s = *data; - set->data.state_update.texgen[index].eye_s = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_eye_t(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].eye_t, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].eye_t = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_eye_t_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].eye_t, data, sizeof(vec4))) return; set->data.state.texgen[index].eye_t = *data; - set->data.state_update.texgen[index].eye_t = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_eye_r(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].eye_r, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].eye_r = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_eye_r_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].eye_r, data, sizeof(vec4))) return; set->data.state.texgen[index].eye_r = *data; - set->data.state_update.texgen[index].eye_r = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_eye_q(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].eye_q, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].eye_q = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_eye_q_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].eye_q, data, sizeof(vec4))) return; set->data.state.texgen[index].eye_q = *data; - set->data.state_update.texgen[index].eye_q = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_object_s(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].object_s, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].object_s = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_object_s_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].object_s, data, sizeof(vec4))) return; set->data.state.texgen[index].object_s = *data; - set->data.state_update.texgen[index].object_s = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_object_t(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].object_t, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].object_t = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_object_t_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].object_t, data, sizeof(vec4))) return; set->data.state.texgen[index].object_t = *data; - set->data.state_update.texgen[index].object_t = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_object_r(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].object_r, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].object_r = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_object_r_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].object_r, data, sizeof(vec4))) return; set->data.state.texgen[index].object_r = *data; - set->data.state_update.texgen[index].object_r = true; set->data.state_update_data = true; } inline void shader_state_texgen_set_object_q(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texgen[index].object_q, &data, sizeof(vec4))) + return; + + set->data.state.texgen[index].object_q = data; + set->data.state_update_data = true; +} + +inline void shader_state_texgen_set_object_q_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texgen[index].object_q, data, sizeof(vec4))) return; set->data.state.texgen[index].object_q = *data; - set->data.state_update.texgen[index].object_q = true; set->data.state_update_data = true; } inline void shader_state_texenv_set_color(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w) { + if (!set || index >= SHADER_MAX_TEXTURE_UNITS) + return; + + vec4 data = { x, y, z, w }; + if (!memcmp(&set->data.state.texenv[index].color, &data, sizeof(vec4))) + return; + + set->data.state.texenv[index].color = data; + set->data.state_update_data = true; +} + +inline void shader_state_texenv_set_color_ptr(shader_set_data* set, size_t index, vec4* data) { - if (!set || index >= shader_MAX_TEXTURE_UNITS || !data) + if (!set || index >= SHADER_MAX_TEXTURE_UNITS || !data) return; if (!memcmp(&set->data.state.texenv[index].color, data, sizeof(vec4))) return; set->data.state.texenv[index].color = *data; - set->data.state_update.texenv[index].color = true; set->data.state_update_data = true; } @@ -1977,159 +2527,55 @@ static char* shader_parse_include(char* data, farc* f) { return temp_data; } -inline static void shader_update_buffer(GLint ubo, - GLintptr offset, GLsizeiptr size, size_t data) { - if (!offset || !size || !data) - return; - - gl_state_bind_uniform_buffer(ubo); - glBufferSubData(GL_UNIFORM_BUFFER, offset, size, (const void*)data); -} - -#define shader_update_state_data_buffer(d) \ -if (data->state_update.d) { \ - *(vec4*)(buf_data + offsetof(shader_state, d)) = data->state.d; \ - data->state_update.d = false; \ -} - -#define shader_update_state_matrix_data_buffer(d) \ -if (data->state_matrix_update.d) { \ - *(shader_state_matrix_data*)(buf_data \ - + offsetof(shader_state_matrix, d)) = data->state_matrix.d; \ - data->state_matrix_update.d = false; \ -} - -#define shader_update_env_vert_data_buffer(d) \ -if (data->env_update.vert[d]) { \ - *(vec4*)(buf_data + sizeof(vec4) * d + sizeof(vec4) \ - * shader_MAX_PROGRAM_ENV_PARAMETERS) = data->env.vert[d]; \ - data->env_update.vert[d] = false; \ -} - -#define shader_update_env_frag_data_buffer(d) \ -if (data->env_update.frag[d]) { \ - *(vec4*)(buf_data + sizeof(vec4) * d) = data->env.frag[d]; \ - data->env_update.frag[d] = false; \ -} - -#define shader_update_buffer_data_buffer(d) \ -if (data->buffer_update.buffer[d]) { \ - *(vec4*)(buf_data + sizeof(vec4) * d) = data->buffer.buffer[d]; \ - data->buffer_update.buffer[d] = false; \ -} - static void shader_update_data(shader_set_data* set) { if (!set) return; - size_t buf_data; shader_data* data = &set->data; - if (data->state_update_data) { + if (!data->state_update_data && !data->state_matrix_update_data + && !data->env_update_data && !data->buffer_update_data) + return; + + GLuint current_uniform_index = gl_state.uniform_buffer_index; + GLuint current_uniform = gl_state.uniform_buffer_binding[current_uniform_index]; + + bool reset = false; + if (data->state_update_data && data->state_ubo) { gl_state_bind_uniform_buffer(data->state_ubo); - buf_data = (size_t)glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - for (int32_t i = 0; i < 2; i++) { - shader_update_state_data_buffer(material[i].ambient); - shader_update_state_data_buffer(material[i].diffuse); - shader_update_state_data_buffer(material[i].specular); - shader_update_state_data_buffer(material[i].emission); - shader_update_state_data_buffer(material[i].shininess); - } - - for (int32_t i = 0; i < shader_MAX_LIGHTS; i++) { - shader_update_state_data_buffer(light[i].ambient); - shader_update_state_data_buffer(light[i].diffuse); - shader_update_state_data_buffer(light[i].specular); - shader_update_state_data_buffer(light[i].position); - shader_update_state_data_buffer(light[i].attenuation); - shader_update_state_data_buffer(light[i].spot_direction); - shader_update_state_data_buffer(light[i].half); - } - - for (int32_t i = 0; i < 2; i++) { - shader_update_state_data_buffer(lightmodel[i].ambient); - shader_update_state_data_buffer(lightmodel[i].scene_color); - } - - for (int32_t i = 0; i < 2; i++) - for (int32_t j = 0; j < shader_MAX_LIGHTS; j++) { - shader_update_state_data_buffer(lightprod[i][j].ambient); - shader_update_state_data_buffer(lightprod[i][j].diffuse); - shader_update_state_data_buffer(lightprod[i][j].specular); - } - - for (int32_t i = 0; i < shader_MAX_TEXTURE_UNITS; i++) { - for (int32_t j = 0; j < 4; j++) - shader_update_state_data_buffer(texgen[i].eye[j]); - - for (int32_t j = 0; j < 4; j++) - shader_update_state_data_buffer(texgen[i].object[j]); - } - - for (int32_t i = 0; i < shader_MAX_TEXTURE_UNITS; i++) - shader_update_state_data_buffer(texenv[i].color); - - shader_update_state_data_buffer(fog.color); - shader_update_state_data_buffer(fog.params); - - for (int32_t i = 0; i < shader_MAX_CLIP_PLANES; i++) - shader_update_state_data_buffer(clip[i].plane); - - shader_update_state_data_buffer(point.size); - shader_update_state_data_buffer(point.attenuation); - shader_update_state_data_buffer(depth.range); - glUnmapBuffer(GL_UNIFORM_BUFFER); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data->state), &data->state); data->state_update_data = false; + reset = true; } - if (data->state_matrix_update_data) { + if (data->state_matrix_update_data && data->state_matrix_ubo) { gl_state_bind_uniform_buffer(data->state_matrix_ubo); - buf_data = (size_t)glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - for (int32_t i = 0; i < shader_MAX_VERTEX_UNITS; i++) - shader_update_state_matrix_data_buffer(modelview[i]); - - shader_update_state_matrix_data_buffer(projection); - shader_update_state_matrix_data_buffer(mvp); - - for (int32_t i = 0; i < shader_MAX_TEXTURE_COORDS; i++) - shader_update_state_matrix_data_buffer(texture[i]); - - for (int32_t i = 0; i < shader_MAX_PALETTE_MATRICES; i++) - shader_update_state_matrix_data_buffer(palette[i]); - - for (int32_t i = 0; i < shader_MAX_PROGRAM_MATRICES; i++) - shader_update_state_matrix_data_buffer(program[i]); - glUnmapBuffer(GL_UNIFORM_BUFFER); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data->state_matrix), &data->state_matrix); data->state_matrix_update_data = false; + reset = true; } - if (data->env_frag_update_data || data->env_vert_update_data) { + if (data->env_update_data && data->env_ubo) { gl_state_bind_uniform_buffer(data->env_ubo); - buf_data = (size_t)glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - if (data->env_frag_update_data) { - for (int32_t i = 0; i < shader_MAX_PROGRAM_ENV_PARAMETERS; i++) - shader_update_env_frag_data_buffer(i); - data->env_frag_update_data = false; - } - - if (data->env_vert_update_data) { - for (int32_t i = 0; i < shader_MAX_PROGRAM_ENV_PARAMETERS; i++) - shader_update_env_vert_data_buffer(i); - data->env_vert_update_data = false; - } - glUnmapBuffer(GL_UNIFORM_BUFFER); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data->env), &data->env); + data->env_update_data = false; + reset = true; } - if (data->buffer_update_data) { + if (data->buffer_update_data && data->buffer_ubo) { gl_state_bind_uniform_buffer(data->buffer_ubo); - buf_data = (size_t)glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY); - for (int32_t i = 0; i < shader_MAX_PROGRAM_PARAMETER_BUFFER_SIZE / sizeof(vec4); i++) - shader_update_buffer_data_buffer(i); - glUnmapBuffer(GL_UNIFORM_BUFFER); + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(data->buffer.buffer), &data->buffer.buffer); data->buffer_update_data = false; + reset = true; } - gl_state_bind_uniform_buffer(0); + + if (reset) + gl_state_bind_uniform_buffer_base(current_uniform_index, current_uniform); } + #undef shader_update_state_data_buffer +#undef shader_update_state_data_buffer_array +#undef shader_update_state_data_buffer_array_of_array +#undef shader_update_state_data_buffer_array_array #undef shader_update_state_matrix_data_buffer #undef shader_update_env_vert_data_buffer #undef shader_update_env_frag_data_buffer diff --git a/src/CRE/shader.h b/src/CRE/shader.h index ace49455..7c500269 100644 --- a/src/CRE/shader.h +++ b/src/CRE/shader.h @@ -13,18 +13,19 @@ #include "../KKdLib/vector.h" #include "static_var.h" -#define shader_MAX_CLIP_PLANES 8 -#define shader_MAX_LIGHTS 8 -#define shader_MAX_PALETTE_MATRICES 32 -#define shader_MAX_PROGRAM_ENV_PARAMETERS 256 -#define shader_MAX_PROGRAM_LOCAL_PARAMETERS 256 -#define shader_MAX_PROGRAM_PARAMETER_BUFFER_SIZE 16384 -#define shader_MAX_PROGRAM_MATRICES 8 -#define shader_MAX_TEXTURE_COORDS 8 -#define shader_MAX_TEXTURE_IMAGE_UNITS 32 -#define shader_MAX_TEXTURE_UNITS 4 -#define shader_MAX_UNIFORM_BLOCK_SIZE 65536 -#define shader_MAX_VERTEX_UNITS 4 +#define SHADER_MAX_CLIP_PLANES 8 +#define SHADER_MAX_LIGHTS 8 +#define SHADER_MAX_PALETTE_MATRICES 32 +#define SHADER_MAX_PROGRAM_ENV_PARAMETERS 256 +#define SHADER_MAX_PROGRAM_LOCAL_PARAMETERS 256 +#define SHADER_MAX_PROGRAM_BUFFER_PARAMETERS 1024 +#define SHADER_MAX_PROGRAM_PARAMETER_BUFFER_SIZE 16384 +#define SHADER_MAX_PROGRAM_MATRICES 8 +#define SHADER_MAX_TEXTURE_COORDS 8 +#define SHADER_MAX_TEXTURE_IMAGE_UNITS 32 +#define SHADER_MAX_TEXTURE_UNITS 4 +#define SHADER_MAX_UNIFORM_BLOCK_SIZE 65536 +#define SHADER_MAX_VERTEX_UNITS 4 typedef struct shader_state_clip { vec4 plane; @@ -76,12 +77,12 @@ typedef struct shader_state_matrix_data { } shader_state_matrix_data; typedef struct shader_state_matrix { - shader_state_matrix_data modelview[shader_MAX_VERTEX_UNITS]; + shader_state_matrix_data modelview[SHADER_MAX_VERTEX_UNITS]; shader_state_matrix_data projection; shader_state_matrix_data mvp; - shader_state_matrix_data texture[shader_MAX_TEXTURE_COORDS]; - shader_state_matrix_data palette[shader_MAX_PALETTE_MATRICES]; - shader_state_matrix_data program[shader_MAX_PROGRAM_MATRICES]; + shader_state_matrix_data texture[SHADER_MAX_TEXTURE_COORDS]; + shader_state_matrix_data palette[SHADER_MAX_PALETTE_MATRICES]; + shader_state_matrix_data program[SHADER_MAX_PROGRAM_MATRICES]; } shader_state_matrix; typedef struct shader_state_point { @@ -116,144 +117,36 @@ typedef struct shader_state_texenv { } shader_state_texenv; typedef struct shader_buffer { - vec4 buffer[shader_MAX_PROGRAM_PARAMETER_BUFFER_SIZE / sizeof(vec4)]; + vec4 buffer[SHADER_MAX_PROGRAM_PARAMETER_BUFFER_SIZE / sizeof(vec4)]; } shader_buffer; typedef struct shader_env { - vec4 frag[shader_MAX_PROGRAM_ENV_PARAMETERS]; - vec4 vert[shader_MAX_PROGRAM_ENV_PARAMETERS]; + vec4 frag[SHADER_MAX_PROGRAM_ENV_PARAMETERS]; + vec4 vert[SHADER_MAX_PROGRAM_ENV_PARAMETERS]; } shader_env; -typedef struct shader_state_clip_update { - bool plane; -} shader_state_clip_update; - -typedef struct shader_state_depth_update { - bool range; -} shader_state_depth_update; - -typedef struct shader_state_fog_update { - bool color; - bool params; -} shader_state_fog_update; - -typedef struct shader_state_light_update { - bool ambient; - bool diffuse; - bool specular; - bool position; - bool attenuation; - bool spot_direction; - bool half; -} shader_state_light_update; - -typedef struct shader_state_lightmodel_update { - bool ambient; - bool scene_color; -} shader_state_lightmodel_update; - -typedef struct shader_state_lightprod_update { - bool ambient; - bool diffuse; - bool specular; -} shader_state_lightprod_update; - -typedef struct shader_state_material_update { - bool ambient; - bool diffuse; - bool specular; - bool emission; - bool shininess; -} shader_state_material_update; - -typedef struct shader_state_matrix_update { - bool modelview[shader_MAX_VERTEX_UNITS]; - bool projection; - bool mvp; - bool texture[shader_MAX_TEXTURE_COORDS]; - bool palette[shader_MAX_PALETTE_MATRICES]; - bool program[shader_MAX_PROGRAM_MATRICES]; -} shader_state_matrix_update; - -typedef struct shader_state_point_update { - bool size; - bool attenuation; -} shader_state_point_update; - -typedef struct shader_state_texgen_update { - union { - bool eye[4]; - struct { - bool eye_s; - bool eye_t; - bool eye_r; - bool eye_q; - }; - }; - - union { - bool object[4]; - struct { - bool object_s; - bool object_t; - bool object_r; - bool object_q; - }; - }; -} shader_state_texgen_update; - -typedef struct shader_state_texenv_update { - bool color; -} shader_state_texenv_update; - -typedef struct shader_buffer_update { - bool buffer[shader_MAX_PROGRAM_PARAMETER_BUFFER_SIZE / sizeof(vec4)]; -} shader_buffer_update; - -typedef struct shader_env_update { - bool frag[shader_MAX_PROGRAM_ENV_PARAMETERS]; - bool vert[shader_MAX_PROGRAM_ENV_PARAMETERS]; -} shader_env_update; - typedef struct shader_state { shader_state_material material[2]; - shader_state_light light[shader_MAX_LIGHTS]; + shader_state_light light[SHADER_MAX_LIGHTS]; shader_state_lightmodel lightmodel[2]; - shader_state_lightprod lightprod[2][shader_MAX_LIGHTS]; - shader_state_texgen texgen[shader_MAX_TEXTURE_UNITS]; - shader_state_texenv texenv[shader_MAX_TEXTURE_UNITS]; + shader_state_lightprod lightprod_front[SHADER_MAX_LIGHTS]; + shader_state_lightprod lightprod_back[SHADER_MAX_LIGHTS]; + shader_state_texgen texgen[SHADER_MAX_TEXTURE_UNITS]; + shader_state_texenv texenv[SHADER_MAX_TEXTURE_UNITS]; shader_state_fog fog; - shader_state_clip clip[shader_MAX_CLIP_PLANES]; + shader_state_clip clip[SHADER_MAX_CLIP_PLANES]; shader_state_point point; shader_state_depth depth; } shader_state; -typedef struct shader_state_update { - shader_state_material_update material[2]; - shader_state_light_update light[shader_MAX_LIGHTS]; - shader_state_lightmodel_update lightmodel[2]; - shader_state_lightprod_update lightprod[2][shader_MAX_LIGHTS]; - shader_state_texgen_update texgen[shader_MAX_TEXTURE_UNITS]; - shader_state_texenv_update texenv[shader_MAX_TEXTURE_UNITS]; - shader_state_fog_update fog; - shader_state_clip_update clip[shader_MAX_CLIP_PLANES]; - shader_state_point_update point; - shader_state_depth_update depth; -} shader_state_update; - typedef struct shader_data { shader_state state; shader_state_matrix state_matrix; shader_env env; shader_buffer buffer; - shader_state_update state_update; - shader_state_matrix_update state_matrix_update; - shader_env_update env_update; - shader_buffer_update buffer_update; bool state_update_data; bool state_matrix_update_data; - bool env_frag_update_data; - bool env_vert_update_data; + bool env_update_data; bool buffer_update_data; GLuint state_ubo; GLuint state_matrix_ubo; @@ -317,6 +210,9 @@ extern void shader_draw_arrays(shader_set_data* set, GLenum mode, GLint first, GLsizei count); extern void shader_draw_elements(shader_set_data* set, GLenum mode, GLsizei count, GLenum type, const void* indices); +extern void shader_draw_range_elements(shader_set_data* set, + GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices); +extern int32_t shader_get_index_by_name(shader_set_data* set, char* name); extern void shader_load(shader_set_data* set, farc* f, bool ignore_cache, bool not_load_cache, char* name, const shader_table** shaders_table, const size_t size, const shader_bind_func* bind_func_table, const size_t bind_func_table_size); @@ -324,6 +220,10 @@ extern void shader_free(shader_set_data* set); extern void shader_set(shader_set_data* set, uint32_t index); extern void shader_unbind(); +extern void shader_buffer_get_ptr(shader_set_data* set, + size_t index, vec4* data); +extern void shader_buffer_get_ptr_array(shader_set_data* set, + size_t index, size_t count, vec4* data); extern void shader_local_frag_get(shader_set_data* set, size_t index, float_t* x, float_t* y, float_t* z, float_t* w); extern void shader_local_frag_get_ptr(shader_set_data* set, @@ -421,6 +321,10 @@ extern void shader_state_texgen_get_object_q(shader_set_data* set, extern void shader_state_texenv_get_color(shader_set_data* set, size_t index, vec4* data); +extern void shader_buffer_set_ptr(shader_set_data* set, + size_t index, vec4* data); +extern void shader_buffer_set_ptr_array(shader_set_data* set, + size_t index, size_t count, vec4* data); extern void shader_local_frag_set(shader_set_data* set, size_t index, float_t x, float_t y, float_t z, float_t w); extern void shader_local_frag_set_ptr(shader_set_data* set, @@ -446,46 +350,88 @@ extern void shader_env_vert_set_ptr(shader_set_data* set, extern void shader_env_vert_set_ptr_array(shader_set_data* set, size_t index, size_t count, vec4* data); extern void shader_state_clip_set_plane(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_clip_set_plane_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_depth_set_range(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w); +extern void shader_state_depth_set_range_ptr(shader_set_data* set, vec4* data); extern void shader_state_fog_set_color(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w); +extern void shader_state_fog_set_color_ptr(shader_set_data* set, vec4* data); extern void shader_state_fog_set_params(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w); +extern void shader_state_fog_set_params_ptr(shader_set_data* set, vec4* data); extern void shader_state_light_set_ambient(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_ambient_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_diffuse(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_diffuse_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_specular(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_specular_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_position(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_position_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_attenuation(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_attenuation_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_spot_direction(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_spot_direction_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_light_set_half(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_light_set_half_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_lightmodel_set_ambient(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_lightmodel_set_ambient_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_lightmodel_set_scene_color(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_lightmodel_set_scene_color_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_lightprod_set_ambient(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_lightprod_set_ambient_ptr(shader_set_data* set, bool back, size_t index, vec4* data); extern void shader_state_lightprod_set_diffuse(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_lightprod_set_diffuse_ptr(shader_set_data* set, bool back, size_t index, vec4* data); extern void shader_state_lightprod_set_specular(shader_set_data* set, + bool back, size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_lightprod_set_specular_ptr(shader_set_data* set, bool back, size_t index, vec4* data); extern void shader_state_material_set_ambient(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_material_set_ambient_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_material_set_diffuse(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_material_set_diffuse_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_material_set_specular(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_material_set_specular_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_material_set_emission(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_material_set_emission_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_material_set_shininess(shader_set_data* set, + bool back, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_material_set_shininess_ptr(shader_set_data* set, bool back, vec4* data); extern void shader_state_matrix_set_modelview(shader_set_data* set, size_t index, mat4* data, bool mult); @@ -493,6 +439,8 @@ extern void shader_state_matrix_set_projection(shader_set_data* set, mat4* data, bool mult); extern void shader_state_matrix_set_mvp(shader_set_data* set, mat4* data); +extern void shader_state_matrix_set_modelview_separate(shader_set_data* set, + size_t index, mat4* model, mat4* view, bool mult); extern void shader_state_matrix_set_mvp_separate(shader_set_data* set, mat4* model, mat4* view, mat4* projection); extern void shader_state_matrix_set_texture(shader_set_data* set, @@ -502,24 +450,46 @@ extern void shader_state_matrix_set_palette(shader_set_data* set, extern void shader_state_matrix_set_program(shader_set_data* set, size_t index, mat4* data); extern void shader_state_point_set_size(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w); +extern void shader_state_point_set_size_ptr(shader_set_data* set, vec4* data); extern void shader_state_point_set_attenuation(shader_set_data* set, + float_t x, float_t y, float_t z, float_t w); +extern void shader_state_point_set_attenuation_ptr(shader_set_data* set, vec4* data); extern void shader_state_texgen_set_eye_s(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_eye_s_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_eye_t(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_eye_t_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_eye_r(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_eye_r_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_eye_q(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_eye_q_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_object_s(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_object_s_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_object_t(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_object_t_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_object_r(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_object_r_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texgen_set_object_q(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texgen_set_object_q_ptr(shader_set_data* set, size_t index, vec4* data); extern void shader_state_texenv_set_color(shader_set_data* set, + size_t index, float_t x, float_t y, float_t z, float_t w); +extern void shader_state_texenv_set_color_ptr(shader_set_data* set, size_t index, vec4* data); \ No newline at end of file diff --git a/src/CRE/shader_aft.h b/src/CRE/shader_aft.h deleted file mode 100644 index 90fd8afc..00000000 --- a/src/CRE/shader_aft.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "shader.h" - -typedef enum shader_aft_enum { - SHADER_AFT_FFP = 0x00, - SHADER_AFT_BLINN = 0x01, - SHADER_AFT_ITEM = 0x02, - SHADER_AFT_STAGE = 0x03, - SHADER_AFT_SKIN = 0x04, - SHADER_AFT_SSS_SKIN = 0x05, - SHADER_AFT_SSS_FILT = 0x06, - SHADER_AFT_HAIR = 0x07, - SHADER_AFT_CLOTH = 0x08, - SHADER_AFT_TIGHTS = 0x09, - SHADER_AFT_SKY = 0x0A, - SHADER_AFT_EYEBALL = 0x0B, - SHADER_AFT_EYELENS = 0x0C, - SHADER_AFT_GLASEYE = 0x0D, - SHADER_AFT_MEMBRAN = 0x0E, - SHADER_AFT_SHDMAP = 0x0F, - SHADER_AFT_ESM = 0x10, - SHADER_AFT_ESMGAUSS = 0x11, - SHADER_AFT_ESMFILT = 0x12, - SHADER_AFT_LITPROJ = 0x13, - SHADER_AFT_SIMPLE = 0x14, - SHADER_AFT_SIL = 0x15, - SHADER_AFT_LAMBERT = 0x16, - SHADER_AFT_CONSTANT = 0x17, - SHADER_AFT_PEEL = 0x18, - SHADER_AFT_TONEMAP = 0x19, - SHADER_AFT_REDUCE = 0x1A, - SHADER_AFT_MAGNIFY = 0x1B, - SHADER_AFT_MLAA = 0x1C, - SHADER_AFT_CONTOUR = 0x1D, - SHADER_AFT_EXPOSURE = 0x1E, - SHADER_AFT_GAUSS = 0x1F, - SHADER_AFT_SUN = 0x20, - SHADER_AFT_FADE = 0x21, - SHADER_AFT_WATER01 = 0x22, - SHADER_AFT_WATER02 = 0x23, - SHADER_AFT_WATRING = 0x24, - SHADER_AFT_W_PTCL = 0x25, - SHADER_AFT_SNOW_PT = 0x26, - SHADER_AFT_LEAF_PT = 0x27, - SHADER_AFT_STAR = 0x28, - SHADER_AFT_SNORING = 0x29, - SHADER_AFT_SN_FOOT = 0x2A, - SHADER_AFT_SN_TSL = 0x2B, - SHADER_AFT_SN_NRM = 0x2C, - SHADER_AFT_FLOOR = 0x2D, - SHADER_AFT_PUDDLE = 0x2E, - SHADER_AFT_S_REFL = 0x2F, - SHADER_AFT_S_REFR = 0x30, - SHADER_AFT_RIPEMIT = 0x31, - SHADER_AFT_RAIN = 0x32, - SHADER_AFT_VOLLIT = 0x33, - SHADER_AFT_FENCE = 0x34, - SHADER_AFT_RIPPLE = 0x35, - SHADER_AFT_FOGPTCL = 0x36, - SHADER_AFT_PARTICL = 0x37, - SHADER_AFT_GLITTER_PT = 0x38, - SHADER_AFT_SHOWVEC = 0x39, - SHADER_AFT_FONT = 0x3A, - SHADER_AFT_MOVIE = 0x3B, - SHADER_AFT_IMGFILT = 0x3C, - SHADER_AFT_SPRITE = 0x3D, - SHADER_AFT_END = 0x3E, -} shader_aft_enum; - -extern void shader_aft_load(shader_set_data* set, farc* f, bool ignore_cache); diff --git a/src/CRE/shader_aft.c b/src/CRE/shader_ft.c similarity index 69% rename from src/CRE/shader_aft.c rename to src/CRE/shader_ft.c index 626e979d..edd71c74 100644 --- a/src/CRE/shader_aft.c +++ b/src/CRE/shader_ft.c @@ -3,95 +3,95 @@ GitHub/GitLab: korenkonder */ -#include "shader_aft.h" +#include "shader_ft.h" #include "gl_state.h" -typedef enum shader_aft_sub_enum { - SHADER_AFT_SUB_SHADER_FFP = 0x00, - SHADER_AFT_SUB_BLINN_VERT = 0x01, - SHADER_AFT_SUB_BLINN_FRAG = 0x02, - SHADER_AFT_SUB_ITEM_BLINN = 0x03, - SHADER_AFT_SUB_STAGE_BLINN = 0x04, - SHADER_AFT_SUB_SKIN_DEFAULT = 0x05, - SHADER_AFT_SUB_SSS_SKIN = 0x06, - SHADER_AFT_SUB_SSS_FILTER = 0x07, - SHADER_AFT_SUB_HAIR_DEFAULT = 0x08, - SHADER_AFT_SUB_HAIR_ANISO = 0x09, - SHADER_AFT_SUB_HAIR_NPR1 = 0x0A, - SHADER_AFT_SUB_CLOTH_DEFAULT = 0x0B, - SHADER_AFT_SUB_CLOTH_ANISO = 0x0C, - SHADER_AFT_SUB_CLOTH_NPR1 = 0x0D, - SHADER_AFT_SUB_TIGHTS = 0x0E, - SHADER_AFT_SUB_SKY_DEFAULT = 0x0F, - SHADER_AFT_SUB_EYE_BALL = 0x10, - SHADER_AFT_SUB_EYE_LENS = 0x11, - SHADER_AFT_SUB_GLASS_EYE = 0x12, - SHADER_AFT_SUB_MEMBRANE = 0x13, - SHADER_AFT_SUB_SHADOWMAP = 0x14, - SHADER_AFT_SUB_ESM = 0x15, - SHADER_AFT_SUB_ESM_GAUSS = 0x16, - SHADER_AFT_SUB_ESM_FILTER = 0x17, - SHADER_AFT_SUB_LIT_PROJ = 0x18, - SHADER_AFT_SUB_SIMPLE = 0x19, - SHADER_AFT_SUB_SILHOUETTE = 0x1A, - SHADER_AFT_SUB_LAMBERT = 0x1B, - SHADER_AFT_SUB_CONSTANT = 0x1C, - SHADER_AFT_SUB_PEEL = 0x1D, - SHADER_AFT_SUB_TONE_MAP = 0x1E, - SHADER_AFT_SUB_TONE_MAP_NPR1 = 0x1F, - SHADER_AFT_SUB_REDUCE_TEX = 0x20, - SHADER_AFT_SUB_MAGNIFY = 0x21, - SHADER_AFT_SUB_MLAA = 0x22, - SHADER_AFT_SUB_CONTOUR = 0x23, - SHADER_AFT_SUB_EXPOSURE = 0x24, - SHADER_AFT_SUB_PP_GAUSS = 0x25, - SHADER_AFT_SUB_SUN = 0x26, - SHADER_AFT_SUB_FADE = 0x27, - SHADER_AFT_SUB_WATER01 = 0x28, - SHADER_AFT_SUB_WATER02 = 0x29, - SHADER_AFT_SUB_WATER_RING = 0x2A, - SHADER_AFT_SUB_WATER_PARTICLE = 0x2B, - SHADER_AFT_SUB_SNOW_PARTICLE = 0x2C, - SHADER_AFT_SUB_LEAF_PARTICLE = 0x2D, - SHADER_AFT_SUB_STAR = 0x2E, - SHADER_AFT_SUB_SNOW_RING = 0x2F, - SHADER_AFT_SUB_SNOW_FOOTPRINT = 0x30, - SHADER_AFT_SUB_SNOW_TEX_SPACE_LIGHT = 0x31, - SHADER_AFT_SUB_SNOW_CALC_NORMAL = 0x32, - SHADER_AFT_SUB_FLOOR = 0x33, - SHADER_AFT_SUB_PUDDLE = 0x34, - SHADER_AFT_SUB_SIMPLE_REFLECT = 0x35, - SHADER_AFT_SUB_SIMPLE_REFRACT = 0x36, - SHADER_AFT_SUB_RIPPLE_EMIT = 0x37, - SHADER_AFT_SUB_RAIN = 0x38, - SHADER_AFT_SUB_VOLUME_LIGHT = 0x39, - SHADER_AFT_SUB_FENCE_ALPHA = 0x3A, - SHADER_AFT_SUB_RIPPLE = 0x3B, - SHADER_AFT_SUB_FOG_PTCL = 0x3C, - SHADER_AFT_SUB_PARTICLE = 0x3D, - SHADER_AFT_SUB_GLITTER_PARTICLE = 0x3E, - SHADER_AFT_SUB_SHOW_VECTOR = 0x3F, - SHADER_AFT_SUB_FONT = 0x40, - SHADER_AFT_SUB_MOVIE = 0x41, - SHADER_AFT_SUB_IMGFILTER = 0x42, - SHADER_AFT_SUB_SPRITE = 0x43, - SHADER_AFT_SUB_SHADER_END = 0x44, -} shader_aft_sub_enum; +typedef enum shader_ft_sub_enum { + SHADER_FT_SUB_SHADER_FFP = 0x00, + SHADER_FT_SUB_BLINN_VERT = 0x01, + SHADER_FT_SUB_BLINN_FRAG = 0x02, + SHADER_FT_SUB_ITEM_BLINN = 0x03, + SHADER_FT_SUB_STAGE_BLINN = 0x04, + SHADER_FT_SUB_SKIN_DEFAULT = 0x05, + SHADER_FT_SUB_SSS_SKIN = 0x06, + SHADER_FT_SUB_SSS_FILTER = 0x07, + SHADER_FT_SUB_HAIR_DEFAULT = 0x08, + SHADER_FT_SUB_HAIR_ANISO = 0x09, + SHADER_FT_SUB_HAIR_NPR1 = 0x0A, + SHADER_FT_SUB_CLOTH_DEFAULT = 0x0B, + SHADER_FT_SUB_CLOTH_ANISO = 0x0C, + SHADER_FT_SUB_CLOTH_NPR1 = 0x0D, + SHADER_FT_SUB_TIGHTS = 0x0E, + SHADER_FT_SUB_SKY_DEFAULT = 0x0F, + SHADER_FT_SUB_EYE_BALL = 0x10, + SHADER_FT_SUB_EYE_LENS = 0x11, + SHADER_FT_SUB_GLASS_EYE = 0x12, + SHADER_FT_SUB_MEMBRANE = 0x13, + SHADER_FT_SUB_SHADOWMAP = 0x14, + SHADER_FT_SUB_ESM = 0x15, + SHADER_FT_SUB_ESM_GAUSS = 0x16, + SHADER_FT_SUB_ESM_FILTER = 0x17, + SHADER_FT_SUB_LIT_PROJ = 0x18, + SHADER_FT_SUB_SIMPLE = 0x19, + SHADER_FT_SUB_SILHOUETTE = 0x1A, + SHADER_FT_SUB_LAMBERT = 0x1B, + SHADER_FT_SUB_CONSTANT = 0x1C, + SHADER_FT_SUB_PEEL = 0x1D, + SHADER_FT_SUB_TONE_MAP = 0x1E, + SHADER_FT_SUB_TONE_MAP_NPR1 = 0x1F, + SHADER_FT_SUB_REDUCE_TEX = 0x20, + SHADER_FT_SUB_MAGNIFY = 0x21, + SHADER_FT_SUB_MLAA = 0x22, + SHADER_FT_SUB_CONTOUR = 0x23, + SHADER_FT_SUB_EXPOSURE = 0x24, + SHADER_FT_SUB_PP_GAUSS = 0x25, + SHADER_FT_SUB_SUN = 0x26, + SHADER_FT_SUB_FADE = 0x27, + SHADER_FT_SUB_WATER01 = 0x28, + SHADER_FT_SUB_WATER02 = 0x29, + SHADER_FT_SUB_WATER_RING = 0x2A, + SHADER_FT_SUB_WATER_PARTICLE = 0x2B, + SHADER_FT_SUB_SNOW_PARTICLE = 0x2C, + SHADER_FT_SUB_LEAF_PARTICLE = 0x2D, + SHADER_FT_SUB_STAR = 0x2E, + SHADER_FT_SUB_SNOW_RING = 0x2F, + SHADER_FT_SUB_SNOW_FOOTPRINT = 0x30, + SHADER_FT_SUB_SNOW_TEX_SPACE_LIGHT = 0x31, + SHADER_FT_SUB_SNOW_CALC_NORMAL = 0x32, + SHADER_FT_SUB_FLOOR = 0x33, + SHADER_FT_SUB_PUDDLE = 0x34, + SHADER_FT_SUB_SIMPLE_REFLECT = 0x35, + SHADER_FT_SUB_SIMPLE_REFRACT = 0x36, + SHADER_FT_SUB_RIPPLE_EMIT = 0x37, + SHADER_FT_SUB_RAIN = 0x38, + SHADER_FT_SUB_VOLUME_LIGHT = 0x39, + SHADER_FT_SUB_FENCE_ALPHA = 0x3A, + SHADER_FT_SUB_RIPPLE = 0x3B, + SHADER_FT_SUB_FOG_PTCL = 0x3C, + SHADER_FT_SUB_PARTICLE = 0x3D, + SHADER_FT_SUB_GLITTER_PARTICLE = 0x3E, + SHADER_FT_SUB_SHOW_VECTOR = 0x3F, + SHADER_FT_SUB_FONT = 0x40, + SHADER_FT_SUB_MOVIE = 0x41, + SHADER_FT_SUB_IMGFILTER = 0x42, + SHADER_FT_SUB_SPRITE = 0x43, + SHADER_FT_SUB_SHADER_END = 0x44, +} shader_ft_sub_enum; static const int32_t blinn_vert_vpt_unival_max[] = { - 1, 1, 0, 1, 0, 0, 0, 3, 1, 1, 0, + 1, 1, 0, 1, 0, 0, 0, 3, 1, 1, 0, 0, // 11th added }; static const int32_t blinn_vert_fpt_unival_max[] = { - 0, 0, 2, 1, 0, 1, 1, 3, 0, 0, 1, + 0, 0, 2, 1, 0, 1, 1, 3, 0, 0, 1, 1, // 11th added }; static const int32_t blinn_frag_vpt_unival_max[] = { - 1, 1, 0, 1, 0, 0, 0, 3, 1, 1, 0, + 1, 1, 0, 1, 0, 0, 0, 3, 1, 1, 0, 0, // 11th added }; static const int32_t blinn_frag_fpt_unival_max[] = { - 0, 0, 2, 1, 1, 1, 1, 3, 0, 0, 1, + 0, 0, 2, 1, 1, 1, 1, 3, 0, 0, 1, 1, // 11th added }; static const int32_t item_blinn_vpt_unival_max[] = { @@ -103,11 +103,11 @@ static const int32_t item_blinn_fpt_unival_max[] = { }; static const int32_t stage_blinn_vpt_unival_max[] = { - 1, 1, 1, 1, 0, 0, 1, 0, 3, 0, 0, + 1, 1, 1, 1, 0, 0, 1, 0, 3, 0, 0, 0, // 11th added }; static const int32_t stage_blinn_fpt_unival_max[] = { - 0, 0, 0, 0, 2, 1, 1, 1, 3, 1, 1, + 0, 0, 0, 0, 2, 1, 1, 1, 3, 1, 1, 1, // 11th added }; static const int32_t skin_default_vpt_unival_max[] = { @@ -135,27 +135,27 @@ static const int32_t sss_filter_fpt_unival_max[] = { }; static const int32_t hair_default_vpt_unival_max[] = { - 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, 0, // 14th Added }; static const int32_t hair_default_fpt_unival_max[] = { - 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, + 1, 0, 2, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, // 14th Added }; static const int32_t hair_aniso_vpt_unival_max[] = { - 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, 0, // 14th Added }; static const int32_t hair_aniso_fpt_unival_max[] = { - 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, // 14th Added }; static const int32_t hair_npr1_vpt_unival_max[] = { - 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, + 1, 1, 0, 0, 1, 0, 0, 3, 0, 2, 1, 0, 0, 0, 0, // 14th Added }; static const int32_t hair_npr1_fpt_unival_max[] = { - 1, 0, 0, 0, 0, 1, 0, 3, 1, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 3, 1, 0, 0, 0, 0, 0, 1, // 14th Added }; static const int32_t cloth_default_vpt_unival_max[] = { @@ -191,11 +191,11 @@ static const int32_t tights_fpt_unival_max[] = { }; static const int32_t sky_default_vpt_unival_max[] = { - 0, 0, 0, 1, 1, 3, + 0, 0, 0, 1, 1, 3, 0, // 6th added }; static const int32_t sky_default_fpt_unival_max[] = { - 3, 3, 2, 0, 0, 3, + 3, 3, 2, 0, 0, 3, 1, // 6th added }; static const int32_t eye_ball_vpt_unival_max[] = { @@ -271,35 +271,35 @@ static const int32_t lit_proj_fpt_unival_max[] = { }; static const int32_t simple_vpt_unival_max[] = { - 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 0, 0, // 6th added }; static const int32_t simple_fpt_unival_max[] = { - 0, 0, 2, 0, 0, 3, + 0, 0, 2, 0, 0, 3, 1, // 6th added }; static const int32_t silhouette_vpt_unival_max[] = { - 1, 1, 1, 2, 1, 1, 0, + 1, 1, 1, 2, 1, 1, 0, 0, // 7th added }; static const int32_t silhouette_fpt_unival_max[] = { - 0, 0, 1, 0, 0, 0, 1, + 0, 0, 1, 0, 0, 0, 1, 1, // 7th added }; static const int32_t lambert_vpt_unival_max[] = { - 1, 1, 0, 1, 3, 1, 1, 0, + 1, 1, 0, 1, 3, 1, 1, 0, 0, // 8th added }; static const int32_t lambert_fpt_unival_max[] = { - 0, 0, 2, 1, 3, 0, 0, 1, + 0, 0, 2, 1, 3, 0, 0, 1, 1, // 8th added }; static const int32_t constant_vpt_unival_max[] = { - 1, 1, 0, 3, 1, 1, + 1, 1, 0, 3, 1, 1, 0, // 6th added }; static const int32_t constant_fpt_unival_max[] = { - 0, 0, 2, 3, 0, 0, + 0, 0, 2, 3, 0, 0, 1, // 6th added }; static const int32_t peel_vpt_unival_max[] = { @@ -391,11 +391,11 @@ static const int32_t fade_fpt_unival_max[] = { }; static const int32_t water01_vpt_unival_max[] = { - 1, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 1, 0, // 8th added }; static const int32_t water01_fpt_unival_max[] = { - 0, 0, 2, 1, 1, 1, 1, 1, + 0, 0, 2, 1, 1, 1, 1, 1, 1, // 8th added }; static const int32_t water02_vpt_unival_max[] = { @@ -415,11 +415,11 @@ static const int32_t water_ring_fpt_unival_max[] = { }; static const int32_t water_particle_vpt_unival_max[] = { - -1, + 0, // 0th added }; static const int32_t water_particle_fpt_unival_max[] = { - -1, + 0, // 0th added }; static const int32_t snow_particle_vpt_unival_max[] = { @@ -479,11 +479,11 @@ static const int32_t snow_calc_normal_fpt_unival_max[] = { }; static const int32_t floor_vpt_unival_max[] = { - 0, 0, 1, 0, 3, 1, 1, + 0, 0, 1, 0, 3, 1, 1, 0, }; static const int32_t floor_fpt_unival_max[] = { - 2, 1, 1, 1, 3, 0, 0, + 2, 1, 1, 1, 3, 0, 0, 1, // 7th Added }; static const int32_t puddle_vpt_unival_max[] = { @@ -559,11 +559,11 @@ static const int32_t fog_ptcl_fpt_unival_max[] = { }; static const int32_t particle_vpt_unival_max[] = { - -1, + 0, // 0th added }; static const int32_t particle_fpt_unival_max[] = { - -1, + 1, // 0th added }; static const int32_t glitter_particle_vpt_unival_max[] = { @@ -616,14 +616,14 @@ static const int32_t sprite_fpt_unival_max[] = { static const shader_sub_table BLINN_table[] = { { - .sub_index = SHADER_AFT_SUB_BLINN_VERT, + .sub_index = SHADER_FT_SUB_BLINN_VERT, .vp_unival_max = blinn_vert_vpt_unival_max, .fp_unival_max = blinn_vert_fpt_unival_max, .vp = "blinn_per_vert", .fp = "blinn_per_vert", }, { - .sub_index = SHADER_AFT_SUB_BLINN_FRAG, + .sub_index = SHADER_FT_SUB_BLINN_FRAG, .vp_unival_max = blinn_frag_vpt_unival_max, .fp_unival_max = blinn_frag_fpt_unival_max, .vp = "blinn_per_frag", @@ -633,7 +633,7 @@ static const shader_sub_table BLINN_table[] = { static const shader_sub_table ITEM_table[] = { { - .sub_index = SHADER_AFT_SUB_ITEM_BLINN, + .sub_index = SHADER_FT_SUB_ITEM_BLINN, .vp_unival_max = item_blinn_vpt_unival_max, .fp_unival_max = item_blinn_fpt_unival_max, .vp = "item_blinn", @@ -643,7 +643,7 @@ static const shader_sub_table ITEM_table[] = { static const shader_sub_table STAGE_table[] = { { - .sub_index = SHADER_AFT_SUB_STAGE_BLINN, + .sub_index = SHADER_FT_SUB_STAGE_BLINN, .vp_unival_max = stage_blinn_vpt_unival_max, .fp_unival_max = stage_blinn_fpt_unival_max, .vp = "stage_blinn", @@ -653,7 +653,7 @@ static const shader_sub_table STAGE_table[] = { static const shader_sub_table SKIN_table[] = { { - .sub_index = SHADER_AFT_SUB_SKIN_DEFAULT, + .sub_index = SHADER_FT_SUB_SKIN_DEFAULT, .vp_unival_max = skin_default_vpt_unival_max, .fp_unival_max = skin_default_fpt_unival_max, .vp = "skin_default", @@ -663,7 +663,7 @@ static const shader_sub_table SKIN_table[] = { static const shader_sub_table SSS_SKIN_table[] = { { - .sub_index = SHADER_AFT_SUB_SSS_SKIN, + .sub_index = SHADER_FT_SUB_SSS_SKIN, .vp_unival_max = sss_skin_vpt_unival_max, .fp_unival_max = sss_skin_fpt_unival_max, .vp = "sss_skin", @@ -673,7 +673,7 @@ static const shader_sub_table SSS_SKIN_table[] = { static const shader_sub_table SSS_FILT_table[] = { { - .sub_index = SHADER_AFT_SUB_SSS_FILTER, + .sub_index = SHADER_FT_SUB_SSS_FILTER, .vp_unival_max = sss_filter_vpt_unival_max, .fp_unival_max = sss_filter_fpt_unival_max, .vp = "sss_filter", @@ -683,21 +683,21 @@ static const shader_sub_table SSS_FILT_table[] = { static const shader_sub_table HAIR_table[] = { { - .sub_index = SHADER_AFT_SUB_HAIR_DEFAULT, + .sub_index = SHADER_FT_SUB_HAIR_DEFAULT, .vp_unival_max = hair_default_vpt_unival_max, .fp_unival_max = hair_default_fpt_unival_max, .vp = "hair_default", .fp = "hair_default", }, { - .sub_index = SHADER_AFT_SUB_HAIR_ANISO, + .sub_index = SHADER_FT_SUB_HAIR_ANISO, .vp_unival_max = hair_aniso_vpt_unival_max, .fp_unival_max = hair_aniso_fpt_unival_max, .vp = "hair_default", .fp = "hair_aniso", }, { - .sub_index = SHADER_AFT_SUB_HAIR_NPR1, + .sub_index = SHADER_FT_SUB_HAIR_NPR1, .vp_unival_max = hair_npr1_vpt_unival_max, .fp_unival_max = hair_npr1_fpt_unival_max, .vp = "hair_default", @@ -707,21 +707,21 @@ static const shader_sub_table HAIR_table[] = { static const shader_sub_table CLOTH_table[] = { { - .sub_index = SHADER_AFT_SUB_CLOTH_DEFAULT, + .sub_index = SHADER_FT_SUB_CLOTH_DEFAULT, .vp_unival_max = cloth_default_vpt_unival_max, .fp_unival_max = cloth_default_fpt_unival_max, .vp = "cloth_default", .fp = "cloth_default", }, { - .sub_index = SHADER_AFT_SUB_CLOTH_ANISO, + .sub_index = SHADER_FT_SUB_CLOTH_ANISO, .vp_unival_max = cloth_aniso_vpt_unival_max, .fp_unival_max = cloth_aniso_fpt_unival_max, .vp = "cloth_default", .fp = "cloth_aniso", }, { - .sub_index = SHADER_AFT_SUB_CLOTH_NPR1, + .sub_index = SHADER_FT_SUB_CLOTH_NPR1, .vp_unival_max = cloth_npr1_vpt_unival_max, .fp_unival_max = cloth_npr1_fpt_unival_max, .vp = "cloth_default", @@ -731,7 +731,7 @@ static const shader_sub_table CLOTH_table[] = { static const shader_sub_table TIGHTS_table[] = { { - .sub_index = SHADER_AFT_SUB_TIGHTS, + .sub_index = SHADER_FT_SUB_TIGHTS, .vp_unival_max = tights_vpt_unival_max, .fp_unival_max = tights_fpt_unival_max, .vp = "tights", @@ -741,7 +741,7 @@ static const shader_sub_table TIGHTS_table[] = { static const shader_sub_table SKY_table[] = { { - .sub_index = SHADER_AFT_SUB_SKY_DEFAULT, + .sub_index = SHADER_FT_SUB_SKY_DEFAULT, .vp_unival_max = sky_default_vpt_unival_max, .fp_unival_max = sky_default_fpt_unival_max, .vp = "sky_default", @@ -751,7 +751,7 @@ static const shader_sub_table SKY_table[] = { static const shader_sub_table EYEBALL_table[] = { { - .sub_index = SHADER_AFT_SUB_EYE_BALL, + .sub_index = SHADER_FT_SUB_EYE_BALL, .vp_unival_max = eye_ball_vpt_unival_max, .fp_unival_max = eye_ball_fpt_unival_max, .vp = "eye_ball", @@ -761,7 +761,7 @@ static const shader_sub_table EYEBALL_table[] = { static const shader_sub_table EYELENS_table[] = { { - .sub_index = SHADER_AFT_SUB_EYE_LENS, + .sub_index = SHADER_FT_SUB_EYE_LENS, .vp_unival_max = eye_lens_vpt_unival_max, .fp_unival_max = eye_lens_fpt_unival_max, .vp = "eye_lens", @@ -771,7 +771,7 @@ static const shader_sub_table EYELENS_table[] = { static const shader_sub_table GLASEYE_table[] = { { - .sub_index = SHADER_AFT_SUB_GLASS_EYE, + .sub_index = SHADER_FT_SUB_GLASS_EYE, .vp_unival_max = glass_eye_vpt_unival_max, .fp_unival_max = glass_eye_fpt_unival_max, .vp = "glass_eye", @@ -781,7 +781,7 @@ static const shader_sub_table GLASEYE_table[] = { static const shader_sub_table MEMBRAN_table[] = { { - .sub_index = SHADER_AFT_SUB_MEMBRANE, + .sub_index = SHADER_FT_SUB_MEMBRANE, .vp_unival_max = membrane_vpt_unival_max, .fp_unival_max = membrane_fpt_unival_max, .vp = "membrane", @@ -791,7 +791,7 @@ static const shader_sub_table MEMBRAN_table[] = { static const shader_sub_table SHDMAP_table[] = { { - .sub_index = SHADER_AFT_SUB_SHADOWMAP, + .sub_index = SHADER_FT_SUB_SHADOWMAP, .vp_unival_max = shadowmap_vpt_unival_max, .fp_unival_max = shadowmap_fpt_unival_max, .vp = "shadowmap", @@ -801,7 +801,7 @@ static const shader_sub_table SHDMAP_table[] = { static const shader_sub_table ESM_table[] = { { - .sub_index = SHADER_AFT_SUB_ESM, + .sub_index = SHADER_FT_SUB_ESM, .vp_unival_max = esm_vpt_unival_max, .fp_unival_max = esm_fpt_unival_max, .vp = "esm", @@ -811,7 +811,7 @@ static const shader_sub_table ESM_table[] = { static const shader_sub_table ESMGAUSS_table[] = { { - .sub_index = SHADER_AFT_SUB_ESM_GAUSS, + .sub_index = SHADER_FT_SUB_ESM_GAUSS, .vp_unival_max = esm_gauss_vpt_unival_max, .fp_unival_max = esm_gauss_fpt_unival_max, .vp = "esm_gauss", @@ -821,7 +821,7 @@ static const shader_sub_table ESMGAUSS_table[] = { static const shader_sub_table ESMFILT_table[] = { { - .sub_index = SHADER_AFT_SUB_ESM_FILTER, + .sub_index = SHADER_FT_SUB_ESM_FILTER, .vp_unival_max = esm_filter_vpt_unival_max, .fp_unival_max = esm_filter_fpt_unival_max, .vp = "esm_filter", @@ -831,7 +831,7 @@ static const shader_sub_table ESMFILT_table[] = { static const shader_sub_table LITPROJ_table[] = { { - .sub_index = SHADER_AFT_SUB_LIT_PROJ, + .sub_index = SHADER_FT_SUB_LIT_PROJ, .vp_unival_max = lit_proj_vpt_unival_max, .fp_unival_max = lit_proj_fpt_unival_max, .vp = "lit_proj", @@ -841,7 +841,7 @@ static const shader_sub_table LITPROJ_table[] = { static const shader_sub_table SIMPLE_table[] = { { - .sub_index = SHADER_AFT_SUB_SIMPLE, + .sub_index = SHADER_FT_SUB_SIMPLE, .vp_unival_max = simple_vpt_unival_max, .fp_unival_max = simple_fpt_unival_max, .vp = "simple", @@ -851,7 +851,7 @@ static const shader_sub_table SIMPLE_table[] = { static const shader_sub_table SIL_table[] = { { - .sub_index = SHADER_AFT_SUB_SILHOUETTE, + .sub_index = SHADER_FT_SUB_SILHOUETTE, .vp_unival_max = silhouette_vpt_unival_max, .fp_unival_max = silhouette_fpt_unival_max, .vp = "silhouette", @@ -861,7 +861,7 @@ static const shader_sub_table SIL_table[] = { static const shader_sub_table LAMBERT_table[] = { { - .sub_index = SHADER_AFT_SUB_LAMBERT, + .sub_index = SHADER_FT_SUB_LAMBERT, .vp_unival_max = lambert_vpt_unival_max, .fp_unival_max = lambert_fpt_unival_max, .vp = "lambert", @@ -871,7 +871,7 @@ static const shader_sub_table LAMBERT_table[] = { static const shader_sub_table CONSTANT_table[] = { { - .sub_index = SHADER_AFT_SUB_CONSTANT, + .sub_index = SHADER_FT_SUB_CONSTANT, .vp_unival_max = constant_vpt_unival_max, .fp_unival_max = constant_fpt_unival_max, .vp = "constant", @@ -881,7 +881,7 @@ static const shader_sub_table CONSTANT_table[] = { static const shader_sub_table PEEL_table[] = { { - .sub_index = SHADER_AFT_SUB_PEEL, + .sub_index = SHADER_FT_SUB_PEEL, .vp_unival_max = peel_vpt_unival_max, .fp_unival_max = peel_fpt_unival_max, .vp = "depth_peel", @@ -891,14 +891,14 @@ static const shader_sub_table PEEL_table[] = { static const shader_sub_table TONEMAP_table[] = { { - .sub_index = SHADER_AFT_SUB_TONE_MAP, + .sub_index = SHADER_FT_SUB_TONE_MAP, .vp_unival_max = tone_map_vpt_unival_max, .fp_unival_max = tone_map_fpt_unival_max, .vp = "tone_map", .fp = "tone_map", }, { - .sub_index = SHADER_AFT_SUB_TONE_MAP_NPR1, + .sub_index = SHADER_FT_SUB_TONE_MAP_NPR1, .vp_unival_max = tone_map_npr1_vpt_unival_max, .fp_unival_max = tone_map_npr1_fpt_unival_max, .vp = "tone_map", @@ -908,7 +908,7 @@ static const shader_sub_table TONEMAP_table[] = { static const shader_sub_table REDUCE_table[] = { { - .sub_index = SHADER_AFT_SUB_REDUCE_TEX, + .sub_index = SHADER_FT_SUB_REDUCE_TEX, .vp_unival_max = reduce_tex_vpt_unival_max, .fp_unival_max = reduce_tex_fpt_unival_max, .vp = "reduce_tex", @@ -918,7 +918,7 @@ static const shader_sub_table REDUCE_table[] = { static const shader_sub_table MAGNIFY_table[] = { { - .sub_index = SHADER_AFT_SUB_MAGNIFY, + .sub_index = SHADER_FT_SUB_MAGNIFY, .vp_unival_max = magnify_vpt_unival_max, .fp_unival_max = magnify_fpt_unival_max, .vp = "magnify", @@ -928,7 +928,7 @@ static const shader_sub_table MAGNIFY_table[] = { static const shader_sub_table MLAA_table[] = { { - .sub_index = SHADER_AFT_SUB_MLAA, + .sub_index = SHADER_FT_SUB_MLAA, .vp_unival_max = mlaa_vpt_unival_max, .fp_unival_max = mlaa_fpt_unival_max, .vp = "mlaa", @@ -938,7 +938,7 @@ static const shader_sub_table MLAA_table[] = { static const shader_sub_table CONTOUR_table[] = { { - .sub_index = SHADER_AFT_SUB_CONTOUR, + .sub_index = SHADER_FT_SUB_CONTOUR, .vp_unival_max = contour_vpt_unival_max, .fp_unival_max = contour_fpt_unival_max, .vp = "contour", @@ -948,7 +948,7 @@ static const shader_sub_table CONTOUR_table[] = { static const shader_sub_table EXPOSURE_table[] = { { - .sub_index = SHADER_AFT_SUB_EXPOSURE, + .sub_index = SHADER_FT_SUB_EXPOSURE, .vp_unival_max = exposure_vpt_unival_max, .fp_unival_max = exposure_fpt_unival_max, .vp = "exposure", @@ -958,7 +958,7 @@ static const shader_sub_table EXPOSURE_table[] = { static const shader_sub_table GAUSS_table[] = { { - .sub_index = SHADER_AFT_SUB_PP_GAUSS, + .sub_index = SHADER_FT_SUB_PP_GAUSS, .vp_unival_max = pp_gauss_vpt_unival_max, .fp_unival_max = pp_gauss_fpt_unival_max, .vp = "pp_gauss", @@ -968,7 +968,7 @@ static const shader_sub_table GAUSS_table[] = { static const shader_sub_table SUN_table[] = { { - .sub_index = SHADER_AFT_SUB_SUN, + .sub_index = SHADER_FT_SUB_SUN, .vp_unival_max = sun_vpt_unival_max, .fp_unival_max = sun_fpt_unival_max, .vp = "sun", @@ -978,7 +978,7 @@ static const shader_sub_table SUN_table[] = { static const shader_sub_table FADE_table[] = { { - .sub_index = SHADER_AFT_SUB_FADE, + .sub_index = SHADER_FT_SUB_FADE, .vp_unival_max = fade_vpt_unival_max, .fp_unival_max = fade_fpt_unival_max, .vp = "fade", @@ -988,7 +988,7 @@ static const shader_sub_table FADE_table[] = { static const shader_sub_table WATER01_table[] = { { - .sub_index = SHADER_AFT_SUB_WATER01, + .sub_index = SHADER_FT_SUB_WATER01, .vp_unival_max = water01_vpt_unival_max, .fp_unival_max = water01_fpt_unival_max, .vp = "water01", @@ -998,7 +998,7 @@ static const shader_sub_table WATER01_table[] = { static const shader_sub_table WATER02_table[] = { { - .sub_index = SHADER_AFT_SUB_WATER02, + .sub_index = SHADER_FT_SUB_WATER02, .vp_unival_max = water02_vpt_unival_max, .fp_unival_max = water02_fpt_unival_max, .vp = "water02", @@ -1008,7 +1008,7 @@ static const shader_sub_table WATER02_table[] = { static const shader_sub_table WATRING_table[] = { { - .sub_index = SHADER_AFT_SUB_WATER_RING, + .sub_index = SHADER_FT_SUB_WATER_RING, .vp_unival_max = water_ring_vpt_unival_max, .fp_unival_max = water_ring_fpt_unival_max, .vp = "water_ring", @@ -1018,7 +1018,7 @@ static const shader_sub_table WATRING_table[] = { static const shader_sub_table W_PTCL_table[] = { { - .sub_index = SHADER_AFT_SUB_WATER_PARTICLE, + .sub_index = SHADER_FT_SUB_WATER_PARTICLE, .vp_unival_max = water_particle_vpt_unival_max, .fp_unival_max = water_particle_fpt_unival_max, .vp = "water_particle", @@ -1028,7 +1028,7 @@ static const shader_sub_table W_PTCL_table[] = { static const shader_sub_table SNOW_PT_table[] = { { - .sub_index = SHADER_AFT_SUB_SNOW_PARTICLE, + .sub_index = SHADER_FT_SUB_SNOW_PARTICLE, .vp_unival_max = snow_particle_vpt_unival_max, .fp_unival_max = snow_particle_fpt_unival_max, .vp = "snow_particle", @@ -1038,7 +1038,7 @@ static const shader_sub_table SNOW_PT_table[] = { static const shader_sub_table LEAF_PT_table[] = { { - .sub_index = SHADER_AFT_SUB_LEAF_PARTICLE, + .sub_index = SHADER_FT_SUB_LEAF_PARTICLE, .vp_unival_max = leaf_particle_vpt_unival_max, .fp_unival_max = leaf_particle_fpt_unival_max, .vp = "leaf_particle", @@ -1048,7 +1048,7 @@ static const shader_sub_table LEAF_PT_table[] = { static const shader_sub_table STAR_table[] = { { - .sub_index = SHADER_AFT_SUB_STAR, + .sub_index = SHADER_FT_SUB_STAR, .vp_unival_max = star_vpt_unival_max, .fp_unival_max = star_fpt_unival_max, .vp = "star", @@ -1058,7 +1058,7 @@ static const shader_sub_table STAR_table[] = { static const shader_sub_table SNORING_table[] = { { - .sub_index = SHADER_AFT_SUB_SNOW_RING, + .sub_index = SHADER_FT_SUB_SNOW_RING, .vp_unival_max = snow_ring_vpt_unival_max, .fp_unival_max = snow_ring_fpt_unival_max, .vp = "snow_ring", @@ -1068,7 +1068,7 @@ static const shader_sub_table SNORING_table[] = { static const shader_sub_table SN_FOOT_table[] = { { - .sub_index = SHADER_AFT_SUB_SNOW_FOOTPRINT, + .sub_index = SHADER_FT_SUB_SNOW_FOOTPRINT, .vp_unival_max = snow_footprint_vpt_unival_max, .fp_unival_max = snow_footprint_fpt_unival_max, .vp = "snow_footprint", @@ -1078,7 +1078,7 @@ static const shader_sub_table SN_FOOT_table[] = { static const shader_sub_table SN_TSL_table[] = { { - .sub_index = SHADER_AFT_SUB_SNOW_TEX_SPACE_LIGHT, + .sub_index = SHADER_FT_SUB_SNOW_TEX_SPACE_LIGHT, .vp_unival_max = snow_tex_space_light_vpt_unival_max, .fp_unival_max = snow_tex_space_light_fpt_unival_max, .vp = "snow_tex_space_light", @@ -1088,7 +1088,7 @@ static const shader_sub_table SN_TSL_table[] = { static const shader_sub_table SN_NRM_table[] = { { - .sub_index = SHADER_AFT_SUB_SNOW_CALC_NORMAL, + .sub_index = SHADER_FT_SUB_SNOW_CALC_NORMAL, .vp_unival_max = snow_calc_normal_vpt_unival_max, .fp_unival_max = snow_calc_normal_fpt_unival_max, .vp = "snow_calc_normal", @@ -1098,7 +1098,7 @@ static const shader_sub_table SN_NRM_table[] = { static const shader_sub_table FLOOR_table[] = { { - .sub_index = SHADER_AFT_SUB_FLOOR, + .sub_index = SHADER_FT_SUB_FLOOR, .vp_unival_max = floor_vpt_unival_max, .fp_unival_max = floor_fpt_unival_max, .vp = "floor", @@ -1108,7 +1108,7 @@ static const shader_sub_table FLOOR_table[] = { static const shader_sub_table PUDDLE_table[] = { { - .sub_index = SHADER_AFT_SUB_PUDDLE, + .sub_index = SHADER_FT_SUB_PUDDLE, .vp_unival_max = puddle_vpt_unival_max, .fp_unival_max = puddle_fpt_unival_max, .vp = "puddle", @@ -1118,7 +1118,7 @@ static const shader_sub_table PUDDLE_table[] = { static const shader_sub_table S_REFL_table[] = { { - .sub_index = SHADER_AFT_SUB_SIMPLE_REFLECT, + .sub_index = SHADER_FT_SUB_SIMPLE_REFLECT, .vp_unival_max = simple_reflect_vpt_unival_max, .fp_unival_max = simple_reflect_fpt_unival_max, .vp = "simple_reflect", @@ -1128,7 +1128,7 @@ static const shader_sub_table S_REFL_table[] = { static const shader_sub_table S_REFR_table[] = { { - .sub_index = SHADER_AFT_SUB_SIMPLE_REFRACT, + .sub_index = SHADER_FT_SUB_SIMPLE_REFRACT, .vp_unival_max = simple_refract_vpt_unival_max, .fp_unival_max = simple_refract_fpt_unival_max, .vp = "simple_refract", @@ -1138,7 +1138,7 @@ static const shader_sub_table S_REFR_table[] = { static const shader_sub_table RIPEMIT_table[] = { { - .sub_index = SHADER_AFT_SUB_RIPPLE_EMIT, + .sub_index = SHADER_FT_SUB_RIPPLE_EMIT, .vp_unival_max = ripple_emit_vpt_unival_max, .fp_unival_max = ripple_emit_fpt_unival_max, .vp = "ripple_emit", @@ -1148,7 +1148,7 @@ static const shader_sub_table RIPEMIT_table[] = { static const shader_sub_table RAIN_table[] = { { - .sub_index = SHADER_AFT_SUB_RAIN, + .sub_index = SHADER_FT_SUB_RAIN, .vp_unival_max = rain_vpt_unival_max, .fp_unival_max = rain_fpt_unival_max, .vp = "rain", @@ -1158,7 +1158,7 @@ static const shader_sub_table RAIN_table[] = { static const shader_sub_table VOLLIT_table[] = { { - .sub_index = SHADER_AFT_SUB_VOLUME_LIGHT, + .sub_index = SHADER_FT_SUB_VOLUME_LIGHT, .vp_unival_max = volume_light_vpt_unival_max, .fp_unival_max = volume_light_fpt_unival_max, .vp = "volume_light", @@ -1168,7 +1168,7 @@ static const shader_sub_table VOLLIT_table[] = { static const shader_sub_table FENCE_table[] = { { - .sub_index = SHADER_AFT_SUB_FENCE_ALPHA, + .sub_index = SHADER_FT_SUB_FENCE_ALPHA, .vp_unival_max = fence_alpha_vpt_unival_max, .fp_unival_max = fence_alpha_fpt_unival_max, .vp = "fence_alpha", @@ -1178,7 +1178,7 @@ static const shader_sub_table FENCE_table[] = { static const shader_sub_table RIPPLE_table[] = { { - .sub_index = SHADER_AFT_SUB_RIPPLE, + .sub_index = SHADER_FT_SUB_RIPPLE, .vp_unival_max = ripple_vpt_unival_max, .fp_unival_max = ripple_fpt_unival_max, .vp = "ripple", @@ -1188,7 +1188,7 @@ static const shader_sub_table RIPPLE_table[] = { static const shader_sub_table FOGPTCL_table[] = { { - .sub_index = SHADER_AFT_SUB_FOG_PTCL, + .sub_index = SHADER_FT_SUB_FOG_PTCL, .vp_unival_max = fog_ptcl_vpt_unival_max, .fp_unival_max = fog_ptcl_fpt_unival_max, .vp = "fog_ptcl", @@ -1198,7 +1198,7 @@ static const shader_sub_table FOGPTCL_table[] = { static const shader_sub_table PARTICL_table[] = { { - .sub_index = SHADER_AFT_SUB_PARTICLE, + .sub_index = SHADER_FT_SUB_PARTICLE, .vp_unival_max = particle_vpt_unival_max, .fp_unival_max = particle_fpt_unival_max, .vp = "particle", @@ -1208,7 +1208,7 @@ static const shader_sub_table PARTICL_table[] = { static const shader_sub_table GLITTER_PT_table[] = { { - .sub_index = SHADER_AFT_SUB_GLITTER_PARTICLE, + .sub_index = SHADER_FT_SUB_GLITTER_PARTICLE, .vp_unival_max = glitter_particle_vpt_unival_max, .fp_unival_max = glitter_particle_fpt_unival_max, .vp = "glitter_particle", @@ -1218,7 +1218,7 @@ static const shader_sub_table GLITTER_PT_table[] = { static const shader_sub_table SHOWVEC_table[] = { { - .sub_index = SHADER_AFT_SUB_SHOW_VECTOR, + .sub_index = SHADER_FT_SUB_SHOW_VECTOR, .vp_unival_max = show_vector_vpt_unival_max, .fp_unival_max = show_vector_fpt_unival_max, .vp = "show_vector", @@ -1228,7 +1228,7 @@ static const shader_sub_table SHOWVEC_table[] = { static const shader_sub_table FONT_table[] = { { - .sub_index = SHADER_AFT_SUB_FONT, + .sub_index = SHADER_FT_SUB_FONT, .vp_unival_max = font_vpt_unival_max, .fp_unival_max = font_fpt_unival_max, .vp = "font", @@ -1238,7 +1238,7 @@ static const shader_sub_table FONT_table[] = { static const shader_sub_table MOVIE_table[] = { { - .sub_index = SHADER_AFT_SUB_MOVIE, + .sub_index = SHADER_FT_SUB_MOVIE, .vp_unival_max = movie_vpt_unival_max, .fp_unival_max = movie_fpt_unival_max, .vp = "movie", @@ -1248,7 +1248,7 @@ static const shader_sub_table MOVIE_table[] = { static const shader_sub_table IMGFILT_table[] = { { - .sub_index = SHADER_AFT_SUB_IMGFILTER, + .sub_index = SHADER_FT_SUB_IMGFILTER, .vp_unival_max = imgfilter_vpt_unival_max, .fp_unival_max = imgfilter_fpt_unival_max, .vp = "imgfilter", @@ -1258,7 +1258,7 @@ static const shader_sub_table IMGFILT_table[] = { static const shader_sub_table SPRITE_table[] = { { - .sub_index = SHADER_AFT_SUB_SPRITE, + .sub_index = SHADER_FT_SUB_SPRITE, .vp_unival_max = sprite_vpt_unival_max, .fp_unival_max = sprite_fpt_unival_max, .vp = "sprite", @@ -1278,6 +1278,7 @@ static const uniform_name BLINN_uniform[] = { U_MORPH, U_MORPH_COLOR, U_LIGHT_1, + U_ALPHA_TEST, // 11th added }; static const uniform_name ITEM_uniform[] = { @@ -1309,6 +1310,7 @@ static const uniform_name STAGE_uniform[] = { U_FOG_HEIGHT, U_LIGHT_1, U12, + U_ALPHA_TEST, // 11th added }; static const uniform_name SKIN_uniform[] = { @@ -1356,6 +1358,7 @@ static const uniform_name HAIR_uniform[] = { U_NPR, U_CHARA_COLOR, U_TONE_CURVE, + U_ALPHA_TEST, // 14th Added }; static const uniform_name CLOTH_uniform[] = { @@ -1397,6 +1400,7 @@ static const uniform_name SKY_uniform[] = { U_MORPH, U_MORPH_COLOR, U_FOG_HEIGHT, + U_ALPHA_TEST, // 6th added }; static const uniform_name EYEBALL_uniform[] = { @@ -1466,6 +1470,7 @@ static const uniform_name SIMPLE_uniform[] = { U_NORMAL, U_INSTANCE, U2E, + U_ALPHA_TEST, // 6th added }; static const uniform_name SIL_uniform[] = { @@ -1476,6 +1481,7 @@ static const uniform_name SIL_uniform[] = { U_MORPH, U_MORPH_COLOR, U0A, + U_ALPHA_TEST, // 7th added }; static const uniform_name LAMBERT_uniform[] = { @@ -1487,6 +1493,7 @@ static const uniform_name LAMBERT_uniform[] = { U_MORPH, U_MORPH_COLOR, U_LIGHT_1, + U_ALPHA_TEST, // 8th added }; static const uniform_name CONSTANT_uniform[] = { @@ -1496,6 +1503,7 @@ static const uniform_name CONSTANT_uniform[] = { U_FOG_HEIGHT, U_MORPH, U_MORPH_COLOR, + U_ALPHA_TEST, // 6th added }; static const uniform_name PEEL_uniform[] = { @@ -1515,7 +1523,7 @@ static const uniform_name TONEMAP_uniform[] = { }; static const uniform_name REDUCE_uniform[] = { - U2A, + U_REDUCE, U01, }; @@ -1560,6 +1568,7 @@ static const uniform_name WATER01_uniform[] = { U_ENV_MAP, U_SPECULAR, U_FOG_HEIGHT, + U_ALPHA_TEST, // 8th added }; static const uniform_name WATER02_uniform[] = { @@ -1572,7 +1581,7 @@ static const uniform_name WATRING_uniform[] = { }; static const uniform_name W_PTCL_uniform[] = { - U_INVALID, + U_ALPHA_TEST, // 0th added }; static const uniform_name SNOW_PT_uniform[] = { @@ -1615,6 +1624,7 @@ static const uniform_name FLOOR_uniform[] = { U_FOG_HEIGHT, U_MORPH, U_MORPH_COLOR, + U_ALPHA_TEST, // 7th Added }; static const uniform_name PUDDLE_uniform[] = { @@ -1669,7 +1679,7 @@ static const uniform_name FOGPTCL_uniform[] = { }; static const uniform_name PARTICL_uniform[] = { - U_INVALID, + U_ALPHA_TEST, // 0th added }; static const uniform_name GLITTER_PT_uniform[] = { @@ -1715,6 +1725,7 @@ static const bool BLINN_permut[] = { false, false, false, + false, // 11th Added }; static const bool ITEM_permut[] = { @@ -1746,6 +1757,7 @@ static const bool STAGE_permut[] = { false, false, false, + false, // 11th added }; static const bool SKIN_permut[] = { @@ -1773,7 +1785,7 @@ static const bool SSS_SKIN_permut[] = { }; static const bool SSS_FILT_permut[] = { - false, + true, false, false, }; @@ -1793,6 +1805,7 @@ static const bool HAIR_permut[] = { false, false, false, + false, // 14th Added }; static const bool CLOTH_permut[] = { @@ -1834,6 +1847,7 @@ static const bool SKY_permut[] = { false, false, false, + false, // 6th added }; static const bool EYEBALL_permut[] = { @@ -1903,6 +1917,7 @@ static const bool SIMPLE_permut[] = { false, false, false, + false, // 6th added }; static const bool SIL_permut[] = { @@ -1913,6 +1928,7 @@ static const bool SIL_permut[] = { false, false, false, + false, // 7th added }; static const bool LAMBERT_permut[] = { @@ -1924,6 +1940,7 @@ static const bool LAMBERT_permut[] = { false, false, false, + false, // 8th added }; static const bool CONSTANT_permut[] = { @@ -1963,7 +1980,7 @@ static const bool MAGNIFY_permut[] = { static const bool MLAA_permut[] = { false, false, - false, + true, true, }; @@ -1997,6 +2014,7 @@ static const bool WATER01_permut[] = { false, false, false, + false, // 8th added }; static const bool WATER02_permut[] = { @@ -2009,7 +2027,7 @@ static const bool WATRING_permut[] = { }; static const bool W_PTCL_permut[] = { - false, + false, // 0th added }; static const bool SNOW_PT_permut[] = { @@ -2052,6 +2070,7 @@ static const bool FLOOR_permut[] = { false, false, false, + false, // 7th Added }; static const bool PUDDLE_permut[] = { @@ -2106,7 +2125,7 @@ static const bool FOGPTCL_permut[] = { }; static const bool PARTICL_permut[] = { - false, + false, // 0th added }; static const bool GLITTER_PT_permut[] = { @@ -2151,7 +2170,7 @@ static const shader_table SHADER_FFP_shader = { #define shader_table_struct(n) \ static const shader_table n##_shader = { \ .name = #n, \ - .index = SHADER_AFT_##n, \ + .index = SHADER_FT_##n, \ .num_sub = sizeof(n##_table) / sizeof(shader_sub_table), \ .sub = n##_table, \ .num_uniform = sizeof(n##_uniform) / sizeof(uniform_name), \ @@ -2222,74 +2241,105 @@ shader_table_struct(IMGFILT) shader_table_struct(SPRITE) #undef shader_table_struct -static const shader_table* shader_aft_table[] = { - [SHADER_AFT_FFP ] = &SHADER_FFP_shader, - [SHADER_AFT_BLINN ] = &BLINN_shader, - [SHADER_AFT_ITEM ] = &ITEM_shader, - [SHADER_AFT_STAGE ] = &STAGE_shader, - [SHADER_AFT_SKIN ] = &SKIN_shader, - [SHADER_AFT_SSS_SKIN ] = &SSS_SKIN_shader, - [SHADER_AFT_SSS_FILT ] = &SSS_FILT_shader, - [SHADER_AFT_HAIR ] = &HAIR_shader, - [SHADER_AFT_CLOTH ] = &CLOTH_shader, - [SHADER_AFT_TIGHTS ] = &TIGHTS_shader, - [SHADER_AFT_SKY ] = &SKY_shader, - [SHADER_AFT_EYEBALL ] = &EYEBALL_shader, - [SHADER_AFT_EYELENS ] = &EYELENS_shader, - [SHADER_AFT_GLASEYE ] = &GLASEYE_shader, - [SHADER_AFT_MEMBRAN ] = &MEMBRAN_shader, - [SHADER_AFT_SHDMAP ] = &SHDMAP_shader, - [SHADER_AFT_ESM ] = &ESM_shader, - [SHADER_AFT_ESMGAUSS ] = &ESMGAUSS_shader, - [SHADER_AFT_ESMFILT ] = &ESMFILT_shader, - [SHADER_AFT_LITPROJ ] = &LITPROJ_shader, - [SHADER_AFT_SIMPLE ] = &SIMPLE_shader, - [SHADER_AFT_SIL ] = &SIL_shader, - [SHADER_AFT_LAMBERT ] = &LAMBERT_shader, - [SHADER_AFT_CONSTANT ] = &CONSTANT_shader, - [SHADER_AFT_PEEL ] = &PEEL_shader, - [SHADER_AFT_TONEMAP ] = &TONEMAP_shader, - [SHADER_AFT_REDUCE ] = &REDUCE_shader, - [SHADER_AFT_MAGNIFY ] = &MAGNIFY_shader, - [SHADER_AFT_MLAA ] = &MLAA_shader, - [SHADER_AFT_CONTOUR ] = &CONTOUR_shader, - [SHADER_AFT_EXPOSURE ] = &EXPOSURE_shader, - [SHADER_AFT_GAUSS ] = &GAUSS_shader, - [SHADER_AFT_SUN ] = &SUN_shader, - [SHADER_AFT_FADE ] = &FADE_shader, - [SHADER_AFT_WATER01 ] = &WATER01_shader, - [SHADER_AFT_WATER02 ] = &WATER02_shader, - [SHADER_AFT_WATRING ] = &WATRING_shader, - [SHADER_AFT_W_PTCL ] = &W_PTCL_shader, - [SHADER_AFT_SNOW_PT ] = &SNOW_PT_shader, - [SHADER_AFT_LEAF_PT ] = &LEAF_PT_shader, - [SHADER_AFT_STAR ] = &STAR_shader, - [SHADER_AFT_SNORING ] = &SNORING_shader, - [SHADER_AFT_SN_FOOT ] = &SN_FOOT_shader, - [SHADER_AFT_SN_TSL ] = &SN_TSL_shader, - [SHADER_AFT_SN_NRM ] = &SN_NRM_shader, - [SHADER_AFT_FLOOR ] = &FLOOR_shader, - [SHADER_AFT_PUDDLE ] = &PUDDLE_shader, - [SHADER_AFT_S_REFL ] = &S_REFL_shader, - [SHADER_AFT_S_REFR ] = &S_REFR_shader, - [SHADER_AFT_RIPEMIT ] = &RIPEMIT_shader, - [SHADER_AFT_RAIN ] = &RAIN_shader, - [SHADER_AFT_VOLLIT ] = &VOLLIT_shader, - [SHADER_AFT_FENCE ] = &FENCE_shader, - [SHADER_AFT_RIPPLE ] = &RIPPLE_shader, - [SHADER_AFT_FOGPTCL ] = &FOGPTCL_shader, - [SHADER_AFT_PARTICL ] = &PARTICL_shader, - [SHADER_AFT_GLITTER_PT] = &GLITTER_PT_shader, - [SHADER_AFT_SHOWVEC ] = &SHOWVEC_shader, - [SHADER_AFT_FONT ] = &FONT_shader, - [SHADER_AFT_MOVIE ] = &MOVIE_shader, - [SHADER_AFT_IMGFILT ] = &IMGFILT_shader, - [SHADER_AFT_SPRITE ] = &SPRITE_shader, +typedef struct glass_eye_struct { + vec4u field_0; + vec4u field_10; + float_t field_20; + float_t field_24; + float_t field_28; + float_t field_2C; + vec3 field_30; + vec3 field_3C; + vec3 field_48; + float_t field_54; + vec3 field_58; + float_t field_64; + vec3 field_68; + vec3 field_74; + vec3 field_80; + float_t field_8C; + vec3 field_90; + uint32_t frame; + vec4u field_A0; + bool field_B0; + bool field_B1; + bool field_B2; + bool field_B3; + int32_t field_B4; + int32_t field_B8; + int32_t field_BC; +} glass_eye_struct; + +static const shader_table* shader_ft_table[] = { + [SHADER_FT_FFP ] = &SHADER_FFP_shader, + [SHADER_FT_BLINN ] = &BLINN_shader, + [SHADER_FT_ITEM ] = &ITEM_shader, + [SHADER_FT_STAGE ] = &STAGE_shader, + [SHADER_FT_SKIN ] = &SKIN_shader, + [SHADER_FT_SSS_SKIN ] = &SSS_SKIN_shader, + [SHADER_FT_SSS_FILT ] = &SSS_FILT_shader, + [SHADER_FT_HAIR ] = &HAIR_shader, + [SHADER_FT_CLOTH ] = &CLOTH_shader, + [SHADER_FT_TIGHTS ] = &TIGHTS_shader, + [SHADER_FT_SKY ] = &SKY_shader, + [SHADER_FT_EYEBALL ] = &EYEBALL_shader, + [SHADER_FT_EYELENS ] = &EYELENS_shader, + [SHADER_FT_GLASEYE ] = &GLASEYE_shader, + [SHADER_FT_MEMBRAN ] = &MEMBRAN_shader, + [SHADER_FT_SHDMAP ] = &SHDMAP_shader, + [SHADER_FT_ESM ] = &ESM_shader, + [SHADER_FT_ESMGAUSS ] = &ESMGAUSS_shader, + [SHADER_FT_ESMFILT ] = &ESMFILT_shader, + [SHADER_FT_LITPROJ ] = &LITPROJ_shader, + [SHADER_FT_SIMPLE ] = &SIMPLE_shader, + [SHADER_FT_SIL ] = &SIL_shader, + [SHADER_FT_LAMBERT ] = &LAMBERT_shader, + [SHADER_FT_CONSTANT ] = &CONSTANT_shader, + [SHADER_FT_PEEL ] = &PEEL_shader, + [SHADER_FT_TONEMAP ] = &TONEMAP_shader, + [SHADER_FT_REDUCE ] = &REDUCE_shader, + [SHADER_FT_MAGNIFY ] = &MAGNIFY_shader, + [SHADER_FT_MLAA ] = &MLAA_shader, + [SHADER_FT_CONTOUR ] = &CONTOUR_shader, + [SHADER_FT_EXPOSURE ] = &EXPOSURE_shader, + [SHADER_FT_GAUSS ] = &GAUSS_shader, + [SHADER_FT_SUN ] = &SUN_shader, + [SHADER_FT_FADE ] = &FADE_shader, + [SHADER_FT_WATER01 ] = &WATER01_shader, + [SHADER_FT_WATER02 ] = &WATER02_shader, + [SHADER_FT_WATRING ] = &WATRING_shader, + [SHADER_FT_W_PTCL ] = &W_PTCL_shader, + [SHADER_FT_SNOW_PT ] = &SNOW_PT_shader, + [SHADER_FT_LEAF_PT ] = &LEAF_PT_shader, + [SHADER_FT_STAR ] = &STAR_shader, + [SHADER_FT_SNORING ] = &SNORING_shader, + [SHADER_FT_SN_FOOT ] = &SN_FOOT_shader, + [SHADER_FT_SN_TSL ] = &SN_TSL_shader, + [SHADER_FT_SN_NRM ] = &SN_NRM_shader, + [SHADER_FT_FLOOR ] = &FLOOR_shader, + [SHADER_FT_PUDDLE ] = &PUDDLE_shader, + [SHADER_FT_S_REFL ] = &S_REFL_shader, + [SHADER_FT_S_REFR ] = &S_REFR_shader, + [SHADER_FT_RIPEMIT ] = &RIPEMIT_shader, + [SHADER_FT_RAIN ] = &RAIN_shader, + [SHADER_FT_VOLLIT ] = &VOLLIT_shader, + [SHADER_FT_FENCE ] = &FENCE_shader, + [SHADER_FT_RIPPLE ] = &RIPPLE_shader, + [SHADER_FT_FOGPTCL ] = &FOGPTCL_shader, + [SHADER_FT_PARTICL ] = &PARTICL_shader, + [SHADER_FT_GLITTER_PT] = &GLITTER_PT_shader, + [SHADER_FT_SHOWVEC ] = &SHOWVEC_shader, + [SHADER_FT_FONT ] = &FONT_shader, + [SHADER_FT_MOVIE ] = &MOVIE_shader, + [SHADER_FT_IMGFILT ] = &IMGFILT_shader, + [SHADER_FT_SPRITE ] = &SPRITE_shader, }; -static const size_t shader_aft_table_size = - sizeof(shader_aft_table) / sizeof(shader_table*); +static const size_t shader_ft_table_size = + sizeof(shader_ft_table) / sizeof(shader_table*); +static void glass_eye_calc(glass_eye_struct* glass_eye); +static void glass_eye_set(glass_eye_struct* glass_eye, shader_set_data* set); static void shader_bind_blinn(shader_set_data* set, shader* shad); static void shader_bind_cloth(shader_set_data* set, shader* shad); static void shader_bind_hair(shader_set_data* set, shader* shad); @@ -2297,59 +2347,185 @@ static void shader_bind_membrane(shader_set_data* set, shader* shad); static void shader_bind_eye_ball(shader_set_data* set, shader* shader); static void shader_bind_tone_map(shader_set_data* set, shader* shader); -static const shader_bind_func shader_aft_bind_func_table[] = { +static const shader_bind_func shader_ft_bind_func_table[] = { { - .index = SHADER_AFT_BLINN, + .index = SHADER_FT_BLINN, .bind_func = shader_bind_blinn, }, { - .index = SHADER_AFT_CLOTH, + .index = SHADER_FT_CLOTH, .bind_func = shader_bind_cloth, }, { - .index = SHADER_AFT_HAIR, + .index = SHADER_FT_HAIR, .bind_func = shader_bind_hair, }, { - .index = SHADER_AFT_MEMBRAN, + .index = SHADER_FT_MEMBRAN, .bind_func = shader_bind_membrane, }, { - .index = SHADER_AFT_EYEBALL, + .index = SHADER_FT_EYEBALL, .bind_func = shader_bind_eye_ball, }, { - .index = SHADER_AFT_TONEMAP, + .index = SHADER_FT_TONEMAP, .bind_func = shader_bind_tone_map, }, }; -static const size_t shader_aft_bind_func_table_size = - sizeof(shader_aft_bind_func_table) / sizeof(shader_bind_func); +static const size_t shader_ft_bind_func_table_size = + sizeof(shader_ft_bind_func_table) / sizeof(shader_bind_func); -void shader_aft_load(shader_set_data* set, farc* f, bool ignore_cache) { - shader_load(set, f, false, false, "aft", shader_aft_table, shader_aft_table_size, - shader_aft_bind_func_table, shader_aft_bind_func_table_size); +shader_set_data shaders_ft; + +glass_eye_struct glass_eye = { + { 5.0f, 5.0f, 0.5f, 0.5f }, + { 2.5f, 2.5f, 0.5f, 0.5f }, + 1.0f, + 1.45f, + 0.02f, + 0.85f, + { 1.0f, 1.2f, 0.45f }, + { 1.0f, 1.2f, 0.25f }, + { 0.5f, 0.6f, 0.4f }, + 0.2f, + { 1.0f, 1.0f, 1.0f }, + 0.0f, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f }, + 0.0, + { 0.0f, 0.0f, 0.0f }, + 0, + { 0.0f, 0.0f, 0.0f }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +void shader_ft_load(shader_set_data* set, farc* f, bool ignore_cache) { + shader_load(set, f, false, false, "ft", shader_ft_table, shader_ft_table_size, + shader_ft_bind_func_table, shader_ft_bind_func_table_size); +} + +static void glass_eye_calc(glass_eye_struct* glass_eye) { + float_t v2 = glass_eye->field_28; + glass_eye->field_64 = glass_eye->field_2C / v2; + glass_eye->field_90 = glass_eye->field_58; + vec3_mult_scalar(glass_eye->field_30, v2, glass_eye->field_68); + vec3_mult_scalar(glass_eye->field_3C, v2, glass_eye->field_74); + vec3_mult_scalar(glass_eye->field_48, v2, glass_eye->field_80); + glass_eye->field_8C = glass_eye->field_54 * v2; + if (glass_eye->field_B0 == 0) { + glass_eye->field_A0 = vec4u_null; + return; + } + + uint32_t frame = get_frame_counter(); + if (frame == glass_eye->frame) + return; + + glass_eye->frame = frame; + if (frame == (frame / 90) * 90) { + glass_eye->field_A0.x = ((float_t)(90.0 / (double_t)(frame % 90)) - 0.5f) * 0.015f; + glass_eye->field_A0.y = ((float_t)((double_t)(frame % 90) / 90.0) - 0.5f) * 0.015f; + //glass_eye->field_A0.x = (mt_random_get_float_value_by_rand_state_id(0) - 0.5f) * 0.015f; + //glass_eye->field_A0.y = (mt_random_get_float_value_by_rand_state_id(0) - 0.5f) * 0.015f; + } + + float_t v17 = (float_t)(uint8_t)frame * (float_t)(M_PI * (1.0 / 128.0)); + float_t v19 = sinf(sinf(v17 * 27.0f) + v17 * 2.0f); + float_t v20 = sinf(v17 * 23.0f); + glass_eye->field_A0.w = 0.0f; + glass_eye->field_A0.z = (v19 + v20) * 0.5f * 0.01f; +} + +static void glass_eye_set(glass_eye_struct* glass_eye, shader_set_data* set) { + vec4 temp; + vec3_mult(glass_eye->field_68, glass_eye->field_68, *(vec3*)&temp); + temp.w = temp.z; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_vert_set_ptr(set, 0x0A, &temp); + shader_local_frag_set_ptr(set, 0x0A, &temp); + + *(vec3*)&temp = glass_eye->field_68; + temp.w = 1.0f; + shader_local_vert_set_ptr(set, 0x0B, &temp); + shader_local_frag_set_ptr(set, 0x0B, &temp); + + vec4u_to_vec4(glass_eye->field_0, temp); + shader_local_vert_set_ptr(set, 0x0C, &temp); + vec4u_to_vec4(glass_eye->field_A0, temp); + shader_local_vert_set_ptr(set, 0x0D, &temp); + + vec3_mult(glass_eye->field_90, glass_eye->field_90, *(vec3*)&temp); + temp.w = temp.z; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_vert_set_ptr(set, 0x0E, &temp); + + vec4u_to_vec4(glass_eye->field_10, temp); + shader_local_vert_set_ptr(set, 0x0F, &temp); + + vec3_mult(glass_eye->field_68, glass_eye->field_68, *(vec3*)&temp); + temp.w = temp.z; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_vert_set_ptr(set, 0x0E, &temp); + + float_t v2 = (glass_eye->field_20 - glass_eye->field_24) / (glass_eye->field_20 + glass_eye->field_24); + v2 *= v2; + shader_local_frag_set(set, 0x0C, 1.0f - v2, v2, 0.0f, 0.0f); + + float_t v3 = (glass_eye->field_20 * glass_eye->field_20) / (glass_eye->field_24 * glass_eye->field_24); + shader_local_frag_set(set, 0x0D, v3, 1.0f - v3, glass_eye->field_20 / glass_eye->field_24, 0.0f); + + float_t v4 = (glass_eye->field_24 * glass_eye->field_24) / (glass_eye->field_20 * glass_eye->field_20); + shader_local_frag_set(set, 0x0E, 1.0f - v4, v4, glass_eye->field_24 / glass_eye->field_20, 0.0f); + + vec3_mult(glass_eye->field_74, glass_eye->field_74, *(vec3*)&temp); + temp.w = -1.0f; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_frag_set_ptr(set, 0x0F, &temp); + + vec3_mult(glass_eye->field_68, glass_eye->field_68, *(vec3*)&temp); + temp.w = -1.0f; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_frag_set_ptr(set, 0x10, &temp); + + vec3_mult(glass_eye->field_80, glass_eye->field_80, *(vec3*)&temp); + temp.w = -1.0f; + vec3_div(vec3_identity, *(vec3*)&temp, *(vec3*)&temp); + shader_local_frag_set_ptr(set, 0x11, &temp); + + vec2_mult(*(vec2*)&glass_eye->field_0, *(vec2*)&glass_eye->field_74, *(vec2*)&temp); + temp.y = glass_eye->field_64 * 1.442695f; + temp.w = glass_eye->field_8C; + vec2_div(vec2_identity, *(vec2*)&temp, *(vec2*)&temp); + shader_local_frag_set_ptr(set, 0x12, &temp); } static void shader_bind_blinn(shader_set_data* set, shader* shad) { shader_bind(shad, uniform_value[U_NORMAL] - ? SHADER_AFT_SUB_BLINN_FRAG : SHADER_AFT_SUB_BLINN_VERT); + ? SHADER_FT_SUB_BLINN_FRAG : SHADER_FT_SUB_BLINN_VERT); } static void shader_bind_cloth(shader_set_data* set, shader* shad) { - shader_bind(shad, uniform_value[U_NPR] ? SHADER_AFT_SUB_CLOTH_NPR1 - : (uniform_value[U_ANISO] ? SHADER_AFT_SUB_CLOTH_ANISO : SHADER_AFT_SUB_CLOTH_DEFAULT)); + shader_bind(shad, uniform_value[U_NPR] ? SHADER_FT_SUB_CLOTH_NPR1 + : (uniform_value[U_ANISO] ? SHADER_FT_SUB_CLOTH_ANISO : SHADER_FT_SUB_CLOTH_DEFAULT)); } static void shader_bind_hair(shader_set_data* set, shader* shad) { - shader_bind(shad, uniform_value[U_NPR] ? SHADER_AFT_SUB_HAIR_NPR1 - : (uniform_value[U_ANISO] ? SHADER_AFT_SUB_HAIR_ANISO : SHADER_AFT_SUB_HAIR_DEFAULT)); + shader_bind(shad, uniform_value[U_NPR] ? SHADER_FT_SUB_HAIR_NPR1 + : (uniform_value[U_ANISO] ? SHADER_FT_SUB_HAIR_ANISO : SHADER_FT_SUB_HAIR_DEFAULT)); } static void shader_bind_membrane(shader_set_data* set, shader* shad) { uniform_value[U_MEMBRANE] = 3; - if (shader_bind(shad, SHADER_AFT_SUB_MEMBRANE) < 0) + if (shader_bind(shad, SHADER_FT_SUB_MEMBRANE) < 0) return; /*uint32_t(* sub_140192E00)() = (void*)0x0000000140192E00; @@ -2361,21 +2537,18 @@ static void shader_bind_membrane(shader_set_data* set, shader* shad) { //vec4 vec = (vec4){ 1.0f, 0.0f, 0.0f, 0.0f }; //mat4_mult_vec(&mat, &vec, &vec); - //glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 10, vec.x, vec.y, vec.z, 0.0); + //shader_local_frag_set(set, 10, vec.x, vec.y, vec.z, 0.0f); } static void shader_bind_eye_ball(shader_set_data* set, shader* shader) { uniform_value[U18] = 0; - if (shader_bind(&set->shaders[SHADER_AFT_GLASEYE], SHADER_AFT_SUB_GLASS_EYE) >= 0) { - /*float_t glass_eye = (float*)0x0000000140CA2D70; - void (* glass_eye_calc)(float* glass_eye) = (void*)0x00000001405E53D0; - void (* glass_eye_set)(float* glass_eye) = (void*)0x00000001405E4750; - glass_eye_calc(glass_eye); - glass_eye_set(glass_eye);*/ + if (shader_bind(&set->shaders[SHADER_FT_GLASEYE], SHADER_FT_SUB_GLASS_EYE) >= 0) { + glass_eye_calc(&glass_eye); + glass_eye_set(&glass_eye, set); } } static void shader_bind_tone_map(shader_set_data* set, shader* shader) { shader_bind(shader, uniform_value[U_NPR] == 1 - ? SHADER_AFT_SUB_TONE_MAP_NPR1 : SHADER_AFT_SUB_TONE_MAP); + ? SHADER_FT_SUB_TONE_MAP_NPR1 : SHADER_FT_SUB_TONE_MAP); } diff --git a/src/CRE/shader_ft.h b/src/CRE/shader_ft.h new file mode 100644 index 00000000..021ca6f0 --- /dev/null +++ b/src/CRE/shader_ft.h @@ -0,0 +1,79 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "shader.h" + +typedef enum shader_ft_enum { + SHADER_FT_FFP = 0x00, + SHADER_FT_BLINN = 0x01, + SHADER_FT_ITEM = 0x02, + SHADER_FT_STAGE = 0x03, + SHADER_FT_SKIN = 0x04, + SHADER_FT_SSS_SKIN = 0x05, + SHADER_FT_SSS_FILT = 0x06, + SHADER_FT_HAIR = 0x07, + SHADER_FT_CLOTH = 0x08, + SHADER_FT_TIGHTS = 0x09, + SHADER_FT_SKY = 0x0A, + SHADER_FT_EYEBALL = 0x0B, + SHADER_FT_EYELENS = 0x0C, + SHADER_FT_GLASEYE = 0x0D, + SHADER_FT_MEMBRAN = 0x0E, + SHADER_FT_SHDMAP = 0x0F, + SHADER_FT_ESM = 0x10, + SHADER_FT_ESMGAUSS = 0x11, + SHADER_FT_ESMFILT = 0x12, + SHADER_FT_LITPROJ = 0x13, + SHADER_FT_SIMPLE = 0x14, + SHADER_FT_SIL = 0x15, + SHADER_FT_LAMBERT = 0x16, + SHADER_FT_CONSTANT = 0x17, + SHADER_FT_PEEL = 0x18, + SHADER_FT_TONEMAP = 0x19, + SHADER_FT_REDUCE = 0x1A, + SHADER_FT_MAGNIFY = 0x1B, + SHADER_FT_MLAA = 0x1C, + SHADER_FT_CONTOUR = 0x1D, + SHADER_FT_EXPOSURE = 0x1E, + SHADER_FT_GAUSS = 0x1F, + SHADER_FT_SUN = 0x20, + SHADER_FT_FADE = 0x21, + SHADER_FT_WATER01 = 0x22, + SHADER_FT_WATER02 = 0x23, + SHADER_FT_WATRING = 0x24, + SHADER_FT_W_PTCL = 0x25, + SHADER_FT_SNOW_PT = 0x26, + SHADER_FT_LEAF_PT = 0x27, + SHADER_FT_STAR = 0x28, + SHADER_FT_SNORING = 0x29, + SHADER_FT_SN_FOOT = 0x2A, + SHADER_FT_SN_TSL = 0x2B, + SHADER_FT_SN_NRM = 0x2C, + SHADER_FT_FLOOR = 0x2D, + SHADER_FT_PUDDLE = 0x2E, + SHADER_FT_S_REFL = 0x2F, + SHADER_FT_S_REFR = 0x30, + SHADER_FT_RIPEMIT = 0x31, + SHADER_FT_RAIN = 0x32, + SHADER_FT_VOLLIT = 0x33, + SHADER_FT_FENCE = 0x34, + SHADER_FT_RIPPLE = 0x35, + SHADER_FT_FOGPTCL = 0x36, + SHADER_FT_PARTICL = 0x37, + SHADER_FT_GLITTER_PT = 0x38, + SHADER_FT_SHOWVEC = 0x39, + SHADER_FT_FONT = 0x3A, + SHADER_FT_MOVIE = 0x3B, + SHADER_FT_IMGFILT = 0x3C, + SHADER_FT_SPRITE = 0x3D, + SHADER_FT_END = 0x3E, +} shader_ft_enum; + +extern shader_set_data shaders_ft; + +extern void shader_ft_load(shader_set_data* set, farc* f, bool ignore_cache); diff --git a/src/CRE/shader_glsl.c b/src/CRE/shader_glsl.c index 43f052f4..c23dbc18 100644 --- a/src/CRE/shader_glsl.c +++ b/src/CRE/shader_glsl.c @@ -84,7 +84,7 @@ static char* shader_parse(char* data, char* parse_string, const char* replace_st size_t len_a = def - data; def += utf8_length(parse_string); - size_t len_b = strlen(replace_string); + size_t len_b = utf8_length((char*)replace_string); size_t len_c = utf8_length(def); size_t len = len_a + len_b + len_c; @@ -122,7 +122,7 @@ static GLuint shader_compile(GLenum type, const char* data) { static GLint shader_get_uniform_location(GLint program, GLchar* name, vector_uint64_t* uniform_name_buf, vector_int32_t* uniform_location_buf) { - uint64_t hash = hash_utf8_fnv1a64(name); + uint64_t hash = hash_utf8_fnv1a64m(name); for (uint64_t* i = uniform_name_buf->begin; i != uniform_name_buf->end; i++) if (*i == hash) return uniform_location_buf->begin[i - uniform_name_buf->begin]; @@ -143,7 +143,7 @@ static GLint shader_get_uniform_location(GLint program, GLchar* name, static GLint shader_get_uniform_block_index(GLint program, GLchar* name, vector_uint64_t* uniform_block_name_buf, vector_int32_t* uniform_block_index_buf) { - uint64_t hash = hash_utf8_fnv1a64(name); + uint64_t hash = hash_utf8_fnv1a64m(name); for (uint64_t* i = uniform_block_name_buf->begin; i != uniform_block_name_buf->end; i++) if (*i == hash) return uniform_block_index_buf->begin[i - uniform_block_name_buf->begin]; @@ -168,10 +168,10 @@ void shader_glsl_load(shader_glsl* s, farc* f, shader_glsl_param* param) { if (s->program) glDeleteProgram(s->program); - vector_uint64_t_clear(&s->uniform_name_buf); - vector_int32_t_clear(&s->uniform_location_buf); - vector_uint64_t_clear(&s->uniform_block_name_buf); - vector_int32_t_clear(&s->uniform_block_index_buf); + vector_uint64_t_clear(&s->uniform_name_buf, 0); + vector_int32_t_clear(&s->uniform_location_buf, 0); + vector_uint64_t_clear(&s->uniform_block_name_buf, 0); + vector_int32_t_clear(&s->uniform_block_index_buf, 0); char temp[0x1000]; temp[0] = 0; @@ -248,10 +248,10 @@ void shader_glsl_load_file(shader_glsl* s, char* vert_path, if (!s || (!vert_path && !frag_path && !geom_path) || !param) return; - vector_uint64_t_clear(&s->uniform_name_buf); - vector_int32_t_clear(&s->uniform_location_buf); - vector_uint64_t_clear(&s->uniform_block_name_buf); - vector_int32_t_clear(&s->uniform_block_index_buf); + vector_uint64_t_clear(&s->uniform_name_buf, 0); + vector_int32_t_clear(&s->uniform_location_buf, 0); + vector_uint64_t_clear(&s->uniform_block_name_buf, 0); + vector_int32_t_clear(&s->uniform_block_index_buf, 0); stream st; size_t l; @@ -297,10 +297,10 @@ void shader_glsl_wload_file(shader_glsl* s, wchar_t* vert_path, if (!s || (!vert_path && !frag_path && !geom_path) || !param) return; - vector_uint64_t_clear(&s->uniform_name_buf); - vector_int32_t_clear(&s->uniform_location_buf); - vector_uint64_t_clear(&s->uniform_block_name_buf); - vector_int32_t_clear(&s->uniform_block_index_buf); + vector_uint64_t_clear(&s->uniform_name_buf, 0); + vector_int32_t_clear(&s->uniform_location_buf, 0); + vector_uint64_t_clear(&s->uniform_block_name_buf, 0); + vector_int32_t_clear(&s->uniform_block_index_buf, 0); stream st; size_t l; @@ -346,10 +346,10 @@ void shader_glsl_load_string(shader_glsl* s, char* vert, if (!s || (!frag && !vert && !geom) || !param) return; - vector_uint64_t_clear(&s->uniform_name_buf); - vector_int32_t_clear(&s->uniform_location_buf); - vector_uint64_t_clear(&s->uniform_block_name_buf); - vector_int32_t_clear(&s->uniform_block_index_buf); + vector_uint64_t_clear(&s->uniform_name_buf, 0); + vector_int32_t_clear(&s->uniform_location_buf, 0); + vector_uint64_t_clear(&s->uniform_block_name_buf, 0); + vector_int32_t_clear(&s->uniform_block_index_buf, 0); char* frag_data = str_utils_copy(frag); char* vert_data = str_utils_copy(vert); @@ -424,8 +424,8 @@ void shader_glsl_free(shader_glsl* s) { s->program = 0; } string_free(&s->name); - vector_uint64_t_free(&s->uniform_name_buf); - vector_int32_t_free(&s->uniform_location_buf); - vector_uint64_t_free(&s->uniform_block_name_buf); - vector_int32_t_free(&s->uniform_block_index_buf); + vector_uint64_t_free(&s->uniform_name_buf, 0); + vector_int32_t_free(&s->uniform_location_buf, 0); + vector_uint64_t_free(&s->uniform_block_name_buf, 0); + vector_int32_t_free(&s->uniform_block_index_buf, 0); } diff --git a/src/CRE/stage.c b/src/CRE/stage.c new file mode 100644 index 00000000..ce80f67b --- /dev/null +++ b/src/CRE/stage.c @@ -0,0 +1,287 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "stage.h" +#include "../KKdLib/str_utils.h" +#include "draw_task.h" + +void stage_init(stage* s) { + memset(s, 0, sizeof(stage)); +} + +void stage_load(stage* s, data_struct* data, auth_3d_database* auth_3d_db, object_database* obj_db, + texture_database* tex_db, stage_database* stage_data, char* name, render_context* rctx) { + if (!s || !stage_data || !name) + return; + + size_t name_len = utf8_length(name); + + s->modern = stage_data->modern; + s->display = true; + s->ring = true; + s->ground = true; + s->sky = true; + s->effects = true; + + string auth_3d_category = string_empty; + uint32_t auth_3d_count = 0; + uint32_t* auth_3d_ids = 0; + uint32_t render_texture = -1; + uint32_t movie_texture = -1; + s->light_param_name = 0; + if (!s->modern) { + s->stage = 0; + vector_stage_info* stage = &stage_data->stage; + for (stage_info* i = stage->begin; i != stage->end; i++) + if (!str_utils_compare_length(name, name_len + 1, + string_data(&i->name), i->name.length + 1)) { + string_copy(&i->auth_3d_name, &auth_3d_category); + s->stage = i; + auth_3d_count = i->auth_3d_count; + auth_3d_ids = i->auth_3d_ids; + render_texture = i->render_texture; + movie_texture = i->movie_texture; + s->light_param_name = light_param_get_string(string_data(&i->name)); + break; + } + + if (!s->stage) + return; + } + else { + s->stage_modern = 0; + vector_stage_info_modern* stage = &stage_data->stage_modern; + for (stage_info_modern* i = stage->begin; i != stage->end; i++) + if (!str_utils_compare_length(name, name_len + 1, + string_data(&i->name), i->name.length + 1)) { + string_copy(&i->auth_3d_name, &auth_3d_category); + s->stage_modern = i; + auth_3d_count = i->auth_3d_count; + auth_3d_ids = i->auth_3d_ids; + render_texture = i->render_texture; + movie_texture = i->movie_texture; + s->light_param_name = light_param_get_string(string_data(&i->name)); + break; + } + + if (!s->stage_modern) + return; + } + + light_param_storage_load_light_param_data(data, s->light_param_name); + + auth_3d_database_uid* uids = auth_3d_db->uid.begin; + if (auth_3d_category.length) { + for (auth_3d_database_category* i = auth_3d_db->category.begin; i != auth_3d_db->category.end; i++) { + if (str_utils_compare_length(string_data(&i->name), i->name.length, + string_data(&auth_3d_category), auth_3d_category.length)) + continue; + else if (i->name.length > auth_3d_category.length + && string_data(&i->name)[auth_3d_category.length] != 'S') + continue; + + string auth_3d_farc; + string_copy(&i->name, &auth_3d_farc); + string_add_length(&auth_3d_farc, ".farc", 5); + + farc f; + farc_init(&f); + data_struct_load_file(data, &f, "rom\\auth_3d\\", string_data(&auth_3d_farc), farc_load_file); + string_free(&auth_3d_farc); + + if (!(f.files.end - f.files.begin)) { + farc_free(&f); + continue; + } + + for (int32_t* j = i->uid.begin; j != i->uid.end; j++) + for (uint32_t k = 0; k < auth_3d_count; k++) { + if (uids[*j].enabled && uids[*j].org_uid != auth_3d_ids[k]) + continue; + + string auth_3d_file; + string_copy(&uids[*j].category, &auth_3d_file); + string_add_length(&auth_3d_file, ".a3da", 5); + + farc_file* ff = farc_read_file(&f, string_data(&auth_3d_file)); + + if (!ff || !ff->data || !ff->size) { + string_free(&auth_3d_file); + continue; + } + + a3da a3da_file; + a3da_init(&a3da_file); + a3da_mread(&a3da_file, ff->data, ff->size); + if (!a3da_file.ready) { + a3da_free(&a3da_file); + string_free(&auth_3d_file); + continue; + } + + int32_t id = auth_3d_data_load_uid(uids[*j].org_uid, auth_3d_db); + auth_3d* auth = auth_3d_data_get_auth_3d(id); + if (auth) { + auth_3d_load(auth, &a3da_file, obj_db, tex_db); + vector_int32_t_push_back(&s->auth_3d_ids, &id); + } + a3da_free(&a3da_file); + + string_free(&auth_3d_file); + } + + farc_free(&f); + break; + } + } + string_free(&auth_3d_category); + + char set_name[11]; + set_name[0] = 0; + if (!str_utils_compare_length(name, name_len, "STGPV", 5)) { + memcpy(set_name, name, 8); + set_name[8] = 0; + + } + else if(!str_utils_compare_length(name, name_len, "STGD2PV", 7)) { + memcpy(set_name, name, 10); + set_name[10] = 0; + } + + object_set_info* set_info; + s->set_id = -1; + if (set_name[0] && object_database_get_object_set_info(obj_db, set_name, &set_info)) { + s->set_id = set_info->id; + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + } + + s->stage_set_id = -1; + if (object_database_get_object_set_info(obj_db, name, &set_info)) { + s->stage_set_id = set_info->id; + object_set_load_by_db_index(&set_info, data, obj_db, set_info->id); + } + + if (render_texture != -1) + post_process_render_texture_set(&rctx->post_process, + texture_storage_get_texture(render_texture), 0); + + if (movie_texture != -1) + post_process_movie_texture_set(&rctx->post_process, + texture_storage_get_texture(movie_texture)); +} + +void stage_set(stage* s, render_context* rctx) { + if (!s || !rctx || s == rctx->stage) + return; + + rctx->stage = s; + render_context_set_light_param(rctx, + light_param_storage_get_light_param_data(s->light_param_name)); +} + +void stage_update(stage* s, render_context* rctx) { + if (!s || s->modern || !s->stage) + return; + + stage_info* info = s->stage; + + if (s->effects) { + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { + auth_3d* auth = auth_3d_data_get_auth_3d(*i); + if (auth) + auth_3d_get_value(auth, (mat4*)&mat4_identity, get_delta_frame()); + } + } + + if (!s->display) + return; + + if (s->ground) + draw_task_add_draw_object_by_object_info_opaque(rctx, + (mat4*)&mat4_identity, info->object_ground); + + if (s->sky) + draw_task_add_draw_object_by_object_info_opaque(rctx, + (mat4*)&mat4_identity, info->object_sky); + + if (s->effects) { + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { + auth_3d* auth = auth_3d_data_get_auth_3d(*i); + if (auth) + auth_3d_data_set(auth, (mat4*)&mat4_identity, rctx); + } + } +} + +void stage_update_modern(stage* s, render_context* rctx) { + if (!s || !s->modern || !s->stage_modern) + return; + + stage_info_modern* info = s->stage_modern; + + if (s->effects) { + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { + auth_3d* auth = auth_3d_data_get_auth_3d(*i); + if (auth) + auth_3d_get_value(auth, (mat4*)&mat4_identity, get_delta_frame()); + } + } + + if (!s->display) + return; + + if (s->ground) + draw_task_add_draw_object_by_object_info_opaque(rctx, + (mat4*)&mat4_identity, info->object_ground); + + if (s->sky) + draw_task_add_draw_object_by_object_info_opaque(rctx, + (mat4*)&mat4_identity, info->object_sky); + + if (s->effects) { + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) { + auth_3d* auth = auth_3d_data_get_auth_3d(*i); + if (auth) + auth_3d_data_set(auth, (mat4*)&mat4_identity, rctx); + } + } +} + +void stage_free(stage* s, render_context* rctx) { + uint32_t render_texture = -1; + uint32_t movie_texture = -1; + if (!s->modern && s->stage) { + stage_info* info = s->stage; + render_texture = info->render_texture; + movie_texture = info->movie_texture; + + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) + auth_3d_data_unload_id(*i, rctx); + vector_int32_t_free(&s->auth_3d_ids, 0); + } + else if (s->modern && s->stage_modern) { + stage_info_modern* info = s->stage_modern; + render_texture = info->render_texture; + movie_texture = info->movie_texture; + + for (int32_t* i = s->auth_3d_ids.begin; i != s->auth_3d_ids.end; i++) + auth_3d_data_unload_id(*i, rctx); + vector_int32_t_free(&s->auth_3d_ids, 0); + } + + if (render_texture != -1) + post_process_render_texture_free(&rctx->post_process, + texture_storage_get_texture(render_texture), false); + + if (movie_texture != -1) + post_process_movie_texture_free(&rctx->post_process, + texture_storage_get_texture(movie_texture)); + + object_storage_delete_object_set(s->set_id); + object_storage_delete_object_set(s->stage_set_id); + free(s->light_param_name); + + rctx->stage = 0; +} diff --git a/src/CRE/stage.h b/src/CRE/stage.h new file mode 100644 index 00000000..b29f8443 --- /dev/null +++ b/src/CRE/stage.h @@ -0,0 +1,39 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/database/stage.h" +#include "render_context.h" +#include "auth_3d.h" + +typedef struct stage { + union { + stage_info* stage; + stage_info_modern* stage_modern; + }; + + bool modern; + bool display; + bool ring; + bool ground; + bool sky; + bool effects; + + uint32_t set_id; + uint32_t stage_set_id; + char* light_param_name; + vector_int32_t auth_3d_ids; +} stage; + +extern void stage_init(stage* s); +extern void stage_load(stage* s, data_struct* data, auth_3d_database* auth_3d_db, object_database* obj_db, + texture_database* tex_db, stage_database* stage_data, char* name, render_context* rctx); +extern void stage_set(stage* s, render_context* rctx); +extern void stage_update(stage* s, render_context* rctx); +extern void stage_update_modern(stage* s, render_context* rctx); +extern void stage_free(stage* s, render_context* rctx); diff --git a/src/CRE/static_var.c b/src/CRE/static_var.c index bcb9e35f..fe059d0a 100644 --- a/src/CRE/static_var.c +++ b/src/CRE/static_var.c @@ -6,6 +6,8 @@ #include "static_var.h" #include "timer.h" +extern timer render_timer; + int32_t sv_max_texture_buffer_size = 0x100000; int32_t sv_max_texture_size = 2048; int32_t sv_max_texture_max_anisotropy = 1; @@ -14,19 +16,15 @@ bool sv_anisotropy_changed = false; int32_t sv_old_anisotropy = 1; int32_t sv_anisotropy = 1; -bool sv_fxaa_changed = false; -bool sv_old_fxaa = false; -bool sv_fxaa = false; +size_t frame_counter = 0; -bool sv_fxaa_preset_changed = false; -int32_t sv_old_fxaa_preset = 5; -int32_t sv_fxaa_preset = 5; +bool select_frame_speed = true; +float_t frame_speed = 1.0f; +float_t target_fps = 60.0f; +float_t current_fps = 60.0f; int32_t uniform_value[U_MAX]; -bool select_frame_speed = false; -float_t frame_speed = 1.0f; - const vec3 sv_rgb_to_luma = { 0.2126f, 0.7152f, 0.0722f }; @@ -50,58 +48,33 @@ void sv_anisotropy_set(int32_t value) { sv_old_anisotropy = sv_anisotropy; } -void sv_fxaa_set(bool value) { - sv_fxaa = value; - if (sv_fxaa != sv_old_fxaa) - sv_fxaa_changed = true; - sv_old_fxaa = sv_fxaa; -} - -void sv_fxaa_preset_set(int32_t value) { - sv_fxaa_preset = clamp(value, 3, 5); - if (sv_fxaa_preset != sv_old_fxaa_preset) - sv_fxaa_changed = true; - sv_old_fxaa_preset = sv_fxaa_preset; -} - -extern timer render_timer; - -float_t get_frame_speed() { +float_t get_delta_frame() { if (!select_frame_speed) return frame_speed; - double_t freq = timer_get_freq(&render_timer); - double_t freq_hist = timer_get_freq_hist(&render_timer); - return (float_t)(min(freq / freq_hist, 1.0) * frame_speed); + double_t freq_ratio = timer_get_freq_ratio(&render_timer); + return (float_t)(freq_ratio * frame_speed); } -typedef union vertex_shader_data { - struct { - vec4 position; - vec4 weight; - vec4 normal; - vec4 color; - vec4 color1; - vec4 fogcoord; - vec4 attrib6; - vec4 attrib7; - union { - struct { - vec4 texcoord0; - vec4 texcoord1; - vec4 texcoord2; - vec4 texcoord3; - vec4 texcoord4; - vec4 texcoord5; - vec4 texcoord6; - vec4 texcoord7; - }; - vec4 texcoord[8]; - }; - }; - vec4 attrib[16]; -} vertex_shader_data; +uint32_t get_frame_counter() { + return (uint32_t)frame_counter; +} -GLuint vertex_shader_vao; -GLuint vertex_shader_vbo; -vertex_shader_data vertex_shader[]; +void uniform_value_reset() { + uniform_value[U_ANISO] = 0; + uniform_value[U0B] = 0; + uniform_value[U_TEXTURE_BLEND] = 0; + uniform_value[U_FOG_HEIGHT] = 0; + uniform_value[U_FOG] = 0; + uniform_value[U_SPECULAR_IBL] = 0; + uniform_value[U_TEX_0_TYPE] = 0; + uniform_value[U_TEX_1_TYPE] = 0; + uniform_value[U_TEXTURE_COUNT] = 0; + uniform_value[U_ENV_MAP] = 0; + uniform_value[U_TRANSLUCENCY] = 0; + uniform_value[U_NORMAL] = 0; + uniform_value[U_TRANSPARENCY] = 0; + uniform_value[U_LIGHT_0] = 0; + uniform_value[U_SPECULAR] = 0; + uniform_value[U45] = 0; +} diff --git a/src/CRE/static_var.h b/src/CRE/static_var.h index 9aed7d88..59e57f27 100644 --- a/src/CRE/static_var.h +++ b/src/CRE/static_var.h @@ -6,26 +6,18 @@ #pragma once #include "../KKdLib/default.h" -#include "../KKdLib/vec.h" +#include "../KKdLib/light_param/fog.h" +#include "../KKdLib/light_param/light.h" #include "../KKdLib/mat.h" +#include "../KKdLib/vec.h" #include -typedef enum alpha_pass_type { - ALPHA_PASS_OPAQUE = 0, - ALPHA_PASS_TRANSLUCENT = 1, - ALPHA_PASS_TRANSPARENT = 2, -} alpha_pass_type; - -typedef enum fog_type { - FOG_NONE = 0, - FOG_NORMAL = 1, - FOG_HEIGHT = 2, -} fog_type; - -typedef struct object_info { - uint16_t id; - uint16_t set_id; -} object_info; +typedef enum draw_pass_3d_type { + DRAW_PASS_3D_OPAQUE = 0, + DRAW_PASS_3D_TRANSLUCENT = 1, + DRAW_PASS_3D_TRANSPARENT = 2, + DRAW_PASS_3D_MAX = 3, +} draw_pass_3d_type; typedef enum uniform_name { U_NONE = 0x00, @@ -70,7 +62,7 @@ typedef enum uniform_name { U_NPR = 0x27, U_LIGHT_1 = 0x28, U_REFLECT = 0x29, - U2A = 0x2A, + U_REDUCE = 0x2A, U_SELF_SHADOW = 0x2B, U_SHADOW = 0x2C, U2D = 0x2D, @@ -109,24 +101,13 @@ extern int32_t sv_max_texture_max_anisotropy; extern bool sv_anisotropy_changed; extern int32_t sv_anisotropy; -extern bool sv_fxaa_changed; -extern bool sv_fxaa; - -extern bool sv_fxaa_preset_changed; -extern int32_t sv_fxaa_preset; - extern int32_t uniform_value[]; -extern float_t frame_speed; -extern float_t target_fps; -extern float_t current_fps; - extern const vec3 sv_rgb_to_luma; extern const mat3 sv_rgb_to_ypbpr; extern const mat3 sv_ypbpr_to_rgb; extern void sv_anisotropy_set(int32_t value); -extern void sv_fxaa_set(bool value); -extern void sv_fxaa_preset_set(int32_t value); - -extern float_t get_frame_speed(); +extern float_t get_delta_frame(); +extern uint32_t get_frame_counter(); +extern void uniform_value_reset(); diff --git a/src/CRE/texture.c b/src/CRE/texture.c index fdeb431b..89e51100 100644 --- a/src/CRE/texture.c +++ b/src/CRE/texture.c @@ -9,37 +9,38 @@ #include "gl_state.h" #include "static_var.h" -static const GLenum target_cube_map_array[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, -}; +vector_func(texture) +vector_ptr_func(texture) static void texture_get_format_type_by_internal_format(GLenum internal_format, GLenum* format, GLenum* type); static int32_t texture_get_size(GLenum internal_format, int32_t width, int32_t height); static int32_t texture_load(GLenum target, GLenum internal_format, int32_t width, int32_t height, int32_t level, void* data); -static texture* texture_load_tex(GLenum target, +static texture* texture_load_tex(uint32_t id, GLenum target, GLenum internal_format, int32_t width, int32_t height, int32_t max_mipmap_level, void** data_ptr, bool use_high_anisotropy); static void texture_set_params(GLenum target, int32_t max_mipmap_level, bool use_high_anisotropy); static GLenum texture_txp_get_internal_format(txp* t); -vector_ptr_func(texture) +vector_ptr_texture texture_storage_data; -texture* texture_load_tex_2d(GLenum internal_format, int32_t width, int32_t height, +texture* texture_init(uint32_t id) { + return texture_storage_create_texture(id); +} + +texture* texture_load_tex_2d(uint32_t id, GLenum internal_format, int32_t width, int32_t height, int32_t max_mipmap_level, void** data_ptr, bool use_high_anisotropy) { - return texture_load_tex(GL_TEXTURE_2D, internal_format, + return texture_load_tex(id, GL_TEXTURE_2D, internal_format, width, height, max_mipmap_level, data_ptr, use_high_anisotropy); } -texture* texture_load_tex_cube_map(GLenum internal_format, int32_t width, int32_t height, +texture* texture_load_tex_cube_map(uint32_t id, GLenum internal_format, int32_t width, int32_t height, int32_t max_mipmap_level, void** data_ptr) { - return texture_load_tex(GL_TEXTURE_CUBE_MAP, internal_format, + return texture_load_tex(id, GL_TEXTURE_CUBE_MAP, internal_format, width, height, max_mipmap_level, data_ptr, false); } -texture* texture_txp_load(txp* t) { +texture* texture_txp_load(txp* t, uint32_t id) { if (!t || !t->data.begin) return 0; @@ -53,30 +54,79 @@ texture* texture_txp_load(txp* t) { int32_t width = t->data.begin->width; int32_t height = t->data.begin->height; int32_t max_mipmap_level = t->mipmaps_count - 1; + texture* tex; if (t->has_cube_map) - tex = texture_load_tex_cube_map(internal_format, width, height, max_mipmap_level, data_ptr); + tex = texture_load_tex_cube_map(id, internal_format, width, height, max_mipmap_level, data_ptr); else - tex = texture_load_tex_2d(internal_format, width, height, max_mipmap_level, data_ptr, true); + tex = texture_load_tex_2d(id, internal_format, width, height, max_mipmap_level, data_ptr, true); free(data_ptr); return tex; } -void texture_dispose(texture* tex) { - glDeleteTextures(1, &tex->texture); - free(tex); +void texture_free(texture* tex) { + texture_storage_delete_texture(tex->id); } -bool texture_txp_set_load(vector_txp* t, vector_ptr_texture* tex) { - if (!t || !tex) +bool texture_txp_set_load(txp_set* t, texture*** texs, uint32_t* ids) { + if (!t || !texs || !ids) return false; - vector_ptr_texture_reserve(tex, t->end - t->begin); - for (txp* i = t->begin; i != t->end; i++) { - texture* temp = texture_txp_load(i); - vector_ptr_texture_push_back(tex, &temp); - } - return tex->end - tex->begin > 0 ? true : false; + size_t count = t->end - t->begin; + *texs = force_malloc_s(texture*, count + 1); + texture** tex = *texs; + for (size_t i = 0; i < count; i++) + tex[i] = texture_txp_load(&t->begin[i], ids[i]); + tex[count] = 0; + return true; +} + +inline void texture_storage_init() { + texture_storage_data = vector_ptr_empty(texture); +} + +inline texture* texture_storage_create_texture(uint32_t id) { + for (texture** i = texture_storage_data.begin; i != texture_storage_data.end; i++) + if (*i && (*i)->id == id) { + (*i)->init_count++; + return *i; + } + + texture** tex = vector_ptr_texture_reserve_back(&texture_storage_data); + *tex = force_malloc(sizeof(texture)); + (*tex)->init_count = 1; + (*tex)->id = id; + return *tex; +} + +inline texture* texture_storage_get_texture(uint32_t id) { + for (texture** i = texture_storage_data.begin; i != texture_storage_data.end; i++) + if (*i && (*i)->id == id) + return *i; + return 0; +} + +inline void texture_storage_delete_texture(uint32_t id) { + for (texture** i = texture_storage_data.begin; i != texture_storage_data.end; i++) + if (*i && (*i)->id == id) { + texture* tex = *i; + if (tex->init_count > 1) { + tex->init_count--; + break; + } + + glDeleteTextures(1, &tex->texture); + vector_ptr_texture_erase(&texture_storage_data, + i - texture_storage_data.begin, 0); + break; + } +} + +inline void texture_storage_free() { + for (texture** i = texture_storage_data.begin; i != texture_storage_data.end; i++) + if (*i) + glDeleteTextures(1, &(*i)->texture); + vector_ptr_texture_free(&texture_storage_data, 0); } static void texture_get_format_type_by_internal_format(GLenum internal_format, GLenum* format, GLenum* type) { @@ -261,10 +311,13 @@ static int32_t texture_load(GLenum target, GLenum internal_format, return -(glGetError() != GL_ZERO); } -static texture* texture_load_tex(GLenum target, +static texture* texture_load_tex(uint32_t id, GLenum target, GLenum internal_format, int32_t width, int32_t height, int32_t max_mipmap_level, void** data_ptr, bool use_high_anisotropy) { - texture* tex = force_malloc(sizeof(texture)); + texture* tex = texture_init(id); + if (tex->init_count > 1) + return tex; + glGenTextures(1, &tex->texture); switch (target) { case GL_TEXTURE_2D: @@ -304,22 +357,27 @@ static texture* texture_load_tex(GLenum target, int32_t size = 0; if (target == GL_TEXTURE_CUBE_MAP) - for (int32_t i = 0; i < 6; i++) { + for (int32_t i = 0; i < 6; i++) for (int32_t j = 0; j <= max_mipmap_level; j++) { - int32_t mip_width = max(width >> i, 1); - int32_t mip_height = max(height >> i, 1); + int32_t mip_width = max(width >> j, 1); + int32_t mip_height = max(height >> j, 1); void* data; if (data_ptr) data = data_ptr[i * (max_mipmap_level + 1) + j]; else data = 0; + static const GLenum target_cube_map_array[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + }; + if (texture_load(target_cube_map_array[i], - internal_format, mip_width, mip_height, i, data) < 0) + internal_format, mip_width, mip_height, j, data) < 0) goto fail; size += texture_get_size(internal_format, mip_width, mip_height); } - } else for (int32_t i = 0; i <= max_mipmap_level; i++) { int32_t mip_width = max(width >> i, 1); @@ -377,8 +435,7 @@ fail: gl_state_bind_texture_cube_map(0); break; } - glDeleteTextures(1, &tex->texture); - free(tex); + texture_free(tex); return 0; } diff --git a/src/CRE/texture.h b/src/CRE/texture.h index b9b48cee..d54045d2 100644 --- a/src/CRE/texture.h +++ b/src/CRE/texture.h @@ -7,6 +7,7 @@ #include "../KKdLib/default.h" #include "../KKdLib/txp.h" +#include "../KKdLib/vector.h" #include typedef enum texture_flags { @@ -14,8 +15,8 @@ typedef enum texture_flags { } texture_flags; typedef struct texture { - int32_t field_0; - int32_t field_4; + int32_t init_count; + int32_t id; texture_flags flags; int16_t width; int16_t height; @@ -26,13 +27,23 @@ typedef struct texture { int32_t size; } texture; +vector(texture) vector_ptr(texture) -extern texture* texture_load_tex_2d(GLenum internal_format, int32_t width, int32_t height, - int32_t max_mipmap_level, void** data_ptr, bool use_high_anisotropy); -extern texture* texture_load_tex_cube_map(GLenum internal_format, int32_t width, int32_t height, - int32_t max_mipmap_level, void** data_ptr); -extern texture* texture_txp_load(txp* t); -extern void texture_dispose(texture* tex); +#define texture_make_id(id, index) ((uint32_t)((id << 24) | (index & 0xFFFFFF))) -extern bool texture_txp_set_load(vector_txp* t, vector_ptr_texture* tex); +extern texture* texture_init(uint32_t id); +extern texture* texture_load_tex_2d(uint32_t id, GLenum internal_format, int32_t width, int32_t height, + int32_t max_mipmap_level, void** data_ptr, bool use_high_anisotropy); +extern texture* texture_load_tex_cube_map(uint32_t id, GLenum internal_format, int32_t width, int32_t height, + int32_t max_mipmap_level, void** data_ptr); +extern texture* texture_txp_load(txp* t, uint32_t id); +extern void texture_free(texture* tex); + +extern bool texture_txp_set_load(txp_set* t, texture*** texs, uint32_t* ids); + +extern void texture_storage_init(); +extern texture* texture_storage_create_texture(uint32_t id); +extern texture* texture_storage_get_texture(uint32_t id); +extern void texture_storage_delete_texture(uint32_t id); +extern void texture_storage_free(); diff --git a/src/CRE/time.c b/src/CRE/time.c index 2398ead7..8cf6ecdb 100644 --- a/src/CRE/time.c +++ b/src/CRE/time.c @@ -5,20 +5,30 @@ #include "time.h" -extern LARGE_INTEGER performance_frequency; -extern double_t inv_performance_frequency_msec; -extern double_t inv_performance_frequency_sec; +static double_t time_struct_get_freq(); + +inline void time_struct_init(time_struct* t) { + if (!QueryPerformanceCounter(&t->timestamp)) + t->timestamp.QuadPart = 0; + t->inv_freq = time_struct_get_freq(); +} inline double_t time_struct_calc_time(time_struct* t) { LARGE_INTEGER timestamp; if (!QueryPerformanceCounter(×tamp)) return 0; - return (double_t)(timestamp.QuadPart - t->timestamp.QuadPart) - * inv_performance_frequency_msec; + return (double_t)(timestamp.QuadPart - t->timestamp.QuadPart) * t->inv_freq; } inline void time_struct_get_timestamp(time_struct* t) { if (!QueryPerformanceCounter(&t->timestamp)) t->timestamp.QuadPart = 0; } + +static double_t time_struct_get_freq() { + LARGE_INTEGER freq; + if (QueryPerformanceFrequency(&freq)) + return 1000.0 / (double_t)freq.LowPart; + return 0.0; +} diff --git a/src/CRE/time.h b/src/CRE/time.h index ba9b992c..affd3299 100644 --- a/src/CRE/time.h +++ b/src/CRE/time.h @@ -9,7 +9,9 @@ typedef struct time_struct { LARGE_INTEGER timestamp; -} time_struct; + double_t inv_freq; +}time_struct; +extern void time_struct_init(time_struct* t); extern double_t time_struct_calc_time(time_struct* t); extern void time_struct_get_timestamp(time_struct* t); diff --git a/src/CRE/timer.c b/src/CRE/timer.c index f968bbce..0c3661b0 100644 --- a/src/CRE/timer.c +++ b/src/CRE/timer.c @@ -5,25 +5,22 @@ #include "timer.h" -LARGE_INTEGER performance_frequency; -double_t inv_performance_frequency_msec; -double_t inv_performance_frequency_sec; - inline void timer_init(timer* t, double_t freq) { - memset(t->history, 0, sizeof(double_t) * HISTORY_COUNT); + for (size_t i = 0; i < HISTORY_COUNT; i++) + t->history[i] = freq; t->history_counter = 0; - t->curr_time.QuadPart = 0; - t->prev_time.QuadPart = 0; + time_struct_init(&t->curr_time); + time_struct_init(&t->prev_time); t->freq = freq; - t->freq_hist = 0.0; + t->freq_hist = freq; lock_init(&t->freq_lock); lock_init(&t->freq_hist_lock); - t->timer = create_timer(); + t->timer = timer_handle_init(); } inline void timer_start_of_cycle(timer* t) { - double_t time = timer_get_msec(t->prev_time); - QueryPerformanceCounter(&t->prev_time); + double_t time = time_struct_calc_time(&t->prev_time); + time_struct_get_timestamp(&t->prev_time); double_t freq = 0; for (uint8_t i = 0; i < t->history_counter; i++) freq += t->history[i]; @@ -39,8 +36,8 @@ inline void timer_start_of_cycle(timer* t) { } inline void timer_end_of_cycle(timer* t) { - double_t msec = 1000.0 / timer_get_freq(t) - timer_get_msec(t->prev_time); - msleep(t->timer, msec); + double_t msec = 1000.0 / timer_get_freq(t) - time_struct_calc_time(&t->prev_time); + timer_handle_sleep(t->timer, msec); } inline double_t timer_get_freq(timer* t) { @@ -65,28 +62,37 @@ inline double_t timer_get_freq_hist(timer* t) { return freq; } +inline double_t timer_get_freq_ratio(timer* t) { + double_t freq = 0.0; + lock_lock(&t->freq_lock); + freq = t->freq; + lock_unlock(&t->freq_lock); + lock_lock(&t->freq_hist_lock); + freq /= t->freq_hist; + lock_unlock(&t->freq_hist_lock); + return freq; +} + +inline void timer_reset(timer* t) { + time_struct_get_timestamp(&t->curr_time); + time_struct_get_timestamp(&t->prev_time); +} + +inline void timer_sleep(timer* t, double_t msec) { + timer_handle_sleep(t->timer, msec); +} + inline void timer_dispose(timer* t) { lock_free(&t->freq_lock); lock_free(&t->freq_hist_lock); - dispose_timer(t->timer); + timer_handle_dispose(t->timer); } -inline double_t timer_get_msec(LARGE_INTEGER t) { - LARGE_INTEGER curr_time; - QueryPerformanceCounter(&curr_time); - return (curr_time.QuadPart - t.QuadPart) * inv_performance_frequency_msec; -} - -inline HANDLE create_timer() { +inline HANDLE timer_handle_init() { return CreateWaitableTimerW(0, 0, 0); } -inline void dispose_timer(HANDLE timer) { - if (timer) - CloseHandle(timer); -} - -inline void msleep(HANDLE timer, double_t msec) { +inline void timer_handle_sleep(HANDLE timer, double_t msec) { if (msec <= 0.0) return; @@ -102,3 +108,8 @@ inline void msleep(HANDLE timer, double_t msec) { Sleep(msec_dw); } } + +inline void timer_handle_dispose(HANDLE timer) { + if (timer) + CloseHandle(timer); +} diff --git a/src/CRE/timer.h b/src/CRE/timer.h index 09cd850f..32b3c682 100644 --- a/src/CRE/timer.h +++ b/src/CRE/timer.h @@ -7,14 +7,15 @@ #include "../KKdLib/default.h" #include "lock.h" +#include "time.h" #define HISTORY_COUNT 0x08 typedef struct timer { double_t history[HISTORY_COUNT]; uint8_t history_counter; - LARGE_INTEGER curr_time; - LARGE_INTEGER prev_time; + time_struct curr_time; + time_struct prev_time; double_t freq; double_t freq_hist; lock freq_lock; @@ -30,9 +31,11 @@ extern void timer_end_of_cycle(timer* t); extern double_t timer_get_freq(timer* t); extern void timer_set_freq(timer* t, double_t freq); extern double_t timer_get_freq_hist(timer* t); +extern double_t timer_get_freq_ratio(timer* t); +extern void timer_reset(timer* t); +extern void timer_sleep(timer* t, double_t msec); extern void timer_dispose(timer* t); -extern double_t timer_get_msec(LARGE_INTEGER t); -extern HANDLE create_timer(); -extern void dispose_timer(HANDLE timer); -extern void msleep(HANDLE timer, double_t msec); +extern HANDLE timer_handle_init(); +extern void timer_handle_sleep(HANDLE timer, double_t msec); +extern void timer_handle_dispose(HANDLE timer); diff --git a/src/CRE/vertex.c b/src/CRE/vertex.c deleted file mode 100644 index d76bf79a..00000000 --- a/src/CRE/vertex.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "vertex.h" -#include "../KKdLib/half_t.h" -#include "../KKdLib/hash.h" -#include "../KKdLib/vector.h" -#include "../CRE/static_var.h" -#include - -vector(obj_vertex_data) - -static void vertex_data_load(vertex* v, vertex_data* data, obj_vertex_data* verts, size_t index); -static void vertex_data_store(vertex* v, obj_vertex_data* verts, size_t index); - -void vertex_init(vertex* v) { - v->vbo = 0; - v->ebo = 0; -} - -void vertex_load(vertex* v, vertex_data* data) { - if (!v || !data) - return; - - vertex_free(v); - - if (!data->vert || !data->count || !data->morph_count) - return; - - v->type = VERTEX_SIMPLE; - v->translucent = false; - size_t count = data->count; - size_t morph_count = data->morph_count; - obj_vertex_data* verts = force_malloc_s(obj_vertex_data, count * morph_count); - for (size_t i = 0; i < morph_count; i++) { - vertex_data_load(v, data, verts, i); - if (~data->flags & OBJ_VERTEX_NORMAL - || data->flags & OBJ_VERTEX_TANGENT - || data->primitive != VERTEX_PRIMITIVE_TRIANGLE) - continue; - - size_t offset = count * i; - size_t count_clamp = count / 3 * 3; - for (size_t j = 0; j < count_clamp; j += 3) { - obj_vertex_data* vert = &verts[j + offset]; - vec2 uv0, uv1; - vec2_sub(vert[1].texcoord0, vert[0].texcoord0, uv0); - vec2_sub(vert[2].texcoord0, vert[0].texcoord0, uv1); - - vec3 edge0; - vec3 edge1; - vec3_sub(vert[1].position, vert[0].position, edge0); - vec3_sub(vert[2].position, vert[0].position, edge1); - - vec3 t0, t1, t; - vec3_mult_scalar(edge0, uv1.y, t0); - vec3_mult_scalar(edge1, uv0.y, t1); - vec3_sub(t0, t1, t); - vec3_normalize(t, t); - - vec3 b0, b1, b; - vec3_mult_scalar(edge1, uv0.x, b0); - vec3_mult_scalar(edge0, uv1.x, b1); - vec3_sub(b0, b1, b); - vec3_normalize(b, b); - - for (int32_t k = 0; k < 3; k++) { - vec3 temp; - float_t direction; - vec3_cross(vert[k].normal, t, temp); - vec3_normalize(temp, temp); - vec3_dot(temp, b, direction); - *(vec3*)&vert[k].tangent = t; - if (direction >= 0.0f) - vert[k].tangent.w = 1.0f; - else - vert[k].tangent.w = -1.0f; - } - } - } - v->ind_count = count; - v->ind = force_malloc_s(uint32_t, v->ind_count); - - vector_obj_vertex_data vert_list = vector_empty(obj_vertex_data); - vector_obj_vertex_data_reserve(&vert_list, count * morph_count); - for (size_t i = 0; i < count; i++) { - bool found = false; - uint32_t l = 0; - for (size_t j = 0; j < morph_count; j++) { - l = 0; - bool f = false; - obj_vertex_data* vert = &verts[i + j * count]; - for (obj_vertex_data* k = vert_list.begin; k != vert_list.end; k += morph_count, l++) - if (!memcmp(k, vert, sizeof(obj_vertex_data))) { - f = true; - break; - } - - if (found && !f) - found = false; - else if (f) - found = true; - } - - if (!found) - for (size_t j = 0; j < morph_count; j++) - vector_obj_vertex_data_push_back(&vert_list, &verts[i + j * count]); - v->ind[i] = l; - } - - v->vert_count = (vert_list.end - vert_list.begin) / data->morph_count; - v->vert = force_malloc_s(vertex_struct, v->vert_count * data->morph_count); - if (!v->vert || !vert_list.begin) { - vector_obj_vertex_data_free(&vert_list); - v->type = VERTEX_NONE; - v->translucent = false; - free(v->vert); - v->vert_count = 0; - free(v->ind); - v->ind_count = 0; - v->bound_box.min = vec3_null; - v->bound_box.max = vec3_null; - v->morph_count = 0; - v->vbo = 0; - v->ebo = 0; - return; - } - v->morph_count = morph_count; - free(verts); - - v->bound_box.min = (vec3){ FLT_MAX, FLT_MAX, FLT_MAX }; - v->bound_box.max = (vec3){ -FLT_MAX, -FLT_MAX, -FLT_MAX }; - for (size_t i = 0; i < morph_count; i++) - vertex_data_store(v, vert_list.begin, i); - vector_obj_vertex_data_free(&vert_list); - - v->vbo = force_malloc_s(uint32_t, v->morph_count); - glGenBuffers((GLsizei)v->morph_count, v->vbo); - for (size_t i = 0; i < morph_count; i++) { - vertex_struct* vert_ptr = v->vert + i * v->vert_count; - - glBindBuffer(GL_ARRAY_BUFFER, v->vbo[i]); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(sizeof(vertex_struct) * v->vert_count), - (void*)vert_ptr, GL_DYNAMIC_DRAW); - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glGenBuffers(1, &v->ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, v->ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(sizeof(uint32_t) * v->ind_count), - v->ind, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void vertex_free(vertex* v) { - if (!v) - return; - - if (v->vbo) { - glDeleteBuffers((GLsizei)v->morph_count, v->vbo); - free(v->vbo); - } - - if (v->ebo) { - glDeleteBuffers(1, &v->ebo); - v->ebo = 0; - } - - free(v->vert); - free(v->ind); - v->vert_count = 0; - v->ind_count = 0; - v->type = VERTEX_NONE; - v->translucent = false; -} - -static void vertex_data_load(vertex* v, vertex_data* data, obj_vertex_data* verts, size_t index) { - size_t count = data->count; - size_t offset = index * count; - obj_vertex_data* vert = data->vert; - - verts += offset; - vert += offset; - if (data->flags & OBJ_VERTEX_POSITION) - for (size_t i = 0; i < count; i++) - verts[i].position = vert[i].position; - else - for (size_t i = 0; i < count; i++) - verts[i].position = vec3_null; - - if (data->flags & OBJ_VERTEX_NORMAL) - for (size_t i = 0; i < count; i++) { - vec3 normal = vert[i].normal; - vec3_normalize(normal, normal); - verts[i].normal = normal; - } - else - for (size_t i = 0; i < count; i++) - verts[i].normal = vec3_null; - - if (data->flags & OBJ_VERTEX_TANGENT) - for (size_t i = 0; i < count; i++) { - vec3 tangent = *(vec3*)&vert[i].tangent; - vec3_normalize(tangent, tangent); - *(vec3*)&verts[i].tangent = tangent; - verts[i].tangent.w = vert[i].tangent.w; - } - else - for (size_t i = 0; i < count; i++) - verts[i].tangent = vec4_null; - - if (data->flags & OBJ_VERTEX_TEXCOORD0) - for (size_t i = 0; i < count; i++) - verts[i].texcoord0 = vert[i].texcoord0; - else - for (size_t i = 0; i < count; i++) - verts[i].texcoord0 = vec2_null; - - if (data->flags & OBJ_VERTEX_TEXCOORD1) - for (size_t i = 0; i < count; i++) - verts[i].texcoord1 = vert[i].texcoord1; - else - for (size_t i = 0; i < count; i++) - verts[i].texcoord1 = vec2_null; - - if (data->flags & OBJ_VERTEX_TEXCOORD2) - for (size_t i = 0; i < count; i++) - verts[i].texcoord2 = vert[i].texcoord2; - else - for (size_t i = 0; i < count; i++) - verts[i].texcoord2 = vec2_null; - - if (data->flags & OBJ_VERTEX_TEXCOORD3) - for (size_t i = 0; i < count; i++) - verts[i].texcoord3 = vert[i].texcoord3; - else - for (size_t i = 0; i < count; i++) - verts[i].texcoord3 = vec2_null; - - if (data->flags & OBJ_VERTEX_COLOR0) - for (size_t i = 0; i < count; i++) { - verts[i].color0 = vert[i].color0; - if (verts[i].color0.w != 1.0f) - v->translucent = true; - } - else - for (size_t i = 0; i < count; i++) - verts[i].color0 = vec4_identity; - - if (data->flags & OBJ_VERTEX_COLOR1) - for (size_t i = 0; i < count; i++) - verts[i].color1 = vert[i].color1; - else - for (size_t i = 0; i < count; i++) - verts[i].color1 = vec4_identity; - - if (data->flags & OBJ_VERTEX_BONE_DATA) - for (size_t i = 0; i < count; i++) { - vec4i bone_index = vert[i].bone_index; - verts[i].bone_index = bone_index; - if (bone_index.x < 0x0000 || bone_index.x > 0xFFFF) - verts[i].bone_index.x = 0xFFFF; - if (bone_index.y < 0x0000 || bone_index.y > 0xFFFF) - verts[i].bone_index.y = 0xFFFF; - if (bone_index.z < 0x0000 || bone_index.z > 0xFFFF) - verts[i].bone_index.z = 0xFFFF; - if (bone_index.w < 0x0000 || bone_index.w > 0xFFFF) - verts[i].bone_index.w = 0xFFFF; - - vec4 bone_weight; - float_t bone_weight_length; - vec4_normalize(vert[i].bone_weight, bone_weight); - vec4_length_squared(bone_weight, bone_weight_length); - verts[i].bone_weight = bone_weight; - if (bone_weight_length != 0.0f) - v->type = VERTEX_BONED; - } - else - for (size_t i = 0; i < count; i++) { - verts[i].bone_index = (vec4i){ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF }; - verts[i].bone_weight = vec4_null; - } -} - -static void vertex_data_store(vertex* v, obj_vertex_data* verts, size_t index) { - size_t count = v->vert_count; - size_t morph_count = v->morph_count; - vertex_struct* vert_ptr = v->vert; - vert_ptr += index * count; - for (size_t i = 0; i < v->vert_count; i++) { - vec3 pos; - vec2 texcoord0; - vec2 texcoord1; - vec2 texcoord2; - vec2 texcoord3; - vec4 color0; - vec4 color1; - vec3 normal; - vec4 tangent; - vec4i bone_index; - vec4 bone_weight; - - obj_vertex_data* vert = &verts[i * v->morph_count + index]; - pos = vert->position; - texcoord0 = vert->texcoord0; - texcoord1 = vert->texcoord1; - texcoord2 = vert->texcoord2; - texcoord3 = vert->texcoord3; - color0 = vert->color0; - color1 = vert->color1; - normal = vert->normal; - tangent = vert->tangent; - bone_index = vert->bone_index; - bone_weight = vert->bone_weight; - - vec3_min(v->bound_box.min, pos, v->bound_box.min); - vec3_max(v->bound_box.max, pos, v->bound_box.max); - - vec3_mult_scalar(normal, 32767.0f, normal); - vec4_mult_scalar(tangent, 32767.0f, tangent); - vec4_mult_scalar(bone_weight, 255.0f, bone_weight); - - vert_ptr->pos = pos; - vec2_to_vec2h(texcoord0, vert_ptr->texcoord[0]); - vec2_to_vec2h(texcoord1, vert_ptr->texcoord[1]); - vec2_to_vec2h(texcoord2, vert_ptr->texcoord[2]); - vec2_to_vec2h(texcoord3, vert_ptr->texcoord[3]); - vec4_to_vec4h(color0, vert_ptr->color[0]); - vec4_to_vec4h(color1, vert_ptr->color[1]); - vec3_to_vec3i16(normal, *(vec3i16*)&vert_ptr->normal); - vert_ptr->normal.w = 0; - vec3_to_vec3i16(tangent, vert_ptr->tangent); - vec4i_to_vec4u16(bone_index, vert_ptr->bone_index); - vec4_to_vec4u8(bone_weight, vert_ptr->bone_weight); - vert_ptr++; - } -} - -vector_func(obj_vertex_data) diff --git a/src/CRE/vertex.h b/src/CRE/vertex.h deleted file mode 100644 index d70c60ea..00000000 --- a/src/CRE/vertex.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/obj.h" -#include "../KKdLib/vec.h" - -typedef enum vertex_type { - VERTEX_NONE = 0, - VERTEX_SIMPLE, - VERTEX_BONED, -} vertex_type; - -typedef enum vertex_primitive_type { - VERTEX_PRIMITIVE_NONE = 0, - VERTEX_PRIMITIVE_POINT, - VERTEX_PRIMITIVE_LINE, - VERTEX_PRIMITIVE_TRIANGLE, -} vertex_primitive_type; - -typedef struct vertex_bounding_box { - vec3 min; - vec3 max; -}vertex_bounding_box; - -#pragma pack(push, 1) -typedef struct vertex_struct { - vec3 pos; - vec4i16 normal; - vec4i16 tangent; - vec2h texcoord[4]; - vec4h color[2]; - vec4u16 bone_index; - vec4u8 bone_weight; -} vertex_struct; -#pragma pack(pop) - -typedef struct vertex { - vertex_type type; - vertex_struct* vert; - size_t vert_count; - uint32_t* ind; - size_t ind_count; - vertex_bounding_box bound_box; - size_t morph_count; - uint32_t* vbo; - uint32_t ebo; - bool translucent; -} vertex; - -typedef struct vertex_data { - vertex_primitive_type primitive; - obj_vertex_flags flags; - obj_vertex_data* vert; - size_t count; - size_t morph_count; -} vertex_data; - -extern void vertex_init(vertex* v); -extern void vertex_load(vertex* v, vertex_data* data); -extern void vertex_free(vertex* v); diff --git a/src/CRE/video_x264.c b/src/CRE/video_x264.c deleted file mode 100644 index 451d0fae..00000000 --- a/src/CRE/video_x264.c +++ /dev/null @@ -1,962 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#if defined(VIDEO) -#include "video_x264.h" -#include - -static void video_x264_pic_convert8(video_x264* x); -static void video_x264_pic_convert10(video_x264* x); - -vector_func(hash_video_x264) - -bool video_x264_init(video_x264* x, video_x264_init_data* init) { - if (!x) - return false; - - SYSTEM_INFO sysinf; - GetSystemInfo(&sysinf); - int32_t threads = sysinf.dwNumberOfProcessors / 2; - if (threads < 1) - threads = 1; - - memset(x, 0x00, sizeof(*x)); - - const char* tune = x264_tune_names[init->tune >= VIDEO_X264_TUNE_FILM - && init->tune <= VIDEO_X264_TUNE_ZEROLATENCY ? init->tune : VIDEO_X264_TUNE_MAX]; - const char* preset = x264_preset_names[init->preset >= VIDEO_X264_PRESET_ULTRAFAST - && init->preset <= VIDEO_X264_PRESET_PLACEBO ? init->preset : VIDEO_X264_PRESET_MEDIUM]; - - lock_init(&x->lock); - x->error_state = 0; - if (!lock_check_init(&x->lock) || x264_param_default_preset(&x->state.param, preset, tune) < 0) { - x->error_state = -1; - return false; - } - - int32_t i_csp = init->color_space; - if (i_csp == VIDEO_X264_COLOR_SPACE_I400) - i_csp = X264_CSP_I400; - else if (i_csp >= VIDEO_X264_COLOR_SPACE_I420 && i_csp <= VIDEO_X264_COLOR_SPACE_NV21) - i_csp = X264_CSP_I420; - else if (i_csp >= VIDEO_X264_COLOR_SPACE_I422 && i_csp <= VIDEO_X264_COLOR_SPACE_NV16) - i_csp = X264_CSP_I422; - else if (i_csp >= VIDEO_X264_COLOR_SPACE_I444 && i_csp <= VIDEO_X264_COLOR_SPACE_RGB) - i_csp = X264_CSP_I444; - else - i_csp = X264_CSP_NONE; - - int32_t i_rc_method = init->rate_control.method; - float_t f_rf_constant = 0.0f; - if (i_rc_method < X264_RC_CQP || i_rc_method > X264_RC_ABR) { - i_rc_method = X264_RC_CRF; - f_rf_constant = 20.0f; - } - else if (i_rc_method == X264_RC_CRF) - f_rf_constant = init->rate_control.crf; - - x->state.param.i_threads = threads; - x->state.param.i_width = init->width; - x->state.param.i_height = init->height; - x->state.param.i_csp = i_csp; - x->state.param.i_bitdepth = 8; - if (init->bit_depth == VIDEO_X264_BIT_DEPTH_10_BIT) { - x->state.param.i_csp |= X264_CSP_HIGH_DEPTH; - x->state.param.i_bitdepth = 10; - } - - if (init->flip) - x->state.param.i_csp |= X264_CSP_VFLIP; - - const char* profile; - switch (i_csp) { - case VIDEO_X264_COLOR_SPACE_I400: - if (init->bit_depth == VIDEO_X264_BIT_DEPTH_10_BIT) - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH + 1]; - else - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH]; - break; - case VIDEO_X264_COLOR_SPACE_I420: - if (init->bit_depth == VIDEO_X264_BIT_DEPTH_10_BIT) - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH + 1]; - else - profile = x264_profile_names[init->profile >= VIDEO_X264_PROFILE_BASELINE - && init->profile <= VIDEO_X264_PROFILE_HIGH ? init->profile : VIDEO_X264_PROFILE_MAIN]; - break; - case VIDEO_X264_COLOR_SPACE_I422: - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH + 2]; - break; - case VIDEO_X264_COLOR_SPACE_I444: - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH + 3]; - break; - default: - profile = 0; - break; - } - - if (f_rf_constant == 0.0f) - profile = x264_profile_names[VIDEO_X264_PROFILE_HIGH + 3]; - - x->state.param.vui.i_sar_height = 1; - x->state.param.vui.i_sar_width = 1; - x->state.param.vui.i_overscan = 1; - x->state.param.vui.i_vidformat = 5; - x->state.param.vui.b_fullrange = true; - x->state.param.vui.i_colorprim = 2; - x->state.param.vui.i_transfer = 2; - x->state.param.vui.i_colmatrix = 1; - x->state.param.vui.i_chroma_loc = 0; - - double_t fps = init->fps; - int32_t i_keyint_max = (int32_t)ceil(fps); - int32_t i_fps_num = 0; - int32_t i_fps_den = 0; - for (int32_t i = 0, j = 1; i < 6; i++, j *= 10) { - i_fps_num = (int32_t)(fps * (double_t)j); - i_fps_den = j; - - if (j < 10) - continue; - - double_t f0 = (double_t)i_fps_num / (double_t)i_fps_den; - double_t f1 = (double_t)(i_fps_num / 10) / (double_t)(i_fps_den / 10); - if (fabs(f0 - f1) <= 0.0001 && fabs(f1 - fps) <= 0.0001) { - i_fps_num /= 10; - i_fps_den /= 10; - break; - } - } - - x->state.param.i_keyint_max = i_keyint_max; - x->state.param.i_bframe = 4; - x->state.param.i_bframe_adaptive = 2; - x->state.param.i_bframe_pyramid = 2; - x->state.param.b_open_gop = true; - x->state.param.b_repeat_headers = true; - x->state.param.b_annexb = true; - x->state.param.b_vfr_input = false; - - x->state.param.i_fps_num = i_fps_num; - x->state.param.i_fps_den = i_fps_den; - - x->state.param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO; - x->state.param.analyse.i_me_method = X264_ME_UMH; - x->state.param.analyse.i_me_range = 24; - x->state.param.analyse.i_subpel_refine = 9; - - x->state.param.rc.i_rc_method = i_rc_method; - switch (i_rc_method) { - case X264_RC_CQP: - x->state.param.rc.i_qp_constant = init->rate_control.cqp; - break; - case X264_RC_CRF: - x->state.param.rc.f_rf_constant = f_rf_constant; - break; - case X264_RC_ABR: - x->state.param.rc.i_bitrate = init->rate_control.abr; - break; - } - x->state.param.rc.f_ip_factor = 1.0f; - x->state.param.rc.f_pb_factor = 1.0f; - - x->state.param.rc.i_aq_mode = X264_AQ_AUTOVARIANCE; - - if (x264_param_apply_profile(&x->state.param, profile) < 0) { - x->error_state = -2; - return false; - } - - x->state.enc = x264_encoder_open(&x->state.param); - if (!x->state.enc) { - x->error_state = -3; - return false; - } - - if (x264_picture_alloc(&x->state.pic, x->state.param.i_csp, - x->state.param.i_width, x->state.param.i_height) < 0) { - x->error_state = -4; - return false; - } - - x->data = force_malloc((size_t)x->state.param.i_width * (size_t)x->state.param.i_height * 8); - x->state.buffer = force_malloc((size_t)x->state.param.i_width - * (size_t)x->state.param.i_height * (init->bit_depth == VIDEO_X264_BIT_DEPTH_10_BIT ? 6 : 3)); - return true; -} - -bool video_x264_encode(video_x264* x, int32_t frame) { - if (!x || x->error_state < 0 || !x->state.enc) - return false; - - x->state.pic.i_type = X264_TYPE_AUTO; - x->state.pic.i_pts = frame; - int32_t i_frame_size = x264_encoder_encode(x->state.enc, - &x->state.nal, &x->state.i_nal, &x->state.pic, &x->state.pic_out); - if (i_frame_size < 0) { - x->error_state = -5; - return false; - } - else if (i_frame_size) - if (!io_write(&x->io, x->state.nal->p_payload, i_frame_size)) { - x->error_state = -6; - return false; - } - return true; -} - -void video_x264_load_image_data(video_x264* x) { - if (!x || x->error_state < 0 || !x->state.enc) - return; - - if (x->state.param.i_csp & X264_CSP_HIGH_DEPTH) - video_x264_pic_convert10(x); - else - video_x264_pic_convert8(x); -} - -bool video_x264_flush(video_x264* x) { - if (!x || x->error_state < 0 || !x->state.enc) - return false; - - while (x264_encoder_delayed_frames(x->state.enc)) { - int32_t i_frame_size = x264_encoder_encode(x->state.enc, - &x->state.nal, &x->state.i_nal, 0, &x->state.pic_out); - if (i_frame_size < 0) { - x->error_state = -7; - return true; - } - else if (i_frame_size) - if (!io_write(&x->io, x->state.nal->p_payload, i_frame_size)) { - x->error_state = -8; - return true; - } - } - return true; -} - -void video_x264_close(video_x264* x) { - if (!x) - return; - - if (x->error_state <= -4 || x->error_state >= 0) { - if (x->error_state <= -5 || x->error_state >= 0) { - free(x->state.buffer); - free(x->data); - x264_picture_clean(&x->state.pic); - } - - if (x->state.enc) - x264_encoder_close(x->state.enc); - } - lock_free(&x->lock); -} - -static void video_x264_pic_convert8(video_x264* x) { - size_t count = (size_t)x->state.param.i_width * (size_t)x->state.param.i_height; - uint8_t* buffer = x->state.buffer; - lock_lock(&x->lock); - switch (x->fmt) { - case VIDEO_X264_PIC_FORMAT_RGB8: { - uint8_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = ptr[0]; - buffer[1] = ptr[1]; - buffer[2] = ptr[2]; - ptr += 3; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB10: { - uint8_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - uint32_t rgb_a = *(uint32_t*)ptr; - buffer[0] = (uint8_t)((rgb_a >> 2) & 0xFF); - buffer[1] = (uint8_t)((rgb_a >> 12) & 0xFF); - buffer[2] = (uint8_t)((rgb_a >> 22) & 0xFF); - ptr += 4; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB16: { - uint32_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - uint32_t rgb = *ptr++; - buffer[0] = (uint8_t)((ptr[0] >> 8) & 0xFF); - buffer[1] = (uint8_t)((ptr[1] >> 8) & 0xFF); - buffer[2] = (uint8_t)((ptr[2] >> 8) & 0xFF); - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGBA8: { - uint8_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = ptr[0]; - buffer[1] = ptr[1]; - buffer[2] = ptr[2]; - ptr += 4; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB10_A2: { - uint32_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - uint32_t rgb_a = *ptr++; - buffer[0] = (uint8_t)((rgb_a >> 2) & 0xFF); - buffer[1] = (uint8_t)((rgb_a >> 12) & 0xFF); - buffer[2] = (uint8_t)((rgb_a >> 22) & 0xFF); - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGBA16: { - uint16_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = (uint8_t)((ptr[0] >> 8) & 0xFF); - buffer[1] = (uint8_t)((ptr[1] >> 8) & 0xFF); - buffer[2] = (uint8_t)((ptr[2] >> 8) & 0xFF); - ptr += 4; - buffer += 3; - } - } break; - } - lock_unlock(&x->lock); - - const int32_t rgb2y_val[3] = { 21260, 71520, 7220 }; - const int32_t rgb2u_val[3] = { -11458, -38542, 50000 }; - const int32_t rgb2v_val[3] = { 50000, -45415, -4585 }; - -#define rgb2y(r, g, b) ((r * rgb2y_val[0] + g * rgb2y_val[1] + b * rgb2y_val[2]) / 100000) -#define rgb2u(r, g, b) ((r * rgb2u_val[0] + g * rgb2u_val[1] + b * rgb2u_val[2]) / 100000) -#define rgb2v(r, g, b) ((r * rgb2v_val[0] + g * rgb2v_val[1] + b * rgb2v_val[2]) / 100000) -#define yclamp(y) (uint8_t)clamp(y, 0, 255) -#define uclamp(u) (uint8_t)clamp(u + 128, 0, 255) -#define vclamp(v) (uint8_t)clamp(v + 128, 0, 255); - - const size_t width = x->state.param.i_width; - const size_t height = x->state.param.i_height; - const size_t width2 = width / 2 * 2; - const size_t height2 = height / 2 * 2; - const size_t width3 = width * 3; - const size_t height3 = height * 3; - buffer = x->state.buffer; - switch (x->state.param.i_csp & X264_CSP_MASK) { - case X264_CSP_I400: { - uint8_t* y_plane = x->state.pic.img.plane[0]; - for (size_t i = 0; i < height; i++) - for (size_t j = 0; j < width; j++) { - uint8_t r = buffer[0]; - uint8_t g = buffer[1]; - uint8_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - *y_plane++ = yclamp(y); - } - } break; - case X264_CSP_I420: { - uint8_t* y_plane = x->state.pic.img.plane[0]; - uint8_t* u_plane = x->state.pic.img.plane[1]; - uint8_t* v_plane = x->state.pic.img.plane[2]; - - size_t i = 0; - for (; i < height2; i += 2) { - size_t j = 0; - for (; j < width2; j += 2) { - uint8_t r; - uint8_t g; - uint8_t b; - int32_t y; - int32_t u[4]; - int32_t v[4]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[2] = rgb2u(r, g, b); - v[2] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[3] = rgb2u(r, g, b); - v[3] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1] + u[2] + u[3]) / 4); - *v_plane = vclamp((v[0] + v[1] + v[2] + v[3]) / 4); - u_plane++; - v_plane++; - } - - for (; j < width; j++) { - uint8_t r; - uint8_t g; - uint8_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - buffer += width3; - y_plane += width; - } - - for (; i < height; i++) { - size_t x = 0; - for (; x < width2; x += 2) { - uint8_t r; - uint8_t g; - uint8_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - - for (; x < width; x++) { - uint8_t r; - uint8_t g; - uint8_t b; - int32_t y; - int32_t u; - int32_t v; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u = rgb2u(r, g, b); - v = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp(u); - *v_plane = vclamp(v); - u_plane++; - v_plane++; - } - buffer += width3; - y_plane += width; - } - } break; - case X264_CSP_I422: { - uint8_t* y_plane = x->state.pic.img.plane[0]; - uint8_t* u_plane = x->state.pic.img.plane[1]; - uint8_t* v_plane = x->state.pic.img.plane[2]; - - for (size_t i = 0; i < height; i++) { - size_t j = 0; - for (; j < width2; j += 2) { - uint8_t r; - uint8_t g; - uint8_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - buffer += 3; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - buffer += 3; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - - for (; j < width; j++) { - uint8_t r = buffer[0]; - uint8_t g = buffer[1]; - uint8_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - int32_t u = rgb2u(r, g, b); - int32_t v = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - *u_plane = uclamp(u); - *v_plane = vclamp(v); - u_plane++; - v_plane++; - } - } - } break; - case X264_CSP_I444: { - uint8_t* y_plane = x->state.pic.img.plane[0]; - uint8_t* u_plane = x->state.pic.img.plane[1]; - uint8_t* v_plane = x->state.pic.img.plane[2]; - - for (size_t i = 0; i < height; i++) - for (size_t j = 0; j < width; j++) { - uint8_t r = buffer[0]; - uint8_t g = buffer[1]; - uint8_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - int32_t u = rgb2u(r, g, b); - int32_t v = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - *u_plane++ = uclamp(u); - *v_plane++ = vclamp(v); - } - } break; - } -#undef rgb2y -#undef rgb2u -#undef rgb2v -#undef yclamp -#undef uclamp -#undef vclamp -} - -static void video_x264_pic_convert10(video_x264* x) { - size_t count = (size_t)x->state.param.i_width * (size_t)x->state.param.i_height; - uint16_t* buffer = x->state.buffer; - lock_lock(&x->lock); - switch (x->fmt) { - case VIDEO_X264_PIC_FORMAT_RGB8: { - uint16_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = (uint16_t)(((ptr[0] << 2) | (ptr[0] >> 6)) & 0x3FF); - buffer[1] = (uint16_t)(((ptr[1] << 2) | (ptr[1] >> 6)) & 0x3FF); - buffer[2] = (uint16_t)(((ptr[2] << 2) | (ptr[2] >> 6)) & 0x3FF); - ptr += 3; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB10: { - uint32_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - uint32_t rgb = *ptr++; - buffer[0] = (uint16_t)(rgb & 0x3FF); - buffer[1] = (uint16_t)((rgb >> 10) & 0x3FF); - buffer[2] = (uint16_t)((rgb >> 20) & 0x3FF); - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB16: { - uint16_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = (uint16_t)((ptr[0] >> 6) & 0x3FF); - buffer[1] = (uint16_t)((ptr[1] >> 6) & 0x3FF); - buffer[2] = (uint16_t)((ptr[2] >> 6) & 0x3FF); - ptr += 3; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGBA8: { - uint16_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = (uint16_t)(((ptr[0] << 2) | (ptr[0] >> 6)) & 0x3FF); - buffer[1] = (uint16_t)(((ptr[1] << 2) | (ptr[1] >> 6)) & 0x3FF); - buffer[2] = (uint16_t)(((ptr[2] << 2) | (ptr[2] >> 6)) & 0x3FF); - ptr += 4; - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGB10_A2: { - uint32_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - uint32_t rgb_a = *ptr++; - buffer[0] = (uint16_t)(rgb_a & 0x3FF); - buffer[1] = (uint16_t)((rgb_a >> 10) & 0x3FF); - buffer[2] = (uint16_t)((rgb_a >> 20) & 0x3FF); - buffer += 3; - } - } break; - case VIDEO_X264_PIC_FORMAT_RGBA16: { - uint16_t* ptr = x->data; - for (size_t i = 0; i < count; i++) { - buffer[0] = (uint16_t)((ptr[0] >> 6) & 0x3FF); - buffer[1] = (uint16_t)((ptr[1] >> 6) & 0x3FF); - buffer[2] = (uint16_t)((ptr[2] >> 6) & 0x3FF); - ptr += 4; - buffer += 3; - } - } break; - } - lock_unlock(&x->lock); - - const int32_t rgb2y_val[3] = { 21260, 71520, 7220 }; - const int32_t rgb2u_val[3] = { -11458, -38542, 50000 }; - const int32_t rgb2v_val[3] = { 50000, -45415, -4585 }; - -#define rgb2y(r, g, b) ((r * rgb2y_val[0] + g * rgb2y_val[1] + b * rgb2y_val[2]) / 100000) -#define rgb2u(r, g, b) ((r * rgb2u_val[0] + g * rgb2u_val[1] + b * rgb2u_val[2]) / 100000) -#define rgb2v(r, g, b) ((r * rgb2v_val[0] + g * rgb2v_val[1] + b * rgb2v_val[2]) / 100000) -#define yclamp(y) (uint16_t)clamp(y, 0, 1023) -#define uclamp(u) (uint16_t)clamp(u + 512, 0, 1023) -#define vclamp(v) (uint16_t)clamp(v + 512, 0, 1023); - - const size_t width = x->state.param.i_width; - const size_t height = x->state.param.i_height; - const size_t width2 = width / 2 * 2; - const size_t height2 = height / 2 * 2; - const size_t width3 = width * 3; - const size_t height3 = height * 3; - buffer = x->state.buffer; - switch (x->state.param.i_csp & X264_CSP_MASK) { - case X264_CSP_I400: { - uint16_t* y_plane = (uint16_t*)x->state.pic.img.plane[0]; - for (size_t i = 0; i < height; i++) - for (size_t j = 0; j < width; j++) { - uint16_t r = buffer[0]; - uint16_t g = buffer[1]; - uint16_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - *y_plane++ = yclamp(y); - } - } break; - case X264_CSP_I420: { - uint16_t* y_plane = (uint16_t*)x->state.pic.img.plane[0]; - uint16_t* u_plane = (uint16_t*)x->state.pic.img.plane[1]; - uint16_t* v_plane = (uint16_t*)x->state.pic.img.plane[2]; - - size_t i = 0; - for (; i < height2; i += 2) { - size_t j = 0; - for (; j < width2; j += 2) { - uint16_t r; - uint16_t g; - uint16_t b; - int32_t y; - int32_t u[4]; - int32_t v[4]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[2] = rgb2u(r, g, b); - v[2] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[3] = rgb2u(r, g, b); - v[3] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1] + u[2] + u[3]) / 4); - *v_plane = vclamp((v[0] + v[1] + v[2] + v[3]) / 4); - u_plane++; - v_plane++; - } - - for (; j < width; j++) { - uint16_t r; - uint16_t g; - uint16_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - r = buffer[width3 + 0]; - g = buffer[width3 + 1]; - b = buffer[width3 + 2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - y_plane[width] = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - buffer += width3; - y_plane += width; - } - - for (; i < height; i++) { - size_t x = 0; - for (; x < width2; x += 2) { - uint16_t r; - uint16_t g; - uint16_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - - for (; x < width; x++) { - uint16_t r; - uint16_t g; - uint16_t b; - int32_t y; - int32_t u; - int32_t v; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - - y = rgb2y(r, g, b); - u = rgb2u(r, g, b); - v = rgb2v(r, g, b); - *y_plane = yclamp(y); - - buffer += 3; - y_plane++; - - *u_plane = uclamp(u); - *v_plane = vclamp(v); - u_plane++; - v_plane++; - } - buffer += width3; - y_plane += width; - } - } break; - case X264_CSP_I422: { - uint16_t* y_plane = (uint16_t*)x->state.pic.img.plane[0]; - uint16_t* u_plane = (uint16_t*)x->state.pic.img.plane[1]; - uint16_t* v_plane = (uint16_t*)x->state.pic.img.plane[2]; - - for (size_t i = 0; i < height; i++) { - size_t j = 0; - for (; j < width2; j += 2) { - uint16_t r; - uint16_t g; - uint16_t b; - int32_t y; - int32_t u[2]; - int32_t v[2]; - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - buffer += 3; - - y = rgb2y(r, g, b); - u[0] = rgb2u(r, g, b); - v[0] = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - - r = buffer[0]; - g = buffer[1]; - b = buffer[2]; - buffer += 3; - - y = rgb2y(r, g, b); - u[1] = rgb2u(r, g, b); - v[1] = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - - *u_plane = uclamp((u[0] + u[1]) / 2); - *v_plane = vclamp((v[0] + v[1]) / 2); - u_plane++; - v_plane++; - } - - for (; j < width; j++) { - uint16_t r = buffer[0]; - uint16_t g = buffer[1]; - uint16_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - int32_t u = rgb2u(r, g, b); - int32_t v = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - *u_plane = uclamp(u); - *v_plane = vclamp(v); - u_plane++; - v_plane++; - } - } - } break; - case X264_CSP_I444: { - uint16_t* y_plane = (uint16_t*)x->state.pic.img.plane[0]; - uint16_t* u_plane = (uint16_t*)x->state.pic.img.plane[1]; - uint16_t* v_plane = (uint16_t*)x->state.pic.img.plane[2]; - - for (size_t i = 0; i < height; i++) - for (size_t j = 0; j < width; j++) { - uint16_t r = buffer[0]; - uint16_t g = buffer[1]; - uint16_t b = buffer[2]; - buffer += 3; - - int32_t y = rgb2y(r, g, b); - int32_t u = rgb2u(r, g, b); - int32_t v = rgb2v(r, g, b); - *y_plane++ = yclamp(y); - *u_plane++ = uclamp(u); - *v_plane++ = vclamp(v); - } - } break; - } -#undef rgb2y -#undef rgb2u -#undef rgb2v -#undef yclamp -#undef uclamp -#undef vclamp -} -#endif diff --git a/src/CRE/video_x264.h b/src/CRE/video_x264.h deleted file mode 100644 index 943aba83..00000000 --- a/src/CRE/video_x264.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#if defined(VIDEO) -#pragma once - -#include "../KKdLib/default.h" -#include "../KKdLib/io_stream.h" -#include "hash.h" -#include "lock.h" -#include - -typedef enum video_x264_bit_depth { - VIDEO_X264_BIT_DEPTH_8_BIT = 0, - VIDEO_X264_BIT_DEPTH_10_BIT = 1, -} video_x264_bit_depth; - -typedef enum video_x264_color_space { - VIDEO_X264_COLOR_SPACE_I400 = 0x01, - VIDEO_X264_COLOR_SPACE_I420 = 0x02, - VIDEO_X264_COLOR_SPACE_YV12 = 0x03, - VIDEO_X264_COLOR_SPACE_NV12 = 0x04, - VIDEO_X264_COLOR_SPACE_NV21 = 0x05, - VIDEO_X264_COLOR_SPACE_I422 = 0x06, - VIDEO_X264_COLOR_SPACE_YV16 = 0x07, - VIDEO_X264_COLOR_SPACE_NV16 = 0x08, - VIDEO_X264_COLOR_SPACE_I444 = 0x0C, - VIDEO_X264_COLOR_SPACE_YV24 = 0x0D, - VIDEO_X264_COLOR_SPACE_BGR = 0x0E, - VIDEO_X264_COLOR_SPACE_BGRA = 0x0F, - VIDEO_X264_COLOR_SPACE_RGB = 0x10, -}video_x264_color_space; - -typedef enum video_x264_rate_control_method { - VIDEO_X264_RATE_CONTROL_CQP = 0, - VIDEO_X264_RATE_CONTROL_CRF = 1, - VIDEO_X264_RATE_CONTROL_ABR = 2, -} video_x264_rate_control_method; - -typedef enum video_x264_pic_format { - VIDEO_X264_PIC_FORMAT_NONE = 0, - VIDEO_X264_PIC_FORMAT_RGB8, - VIDEO_X264_PIC_FORMAT_RGB10, - VIDEO_X264_PIC_FORMAT_RGB16, - VIDEO_X264_PIC_FORMAT_RGBA8, - VIDEO_X264_PIC_FORMAT_RGB10_A2, - VIDEO_X264_PIC_FORMAT_RGBA16, -} video_x264_pic_format; - -typedef enum video_x264_profile { - VIDEO_X264_PROFILE_NONE = -1, - VIDEO_X264_PROFILE_BASELINE = 0, - VIDEO_X264_PROFILE_MAIN = 1, - VIDEO_X264_PROFILE_HIGH = 2, -} video_x264_profile; - -typedef enum video_x264_preset { - VIDEO_X264_PRESET_NONE = -1, - VIDEO_X264_PRESET_ULTRAFAST = 0, - VIDEO_X264_PRESET_SUPERFAST = 1, - VIDEO_X264_PRESET_VERYFAST = 2, - VIDEO_X264_PRESET_FASTER = 3, - VIDEO_X264_PRESET_FAST = 4, - VIDEO_X264_PRESET_MEDIUM = 5, - VIDEO_X264_PRESET_SLOW = 6, - VIDEO_X264_PRESET_SLOWER = 7, - VIDEO_X264_PRESET_VERYSLOW = 8, - VIDEO_X264_PRESET_PLACEBO = 9, -} video_x264_preset; - -typedef enum video_x264_tune { - VIDEO_X264_TUNE_NONE = -1, - VIDEO_X264_TUNE_FILM = 0, - VIDEO_X264_TUNE_ANIMATION = 1, - VIDEO_X264_TUNE_GRAIN = 2, - VIDEO_X264_TUNE_STILLIMAGE = 3, - VIDEO_X264_TUNE_PSNR = 4, - VIDEO_X264_TUNE_SSIM = 5, - VIDEO_X264_TUNE_FASTDECODE = 6, - VIDEO_X264_TUNE_ZEROLATENCY = 7, - VIDEO_X264_TUNE_MAX = 8, -} video_x264_tune; - -typedef struct video_x264_rate_control { - video_x264_rate_control_method method; - union { - int32_t cqp; - float_t crf; - int32_t abr; - }; -} video_x264_rate_control; - -typedef struct video_x264_init_data { - int32_t width; - int32_t height; - double_t fps; - bool flip; - video_x264_preset preset; - video_x264_tune tune; - video_x264_profile profile; - video_x264_color_space color_space; - video_x264_bit_depth bit_depth; - video_x264_rate_control rate_control; -} video_x264_init_data; - -typedef struct video_x264_state { - x264_param_t param; - x264_picture_t pic; - x264_picture_t pic_out; - x264_t* enc; - x264_nal_t* nal; - int32_t i_nal; - void* buffer; -} video_x264_state; - -typedef struct video_x264 { - int32_t error_state; - int32_t frame; - video_x264_state state; - stream io; - void* data; - video_x264_pic_format fmt; - lock lock; -} video_x264; - -hash_dat(video_x264) -vector(hash_video_x264) - -extern bool video_x264_init(video_x264* x, video_x264_init_data* init); -extern bool video_x264_encode(video_x264* x, int32_t frame); -extern void video_x264_load_image_data(video_x264* x); -extern bool video_x264_flush(video_x264* x); -extern void video_x264_close(video_x264* x); -#endif diff --git a/src/DivaGL/DivaGL.rc b/src/DivaGL/DivaGL.rc new file mode 100644 index 00000000..54d610ea --- /dev/null +++ b/src/DivaGL/DivaGL.rc @@ -0,0 +1,46 @@ +#define IDR_VERSION2 101 + +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,1,2,0 + PRODUCTVERSION 0,1,2,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000904b0" + BEGIN + VALUE "FileDescription", "DivaGL plugin for PDAFT 7.10" + VALUE "FileVersion", "0.1.2.0" + VALUE "InternalName", "DivaGL" + VALUE "LegalCopyright", "korenkonder (C) 2020-2021" + VALUE "OriginalFilename", "DivaGL.dll" + VALUE "ProductName", "DivaGL" + VALUE "ProductVersion", "0.1.2.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x9, 1200 + END +END diff --git a/src/DivaGL/DivaGL.vcxproj b/src/DivaGL/DivaGL.vcxproj new file mode 100644 index 00000000..5dc5648b --- /dev/null +++ b/src/DivaGL/DivaGL.vcxproj @@ -0,0 +1,402 @@ + + + + + Debug + x64 + + + DebugDev + x64 + + + DebugOpt + x64 + + + DebugOptDev + x64 + + + Release + x64 + + + ReleaseDev + x64 + + + + 16.0 + {4D949362-9095-4113-9423-7E0492618F16} + Win32Proj + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + Unicode + + + DynamicLibrary + false + v142 + Unicode + + + DynamicLibrary + false + v142 + Unicode + + + DynamicLibrary + false + v142 + Unicode + + + + + + + + + + + + + + + + + + + + + + + true + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)objdebug\DivaGL\ + .dva + + + true + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)objdebug\DivaGLDev\ + .dva + + + false + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)objdebugopt\DivaGL\ + .dva + + + false + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)objdebugopt\DivaGLDev\ + .dva + + + false + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)obj\DivaGL\ + .dva + + + false + DivaGL + $(SolutionDir)bin\ + $(SolutionDir)obj\DivaGLDev\ + .dva + + + + NotUsing + Level3 + Disabled + WIN32;DEBUG;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + EditAndContinue + false + OnlyExplicitInline + FastCall + CompileAsC + true + false + MultiThreadedDebug + $(IntDir)/%(RelativeDir) + false + + + MachineX64 + DebugFull + Windows + $(SolutionDir)extern\lib;$(SolutionDir)libdebug\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + false + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + NotUsing + Level3 + Disabled + WIN32;DEBUG;DIVAGL_DEV;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + EditAndContinue + false + OnlyExplicitInline + FastCall + CompileAsC + true + false + MultiThreadedDebug + $(IntDir)/%(RelativeDir) + false + + + MachineX64 + DebugFull + Windows + $(SolutionDir)extern\lib;$(SolutionDir)libdebug\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + false + + + _UNICODE;UNICODE;DIVAGL_DEV;%(PreprocessorDefinitions) + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + NotUsing + Level3 + MaxSpeed + WIN32;DEBUG_OPT;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + false + ProgramDatabase + OnlyExplicitInline + true + FastCall + CompileAsC + false + MultiThreaded + /Gw %(AdditionalOptions) + $(IntDir)/%(RelativeDir) + false + Speed + false + + + MachineX64 + true + Windows + $(SolutionDir)extern\lib;$(SolutionDir)libdebugopt\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + true + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + true + false + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + NotUsing + Level3 + MaxSpeed + WIN32;DEBUG_OPT;DIVAGL_DEV;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + false + ProgramDatabase + OnlyExplicitInline + true + FastCall + CompileAsC + false + MultiThreaded + /Gw %(AdditionalOptions) + $(IntDir)/%(RelativeDir) + false + Speed + false + + + MachineX64 + true + Windows + $(SolutionDir)extern\lib;$(SolutionDir)libdebugopt\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + true + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + true + false + + + _UNICODE;UNICODE;DIVAGL_DEV;%(PreprocessorDefinitions) + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + NotUsing + Level3 + MaxSpeed + WIN32;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + false + ProgramDatabase + OnlyExplicitInline + true + FastCall + CompileAsC + false + true + MultiThreaded + /Gw %(AdditionalOptions) + $(IntDir)/%(RelativeDir) + false + Speed + false + + + MachineX64 + true + Windows + $(SolutionDir)extern\lib;$(SolutionDir)lib\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + true + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + true + false + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + NotUsing + Level3 + MaxSpeed + WIN32;DIVAGL_DEV;%(PreprocessorDefinitions) + $(SolutionDir)extern\src + true + NotSet + false + ProgramDatabase + OnlyExplicitInline + true + FastCall + CompileAsC + false + true + MultiThreaded + /Gw %(AdditionalOptions) + $(IntDir)/%(RelativeDir) + false + Speed + false + + + MachineX64 + true + Windows + $(SolutionDir)extern\lib;$(SolutionDir)lib\ + glad.lib;KKdLib.lib;%(AdditionalDependencies) + UseLinkTimeCodeGeneration + true + /ignore:4098 /ignore:4099 /ignore:4286 %(AdditionalOptions) + true + false + + + _UNICODE;UNICODE;DIVAGL_DEV;%(PreprocessorDefinitions) + + + copy /Y "$(SolutionDir)bin\$(TargetName).dva" "N:\DUMP\plugins\$(TargetName).dva" +copy /Y "$(SolutionDir)bin\$(TargetName).pdb" "N:\DUMP\plugins\$(TargetName).pdb" +del "$(SolutionDir)bin\$(TargetName).exp" +del "$(SolutionDir)bin\$(TargetName).lib" + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/DivaGL/DivaGL.vcxproj.user b/src/DivaGL/DivaGL.vcxproj.user new file mode 100644 index 00000000..1520ae29 --- /dev/null +++ b/src/DivaGL/DivaGL.vcxproj.user @@ -0,0 +1,39 @@ + + + + N:\DUMP\diva.exe + N:\DUMP + WindowsLocalDebugger + --launch -w + + + N:\DUMP\diva.exe + N:\DUMP + WindowsLocalDebugger + --launch -w + + + N:\DUMP\diva.exe + --launch -w + N:\DUMP + WindowsLocalDebugger + + + N:\DUMP\diva.exe + --launch -w + N:\DUMP + WindowsLocalDebugger + + + N:\DUMP\diva.exe + --launch -w + N:\DUMP + WindowsLocalDebugger + + + N:\DUMP\diva.exe + --launch -w + N:\DUMP + WindowsLocalDebugger + + \ No newline at end of file diff --git a/src/DivaGL/bone_data.c b/src/DivaGL/bone_data.c new file mode 100644 index 00000000..55404b69 --- /dev/null +++ b/src/DivaGL/bone_data.c @@ -0,0 +1,3274 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "bone_data.h" +#include "../KKdLib/interpolation.h" + +typedef enum HeapCMallocType { + HeapCMallocSystem = 0x00, + HeapCMallocTemp = 0x01, + HeapCMallocMode = 0x02, + HeapCMallocEvent = 0x03, + HeapCMallocDebug = 0x04, + HeapCMallocMax = 0x05, +} HeapCMallocType; + +typedef struct skeleton_rotation_offset { + bool x; + bool y; + bool z; + vec3 rotation; +} skeleton_rotation_offset; + +typedef struct struc_403 { + int32_t field_0; + int32_t field_4; + int32_t field_8; +} struc_403; + +typedef struct struc_404 { + int32_t field_0; + int32_t field_4; +} struc_404; + +static aft_bone_database_struct** bone_database_ptr = (void*)0x00000000140FBC1C0; +static struc_403** rob_cmn_mottbl_data_ptr = (void*)0x00000001411E8258; +static void* (*HeapCMallocAllocate)(HeapCMallocType type, size_t size, char* name) = (void*)0x00000001403F2A00; +static void(*HeapCMallocFree)(HeapCMallocType type, void* data) = (void*)0x00000001403F2960; + +static void bone_node_expression_data_set_position_rotation(bone_node_expression_data* data, + float_t position_x, float_t position_y, float_t position_z, + float_t rotation_x, float_t rotation_y, float_t rotation_z) { + data->position.x = position_x; + data->position.y = position_y; + data->position.z = position_z; + data->rotation.x = rotation_x; + data->rotation.z = rotation_z; + data->rotation.y = rotation_y; + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static void bone_node_expression_data_reset_scale(bone_node_expression_data* data) { + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static void bone_node_data_reset_position_rotation(bone_node_expression_data* data) { + data->position = vec3_null; + data->rotation = vec3_null; + data->scale = vec3_identity; + data->data_scale = vec3_identity; +} + +static bone_data* bone_data_init(bone_data* bone) { + bone->type = 0; + bone->has_parent = 0; + bone->motion_bone_index = 0; + bone->mirror = 0; + bone->parent = 0; + bone->flags = 0; + bone->key_set_offset = 0; + bone->key_set_count = 0; + bone->frame = 0; + + for (int32_t i = 0; i < 2; i++) + bone->base_translation[i] = vec3_null; + + bone->rotation = vec3_null; + bone->ik_target = vec3_null; + bone->trans = vec3_null; + for (int32_t i = 0; i < 2; i++) + bone->rot_mat[i] = mat4u_null; + + for (int32_t i = 0; i < 2; i++) + bone->trans_dup[i] = vec3_null; + + for (int32_t i = 0; i < 6; i++) + bone->rot_mat_dup[i] = mat4u_null; + + bone->pole_target_mat = 0; + bone->parent_mat = 0; + bone->node = 0; + bone->field_2E0 = 0.0f; + bone->eyes_xrot_adjust_neg = 1.0f; + bone->eyes_xrot_adjust_pos = 1.0f; + return bone; +} + +static void aft_bone_database_bones_calculate_count(aft_bone_database_bone* bones, size_t* object_bone_count, + size_t* motion_bone_count, size_t* total_bone_count, size_t* ik_bone_count, size_t* chain_pos) { + size_t _object_bone_count = 0; + size_t _motion_bone_count = 0; + size_t _total_bone_count = 0; + size_t _ik_bone_count = 0; + size_t _chain_pos = 0; + for (aft_bone_database_bone* i = bones; i->type != AFT_BONE_DATABASE_BONE_END; i++) + switch (i->type) { + case AFT_BONE_DATABASE_BONE_ROTATION: + case AFT_BONE_DATABASE_BONE_TYPE_1: + case AFT_BONE_DATABASE_BONE_POSITION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count++; + _chain_pos++; + break; + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count++; + _ik_bone_count++; + _chain_pos++; + break; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count += 3; + _ik_bone_count++; + _chain_pos += 2; + break; + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + _object_bone_count += 3; + _motion_bone_count++; + _total_bone_count += 4; + _ik_bone_count++; + _chain_pos += 3; + break; + } + *object_bone_count = _object_bone_count; + *motion_bone_count = _motion_bone_count; + *total_bone_count = _total_bone_count; + *ik_bone_count = _ik_bone_count; + *chain_pos = _chain_pos; +} + +static aft_bone_database_skeleton* aft_bone_database_get_skeleton_by_type(aft_bone_database_skeleton_type type) { + if (type == AFT_BONE_DATABASE_SKELETON_NONE || !*bone_database_ptr + || (*bone_database_ptr)->signature != 0x9102720) + return 0; + + return (*bone_database_ptr)->skeletons[type]; +} + +static aft_bone_database_bone* aft_bone_database_get_bones_by_type(aft_bone_database_skeleton_type type) { + aft_bone_database_skeleton* skel = aft_bone_database_get_skeleton_by_type(type); + if (!skel) + return 0; + + return skel->bones; +} + +static uint16_t* aft_bone_database_get_skeleton_parent_indices_by_type(aft_bone_database_skeleton_type type) { + aft_bone_database_skeleton* skel = aft_bone_database_get_skeleton_by_type(type); + if (!skel) + return 0; + + return skel->parent_indices; +} + +static vec3* aft_bone_database_get_skeleton_positions_by_type(aft_bone_database_skeleton_type type) { + aft_bone_database_skeleton* skel = aft_bone_database_get_skeleton_by_type(type); + if (!skel) + return 0; + + return skel->positions; +} + +static float_t aft_bone_database_get_skeleton_heel_height(aft_bone_database_skeleton_type a1) { + aft_bone_database_skeleton* skel = aft_bone_database_get_skeleton_by_type(a1); + if (skel) + return skel->heel_height[0]; + else + return 0.0f; +} + +static void rob_chara_data_bone_data_reserve(rob_chara_data_bone_data* rob_bone_data) { + if (rob_bone_data->mats.begin) + HeapCMallocFree(HeapCMallocSystem, rob_bone_data->mats.begin); + + size_t mats_size = rob_bone_data->object_bone_count; + rob_bone_data->mats.begin = HeapCMallocAllocate(HeapCMallocSystem, + mats_size * sizeof(mat4), "ALLOCsys"); + rob_bone_data->mats.end = rob_bone_data->mats.begin + mats_size; + rob_bone_data->mats.capacity_end = rob_bone_data->mats.begin + mats_size; + + for (mat4* i = rob_bone_data->mats.begin; i != rob_bone_data->mats.end; i++) + *i = mat4_identity; + + if (rob_bone_data->mats2.begin) + HeapCMallocFree(HeapCMallocSystem, rob_bone_data->mats2.begin); + + size_t mats2_size = rob_bone_data->total_bone_count - rob_bone_data->object_bone_count; + rob_bone_data->mats2.begin = HeapCMallocAllocate(HeapCMallocSystem, + mats2_size * sizeof(mat4), "ALLOCsys"); + rob_bone_data->mats2.end = rob_bone_data->mats2.begin + mats2_size; + rob_bone_data->mats2.capacity_end = rob_bone_data->mats2.begin + mats2_size; + + for (mat4* i = rob_bone_data->mats2.begin; i != rob_bone_data->mats2.end; i++) + *i = mat4_identity; + + if (rob_bone_data->nodes.begin) + HeapCMallocFree(HeapCMallocSystem, rob_bone_data->nodes.begin); + + size_t nodes_size = rob_bone_data->total_bone_count; + rob_bone_data->nodes.begin = HeapCMallocAllocate(HeapCMallocSystem, + nodes_size * sizeof(bone_node), "ALLOCsys"); + rob_bone_data->nodes.end = rob_bone_data->nodes.begin + nodes_size; + rob_bone_data->nodes.capacity_end = rob_bone_data->nodes.begin + nodes_size; + + for (bone_node* i = rob_bone_data->nodes.begin; i != rob_bone_data->nodes.end; i++) { + i->name = 0; + i->mat = 0; + i->parent = 0; + i->exp_data.position = vec3_null; + i->exp_data.rotation = vec3_null; + i->exp_data.scale = vec3_identity; + i->exp_data.data_scale = vec3_identity; + i->ex_data_mat = 0; + } +} + +static void rob_chara_data_bone_data_calculate_bones(rob_chara_data_bone_data* rob_bone_data, + aft_bone_database_bone* bones) { + aft_bone_database_bones_calculate_count(bones, &rob_bone_data->object_bone_count, + &rob_bone_data->motion_bone_count, &rob_bone_data->total_bone_count, + &rob_bone_data->ik_bone_count, &rob_bone_data->chain_pos); +} + +static void rob_chara_data_bone_data_set_mats(rob_chara_data_bone_data* rob_bone_data, + aft_bone_database_bone* a2) { + size_t chain_pos = 0; + size_t ik_bone_count = 0; + size_t total_bone_count = 0; + + mat4* mats = rob_bone_data->mats.begin; + mat4* mats2 = rob_bone_data->mats2.begin; + bone_node* nodes = rob_bone_data->nodes.begin; + for (aft_bone_database_bone* i = a2; i->type != AFT_BONE_DATABASE_BONE_END; i++) + switch (i->type) { + case AFT_BONE_DATABASE_BONE_ROTATION: + case AFT_BONE_DATABASE_BONE_TYPE_1: + case AFT_BONE_DATABASE_BONE_POSITION: + (nodes++)->mat = mats++; + + chain_pos++; + total_bone_count++; + break; + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: + (nodes++)->mat = mats++; + + chain_pos++; + ik_bone_count++; + total_bone_count++; + break; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + (nodes++)->mat = mats2++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats2++; + + chain_pos += 2; + ik_bone_count++; + total_bone_count += 3; + break; + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + (nodes++)->mat = mats++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats++; + (nodes++)->mat = mats2++; + + chain_pos += 3; + ik_bone_count++; + total_bone_count += 4; + break; + } + + for (bone_node* i = rob_bone_data->nodes.begin; i != rob_bone_data->nodes.end; i++) + i->ex_data_mat = i->mat; + + if (total_bone_count != rob_bone_data->total_bone_count) + printf("Node mismatch\n"); + if (mats - rob_bone_data->mats.begin != rob_bone_data->object_bone_count) + printf("Matrix mismatch\n"); + if (mats2 - rob_bone_data->mats2.begin != rob_bone_data->total_bone_count - rob_bone_data->object_bone_count) + printf("Matrix2 mismatch\n"); + if (ik_bone_count != rob_bone_data->ik_bone_count) + printf("LeafPos mismatch\n"); + if (chain_pos != rob_bone_data->chain_pos) + printf("ChainPos mismatch\n"); +} + +static void rob_chara_data_bone_data_set_parent_mats(rob_chara_data_bone_data* rob_bone_data, + uint16_t* parent_indices) { + if (rob_bone_data->nodes.end - rob_bone_data->nodes.begin < 1) + return; + + parent_indices++; + for (bone_node* i = &rob_bone_data->nodes.begin[1]; i != rob_bone_data->nodes.end; i++) + i->parent = &rob_bone_data->nodes.begin[*parent_indices++]; +} + +static void bone_data_parent_load_rob_chara_data(bone_data_parent* a1) { + rob_chara_data_bone_data* rob_bone_data = a1->rob_bone_data; + if (!rob_bone_data) + return; + + a1->motion_bone_count = rob_bone_data->motion_bone_count; + a1->ik_bone_count = rob_bone_data->ik_bone_count; + a1->chain_pos = rob_bone_data->chain_pos; + + if (a1->bones.begin) + HeapCMallocFree(HeapCMallocSystem, a1->bones.begin); + + size_t bones_size = rob_bone_data->motion_bone_count; + a1->bones.begin = HeapCMallocAllocate(HeapCMallocSystem, + bones_size * sizeof(bone_data), "ALLOCsys"); + a1->bones.end = a1->bones.begin + bones_size; + a1->bones.capacity_end = a1->bones.begin + bones_size; + + for (bone_data* i = a1->bones.begin; i != a1->bones.end; i++) + bone_data_init(i); + + a1->global_key_set_count = 6; + a1->field_8 = true; + a1->bone_key_set_count = (uint32_t)((a1->motion_bone_count + a1->ik_bone_count) * 3); +} + +static void bone_data_parent_load_bone_database(bone_data_parent* bone, + aft_bone_database_bone* bones, vec3* common_translation, vec3* translation) { + rob_chara_data_bone_data* rob_bone_data = bone->rob_bone_data; + size_t chain_pos = 0; + size_t total_bone_count = 0; + size_t ik_bone_count = 0; + + aft_bone_database_bone* v15 = bones; + bone_data* v16 = bone->bones.begin; + for (size_t i = 0; v15->type != AFT_BONE_DATABASE_BONE_END; i++, v15++, v16++) { + v16->motion_bone_index = (uint32_t)i; + v16->type = v15->type; + v16->mirror = v15->mirror; + v16->parent = v15->parent; + v16->flags = v15->flags; + if (v15->type >= AFT_BONE_DATABASE_BONE_POSITION_ROTATION) + v16->key_set_count = 6; + else + v16->key_set_count = 3; + v16->base_translation[0] = *common_translation++; + v16->base_translation[1] = *translation++; + v16->node = &rob_bone_data->nodes.begin[total_bone_count]; + v16->has_parent = v15->has_parent; + if (v15->has_parent) + v16->parent_mat = &rob_bone_data->mats.begin[v15->parent]; + else + v16->parent_mat = 0; + + v16->pole_target_mat = 0; + switch (v15->type) { + case AFT_BONE_DATABASE_BONE_ROTATION: + case AFT_BONE_DATABASE_BONE_TYPE_1: + case AFT_BONE_DATABASE_BONE_POSITION: + chain_pos++; + total_bone_count++; + break; + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: + chain_pos++; + ik_bone_count++; + total_bone_count++; + break; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + v16->ik_segment_length[0] = (common_translation++)->x; + v16->ik_segment_length[1] = (translation++)->x; + + chain_pos += 2; + ik_bone_count++; + total_bone_count += 3; + break; + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + v16->ik_segment_length[0] = (common_translation++)->x; + v16->ik_segment_length[1] = (translation++)->x; + v16->ik_2nd_segment_length[0] = (common_translation++)->x; + v16->ik_2nd_segment_length[1] = (translation++)->x; + + mat4* pole_target = 0; + if (v15->pole_target) + pole_target = &rob_bone_data->mats.begin[v15->pole_target]; + v16->pole_target_mat = pole_target; + + chain_pos += 3; + ik_bone_count++; + total_bone_count += 4; + break; + } + } + + if (total_bone_count != rob_bone_data->total_bone_count) + printf("Node mismatch\n"); + if (ik_bone_count != bone->ik_bone_count) + printf("LeafPos mismatch\n"); + if (chain_pos != bone->chain_pos) + printf("ChainPos mismatch\n"); +} + +static void bone_data_parent_data_init(bone_data_parent* bone, + rob_chara_data_bone_data* rob_bone_data) { + bone->rob_bone_data = rob_bone_data; + aft_bone_database_bone* common_bone_data = aft_bone_database_get_bones_by_type(rob_bone_data->base_skeleton_type); + vec3* common_translation = aft_bone_database_get_skeleton_positions_by_type(rob_bone_data->base_skeleton_type); + vec3* translation = aft_bone_database_get_skeleton_positions_by_type(rob_bone_data->skeleton_type); + bone_data_parent_load_rob_chara_data(bone); + bone_data_parent_load_bone_database(bone, common_bone_data, common_translation, translation); +} + +static void mot_parent_get_key_set_count(mot_parent* a1, size_t motion_bone_count, size_t ik_bone_count) { + a1->key_set_count = (motion_bone_count + ik_bone_count) * 3 + 16; +} + +static void mot_parent_reserve_key_sets(mot_parent* a1) { + if (a1->key_set.begin) + HeapCMallocFree(HeapCMallocSystem, a1->key_set.begin); + + size_t key_set_count = a1->key_set_count; + a1->key_set.begin = HeapCMallocAllocate(HeapCMallocSystem, + key_set_count * sizeof(mot_key_set), "ALLOCsys"); + a1->key_set.end = a1->key_set.begin + key_set_count; + a1->key_set.capacity_end = a1->key_set.begin + key_set_count; + + for (mot_key_set* i = a1->key_set.begin; i != a1->key_set.end; i++) { + i->type = 0; + i->keys_count = 0; + i->current_key = 0; + i->last_key = 0; + i->frames = 0; + i->values = 0; + } + + if (a1->key_set_data.begin) + HeapCMallocFree(HeapCMallocSystem, a1->key_set_data.begin); + + a1->key_set_data.begin = HeapCMallocAllocate(HeapCMallocSystem, + key_set_count * sizeof(float_t), "ALLOCsys"); + a1->key_set_data.end = a1->key_set_data.begin + key_set_count; + a1->key_set_data.capacity_end = a1->key_set_data.begin + key_set_count; + + for (float_t* i = a1->key_set_data.begin; i != a1->key_set_data.end; i++) + *i = 0.0f; + + a1->mot.key_sets = a1->key_set.begin; + a1->key_sets_ready = true; +} + +static void mot_parent_init_key_sets(mot_parent* a1, aft_bone_database_skeleton_type type, + size_t motion_bone_count, size_t ik_bone_count) { + mot_parent_get_key_set_count(a1, motion_bone_count, ik_bone_count); + mot_parent_reserve_key_sets(a1); + a1->skeleton_type = type; +} + +static void sub_14040F650(struc_313* a1, size_t a2) { + uint32_t* v5 = a1->bitfield.end; + uint32_t* v6 = a1->bitfield.begin; + size_t v7 = (a2 + 31) >> 5; + if ((ssize_t)v7 < v5 - v6) { + uint32_t* v8 = &v6[v7]; + if (v8 == v6) + a1->bitfield.end = v6; + else if (v8 != v5) { + memmove(&v6[v7], v5, 0); + a1->bitfield.end = v8; + } + } + a1->motion_bone_count = a2; + + a2 &= 0x1F; + if (a2) + a1->bitfield.begin[v7 - 1] &= (1 << a2) - 1; +} + +static struc_314* sub_1404122C0(struc_313* a1, struc_314* a2, struc_314* a3, struc_314* a4) { + uint32_t* v4 = a1->bitfield.begin; + size_t v7 = a1->motion_bone_count; + + struc_314 v8; + v8.field_0 = a1->bitfield.begin; + v8.field_8 = 0; + if (v7) { + size_t v12 = (a3->field_0 - v4) * 32 + a3->field_8; + v8.field_0 = &v4[v12 >> 5]; + v8.field_8 = v12 & 0x1F; + } + + struc_314 v16; + v16.field_0 = a1->bitfield.begin; + v16.field_8 = 0; + if (v7) { + size_t v17 = (a4->field_0 - v4) * 32 + a4->field_8; + v16.field_0 = &v4[v17 >> 5]; + v16.field_8 = v17 & 0x1F; + } + + if (v8.field_0 != v16.field_0 || v8.field_8 != v16.field_8) { + size_t v19 = 0; + if (v7) { + v4 += v7 >> 5; + v19 = a1->motion_bone_count & 0x1F; + } + + struc_314 v20 = v16; + struc_314 v22 = v8; + while (v20.field_0 != v4 || v20.field_8 != v19) { + if (*v20.field_0 & (1 << v20.field_8) ) + *v22.field_0 |= 1 << v22.field_8; + else + *v22.field_0 &= ~(1 << v22.field_8); + + if (v22.field_8 >= 0x1F) { + v22.field_8 = 0; + v22.field_0++; + } + else + v22.field_8++; + + if (v20.field_8 >= 0x1F) { + v20.field_8 = 0; + v20.field_0++; + } + else + v20.field_8++; + } + sub_14040F650(a1, (v22.field_0 - a1->bitfield.begin) * 32 + v22.field_8); + } + + size_t v18 = (v8.field_0 - v4) * 32 + v8.field_8; + a2->field_0 = &a1->bitfield.begin[v18 >> 5]; + a2->field_8 = v18 & 0x1F; + return a2; +} + +static void sub_1404119A0(struc_313* a1) { + uint32_t* v1 = a1->bitfield.begin; + size_t v2 = a1->motion_bone_count; + struc_314 v3; + v3.field_0 = &v1[v2 >> 5]; + v3.field_8 = v2 & 0x1F; + struc_314 v4; + v4.field_0 = v1; + v4.field_8 = 0; + struc_314 v5; + sub_1404122C0(a1, &v5, &v4, &v3); +} + +static uint32_t* sub_14040BDB0(uint32_t* a1, uint32_t* a2, uint32_t* a3) { + for (; a1 != a2; a1++, a3++) + *a3 = *a1; + return a3; +} + +static void sub_14040BD00(uint32_t* a1, size_t a2, uint32_t* a3) { + for (; a2; a1++, a2--) + *a1 = *a3; +} + +static void sub_14040E690(struc_313* a1, uint32_t** a2, uint32_t* a3, size_t a4, uint32_t* a5) { + size_t v8 = a3 - a1->bitfield.begin; + if (!a4) { + *a2 = &a1->bitfield.begin[v8]; + return; + } + + uint32_t* v9 = a1->bitfield.end; + if (a1->bitfield.capacity_end - v9 >= (ssize_t)a4) { + if (v9 - a3 >= (ssize_t)a4) { + uint32_t v20 = *a5; + size_t v21 = a4; + uint32_t* v22 = &v9[-(ssize_t)a4]; + a1->bitfield.end = sub_14040BDB0(v22, v9, v9); + memmove(&v9[-(v22 - a3)], a3, 4 * (v22 - a3)); + for (uint32_t* i = a3; i != &a3[v21]; i++) + *i = v20; + } + else { + uint32_t v17 = *a5; + uint32_t v26 = *a5; + sub_14040BDB0(a3, v9, &a3[a4]); + sub_14040BD00(a1->bitfield.end, a4 - (a1->bitfield.end - a3), &v26); + a1->bitfield.end += a4; + uint32_t* v18 = &a1->bitfield.end[-(ssize_t)a4]; + for (uint32_t* i = a3; i != v18; i++) + *i = v17; + } + } + else { + uint32_t* v7 = a1->bitfield.begin; + size_t v10 = v9 - v7; + size_t v11 = a1->bitfield.capacity_end - v7; + size_t v12; + if (UINT64_MAX / sizeof(uint32_t) - (v11 >> 1) >= v11) + v12 = (v11 >> 1) + v11; + else + v12 = 0; + if (v12 < v10 + a4) + v12 = v10 + a4; + uint32_t* v14 = HeapCMallocAllocate(HeapCMallocSystem, sizeof(uint32_t) * v12, "ALLOCsys"); + size_t v15 = a3 - a1->bitfield.begin; + sub_14040BD00(&v14[v15], a4, a5); + sub_14040BDB0(a1->bitfield.begin, a3, v14); + sub_14040BDB0(a3, a1->bitfield.end, &v14[v15 + a4]); + size_t v16 = a1->bitfield.end - a1->bitfield.begin + a4; + if (a1->bitfield.begin) + HeapCMallocFree(HeapCMallocSystem, a1->bitfield.begin); + a1->bitfield.capacity_end = &v14[v12]; + a1->bitfield.end = &v14[v16]; + a1->bitfield.begin = v14; + } + *a2 = &a1->bitfield.begin[v8]; +} + +static void sub_140413F30(struc_313* a1, size_t a2, uint32_t* a3) { + uint32_t* v3 = a1->bitfield.end; + uint32_t* v5 = a1->bitfield.begin; + size_t v6 = v3 - v5; + if (v6 > a2) { + uint32_t* v7 = &v5[a2]; + if (v7 == v5) + a1->bitfield.end = v5; + else if (v7 != v3) + a1->bitfield.end = v7; + } + else if (v6 < a2) { + uint32_t* a2a; + sub_14040E690(a1, &a2a, v3, a2 - v6, a3); + } +} + +static size_t sub_14040EB30(struc_313* a1, struc_314* a2, size_t a3) { + size_t v5 = (a2->field_0 - a1->bitfield.begin) * 32 + a2->field_8; + if (!a3) + return v5; + + size_t v6 = a1->motion_bone_count; + uint32_t v21 = 0; + sub_140413F30(a1, (v6 + a3 + 31) >> 5, &v21); + v6 = a1->motion_bone_count; + if (!v6) { + a1->motion_bone_count = a3; + return v5; + } + + size_t v11 = a3 + v6; + uint32_t* v9 = a1->bitfield.begin; + struc_314 v14; + v14.field_0 = &v9[v6 >> 5]; + v14.field_8 = v6 & 0x1F; + a1->motion_bone_count = v11; + struc_314 v16; + v16.field_0 = &v9[v11 >> 5]; + v16.field_8 = v11 & 0x1F; + struc_314 v12; + v12.field_0 = &v9[v5 >> 5]; + v12.field_8 = v5 & 0x1F; + while (v12.field_0 != v14.field_0 || v12.field_8 != v14.field_8) { + if (v14.field_8) + v14.field_8--; + else { + v14.field_8 = 31; + v14.field_0--; + } + + if (v16.field_8) + v16.field_8--; + else { + v16.field_8 = 31; + v16.field_0--; + } + + if (*v14.field_0 & (1 << v14.field_8)) + *v16.field_0 |= 1 << v16.field_8; + else + *v16.field_0 &= ~(1 << v16.field_8); + } + return v5; +} + +static struc_314* sub_14040E980(struc_313* a1, struc_314* a2, struc_314* a3, size_t a4, bool* a5) { + struc_314 v20 = *a3; + size_t v8 = sub_14040EB30(a1, &v20, a4); + uint32_t* v9 = a1->bitfield.begin; + + size_t v10 = v8 + a4; + struc_314 v12; + v12.field_0 = &v9[v10 >> 5]; + v12.field_8 = v10 & 0x1F; + v20.field_0 = &v9[v8 >> 5]; + v20.field_8 = v8 & 0x1F; + while (v20.field_0 != v12.field_0 || v20.field_8 != v12.field_8) { + if (*a5) + *v20.field_0 |= (1 << v20.field_8); + else + *v20.field_0 &= ~(1 << v20.field_8); + + if (v20.field_8 >= 0x1F) { + v20.field_8 = 0; + v20.field_0++; + } + else + v20.field_8++; + } + + uint32_t* v17 = a1->bitfield.begin; + a2->field_0 = &v17[v8 >> 5]; + a2->field_8 = v8 & 0x1F; + return a2; +} + +static void sub_140414550(struc_313* a1, size_t a2, char a3) { + struc_314 a3a; + struc_314 a4; + struc_314 a2a; + + size_t v3 = a1->motion_bone_count; + if (a2 <= v3) { + if (a2 < v3) { + uint32_t* v6 = a1->bitfield.begin; + a4.field_0 = &v6[v3 >> 5]; + a4.field_8 = v3 & 0x1F; + a3a.field_0 = &v6[a2 >> 5]; + a3a.field_8 = a2 & 0x1F; + sub_1404122C0(a1, &a2a, &a3a, &a4); + } + } + else { + uint32_t* v5 = a1->bitfield.begin; + a3a.field_0 = &v5[v3 >> 5]; + a3a.field_8 = v3 & 0x1F; + a4 = a3a; + sub_14040E980(a1, &a3a, &a4, a2 - v3, &a3); + } +} + +static void sub_1404146F0(struc_240* a1) { + struc_314 v1; + v1.field_0 = a1->field_8.bitfield.begin; + v1.field_8 = 0; + motion_bone_index v2 = MOTION_BONE_N_HARA_CP; + size_t v5 = a1->field_8.motion_bone_count; + uint32_t* v6 = a1->field_8.bitfield.begin; + while (true) { + struc_314 v7; + v7.field_0 = &v6[v5 >> 5]; + v7.field_8 = v5 & 0x1F; + if (v1.field_0 == v7.field_0 && v1.field_8 == v7.field_8) + break; + + if (a1->bone_check_func(v2++)) + *v1.field_0 |= 1 << v1.field_8; + else + *v1.field_0 &= ~(1 << v1.field_8); + + if (v1.field_8 >= 0x1F) { + v1.field_8 = 0; + v1.field_0++; + } + else + v1.field_8++; + } +} + +static void sub_140413350(struc_240* a1, bool(*bone_check_func)(motion_bone_index), size_t motion_bone_count) { + a1->bone_check_func = bone_check_func; + a1->motion_bone_count = motion_bone_count; + sub_1404119A0(&a1->field_8); + sub_140414550(&a1->field_8, motion_bone_count, 0); + sub_1404146F0(a1); +} + +static void motion_blend_mot_load_bone_data(motion_blend_mot* a1, rob_chara_data_bone_data* rob_bone_data, + bool(*bone_check_func)(motion_bone_index)) { + bone_data_parent_data_init(&a1->bone_data, rob_bone_data); + mot_parent_init_key_sets( + &a1->mot_data, + a1->bone_data.rob_bone_data->base_skeleton_type, + a1->bone_data.motion_bone_count, + a1->bone_data.ik_bone_count); + sub_140413350(&a1->field_0, bone_check_func, a1->bone_data.motion_bone_count); +} + +static void sub_140414900(struc_308* a1, mat4* mat) { + if (mat) { + mat4_to_mat4u(mat, &a1->mat); + a1->field_8C = true; + } + else { + a1->mat = mat4u_identity; + a1->field_8C = false; + } +} + +static void sub_1401EA670(bone_data* a1, vec3* a2) { + mat4 mat; + mat4_transpose(a1->node[0].mat, &mat); + + vec3 v15; + mat4_mult_vec3_inv(&mat, a2, &v15); + + float_t len; + vec3_length_squared(v15, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v15, 1.0f / len, v15); + + vec3 v17; + v17.x = -v15.z * v15.x - v15.z; + v17.y = -v15.y * v15.z; + v17.z = v15.x * v15.x + v15.y * v15.y + v15.x; + vec3_length_squared(v17, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v17, 1.0f / len, v17); + + vec3 v16; + vec3_cross(v17, v15, v16); + + mat4 rot_mat = mat4_identity; + *(vec3*)&rot_mat.row0 = v15; + *(vec3*)&rot_mat.row1 = v16; + *(vec3*)&rot_mat.row2 = v17; + + mat4_mult(&rot_mat, &mat, &mat); + mat4_transpose(&mat, a1->node[0].mat); +} + +static void sub_1401EAC20(bone_data* a1, vec3* a2, float_t a3) { + float_t len; + vec3 v8; + + mat4 mat; + mat4_transpose(a1->node[0].mat, &mat); + mat4_mult_vec3_inv(&mat, a2, &v8); + v8.x = 0.0f; + vec3_length(v8, len); + if (len <= 0.000001f) + return; + + vec3_mult_scalar(v8, 1.0f / len, v8); + float_t angle = atan2f(v8.z, v8.y); + mat4_rotate_x_mult(&mat, angle * a3, &mat); + mat4_transpose(&mat, a1->node[0].mat); +} + +static void sub_1401EA970(bone_data* a1, vec3* a2) { + vec3 v9 = *a2; + + float_t len; + vec3_length_squared(v9, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v9, 1.0f / len, v9); + + vec3 v8; + v8.x = -v9.z * v9.x; + v8.y = -v9.z * v9.y - v9.z; + v8.z = v9.y * v9.y - v9.x * -v9.x + v9.y; + + vec3_length_squared(v8, len); + if (len <= 0.000001f) + return; + + len = sqrtf(len); + if (len != 0.0f) + vec3_mult_scalar(v8, 1.0f / len, v8); + + vec3 v10; + vec3_cross(v9, v8, v10); + + mat4 rot_mat = mat4_identity; + *(vec3*)&rot_mat.row0 = v10; + *(vec3*)&rot_mat.row1 = v9; + *(vec3*)&rot_mat.row2 = v8; + + mat4 mat; + mat4_transpose(a1->node[0].mat, &mat); + mat4_mult(&rot_mat, &mat, &mat); + mat4_transpose(&mat, a1->node[0].mat); +} + +static bool sub_1401E9D60(bone_data* a1, bone_data* a2) { + bone_node* v5; + vec3 v30; + mat4 mat; + + switch (a1->motion_bone_index) { + case MOTION_BONE_N_SKATA_L_WJ_CD_EX: + v5 = a2[MOTION_BONE_C_KATA_L].node; + mat4_transpose(v5[2].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EA670(a1, &v30); + break; + case MOTION_BONE_N_SKATA_R_WJ_CD_EX: + v5 = a2[MOTION_BONE_C_KATA_R].node; + mat4_transpose(v5[2].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EA670(a1, &v30); + break; + case MOTION_BONE_N_SKATA_B_L_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_L_EX].node; + mat4_transpose(v5[0].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EAC20(a1, &v30, 0.333f); + break; + case MOTION_BONE_N_SKATA_B_R_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_R_EX].node; + mat4_transpose(v5[0].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EAC20(a1, &v30, 0.333f); + break; + case MOTION_BONE_N_SKATA_C_L_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_L_EX].node; + mat4_transpose(v5[0].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EAC20(a1, &v30, 0.5f); + break; + case MOTION_BONE_N_SKATA_C_R_WJ_CD_CU_EX: + v5 = a2[MOTION_BONE_N_UP_KATA_R_EX].node; + mat4_transpose(v5[0].mat, &mat); + mat4_get_translation(&mat, &v30); + sub_1401EAC20(a1, &v30, 0.5f); + break; + case MOTION_BONE_N_MOMO_A_L_WJ_CD_EX: + v5 = a2[MOTION_BONE_CL_MOMO_L].node; + mat4_transpose(v5[2].mat, &mat); + mat4_get_translation(&mat, &v30); + mat4_transpose(a1->node[0].mat, &mat); + mat4_mult_vec3_inv(&mat, &v30, &v30); + vec3_negate(v30, v30); + sub_1401EA970(a1, &v30); + break; + case MOTION_BONE_N_MOMO_A_R_WJ_CD_EX: + v5 = a2[MOTION_BONE_CL_MOMO_R].node; + mat4_transpose(v5[2].mat, &mat); + mat4_get_translation(&mat, &v30); + mat4_transpose(a1->node[0].mat, &mat); + mat4_mult_vec3_inv(&mat, &v30, &v30); + vec3_negate(v30, v30); + sub_1401EA970(a1, &v30); + break; + case MOTION_BONE_N_HARA_CD_EX: + v5 = a2[MOTION_BONE_KL_MUNE_B_WJ].node; + mat4_transpose(v5[0].mat, &mat); + mat4_get_translation(&mat, &v30); + mat4_transpose(a1->node[0].mat, &mat); + mat4_mult_vec3_inv(&mat, &v30, &v30); + sub_1401EA970(a1, &v30); + break; + default: + return false; + } + return true; +} + +static float_t sub_1401E9D10(float_t a1) { + bool neg; + if (a1 < 0.0f) { + a1 = -a1; + neg = true; + } + else + neg = false; + + a1 = fmodf(a1 + (float_t)M_PI, (float_t)(M_PI * 2.0)) - (float_t)M_PI; + if (neg) + return -a1; + else + return a1; +} + +static bool sub_1401EA070(bone_data* a1, bone_node_expression_data* a2, bone_data* a3) { + float_t v10; + bone_node* v11; + vec3 v15; + mat4 dst; + mat4 mat; + + bool ret = true; + switch (a1->motion_bone_index) { + case MOTION_BONE_N_EYE_L_WJ_EX: + a2->rotation.x = -a3[MOTION_BONE_KL_EYE_L].node[0].exp_data.rotation.x; + a2->rotation.y = a3[MOTION_BONE_KL_EYE_L].node[0].exp_data.rotation.y * (float_t)(-1.0 / 2.0); + break; + case MOTION_BONE_N_EYE_R_WJ_EX: + a2->rotation.x = -a3[MOTION_BONE_KL_EYE_R].node[0].exp_data.rotation.x; + a2->rotation.y = a3[MOTION_BONE_KL_EYE_R].node[0].exp_data.rotation.y * (float_t)(-1.0 / 2.0); + break; + case MOTION_BONE_N_KUBI_WJ_EX: + mat4u_to_mat4_transpose(&a3[MOTION_BONE_CL_KAO].rot_mat[0], &dst); + mat4u_to_mat4_transpose(&a3[MOTION_BONE_CL_KAO].rot_mat[1], &mat); + mat4_mult(&mat, &dst, &dst); + mat4_get_rotation(&dst, &v15); + v10 = v15.z; + if (v10 < (float_t)-M_PI_2) + v10 += (float_t)(M_PI * 2.0); + a2->rotation.y = (v10 - (float_t)M_PI_2) * 0.2f; + break; + case MOTION_BONE_N_HITO_L_EX: + case MOTION_BONE_N_HITO_R_EX: + a2->rotation.z = (float_t)(-9.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_KO_L_EX: + a2->rotation.x = (float_t)(-8.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(16.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_KUSU_L_EX: + case MOTION_BONE_N_KUSU_R_EX: + a2->rotation.z = (float_t)(9.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_NAKA_L_EX: + case MOTION_BONE_N_NAKA_R_EX: + a2->rotation.z = (float_t)(-1.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_OYA_L_EX: + a2->rotation.x = (float_t)(75.0 * DEG_TO_RAD); + a2->rotation.y = (float_t)(12.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(-24.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_STE_L_WJ_EX: + a2->rotation.x = a3[MOTION_BONE_KL_TE_L_WJ].node[0].exp_data.rotation.x; + break; + case MOTION_BONE_N_SUDE_L_WJ_EX: + case MOTION_BONE_N_SUDE_B_L_WJ_EX: + v11 = &a3[MOTION_BONE_KL_TE_L_WJ].node[0]; + a2->rotation.x = sub_1401E9D10(v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_SUDE_R_WJ_EX: + case MOTION_BONE_N_SUDE_B_R_WJ_EX: + v11 = &a3[MOTION_BONE_KL_TE_R_WJ].node[0]; + a2->rotation.x = sub_1401E9D10(v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_HIJI_L_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_C_KATA_L].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_UP_KATA_L_EX: + case MOTION_BONE_N_UP_KATA_R_EX: + break; + case MOTION_BONE_N_KO_R_EX: + a2->rotation.x = (float_t)(8.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(16.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_OYA_R_EX: + a2->rotation.x = (float_t)(-75.0 * DEG_TO_RAD); + a2->rotation.y = (float_t)(-12.0 * DEG_TO_RAD); + a2->rotation.z = (float_t)(-24.0 * DEG_TO_RAD); + break; + case MOTION_BONE_N_STE_R_WJ_EX: + a2->rotation.x = a3[MOTION_BONE_KL_TE_R_WJ].node[0].exp_data.rotation.x; + break; + case MOTION_BONE_N_HIJI_R_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_C_KATA_R].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_HIZA_L_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_CL_MOMO_L].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_HIZA_R_WJ_EX: + a2->rotation.z = a3[MOTION_BONE_CL_MOMO_R].node[2].exp_data.rotation.z * (float_t)(1.0 / 2.0); + break; + case MOTION_BONE_N_MOMO_B_L_WJ_EX: + case MOTION_BONE_N_MOMO_C_L_WJ_EX: + v11 = &a3[MOTION_BONE_CL_MOMO_L].node[0]; + a2->rotation.y = sub_1401E9D10(v11->exp_data.rotation.y + + v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_MOMO_B_R_WJ_EX: + case MOTION_BONE_N_MOMO_C_R_WJ_EX: + v11 = &a3[MOTION_BONE_CL_MOMO_R].node[0]; + a2->rotation.y = sub_1401E9D10(v11->exp_data.rotation.y + + v11->exp_data.rotation.x) * (float_t)(1.0 / 3.0); + break; + case MOTION_BONE_N_HARA_B_WJ_EX: + a2->rotation.y = a3[MOTION_BONE_CL_MUNE].node[0].exp_data.rotation.y * (float_t)(1.0 / 3.0) + + a3[MOTION_BONE_KL_KOSI_Y].node[0].exp_data.rotation.y * (float_t)(2.0 / 3.0); + break; + case MOTION_BONE_N_HARA_C_WJ_EX: + a2->rotation.y = a3[MOTION_BONE_CL_MUNE].node[0].exp_data.rotation.y * (float_t)(2.0 / 3.0) + + a3[MOTION_BONE_KL_KOSI_Y].node[0].exp_data.rotation.y * (float_t)(1.0 / 3.0); + break; + default: + ret = false; + break; + } + return ret; +} + +void bone_data_mult_ik(bone_data* a1, int32_t skeleton_select) { + if (a1->type < AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION) + return; + + mat4 mat; + mat4_transpose(a1->node[0].mat, &mat); + + vec3 v30; + mat4_mult_vec3_inv(&mat, &a1->ik_target, &v30); + float_t v6; + float_t v8; + vec2_length_squared(*(vec2*)&v30, v6); + vec3_length_squared(v30, v8); + float_t v9 = sqrtf(v6); + float_t v10 = sqrtf(v8); + mat4 rot_mat; + if (v9 > 0.000001f && v8 > 0.000001f) { + mat4_rotate_z_sin_cos(v30.y / v9, v30.x / v9, &rot_mat); + mat4_rotate_y_mult_sin_cos(&rot_mat, -v30.z / v10, v9 / v10, &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + } + else + rot_mat = mat4_identity; + + if (a1->pole_target_mat) { + mat4 pole_target_mat; + mat4_transpose(a1->pole_target_mat, &pole_target_mat); + vec3 pole_target; + mat4_get_translation(&pole_target_mat, &pole_target); + mat4_mult_vec3_inv(&mat, &pole_target, &pole_target); + float_t pole_target_length; + vec2_length(*(vec2*)&pole_target.y, pole_target_length); + if (pole_target_length > 0.000001f) { + vec3_mult_scalar(pole_target, 1.0f / pole_target_length, pole_target); + float_t cos_val = pole_target.y; + float_t sin_val = pole_target.z; + mat4_rotate_x_mult_sin_cos(&mat, sin_val, cos_val, &mat); + mat4_rotate_x_mult_sin_cos(&rot_mat, sin_val, cos_val, &rot_mat); + } + } + + if (a1->type == AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION) { + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[1]); + mat4_transpose(&mat, a1->node[1].mat); + mat4_translate_mult(&mat, a1->ik_segment_length[skeleton_select], 0.0f, 0.0f, &mat); + mat4_transpose(&mat, a1->node[2].mat); + return; + } + + float_t v20 = a1->ik_2nd_segment_length[skeleton_select]; + float_t v21 = a1->ik_segment_length[skeleton_select]; + float_t v22; + float_t v23; + float_t v24; + float_t v25; + if (fabsf(v8) > 0.000001f) { + float_t v26 = a1->field_2E0; + if (v26 > 0.0001f) { + float_t v27 = (v21 + v20) * v26; + if (v10 > v27) { + v10 = v27; + v8 = v27 * v27; + } + } + float_t v28 = (v8 - v20 * v20) / v21; + v23 = (v28 + v21) / (2.0f * v10); + v22 = (v28 - v21) / (2.0f * v20); + + v23 = clamp(v23, -1.0f, 1.0f); + v22 = clamp(v22, -1.0f, 1.0f); + + v24 = sqrtf(1.0f - v23 * v23); + v25 = sqrtf(1.0f - v22 * v22); + if (a1->type == AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION) + v24 = -v24; + else + v25 = -v25; + } + else { + v22 = -1.0f; + v23 = 1.0f; + v24 = 0.0f; + v25 = 0.0f; + } + + mat4_rotate_z_mult_sin_cos(&mat, v24, v23, &mat); + mat4_transpose(&mat, a1->node[1].mat); + mat4_rotate_z_mult_sin_cos(&rot_mat, v24, v23, &rot_mat); + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[1]); + mat4_translate_mult(&mat, v21, 0.0f, 0.0f, &mat); + mat4_rotate_z_mult_sin_cos(&mat, v25, v22, &mat); + mat4_transpose(&mat, a1->node[2].mat); + mat4_rotate_z_sin_cos(v25, v22, &rot_mat); + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[2]); + mat4_translate_mult(&mat, v20, 0.0f, 0.0f, &mat); + mat4_transpose(&mat, a1->node[3].mat); +} + +static void bone_data_mult_0(bone_data* a1, int32_t skeleton_select) { + if (a1->flags != 0) + return; + + mat4 mat; + if (a1->has_parent) + mat4_transpose(a1->parent_mat, &mat); + else + mat = mat4_identity; + + if (a1->type == AFT_BONE_DATABASE_BONE_POSITION) { + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + a1->rot_mat[0] = mat4u_identity; + } + else if (a1->type == AFT_BONE_DATABASE_BONE_TYPE_1) { + mat4_mult_vec3_inv(&mat, &a1->trans, &a1->trans); + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + a1->rot_mat[0] = mat4u_identity; + } + else { + mat4 rot_mat; + if (a1->type == AFT_BONE_DATABASE_BONE_POSITION_ROTATION) { + mat4u_to_mat4_transpose(&a1->rot_mat[0], &rot_mat); + mat4_rotate_z_mult(&rot_mat, a1->rotation.z, &rot_mat); + } + else { + a1->trans = a1->base_translation[skeleton_select]; + mat4_rotate_z(a1->rotation.z, &rot_mat); + } + + mat4_rotate_y_mult(&rot_mat, a1->rotation.y, &rot_mat); + + if (a1->motion_bone_index == MOTION_BONE_KL_EYE_L + || a1->motion_bone_index == MOTION_BONE_KL_EYE_R) { + if (a1->rotation.x > 0.0) + a1->rotation.x *= a1->eyes_xrot_adjust_pos; + else if (a1->rotation.x < 0.0) + a1->rotation.x *= a1->eyes_xrot_adjust_neg; + } + + mat4_rotate_x_mult(&rot_mat, a1->rotation.x, &rot_mat); + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + mat4_mult(&rot_mat, &mat, &mat); + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[0]); + } + + mat4_transpose(&mat, a1->node[0].mat); + + bone_data_mult_ik(a1, skeleton_select); +} + +void bone_data_mult_1(bone_data* a1, mat4* parent_mat, bone_data* a3, bool a4) { + mat4 mat; + mat4 rot_mat; + if (a1->has_parent) + mat4_transpose(a1->parent_mat, &mat); + else + mat4_transpose(parent_mat, &mat); + + if (a1->type != AFT_BONE_DATABASE_BONE_TYPE_1 && a1->type != AFT_BONE_DATABASE_BONE_POSITION) { + if (a1->type != AFT_BONE_DATABASE_BONE_POSITION_ROTATION) + a1->trans = a1->base_translation[1]; + + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + if (a4) { + a1->node[0].exp_data.rotation = vec3_null; + if (!a1->flags) { + mat4u_to_mat4_transpose(&a1->rot_mat[0], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[0].exp_data.rotation); + } + else if (sub_1401EA070(a1, &a1->node[0].exp_data, a3)) { + vec3 rotation = a1->node[0].exp_data.rotation; + mat4_rotate(rotation.x, rotation.y, rotation.z, &rot_mat); + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[0]); + } + else { + mat4_transpose(&mat, a1->node[0].mat); + + if (sub_1401E9D60(a1, a3)) { + mat4 dst; + mat4_invrot_normalized(&mat, &rot_mat); + mat4_transpose(a1->node[0].mat, &dst); + mat4_mult(&dst, &rot_mat, &rot_mat); + mat4_clear_trans(&rot_mat, &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[0].exp_data.rotation); + mat4_to_mat4u_transpose(&rot_mat, &a1->rot_mat[0]); + } + else + a1->rot_mat[0] = mat4u_identity; + } + } + + mat4u_to_mat4_transpose(&a1->rot_mat[0], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + + } + else { + mat4_translate_mult(&mat, a1->trans.x, a1->trans.y, a1->trans.z, &mat); + if (a4) + a1->node[0].exp_data.rotation = vec3_null; + } + + mat4_transpose(&mat, a1->node[0].mat); + if (a4) { + a1->node[0].exp_data.position = a1->trans; + bone_node_expression_data_reset_scale(&a1->node[0].exp_data); + } + + if (a1->type < AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION) + return; + + mat4u_to_mat4_transpose(&a1->rot_mat[1], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + mat4_transpose(&mat, a1->node[1].mat); + mat4_translate_mult(&mat, a1->ik_segment_length[1], 0.0f, 0.0f, &mat); + + if (a1->type == AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION) { + mat4_transpose(&mat, a1->node[2].mat); + if (!a4) + return; + + a1->node[1].exp_data.position = vec3_null; + mat4u_to_mat4_transpose(&a1->rot_mat[1], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[1].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[1].exp_data); + bone_node_expression_data_set_position_rotation(&a1->node[2].exp_data, + a1->ik_segment_length[1], 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + else { + mat4u_to_mat4_transpose(&a1->rot_mat[2], &rot_mat); + mat4_mult(&rot_mat, &mat, &mat); + mat4_transpose(&mat, a1->node[2].mat); + mat4_translate_mult(&mat, a1->ik_2nd_segment_length[1], 0.0f, 0.0f, &mat); + mat4_transpose(&mat, a1->node[3].mat); + if (!a4) + return; + + a1->node[1].exp_data.position = vec3_null; + mat4u_to_mat4_transpose(&a1->rot_mat[1], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[1].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[1].exp_data); + a1->node[2].exp_data.position.x = a1->ik_segment_length[1]; + *(vec2*)&a1->node[2].exp_data.position.y = vec2_null; + mat4u_to_mat4_transpose(&a1->rot_mat[2], &rot_mat); + mat4_get_rotation(&rot_mat, &a1->node[2].exp_data.rotation); + bone_node_expression_data_reset_scale(&a1->node[2].exp_data); + bone_node_expression_data_set_position_rotation(&a1->node[3].exp_data, + a1->ik_2nd_segment_length[1], 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } +} + +void bone_data_mult_2(rob_chara_data_bone_data* rob_bone_data, mat4* mat) { + for (bone_node* i = rob_bone_data->nodes.begin; i != rob_bone_data->nodes.end; i++) + mat4_mult(i->mat, mat, i->mat); + sub_140414900(&rob_bone_data->motion_loaded.head->next->value->field_4F8, mat); +} + +static void sub_140413EB0(struc_308* a1) { + a1->field_8C = false; + a1->field_4C = a1->mat; + a1->mat = mat4u_identity; +} + +static void sub_1404117F0(motion_blend_mot* a1) { + sub_140413EB0(&a1->field_4F8); + int32_t skeleton_select = a1->mot_data.skeleton_select; + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) + bone_data_mult_0(i, skeleton_select); +} + +static void sub_14040FBF0(motion_blend_mot* a1, float_t a2) { + bone_data* b_n_hara_cp = &a1->bone_data.bones.begin[MOTION_BONE_N_HARA_CP]; + bone_data* b_kg_hara_y = &a1->bone_data.bones.begin[MOTION_BONE_KG_HARA_Y]; + bone_data* b_kl_hara_xz = &a1->bone_data.bones.begin[MOTION_BONE_KL_HARA_XZ]; + bone_data* b_kl_hara_etc = &a1->bone_data.bones.begin[MOTION_BONE_KL_HARA_ETC]; + a1->field_4F8.field_90 = vec3_null; + + mat4 rot_mat; + mat4 mat; + mat4u_to_mat4_transpose(&b_n_hara_cp->rot_mat[0], &rot_mat); + mat4u_to_mat4_transpose(&b_kg_hara_y->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4u_to_mat4_transpose(&b_kl_hara_xz->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4u_to_mat4_transpose(&b_kl_hara_etc->rot_mat[0], &mat); + mat4_mult(&mat, &rot_mat, &rot_mat); + mat4_to_mat4u_transpose(&rot_mat, &b_n_hara_cp->rot_mat[0]); + b_kg_hara_y->rot_mat[0] = mat4u_identity; + b_kl_hara_xz->rot_mat[0] = mat4u_identity; + b_kl_hara_etc->rot_mat[0] = mat4u_identity; + + float_t v8 = a1->field_4F8.field_C0; + float_t v9 = a1->field_4F8.field_C4; + vec3 v10 = a1->field_4F8.field_C8; + a1->field_4F8.field_A8 = b_n_hara_cp->trans; + if (!a1->mot_data.skeleton_select) { + if (a2 != v9) { + b_n_hara_cp->trans.x = (b_n_hara_cp->trans.x - v10.x) * v9 + v10.x; + b_n_hara_cp->trans.z = (b_n_hara_cp->trans.z - v10.z) * v9 + v10.z; + } + b_n_hara_cp->trans.y = ((b_n_hara_cp->trans.y - v10.y) * v8) + v10.y; + } + else { + if (a2 != v9) { + v9 /= a2; + b_n_hara_cp->trans.x = (b_n_hara_cp->trans.x - v10.x) * v9 + v10.x; + b_n_hara_cp->trans.z = (b_n_hara_cp->trans.z - v10.z) * v9 + v10.z; + } + + if (a2 != v8) { + v8 /= a2; + b_n_hara_cp->trans.y = (b_n_hara_cp->trans.y - v10.y) * v8 + v10.y; + } + } +} + +static bool sub_1404136B0(motion_blend_mot* a1) { + motion_blend* v1 = a1->field_5D0; + if (v1) + return v1->__vftable->field_30(v1); + else + return false; +} + +static bool sub_140410250(struc_313* a1, size_t a2) { + return (a1->bitfield.begin[a2 >> 5] & (1 << (a2 & 0x1F))) != 0; +} + +static void sub_140410A40(motion_blend_mot* a1, vector_bone_data* a2, vector_bone_data* a3) { + motion_blend* v1 = a1->field_5D0; + if (!v1 || !v1->field_9) + return; + + v1->__vftable->field_20(v1, a2, a3); + for (bone_data* i = a2->begin; i != a2->end; i++) { + if (!sub_140410250(&a1->field_0.field_8, i->motion_bone_index)) + continue; + + bone_data* v8 = 0; + if (a3) + v8 = &a3->begin[i->motion_bone_index]; + v1->__vftable->field_28(v1, &a2->begin[i->motion_bone_index], v8); + } +} + +static void sub_140410B70(motion_blend_mot* a1, vector_bone_data* a2) { + motion_blend* v1 = a1->field_5D0; + if (!v1 || !v1->field_9) + return; + + v1->__vftable->field_20(v1, &a1->bone_data.bones, a2); + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) { + if (!sub_140410250(&a1->field_0.field_8, i->motion_bone_index)) + continue; + + bone_data* v6 = 0; + if (a2) + v6 = &a2->begin[i->motion_bone_index]; + v1->__vftable->field_28(a1->field_5D0, &a1->bone_data.bones.begin[i->motion_bone_index], v6); + } +} + +static motion_blend_type sub_1404125C0(motion_blend_mot* a1) { + motion_blend* v1 = a1->field_5D0; + if (v1 == &a1->cross.base) + return MOTION_BLEND_CROSS; + if (v1 == &a1->freeze.base) + return MOTION_BLEND_FREEZE; + if (v1 == &a1->combine.base.base) + return MOTION_BLEND_COMBINE; + return MOTION_BLEND; +} + +static void sub_140410CB0(mot_blend* a1, vector_bone_data* a2) { + motion_blend* v1 = &a1->field_F8; + if (!v1->field_9) + return; + + for (bone_data* i = a2->begin; i != a2->end; i++) + if (sub_140410250(&a1->field_0.field_8, i->motion_bone_index)) + v1->__vftable->field_28(&a1->field_F8, &a2->begin[i->motion_bone_index], 0); +} + +static void sub_1404182B0(rob_chara_data_bone_data* rob_bone_data) { + if (!rob_bone_data->motion_loaded.size) + return; + + list_ptr_motion_blend_mot_node* head = rob_bone_data->motion_loaded.head; + list_ptr_motion_blend_mot_node* v2 = head; + while (v2 != head->next) { + bool v2a = v2 != head; + v2 = v2->prev; + if (sub_1404136B0(v2->value)) + if (v2a) + sub_140410A40(v2->value, &v2->prev->value->bone_data.bones, + &v2->value->bone_data.bones); + } + + list_ptr_motion_blend_mot_node* v5 = head; + while (v5 != head->next) { + bool v5a = v5 != head; + v5 = v5->prev; + if (!sub_1404136B0(v5->value)) + if (v5a) + sub_140410B70(v5->value, &v5->next->value->bone_data.bones); + else if (sub_1404125C0(v5->value) == MOTION_BLEND_FREEZE) + sub_140410B70(v5->value, 0); + } + + motion_blend_mot* v3 = head->next->value; + sub_140410CB0(&rob_bone_data->face, &v3->bone_data.bones); + sub_140410CB0(&rob_bone_data->hand_l, &v3->bone_data.bones); + sub_140410CB0(&rob_bone_data->hand_r, &v3->bone_data.bones); + sub_140410CB0(&rob_bone_data->mouth, &v3->bone_data.bones); + sub_140410CB0(&rob_bone_data->eye, &v3->bone_data.bones); + sub_140410CB0(&rob_bone_data->eyelid, &v3->bone_data.bones); + + bone_data* b_n_hara_cp = &v3->bone_data.bones.begin[MOTION_BONE_N_HARA_CP]; + v3->field_4F8.field_9C = b_n_hara_cp->trans; + if (v3->field_4F8.field_0 & 2) { + v3->field_4F8.field_90 = b_n_hara_cp->trans; + b_n_hara_cp->trans = vec3_null; + } +} + +static void sub_14041B9F0(rob_chara_data_bone_data* rob_bone_data) { + list_ptr_motion_blend_mot_node* v1 = rob_bone_data->motion_loaded.head; + list_ptr_motion_blend_mot_node* v3 = v1->next; + while (v3 != v1) { + sub_1404146F0(&v3->value->field_0); + v3 = v3->next; + } + sub_1404146F0(&rob_bone_data->face.field_0); + sub_1404146F0(&rob_bone_data->eyelid.field_0); +} + +static void motion_blend_mot_mult_mat(motion_blend_mot* a1, mat4* a2) { + sub_140414900(&a1->field_4F8, a2); + + mat4 mat; + mat4u_to_mat4(&a1->field_4F8.mat, &mat); + bone_data* v3 = a1->bone_data.bones.begin; + for (bone_data* v4 = a1->bone_data.bones.begin; v4 != a1->bone_data.bones.end; v4++) + bone_data_mult_1(v4, &mat, v3, true); +} + +void rob_chara_data_bone_data_update(rob_chara_data_bone_data* rob_bone_data, mat4* a2) { + if (!rob_bone_data->motion_loaded.size) + return; + + list_ptr_motion_blend_mot_node* v4 = rob_bone_data->motion_loaded.head; + list_ptr_motion_blend_mot_node* v5 = v4->next; + while (v5 != v4) { + sub_1404117F0(v5->value); + sub_14040FBF0(v5->value, rob_bone_data->ik_scale.ratio0); + v5 = v5->next; + } + sub_1404182B0(rob_bone_data); + sub_14041B9F0(rob_bone_data); + motion_blend_mot_mult_mat(rob_bone_data->motion_loaded.head->next->value, a2); +} + +static mot_blend* mot_blend_init(mot_blend* a1) { + memset(a1, 0, sizeof(mot_blend)); + a1->field_38.frame = -1.0f; + a1->field_38.motion_id = -1; + a1->field_A8.field_8 = 1.0f; + a1->field_A8.field_4 = 1.0f; + a1->field_A8.field_10 = -1.0f; + a1->field_A8.field_14 = -1.0f; + a1->field_A8.field_18 = -1; + a1->field_A8.field_1C = -1; + a1->field_A8.field_24 = -1.0f; + a1->field_A8.field_2C = -1; + a1->field_F8.field_14 = 1.0f; + return a1; +} + +static void rob_chara_data_bone_data_eyes_xrot_adjust(rob_chara_data_bone_data* rob_bone_data, + struc_241* a2, eyes_adjust* a3) { + float_t v1_neg; + float_t v1_pos; + switch (a3->base_adjust) { + case EYES_BASE_ADJUST_DIRECTION: + default: + v1_neg = a2->field_34 * -(float_t)(1.0 / 3.8); + v1_pos = a2->field_38 * (float_t)(1.0 / 6.0); + break; + case EYES_BASE_ADJUST_CLEARANCE: + v1_neg = a2->field_3C * -(float_t)(1.0 / 3.8); + v1_pos = a2->field_40 * (float_t)(1.0 / 6.0); + break; + case EYES_BASE_ADJUST_OFF: + v1_neg = 1.0f; + v1_pos = 1.0f; + break; + } + + float_t v2_pos = 1.0f; + float_t v2_neg = 1.0f; + if (a3->xrot_adjust) { + v2_neg = a2->field_2C; + v2_pos = a2->field_30; + } + + if (a3->neg >= 0.0f && a3->pos >= 0.0f) { + v2_neg = a3->neg; + v2_pos = a3->pos; + } + + float_t eyes_xrot_adjust_neg = v1_neg * v2_neg; + float_t eyes_xrot_adjust_pos = v1_pos * v2_pos; + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) { + bone_data* data = (*i)->bone_data.bones.begin; + data[MOTION_BONE_KL_EYE_L].eyes_xrot_adjust_neg = eyes_xrot_adjust_neg; + data[MOTION_BONE_KL_EYE_L].eyes_xrot_adjust_pos = eyes_xrot_adjust_pos; + data[MOTION_BONE_KL_EYE_R].eyes_xrot_adjust_neg = eyes_xrot_adjust_neg; + data[MOTION_BONE_KL_EYE_R].eyes_xrot_adjust_pos = eyes_xrot_adjust_pos; + } +} + +static void rob_chara_data_bone_data_init_skeleton(rob_chara_data_bone_data* rob_bone_data, + aft_bone_database_skeleton_type base_skeleton_type, + aft_bone_database_skeleton_type skeleton_type) { + if (rob_bone_data->base_skeleton_type == base_skeleton_type + && rob_bone_data->skeleton_type == skeleton_type) + return; + + aft_bone_database_bone* bones = aft_bone_database_get_bones_by_type(base_skeleton_type); + rob_chara_data_bone_data_calculate_bones(rob_bone_data, bones); + rob_chara_data_bone_data_reserve(rob_bone_data); + rob_chara_data_bone_data_set_mats(rob_bone_data, bones); + uint16_t* parent_indices = aft_bone_database_get_skeleton_parent_indices_by_type(base_skeleton_type); + rob_chara_data_bone_data_set_parent_mats(rob_bone_data, parent_indices); + rob_bone_data->base_skeleton_type = base_skeleton_type; + rob_bone_data->skeleton_type = skeleton_type; +} + +static bool motion_blend_mot_check(motion_bone_index bone_index) { + return true; +} + +static bool mot_blend_face_check(motion_bone_index bone_index) { + return bone_index >= MOTION_BONE_FACE_ROOT && bone_index <= MOTION_BONE_TL_TOOTH_UPPER_WJ; +} + +static bool mot_blend_hand_l_check(motion_bone_index bone_index) { + return bone_index >= MOTION_BONE_N_HITO_L_EX && bone_index <= MOTION_BONE_NL_OYA_C_L_WJ; +} + +static bool mot_blend_hand_r_check(motion_bone_index bone_index) { + return bone_index >= MOTION_BONE_N_HITO_R_EX && bone_index <= MOTION_BONE_NL_OYA_C_R_WJ; +} + +static bool mot_blend_mouth_check(motion_bone_index bone_index) { + return (bone_index >= MOTION_BONE_N_AGO && bone_index <= MOTION_BONE_TL_TOOTH_UNDER_WJ) + || (bone_index >= MOTION_BONE_N_KUTI_D && bone_index <= MOTION_BONE_TL_KUTI_U_R_WJ) + || (bone_index >= MOTION_BONE_N_TOOTH_UPPER && bone_index <= MOTION_BONE_TL_TOOTH_UPPER_WJ); +} + +static bool mot_blend_eye_check(motion_bone_index bone_index) { + return bone_index >= MOTION_BONE_N_EYE_L && bone_index <= MOTION_BONE_KL_HIGHLIGHT_R_WJ; +} + +static bool mot_blend_eyelid_check(motion_bone_index bone_index) { + return (bone_index >= MOTION_BONE_N_EYE_L && bone_index <= MOTION_BONE_KL_HIGHLIGHT_R_WJ) + || (bone_index >= MOTION_BONE_N_EYELID_L_A && bone_index <= MOTION_BONE_TL_EYELID_R_B_WJ) + || (bone_index >= MOTION_BONE_N_MABU_L_D_A && bone_index <= MOTION_BONE_TL_MABU_R_U_C_WJ); +} + +static void mot_parent_get_key_set_count_by_bone_database_bones(mot_parent* a1, aft_bone_database_bone* bones) { + size_t object_bone_count; + size_t motion_bone_count; + size_t total_bone_count; + size_t ik_bone_count; + size_t chain_pos; + aft_bone_database_bones_calculate_count(bones, &object_bone_count, + &motion_bone_count, &total_bone_count, &ik_bone_count, &chain_pos); + mot_parent_get_key_set_count(a1, motion_bone_count, ik_bone_count); +} + +static void mot_parent_reserve_key_sets_by_skeleton_type(mot_parent* a1, + aft_bone_database_skeleton_type type) { + mot_parent_get_key_set_count_by_bone_database_bones(a1, aft_bone_database_get_bones_by_type(type)); + mot_parent_reserve_key_sets(a1); + a1->skeleton_type = type; +} + +static void mot_blend_reserve_key_sets(mot_blend* blend, aft_bone_database_skeleton_type type, + bool(*a3)(motion_bone_index), size_t motion_bone_count) { + mot_parent_reserve_key_sets_by_skeleton_type(&blend->field_38, type); + sub_140413350(&blend->field_0, a3, motion_bone_count); +} + +static void rob_chara_data_bone_data_init_data(rob_chara_data_bone_data* rob_bone_data, + aft_bone_database_skeleton_type base_type, + aft_bone_database_skeleton_type type) { + rob_chara_data_bone_data_init_skeleton(rob_bone_data, base_type, type); + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) + motion_blend_mot_load_bone_data(*i, rob_bone_data, motion_blend_mot_check); + size_t motion_bone_count = rob_bone_data->motion_bone_count; + mot_blend_reserve_key_sets(&rob_bone_data->face, base_type, mot_blend_face_check, motion_bone_count); + mot_blend_reserve_key_sets(&rob_bone_data->hand_l, base_type, mot_blend_hand_l_check, motion_bone_count); + mot_blend_reserve_key_sets(&rob_bone_data->hand_r, base_type, mot_blend_hand_r_check, motion_bone_count); + mot_blend_reserve_key_sets(&rob_bone_data->mouth, base_type, mot_blend_mouth_check, motion_bone_count); + mot_blend_reserve_key_sets(&rob_bone_data->eye, base_type, mot_blend_eye_check, motion_bone_count); + mot_blend_reserve_key_sets(&rob_bone_data->eyelid, base_type, mot_blend_eyelid_check, motion_bone_count); +} + +static void bone_data_parent_reset(bone_data_parent* a1) { + a1->rob_bone_data = 0; + a1->field_8 = false; + a1->field_9 = false; + a1->motion_bone_count = 0; + a1->global_trans = vec3_null; + a1->global_rotation = vec3_null; + a1->ik_bone_count = 0; + a1->chain_pos = 0; + a1->bone_key_set_count = 0; + a1->global_key_set_count = 0; + a1->field_78 = 0; + a1->rotation_y = 0; + a1->bones.end = a1->bones.begin; + a1->bone_indices.end = a1->bone_indices.begin; +} + +static void sub_140413470(struc_308* a1) { + a1->field_0 = 0; + a1->field_8 = 0; + a1->mat = mat4u_identity; + a1->field_4C = mat4u_identity; + a1->field_8C = false; + a1->eyes_adjust = 0; + a1->field_B8 = 0; + a1->field_90 = vec3_identity; + a1->field_9C = vec3_identity; + a1->field_A8 = vec3_identity; + a1->field_BC = 0; + a1->field_BD = 0; + a1->field_C0 = 1.0f; + a1->field_C4 = 1.0f; + a1->field_C8 = vec3_null; +} + +static void motion_blend_mot_reset(motion_blend_mot* a1) { + bone_data_parent_reset(&a1->bone_data); + a1->mot_data.key_sets_ready = 0; + a1->mot_data.skeleton_type = AFT_BONE_DATABASE_SKELETON_NONE; + a1->mot_data.frame = -1.0f; + a1->mot_data.key_set_count = 0; + a1->mot_data.mot_data = 0; + a1->mot_data.skeleton_select = 0; + a1->mot_data.field_68.field_0 = 0; + a1->mot_data.field_68.field_4 = 0.0f; + a1->mot_data.key_set.end = a1->mot_data.key_set.begin; + a1->mot_data.key_set_data.end = a1->mot_data.key_set_data.begin; + a1->mot_data.motion_id = -1; + a1->field_4A8.field_0.frame = 0.0f; + a1->field_4A8.field_0.field_8 = 1.0f; + a1->field_4A8.field_0.field_4 = 1.0f; + a1->field_4A8.field_0.field_C = 0.0f; + a1->field_4A8.field_0.field_10 = -1.0f; + a1->field_4A8.field_0.field_14 = -1.0f; + a1->field_4A8.field_0.field_18 = -1; + a1->field_4A8.field_0.field_1C = -1; + a1->field_4A8.field_0.field_20 = 0.0f; + a1->field_4A8.field_0.field_24 = -1.0f; + a1->field_4A8.field_0.field_28 = 0; + a1->field_4A8.field_0.field_2C = -1; + a1->field_4A8.field_30 = 0; + a1->field_4A8.field_34 = 0; + a1->field_4A8.field_38 = 0.0f; + a1->field_4A8.field_40 = 0; + a1->field_4A8.ex_data_mat = 0; + sub_140413470(&a1->field_4F8); + a1->field_0.bone_check_func = 0; + sub_1404119A0(&a1->field_0.field_8); + a1->field_0.motion_bone_count = 0; + a1->cross.base.__vftable->field_8(&a1->cross.base); + a1->freeze.base.__vftable->field_8(&a1->freeze.base); + a1->combine.base.base.__vftable->field_8(&a1->combine.base.base); + a1->field_5D0 = 0; +} + +static void mot_blend_reset(mot_blend* a1) { + a1->field_38.key_sets_ready = 0; + a1->field_38.skeleton_type = AFT_BONE_DATABASE_SKELETON_NONE; + a1->field_38.frame = -1.0f; + a1->field_38.key_set_count = 0; + a1->field_38.mot_data = 0; + a1->field_38.skeleton_select = 0; + a1->field_38.field_68.field_0 = 0; + a1->field_38.field_68.field_4 = 0.0f; + a1->field_38.key_set.end = a1->field_38.key_set.begin; + a1->field_38.key_set_data.end = a1->field_38.key_set_data.begin; + a1->field_38.motion_id = -1; + a1->field_A8.frame = 0.0f; + a1->field_A8.field_8 = 1.0f; + a1->field_A8.field_4 = 1.0f; + a1->field_A8.field_C = 0.0f; + a1->field_A8.field_10 = -1.0f; + a1->field_A8.field_14 = -1.0f; + a1->field_A8.field_18 = -1; + a1->field_A8.field_1C = -1; + a1->field_A8.field_20 = 0.0f; + a1->field_A8.field_24 = -1.0f; + a1->field_A8.field_28 = 0; + a1->field_A8.field_2C = -1; + a1->field_D8 = 0; + a1->field_DC = 0; + a1->field_E0 = 0; + a1->field_E8 = 0; + a1->field_F0 = 0; + a1->field_F8.__vftable->field_8(&a1->field_F8); + a1->field_0.bone_check_func = 0; + sub_1404119A0(&a1->field_0.field_8); + a1->field_0.motion_bone_count = 0; + a1->field_30 = 0; +} + +static void sub_1404198D0(struc_258* a1) { + a1->field_0 = 0; + a1->field_8 = mat4u_identity; + a1->ex_data_mat.field_0 = 0.0f; + a1->ex_data_mat.field_4 = 0.0f; + a1->ex_data_mat.field_8 = 0.0f; + a1->ex_data_mat.field_C = 0.0f; + a1->ex_data_mat.field_10 = 0.0f; + a1->ex_data_mat.field_14 = 0.0f; + a1->ex_data_mat.field_18 = 0.0f; + a1->ex_data_mat.field_1C = 0.0f; + a1->ex_data_mat.field_20 = 0.0f; + a1->ex_data_mat.field_24 = 0.0f; + a1->ex_data_mat.field_28 = 0.0f; + a1->ex_data_mat.field_2C = 1.0f; + a1->ex_data_mat.field_30 = 1.0f; + a1->ex_data_mat.field_34 = -3.8f; + a1->ex_data_mat.field_38 = 6.0f; + a1->ex_data_mat.field_3C = -3.8f; + a1->ex_data_mat.field_40 = 6.0f; + a1->field_8C = 0; + a1->field_8D = 0; + a1->field_8E = 0; + a1->field_8F = 0; + a1->field_90 = 0; + a1->field_91 = 0; + a1->field_94 = 0.0f; + a1->field_98 = 1.0f; + a1->field_9C = 1.0f; + a1->field_A0 = 0; + a1->field_A4 = 0; + a1->field_A8 = 0; + a1->field_AC = 0; + a1->eyes_adjust = 0; + a1->field_B8 = 0; + a1->field_B0 = 0; + a1->field_BC = 0; + a1->field_C0 = vec3_null; + a1->field_CC = mat4u_identity; + a1->field_10C = mat4u_identity; + a1->field_14C = 0; + a1->field_150 = 0; + a1->field_158 = 0.0f; + a1->field_15C.field_0 = 0; + a1->field_15C.field_4 = 0; + a1->field_15C.field_8 = 0; + a1->field_15C.field_C = 0; + a1->field_15C.field_10 = 0; + a1->field_15C.field_14 = 0; + a1->field_15C.field_18 = 0; + a1->field_15C.field_1C = 0; + a1->field_15C.field_20 = 0; + a1->field_15C.field_24 = 0; + a1->field_184 = 0; + a1->field_188 = 0; + a1->field_18C = 0; + a1->field_190 = 0; + a1->field_194 = 0; + a1->field_195 = 0; + a1->field_198 = 0; + a1->field_19C = 0; + a1->field_1A0 = 0; + a1->field_1A4 = 0; + a1->field_1A8 = 0; + a1->field_1AC = 0; + a1->field_1B0 = 0; + a1->field_1B4 = 0; + a1->field_1B8 = 0; + a1->field_1C8 = 0; + a1->field_1BC = vec2_identity; + a1->field_1C4 = 0; +} + +static void sub_1403FAEF0(struc_312* a1) { + a1->field_0.field_0 = 0; + a1->field_0.field_4 = 0; + a1->field_0.field_8 = 0; + a1->field_0.field_C = 0; + a1->field_0.field_10 = 0; + a1->field_0.field_14 = 0; + a1->field_0.field_18 = 0; + a1->field_0.field_1C = 0; + a1->field_0.field_20 = 0; + a1->field_0.field_24 = 0; + a1->field_0.field_28 = 0; + a1->field_2C.field_0 = 0; + a1->field_2C.field_4 = 0; + a1->field_2C.field_8 = 0; + a1->field_2C.field_C = 0; + a1->field_2C.field_10 = 0; + a1->field_2C.field_14 = 0; + a1->field_2C.field_18 = 0; + a1->field_2C.field_1C = 0; + a1->field_2C.field_20 = 0; + a1->field_2C.field_24 = 0; + a1->field_2C.field_28 = 0; + a1->field_58 = 0; + a1->field_8C = 1.0f; + a1->field_90 = 0; + a1->field_94 = 0; + a1->field_98 = 1.0f; + a1->field_5C = 0; + a1->field_68 = 0; + a1->field_74 = 0; + a1->field_80 = 0; + a1->field_60 = 0; + a1->field_6C = 0; + a1->field_78 = 0; + a1->field_84 = 0; + a1->field_64 = 0; + a1->field_70 = 0; + a1->field_7C = 0; + a1->field_88 = 0; +} + +static void rob_chara_data_bone_data_reset(rob_chara_data_bone_data* rob_bone_data) { + void(*rob_chara_data_bone_data_motion_blend_mot_list_free)(rob_chara_data_bone_data * rob_bone_data, + size_t a2) = (void*)0x0000000140418E80; + void(*rob_chara_data_bone_data_motion_blend_mot_list_init)(rob_chara_data_bone_data * rob_bone_data) + = (void*)0x000000014041A9E0; + void(*rob_chara_data_bone_data_motion_blend_mot_free)(rob_chara_data_bone_data * rob_bone_data) + = (void*)0x0000000140419000; + void(*rob_chara_data_bone_data_motion_blend_mot_init)(rob_chara_data_bone_data * rob_bone_data) + = (void*)0x000000014041A1A0; + + rob_bone_data->field_0 = 0; + rob_bone_data->field_1 = 0; + rob_bone_data->object_bone_count = 0; + rob_bone_data->motion_bone_count = 0; + rob_bone_data->total_bone_count = 0; + rob_bone_data->ik_bone_count = 0; + rob_bone_data->chain_pos = 0; + rob_bone_data->mats.end = rob_bone_data->mats.begin; + rob_bone_data->mats2.end = rob_bone_data->mats2.begin; + rob_bone_data->nodes.end = rob_bone_data->nodes.begin; + rob_bone_data->base_skeleton_type = AFT_BONE_DATABASE_SKELETON_NONE; + rob_bone_data->skeleton_type = AFT_BONE_DATABASE_SKELETON_NONE; + + if (rob_bone_data->motion_loaded.size + && rob_bone_data->motions.end - rob_bone_data->motions.begin == 3) { + rob_chara_data_bone_data_motion_blend_mot_list_free(rob_bone_data, 0); + for (motion_blend_mot** i = rob_bone_data->motions.begin; i != rob_bone_data->motions.end; i++) + motion_blend_mot_reset(*i); + rob_chara_data_bone_data_motion_blend_mot_list_init(rob_bone_data); + } + else { + rob_chara_data_bone_data_motion_blend_mot_free(rob_bone_data); + rob_chara_data_bone_data_motion_blend_mot_init(rob_bone_data); + } + + mot_blend_reset(&rob_bone_data->face); + mot_blend_reset(&rob_bone_data->hand_l); + mot_blend_reset(&rob_bone_data->hand_r); + mot_blend_reset(&rob_bone_data->mouth); + mot_blend_reset(&rob_bone_data->eye); + mot_blend_reset(&rob_bone_data->eyelid); + rob_bone_data->field_758 = 0; + rob_bone_data->ik_scale.ratio0 = 1.0f; + rob_bone_data->ik_scale.ratio1 = 1.0f; + rob_bone_data->ik_scale.ratio2 = 1.0f; + rob_bone_data->ik_scale.ratio3 = 1.0f; + rob_bone_data->field_76C = vec3_null; + rob_bone_data->field_778 = vec3_null; + sub_1404198D0(&rob_bone_data->field_788); + sub_1403FAEF0(&rob_bone_data->field_958); +} + +static skeleton_rotation_offset* skeleton_rotation_offset_array_get(aft_bone_database_skeleton_type type) { + skeleton_rotation_offset** skeleton_rotation_offset_array_ptr = (void*)0x0000000140A01560; + if (type >= AFT_BONE_DATABASE_SKELETON_COMMON && type <= AFT_BONE_DATABASE_SKELETON_TETO) + return skeleton_rotation_offset_array_ptr[type]; + else + return 0; +} + +static vec3* bone_data_set_key_data(bone_data* data, vec3* keyframe_data, + aft_bone_database_skeleton_type skeleton_type, bool get_data, bool reverse_x) { + aft_bone_database_bone_type type = data->type; + if (type == AFT_BONE_DATABASE_BONE_POSITION_ROTATION) { + if (get_data) { + data->trans = *keyframe_data; + if (reverse_x) + data->trans.x = -data->trans.x; + } + keyframe_data++; + } + else if (type >= AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION + && type <= AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION) { + if (get_data) { + data->ik_target = *keyframe_data; + if (reverse_x) + data->ik_target.x = -data->ik_target.x; + } + keyframe_data++; + } + + if (get_data) { + if (type == AFT_BONE_DATABASE_BONE_TYPE_1 || type == AFT_BONE_DATABASE_BONE_POSITION) { + data->trans = *keyframe_data; + if (reverse_x) + data->trans.x = -data->trans.x; + } + else if (!data->flags) { + data->rotation = *keyframe_data; + if (reverse_x) { + skeleton_rotation_offset* rot_off = skeleton_rotation_offset_array_get(skeleton_type); + size_t index = data->motion_bone_index; + if (rot_off[index].x) + data->rotation.x = rot_off[index].rotation.x - data->rotation.x; + if (rot_off[index].y) + data->rotation.y = rot_off[index].rotation.y - data->rotation.y; + if (rot_off[index].z) + data->rotation.z = rot_off[index].rotation.z - data->rotation.z; + } + } + } + keyframe_data++; + return keyframe_data; +} + +static void mot_key_frame_interpolate(mot* a1, float_t frame, float_t* value, + mot_key_set* a4, uint32_t key_set_count, struc_369* a6) { + if (a6->field_0 == 4) { + int32_t frame_int = (int32_t)frame; + if (frame != -0.0f && (float_t)frame_int != frame) + frame = (float_t)(frame < 0.0f ? frame_int - 1 : frame_int); + } + + if (!key_set_count) + return; + + for (uint32_t i = key_set_count; i; i--, a4++, value++) { + mot_key_set_type type = a4->type; + float_t* values = a4->values; + if (type == MOT_KEY_SET_STATIC) { + *value = values[0]; + continue; + } + else if (type != MOT_KEY_SET_HERMITE && type != MOT_KEY_SET_HERMITE_TANGENT) { + *value = 0.0f; + continue; + } + + int32_t current_key = a4->current_key; + int32_t keys_count = a4->keys_count; + uint16_t* frames = a4->frames; + int32_t frame_int = (int32_t)frame; + size_t key_index; + if (current_key > keys_count + || (frame_int > a4->last_key + frames[current_key]) + || current_key > 0 && frame_int < frames[current_key - 1]) { + uint16_t* key = a4->frames; + size_t length = keys_count; + size_t temp; + while (length > 0) + if (frame_int < key[temp = length / 2]) + length /= 2; + else { + key += temp + 1; + length -= temp + 1; + } + key_index = key - frames; + } + else { + uint16_t* key = &frames[current_key]; + for (uint16_t* v17 = &frames[keys_count]; key != v17; key++) + if (frame_int < *key) + break; + key_index = key - frames; + } + + bool found = false; + if (key_index < keys_count) + for (; key_index < keys_count; key_index++) + if ((float_t)frames[key_index] >= frame) { + found = true; + break; + } + + if (found) { + float_t next_frame = (float_t)frames[key_index]; + if (fabsf(next_frame - frame) > 0.000001f && key_index > 0) { + float_t curr_frame = (float_t)frames[key_index - 1]; + float_t t = (frame - curr_frame) / (next_frame - curr_frame); + if (type == MOT_KEY_SET_HERMITE) { + values += key_index - 1; + float_t p1 = values[0]; + float_t p2 = values[1]; + *value = (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; + } + else { + values += key_index * 2 - 2; + float_t p1 = values[0]; + float_t p2 = values[2]; + float_t t1 = values[1]; + float_t t2 = values[3]; + *value = ((t - 1.0f) * t1 + t * t2) * (t - 1.0f) * (frame - curr_frame) + + (t * 2.0f - 3.0f) * (t * t) * (p1 - p2) + p1; + } + a4->current_key = (int32_t)key_index; + continue; + } + } + + key_index--; + if (type == MOT_KEY_SET_HERMITE) + *value = values[key_index]; + else + *value = values[2 * key_index]; + a4->current_key = (int32_t)key_index; + } +} + +static void mot_parent_interpolate(mot_parent* a1, float_t frame, + uint32_t key_set_offset, uint32_t key_set_count) { + mot_key_frame_interpolate(&a1->mot, frame, + &a1->key_set_data.begin[key_set_offset], + &a1->key_set.begin[key_set_offset], key_set_count, &a1->field_68); +} + +static bool motion_blend_mot_interpolate_get_reverse(int32_t* a1) { + return (*a1 & 1) && (*a1 & 8) == 0 || !(*a1 & 1) && (*a1 & 8) != 0; +} + +static void sub_140415430(motion_blend_mot* a1) { + float_t rotation_y = a1->bone_data.rotation_y; + vec3 global_trans = a1->bone_data.global_trans; + vec3 global_rotation = a1->bone_data.global_rotation; + mat4 mat; + mat4_rotate_y(rotation_y, &mat); + mat4_translate_mult(&mat, global_trans.x, global_trans.y, global_trans.z, &mat); + mat4_rotate_mult(&mat, global_rotation.x, global_rotation.y, global_rotation.z, &mat); + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) + switch (i->type) { + case AFT_BONE_DATABASE_BONE_TYPE_1: + mat4_mult_vec3_trans(&mat, &i->trans, &i->trans); + break; + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: { + mat4 rot_mat; + mat4_clear_trans(&mat, &rot_mat); + mat4_to_mat4u_transpose(&rot_mat, &i->rot_mat[0]); + mat4_mult_vec3_trans(&mat, &i->trans, &i->trans); + } break; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + mat4_mult_vec3_trans(&mat, &i->ik_target, &i->ik_target); + break; + } +} + +static void motion_blend_mot_interpolate(motion_blend_mot* a1) { + vec3* keyframe_data = (vec3*)a1->mot_data.key_set_data.begin; + bool reverse = motion_blend_mot_interpolate_get_reverse(&a1->field_4F8.field_0); + float_t frame = a1->field_4A8.field_0.frame; + + aft_bone_database_skeleton_type skeleton_type = a1->bone_data.rob_bone_data->base_skeleton_type; + bone_data* bones_data = a1->bone_data.bones.begin; + for (uint16_t* i = a1->bone_data.bone_indices.begin; i != a1->bone_data.bone_indices.end; i++) { + bone_data* data = &bones_data[*i]; + bool get_data = sub_140410250(&a1->field_0.field_8, data->motion_bone_index); + if (reverse && data->mirror != 255) + data = &bones_data[data->mirror]; + + if (get_data && frame != data->frame) { + mot_parent_interpolate(&a1->mot_data, frame, data->key_set_offset, data->key_set_count); + data->frame = frame; + } + + keyframe_data = bone_data_set_key_data(data, keyframe_data, skeleton_type, get_data, reverse); + } + + uint32_t v15 = a1->bone_data.bone_key_set_count; + if (frame != a1->mot_data.frame) { + mot_parent_interpolate(&a1->mot_data, frame, v15, a1->bone_data.global_key_set_count); + a1->mot_data.frame = frame; + } + + keyframe_data = (vec3*)&a1->mot_data.key_set_data.begin[v15]; + vec3 global_trans = keyframe_data[0]; + vec3 global_rotation = keyframe_data[1]; + if (reverse) + vec3_negate(global_trans, global_trans); + a1->bone_data.global_trans = global_trans; + a1->bone_data.global_rotation = global_rotation; + + sub_140415430(a1); +} + +static void mot_blend_interpolate(mot_blend* a1, vector_bone_data* bones, + vector_uint16_t* bone_indices, aft_bone_database_skeleton_type skeleton_type) { + if (!a1->field_38.key_sets_ready || !a1->field_38.mot_data || a1->field_30) + return; + + float_t frame = a1->field_A8.frame; + vec3* keyframe_data = (vec3*)a1->field_38.key_set_data.begin; + bone_data* bones_data = bones->begin; + for (uint16_t* i = bone_indices->begin; i != bone_indices->end; i++) { + bone_data* data = &bones_data[*i]; + bool get_data = sub_140410250(&a1->field_0.field_8, data->motion_bone_index); + if (get_data) { + mot_parent_interpolate(&a1->field_38, frame, data->key_set_offset, data->key_set_count); + data->frame = frame; + } + keyframe_data = bone_data_set_key_data(data, keyframe_data, skeleton_type, get_data, 0); + } +} + +static void sub_1401EB1D0(bone_data* a1, int32_t a2) { + if (!a1->flags) + return; + + if (a1->type >= AFT_BONE_DATABASE_BONE_TYPE_1 && a1->type <= AFT_BONE_DATABASE_BONE_POSITION_ROTATION) + a1->trans_dup[a2] = a1->trans; + + switch (a1->type) { + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + a1->rot_mat_dup[a2 + 4] = a1->rot_mat[2]; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + a1->rot_mat_dup[a2 + 2] = a1->rot_mat[1]; + case AFT_BONE_DATABASE_BONE_ROTATION: + case AFT_BONE_DATABASE_BONE_TYPE_1: + case AFT_BONE_DATABASE_BONE_POSITION: + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: + default: + a1->rot_mat_dup[a2] = a1->rot_mat[0]; + break; + } +} + +static void sub_14041B4E0(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_FACE_ROOT; + i <= MOTION_BONE_TL_TOOTH_UPPER_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B580(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_FACE_ROOT; + i <= MOTION_BONE_TL_TOOTH_UPPER_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); + + for (motion_bone_index i = MOTION_BONE_N_EYE_L; + i <= MOTION_BONE_KL_HIGHLIGHT_R_WJ; i++) + bitfield[i >> 5] |= 1 << (i & 0x1F); +} + +static void sub_14041B800(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_KUTI_D; + i <= MOTION_BONE_TL_KUTI_U_R_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); + + for (motion_bone_index i = MOTION_BONE_N_AGO; + i <= MOTION_BONE_TL_TOOTH_UNDER_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); + + for (motion_bone_index i = MOTION_BONE_N_TOOTH_UPPER; + i <= MOTION_BONE_TL_TOOTH_UPPER_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B440(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_EYE_L; + i <= MOTION_BONE_KL_HIGHLIGHT_R_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B1C0(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_MABU_L_D_A; + i <= MOTION_BONE_TL_MABU_R_U_C_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); + + for (motion_bone_index i = MOTION_BONE_N_EYELID_L_A; + i <= MOTION_BONE_TL_EYELID_R_B_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B6B0(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_HITO_L_EX; + i <= MOTION_BONE_NL_OYA_C_L_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B750(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_HITO_R_EX; + i <= MOTION_BONE_NL_OYA_C_R_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_14041B300(struc_313* a1) { + uint32_t* bitfield = a1->bitfield.begin; + for (motion_bone_index i = MOTION_BONE_N_MABU_L_D_A; + i <= MOTION_BONE_TL_MABU_R_U_C_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); + + for (motion_bone_index i = MOTION_BONE_N_EYELID_L_A; + i <= MOTION_BONE_TL_EYELID_R_B_WJ; i++) + bitfield[i >> 5] &= ~(1 << (i & 0x1F)); +} + +static void sub_140413EA0(struc_240* a1, void(*a2)(struc_313*)) { + a2(&a1->field_8); +} + +static void sub_14041AD90(rob_chara_data_bone_data* a1) { + if (a1->mouth.field_38.key_sets_ready && a1->mouth.field_38.mot_data && !a1->mouth.field_30) + sub_140413EA0(&a1->face.field_0, sub_14041B800); + if (a1->eyelid.field_38.key_sets_ready && a1->eyelid.field_38.mot_data && !a1->eyelid.field_30) + sub_140413EA0(&a1->face.field_0, sub_14041B1C0); + else if (a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30 || a1->field_758) + sub_140413EA0(&a1->face.field_0, sub_14041B440); +} + +static void sub_14041AD50(rob_chara_data_bone_data* a1) { + if (a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30 || a1->field_758) + sub_140413EA0(&a1->eyelid.field_0, sub_14041B440); +} + +static void sub_140412F20(mot_blend* a1, vector_bone_data* a2) { + uint32_t* bitfield = a1->field_0.field_8.bitfield.begin; + for (bone_data* i = a2->begin; i != a2->end; ++i) { + motion_bone_index v5 = i->motion_bone_index; + if (bitfield[v5 >> 5] & (1 << (v5 & 0x1F))) + sub_1401EB1D0(i, 0); + } +} + +static mot_data* mot_parent_load_file(mot_parent* a1, int32_t motion_id) { + mot_data* (*sub_140403C90)(int32_t a1) = (void*)0x0000000140403C90; + bool(*mot_load_file)(mot * a1, mot_key_set_file * a2) = (void*)0x000000014036F7B0; + + mot_data* v4; + if (a1->motion_id == motion_id) + v4 = a1->mot_data; + else { + v4 = sub_140403C90(motion_id); + a1->mot_data = v4; + if (v4) { + a1->motion_id = motion_id; + a1->skeleton_select = mot_load_file(&a1->mot, v4->data_file); + } + else { + a1->skeleton_select = 0; + a1->motion_id = -1; + } + } + a1->frame = -1.0f; + a1->field_68.field_0 = 0; + a1->field_68.field_4 = 0.0f; + return v4; +} + +static void sub_140414ED0(mot_blend* a1, int32_t motion_id) { + mot_parent_load_file(&a1->field_38, motion_id); + a1->field_F8.__vftable->field_8(&a1->field_F8); +} + +static void sub_14041BE50(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_14041AD90(rob_bone_data); + mot_blend* v3 = &rob_bone_data->face; + sub_140412F20(v3, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_1404146F0(&v3->field_0); + sub_140414ED0(v3, motion_id); +} + +static void sub_14041ABA0(rob_chara_data_bone_data* a1) { + list_ptr_motion_blend_mot_node* v1 = a1->motion_loaded.head; + list_ptr_motion_blend_mot_node* v3 = v1->next; + while (v3 != v1) { + if (a1->face.field_38.key_sets_ready && a1->face.field_38.mot_data && !a1->face.field_30) { + if (!a1->field_758 || a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B4E0); + else + sub_140413EA0(&v3->value->field_0, sub_14041B580); + } + else { + if (a1->mouth.field_38.key_sets_ready && a1->mouth.field_38.mot_data && !a1->mouth.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B800); + if (a1->eyelid.field_38.key_sets_ready && a1->eyelid.field_38.mot_data && !a1->eyelid.field_30) { + if (!a1->field_758 + || a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B1C0); + else + sub_140413EA0(&v3->value->field_0, sub_14041B300); + } + else if (a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B440); + } + + if (a1->hand_l.field_38.key_sets_ready && a1->hand_l.field_38.mot_data && !a1->hand_l.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B6B0); + if (a1->hand_r.field_38.key_sets_ready && a1->hand_r.field_38.mot_data && !a1->hand_r.field_30) + sub_140413EA0(&v3->value->field_0, sub_14041B750); + v3 = v3->next; + } + sub_14041AD90(a1); + sub_14041AD50(a1); +} + +static bool sub_140413630(struc_308* a1) { + return (a1->field_4 & 2) != 0; +} + +static bool sub_140413790(struc_308* a1) { + return (a1->field_0 & 2) != 0; +} + +static bool sub_1404137A0(struc_308* a1) { + return (a1->field_0 & 0x10) != 0; +} + +static void sub_140415A10(motion_blend_mot* a1) { + motion_blend* v1 = a1->field_5D0; + if (!v1) + return; + + struc_400 v7; + v7.field_0 = 0; + v7.field_2 = 0; + v7.field_3 = 0; + v7.field_4 = 0; + if (!a1->field_4F8.field_BD) + v7.field_0 = !sub_140413630(&a1->field_4F8); + if (!a1->field_4F8.field_BC) + v7.field_2 = !sub_140413790(&a1->field_4F8); + + v7.field_1 = sub_1404137A0(&a1->field_4F8) ? 1 : 0; + v7.field_8 = a1->mot_data.frame; + v7.field_C = a1->field_4F8.eyes_adjust; + v7.field_10 = a1->field_4F8.field_B8; + v1->__vftable->field_18(v1, &v7.field_0); +} + +static bool sub_140410A20(motion_blend_mot* a1) { + motion_blend* v1 = a1->field_5D0; + return !v1 || !v1->field_9; +} + +static void sub_140415B30(mot_blend* a1) { + struc_400 v3; // [rsp+20h] [rbp-28h] BYREF + + motion_blend* v1 = &a1->field_F8; + v3.field_0 = 0; + v3.field_1; + v3.field_2; + v3.field_3; + v3.field_4 = 0; + v3.field_8 = 0.0f; + v3.field_C = 0.0f; + v3.field_10 = 0.0f; + a1->field_F8.__vftable->field_18(&a1->field_F8, &v3.field_0); +} + +static void sub_14041DAC0(rob_chara_data_bone_data* a1) { + void(*rob_bone_data_motion_blend_mot_list_free)(rob_chara_data_bone_data * rob_bone_data, + size_t a2) = (void*)0x0000000140418E80; + + size_t v2 = 0; + bool v3 = 0; + list_ptr_motion_blend_mot_node* v1 = a1->motion_loaded.head; + list_ptr_motion_blend_mot_node* v4 = v1->next; + while (v4 != v1) { + if (sub_1404136B0(v4->value)) + sub_140415A10(v4->value); + else { + if (v3) { + rob_bone_data_motion_blend_mot_list_free(a1, v2); + break; + } + sub_140415A10(v4->value); + v3 = sub_140410A20(v4->value); + } + v4 = v4->next; + v2++; + } + + sub_140415B30(&a1->face); + sub_140415B30(&a1->hand_l); + sub_140415B30(&a1->hand_r); + sub_140415B30(&a1->mouth); + sub_140415B30(&a1->eye); + sub_140415B30(&a1->eyelid); +} + +void rob_chara_data_bone_data_interpolate(rob_chara_data_bone_data* rob_bone_data) { + if (!rob_bone_data->motion_loaded.size) + return; + + sub_14041ABA0(rob_bone_data); + sub_14041DAC0(rob_bone_data); + + list_ptr_motion_blend_mot_node* v2 = rob_bone_data->motion_loaded.head; + list_ptr_motion_blend_mot_node* v3 = v2->next; + while (v3 != v2) { + motion_blend_mot_interpolate(v3->value); + v3 = v3->next; + } + + aft_bone_database_skeleton_type skeleton_type = rob_bone_data->base_skeleton_type; + motion_blend_mot* v5 = rob_bone_data->motion_loaded.head->next->value; + vector_bone_data* bones = &v5->bone_data.bones; + vector_uint16_t* bone_indices = &v5->bone_data.bone_indices; + mot_blend_interpolate(&rob_bone_data->face, bones, bone_indices, skeleton_type); + mot_blend_interpolate(&rob_bone_data->hand_l, bones, bone_indices, skeleton_type); + mot_blend_interpolate(&rob_bone_data->hand_r, bones, bone_indices, skeleton_type); + mot_blend_interpolate(&rob_bone_data->mouth, bones, bone_indices, skeleton_type); + mot_blend_interpolate(&rob_bone_data->eye, bones, bone_indices, skeleton_type); + mot_blend_interpolate(&rob_bone_data->eyelid, bones, bone_indices, skeleton_type); +} + +static void sub_140412E10(motion_blend_mot* a1, int32_t a2) { + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) { + motion_bone_index v5 = i->motion_bone_index; + if (!(a1->field_0.field_8.bitfield.begin[v5 >> 5] & (1 << (v5 & 0x1F)))) + continue; + + sub_1401EB1D0(i, a2); + if (i->type == AFT_BONE_DATABASE_BONE_POSITION_ROTATION && a1->field_4F8.field_0 & 2) + vec3_add(i->trans_dup[a2], a1->field_4F8.field_90, i->trans_dup[a2]); + } +} + +static void sub_1401EAD00(bone_data* a1, bone_data* a2) { + if (!a1->flags) + return; + + if (a1->type >= AFT_BONE_DATABASE_BONE_TYPE_1 && a1->type <= AFT_BONE_DATABASE_BONE_POSITION_ROTATION) { + a1->trans = a2->trans; + a1->trans_dup[0] = a2->trans_dup[0]; + } + + switch (a1->type) { + case AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION: + case AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION: + a1->rot_mat[2] = a1->rot_mat[2]; + a1->rot_mat_dup[4] = a1->rot_mat_dup[4]; + case AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION: + a1->rot_mat[1] = a1->rot_mat[1]; + a1->rot_mat_dup[2] = a1->rot_mat_dup[2]; + case AFT_BONE_DATABASE_BONE_ROTATION: + case AFT_BONE_DATABASE_BONE_TYPE_1: + case AFT_BONE_DATABASE_BONE_POSITION: + case AFT_BONE_DATABASE_BONE_POSITION_ROTATION: + default: + a1->rot_mat[0] = a1->rot_mat[0]; + a1->rot_mat_dup[0] = a1->rot_mat_dup[0]; + break; + } +} + +static void sub_140412BB0(motion_blend_mot* a1, vector_bone_data* a2) { + for (bone_data* i = a1->bone_data.bones.begin; i != a1->bone_data.bones.end; i++) + sub_1401EAD00(i, &a2->begin[i->motion_bone_index]); +} + +static void sub_1403FBF10(motion_blend* a1, float_t a2) { + a1->blend = clamp(a2, 0.0f, 1.0f); + a1->field_8 = 1; + a1->field_9 = 1; +} + +static void sub_1404148C0(motion_blend_mot* a1, float_t a2) { + motion_blend* v2 = a1->field_5D0; + if (v2) + sub_1403FBF10(v2, a2); +} + +static void sub_1404147F0(motion_blend_mot* a1, motion_blend_type type, float_t blend) { + if (type == MOTION_BLEND_FREEZE) { + a1->freeze.base.__vftable->field_8(&a1->freeze.base); + a1->field_5D0 = &a1->freeze.base; + sub_140412E10(a1, 0); + } + else if (type == MOTION_BLEND_CROSS) { + a1->cross.base.__vftable->field_8(&a1->cross.base); + a1->field_5D0 = &a1->cross.base; + } + else if (type == MOTION_BLEND_COMBINE) { + a1->combine.base.base.__vftable->field_8(&a1->combine.base.base); + a1->field_5D0 = &a1->combine.base.base; + sub_1404148C0(a1, blend); + } + else + a1->field_5D0 = 0; +} + +static int32_t sub_1401F0E70(aft_bone_database_skeleton_type type, char* name) { + aft_bone_database_struct* bone_database = *(void**)0x0000000140FBC1C0; + int32_t(*sub_1401F0EA0)(char* a1, char* a2) = (void*)0x00000001401F0EA0; + + if (!bone_database || type == AFT_BONE_DATABASE_SKELETON_NONE) + return -1; + else + return sub_1401F0EA0(bone_database->skeleton_names[type], name); +} + +static void bone_data_parent_load_bone_indices_from_mot(bone_data_parent* a1, mot_data* a2) { + if (!a2) + return; + + char** (*sub_140403B00)() = (void*)0x0000000140403B00; + void (*sub_14040F210)(vector_uint16_t * a1, size_t a2) = (void*)0x000000014040F210; + + char** v4 = sub_140403B00(); + vector_uint16_t* v5 = &a1->bone_indices; + uint16_t v6 = a2->data_file->info; + a1->bone_indices.end = a1->bone_indices.begin; + aft_bone_database_skeleton_type v8 = a1->rob_bone_data->base_skeleton_type; + uint16_t v9 = (v6 & 0x3FFF) - 1; + if (!v9) + return; + + for (size_t v10 = 0, v11 = 0; v10 < v9; v11++) { + int32_t v12 = sub_1401F0E70(v8, v4[a2->bone_info[v11]]); + if (v12 == -1) { + v12 = sub_1401F0E70(v8, v4[a2->bone_info[++v11]]); + if (v12 == -1) + break; + } + + uint16_t* v14 = v5->end; + bone_data* v15 = &a1->bones.begin[v12]; + uint16_t v21 = (uint16_t)v12; + if (&v21 >= v14 || v5->begin > &v21) { + if (v14 == v5->capacity_end) + sub_14040F210(v5, 1); + + uint16_t* v18 = v5->end; + if (v18) + *v18 = v21; + } + else { + size_t v16 = &v21 - v5->begin; + if (v14 == v5->capacity_end) + sub_14040F210(v5, 1); + + uint16_t* v17 = v5->end; + if (v17) + *v17 = v5->begin[v16]; + } + v5->end++; + + v15->key_set_offset = (int32_t)v10; + v15->frame = -1.0f; + if (v15->type >= AFT_BONE_DATABASE_BONE_POSITION_ROTATION) + v10 += 6; + else + v10 += 3; + } +} + +static void sub_140413C30(struc_308* a1) { + a1->field_8C = false; + a1->field_4C = a1->mat; + a1->mat = mat4u_identity; +} + +static void motion_blend_mot_load_file(motion_blend_mot* a1, int32_t motion_id, int32_t a3, float_t blend) { + sub_1404147F0(a1, a3, blend); + mot_data* v5 = mot_parent_load_file(&a1->mot_data, motion_id); + bone_data_parent* v6 = &a1->bone_data; + if (v5) { + bone_data_parent_load_bone_indices_from_mot(v6, v5); + uint16_t* v7 = a1->bone_data.bone_indices.begin; + uint16_t* v8 = a1->bone_data.bone_indices.end; + bone_data* v9 = a1->bone_data.bones.begin; + for (; v7 != v8; v7++) + v9[*v7].frame = -1.0f; + } + else { + rob_chara_data_bone_data* rob_bone_data = v6->rob_bone_data; + for (mat4* i = rob_bone_data->mats.begin; i != rob_bone_data->mats.end; i++) + *i = mat4_identity; + + for (mat4* i = rob_bone_data->mats2.begin; i != rob_bone_data->mats2.end; i++) + *i = mat4_identity; + + a1->bone_data.bone_indices.end = a1->bone_data.bone_indices.begin; + } + sub_140413C30(&a1->field_4F8); +} + +static void sub_14041BA60(rob_chara_data_bone_data* rob_bone_data) { + motion_blend_mot* v1 = rob_bone_data->motion_loaded.head->next->value; + if (v1) + sub_1404146F0(&v1->field_0); +} + +static void sub_14041AE40(rob_chara_data_bone_data* a1) { + list_ptr_motion_blend_mot_node* v1 = a1->motion_loaded.head; + struc_240* v3 = &v1->next->value->field_0; + if (!v3) + return; + + if (a1->face.field_38.key_sets_ready && a1->face.field_38.mot_data && !a1->face.field_30) { + if (!a1->field_758 || a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(v3, sub_14041B4E0); + else + sub_140413EA0(v3, sub_14041B580); + } + else { + if (a1->mouth.field_38.key_sets_ready && a1->mouth.field_38.mot_data && !a1->mouth.field_30) + sub_140413EA0(&v1->next->value->field_0, sub_14041B800); + else if (a1->eyelid.field_38.key_sets_ready && a1->eyelid.field_38.mot_data && !a1->eyelid.field_30) { + if (!a1->field_758 || a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(v3, sub_14041B1C0); + else + sub_140413EA0(v3, sub_14041B300); + } + else if (a1->eye.field_38.key_sets_ready && a1->eye.field_38.mot_data && !a1->eye.field_30) + sub_140413EA0(v3, sub_14041B440); + } + + if (a1->hand_l.field_38.key_sets_ready && a1->hand_l.field_38.mot_data && !a1->hand_l.field_30) + sub_140413EA0(v3, sub_14041B6B0); + if (a1->hand_r.field_38.key_sets_ready && a1->hand_r.field_38.mot_data && !a1->hand_r.field_30) + sub_140413EA0(v3, sub_14041B750); +} + +void rob_chara_data_bone_data_motion_load(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id, int32_t index) { + void(*rob_bone_data_motion_blend_mot_list_init)(rob_chara_data_bone_data * rob_bone_data) + = (void*)0x000000014041A9E0; + void(*rob_bone_data_motion_blend_mot_list_free)(rob_chara_data_bone_data * rob_bone_data, + size_t a2) = (void*)0x0000000140418E80; + list_ptr_motion_blend_mot_node* (*sub_140415D30)(list_ptr_motion_blend_mot * a1, + list_ptr_motion_blend_mot_node * a2, list_ptr_motion_blend_mot_node * a3, + motion_blend_mot * *a4) = (void*)0x0000000140415D30; + list_size_t_node* (*sub_140415DB0)(list_size_t_node * *a1, list_size_t_node * a2, + list_size_t_node * a3, size_t * a4) = (void*)0x0000000140415DB0; + motion_blend_mot* (*sub_140411A70)(motion_blend_mot * a1, + rob_chara_data_bone_data * rob_bone_data) = (void*)0x0000000140411A70; + + if (!rob_bone_data->motion_loaded.size) + return; + if (index == 1) { + rob_bone_data_motion_blend_mot_list_free(rob_bone_data, 1); + sub_14041AE40(rob_bone_data); + list_ptr_motion_blend_mot_node*v15 = rob_bone_data->motion_loaded.head; + motion_blend_mot_load_file(v15->next->value, motion_id, 1, 1.0f); + sub_14041BA60(rob_bone_data); + return; + } + + if (index != 2) { + if (index == 3) + index = 0; + rob_bone_data_motion_blend_mot_list_free(rob_bone_data, 1); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.head->next->value, motion_id, index, 1.0f); + return; + } + + rob_bone_data_motion_blend_mot_list_free(rob_bone_data, 2); + if (rob_bone_data->motion_indices.size) { + motion_blend_mot* v6 = rob_bone_data->motion_loaded.head->next->value; + rob_bone_data_motion_blend_mot_list_init(rob_bone_data); + sub_140412BB0(rob_bone_data->motion_loaded.head->next->value, &v6->bone_data.bones); + motion_blend_mot_load_file(rob_bone_data->motion_loaded.head->next->value, motion_id, 2, 1.0f); + return; + } + + list_ptr_motion_blend_mot* v7 = &rob_bone_data->motion_loaded; + motion_blend_mot* v16 = sub_140411A70(rob_bone_data->motion_loaded.head->next->value, rob_bone_data); + if (!v16) { + rob_bone_data_motion_blend_mot_list_free(rob_bone_data, 1); + sub_14041AE40(rob_bone_data); + list_ptr_motion_blend_mot_node* v15 = v7->head; + motion_blend_mot_load_file(v15->next->value, motion_id, 1, 1.0f); + sub_14041BA60(rob_bone_data); + return; + } + + list_ptr_motion_blend_mot_node* v8 = v7->head->next; + motion_blend_mot* v9 = v8->value; + list_ptr_motion_blend_mot_node* v10 = sub_140415D30(&rob_bone_data->motion_loaded, v8, v8->prev, &v16); + rob_bone_data->motion_loaded.size++; + v8->prev = v10; + v10->prev->next = v10; + size_t v17 = rob_bone_data->motions.end - rob_bone_data->motions.begin; + list_size_t_node* v12 = rob_bone_data->motion_loaded_indices.head->next; + list_size_t_node* v13 = sub_140415DB0(&rob_bone_data->motion_loaded_indices.head, v12, v12->prev, &v17); + rob_bone_data->motion_loaded_indices.size++; + v12->prev = v13; + v13->prev->next = v13; + sub_140412BB0(v7->head->next->value, &v9->bone_data.bones); + motion_blend_mot_load_file(v7->head->next->value, motion_id, 2, 1.0f); +} + +static void sub_14041BFC0(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_140412F20(&rob_bone_data->hand_l, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_140414ED0(&rob_bone_data->hand_l, motion_id); +} + +static void sub_14041C260(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_140412F20(&rob_bone_data->hand_r, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_140414ED0(&rob_bone_data->hand_r, motion_id); +} + +static void sub_14041D200(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_140412F20(&rob_bone_data->mouth, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_140414ED0(&rob_bone_data->mouth, motion_id); +} + +static void sub_14041BDB0(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_140412F20(&rob_bone_data->eye, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_140414ED0(&rob_bone_data->eye, motion_id); +} + +static void sub_14041BD20(rob_chara_data_bone_data* rob_bone_data, int32_t motion_id) { + sub_14041AD50(rob_bone_data); + mot_blend* v3 = &rob_bone_data->eyelid; + sub_140412F20(v3, &rob_bone_data->motion_loaded.head->next->value->bone_data.bones); + sub_1404146F0(&v3->field_0); + sub_140414ED0(v3, motion_id); +} + +static void sub_140414BC0(struc_346* a1, float_t frame) { + float_t v2 = a1->field_14; + a1->frame = frame; + a1->field_28 = 0; + if (v2 >= 0.0f && (a1->field_18 == 2 && frame <= v2) || frame >= v2) + a1->field_14 = -1.0; +} + +static void rob_chara_data_bone_data_set_frame(rob_chara_data_bone_data* a1, float_t frame) { + sub_140414BC0(&a1->motion_loaded.head->next->value->field_4A8.field_0, frame); +} + +static void sub_14041C680(rob_chara_data_bone_data* a1, char a2) { + struc_308* v2 = &a1->motion_loaded.head->next->value->field_4F8; + if (a2) + v2->field_0 |= 2; + else + v2->field_0 &= ~2; +} + +static void sub_14041C9D0(rob_chara_data_bone_data* a1, char a2) { + struc_308* v2 = &a1->motion_loaded.head->next->value->field_4F8; + v2->field_8 = (uint8_t)(v2->field_0 & 1); + if (a2) + v2->field_0 |= 1; + else + v2->field_0 &= ~1; +} + +static void sub_14041D2D0(rob_chara_data_bone_data* a1, char a2) { + struc_308* v2 = &a1->motion_loaded.head->next->value->field_4F8; + if (a2) + v2->field_0 |= 4; + else + v2->field_0 &= ~4; +} + +static void sub_14041BC40(rob_chara_data_bone_data* a1, char a2) { + struc_308* v2 = &a1->motion_loaded.head->next->value->field_4F8; + if (a2) + v2->field_0 |= 8; + else + v2->field_0 &= ~8; +} + +static void sub_140414F00(struc_308* a1, float_t a2) { + a1->field_B8 = a1->eyes_adjust; + a1->eyes_adjust = a2; +} + +static void sub_14041D270(rob_chara_data_bone_data* a1, float_t a2) { + sub_140414F00(&a1->motion_loaded.head->next->value->field_4F8, a2); +} + +static void sub_14041D2A0(rob_chara_data_bone_data* a1, float_t a2) { + a1->motion_loaded.head->next->value->field_4F8.field_B8 = a2; +} + +static void rob_chara_data_bone_data_set_rotation_y(rob_chara_data_bone_data* rob_bone_data, float_t rotation_y) { + rob_bone_data->motion_loaded.head->next->value->bone_data.rotation_y = rotation_y; +} + +static void sub_1403FBED0(motion_blend* a1, float_t a2, float_t a3, float_t a4) { + if (a2 < 0.0f) { + a1->field_8 = false; + a1->field_C = 0.0f; + a1->field_10 = 0.0f; + a1->field_14 = a3; + a1->field_18 = a4; + } + else { + a1->field_8 = true; + a1->field_C = a2; + a1->field_10 = 0.0f; + a1->field_14 = a3; + a1->field_18 = a4; + } +} + +static void sub_140414C60(motion_blend_mot* a1, float_t a2, float_t a3, float_t a4) { + motion_blend* v4 = a1->field_5D0; + if (v4) + sub_1403FBED0(v4, a2, a3, a4); +} + +static void sub_14041BF80(rob_chara_data_bone_data* a1, float_t a2, float_t a3, float_t a4) { + sub_140414C60(a1->motion_loaded.head->next->value, a2, a3, a4); +} + +static void sub_14041D310(rob_chara_data_bone_data* a1) { + motion_blend* v1 = a1->motion_loaded.head->next->value->field_5D0; + if (v1) + v1->__vftable->field_10(v1); +} + +static void rob_chara_data_load_default_motion_sub(rob_chara_data* a1, int32_t a2, int32_t motion_id) { + sub_14041BE50(a1->bone_data, -1); + sub_14041BFC0(a1->bone_data, -1); + sub_14041C260(a1->bone_data, -1); + sub_14041D200(a1->bone_data, -1); + sub_14041BDB0(a1->bone_data, -1); + sub_14041BD20(a1->bone_data, -1); + rob_chara_data_bone_data_motion_load(a1->bone_data, motion_id, 1); + rob_chara_data_bone_data_set_frame(a1->bone_data, 0.0f); + sub_14041C680(a1->bone_data, 0); + sub_14041C9D0(a1->bone_data, 0); + sub_14041D2D0(a1->bone_data, 0); + sub_14041BC40(a1->bone_data, 0); + sub_14041D270(a1->bone_data, 0.0f); + sub_14041D2A0(a1->bone_data, 0.0f); + rob_chara_data_bone_data_set_rotation_y(a1->bone_data, 0.0f); + sub_14041BF80(a1->bone_data, 0.0f, 1.0f, 1.0f); + sub_14041D310(a1->bone_data); + rob_chara_data_bone_data_interpolate(a1->bone_data); + rob_chara_data_bone_data_update(a1->bone_data, 0); + sub_140412E10(a1->bone_data->motion_loaded.head->next->value, a2); +} + +int32_t rob_cmn_mottbl_get_motion_index(rob_chara_data* a1, int32_t a2) { + struc_403* rob_cmn_mottbl_data = *rob_cmn_mottbl_data_ptr; + + if (a2 == 224) + return a1->field_440.field_290.field_0; + if (a2 >= 214 && a2 <= 223) + return ((uint32_t*)&a1->field_4228.field_1E68.field_1C88)[a2]; + if (a2 >= 226 && a2 <= 235) + return ((uint32_t*)&a1->field_4228.field_1E68.field_1C78)[a2 + 1]; + + size_t v7 = a1->field_440.field_8.field_1A4; + size_t v8 = a1->chara_index; + if (!rob_cmn_mottbl_data + || v8 < 0 || v8 >= rob_cmn_mottbl_data->field_0 + || a2 < 0 || a2 >= rob_cmn_mottbl_data->field_4) + return -1; + + struc_404* v4 = (struc_404*)((size_t)rob_cmn_mottbl_data + rob_cmn_mottbl_data->field_8); + if (v7 < v4[v8].field_4) + return ((int32_t*)((size_t)rob_cmn_mottbl_data + + ((uint32_t*)((size_t)rob_cmn_mottbl_data + v4[v8].field_0))[v7]))[a2]; + return -1; +} + +static void rob_chara_data_load_default_motion(rob_chara_data* a1) { + rob_chara_data_load_default_motion_sub(a1, 1, rob_cmn_mottbl_get_motion_index(a1, 0)); +} + +static bone_node* rob_chara_data_bone_data_get_node(rob_chara_data_bone_data* rob_bone_data, size_t index) { + if ((ssize_t)index < rob_bone_data->nodes.end - rob_bone_data->nodes.begin) + return &rob_bone_data->nodes.begin[index]; + return 0; +} + +static char* ex_node_block_get_parent_name(ex_node_block* a1) { + return string_data(&a1->parent_name); +} + +static bone_node* rob_chara_data_item_equip_object_get_bone_node( + rob_chara_data_item_equip_object* a1, int32_t a2) { + bool ex_data = a2 & 0x8000 ? true : false; + a2 &= 0x7FFF; + if (!ex_data) + return &a1->bone_nodes[a2]; + else if (a2 < a1->ex_data_bone_nodes.end - a1->ex_data_bone_nodes.begin) + return &a1->ex_data_bone_nodes.begin[a2]; + return 0; +} + +static bone_node* rob_chara_data_item_equip_object_get_bone_node_by_name( + rob_chara_data_item_equip_object* a1, char* a2) { + int32_t(*rob_chara_data_item_equip_object_get_bone_index)( + rob_chara_data_item_equip_object * a1, char* a2) = (void*)0x00000001405F3400; + return rob_chara_data_item_equip_object_get_bone_node(a1, + rob_chara_data_item_equip_object_get_bone_index(a1, a2)); +} + +static void rob_chara_data_item_equip_object_get_parent_bone_nodes( + rob_chara_data_item_equip_object* a1, bone_node* a2) { + a1->bone_nodes = a2; + a1->mat = a2->mat; + for (ex_node_block** i = a1->node_blocks.begin; i != a1->node_blocks.end; i++) + (*i)->parent_bone_node = rob_chara_data_item_equip_object_get_bone_node_by_name( + a1, ex_node_block_get_parent_name(*i)); +} + +static void rob_chara_data_item_equip_get_parent_bone_nodes(rob_chara_data_item_equip* a1, bone_node* a2) { + a1->bone_nodes = a2; + a1->matrices = a2->mat; + for (int32_t v2 = a1->first_item_equip_object; v2 < a1->max_item_equip_object; v2++) + rob_chara_data_item_equip_object_get_parent_bone_nodes(&a1->item_equip_object[v2], a1->bone_nodes); +} + +static bool rob_chara_data_check_for_ageageagain_module(chara_index chara_index, int32_t module_index) { + return chara_index == CHARA_MIKU && module_index == 148; +} + +static void sub_140517060(rob_chara_data* a1, bool a2) { + void(*sub_140543780)(int32_t a1, int32_t a2, char a3) = (void*)0x0000000140543780; + + a1->field_440.field_0 &= ~1; + a1->field_440.field_3 &= ~1; + a1->field_440.field_0 |= a2 & 1; + a1->field_440.field_3 |= a2 & 1; + if (rob_chara_data_check_for_ageageagain_module(a1->chara_index, a1->module_index)) { + sub_140543780(a1->chara_id, 1, a2); + sub_140543780(a1->chara_id, 2, a2); + } +} + +static float_t chara_size_table_get_value(uint32_t a1) { + static const float_t chara_size_table[] = { + 1.07f, 1.0f, 0.96f, 0.987f, 1.025f + }; + + if (a1 > 4) + return 1.0f; + else + return chara_size_table[a1]; +} + +static float_t sub_140510320(uint32_t a1) { + static const float_t flt_1411ADAD0[] = { + 0.071732f, 0.0f, -0.03859f, 0.0f, 0.0f + }; + + if (a1 > 4) + return 0.0f; + else + return flt_1411ADAD0[a1]; +} + +static void sub_14041C5C0(rob_chara_data_bone_data* a1, struc_243* a2) { + a1->field_788.field_15C = *a2; +} + +static void sub_14041D4E0(rob_chara_data_bone_data* a1, struc_242* a2) { + a1->field_958.field_0 = *a2; +} + +static void sub_14041D5C0(rob_chara_data_bone_data* a1, struc_242* a2) { + a1->field_958.field_2C = *a2; +} + +static void sub_14041D560(rob_chara_data_bone_data* a1, char a2, char a3) { + a1->field_958.field_58 = a2; + a1->field_958.field_59 = a3; +} + +static void rob_chara_data_bone_data_ik_scale_calculate( + rob_chara_data_bone_data_ik_scale* a1, vector_bone_data* a2, + aft_bone_database_skeleton_type base_skeleton_type, + aft_bone_database_skeleton_type skeleton_type) { + bone_data* b_cl_mune = &a2->begin[MOTION_BONE_CL_MUNE]; + bone_data* b_kl_kubi = &a2->begin[MOTION_BONE_KL_KUBI]; + bone_data* b_c_kata_l = &a2->begin[MOTION_BONE_C_KATA_L]; + bone_data* b_cl_momo_l = &a2->begin[MOTION_BONE_CL_MOMO_L]; + + float_t base_height = fabsf(b_cl_momo_l->base_translation[0].y) + b_cl_momo_l->ik_segment_length[0] + + b_cl_momo_l->ik_2nd_segment_length[0] + aft_bone_database_get_skeleton_heel_height(base_skeleton_type); + float_t height = fabsf(b_cl_momo_l->base_translation[1].y) + b_cl_momo_l->ik_segment_length[1] + + b_cl_momo_l->ik_2nd_segment_length[1] + aft_bone_database_get_skeleton_heel_height(skeleton_type); + a1->ratio0 = height / base_height; + a1->ratio1 = (fabsf(b_kl_kubi->base_translation[1].y) + b_cl_mune->ik_segment_length[1]) + / (fabsf(b_kl_kubi->base_translation[0].y) + b_cl_mune->ik_segment_length[0]); + a1->ratio2 = (b_c_kata_l->ik_segment_length[1] + b_c_kata_l->ik_2nd_segment_length[1]) + / (b_c_kata_l->ik_segment_length[0] + b_c_kata_l->ik_2nd_segment_length[0]); + a1->ratio3 = (fabsf(b_kl_kubi->base_translation[1].y) + b_cl_mune->ik_segment_length[1] + height) + / (fabsf(b_kl_kubi->base_translation[0].y) + b_cl_mune->ik_segment_length[0] + base_height); +} + +static void rob_chara_data_bone_data_get_ik_scale(rob_chara_data_bone_data* a1) { + if (!a1->motion_loaded.size) + return; + + motion_blend_mot* v2 = a1->motion_loaded.head->next->value; + rob_chara_data_bone_data_ik_scale_calculate(&a1->ik_scale, &v2->bone_data.bones, a1->base_skeleton_type, a1->skeleton_type); + float_t ratio0 = a1->ik_scale.ratio0; + v2->field_4F8.field_C0 = ratio0; + v2->field_4F8.field_C4 = ratio0; + v2->field_4F8.field_C8 = vec3_null; +} + +static float_t rob_chara_data_bone_data_get_ik_scale_ratio0(rob_chara_data_bone_data* a1) { + return a1->ik_scale.ratio0; +} + +static void sub_1405167A0(rob_chara_data* a1) { + a1->field_C = 1; +} + +static void sub_140513C60(rob_chara_data_item_equip* a1, int32_t a2, bool a3) { + if (a3) + a1->field_18[a2] &= ~4; + else + a1->field_18[a2] |= 4; +} + +static aft_object_info sub_140525C00(struc_288* a1, int32_t a2) { + tree_pair_int32_t_int32_t_node* v2 = a1->field_3F8.head; + tree_pair_int32_t_int32_t_node* v3 = v2; + tree_pair_int32_t_int32_t_node* v4 = v2->parent; + while (!v4->is_null) + if (v4->key >= a2) { + v3 = v4; + v4 = v4->left; + } + else + v4 = v4->right; + + tree_pair_int32_t_int32_t_node* v6; + if (v3 == v2 || a2 < v3->key) + v6 = v2; + else + v6 = v3; + + if (v6 == v2) + return (aft_object_info) { -1, -1 }; + else + return *(aft_object_info*)&v6->value; +} + +static aft_object_info sub_1405104C0(rob_chara_data* a1, int32_t a2) { + if (a2 > 8) + return (aft_object_info) { -1, -1 }; + + aft_object_info v3 = sub_140525C00(&a1->field_38, a2); + if (v3.id == -1 && v3.set_id == -1) + return a1->chara_init_data->head_objects[a2]; + return v3; +} + +static void sub_1405139E0(rob_chara_data_item_equip* a1, uint32_t a2, bool draw) { + a1->item_equip_object[a2].draw = draw; +} + +static void sub_140517120(rob_chara_data* a1, uint32_t a2, bool draw) { + if (a2 < 31) + sub_1405139E0(a1->item_equip, a2, draw); + else if (a2 == 31) { + void(*sub_140543780)(int32_t a1, int32_t a2, char a3) = (void*)0x0000000140543780; + void(*sub_1405430F0)(int32_t a1, int32_t a2) = (void*)0x00000001405430F0; + + for (int32_t i = 1; i < 31; i++) { + sub_1405139E0(a1->item_equip, i, draw); + if (i == 1 && rob_chara_data_check_for_ageageagain_module( + a1->chara_index, a1->module_index)) { + sub_140543780(a1->chara_id, 1, draw); + sub_140543780(a1->chara_id, 2, draw); + sub_1405430F0(a1->chara_id, 1); + sub_1405430F0(a1->chara_id, 2); + } + } + } +} + +void rob_chara_data_reset(rob_chara_data* a1, rob_chara_pv_data* a2) { + float_t(*sub_140228BD0)(vec3 * a1, float_t a2) = (void*)0x0000000140228BD0; + void(*sub_140505EA0)(struc_263 * a1) = (void*)0x0000000140505EA0; + struc_243* (*sub_140510550)(int32_t a1) = (void*)0x0000000140510550; + struc_241* (*sub_1405106E0)(int32_t a1) = (void*)0x00000001405106E0; + void(*sub_1405552A0)(rob_chara_data * a1, int32_t motion_id, + bool a3, float_t a4, int32_t a5) = (void*)0x00000001405552A0; + + int32_t v2 = a1->field_440.field_8.field_1CC; + rob_chara_data_bone_data_reset(a1->bone_data); + rob_chara_data_bone_data_init_data(a1->bone_data, + AFT_BONE_DATABASE_SKELETON_COMMON, a1->chara_init_data->skeleton_type); + sub_140505EA0(&a1->field_440); + sub_140505EA0(&a1->field_4228); + rob_chara_data_item_equip_get_parent_bone_nodes(a1->item_equip, + rob_chara_data_bone_data_get_node(a1->bone_data, 0)); + a1->field_4 = a2->index; + sub_140517060(a1, a2->field_4); + a1->field_A = a2->field_16; + a1->field_1C = 1.0f; + vec3 v8 = a2->field_8; + if (a2->index != 2) { + vec3 v19 = a2->field_8; + v19.y += 1.0f; + v8.y = sub_140228BD0(&v19, 0.0); + } + + struc_263* v3 = &a1->field_440; + v3->field_1D38.field_0 = a2->field_14; + v3->field_1D38.field_6 = a2->field_14; + v3->field_1D38.field_18 = v8; + v3->field_1D38.field_24 = v8; + v3->field_1D38.ex_data_mat = v8; + v3->field_1DE4.scale = chara_size_table_get_value(a1->pv_data.field_9C); + v3->field_1DE4.field_4 = a1->pv_data.field_A0; + v3->field_1DE4.field_8 = sub_140510320(a1->pv_data.field_9C); + v3->field_8.field_1A8 = a1->chara_init_data->field_838[v3->field_8.field_1A4]; + sub_14041C5C0(a1->bone_data, sub_140510550(a1->chara_index)); + rob_chara_data_bone_data_eyes_xrot_adjust(a1->bone_data, + sub_1405106E0(a1->chara_index), &a2->eyes_adjust); + sub_14041D4E0(a1->bone_data, &a2->field_18); + sub_14041D5C0(a1->bone_data, &a2->field_44); + sub_14041D560(a1->bone_data, 1, 0); + rob_chara_data_bone_data_get_ik_scale(a1->bone_data); + float_t ratio0 = rob_chara_data_bone_data_get_ik_scale_ratio0(a1->bone_data); + v3->field_290.field_138 = ratio0; + v3->field_290.field_13C = ratio0; + v3->field_290.field_140 = 0; + v3->field_290.field_144 = 0; + v3->field_290.field_148 = 0; + rob_chara_data_load_default_motion(a1); + v3->field_8.field_4 = 1; + v3->field_8.field_10 = rob_cmn_mottbl_get_motion_index(a1, 0); + v3->field_8.field_0 = 0; + v3->field_8.field_14 = a2->field_5; + sub_1405552A0(a1, v3->field_8.field_10, v3->field_8.field_14, 0.0, 0); + if (!a2->field_6) + v3->field_8.field_1CC = v2; + sub_1405167A0(a1); + a1->item_equip->field_DC = 0; + sub_140513C60(a1->item_equip, 1, false); + sub_140513C60(a1->item_equip, 10, false); + sub_140513C60(a1->item_equip, 11, false); + aft_object_info v17 = sub_1405104C0(a1, 0); + v3->field_290.field_300 = v17; + v3->field_290.field_560 = v17; + sub_140517120(a1, 0x1F, true); + a1->field_20 = 0; +} diff --git a/src/DivaGL/bone_data.h b/src/DivaGL/bone_data.h new file mode 100644 index 00000000..6ea2441e --- /dev/null +++ b/src/DivaGL/bone_data.h @@ -0,0 +1,3717 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/mat.h" +#include "../KKdLib/string.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/vector.h" +#include "shader_table.h" +#include + +typedef enum shadow_type_enum { + SHADOW_CHARA = 0x00, + SHADOW_STAGE = 0x01, +} shadow_type_enum; + +typedef enum aft_obj_vertex_attrib_type { + AFT_OBJ_VERTEX_ATTRIB_POSITION = 0x0001, + AFT_OBJ_VERTEX_ATTRIB_NORMAL = 0x0002, + AFT_OBJ_VERTEX_ATTRIB_TANGENT = 0x0004, + AFT_OBJ_VERTEX_ATTRIB_BINORMAL = 0x0008, + AFT_OBJ_VERTEX_ATTRIB_TEXCOORD0 = 0x0010, + AFT_OBJ_VERTEX_ATTRIB_TEXCOORD1 = 0x0020, + AFT_OBJ_VERTEX_ATTRIB_TEXCOORD2 = 0x0040, + AFT_OBJ_VERTEX_ATTRIB_TEXCOORD3 = 0x0080, + AFT_OBJ_VERTEX_ATTRIB_COLOR0 = 0x0100, + AFT_OBJ_VERTEX_ATTRIB_COLOR1 = 0x0200, + AFT_OBJ_VERTEX_ATTRIB_BONE_WEIGHT = 0x0400, + AFT_OBJ_VERTEX_ATTRIB_BONE_INDEX = 0x0800, + AFT_OBJ_VERTEX_ATTRIB_UNK_1000 = 0x1000, +} aft_obj_vertex_attrib_type; + +typedef enum aft_obj_mesh_flags { + AFT_OBJ_MESH_1 = 0x01, + AFT_OBJ_MESH_FACE_CAMERA_POSITION = 0x02, + AFT_OBJ_MESH_TRANSLUCENT_NO_SHADOW = 0x04, + AFT_OBJ_MESH_FACE_CAMERA_VIEW = 0x08, +} aft_obj_mesh_flags; + +typedef enum aft_obj_material_flags { + AFT_OBJ_MATERIAL_COLOR = 0x0001, + AFT_OBJ_MATERIAL_COLOR_ALPHA = 0x0002, + AFT_OBJ_MATERIAL_COLOR_L1 = 0x0004, + AFT_OBJ_MATERIAL_COLOR_L1_ALPHA = 0x0008, + AFT_OBJ_MATERIAL_COLOR_L2 = 0x0010, + AFT_OBJ_MATERIAL_COLOR_L2_ALPHA = 0x0020, + AFT_OBJ_MATERIAL_TRANSPARENCY = 0x0040, + AFT_OBJ_MATERIAL_SPECULAR = 0x0080, + AFT_OBJ_MATERIAL_NORMAL = 0x0100, + AFT_OBJ_MATERIAL_NORMALALT = 0x0200, + AFT_OBJ_MATERIAL_ENVIRONMENT = 0x0400, + AFT_OBJ_MATERIAL_COLOR_L3 = 0x0800, + AFT_OBJ_MATERIAL_COLOR_L3_ALPHA = 0x1000, + AFT_OBJ_MATERIAL_TRANSLUCENCY = 0x2000, + AFT_OBJ_MATERIAL_FLAG_14 = 0x4000, + AFT_OBJ_MATERIAL_OVERRIDE_IBL = 0x8000, +} aft_obj_material_flags; + +typedef enum aft_obj_material_texture_sampler_flags { + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_REPEAT_U = 0x00001, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_REPEAT_V = 0x00002, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_MIRROR_U = 0x00004, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_MIRROR_V = 0x00008, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_IGNORE_ALPHA = 0x00010, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_BORDER = 0x08000, + AFT_OBJ_MATERIAL_TEXTURE_SAMPLER_CLAMP_TO_EDGE = 0x10000, +} aft_obj_material_texture_sampler_flags; + +typedef enum aft_obj_primitive_type { + AFT_OBJ_PRIMITIVE_POINTS = 0x00, + AFT_OBJ_PRIMITIVE_LINES = 0x01, + AFT_OBJ_PRIMITIVE_LINE_STRIP = 0x02, + AFT_OBJ_PRIMITIVE_LINE_LOOP = 0x03, + AFT_OBJ_PRIMITIVE_TRIANGLES = 0x04, + AFT_OBJ_PRIMITIVE_TRIANGLE_STRIP = 0x05, + AFT_OBJ_PRIMITIVE_TRIANGLE_FAN = 0x06, + AFT_OBJ_PRIMITIVE_QUADS = 0x07, + AFT_OBJ_PRIMITIVE_QUAD_STRIP = 0x08, + AFT_OBJ_PRIMITIVE_POLYGON = 0x09, +} aft_obj_primitive_type; + +typedef enum aft_obj_index_format { + AFT_OBJ_INDEX_U8 = 0x00, + AFT_OBJ_INDEX_U16 = 0x01, + AFT_OBJ_INDEX_U32 = 0x02, +} aft_obj_index_format; + +typedef enum aft_obj_sub_mesh_flags { + AFT_OBJ_SUB_MESH_RECIEVE_SHADOW = 0x01, + AFT_OBJ_SUB_MESH_CAST_SHADOW = 0x02, + AFT_OBJ_SUB_MESH_TRANSPARENT = 0x04, + AFT_OBJ_SUB_MESH_FLAG_8 = 0x08, + AFT_OBJ_SUB_MESH_FLAG_10 = 0x10, + AFT_OBJ_SUB_MESH_FLAG_20 = 0x20, + AFT_OBJ_SUB_MESH_FLAG_40 = 0x40, + AFT_OBJ_SUB_MESH_FLAG_80 = 0x80, +} aft_obj_sub_mesh_flags; + +typedef enum aft_obj_skin_block_constraint_type { + AFT_OBJ_SKIN_BLOCK_CONSTRAINT_NONE = 0x00, + AFT_OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION = 0x01, + AFT_OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION = 0x02, + AFT_OBJ_SKIN_BLOCK_CONSTRAINT_POSITION = 0x03, + AFT_OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE = 0x04, +} aft_obj_skin_block_constraint_type; + +typedef enum aft_obj_database_string_type { + AFT_OBJ_DATABASE_STRING_OBJECT_FILE_NAME = 0x00, + AFT_OBJ_DATABASE_STRING_TEXTURE_FILE_NAME = 0x01, + AFT_OBJ_DATABASE_STRING_ARCHIVE_FILE_NAME = 0x02, +} aft_obj_database_string_type; + +typedef enum aft_obj_material_texture_type { + AFT_OBJ_MATERIAL_TEXTURE_NONE = 0x0, + AFT_OBJ_MATERIAL_TEXTURE_COLOR = 0x01, + AFT_OBJ_MATERIAL_TEXTURE_NORMAL = 0x02, + AFT_OBJ_MATERIAL_TEXTURE_SPECULAR = 0x03, + AFT_OBJ_MATERIAL_TEXTURE_HEIGHT = 0x04, + AFT_OBJ_MATERIAL_TEXTURE_REFLECTION = 0x05, + AFT_OBJ_MATERIAL_TEXTURE_TRANSLUCENCY = 0x06, + AFT_OBJ_MATERIAL_TEXTURE_TRANSPARENCY = 0x07, + AFT_OBJ_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE = 0x08, + AFT_OBJ_MATERIAL_TEXTURE_ENVIRONMENT_CUBE = 0x09, +} aft_obj_material_texture_type; + +typedef enum aft_obj_material_shader_vertex_tranlsation_type { + AFT_OBJ_MATERIAL_SHADER_VERTEX_TRANLSATION_DEFAULT = 0x00, + AFT_OBJ_MATERIAL_SHADER_VERTEX_TRANLSATION_ENVELOPE = 0x01, + AFT_OBJ_MATERIAL_SHADER_VERTEX_TRANLSATION_MORPHING = 0x02, +} aft_obj_material_shader_vertex_tranlsation_type; + +typedef enum aft_obj_material_shader_color_source_type { + AFT_OBJ_MATERIAL_SHADER_COLOR_SOURCE_MATERIAL_COLOR = 0x00, + AFT_OBJ_MATERIAL_SHADER_COLOR_SOURCE_VERTEX_COLOR = 0x01, + AFT_OBJ_MATERIAL_SHADER_COLOR_SOURCE_VERTEX_MORPH = 0x02, +} aft_obj_material_shader_color_source_type; + +typedef enum aft_obj_material_shader_bump_map_type { + AFT_OBJ_MATERIAL_SHADER_BUMP_MAP_NONE = 0x00, + AFT_OBJ_MATERIAL_SHADER_BUMP_MAP_DOT = 0x01, + AFT_OBJ_MATERIAL_SHADER_BUMP_MAP_ENV = 0x02, +} aft_obj_material_shader_bump_map_type; + +typedef enum aft_obj_material_shader_specular_quality { + AFT_OBJ_MATERIAL_SHADER_SPECULAR_QUALITY_LOW = 0x00, + AFT_OBJ_MATERIAL_SHADER_SPECULAR_QUALITY_HIGH = 0x01, +} aft_obj_material_shader_specular_quality; + +typedef enum aft_obj_material_shader_aniso_direction { + AFT_OBJ_MATERIAL_SHADER_ANISO_DIRECTION_NORMAL = 0x00, + AFT_OBJ_MATERIAL_SHADER_ANISO_DIRECTION_U = 0x01, + AFT_OBJ_MATERIAL_SHADER_ANISO_DIRECTION_V = 0x02, + AFT_OBJ_MATERIAL_SHADER_ANISO_DIRECTION_RADIAL = 0x03, +} aft_obj_material_shader_aniso_direction; + +typedef enum aft_obj_material_shader_blend_factor { + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_ZERO = 0x0, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_ONE = 0x1, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_SRC_COLOR = 0x2, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_INVERSE_SRC_COLOR = 0x3, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_SRC_ALPHA = 0x4, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_INVERSE_SRC_ALPHA = 0x5, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_DST_ALPHA = 0x6, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_INVERSE_DST_ALPHA = 0x7, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_DST_COLOR = 0x8, + AFT_OBJ_MATERIAL_SHADER_BLEND_FACTOR_INVERSE_DST_COLOR = 0x9, +} aft_obj_material_shader_blend_factor; + +typedef enum aft_obj_material_specular_quality { + AFT_OBJ_MATERIAL_SPECULAR_QUALITY_LOW = 0x00, + AFT_OBJ_MATERIAL_SPECULAR_QUALITY_HIGH = 0x01, +} aft_obj_material_specular_quality; + +typedef enum aft_obj_material_vertex_translation_type { + AFT_OBJ_MATERIAL_VERTEX_TRANSLATION_DEFAULT = 0x00, + AFT_OBJ_MATERIAL_VERTEX_TRANSLATION_ENVELOPE = 0x01, + AFT_OBJ_MATERIAL_VERTEX_TRANSLATION_MORPHING = 0x02, +} aft_obj_material_vertex_translation_type; + +typedef enum aft_obj_material_shader_lighting_type { + AFT_OBJ_MATERIAL_SHADER_LIGHTING_LAMBERT = 0x00, + AFT_OBJ_MATERIAL_SHADER_LIGHTING_CONSTANT = 0x01, + AFT_OBJ_MATERIAL_SHADER_LIGHTING_PHONG = 0x02, +} aft_obj_material_shader_lighting_type; + +typedef enum aft_bone_database_bone_type { + AFT_BONE_DATABASE_BONE_ROTATION = 0x00, + AFT_BONE_DATABASE_BONE_TYPE_1 = 0x01, + AFT_BONE_DATABASE_BONE_POSITION = 0x02, + AFT_BONE_DATABASE_BONE_POSITION_ROTATION = 0x03, + AFT_BONE_DATABASE_BONE_HEAD_IK_ROTATION = 0x04, + AFT_BONE_DATABASE_BONE_ARM_IK_ROTATION = 0x05, + AFT_BONE_DATABASE_BONE_LEGS_IK_ROTATION = 0x06, + AFT_BONE_DATABASE_BONE_END = 0xFF, +} aft_bone_database_bone_type; + +typedef enum aft_bone_database_skeleton_type { + AFT_BONE_DATABASE_SKELETON_COMMON = 0, + AFT_BONE_DATABASE_SKELETON_MIKU = 1, + AFT_BONE_DATABASE_SKELETON_KAITO = 2, + AFT_BONE_DATABASE_SKELETON_LEN = 3, + AFT_BONE_DATABASE_SKELETON_LUKA = 4, + AFT_BONE_DATABASE_SKELETON_MEIKO = 5, + AFT_BONE_DATABASE_SKELETON_RIN = 6, + AFT_BONE_DATABASE_SKELETON_HAKU = 7, + AFT_BONE_DATABASE_SKELETON_NERU = 8, + AFT_BONE_DATABASE_SKELETON_SAKINE = 9, + AFT_BONE_DATABASE_SKELETON_TETO = 10, + AFT_BONE_DATABASE_SKELETON_NONE = -1, +} aft_bone_database_skeleton_type; + +typedef enum chara_index { + CHARA_MIKU = 0, + CHARA_RIN = 1, + CHARA_LEN = 2, + CHARA_LUKA = 3, + CHARA_NERU = 4, + CHARA_HAKU = 5, + CHARA_KAITO = 6, + CHARA_MEIKO = 7, + CHARA_SAKINE = 8, + CHARA_TETO = 9, + CHARA_MAX = 10, +} chara_index; + +typedef enum draw_task_flags { + DRAW_TASK_SHADOW = 0x00000001, + DRAW_TASK_2 = 0x00000002, + DRAW_TASK_4 = 0x00000004, + DRAW_TASK_SELF_SHADOW = 0x00000008, + DRAW_TASK_10 = 0x00000010, + DRAW_TASK_20 = 0x00000020, + DRAW_TASK_40 = 0x00000040, + DRAW_TASK_SHADOW_OBJECT = 0x00000080, + DRAW_TASK_CHARA_REFLECT = 0x00000100, + DRAW_TASK_REFLECT = 0x00000200, + DRAW_TASK_REFRACT = 0x00000400, + DRAW_TASK_800 = 0x00000800, + DRAW_TASK_1000 = 0x00001000, + DRAW_TASK_SSS = 0x00002000, + DRAW_TASK_4000 = 0x00004000, + DRAW_TASK_8000 = 0x00008000, + DRAW_TASK_10000 = 0x00010000, + DRAW_TASK_20000 = 0x00020000, + DRAW_TASK_40000 = 0x00040000, + DRAW_TASK_80000 = 0x00080000, + DRAW_TASK_100000 = 0x00100000, + DRAW_TASK_200000 = 0x00200000, + DRAW_TASK_400000 = 0x00400000, + DRAW_TASK_800000 = 0x00800000, + DRAW_TASK_RIPPLE = 0x01000000, + DRAW_TASK_2000000 = 0x02000000, + DRAW_TASK_4000000 = 0x04000000, + DRAW_TASK_8000000 = 0x08000000, + DRAW_TASK_10000000 = 0x10000000, + DRAW_TASK_20000000 = 0x20000000, + DRAW_TASK_40000000 = 0x40000000, + DRAW_TASK_NO_TRANSLUCENCY = 0x80000000, +} draw_task_flags; + +typedef enum ex_expression_block_stack_type { + EX_EXPRESSION_BLOCK_STACK_NUMBER = 0x00, + EX_EXPRESSION_BLOCK_STACK_VARIABLE = 0x01, + EX_EXPRESSION_BLOCK_STACK_VARIABLE_RADIAN = 0x02, + EX_EXPRESSION_BLOCK_STACK_OP1 = 0x03, + EX_EXPRESSION_BLOCK_STACK_OP2 = 0x04, + EX_EXPRESSION_BLOCK_STACK_OP3 = 0x05, +} ex_expression_block_stack_type; + +typedef enum ex_node_type { + EX_NONE = 0x00, + EX_OSAGE = 0x01, + EX_EXPRESSION = 0x02, + EX_CONSTRAINT = 0x03, + EX_CLOTH = 0x04, +} ex_node_type; + +typedef enum eyes_base_adjust_type { + EYES_BASE_ADJUST_DIRECTION = 0, + EYES_BASE_ADJUST_CLEARANCE = 1, + EYES_BASE_ADJUST_OFF = 2, +} eyes_base_adjust_type; + +typedef enum mot_key_set_type { + MOT_KEY_SET_NONE = 0x00, + MOT_KEY_SET_STATIC = 0x01, + MOT_KEY_SET_HERMITE = 0x02, + MOT_KEY_SET_HERMITE_TANGENT = 0x03, +} mot_key_set_type; + +typedef enum mothead_data_type { + MOTHEAD_DATA_TYPE_0 = 0x00, + MOTHEAD_DATA_TYPE_1 = 0x01, + MOTHEAD_DATA_TYPE_2 = 0x02, + MOTHEAD_DATA_TYPE_3 = 0x03, + MOTHEAD_DATA_TYPE_4 = 0x04, + MOTHEAD_DATA_TYPE_5 = 0x05, + MOTHEAD_DATA_TYPE_6 = 0x06, + MOTHEAD_DATA_TYPE_7 = 0x07, + MOTHEAD_DATA_TYPE_8 = 0x08, + MOTHEAD_DATA_TYPE_9 = 0x09, + MOTHEAD_DATA_TYPE_10 = 0x0A, + MOTHEAD_DATA_TYPE_11 = 0x0B, + MOTHEAD_DATA_TYPE_12 = 0x0C, + MOTHEAD_DATA_TYPE_13 = 0x0D, + MOTHEAD_DATA_TYPE_14 = 0x0E, + MOTHEAD_DATA_TYPE_15 = 0x0F, + MOTHEAD_DATA_TYPE_16 = 0x10, + MOTHEAD_DATA_TYPE_17 = 0x11, + MOTHEAD_DATA_TYPE_18 = 0x12, + MOTHEAD_DATA_TYPE_19 = 0x13, + MOTHEAD_DATA_TYPE_20 = 0x14, + MOTHEAD_DATA_TYPE_21 = 0x15, + MOTHEAD_DATA_TYPE_22 = 0x16, + MOTHEAD_DATA_TYPE_23 = 0x17, + MOTHEAD_DATA_TYPE_24 = 0x18, + MOTHEAD_DATA_TYPE_25 = 0x19, + MOTHEAD_DATA_TYPE_26 = 0x1A, + MOTHEAD_DATA_TYPE_27 = 0x1B, + MOTHEAD_DATA_TYPE_28 = 0x1C, + MOTHEAD_DATA_TYPE_29 = 0x1D, + MOTHEAD_DATA_TYPE_30 = 0x1E, + MOTHEAD_DATA_TYPE_31 = 0x1F, + MOTHEAD_DATA_TYPE_32 = 0x20, + MOTHEAD_DATA_TYPE_33 = 0x21, + MOTHEAD_DATA_TYPE_34 = 0x22, + MOTHEAD_DATA_TYPE_35 = 0x23, + MOTHEAD_DATA_TYPE_36 = 0x24, + MOTHEAD_DATA_TYPE_37 = 0x25, + MOTHEAD_DATA_TYPE_38 = 0x26, + MOTHEAD_DATA_TYPE_39 = 0x27, + MOTHEAD_DATA_TYPE_40 = 0x28, + MOTHEAD_DATA_TYPE_41 = 0x29, + MOTHEAD_DATA_TYPE_42 = 0x2A, + MOTHEAD_DATA_TYPE_43 = 0x2B, + MOTHEAD_DATA_TYPE_44 = 0x2C, + MOTHEAD_DATA_TYPE_45 = 0x2D, + MOTHEAD_DATA_TYPE_46 = 0x2E, + MOTHEAD_DATA_TYPE_47 = 0x2F, + MOTHEAD_DATA_TYPE_48 = 0x30, + MOTHEAD_DATA_TYPE_49 = 0x31, + MOTHEAD_DATA_TYPE_50 = 0x32, + MOTHEAD_DATA_TYPE_51 = 0x33, + MOTHEAD_DATA_TYPE_52 = 0x34, + MOTHEAD_DATA_TYPE_53 = 0x35, + MOTHEAD_DATA_TYPE_54 = 0x36, + MOTHEAD_DATA_TYPE_55 = 0x37, + MOTHEAD_DATA_TYPE_56 = 0x38, + MOTHEAD_DATA_TYPE_57 = 0x39, + MOTHEAD_DATA_TYPE_58 = 0x3A, + MOTHEAD_DATA_TYPE_59 = 0x3B, + MOTHEAD_DATA_TYPE_60 = 0x3C, + MOTHEAD_DATA_TYPE_61 = 0x3D, + MOTHEAD_DATA_TYPE_62 = 0x3E, + MOTHEAD_DATA_TYPE_63 = 0x3F, + MOTHEAD_DATA_TYPE_64 = 0x40, + MOTHEAD_DATA_TYPE_65 = 0x41, + MOTHEAD_DATA_TYPE_66 = 0x42, + MOTHEAD_DATA_TYPE_67 = 0x43, + MOTHEAD_DATA_TYPE_68 = 0x44, + MOTHEAD_DATA_TYPE_69 = 0x45, + MOTHEAD_DATA_TYPE_70 = 0x46, + MOTHEAD_DATA_TYPE_71 = 0x47, + MOTHEAD_DATA_TYPE_72 = 0x48, + MOTHEAD_DATA_TYPE_73 = 0x49, + MOTHEAD_DATA_TYPE_74 = 0x4A, + MOTHEAD_DATA_TYPE_75 = 0x4B, + MOTHEAD_DATA_TYPE_76 = 0x4C, + MOTHEAD_DATA_TYPE_77 = 0x4D, + MOTHEAD_DATA_TYPE_78 = 0x4E, + MOTHEAD_DATA_TYPE_79 = 0x4F, + MOTHEAD_DATA_TYPE_80 = 0x50, +} mothead_data_type; + +typedef enum motion_blend_type { + MOTION_BLEND_NONE = -1, + MOTION_BLEND = 0x00, + MOTION_BLEND_FREEZE = 0x01, + MOTION_BLEND_CROSS = 0x02, + MOTION_BLEND_COMBINE = 0x03, +} motion_blend_type; + +typedef enum motion_bone_index { + MOTION_BONE_NONE = -1, + MOTION_BONE_N_HARA_CP = 0x00, + MOTION_BONE_KG_HARA_Y = 0x01, + MOTION_BONE_KL_HARA_XZ = 0x02, + MOTION_BONE_KL_HARA_ETC = 0x03, + MOTION_BONE_N_HARA = 0x04, + MOTION_BONE_CL_MUNE = 0x05, + MOTION_BONE_N_MUNE_B = 0x06, + MOTION_BONE_KL_MUNE_B_WJ = 0x07, + MOTION_BONE_KL_KUBI = 0x08, + MOTION_BONE_N_KAO = 0x09, + MOTION_BONE_CL_KAO = 0x0A, + MOTION_BONE_FACE_ROOT = 0x0B, + MOTION_BONE_N_AGO = 0x0C, + MOTION_BONE_KL_AGO_WJ = 0x0D, + MOTION_BONE_N_TOOTH_UNDER = 0x0E, + MOTION_BONE_TL_TOOTH_UNDER_WJ = 0x0F, + MOTION_BONE_N_EYE_L = 0x10, + MOTION_BONE_KL_EYE_L = 0x11, + MOTION_BONE_N_EYE_L_WJ_EX = 0x12, + MOTION_BONE_KL_HIGHLIGHT_L_WJ = 0x13, + MOTION_BONE_N_EYE_R = 0x14, + MOTION_BONE_KL_EYE_R = 0x15, + MOTION_BONE_N_EYE_R_WJ_EX = 0x16, + MOTION_BONE_KL_HIGHLIGHT_R_WJ = 0x17, + MOTION_BONE_N_EYELID_L_A = 0x18, + MOTION_BONE_TL_EYELID_L_A_WJ = 0x19, + MOTION_BONE_N_EYELID_L_B = 0x1A, + MOTION_BONE_TL_EYELID_L_B_WJ = 0x1B, + MOTION_BONE_N_EYELID_R_A = 0x1C, + MOTION_BONE_TL_EYELID_R_A_WJ = 0x1D, + MOTION_BONE_N_EYELID_R_B = 0x1E, + MOTION_BONE_TL_EYELID_R_B_WJ = 0x1F, + MOTION_BONE_N_KUTI_D = 0x20, + MOTION_BONE_TL_KUTI_D_WJ = 0x21, + MOTION_BONE_N_KUTI_D_L = 0x22, + MOTION_BONE_TL_KUTI_D_L_WJ = 0x23, + MOTION_BONE_N_KUTI_D_R = 0x24, + MOTION_BONE_TL_KUTI_D_R_WJ = 0x25, + MOTION_BONE_N_KUTI_DS_L = 0x26, + MOTION_BONE_TL_KUTI_DS_L_WJ = 0x27, + MOTION_BONE_N_KUTI_DS_R = 0x28, + MOTION_BONE_TL_KUTI_DS_R_WJ = 0x29, + MOTION_BONE_N_KUTI_L = 0x2A, + MOTION_BONE_TL_KUTI_L_WJ = 0x2B, + MOTION_BONE_N_KUTI_M_L = 0x2C, + MOTION_BONE_TL_KUTI_M_L_WJ = 0x2D, + MOTION_BONE_N_KUTI_M_R = 0x2E, + MOTION_BONE_TL_KUTI_M_R_WJ = 0x2F, + MOTION_BONE_N_KUTI_R = 0x30, + MOTION_BONE_TL_KUTI_R_WJ = 0x31, + MOTION_BONE_N_KUTI_U = 0x32, + MOTION_BONE_TL_KUTI_U_WJ = 0x33, + MOTION_BONE_N_KUTI_U_L = 0x34, + MOTION_BONE_TL_KUTI_U_L_WJ = 0x35, + MOTION_BONE_N_KUTI_U_R = 0x36, + MOTION_BONE_TL_KUTI_U_R_WJ = 0x37, + MOTION_BONE_N_MABU_L_D_A = 0x38, + MOTION_BONE_TL_MABU_L_D_A_WJ = 0x39, + MOTION_BONE_N_MABU_L_D_B = 0x3A, + MOTION_BONE_TL_MABU_L_D_B_WJ = 0x3B, + MOTION_BONE_N_MABU_L_D_C = 0x3C, + MOTION_BONE_TL_MABU_L_D_C_WJ = 0x3D, + MOTION_BONE_N_MABU_L_U_A = 0x3E, + MOTION_BONE_TL_MABU_L_U_A_WJ = 0x3F, + MOTION_BONE_N_MABU_L_U_B = 0x40, + MOTION_BONE_TL_MABU_L_U_B_WJ = 0x41, + MOTION_BONE_N_EYELASHES_L = 0x42, + MOTION_BONE_TL_EYELASHES_L_WJ = 0x43, + MOTION_BONE_N_MABU_L_U_C = 0x44, + MOTION_BONE_TL_MABU_L_U_C_WJ = 0x45, + MOTION_BONE_N_MABU_R_D_A = 0x46, + MOTION_BONE_TL_MABU_R_D_A_WJ = 0x47, + MOTION_BONE_N_MABU_R_D_B = 0x48, + MOTION_BONE_TL_MABU_R_D_B_WJ = 0x49, + MOTION_BONE_N_MABU_R_D_C = 0x4A, + MOTION_BONE_TL_MABU_R_D_C_WJ = 0x4B, + MOTION_BONE_N_MABU_R_U_A = 0x4C, + MOTION_BONE_TL_MABU_R_U_A_WJ = 0x4D, + MOTION_BONE_N_MABU_R_U_B = 0x4E, + MOTION_BONE_TL_MABU_R_U_B_WJ = 0x4F, + MOTION_BONE_N_EYELASHES_R = 0x50, + MOTION_BONE_TL_EYELASHES_R_WJ = 0x51, + MOTION_BONE_N_MABU_R_U_C = 0x52, + MOTION_BONE_TL_MABU_R_U_C_WJ = 0x53, + MOTION_BONE_N_MAYU_L = 0x54, + MOTION_BONE_TL_MAYU_L_WJ = 0x55, + MOTION_BONE_N_MAYU_L_B = 0x56, + MOTION_BONE_TL_MAYU_L_B_WJ = 0x57, + MOTION_BONE_N_MAYU_L_C = 0x58, + MOTION_BONE_TL_MAYU_L_C_WJ = 0x59, + MOTION_BONE_N_MAYU_R = 0x5A, + MOTION_BONE_TL_MAYU_R_WJ = 0x5B, + MOTION_BONE_N_MAYU_R_B = 0x5C, + MOTION_BONE_TL_MAYU_R_B_WJ = 0x5D, + MOTION_BONE_N_MAYU_R_C = 0x5E, + MOTION_BONE_TL_MAYU_R_C_WJ = 0x5F, + MOTION_BONE_N_TOOTH_UPPER = 0x60, + MOTION_BONE_TL_TOOTH_UPPER_WJ = 0x61, + MOTION_BONE_N_KUBI_WJ_EX = 0x62, + MOTION_BONE_N_WAKI_L = 0x63, + MOTION_BONE_KL_WAKI_L_WJ = 0x64, + MOTION_BONE_TL_UP_KATA_L = 0x65, + MOTION_BONE_C_KATA_L = 0x66, + MOTION_BONE_KL_TE_L_WJ = 0x67, + MOTION_BONE_N_HITO_L_EX = 0x68, + MOTION_BONE_NL_HITO_L_WJ = 0x69, + MOTION_BONE_NL_HITO_B_L_WJ = 0x6A, + MOTION_BONE_NL_HITO_C_L_WJ = 0x6B, + MOTION_BONE_N_KO_L_EX = 0x6C, + MOTION_BONE_NL_KO_L_WJ = 0x6D, + MOTION_BONE_NL_KO_B_L_WJ = 0x6E, + MOTION_BONE_NL_KO_C_L_WJ = 0x6F, + MOTION_BONE_N_KUSU_L_EX = 0x70, + MOTION_BONE_NL_KUSU_L_WJ = 0x71, + MOTION_BONE_NL_KUSU_B_L_WJ = 0x72, + MOTION_BONE_NL_KUSU_C_L_WJ = 0x73, + MOTION_BONE_N_NAKA_L_EX = 0x74, + MOTION_BONE_NL_NAKA_L_WJ = 0x75, + MOTION_BONE_NL_NAKA_B_L_WJ = 0x76, + MOTION_BONE_NL_NAKA_C_L_WJ = 0x77, + MOTION_BONE_N_OYA_L_EX = 0x78, + MOTION_BONE_NL_OYA_L_WJ = 0x79, + MOTION_BONE_NL_OYA_B_L_WJ = 0x7A, + MOTION_BONE_NL_OYA_C_L_WJ = 0x7B, + MOTION_BONE_N_STE_L_WJ_EX = 0x7C, + MOTION_BONE_N_SUDE_L_WJ_EX = 0x7D, + MOTION_BONE_N_SUDE_B_L_WJ_EX = 0x7E, + MOTION_BONE_N_HIJI_L_WJ_EX = 0x7F, + MOTION_BONE_N_UP_KATA_L_EX = 0x80, + MOTION_BONE_N_SKATA_L_WJ_CD_EX = 0x81, + MOTION_BONE_N_SKATA_B_L_WJ_CD_CU_EX = 0x82, + MOTION_BONE_N_SKATA_C_L_WJ_CD_CU_EX = 0x83, + MOTION_BONE_N_WAKI_R = 0x84, + MOTION_BONE_KL_WAKI_R_WJ = 0x85, + MOTION_BONE_TL_UP_KATA_R = 0x86, + MOTION_BONE_C_KATA_R = 0x87, + MOTION_BONE_KL_TE_R_WJ = 0x88, + MOTION_BONE_N_HITO_R_EX = 0x89, + MOTION_BONE_NL_HITO_R_WJ = 0x8A, + MOTION_BONE_NL_HITO_B_R_WJ = 0x8B, + MOTION_BONE_NL_HITO_C_R_WJ = 0x8C, + MOTION_BONE_N_KO_R_EX = 0x8D, + MOTION_BONE_NL_KO_R_WJ = 0x8E, + MOTION_BONE_NL_KO_B_R_WJ = 0x8F, + MOTION_BONE_NL_KO_C_R_WJ = 0x90, + MOTION_BONE_N_KUSU_R_EX = 0x91, + MOTION_BONE_NL_KUSU_R_WJ = 0x92, + MOTION_BONE_NL_KUSU_B_R_WJ = 0x93, + MOTION_BONE_NL_KUSU_C_R_WJ = 0x94, + MOTION_BONE_N_NAKA_R_EX = 0x95, + MOTION_BONE_NL_NAKA_R_WJ = 0x96, + MOTION_BONE_NL_NAKA_B_R_WJ = 0x97, + MOTION_BONE_NL_NAKA_C_R_WJ = 0x98, + MOTION_BONE_N_OYA_R_EX = 0x99, + MOTION_BONE_NL_OYA_R_WJ = 0x9A, + MOTION_BONE_NL_OYA_B_R_WJ = 0x9B, + MOTION_BONE_NL_OYA_C_R_WJ = 0x9C, + MOTION_BONE_N_STE_R_WJ_EX = 0x9D, + MOTION_BONE_N_SUDE_R_WJ_EX = 0x9E, + MOTION_BONE_N_SUDE_B_R_WJ_EX = 0x9F, + MOTION_BONE_N_HIJI_R_WJ_EX = 0xA0, + MOTION_BONE_N_UP_KATA_R_EX = 0xA1, + MOTION_BONE_N_SKATA_R_WJ_CD_EX = 0xA2, + MOTION_BONE_N_SKATA_B_R_WJ_CD_CU_EX = 0xA3, + MOTION_BONE_N_SKATA_C_R_WJ_CD_CU_EX = 0xA4, + MOTION_BONE_KL_KOSI_Y = 0xA5, + MOTION_BONE_KL_KOSI_XZ = 0xA6, + MOTION_BONE_KL_KOSI_ETC_WJ = 0xA7, + MOTION_BONE_CL_MOMO_L = 0xA8, + MOTION_BONE_KL_ASI_L_WJ_CO = 0xA9, + MOTION_BONE_KL_TOE_L_WJ = 0xAA, + MOTION_BONE_N_HIZA_L_WJ_EX = 0xAB, + MOTION_BONE_CL_MOMO_R = 0xAC, + MOTION_BONE_KL_ASI_R_WJ_CO = 0xAD, + MOTION_BONE_KL_TOE_R_WJ = 0xAE, + MOTION_BONE_N_HIZA_R_WJ_EX = 0xAF, + MOTION_BONE_N_MOMO_A_L_WJ_CD_EX = 0xB0, + MOTION_BONE_N_MOMO_B_L_WJ_EX = 0xB1, + MOTION_BONE_N_MOMO_C_L_WJ_EX = 0xB2, + MOTION_BONE_N_MOMO_A_R_WJ_CD_EX = 0xB3, + MOTION_BONE_N_MOMO_B_R_WJ_EX = 0xB4, + MOTION_BONE_N_MOMO_C_R_WJ_EX = 0xB5, + MOTION_BONE_N_HARA_CD_EX = 0xB6, + MOTION_BONE_N_HARA_B_WJ_EX = 0xB7, + MOTION_BONE_N_HARA_C_WJ_EX = 0xB8, + MOTION_BONE_MAX = 0xB9, +} motion_bone_index; + +typedef enum rob_sub_action_execute_type { + ROB_SUB_ACTION_EXECUTE_NONE = 0, + ROB_SUB_ACTION_EXECUTE_CRY = 1, + ROB_SUB_ACTION_EXECUTE_SHAKE_HAND = 2, + ROB_SUB_ACTION_EXECUTE_EMBARRASSED = 3, + ROB_SUB_ACTION_EXECUTE_ANGRY = 4, + ROB_SUB_ACTION_EXECUTE_LAUGH = 5, + ROB_SUB_ACTION_EXECUTE_COUNT_NUM = 6, +} rob_sub_action_execute_type; + +typedef enum rob_sub_action_param_type { + ROB_SUB_ACTION_PARAM_NONE = 0, + ROB_SUB_ACTION_PARAM_CRY = 1, + ROB_SUB_ACTION_PARAM_SHAKE_HAND = 2, + ROB_SUB_ACTION_PARAM_EMBARRASSED = 3, + ROB_SUB_ACTION_PARAM_ANGRY = 4, + ROB_SUB_ACTION_PARAM_LAUGH = 5, + ROB_SUB_ACTION_PARAM_COUNT_NUM = 6, +} rob_sub_action_param_type; + +typedef enum texture_flags { + TEXTURE_BLOCK_COMPRESSION = 0x1, +} texture_flags; + +#define list(t) \ +typedef struct list_##t##_node list_##t##_node; \ +\ +struct list_##t##_node { \ + list_##t##_node* next; \ + list_##t##_node* prev; \ + t* value; \ +}; \ + \ +typedef struct list_##t { \ + list_##t##_node* head; \ + size_t size; \ +} list_##t; + +#define list_ptr(t) \ +typedef struct list_ptr_##t##_node list_ptr_##t##_node; \ +\ +struct list_ptr_##t##_node { \ + list_ptr_##t##_node* next; \ + list_ptr_##t##_node* prev; \ + t* value; \ +}; \ + \ +typedef struct list_ptr_##t { \ + list_ptr_##t##_node* head; \ + size_t size; \ +} list_ptr_##t; + +#define tree_def(t1, t2) \ +typedef struct tree_##t##_node tree_##t##_node; \ +\ +struct tree_##t##_node { \ + tree_##t##_node* left; \ + tree_##t##_node* parent; \ + tree_##t##_node* right; \ + uint8_t color; \ + uint8_t is_null; \ + t value; \ +}; \ + \ +typedef struct tree_##t { \ + tree_##t##_node* head; \ + size_t size; \ +} tree_##t; + +#define tree_ptr(t1, t2) \ +typedef struct tree_ptr_##t##_node tree_ptr_##t##_node; \ +\ +struct tree_ptr_##t##_node { \ + tree_ptr_##t##_node* left; \ + tree_ptr_##t##_node* parent; \ + tree_ptr_##t##_node* right; \ + uint8_t color; \ + uint8_t is_null; \ + t* value; \ +}; \ + \ +typedef struct tree_ptr_##t { \ + tree_ptr_##t##_node* head; \ + size_t size; \ +} tree_ptr_##t; + +#define tree_pair(t1, t2) \ +typedef struct tree_pair_##t1##_##t2##_node tree_pair_##t1##_##t2##_node; \ +\ +struct tree_pair_##t1##_##t2##_node { \ + tree_pair_##t1##_##t2##_node* left; \ + tree_pair_##t1##_##t2##_node* parent; \ + tree_pair_##t1##_##t2##_node* right; \ + uint8_t color; \ + uint8_t is_null; \ + t1 key; \ + t2 value; \ +}; \ + \ +typedef struct tree_pair_##t1##_##t2 { \ + tree_pair_##t1##_##t2##_node* head; \ + size_t size; \ +} tree_pair_##t1##_##t2; + +#define tree_pair_ptr(t1, t2) \ +typedef struct tree_pair_##t1##_ptr_##t2##_node tree_pair_##t1##_ptr_##t2##_node; \ +\ +struct tree_pair_##t1##_ptr_##t2##_node { \ + tree_pair_##t1##_ptr_##t2##_node* left; \ + tree_pair_##t1##_ptr_##t2##_node* parent; \ + tree_pair_##t1##_ptr_##t2##_node* right; \ + uint8_t color; \ + uint8_t is_null; \ + t1 key; \ + t2* value; \ +}; \ + \ +typedef struct tree_pair_##t1##_ptr_##t2 { \ + tree_pair_##t1##_ptr_##t2##_node* head; \ + size_t size; \ +} tree_pair_##t1##_ptr_##t2; + +typedef struct aft_bone_database_bone { + uint8_t type; + bool has_parent; + uint8_t parent; + uint8_t pole_target; + uint8_t mirror; + uint8_t flags; + char* name; +} aft_bone_database_bone; + +typedef struct aft_bone_database_bone_file { + uint8_t type; + bool has_parent; + uint8_t parent; + uint8_t pole_target; + uint8_t mirror; + uint8_t flags; + uint32_t name_offset; +} aft_bone_database_bone_file; + +typedef struct aft_bone_database_skeleton { + aft_bone_database_bone* bones; + int32_t posittion_count; + int32_t field_C; + vec3* positions; + float_t* heel_height; + uint32_t object_bone_name_count; + int32_t field_24; + char** object_bone_names; + int32_t motion_bone_name_count; + int32_t field_34; + char** motion_bone_names; + uint16_t* parent_indices; + int32_t ex_data_mat; + int32_t field_4C; + int32_t field_50; + int32_t field_54; + int32_t field_58; + int32_t field_5C; +} aft_bone_database_skeleton; + +typedef struct aft_bone_database_struct { + uint32_t signature; + uint32_t skeleton_count; + aft_bone_database_skeleton** skeletons; + char** skeleton_names; +} aft_bone_database_struct; + +typedef struct rob_chara_data rob_chara_data; +typedef struct rob_chara_data_bone_data rob_chara_data_bone_data; +typedef struct rob_chara_data_item_equip rob_chara_data_item_equip; +typedef struct bone_node bone_node; + +typedef struct bone_node_expression_data { + vec3 position; + vec3 rotation; + vec3 scale; + vec3 data_scale; +} bone_node_expression_data; + +typedef struct bone_node { + char* name; + mat4* mat; + bone_node* parent; + bone_node_expression_data exp_data; + mat4* ex_data_mat; +} bone_node; + +vector(bone_node) + +typedef struct struc_314 { + uint32_t* field_0; + size_t field_8; +} struc_314; + +typedef struct mot_key_set { + mot_key_set_type type; + int32_t keys_count; + int32_t current_key; + int32_t last_key; + uint16_t* frames; + float_t* values; +} mot_key_set; + +vector(mot_key_set) + +typedef union request_data_object_data { + struct { + int32_t zujo; + int32_t kami; + int32_t hitai; + int32_t me; + int32_t megane; + int32_t mimi; + int32_t kuchi; + int32_t maki; + int32_t kubi; + int32_t inner; + int32_t outer; + int32_t joha_mae; + int32_t joha_ushiro; + int32_t hada; + int32_t kata; + int32_t u_ude; + int32_t l_ude; + int32_t te; + int32_t belt; + int32_t cosi; + int32_t pants; + int32_t asi; + int32_t sune; + int32_t kutsu; + int32_t head; + }; + int32_t array[25]; +} request_data_object_data; + +typedef struct struc_285 { + int64_t field_0; + int64_t field_8; + int64_t field_10; + int64_t field_18; +} struc_285; + +list(struc_285) + +typedef struct struc_289 { + int32_t field_0; + int32_t field_4; + int64_t field_8; + int64_t field_10; + int64_t field_18; +} struc_289; + +list(struc_289) + +typedef struct struc_298 { + int64_t field_0; + int64_t field_8; + int64_t field_10; +} struc_298; + +typedef struct struc_293 { + int32_t key; + void* value; +} struc_293; + +list(struc_293) + +tree_pair(int32_t, int32_t) + +list_ptr(void) + +typedef struct struc_288 { + chara_index chara_index; + int32_t field_4; + request_data_object_data field_8; + request_data_object_data field_6C; + list_struc_285 field_D0; + list_struc_289 field_E0; + list_struc_293 field_F0; + list_ptr_void field_100; + struc_298 field_110[31]; + tree_pair_int32_t_int32_t field_3F8; +} struc_288; + +typedef struct struc_264 { + uint8_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; + int32_t field_10; + uint8_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + uint8_t field_28; + int32_t field_2C; + int32_t field_30; + int32_t field_34; + int32_t field_38; + uint8_t field_3C; + int32_t field_40; + int32_t field_44; + int32_t ex_data_mat; + int32_t field_4C; + uint8_t field_50; + int32_t field_54; + int64_t field_58; + int32_t field_60; + uint8_t field_64; + int32_t field_68; + int32_t field_6C; + int32_t field_70; + float_t field_74; + int16_t field_78; + int32_t field_7C; + int32_t field_80; + int32_t field_84; + int32_t field_88; + int32_t field_8C; + int32_t field_90; + int32_t field_94; + uint8_t field_98; + int32_t field_9C; + int32_t field_A0; + uint8_t field_A4; + uint8_t field_A5; + int32_t field_A8; + int32_t field_AC; + int32_t field_B0; + uint8_t eyes_adjust; + int32_t field_B8; + int32_t field_BC; + int16_t field_C0; + int32_t field_C4; + float_t field_C8; + float_t field_CC; + float_t field_D0; + int64_t field_D8; + int64_t field_E0; + int32_t field_E8; + int32_t field_EC; + int32_t field_F0; + int32_t field_F4; + int32_t field_F8; + int32_t field_FC; + int32_t field_100; + int32_t field_104; + int32_t field_108; + int32_t field_10C; + list_ptr_void field_110; + int32_t field_120; + int32_t field_124; + int32_t field_128; + int32_t field_12C; + int32_t field_130; + float_t field_134; + int32_t field_138; + int32_t field_13C; + int32_t field_140; + uint8_t field_144; + uint8_t field_145; + uint8_t field_146; + uint8_t field_147; + int32_t field_148; + int32_t field_14C; + uint8_t field_150; + int16_t field_152; + int32_t field_154; + int32_t field_158; + int32_t field_15C; + int32_t field_160; + int32_t field_164; + int32_t field_168; + int32_t field_16C; + int32_t field_170; + int32_t field_174; + int32_t field_178; + int32_t field_17C; + uint8_t field_180; + int32_t field_184; + int32_t field_188; + float_t field_18C; + uint8_t field_190; + int32_t field_194; + int32_t field_198; + int32_t field_19C; + int32_t field_1A0; + uint8_t field_1A4; + uint8_t** field_1A8; + int32_t field_1B0; + int32_t field_1B4; + int32_t field_1B8; + int32_t field_1BC; + int32_t field_1C0; + int32_t field_1C4; + uint8_t field_1C8; + uint8_t field_1C9; + uint8_t field_1CA; + int32_t field_1CC; + int32_t field_1D0; + int32_t field_1D4; +} struc_264; + +typedef struct rob_sub_action_execute rob_sub_action_execute; + +typedef struct rob_sub_action_execute_vftable { + void(*dispose)(rob_sub_action_execute*); + void(*field_8)(rob_sub_action_execute*); + void(*field_10)(rob_sub_action_execute*); + void(*field_18)(rob_sub_action_execute*, rob_chara_data*); + void(*field_20)(rob_sub_action_execute*, rob_chara_data*); +} rob_sub_action_execute_vftable; + +struct rob_sub_action_execute { + rob_sub_action_execute_vftable* vftable; + rob_sub_action_execute_type type; + int32_t field_C; +}; + +typedef struct rob_sub_action_execute_cry { + rob_sub_action_execute base; +} rob_sub_action_execute_cry; + +typedef struct rob_sub_action_execute_shake_hand { + rob_sub_action_execute base; + int64_t field_10; + uint8_t field_18; +} rob_sub_action_execute_shake_hand; + +typedef struct rob_sub_action_execute_embarrassed { + rob_sub_action_execute base; + uint8_t field_10; +} rob_sub_action_execute_embarrassed; + +typedef struct rob_sub_action_execute_angry { + rob_sub_action_execute base; +} rob_sub_action_execute_angry; + +typedef struct rob_sub_action_execute_laugh { + rob_sub_action_execute base; +} rob_sub_action_execute_laugh; + +typedef struct rob_sub_action_execute_count_num { + rob_sub_action_execute base; + int64_t field_10; + int32_t field_18; +} rob_sub_action_execute_count_num; + +typedef struct rob_sub_action_param { + rob_sub_action_param_type type; +} rob_sub_action_param; + +typedef struct rob_sub_action { + void** dispose; + rob_sub_action_execute* field_8; + rob_sub_action_execute* field_10; + rob_sub_action_param* field_18; + rob_sub_action_execute* field_20; + rob_sub_action_execute_cry cry; + rob_sub_action_execute_shake_hand shake_hand; + rob_sub_action_execute_embarrassed embarrassed; + rob_sub_action_execute_angry angry; + rob_sub_action_execute_laugh laugh; + rob_sub_action_execute_count_num count_num; +} rob_sub_action; + +typedef struct struc_389 { + float_t field_0; + float_t field_4; + float_t field_8; +} struc_389; + +typedef struct rob_partial_motion rob_partial_motion; + +typedef struct rob_partial_motion_vtbl { + void(*dispose)(rob_partial_motion*); + void(*field_8)(void*); +} rob_partial_motion_vtbl; + +struct rob_partial_motion { + rob_partial_motion_vtbl* __vftable; + int32_t field_8; + int32_t field_C; + int32_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + float_t field_24; + float_t field_28; + float_t field_2C; + struc_389* field_30; + struc_389* field_38; + int32_t field_40; + int32_t field_44; +}; + +typedef struct rob_face_motion { + rob_partial_motion base; +} rob_face_motion; + +typedef struct rob_hand_motion { + rob_partial_motion base; +} rob_hand_motion; + +typedef struct rob_mouth_motion { + rob_partial_motion base; +} rob_mouth_motion; + +typedef struct rob_eyes_motion { + rob_partial_motion base; +} rob_eyes_motion; + +typedef struct rob_eyelid_motion { + rob_partial_motion base; +} rob_eyelid_motion; + +typedef struct struc_269 { + uint8_t field_0; + float_t field_4; + float_t field_8; + vec3 field_C; + float_t field_18; + float_t field_1C; + int32_t field_20; + int32_t field_24; + float_t field_28; + int32_t field_2C; + int32_t field_30; + uint8_t field_34; + vec3 field_38; + vec3 field_44; + vec3 field_50; + float_t field_5C; + float_t field_60; + float_t field_64; + float_t field_68; + float_t field_6C; +} struc_269; + +typedef struct struc_229 { + uint8_t field_0; + uint8_t field_1; + int16_t field_2; + int16_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + uint8_t field_20; + uint8_t field_21; + uint8_t field_22; + uint8_t field_23; + vec3 field_24; + vec3 field_30; + int32_t field_3C; + int32_t field_40; +} struc_229; + +typedef struct struc_222 { + uint8_t field_0; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; +} struc_222; + +typedef struct aft_object_info { + uint16_t id; + uint16_t set_id; +} aft_object_info; + +typedef struct struc_268 { + int32_t field_0; + int32_t field_4; + struc_389 field_8; + struc_389 step; + float_t osage_phys_step; + int32_t field_24; + uint8_t field_28; + uint8_t field_29; + uint8_t field_2A; + int32_t field_2C; + int32_t field_30; + int64_t field_38; + int64_t field_40; + int64_t ex_data_mat; + int64_t field_50; + int64_t field_58; + int64_t field_60; + int64_t field_68; + int64_t field_70; + int64_t field_78; + int64_t field_80; + int64_t field_88; + int64_t field_90; + int64_t field_98; + int64_t field_A0; + int64_t field_A8; + int64_t field_B0; + int64_t field_B8; + int64_t field_C0; + int64_t field_C8; + int64_t field_D0; + int64_t field_D8; + int64_t field_E0; + int64_t field_E8; + int64_t field_F0; + int64_t field_F8; + int64_t field_100; + int64_t field_108; + int64_t field_110; + int64_t field_118; + int64_t field_120; + int64_t field_128; + int64_t field_130; + float_t field_138; + float_t field_13C; + int32_t field_140; + int32_t field_144; + int32_t field_148; + int32_t field_14C; + rob_face_motion field_150; + rob_hand_motion field_198; + rob_hand_motion field_1E0; + rob_mouth_motion field_228; + rob_eyes_motion field_270; + rob_eyelid_motion field_2B8; + aft_object_info field_300; + aft_object_info field_304; + aft_object_info field_308; + aft_object_info field_30C; + int32_t field_310; + float_t field_314; + rob_hand_motion field_318; + rob_hand_motion field_360; + aft_object_info field_3A8; + aft_object_info field_3AC; + rob_face_motion field_3B0; + rob_hand_motion field_3F8; + rob_hand_motion field_440; + rob_mouth_motion field_488; + rob_eyes_motion field_4D0; + rob_eyelid_motion field_518; + aft_object_info field_560; + aft_object_info field_564; + aft_object_info field_568; + aft_object_info field_56C; + float_t field_570; + struc_269 field_578[13]; + struc_269 field_B28[13]; + struc_269 field_10D8; + struc_269 field_1148; + struc_229 field_11B8[2]; + struc_229 field_1240[2]; + struc_222 field_12C8[2]; +} struc_268; + +typedef struct struc_228 { + int32_t field_0; + int32_t field_4; + uint32_t field_8; + int32_t field_C; +} struc_228; + +typedef struct struc_227 { + int32_t field_0; + float_t field_4; + float_t field_8; +} struc_227; + +typedef struct mothead_data { + mothead_data_type type; + int32_t frame; + void* data; +} mothead_data; + +typedef struct struc_377 { + mothead_data* field_0; + mothead_data* field_8; +} struc_377; + +typedef struct struc_226 { + uint8_t field_0[27]; +} struc_226; + +typedef struct struc_225 { + float_t field_0[27]; +} struc_225; + +typedef struct struc_224 { + int32_t field_0[27]; +} struc_224; + +typedef struct struc_306 { + int16_t field_0; + float_t field_4; + float_t field_8; + int16_t field_C; + int16_t field_E; + vec3 field_10; + vec3 field_1C; + vec3 field_28; + int32_t field_34; + int32_t field_38; + int32_t field_3C; + int32_t field_40; + int32_t field_44; + int32_t ex_data_mat; +} struc_306; + +typedef struct struc_223 { + int32_t field_0; + float_t field_4; + float_t field_8; + int16_t field_C; + struc_228 field_10; + struc_228 field_20; + struc_228 field_30; + struc_228 field_40; + int16_t field_50; + int16_t field_52; + int16_t field_54; + int32_t field_58; + int32_t field_5C; + int32_t field_60; + int32_t field_64; + int32_t field_68; + int32_t field_6C; + float_t field_70; + float_t field_74; + float_t field_78; + float_t field_7C; + float_t field_80; + uint8_t field_84; + int32_t field_88; + int32_t field_8C; + int32_t field_90; + int16_t field_94; + int32_t field_98; + int32_t field_9C; + int16_t field_A0; + int32_t field_A4; + int64_t field_A8; + struc_227 field_B0[26]; + int32_t field_1E8; + float_t field_1EC; + float_t field_1F0; + float_t field_1F4; + float_t field_1F8; + float_t field_1FC; + float_t field_200; + int32_t field_204; + int32_t field_208; + int32_t field_20C; + int64_t field_210; + float_t field_218; + float_t field_21C; + int16_t field_220; + list_ptr_void field_228; + int16_t field_238; + int32_t field_23C; + int32_t field_240; + int16_t field_244; + int64_t field_248; + int64_t field_250; + float_t field_258; + int32_t field_25C; + int64_t field_260; + int64_t field_268; + int32_t field_270; + int16_t field_274; + int16_t field_276; + int32_t field_278; + int32_t field_27C; + int32_t field_280; + int16_t field_284; + int64_t field_288; + int32_t field_290; + int32_t field_294; + int32_t field_298; + float_t field_29C; + uint8_t field_2A0; + float_t field_2A4; + float_t coli; + float_t field_2AC; + int64_t field_2B0; + int16_t rotation_y; + int32_t field_2BC; + float_t field_2C0; + float_t field_2C4; + int32_t field_2C8; + int32_t field_2CC; + int64_t field_2D0; + int64_t field_2D8; + int64_t field_2E0; + int16_t field_2E8; + int32_t field_2EC; + int32_t field_2F0; + int32_t field_2F4; + int32_t field_2F8; + int32_t field_2FC; + uint8_t field_300; + int32_t field_304; + int32_t field_308; + float_t field_30C; + int32_t field_310; + int16_t field_314; + float_t field_318; + float_t field_31C; + float_t field_320; + float_t field_324; + float_t field_328; + int32_t field_32C; + struc_377 field_330; + int32_t field_340; + int32_t field_344; + int32_t field_348; + float_t field_34C; + vec3 field_350; + struc_226 field_35C[3]; + struc_225 field_3B0[3]; + struc_224 field_4F4[3]; + int64_t field_638; + float_t field_640; + float_t field_644; + uint8_t field_648; + int32_t field_64C; + float_t field_650; + float_t field_654; + float_t field_658; + int32_t field_65C; + float_t field_660; + float_t field_664; + uint8_t field_668; + struc_306 field_66C[4]; + int64_t* field_7A0; + int32_t field_7A8; +} struc_223; + +typedef struct struc_399 { + int16_t field_0; + int16_t field_2; + int16_t field_4; + int16_t field_6; + int32_t field_8; + int32_t field_C; + int32_t field_10; + int32_t field_14; + vec3 field_18; + vec3 field_24; + int32_t field_30; + int32_t field_34; + int32_t field_38; + int32_t field_3C; + int32_t field_40; + int32_t field_44; + vec3 ex_data_mat; + vec3 field_54; + int32_t field_60; + int32_t field_64; + int32_t field_68; + mat4u field_6C; +} struc_399; + +typedef struct struc_220 { + float_t scale; + uint8_t field_4; + float_t field_8; + vec3 field_C; + float_t field_18; + float_t field_1C; + float_t field_20; + uint8_t field_24; + uint8_t field_25; + uint8_t field_26; + uint8_t field_27; + vec3 trans; + mat4u mat; + vec4u field_74; +} struc_220; + +typedef struct struc_195 { + vec3 rotation; + vec3 trans; + float_t scale; + float_t field_1C; + float_t field_20; + float_t field_24; +} struc_195; + +typedef struct struc_210 { + vec2 field_0; + float_t scale; +} struc_210; + +typedef struct struc_215 { + int64_t field_0; + float_t field_8; +} struc_215; + +vector(struc_215) + +typedef struct struc_267 { + float_t field_0; + int16_t field_4; + float_t field_8; + int16_t field_C; +} struc_267; + +typedef struct struc_209 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; + int32_t field_10; + int32_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + int32_t field_28; + int32_t field_2C; + int32_t field_30; + int32_t field_34; + int32_t field_38; + int32_t field_3C; + int32_t field_40; + int32_t field_44; + int32_t ex_data_mat; + int32_t field_4C; + int32_t field_50; + int32_t field_54; + int32_t field_58; + int32_t field_5C; + int32_t field_60; + float_t field_64; + int32_t field_68; + int32_t field_6C; + int32_t field_70; + int32_t field_74; + mat4u field_78[27]; + mat4u field_738[27]; + struc_195 field_DF8[27]; + struc_195 field_1230[27]; + struc_195 field_1668[27]; + struc_210 field_1AA0[27]; + float_t field_1BE4[27]; + vector_struc_215 field_1C50; + int64_t field_1C68; + int64_t field_1C70; + int64_t field_1C78; + int64_t field_1C80; + int32_t field_1C88[27]; + int32_t field_1CF4[27]; + int32_t field_1D60[27]; + int32_t field_1DCC; + int32_t field_1DD0; + int32_t field_1DD4; + int32_t field_1DD8; + int32_t field_1DDC; + int32_t field_1DE0; + int32_t field_1DE4; + int32_t field_1DE8; + int32_t field_1DEC; + int32_t field_1DF0; + int32_t field_1DF4; + int32_t field_1DF8; + int32_t field_1DFC; + int32_t field_1E00; + int32_t field_1E04; + int32_t field_1E08; + int32_t field_1E0C; + int32_t field_1E10; + int32_t field_1E14; + int32_t field_1E18; + int32_t field_1E1C; + int32_t field_1E20; + int32_t field_1E24; + int32_t field_1E28; + int32_t field_1E2C; + int32_t field_1E30; + int32_t field_1E34; + int32_t field_1E38; + int32_t field_1E3C; + int32_t field_1E40; + int32_t field_1E44; + int32_t field_1E48; + int32_t field_1E4C; + int32_t field_1E50; + int32_t field_1E54; + int32_t field_1E58; + int32_t field_1E5C; + int32_t field_1E60; + int32_t field_1E64; + int32_t field_1E68; + int32_t field_1E6C; + int32_t field_1E70; + int32_t field_1E74; + int32_t field_1E78; + int32_t field_1E7C; + int32_t field_1E80; + int32_t field_1E84; + int32_t field_1E88; + int32_t field_1E8C; + int32_t field_1E90; + int32_t field_1E94; + int32_t field_1E98; + int32_t field_1E9C; + int32_t field_1EA0; + int32_t field_1EA4; + int32_t field_1EA8; + int32_t field_1EAC; + int32_t field_1EB0; + struc_267 field_1EB4[4]; + int32_t field_1EF4; + int32_t field_1EF8; + int32_t field_1EFC; + int32_t field_1F00; + uint8_t field_1F04; + int32_t field_1F08; + int32_t field_1F0C; + int32_t field_1F10; + int32_t field_1F14; + int32_t field_1F18; + int32_t field_1F1C; + int32_t field_1F20; + uint8_t field_1F24; + uint8_t field_1F25; + uint8_t field_1F26; +} struc_209; + +typedef struct struc_263 { + bool field_0; + uint8_t field_1; + uint8_t field_2; + uint8_t field_3; + int32_t field_4; + struc_264 field_8; + rob_sub_action rob_sub_action; + struc_268 field_290; + struc_223 field_1588; + struc_399 field_1D38; + struc_220 field_1DE4; + struc_209 field_1E68; + float_t field_3D90; + int32_t field_3D94; + int16_t field_3D98; + int16_t field_3D9A; + uint8_t field_3D9C; + uint8_t field_3D9D; + int32_t field_3DA0; + uint8_t field_3DA4; + int64_t field_3DA8; + int64_t field_3DB0; + int32_t field_3DB8; + int32_t field_3DBC; + int32_t field_3DC0; + int32_t field_3DC4; + int32_t field_3DC8; + int32_t field_3DCC; + int32_t field_3DD0; + float_t field_3DD4; + int32_t field_3DD8; + float_t field_3DDC; + uint8_t field_3DE0; +} struc_263; + +typedef struct struc_242 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; + int32_t field_10; + int32_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + int32_t field_28; +} struc_242; + +typedef struct eyes_adjust { + bool xrot_adjust; + eyes_base_adjust_type base_adjust; + float_t neg; + float_t pos; +} eyes_adjust; + +typedef struct rob_chara_pv_data { + int32_t index; + uint8_t field_4; + uint8_t field_5; + uint8_t field_6; + vec3 field_8; + int16_t field_14; + int16_t field_16; + struc_242 field_18; + struc_242 field_44; + int32_t field_70; + int32_t field_74; + int32_t field_78; + int32_t field_7C; + int32_t field_80; + int32_t field_84; + int32_t field_88; + int32_t field_8C; + int32_t field_90; + int32_t field_94; + int32_t field_98; + int32_t field_9C; + uint8_t field_A0; + int32_t field_A4[4]; + eyes_adjust eyes_adjust; +} rob_chara_pv_data; + +typedef struct touch_area touch_area; + +typedef struct touch_area_vftable { + void(*dispose)(touch_area*); + void(*field_8)(touch_area*); + void(*field_10)(touch_area*); + void(*field_18)(touch_area*); + void(*field_20)(touch_area*); + void(*field_28)(touch_area*); + void(*field_30)(touch_area*); +} touch_area_vftable; + +struct touch_area { + touch_area_vftable* vftable; + int32_t field_8; + int32_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + int32_t field_24; +}; + +typedef struct rob_touch_area { + touch_area area; + int64_t field_28; + uint8_t field_30[3]; + int16_t field_34; +} rob_touch_area; + +vector(rob_touch_area) + +typedef struct rob_touch { + void** dispose; + uint8_t field_8; + vector_rob_touch_area area; +} rob_touch; + +typedef struct struc_307 { + int64_t field_0; + int32_t field_8; + int32_t field_C; + int64_t field_10; + int16_t field_18; + int16_t field_1A; + int16_t field_1C; + int16_t field_1E; + int64_t field_20; + rob_chara_data_bone_data* field_28; +} struc_307; + +typedef struct struc_218 { + vec3 bone_offset; + float_t scale; + int32_t bone_index; + int32_t field_14; +} struc_218; + +typedef struct struc_344 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; +} struc_344; + +typedef struct chara_init_data { + int32_t field_0; + int32_t object_set; + aft_bone_database_skeleton_type skeleton_type; + int32_t field_C; + int32_t field_10; + int32_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + int32_t field_28; + int32_t field_2C; + int32_t field_30; + int32_t field_34; + int32_t field_38; + int32_t field_3C; + int32_t field_40; + int32_t field_44; + int32_t ex_data_mat; + int32_t field_4C; + int32_t field_50; + int32_t field_54; + int32_t field_58; + int32_t field_5C; + int32_t field_60; + int32_t field_64; + int32_t field_68; + int32_t field_6C; + int32_t field_70; + int32_t field_74; + int32_t field_78; + int32_t field_7C; + int32_t field_80; + int32_t field_84; + int32_t field_88; + int32_t field_8C; + int32_t field_90; + int32_t field_94; + int32_t field_98; + int32_t field_9C; + int32_t field_A0; + int32_t field_A4; + int32_t field_A8; + int32_t field_AC; + int32_t field_B0; + int32_t eyes_adjust; + int32_t field_B8; + int32_t field_BC; + int32_t field_C0; + int32_t field_C4; + int32_t field_C8; + int32_t field_CC; + int32_t field_D0; + int32_t field_D4; + int32_t field_D8; + int32_t field_DC; + int32_t field_E0; + int32_t field_E4; + int32_t field_E8; + int32_t field_EC; + int32_t field_F0; + int32_t field_F4; + int32_t field_F8; + int32_t field_FC; + int32_t field_100; + int32_t field_104; + int32_t field_108; + int32_t field_10C; + int32_t field_110; + int32_t field_114; + int32_t field_118; + int32_t field_11C; + int32_t field_120; + int32_t field_124; + int32_t field_128; + int32_t field_12C; + int32_t field_130; + int32_t field_134; + int32_t field_138; + int32_t field_13C; + int32_t field_140; + int32_t field_144; + int32_t field_148; + int32_t field_14C; + int32_t field_150; + int32_t field_154; + int32_t field_158; + int32_t field_15C; + int32_t field_160; + int32_t field_164; + int32_t field_168; + int32_t field_16C; + int32_t field_170; + int32_t field_174; + int32_t field_178; + int32_t field_17C; + int32_t field_180; + int32_t field_184; + int32_t field_188; + int32_t field_18C; + int32_t field_190; + int32_t field_194; + int32_t field_198; + int32_t field_19C; + int32_t field_1A0; + int32_t field_1A4; + int32_t field_1A8; + int32_t field_1AC; + int32_t field_1B0; + int32_t field_1B4; + int32_t field_1B8; + int32_t field_1BC; + int32_t field_1C0; + int32_t field_1C4; + int32_t field_1C8; + int32_t field_1CC; + int32_t field_1D0; + int32_t field_1D4; + int32_t field_1D8; + int32_t field_1DC; + int32_t field_1E0; + int32_t field_1E4; + int32_t field_1E8; + int32_t field_1EC; + int32_t field_1F0; + int32_t field_1F4; + int32_t field_1F8; + int32_t field_1FC; + int32_t field_200; + int32_t field_204; + int32_t field_208; + int32_t field_20C; + int32_t field_210; + int32_t field_214; + int32_t field_218; + int32_t field_21C; + int32_t field_220; + int32_t field_224; + int32_t field_228; + int32_t field_22C; + int32_t field_230; + int32_t field_234; + int32_t field_238; + int32_t field_23C; + int32_t field_240; + int32_t field_244; + int32_t field_248; + int32_t field_24C; + int32_t field_250; + int32_t field_254; + int32_t field_258; + int32_t field_25C; + int32_t field_260; + int32_t field_264; + int32_t field_268; + int32_t field_26C; + int32_t field_270; + int32_t field_274; + int32_t field_278; + int32_t field_27C; + int32_t field_280; + int32_t field_284; + int32_t field_288; + int32_t field_28C; + int32_t field_290; + int32_t field_294; + int32_t field_298; + int32_t field_29C; + int32_t field_2A0; + int32_t field_2A4; + int32_t coli; + int32_t field_2AC; + int32_t field_2B0; + int32_t field_2B4; + int32_t field_2B8; + int32_t field_2BC; + int32_t field_2C0; + int32_t field_2C4; + int32_t field_2C8; + int32_t field_2CC; + int32_t field_2D0; + int32_t field_2D4; + int32_t field_2D8; + int32_t field_2DC; + int32_t field_2E0; + int32_t field_2E4; + int32_t field_2E8; + int32_t field_2EC; + int32_t field_2F0; + int32_t field_2F4; + int32_t field_2F8; + int32_t field_2FC; + int32_t field_300; + int32_t field_304; + int32_t field_308; + int32_t field_30C; + int32_t field_310; + int32_t field_314; + int32_t field_318; + int32_t field_31C; + int32_t field_320; + int32_t field_324; + int32_t field_328; + int32_t field_32C; + int32_t field_330; + int32_t field_334; + int32_t field_338; + int32_t field_33C; + int32_t field_340; + int32_t field_344; + int32_t field_348; + int32_t field_34C; + int32_t field_350; + int32_t field_354; + int32_t field_358; + int32_t field_35C; + int32_t field_360; + int32_t field_364; + int32_t field_368; + int32_t field_36C; + int32_t field_370; + int32_t field_374; + int32_t field_378; + int32_t field_37C; + int32_t field_380; + int32_t field_384; + int32_t field_388; + int32_t field_38C; + int32_t field_390; + int32_t field_394; + int32_t field_398; + int32_t field_39C; + int32_t field_3A0; + int32_t field_3A4; + int32_t field_3A8; + int32_t field_3AC; + int32_t field_3B0; + int32_t field_3B4; + int32_t field_3B8; + int32_t field_3BC; + int32_t field_3C0; + int32_t field_3C4; + int32_t field_3C8; + int32_t field_3CC; + int32_t field_3D0; + int32_t field_3D4; + int32_t field_3D8; + int32_t field_3DC; + int32_t field_3E0; + int32_t field_3E4; + int32_t field_3E8; + int32_t field_3EC; + int32_t field_3F0; + int32_t field_3F4; + int32_t field_3F8; + int32_t field_3FC; + int32_t field_400; + int32_t field_404; + int32_t field_408; + int32_t field_40C; + int32_t field_410; + int32_t field_414; + int32_t field_418; + int32_t field_41C; + int32_t field_420; + int32_t field_424; + int32_t field_428; + int32_t field_42C; + int32_t field_430; + int32_t field_434; + int32_t field_438; + int32_t field_43C; + int32_t field_440; + int32_t field_444; + int32_t field_448; + int32_t field_44C; + int32_t field_450; + int32_t field_454; + int32_t field_458; + int32_t field_45C; + int32_t field_460; + int32_t field_464; + int32_t field_468; + int32_t field_46C; + int32_t field_470; + int32_t field_474; + int32_t field_478; + int32_t field_47C; + int32_t field_480; + int32_t field_484; + int32_t field_488; + int32_t field_48C; + int32_t field_490; + int32_t field_494; + int32_t field_498; + int32_t field_49C; + int32_t field_4A0; + int32_t field_4A4; + int32_t field_4A8; + int32_t field_4AC; + int32_t field_4B0; + int32_t field_4B4; + int32_t field_4B8; + int32_t field_4BC; + int32_t field_4C0; + int32_t field_4C4; + int32_t field_4C8; + int32_t field_4CC; + int32_t field_4D0; + int32_t field_4D4; + int32_t field_4D8; + int32_t field_4DC; + int32_t field_4E0; + int32_t field_4E4; + int32_t field_4E8; + int32_t field_4EC; + int32_t field_4F0; + int32_t field_4F4; + int32_t field_4F8; + int32_t field_4FC; + int32_t field_500; + int32_t field_504; + int32_t field_508; + int32_t field_50C; + int32_t field_510; + int32_t field_514; + int32_t field_518; + int32_t field_51C; + int32_t field_520; + int32_t field_524; + int32_t field_528; + int32_t field_52C; + int32_t field_530; + int32_t field_534; + int32_t field_538; + int32_t field_53C; + int32_t field_540; + int32_t field_544; + int32_t field_548; + int32_t field_54C; + int32_t field_550; + int32_t field_554; + int32_t field_558; + int32_t field_55C; + int32_t field_560; + int32_t field_564; + int32_t field_568; + int32_t field_56C; + int32_t field_570; + int32_t field_574; + int32_t field_578; + int32_t field_57C; + int32_t field_580; + int32_t field_584; + int32_t field_588; + int32_t field_58C; + int32_t field_590; + int32_t field_594; + int32_t field_598; + int32_t field_59C; + int32_t field_5A0; + int32_t field_5A4; + int32_t field_5A8; + int32_t field_5AC; + int32_t field_5B0; + int32_t field_5B4; + int32_t field_5B8; + int32_t field_5BC; + int32_t field_5C0; + int32_t field_5C4; + int32_t field_5C8; + int32_t field_5CC; + int32_t field_5D0; + int32_t field_5D4; + int32_t field_5D8; + int32_t field_5DC; + int32_t field_5E0; + int32_t field_5E4; + int32_t field_5E8; + int32_t field_5EC; + int32_t field_5F0; + int32_t field_5F4; + int32_t field_5F8; + int32_t field_5FC; + int32_t field_600; + int32_t field_604; + int32_t field_608; + int32_t field_60C; + int32_t field_610; + int32_t field_614; + int32_t field_618; + int32_t field_61C; + int32_t field_620; + int32_t field_624; + int32_t field_628; + int32_t field_62C; + int32_t field_630; + int32_t field_634; + int32_t field_638; + int32_t field_63C; + int32_t field_640; + int32_t field_644; + int32_t field_648; + int32_t field_64C; + int32_t field_650; + int32_t field_654; + int32_t field_658; + int32_t field_65C; + int32_t field_660; + int32_t field_664; + int32_t field_668; + int32_t field_66C; + int32_t field_670; + int32_t field_674; + int32_t field_678; + int32_t field_67C; + int32_t field_680; + int32_t field_684; + int32_t field_688; + int32_t field_68C; + int32_t field_690; + int32_t field_694; + int32_t field_698; + int32_t field_69C; + int32_t field_6A0; + int32_t field_6A4; + int32_t field_6A8; + int32_t field_6AC; + int32_t field_6B0; + int32_t field_6B4; + int32_t field_6B8; + int32_t field_6BC; + int32_t field_6C0; + int32_t field_6C4; + int32_t field_6C8; + int32_t field_6CC; + int32_t field_6D0; + int32_t field_6D4; + int32_t field_6D8; + int32_t field_6DC; + int32_t field_6E0; + int32_t field_6E4; + int32_t field_6E8; + int32_t field_6EC; + int32_t field_6F0; + int32_t field_6F4; + int32_t field_6F8; + int32_t field_6FC; + int32_t field_700; + int32_t field_704; + int32_t field_708; + int32_t field_70C; + int32_t field_710; + int32_t field_714; + int32_t field_718; + int32_t field_71C; + int32_t field_720; + int32_t field_724; + int32_t field_728; + int32_t field_72C; + int32_t field_730; + int32_t field_734; + int32_t field_738; + int32_t field_73C; + int32_t field_740; + int32_t field_744; + int32_t field_748; + int32_t field_74C; + int32_t field_750; + int32_t field_754; + int32_t field_758; + int32_t field_75C; + int32_t field_760; + int32_t field_764; + int32_t field_768; + int32_t field_76C; + int32_t field_770; + int32_t field_774; + int32_t field_778; + int32_t field_77C; + int32_t field_780; + int32_t field_784; + int32_t field_788; + int32_t field_78C; + int32_t field_790; + int32_t field_794; + int32_t field_798; + int32_t field_79C; + int32_t field_7A0; + int32_t field_7A4; + int32_t field_7A8; + int32_t field_7AC; + int32_t field_7B0; + int32_t field_7B4; + int32_t field_7B8; + int32_t field_7BC; + int32_t field_7C0; + int32_t field_7C4; + int32_t field_7C8; + int32_t field_7CC; + int32_t field_7D0; + int32_t field_7D4; + int32_t field_7D8; + int32_t field_7DC; + int32_t field_7E0; + int16_t base_face_object_id; + int16_t base_face_object_set; + int32_t field_7E8; + int32_t field_7EC; + int32_t field_7F0; + int32_t field_7F4; + int32_t field_7F8; + int32_t field_7FC; + int32_t field_800; + int32_t field_804; + int32_t field_808; + int32_t field_80C; + int32_t field_810; + int32_t field_814; + int32_t field_818; + int32_t motion_set; + int32_t field_820; + int32_t field_824; + struc_218* field_828; + struc_218* field_830; + uint8_t*** field_838; + int32_t field_840; + int32_t field_844; + struc_344* field_848; + aft_object_info* head_objects; + void* field_858; + void* field_860; + aft_object_info* face_objects; +} chara_init_data; + +typedef struct rob_detail { + rob_chara_data* field_8; + struc_263* field_10; +} rob_detail; + +struct rob_chara_data { + uint8_t chara_id; + uint8_t field_1; + uint8_t field_2; + uint8_t field_3; + int32_t field_4; + int16_t field_8; + int16_t field_A; + uint8_t field_C; + uint8_t field_D; + chara_index chara_index; + int32_t module_index; + int32_t field_18; + float_t field_1C; + struc_307* field_20; + rob_chara_data_bone_data* bone_data; + rob_chara_data_item_equip* item_equip; + struc_288 field_38; + struc_263 field_440; + struc_263 field_4228; + chara_init_data* chara_init_data; + rob_detail* rob_detail; + rob_chara_pv_data pv_data; + int32_t field_80E4; + rob_touch rob_touch; +}; + +typedef struct struc_313 { + vector_uint32_t bitfield; + size_t motion_bone_count; +} struc_313; + +typedef struct mot { + uint16_t key_set_count; + uint16_t frame_count; + uint16_t field_4; + uint16_t field_6; + mot_key_set* key_sets; +} mot; + +typedef struct struc_369 { + int32_t field_0; + float_t field_4; +} struc_369; + +typedef struct mot_key_set_file { + uint16_t info; + uint16_t frame_count; +} mot_key_set_file; + +typedef struct mot_data { + mot_key_set_file* data_file; + uint16_t* key_set_types; + void* key_sets; + uint16_t* bone_info; +} mot_data; + +typedef struct mot_parent { + bool key_sets_ready; + size_t key_set_count; + vector_mot_key_set key_set; + mot mot; + vector_float_t key_set_data; + mot_data* mot_data; + aft_bone_database_skeleton_type skeleton_type; + int32_t skeleton_select; + int32_t motion_id; + float_t frame; + struc_369 field_68; +} mot_parent; + +typedef struct bone_data { + aft_bone_database_bone_type type; + int32_t has_parent; + motion_bone_index motion_bone_index; + int32_t mirror; + int32_t parent; + int32_t flags; + int32_t key_set_offset; + int32_t key_set_count; + float_t frame; + vec3 base_translation[2]; + vec3 rotation; + vec3 ik_target; + vec3 trans; + mat4u rot_mat[3]; + vec3 trans_dup[2]; + mat4u rot_mat_dup[6]; + mat4* pole_target_mat; + mat4* parent_mat; + bone_node* node; + float_t ik_segment_length[2]; + float_t ik_2nd_segment_length[2]; + float_t field_2E0; + float_t eyes_xrot_adjust_neg; + float_t eyes_xrot_adjust_pos; +} bone_data; + +vector(bone_data) + +typedef struct motion_blend motion_blend; + +typedef struct motion_blend_vtbl { + void(*dispose)(motion_blend*); + void(*field_8)(motion_blend*); + void(*field_10)(motion_blend*); + void(*field_18)(motion_blend*, uint8_t*); + void(*field_20)(motion_blend*, vector_bone_data*, vector_bone_data*); + void(*field_28)(motion_blend*, bone_data*, bone_data*); + bool(*field_30)(motion_blend*); +} motion_blend_vtbl; + +struct motion_blend { + motion_blend_vtbl* __vftable; + bool field_8; + bool field_9; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t blend; +}; + +typedef struct motion_blend_cross { + motion_blend base; + bool field_20; + bool field_21; + mat4u field_24; + mat4u field_64; + mat4u field_A4; + mat4u field_E4; +} motion_blend_cross; + +typedef struct motion_blend_freeze { + motion_blend base; + uint8_t field_20; + uint8_t field_21; + int32_t field_24; + float_t field_28; + float_t field_2C; + int32_t field_30; + mat4u field_34; + mat4u field_74; + mat4u eyes_adjust; + mat4u field_F4; +} motion_blend_freeze; + +typedef struct motion_blend_combine { + motion_blend_cross base; +} motion_blend_combine; + +typedef struct struc_400 { + char field_0; + char field_1; + char field_2; + char field_3; + char field_4; + float_t field_8; + float_t field_C; + float_t field_10; +} struc_400; + +typedef struct struc_240 { + bool(*bone_check_func)(motion_bone_index bone_index); + struc_313 field_8; + size_t motion_bone_count; +} struc_240; + +typedef struct struc_346 { + float_t frame; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + int32_t field_18; + int32_t field_1C; + float_t field_20; + float_t field_24; + uint8_t field_28; + int32_t field_2C; +} struc_346; + +typedef struct mot_blend { + struc_240 field_0; + uint8_t field_30; + mot_parent field_38; + struc_346 field_A8; + int32_t field_D8; + uint8_t field_DC; + int32_t field_E0; + int32_t field_E4; + int64_t field_E8; + int64_t field_F0; + motion_blend field_F8; +} mot_blend; + +typedef struct struc_241 { + float_t field_0; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + float_t field_24; + float_t field_28; + float_t field_2C; + float_t field_30; + float_t field_34; + float_t field_38; + float_t field_3C; + float_t field_40; +} struc_241; + +typedef struct struc_243 { + int32_t field_0; + int32_t field_4; + int32_t field_8; + int32_t field_C; + int32_t field_10; + int32_t field_14; + int32_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; +} struc_243; + +typedef struct struc_258 { + vector_bone_data* field_0; + mat4u field_8; + struc_241 ex_data_mat; + uint8_t field_8C; + uint8_t field_8D; + uint8_t field_8E; + uint8_t field_8F; + uint8_t field_90; + uint8_t field_91; + float_t field_94; + float_t field_98; + float_t field_9C; + float_t field_A0; + float_t field_A4; + int32_t field_A8; + int32_t field_AC; + float_t field_B0; + int32_t eyes_adjust; + int32_t field_B8; + int32_t field_BC; + vec3 field_C0; + mat4u field_CC; + mat4u field_10C; + uint8_t field_14C; + float_t field_150; + float_t field_154; + float_t field_158; + struc_243 field_15C; + int32_t field_184; + int32_t field_188; + int32_t field_18C; + int32_t field_190; + uint8_t field_194; + uint8_t field_195; + int32_t field_198; + int32_t field_19C; + int32_t field_1A0; + int32_t field_1A4; + int32_t field_1A8; + int32_t field_1AC; + int32_t field_1B0; + int32_t field_1B4; + int32_t field_1B8; + vec2 field_1BC; + uint8_t field_1C4; + int32_t field_1C8; + int32_t field_1CC; +} struc_258; + +typedef struct struc_312 { + struc_242 field_0; + struc_242 field_2C; + uint8_t field_58; + uint8_t field_59; + int32_t field_5C; + int32_t field_60; + int32_t field_64; + int32_t field_68; + int32_t field_6C; + int32_t field_70; + int32_t field_74; + int32_t field_78; + int32_t field_7C; + int32_t field_80; + int32_t field_84; + int32_t field_88; + float_t field_8C; + int32_t field_90; + int32_t field_94; + float_t field_98; + int32_t field_9C; +} struc_312; + +typedef struct bone_data_parent { + rob_chara_data_bone_data* rob_bone_data; + bool field_8; + bool field_9; + size_t motion_bone_count; + size_t ik_bone_count; + size_t chain_pos; + vector_bone_data bones; + vector_uint16_t bone_indices; + vec3 global_trans; + vec3 global_rotation; + uint32_t bone_key_set_count; + uint32_t global_key_set_count; + float_t field_78; + float_t rotation_y; +} bone_data_parent; + +typedef struct struc_370 { + struc_346 field_0; + int32_t field_30; + bool field_34; + float_t field_38; + float_t* field_40; + float_t* ex_data_mat; +} struc_370; + +typedef struct struc_308 { + int32_t field_0; + int32_t field_4; + uint8_t field_8; + mat4u mat; + mat4u field_4C; + bool field_8C; + vec3 field_90; + vec3 field_9C; + vec3 field_A8; + float_t eyes_adjust; + float_t field_B8; + uint8_t field_BC; + uint8_t field_BD; + float_t field_C0; + float_t field_C4; + vec3 field_C8; +} struc_308; + +typedef struct motion_blend_mot { + struc_240 field_0; + motion_blend_cross cross; + motion_blend_freeze freeze; + motion_blend_combine combine; + bone_data_parent bone_data; + mot_parent mot_data; + struc_370 field_4A8; + struc_308 field_4F8; + int32_t field_5CC; + motion_blend* field_5D0; +} motion_blend_mot; + +vector_ptr(motion_blend_mot) +list_ptr(motion_blend_mot) +list(size_t) + +typedef struct rob_chara_data_bone_data_ik_scale { + float_t ratio0; + float_t ratio1; + float_t ratio2; + float_t ratio3; +} rob_chara_data_bone_data_ik_scale; + +struct rob_chara_data_bone_data { + uint8_t field_0; + uint8_t field_1; + size_t object_bone_count; + size_t total_bone_count; + size_t motion_bone_count; + size_t ik_bone_count; + size_t chain_pos; + vector_mat4 mats; + vector_mat4 mats2; + vector_bone_node nodes; + aft_bone_database_skeleton_type base_skeleton_type; + aft_bone_database_skeleton_type skeleton_type; + vector_ptr_motion_blend_mot motions; + list_size_t motion_indices; + list_size_t motion_loaded_indices; + list_ptr_motion_blend_mot motion_loaded; + mot_blend face; + mot_blend hand_l; + mot_blend hand_r; + mot_blend mouth; + mot_blend eye; + mot_blend eyelid; + uint8_t field_758; + rob_chara_data_bone_data_ik_scale ik_scale; + vec3 field_76C; + vec3 field_778; + int32_t field_784; + struc_258 field_788; + struc_312 field_958; +}; + +typedef struct struc_373 { + int32_t motion_id; + float_t frame; + float_t frame_count; + uint8_t field_C; + int32_t field_10; + float_t blend; +} struc_373; + +vector(struc_373) + +typedef struct aft_obj_skin_block_node { + char* parent_name; + vec3 position; + vec3 rotation; + vec3 scale; +} aft_obj_skin_block_node; + +typedef struct aft_obj_skin_block_osage_node { + uint32_t name_index; + float_t length; + vec3 rotation; +} aft_obj_skin_block_osage_node; + +typedef struct aft_obj_skin_block_osage { + aft_obj_skin_block_node node; + int32_t start_index; + int32_t count; + int32_t external_name_index; + int32_t name_index; + aft_obj_skin_block_osage_node* nodes; + int32_t ex_data_mat; + int32_t field_4C; + int32_t field_50; + int32_t field_54; +} aft_obj_skin_block_osage; + +typedef struct aft_obj_skin_block_expression { + aft_obj_skin_block_node node; + char* name; + uint32_t expression_count; + char* expressions[9]; +} aft_obj_skin_block_expression; + +typedef struct struc_231 { + uint8_t* bone_name; + float_t weight; + uint32_t matrix_index; + uint32_t field_10; + int32_t field_14; +} struc_231; + +typedef struct struc_230 { + vec3 field_0; + vec3 field_C; + float_t field_18; + int32_t field_1C; + int32_t field_20; + int32_t field_24; + struc_231 field_28[4]; +} struc_230; + +typedef struct struc_251 { + uint32_t field_0; + float_t field_4; + float_t field_8; + float_t field_C; + float_t field_10; + float_t field_14; + float_t field_18; + float_t field_1C; + float_t field_20; + float_t field_24; + float_t field_28; +} struc_251; + +typedef struct aft_obj_skin_block_cloth { + char* mesh_name; + char* backface_mesh_name; + uint32_t field_8; + uint32_t count; + uint32_t field_10; + int32_t field_14; + mat4u* field_18; + struc_230* field_1C; + struc_251* field_20; + uint16_t* field_24; + uint16_t* field_28; + int64_t ex_data_mat; + uint32_t field_30; + uint32_t field_54; +} aft_obj_skin_block_cloth; + +typedef struct aft_obj_skin_block_constraint_orientation { + vec3 offset; +} aft_obj_skin_block_constraint_orientation; + +typedef struct aft_obj_skin_block_constraint_up_vector { + bool active; + float_t roll; + vec3 affected_axis; + vec3 point_at; + char* name; +} aft_obj_skin_block_constraint_up_vector; + +typedef struct aft_obj_skin_block_constraint_direction { + aft_obj_skin_block_constraint_up_vector up_vector; + vec3 align_axis; + vec3 target_offset; +} aft_obj_skin_block_constraint_direction; + +typedef struct aft_obj_skin_block_constraint_attach_point { + int32_t affected_by_orientation; + int32_t affected_by_scaling; + vec3 offset; +} aft_obj_skin_block_constraint_attach_point; + +typedef struct aft_obj_skin_block_constraint_position { + aft_obj_skin_block_constraint_up_vector up_vector; + aft_obj_skin_block_constraint_attach_point constrained_object; + aft_obj_skin_block_constraint_attach_point constraining_object; +} aft_obj_skin_block_constraint_position; + +typedef struct aft_obj_skin_block_constraint_distance { + aft_obj_skin_block_constraint_up_vector up_vector; + float_t distance; + aft_obj_skin_block_constraint_attach_point constrained_object; + aft_obj_skin_block_constraint_attach_point constraining_object; +} aft_obj_skin_block_constraint_distance; + +typedef struct aft_obj_skin_block_constraint { + aft_obj_skin_block_node node; + char* type; + char* name; + int32_t coupling; + char* source_node_name; + union { + aft_obj_skin_block_constraint_orientation orientation; + aft_obj_skin_block_constraint_direction direction; + aft_obj_skin_block_constraint_position position; + aft_obj_skin_block_constraint_distance distance; + }; +} aft_obj_skin_block_constraint; + +typedef struct aft_obj_skin_block { + char* signature; + union { + aft_obj_skin_block_node node; + aft_obj_skin_block_osage osage; + aft_obj_skin_block_expression expression; + aft_obj_skin_block_cloth cloth; + aft_obj_skin_block_constraint constraint; + }; +} aft_obj_skin_block; + +typedef struct rob_chara_data_item_equip_object rob_chara_data_item_equip_object; +typedef struct ex_node_block ex_node_block; + +typedef struct ex_node_block_vtbl { + void* (*dispose)(ex_node_block*, bool dispose); + void(*field_8)(ex_node_block*); + void(*field_10)(ex_node_block*); + void(*field_18)(ex_node_block*, int64_t, int64_t); + void(*field_20)(ex_node_block*); + void(*field_28)(ex_node_block*); + void* (*field_30)(ex_node_block*); + void(*field_38)(ex_node_block*); + void(*field_40)(ex_node_block*); + void(*field_48)(ex_node_block*); + void(*field_50)(ex_node_block*); + void(*field_58)(ex_node_block*); +} ex_node_block_vtbl; + +struct ex_node_block { + ex_node_block_vtbl* __vftable; + bone_node* bone_node; + ex_node_type type; + int32_t field_14; + char* name; + bone_node* parent_bone_node; + string parent_name; + ex_node_block* parent_node; + rob_chara_data_item_equip_object* field_50; + bool field_58; + bool field_59; + bool field_5A; +}; + +typedef struct ex_null_block { + ex_node_block base; + aft_obj_skin_block_node* node_data; +} ex_null_block; + +typedef struct rob_osage_node rob_osage_node; + +typedef struct struc_419 { + bool field_0; + int32_t field_4; + rob_osage_node* field_8; + rob_osage_node* field_10; + rob_osage_node* field_18; + rob_osage_node* field_20; + rob_osage_node* field_28; + mat4u field_30; +} struc_419; + +typedef struct skin_param_hinge { + float_t ymin; + float_t ymax; + float_t zmin; + float_t zmax; +} skin_param_hinge; + +typedef struct skin_param_osage_node { + float_t coli_r; + float_t weight; + float_t inertial_cancel; + skin_param_hinge hinge; +} skin_param_osage_node; + +typedef struct rob_osage_node_data { + float_t force; + int64_t field_8; + int64_t field_10; + int64_t field_18; + struc_419 field_20; + skin_param_osage_node skp_osg_node; +} rob_osage_node_data; + +typedef struct struc_331 { + int64_t field_0; + int64_t field_8; + int64_t field_10; +} struc_331; + +vector(struc_331) + +struct rob_osage_node { + float_t length; + vec3 field_4; + vec3 field_10; + vec3 field_1C; + int32_t field_28; + int32_t field_2C; + int32_t field_30; + float_t field_34; + bone_node* field_38; + mat4u* field_40; + mat4u ex_data_mat; + float_t field_88; + float_t field_8C; + float_t field_90; + vec3 field_94; + int64_t field_A0; + int64_t field_A8; + int64_t field_B0; + int64_t field_B8; + int64_t field_C0; + int32_t field_C8; + float_t field_CC; + vec3 field_D0; + int32_t field_DC; + rob_osage_node_data* field_E0; + rob_osage_node_data field_E8; + int32_t field_194; + vector_struc_331 field_198; + int32_t field_1B0; + int32_t field_1B4; + int32_t field_1B8; + int32_t field_1BC; + int32_t field_1C0; + int32_t field_1C4; + int32_t field_1C8; + int32_t field_1CC; +}; + +vector(rob_osage_node) + +typedef struct skin_param { + int64_t field_0; + int64_t field_8; + int64_t field_10; + int64_t field_18; + int64_t field_20; + int64_t field_28; + int64_t field_30; + int64_t field_38; + int64_t field_40; + int32_t ex_data_mat; + vec4u field_4C; + int32_t field_5C; + int32_t field_60; + int32_t field_64; + int64_t field_68; +} skin_param; + +typedef struct osage_coli { + int32_t type; + float_t radius; + vec3 bone0_pos; + vec3 bone1_pos; + vec3 bone_pos_diff; + float_t bone_pos_diff_length; + float_t bone_pos_diff_length_squared; + float_t field_34; +} osage_coli; + +typedef struct rob_osage { + skin_param* field_0; + bone_node_expression_data field_8; + vector_rob_osage_node field_38; + rob_osage_node field_50; + skin_param field_220; + int32_t field_290; + int64_t field_298; + uint8_t field_2A0; + uint8_t field_2A1; + float_t field_2A4; + osage_coli coli[64]; + osage_coli coli_ring[64]; + vec3 wind_direction; + float_t field_1EB4; + int32_t field_1EB8; + int32_t field_1EBC; + mat4* field_1EC0; + mat4u field_1EC8; + float_t field_1F08; + bool field_1F0C; + bool field_1F0D; + bool field_1F0E; + bool field_1F0F; + float_t field_1F10; + float_t field_1F14; + float_t field_1F18; + float_t field_1F1C; + float_t field_1F20; + float_t field_1F24; + bool field_1F28; + int64_t field_1F30; + int64_t field_1F38; + int64_t field_1F40; + int64_t field_1F48; + int64_t field_1F50; + int64_t field_1F58; + int64_t field_1F60; + int64_t field_1F68; + int64_t field_1F70; + uint8_t field_1F78; + vec3 field_1F7C; +} rob_osage; + +typedef struct ex_osage_block { + ex_node_block base; + int64_t field_60; + rob_osage rob; + mat4* mat; + int32_t field_1FF8; + float_t field_1FFC; +} ex_osage_block; + +typedef struct ex_constraint_block { + ex_node_block base; + aft_obj_skin_block_constraint_type type; + bone_node* source_node_bone_node; + bone_node* direction_up_vector_bone_node; + aft_obj_skin_block_constraint* cns_data; + int64_t field_80; +} ex_constraint_block; + +typedef struct struc_323 { + int32_t field_0; + int64_t field_8; + int64_t field_10; + int64_t field_18; + int64_t field_20; +} struc_323; + +typedef struct ex_expression_block_stack ex_expression_block_stack; + +typedef struct ex_expression_block_stack_number { + float_t value; +}ex_expression_block_stack_number; + +typedef struct ex_expression_block_stack_variable { + float_t* value; +}ex_expression_block_stack_variable; + +typedef struct ex_expression_block_stack_variable_radian { + float_t* value; +} ex_expression_block_stack_variable_radian; + +typedef struct ex_expression_block_stack_op1 { + float_t(*func)(float_t v1); + ex_expression_block_stack* v1; +} ex_expression_block_stack_op1; + +typedef struct ex_expression_block_stack_op2 { + float_t(*func)(float_t v1, float_t v2); + ex_expression_block_stack* v1; + ex_expression_block_stack* v2; +} ex_expression_block_stack_op2; + +typedef struct ex_expression_block_stack_op3 { + float_t(*func)(float_t v1, float_t v2, float_t v3); + ex_expression_block_stack* v1; + ex_expression_block_stack* v2; + ex_expression_block_stack* v3; +} ex_expression_block_stack_op3; + +struct ex_expression_block_stack { + ex_expression_block_stack_type type; + union { + ex_expression_block_stack_number number; + ex_expression_block_stack_variable var; + ex_expression_block_stack_variable_radian var_rad; + ex_expression_block_stack_op1 op1; + ex_expression_block_stack_op2 op2; + ex_expression_block_stack_op3 op3; + }; +}; + +typedef struct ex_expression_block { + ex_node_block base; + float_t* values[9]; + ex_expression_block_stack_type types[9]; + ex_expression_block_stack* expressions[9]; + ex_expression_block_stack stack_data[384]; + aft_obj_skin_block_expression* exp_data; + bool field_3D20; + void(*field_3D28)(bone_node_expression_data*); + float_t frame; + bool init; +} ex_expression_block; + +typedef struct cloth cloth; + +typedef struct cloth_vftable { + void(*dispose)(void*); + void(*field_8)(void*); + void(*field_10)(void*); + void(*field_18)(void*); + void(*field_20)(void*); + void(*field_28)(void*, int64_t); + void(*field_30)(void*); + void(*field_38)(void*); + void(*field_40)(void*); + void(*ex_data_mat)(void*); + void(*field_50)(void*); + void(*field_58)(void*); +} cloth_vftable; + +typedef struct struc_342 { + int32_t field_0; + vec3 field_4; + int64_t field_10; + int64_t field_18; + int64_t field_20; + int64_t field_28; + int32_t field_30; + vec3 field_34; + vec3 field_40; + vec3 field_4C; + int64_t field_58; + int64_t field_60; + int64_t field_68; + int64_t field_70; + int64_t field_78; + int64_t field_80; + int64_t field_88; + int64_t field_90; + int64_t field_98; + int64_t field_A0; + int64_t field_A8; + int64_t field_B0; + int64_t field_B8; + int64_t field_C0; + int64_t field_C8; + int64_t field_D0; + int64_t field_D8; + int64_t field_E0; + int64_t field_E8; +} struc_342; + +typedef struct struc_341 { + int64_t field_0; + int64_t field_8; + int64_t field_10; +} struc_341; + +vector(struc_341) + +struct cloth { + cloth_vftable* vftable; + int32_t field_8; + int64_t field_10; + int64_t field_18; + struc_342* field_20; + int64_t field_28; + int64_t field_30; + vec3 field_38; + float_t field_44; + uint8_t ex_data_mat; + vec3 field_4C; + vector_struc_341 field_58; + skin_param* field_70; + skin_param field_78; + osage_coli coli[64]; + osage_coli coli_ring[64]; + vec3 field_1CE8; + vec3 field_1CF4; + bool field_1D00; + int64_t field_1D08; + int64_t field_1D10; + int64_t field_1D18; + int64_t field_1D20; + int64_t field_1D28; + int64_t field_1D30; + mat4u* field_1D38; +}; + +typedef struct aft_obj_bounding_sphere { + vec3 center; + float_t radius; +} aft_obj_bounding_sphere; + +typedef struct aft_obj_axis_aligned_bounding_box { + vec3 center; + vec3 size; +} aft_obj_axis_aligned_bounding_box; + +typedef struct aft_obj_sub_mesh { + uint32_t field_0; + aft_obj_bounding_sphere bounding_sphere; + uint32_t material_index; + uint8_t texcoord_indices[8]; + uint32_t bone_indices_count; + uint16_t* bone_indices; + uint32_t bones_per_vertex; + aft_obj_primitive_type primitive_type; + aft_obj_index_format index_format; + uint32_t indices_count; + uint16_t* indices; + aft_obj_sub_mesh_flags flags; + uint32_t field_4C; + int32_t field_50; + int32_t field_54; + int32_t field_58; + int32_t field_5C; + aft_obj_axis_aligned_bounding_box* axis_aligned_bounding_box; + uint16_t first_index; + uint16_t last_index; + uint32_t indices_offset; +} aft_obj_sub_mesh; + +typedef union aft_obj_mesh_attrib_offsets { + struct { + vec3* position; + vec3* normal; + vec4* tangent; + vec3* binormal; + vec2* texcoord0; + vec2* texcoord1; + vec2* texcoord2; + vec2* texcoord3; + vec4* color0; + vec4* color1; + vec4* bone_weight; + vec4* bone_index; + void* field_60; + void* field_68; + void* field_70; + void* field_78; + void* field_80; + void* field_88; + void* field_90; + void* field_98; + }; + void* ptr[20]; +} aft_obj_mesh_attrib_offsets; + +typedef struct aft_obj_mesh { + uint32_t field_0; + aft_obj_bounding_sphere bounding_sphere; + uint32_t sub_meshes_count; + aft_obj_sub_mesh* sub_meshes; + aft_obj_vertex_attrib_type attrib_type; + uint32_t vertex_size; + uint32_t vertex_count; + aft_obj_mesh_attrib_offsets attrib_offsets; + aft_obj_mesh_flags flags; + uint32_t attrib_flags; + uint32_t field_D8; + uint32_t field_DC; + uint32_t field_E0; + uint32_t field_E4; + uint32_t field_E8; + uint32_t field_EC; + char name[64]; +} aft_obj_mesh; + +typedef union aft_obj_material_shader { + char name[8]; + aft_shader_enum index; +} aft_obj_material_shader; + +typedef struct aft_obj_material_shader_flags { + uint32_t vertex_translation_type : 2; + uint32_t color_source_type : 2; + uint32_t lambert_shading : 1; + uint32_t phong_shading : 1; + uint32_t per_pixel_shading : 1; + uint32_t double_shading : 1; + uint32_t bump_map_type : 2; + uint32_t fresnel : 4; + uint32_t line_light : 4; + uint32_t recieve_shadow : 1; + uint32_t cast_shadow : 1; + uint32_t specular_quality : 1; + uint32_t aniso_direction : 3; +} aft_obj_material_shader_flags; + +typedef struct aft_obj_material_texture { + aft_obj_material_texture_sampler_flags sampler_flags; + uint32_t texture_id; + int32_t texture_flags; + char shader_name[8]; + float_t weight; + mat4u tex_coord_mat; + float_t unk[8]; +} aft_obj_material_texture; + +typedef struct aft_obj_material { + aft_obj_material_flags material_flags; + aft_obj_material_shader shader; + union { + uint32_t shader_flags; + aft_obj_material_shader_flags shader_flags_data; + }; + aft_obj_material_texture textures[8]; + int32_t blend_flags; + vec4u diffuse; + vec4u ambient; + vec4u specular; + vec4u emission; + float_t shininess; + float_t intensity; + aft_obj_bounding_sphere reserved_sphere; + char name[64]; + float_t bump_depth; + float_t unk[15]; +} aft_obj_material; + +typedef struct aft_obj_material_data { + int32_t texture_count; + aft_obj_material material; +} aft_obj_material_data; + +typedef struct aft_obj { + uint32_t field_0; + uint32_t field_4; + aft_obj_bounding_sphere bounding_sphere; + uint32_t meshes_count; + aft_obj_mesh* meshes; + uint32_t materials_count; + aft_obj_material_data* materials; + uint32_t field_38; + uint32_t field_3C; + uint32_t field_40; + uint32_t field_44; + uint32_t ex_data_mat; + uint32_t field_4C; + uint32_t field_50; + uint32_t field_54; + uint32_t field_58; + uint32_t field_5C; +} aft_obj; + +typedef struct aft_obj_mesh_vertex_buffer +{ + int32_t count; + GLuint buffers[3]; + int32_t index; + GLenum enum_data; +} aft_obj_mesh_vertex_buffer; + +typedef struct aft_obj_vertex_buffer { + int32_t meshes_count; + aft_obj_mesh_vertex_buffer* meshes; +} aft_obj_vertex_buffer; + +typedef GLuint aft_obj_mesh_index_buffer; + +typedef struct aft_obj_index_buffer { + int32_t meshes_count; + aft_obj_mesh_index_buffer* meshes; +} aft_obj_index_buffer; + +typedef struct texture_pattern_struct { + int32_t src; + int32_t dst; +} texture_pattern_struct; + +vector(texture_pattern_struct) + +typedef struct aft_obj_skin_osage_node { + int32_t name_index; + float_t length; + int32_t index; +} aft_obj_skin_osage_node; + +typedef struct aft_obj_skin_ex_data { + int32_t osage_name_count; + int32_t osage_node_count; + char** field_8; + aft_obj_skin_osage_node* osage_nodes; + char** osage_names; + aft_obj_skin_block* blocks; + int32_t field_28; + int32_t field_2C; + char** strings; + int64_t osage_sibling_infos; + int32_t field_40; + int32_t field_44; + int32_t ex_data_mat; + int32_t field_4C; + int32_t field_50; + int32_t field_54; + int32_t field_58; + int32_t field_5C; +} aft_obj_skin_ex_data; + +typedef struct aft_obj_skin { + uint32_t* bone_ids; + mat4u* bone_matrices; + char** bone_names; + aft_obj_skin_ex_data* ex_data; + uint32_t bone_count; + int32_t bone_parent_ids_offset; + int32_t field_28; + int32_t field_2C; + int32_t field_30; +} aft_obj_skin; + +typedef struct aft_obj_set_info { + int32_t id; + string name; + string object_file_name; + string texture_file_name; + string archive_file_name; +} aft_obj_set_info; + +typedef struct pair_uint32_t_obj_set_info { + uint32_t id; + aft_obj_set_info data; +} pair_uint32_t_obj_set_info; + +vector(pair_uint32_t_obj_set_info) + +typedef struct aft_obj_database { + vector_pair_uint32_t_obj_set_info field_0; + size_t field_18; + vector_pair_uint32_t_obj_set_info field_20; + bool field_38; +} aft_obj_database; + +typedef struct aft_obj_set { + uint32_t signature; + uint32_t objects_count; + uint32_t max_object_id; + aft_obj** objects; + aft_obj_skin** object_skins; + char** object_names; + uint32_t* object_ids; + uint32_t* texture_ids; + uint32_t texture_ids_count; + uint32_t field_3C; + uint32_t field_40; +} aft_obj_set; + +typedef struct aft_obj_bounding_box { + vec3 center; + vec3 size; +} aft_obj_bounding_box; + +typedef struct pair_int32_t_int32_t { + int32_t key; + int32_t value; +} pair_int32_t_int32_t; + +typedef struct texture { + int32_t init_count; + int32_t id; + texture_flags flags; + int16_t width; + int16_t height; + GLuint texture; + GLenum target; + GLenum internal_format; + int32_t max_mipmap_level; + int32_t size; +} texture; + +typedef struct struc_332 { + aft_obj_sub_mesh field_0; + int64_t field_70; + int64_t field_78; + int64_t field_80; + int64_t field_88; + int64_t field_90; + int64_t field_98; + int64_t field_A0; + int64_t field_A8; + int64_t field_B0; + int64_t field_B8; + int64_t field_C0; + int64_t field_C8; + int64_t field_D0; + int64_t field_D8; + int64_t field_E0; + int64_t field_E8; + int64_t field_F0; + int64_t field_F8; + int64_t field_100; + int64_t field_108; + int64_t field_110; + int64_t field_118; + int64_t field_120; + int64_t field_128; + int64_t field_130; + int64_t field_138; + int64_t field_140; + int64_t field_148; + int64_t field_150; + int64_t field_158; + int64_t field_160; + int64_t field_168; + int64_t field_170; + int64_t field_178; + int64_t field_180; + int64_t field_188; + int64_t field_190; + int64_t field_198; + int64_t field_1A0; + int64_t field_1A8; + int64_t field_1B0; + int64_t field_1B8; +} struc_332; + +typedef struct struc_295 { + int32_t field_0; + int32_t field_4; + int64_t field_8; + int64_t field_10; +} struc_295; + +vector(struc_295) + +typedef struct rob_cloth { + cloth base; + int64_t field_1D40; + int64_t field_1D48; + int64_t field_1D50; + rob_chara_data_item_equip_object* field_1D58; + struc_230* field_1D60; + aft_obj_skin_block_cloth* cloth_block; + float_t field_1D70; + uint8_t field_1D74; + aft_obj_mesh field_1D78[2]; + struc_332 field_1FD8[2]; + aft_obj_axis_aligned_bounding_box field_2358; + aft_obj_mesh_vertex_buffer field_2370[2]; + GLuint mesh_buffer; + int32_t field_23A4; + vector_struc_295 field_23A8; + int64_t field_23B8; +} rob_cloth; + +typedef struct ex_cloth_block { + ex_node_block base; + rob_cloth rob; + aft_obj_skin_block_cloth* cloth_block; + mat4* field_2428; + int64_t field_2430; +} ex_cloth_block; + +vector_ptr(ex_node_block) +vector_ptr(ex_null_block) +vector_ptr(ex_osage_block) +vector_ptr(ex_constraint_block) +vector_ptr(ex_expression_block) +vector_ptr(ex_cloth_block) + +typedef struct ex_data_name_bone_index { + char* name; + int32_t bone_index; +} ex_data_name_bone_index; + +vector(ex_data_name_bone_index) + +typedef struct texture_data_struct { + int32_t field_0; + vec3 field_4; + vec3 field_10; + vec3 field_1C; + vec3 field_28; +} texture_data_struct; + +struct rob_chara_data_item_equip_object { + size_t index; + mat4* mat; + aft_object_info object_info; + int32_t field_14; + vector_texture_pattern_struct field_18; + texture_data_struct texture_data; + char field_64; + bone_node_expression_data exp_data; + float_t alpha; + draw_task_flags draw_task_flags; + bool draw; + int32_t field_A4; + mat4* field_A8; + int32_t field_B0; + bone_node* bone_nodes; + vector_ptr_ex_node_block node_blocks; + vector_bone_node ex_data_bone_nodes; + vector_mat4 ex_data_matrices; + vector_mat4 field_108; + vector_ex_data_name_bone_index ex_bones; + int64_t field_138; + vector_ptr_ex_null_block null_blocks; + vector_ptr_ex_osage_block osage_blocks; + vector_ptr_ex_constraint_block constraint_blocks; + vector_ptr_ex_expression_block expression_blocks; + vector_ptr_ex_cloth_block cloth_blocks; + char field_1B8; + int64_t field_1C0; + char field_1C8; + aft_obj_skin_ex_data* skin_ex_data; + aft_obj_skin* skin; + rob_chara_data_item_equip* item_equip; +}; + +struct rob_chara_data_item_equip { + bone_node* bone_nodes; + mat4* matrices; + rob_chara_data_item_equip_object* item_equip_object; + int32_t field_18[31]; + bool item_equip_range; + int32_t first_item_equip_object; + int32_t max_item_equip_object; + int32_t field_A0; + shadow_type_enum shadow_type; + vec3 position; + int32_t eyes_adjust; + vector_texture_pattern_struct texture_pattern; + aft_object_info field_D0; + int32_t field_D4; + uint8_t field_D8; + int32_t field_DC; + vec4u texture_color_coeff; + float_t wet; + float_t field_F4; + uint8_t chara_color; + uint8_t field_F9; + mat4u mat; + mat4u field_13C[30]; + int32_t field_8BC; + int32_t field_8C0; + int32_t field_8C4; + int32_t field_8C8; + int32_t field_8CC; + int32_t field_8D0; + int32_t field_8D4; + int32_t field_8D8; + int32_t field_8DC; + int32_t field_8E0; + int32_t field_8E4; + int32_t field_8E8; + int32_t field_8EC; + int32_t field_8F0; + int32_t field_8F4; + int32_t field_8F8; + int32_t field_8FC; + int64_t field_900; + int64_t field_908; + int64_t field_910; + int64_t field_918; + int64_t field_920; + int64_t field_928; + int64_t field_930; + float_t osage_phys_step; + uint8_t field_93C; + vector_struc_373 field_940; + uint8_t field_958; + uint8_t field_959; + uint8_t field_95A; +}; + +extern void bone_data_mult_ik(bone_data* a1, int32_t a2); +extern void bone_data_mult_1(bone_data* a1, mat4* parent_mat, bone_data* a3, bool solve_ik); +extern void bone_data_mult_2(rob_chara_data_bone_data* a1, mat4* a2); +extern void rob_chara_data_bone_data_motion_load(rob_chara_data_bone_data* a1, int32_t motion_id, int32_t a3); +extern void rob_chara_data_bone_data_interpolate(rob_chara_data_bone_data* a1); +extern void rob_chara_data_bone_data_update(rob_chara_data_bone_data* a1, mat4* a2); +extern void rob_chara_data_reset(rob_chara_data* a1, rob_chara_pv_data* a2); diff --git a/src/DivaGL/dllmain.c b/src/DivaGL/dllmain.c new file mode 100644 index 00000000..413a9d11 --- /dev/null +++ b/src/DivaGL/dllmain.c @@ -0,0 +1,36 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "../KKdLib/default.h" +#include "inject.h" +#include "print.h" +#include "shader_table.h" +#include + +bool APIENTRY DllMain(HMODULE handle, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + printf_divagl("Current version - v0.1.2.0"); + printf_divagl("Attach"); + printf_divagl("Patching memory"); + inject_patches(); + break; + + case DLL_PROCESS_DETACH: + printf_divagl("Detach"); + printf_divagl("Restore memory"); + inject_restore(); + break; + } + return true; +} + +extern __declspec(dllexport) LPCWSTR GetPluginName(void) { + return L"DivaGL"; +} + +extern __declspec(dllexport) LPCWSTR GetPluginDescription(void) { + return L"DivaGL Plugin by korenkonder"; +} diff --git a/src/DivaGL/gl.c b/src/DivaGL/gl.c new file mode 100644 index 00000000..9c2bfeda --- /dev/null +++ b/src/DivaGL/gl.c @@ -0,0 +1,60 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "gl.h" + +void (FASTCALL* _glPushMatrix)(); +void (FASTCALL* _glPopMatrix)(); +void (FASTCALL* _glAlphaFunc)(GLenum func, float ref); +void (FASTCALL* _glBlendFunc)(GLenum sfactor, GLenum dfactor); +void (FASTCALL* _glDepthMask)(bool mask); +void (FASTCALL* _glTexCoordPointer)(int size, GLenum type, int stride, void* pointer); +void (FASTCALL* _glBegin)(GLenum mode); +void (FASTCALL* _glEnd)(); +void (FASTCALL* _glMaterialfv)(GLenum face, GLenum pname, float* param); +void (FASTCALL* _glVertexPointer)(int size, GLenum type, int stride, void* pointer); +int (FASTCALL* _glGetError)(); +void (FASTCALL* _glPushClientAttrib)(GLbitfield mask); +void (FASTCALL* _glPopClientAttrib)(); +void (FASTCALL* _glEnableClientState)(GLenum cap); +void (FASTCALL* _glDrawArrays)(int mode, int first, int count); +void (FASTCALL* _glBindTexture)(GLenum texture, int param); +void (FASTCALL* _glDisableClientState)(GLenum cap); +void (FASTCALL* _glColorPointer)(int size, GLenum type, int stride, void* pointer); +void (FASTCALL* _glDisable)(GLenum cap); +void (FASTCALL* _glEnable)(GLenum cap); +void (FASTCALL* _glMatrixMode)(GLenum mode); +void (FASTCALL* _glLoadIdentity)(); +void (FASTCALL* _glGetFloatv)(GLenum pname, float* params); + +void (FASTCALL* glutMainLoop)(); + +void gl_get_func_pointers() { + _glPushMatrix = *(void**)0x0000000140965CA0; + _glPopMatrix = *(void**)0x0000000140965CA8; + _glAlphaFunc = *(void**)0x0000000140965A00; + _glBlendFunc = *(void**)0x0000000140965A20; + _glDepthMask = *(void**)0x0000000140965A28; + _glTexCoordPointer = *(void**)0x0000000140965A30; + _glBegin = *(void**)0x0000000140965A70; + _glEnd = *(void**)0x0000000140965A78; + _glMaterialfv = *(void**)0x0000000140965A80; + _glVertexPointer = *(void**)0x0000000140965B00; + _glGetError = *(void**)0x0000000140965BA8; + _glPushClientAttrib = *(void**)0x0000000140965BC0; + _glPopClientAttrib = *(void**)0x0000000140965BD0; + _glEnableClientState = *(void**)0x0000000140965BE8; + _glDrawArrays = *(void**)0x0000000140965BF0; + _glBindTexture = *(void**)0x0000000140965BF8; + _glDisableClientState = *(void**)0x0000000140965C28; + _glColorPointer = *(void**)0x0000000140965C30; + _glDisable = *(void**)0x0000000140965C48; + _glEnable = *(void**)0x0000000140965C50; + _glMatrixMode = *(void**)0x0000000140965C80; + _glLoadIdentity = *(void**)0x0000000140965C88; + _glGetFloatv = *(void**)0x0000000140965C90; + + glutMainLoop(); +} diff --git a/src/DivaGL/gl.h b/src/DivaGL/gl.h new file mode 100644 index 00000000..5d7a7d87 --- /dev/null +++ b/src/DivaGL/gl.h @@ -0,0 +1,39 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../KKdLib/vec.h" +#include "../KKdLib/mat.h" +#include + +extern void (FASTCALL* _glPushMatrix)(); +extern void (FASTCALL* _glPopMatrix)(); +extern void (FASTCALL* _glAlphaFunc)(GLenum func, float_t ref); +extern void (FASTCALL* _glBlendFunc)(GLenum sfactor, GLenum dfactor); +extern void (FASTCALL* _glDepthMask)(bool mask); +extern void (FASTCALL* _glTexCoordPointer)(int32_t size, GLenum type, int32_t stride, void* pointer); +extern void (FASTCALL* _glBegin)(GLenum mode); +extern void (FASTCALL* _glEnd)(); +extern void (FASTCALL* _glMaterialfv)(GLenum face, GLenum pname, float_t* param); +extern void (FASTCALL* _glVertexPointer)(int32_t size, GLenum type, int32_t stride, void* pointer); +extern int (FASTCALL* _glGetError)(); +extern void (FASTCALL* _glPushClientAttrib)(GLbitfield mask); +extern void (FASTCALL* _glPopClientAttrib)(); +extern void (FASTCALL* _glEnableClientState)(GLenum cap); +extern void (FASTCALL* _glDrawArrays)(int32_t mode, int32_t first, int32_t count); +extern void (FASTCALL* _glBindTexture)(GLenum texture, int32_t param); +extern void (FASTCALL* _glDisableClientState)(GLenum cap); +extern void (FASTCALL* _glColorPointer)(int32_t size, GLenum type, int32_t stride, void* pointer); +extern void (FASTCALL* _glDisable)(GLenum cap); +extern void (FASTCALL* _glEnable)(GLenum cap); +extern void (FASTCALL* _glMatrixMode)(GLenum mode); +extern void (FASTCALL* _glLoadIdentity)(); +extern void (FASTCALL* _glGetFloatv)(GLenum pname, float_t* params); + +extern void (FASTCALL* glutMainLoop)(); + +extern void gl_get_func_pointers(); diff --git a/src/DivaGL/inject.c b/src/DivaGL/inject.c new file mode 100644 index 00000000..16d6b934 --- /dev/null +++ b/src/DivaGL/inject.c @@ -0,0 +1,122 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "inject.h" +#include "bone_data.h" +#include "gl.h" +#include "print.h" +#include "shader_table.h" +#include + +typedef struct patch_struct { + void* address; + size_t func_ptr; + void* orig_data; +} patch_struct; + +void* inject_data(void* address, void* data, size_t count) { + DWORD old_protect; + VirtualProtect(address, count, PAGE_EXECUTE_READWRITE, &old_protect); + void* orig_data = force_malloc(count); + memcpy(orig_data, (const void*)address, count); + memcpy(address, (const void*)data, count); + VirtualProtect(address, count, old_protect, &old_protect); + return orig_data; +} + +uint8_t inject_uint8_t(void* address, uint8_t data) { + DWORD old_protect; + VirtualProtect(address, sizeof(uint8_t), PAGE_EXECUTE_READWRITE, &old_protect); + uint8_t value = *(uint8_t*)address; + *(uint8_t*)address = data; + VirtualProtect(address, sizeof(uint8_t), old_protect, &old_protect); + return value; +} + +uint16_t inject_uint16_t(void* address, uint16_t data) { + DWORD old_protect; + VirtualProtect(address, sizeof(uint16_t), PAGE_EXECUTE_READWRITE, &old_protect); + uint16_t value = *(uint16_t*)address; + *(uint16_t*)address = data; + VirtualProtect(address, sizeof(uint16_t), old_protect, &old_protect); + return value; +} + +uint32_t inject_uint32_t(void* address, uint32_t data) { + DWORD old_protect; + VirtualProtect(address, sizeof(uint32_t), PAGE_EXECUTE_READWRITE, &old_protect); + uint32_t value = *(uint32_t*)address; + *(uint32_t*)address = data; + VirtualProtect(address, sizeof(uint32_t), old_protect, &old_protect); + return value; +} + +uint64_t inject_uint64_t(void* address, uint64_t data) { + DWORD old_protect; + VirtualProtect(address, sizeof(uint64_t), PAGE_EXECUTE_READWRITE, &old_protect); + uint64_t value = *(uint64_t*)address; + *(uint64_t*)address = data; + VirtualProtect(address, sizeof(uint64_t), old_protect, &old_protect); + return value; +} + +static patch_struct patch_data[] = { + { (void*)0x00000001405E4CE0, (uint64_t)&aft_shader_set, }, + { (void*)0x00000001405E4FC0, (uint64_t)&aft_shader_load_all_shaders, }, + { (void*)0x00000001405E4B50, (uint64_t)&aft_shader_bind, }, + { (void*)0x00000001401D3860, (uint64_t)&printf_proxy, }, + //{ (void*)0x0000000140507210, (uint64_t)&rob_chara_data_reset, }, + //{ (void*)0x00000001401EBD30, (uint64_t)&bone_data_mult_ik, }, + //{ (void*)0x00000001401EB6D0, (uint64_t)&bone_data_mult_1, }, + //{ (void*)0x000000014041DA50, (uint64_t)&bone_data_mult_2, }, + //{ (void*)0x000000014041CF50, (uint64_t)&rob_chara_data_bone_data_motion_load, }, + //{ (void*)0x0000000140418870, (uint64_t)&rob_chara_data_bone_data_interpolate, }, + //{ (void*)0x0000000140418A60, (uint64_t)&rob_chara_data_bone_data_update, }, +}; + +static uint64_t shader_bind_func_orig_data[6]; + +void inject_patches() { + char buf[12]; + buf[0] = 0x48; + buf[1] = 0xB8; + buf[10] = 0xFF; + buf[11] = 0xE0; + + for (int32_t i = 0; i < sizeof(patch_data) / sizeof(patch_struct); i++) + if (patch_data[i].func_ptr) { + free(patch_data[i].orig_data); + *(uint64_t*)&buf[2] = patch_data[i].func_ptr; + patch_data[i].orig_data = inject_data(patch_data[i].address, buf, 12); + } + + glutMainLoop = (void*)inject_uint64_t((void*)0x0000000140966008, (uint64_t)&gl_get_func_pointers); + + shader_bind_func_orig_data[0] = inject_uint64_t( + (void*)&shader_name_bind_func_table[0].bind_func, (uint64_t)&aft_shader_bind_blinn); + shader_bind_func_orig_data[1] = inject_uint64_t( + (void*)&shader_name_bind_func_table[1].bind_func, (uint64_t)&aft_shader_bind_cloth); + shader_bind_func_orig_data[2] = inject_uint64_t( + (void*)&shader_name_bind_func_table[2].bind_func, (uint64_t)&aft_shader_bind_hair); + shader_bind_func_orig_data[3] = inject_uint64_t( + (void*)&shader_name_bind_func_table[3].bind_func, (uint64_t)&aft_shader_bind_membrane); + shader_bind_func_orig_data[4] = inject_uint64_t( + (void*)&shader_name_bind_func_table[4].bind_func, (uint64_t)&aft_shader_bind_eye_ball); + shader_bind_func_orig_data[5] = inject_uint64_t( + (void*)&shader_name_bind_func_table[5].bind_func, (uint64_t)&aft_shader_bind_tone_map); +} + +void inject_restore() { + for (int32_t i = 0; i < sizeof(patch_data) / sizeof(patch_struct); i++) + if (patch_data[i].func_ptr) { + void* data = inject_data(patch_data[i].address, patch_data[i].orig_data, 12); + free(data); + } + + inject_uint64_t((void*)0x0000000140966008, (uint64_t)glutMainLoop); + + for (int32_t i = 0; i < 6; i++) + inject_uint64_t(shader_name_bind_func_table[i].bind_func, shader_bind_func_orig_data[i]); +} diff --git a/src/DivaGL/inject.h b/src/DivaGL/inject.h new file mode 100644 index 00000000..f3b16238 --- /dev/null +++ b/src/DivaGL/inject.h @@ -0,0 +1,16 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" + +extern void* inject_data(void* address, void* data, size_t count); +extern uint8_t inject_uint8_t(void* address, uint8_t data); +extern uint16_t inject_uint16_t(void* address, uint16_t data); +extern uint32_t inject_uint32_t(void* address, uint32_t data); +extern uint64_t inject_uint64_t(void* address, uint64_t data); +extern void inject_patches(); +extern void inject_restore(); diff --git a/src/DivaGL/print.c b/src/DivaGL/print.c new file mode 100644 index 00000000..db90e92a --- /dev/null +++ b/src/DivaGL/print.c @@ -0,0 +1,22 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "print.h" + +void printf_divagl(const char* fmt, ...) { + char buf[0x1000]; + va_list args; + va_start(args, fmt); + snprintf(buf, sizeof(buf), "[DivaGL] %s\n", fmt); + vprintf(buf, args); + va_end(args); +} + +void printf_proxy(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} diff --git a/src/DivaGL/print.h b/src/DivaGL/print.h new file mode 100644 index 00000000..64fc74eb --- /dev/null +++ b/src/DivaGL/print.h @@ -0,0 +1,11 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" + +extern void printf_divagl(const char* fmt, ...); +extern void printf_proxy(const char* fmt, ...); diff --git a/src/DivaGL/shader_table.c b/src/DivaGL/shader_table.c new file mode 100644 index 00000000..9ceea8ac --- /dev/null +++ b/src/DivaGL/shader_table.c @@ -0,0 +1,213 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "shader_table.h" +#include "gl.h" +#include "../KKdLib/mat.h" + +typedef struct uniform_array { + int32_t array[70]; +} uniform_array; + +extern uniform_array* uniform; + +aft_shader* shaders = (void*)0x000000014CC57C10; +aft_shader_table_struct* aft_shader_table = (void*)0x0000000140A41D20; +aft_shader_bind_func* shader_name_bind_func_table = (void*)0x0000000140A40F50; +uniform_array* uniform = (void*)0x000000014CC57AF0; +int32_t* current_vp = (void*)0x000000014CC587B0; +int32_t* current_fp = (void*)0x000000014CC587B4; + +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +typedef void (GLAPIENTRY* PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (GLAPIENTRY* PFNGLPROGRAMLOCALPARAMETER4FARBPROC) + (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAPIENTRY* PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint* programs); + +void FASTCALL aft_shader_set(aft_shader_enum name) { + if (!name) { + aft_shader_unbind(); + return; + } + + PFNGLPROGRAMLOCALPARAMETER4FARBPROC _glProgramEnvParameter4fARB = *(void**)0x00000001411A4A88; + _glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 24, + (float_t)uniform->array[U_TEXTURE_BLEND], 0.0f, 0.0f, 0.0f); + + aft_shader* shad = &shaders[name]; + void (FASTCALL * bind_func)(aft_shader*) = shad->bind_func; + if (bind_func) + bind_func(shad); + else + aft_shader_bind(shad, shad->subs->sub_name); +} + +void FASTCALL aft_shader_bind_blinn(aft_shader* shad) { + aft_shader_bind(shad, uniform->array[U_NORMAL] ? BLINN_FRAG : BLINN_VERT); +} + +void FASTCALL aft_shader_bind_cloth(aft_shader* shad) { + aft_shader_bind(shad, uniform->array[U_NPR] ? CLOTH_NPR1 + : (uniform->array[U_ANISO] ? CLOTH_ANISO : CLOTH_DEFAULT)); +} + +void FASTCALL aft_shader_bind_hair(aft_shader* shad) { + aft_shader_bind(shad, uniform->array[U_NPR] ? HAIR_NPR1 + : (uniform->array[U_ANISO] ? HAIR_ANISO : HAIR_DEFAULT)); +} + +void FASTCALL aft_shader_bind_membrane(aft_shader* shad) { + uniform->array[U_MEMBRANE] = 3; + if (aft_shader_bind(shad, MEMBRANE) < 0) + return; + + uint32_t(FASTCALL * sub_140192E00)() = (void*)0x0000000140192E00; + uint32_t v1 = sub_140192E00(); + mat4 mat = mat4_identity; + mat4_rotate_x_mult(&mat, (float_t)((v1 & 0x1FF) * (M_PI / 256.0)), &mat); + mat4_rotate_z_mult(&mat, (float_t)((v1 % 0x168) * (M_PI / 180.0)), &mat); + + vec4 vec = (vec4){ 1.0f, 0.0f, 0.0f, 0.0f }; + mat4_mult_vec(&mat, &vec, &vec); + + PFNGLPROGRAMLOCALPARAMETER4FARBPROC _glProgramLocalParameter4fARB = *(void**)0x00000001411A4AA8; + _glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 10, vec.x, vec.y, vec.z, 0.0); +} + +void FASTCALL aft_shader_bind_eye_ball(aft_shader* shader) { + uniform->array[U18] = 0; + if (aft_shader_bind(&shaders[_GLASEYE], GLASS_EYE) >= 0) { + float_t* glass_eye = (float_t*)0x0000000140CA2D70; + void (FASTCALL * glass_eye_calc)(float_t * glass_eye) = (void*)0x00000001405E53D0; + void (FASTCALL * glass_eye_set)(float_t * glass_eye) = (void*)0x00000001405E4750; + glass_eye_calc(glass_eye); + glass_eye_set(glass_eye); + } +} + +void FASTCALL aft_shader_bind_tone_map(aft_shader* shader) { + aft_shader_bind(shader, uniform->array[U_NPR] == 1 ? TONEMAP_NPR1 : TONEMAP); +} + +int32_t FASTCALL aft_shader_bind(aft_shader* shader, aft_shader_sub_enum name) { + int32_t num_sub = shader->num_sub; + int32_t subshader_index = 0; + if (num_sub <= 0) + return -1; + + for (aft_shader_sub* i = shader->subs; i->sub_name != name; i++) { + subshader_index++; + if (subshader_index >= num_sub) + return -1; + } + + aft_shader_sub* subshader = &shader->subs[subshader_index]; + if (!subshader) + return -1; + + int32_t use_unis_count = shader->num_uniform; + int32_t unival_vp_curr = 1; + int32_t unival_fp_curr = 1; + int32_t unival_vp = 0; + int32_t unival_fp = 0; + if (use_unis_count > 0) { + int32_t* vp_unival_max = subshader->vp_unival_max; + int32_t* fp_unival_max = subshader->fp_unival_max; + for (size_t i = 0; i < use_unis_count; i++) { + int32_t unival = uniform->array[shader->use_uniform[i]]; + unival_vp += unival_vp_curr * min(unival, vp_unival_max[i]); + unival_fp += unival_fp_curr * min(unival, fp_unival_max[i]); + unival_vp_curr *= vp_unival_max[i] + 1; + unival_fp_curr *= fp_unival_max[i] + 1; + } + } + + int32_t vp = subshader->vp[unival_vp]; + int32_t fp = subshader->fp[unival_fp]; + + PFNGLBINDPROGRAMARBPROC _glBindProgramARB = *(void**)0x00000001411A4A60; + if (*current_vp != vp) { + _glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp); + *current_vp = vp; + } + + if (*current_fp != fp) { + _glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fp); + *current_fp = fp; + } + + _glEnable(GL_VERTEX_PROGRAM_ARB); + _glEnable(GL_FRAGMENT_PROGRAM_ARB); + return 0; +} + +void FASTCALL aft_shader_unbind() { + if (current_vp) + _glDisable(GL_VERTEX_PROGRAM_ARB); + if (current_fp) + _glDisable(GL_FRAGMENT_PROGRAM_ARB); + current_fp = 0; + current_vp = 0; +} + +void FASTCALL aft_shader_load_all_shaders() { + PFNGLGENPROGRAMSARBPROC _glGenProgramsARB = *(void**)0x00000001411A4A70; + void (FASTCALL * shader_load_program_file)(GLuint program, const char* file_name, bool vertex_program) + = (void*)0x00000001405E52D0; + + aft_shader_table_struct* shaders_table = &aft_shader_table[_BLINN]; + aft_shader* shader = &shaders[_BLINN]; + aft_shader_enum curr_shader = SHADER_END - 1; + do { + shader->name = shaders_table->name; + shader->name_enum = shaders_table->name_enum; + shader->num_sub = shaders_table->num_sub; + int32_t num_sub = shaders_table->num_sub; + void* v9 = force_malloc(sizeof(aft_shader_sub) * num_sub + 8); + *(int64_t*)v9 = num_sub; + + const aft_shader_sub_table_struct* sub = shaders_table->sub; + aft_shader_sub* subs = (aft_shader_sub*)((char*)v9 + 8); + for (int32_t i = 0; i < num_sub; i++) + subs[i] = (aft_shader_sub){ 0 }; + + shader->subs = subs; + shader->num_uniform = shaders_table->num_uniform; + shader->use_uniform = shaders_table->use_uniform; + + for (int32_t i = 0; i < num_sub; i++, sub++, subs++) { + subs->sub_name = sub->sub_name; + subs->vp_unival_max = (int32_t*)sub->vp_unival_max; + subs->fp_unival_max = (int32_t*)sub->fp_unival_max; + subs->num_vp = sub->num_vp; + subs->num_fp = sub->num_fp; + subs->vp = force_malloc(sizeof(int32_t) * sub->num_vp); + subs->fp = force_malloc(sizeof(int32_t) * sub->num_fp); + + _glGenProgramsARB(sub->num_vp, subs->vp); + _glGenProgramsARB(sub->num_fp, subs->fp); + + for (int32_t j = 0; j < sub->num_vp; j++) + shader_load_program_file(subs->vp[j], sub->vp[j], true); + + for (int32_t j = 0; j < sub->num_fp; j++) + shader_load_program_file(subs->fp[j], sub->fp[j], false); + } + shader->bind_func = 0; + + aft_shader_bind_func* bind_func_table = shader_name_bind_func_table; + aft_shader_enum bind_func_name = _BLINN; + while (shader->name_enum != bind_func_name) { + bind_func_name = (++bind_func_table)->name; + if (bind_func_table->name == SHADER_END) + break; + } + shader->bind_func = bind_func_table->bind_func; + shader++; + shaders_table++; + curr_shader--; + } while (curr_shader); +} diff --git a/src/DivaGL/shader_table.h b/src/DivaGL/shader_table.h new file mode 100644 index 00000000..a5d11cd7 --- /dev/null +++ b/src/DivaGL/shader_table.h @@ -0,0 +1,212 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../KKdLib/default.h" +#include "../CRE/shared.h" + +typedef enum aft_shader_sub_enum { + SHADER_SUB_FFP = 0, + BLINN_VERT = 1, + BLINN_FRAG = 2, + ITEM_BLINN = 3, + STAGE_BLINN = 4, + SKIN_DEFAULT = 5, + SSS_SKIN = 6, + SSS_FILTER = 7, + HAIR_DEFAULT = 8, + HAIR_ANISO = 9, + HAIR_NPR1 = 10, + CLOTH_DEFAULT = 11, + CLOTH_ANISO = 12, + CLOTH_NPR1 = 13, + TIGHTS = 14, + SKY_DEFAULT = 15, + EYE_BALL = 16, + EYE_LENS = 17, + GLASS_EYE = 18, + MEMBRANE = 19, + SHADOWMAP = 20, + ESM = 21, + ESM_GAUSS = 22, + ESM_FILTER = 23, + LIT_PROJ = 24, + SIMPLE = 25, + SILHOUETTE = 26, + LAMBERT = 27, + CONSTANT = 28, + PEEL = 29, + TONEMAP = 30, + TONEMAP_NPR1 = 31, + REDUCE_TEX = 32, + MAGNIFY = 33, + MLAA = 34, + CONTOUR = 35, + EXPOSURE = 36, + PP_GAUSS = 37, + SUN = 38, + FADE = 39, + WATER01 = 40, + WATER02 = 41, + WATER_RING = 42, + WATER_PARTICLE = 43, + SNOW_PARTICLE = 44, + LEAF_PARTICLE = 45, + STAR = 46, + SNOW_RING = 47, + SNOW_FOOTPRINT = 48, + SNOW_TEX_SPACE_LIGHT = 49, + SNOW_CALC_NORMAL = 50, + FLOOR = 51, + PUDDLE = 52, + SIMPLE_REFLECT = 53, + SIMPLE_REFRACT = 54, + RIPPLE_EMIT = 55, + RAIN = 56, + VOLUME_LIGHT = 57, + FENCE_ALPHA = 58, + RIPPLE = 59, + FOG_PTCL = 60, + PARTICLE = 61, + GLITTER_PARTICLE = 62, + SHOW_VECTOR = 63, + FONT = 64, + MOVIE = 65, + IMGFILTER = 66, + SPRITE = 67, +} aft_shader_sub_enum; + +typedef enum aft_shader_enum { + SHADER_FFP = 0, + _BLINN = 1, + _ITEM = 2, + _STAGE = 3, + _SKIN = 4, + _SSS_SKIN = 5, + _SSS_FILT = 6, + _HAIR = 7, + _CLOTH = 8, + _TIGHTS = 9, + _SKY = 10, + _EYEBALL = 11, + _EYELENS = 12, + _GLASEYE = 13, + _MEMBRAN = 14, + _SHDMAP = 15, + _ESM = 16, + _ESMGAUSS = 17, + _ESMFILT = 18, + _LITPROJ = 19, + _SIMPLE = 20, + _SIL = 21, + _LAMBERT = 22, + _CONSTANT = 23, + _PEEL = 24, + _TONEMAP = 25, + _REDUCE = 26, + _MAGNIFY = 27, + _MLAA = 28, + _CONTOUR = 29, + _EXPOSURE = 30, + _GAUSS = 31, + _SUN = 32, + _FADE = 33, + _WATER01 = 34, + _WATER02 = 35, + _WATRING = 36, + _W_PTCL = 37, + _SNOW_PT = 38, + _LEAF_PT = 39, + _START = 40, + _SNORING = 41, + _SN_FOOT = 42, + _SN_TSL = 43, + _SN_NRM = 44, + _FLOOR = 45, + _PUDDLE = 46, + _S_REFL = 47, + _S_REFR = 48, + _RIPEMIT = 49, + _RAIN = 50, + _VOLLIT = 51, + _FENCE = 52, + _RIPPLE = 53, + _FOGPTCL = 54, + _PARTICL = 55, + _GLITTER_PT = 56, + _SHOWVEC = 57, + _FONT = 58, + _MOVIE = 59, + _IMGFILT = 60, + _SPRITE = 61, + SHADER_END = 62, +} aft_shader_enum; + +typedef struct aft_shader_sub_table_struct { + aft_shader_sub_enum sub_name; + int32_t padding; + const int32_t* vp_unival_max; + const int32_t* fp_unival_max; + int32_t num_vp; + int32_t num_fp; + const char** vp; + const char** fp; +} aft_shader_sub_table_struct; + +typedef struct aft_shader_table_struct { + const char* name; + aft_shader_enum name_enum; + int32_t num_sub; + const aft_shader_sub_table_struct* sub; + int32_t num_uniform; + int32_t padding; + int32_t* use_uniform; +} aft_shader_table_struct; + +typedef struct aft_shader_sub { + aft_shader_sub_enum sub_name; + int32_t padding; + int32_t* vp_unival_max; + int32_t* fp_unival_max; + int32_t num_vp; + int32_t num_fp; + int32_t* vp; + int32_t* fp; +} aft_shader_sub; + +typedef struct aft_shader { + const char* name; + aft_shader_enum name_enum; + int32_t num_sub; + aft_shader_sub* subs; + int32_t num_uniform; + int32_t padding; + int32_t* use_uniform; + void* bind_func; +} aft_shader; + +typedef struct aft_shader_bind_func { + aft_shader_enum name; + int32_t padding; + void* bind_func; +} aft_shader_bind_func; + +extern aft_shader* shaders; +extern aft_shader_table_struct* aft_shader_table; +extern aft_shader_bind_func* shader_name_bind_func_table; +extern int32_t* current_vp; +extern int32_t* current_fp; + +extern void FASTCALL aft_shader_set(aft_shader_enum name); // 0x00000001405E4CE0 +extern void FASTCALL aft_shader_bind_blinn(aft_shader* shader); // 0x00000001405E4320 +extern void FASTCALL aft_shader_bind_cloth(aft_shader* shader); // 0x00000001405E4340 +extern void FASTCALL aft_shader_bind_hair(aft_shader* shader); // 0x00000001405E4370 +extern void FASTCALL aft_shader_bind_membrane(aft_shader* shader); // 0x00000001405E43A0 +extern void FASTCALL aft_shader_bind_eye_ball(aft_shader* shader); // 0x00000001405E4530 +extern void FASTCALL aft_shader_bind_tone_map(aft_shader* shader); // 0x00000001405E4580 +extern int32_t FASTCALL aft_shader_bind(aft_shader* shader, aft_shader_sub_enum name); // 0x00000001405E4B50 +extern void FASTCALL aft_shader_unbind(); // 0x00000001405E5660 +extern void FASTCALL aft_shader_load_all_shaders(); // 0x00000001405E4FC0 diff --git a/src/KKdLib/a3da.c b/src/KKdLib/a3da.c new file mode 100644 index 00000000..9e104e50 --- /dev/null +++ b/src/KKdLib/a3da.c @@ -0,0 +1,3594 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "a3da.h" +#include "f2/struct.h" +#include "io/path.h" +#include "io/stream.h" +#include "half_t.h" +#include "hash.h" +#include "key_val.h" +#include "str_utils.h" +#include + +typedef struct a3da_vec3_header { + uint32_t x; + uint32_t y; + uint32_t z; +} a3da_vec3_header; + +typedef struct a3da_model_transform_header { + a3da_vec3_header scale; + a3da_vec3_header rotation; + a3da_vec3_header translation; + uint32_t visibility; +} a3da_model_transform_header; + +typedef struct a3dc_header { + uint32_t binary_length; + uint32_t binary_offset; + uint32_t string_length; + uint32_t string_offset; +} a3dc_header; + +typedef struct a3dc_key_header { + a3da_key_type type : 8; + a3da_ep_type ep_type_pre : 4; + a3da_ep_type ep_type_post : 4; + uint32_t padding : 16; + float_t value; + float_t max; + uint32_t length; +} a3dc_key_header; + +vector_func(a3da_ambient) +vector_func(a3da_model_transform) +vector_func(a3da_camera_root) +vector_func(a3da_chara) +vector_func(a3da_curve) +vector_func(a3da_event) +vector_func(a3da_fog) +vector_func(a3da_light) +vector_func(a3da_m_object_hrc) +vector_func(a3da_material_list) +vector_func(a3da_object) +vector_func(a3da_object_hrc) +vector_func(a3da_object_instance) +vector_func(a3da_object_node) +vector_func(a3da_object_texture_pattern) +vector_func(a3da_object_texture_transform) +vector_func(a3da_point) + +#define A3DA_TEXT_BUF_SIZE 0x400 + +static void a3da_read_inner(a3da* a, stream* s); +static void a3da_write_inner(a3da* a, stream* s); +static void a3da_read_text(a3da* a, void* data, size_t length); +static void a3da_write_text(a3da* a, void** data, size_t* length, bool a3dc); +static void a3da_read_data(a3da* a, void* data, size_t length); +static void a3da_write_data(a3da* a, void** data, size_t* length); +static void a3da_get_time_stamp(char* buf, size_t buf_size); +static bool key_val_read_a3da_key(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_key* value); +static void key_val_write_a3da_key(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_key* value); +static bool key_val_read_a3da_key_raw_data(key_val* kv, char* buf, + size_t offset, a3da_key* value); +static void key_val_write_a3da_key_raw_data(stream* s, char* buf, + size_t offset, a3da_key* value); +static bool key_val_read_a3da_model_transform(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_model_transform* value); +static void key_val_write_a3da_model_transform(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_model_transform* value, int32_t write_mask); +static bool key_val_read_a3da_rgba(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_rgba* value); +static void key_val_write_a3da_rgba(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_rgba* value); +static bool key_val_read_a3da_vec3(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_vec3* value); +static void key_val_write_a3da_vec3(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_vec3* value); +static void a3dc_read_a3da_key(void* data, size_t length, a3da_key* value); +static void a3dc_write_a3da_key(stream* s, a3da_key* value); +static void a3dc_read_a3da_key_f16(void* data, size_t length, a3da_key* value, a3da_compress_f16 f16); +static void a3dc_write_a3da_key_f16(stream* s, a3da_key* value, a3da_compress_f16 f16); +static void a3dc_read_a3da_model_transform(void* data, size_t length, + a3da_model_transform* value, a3da_compress_f16 f16); +static void a3dc_write_a3da_model_transform(stream* s, + a3da_model_transform* value, a3da_compress_f16 f16); +static void a3dc_write_a3da_model_transform_offset(stream* s, + a3da_model_transform* value); +static void a3dc_write_a3da_model_transform_offset_data(stream* s, + a3da_model_transform* value); +static void a3dc_read_a3da_rgba(void* data, size_t length, a3da_rgba* value); +static void a3dc_write_a3da_rgba(stream* s, a3da_rgba* value); +static void a3dc_read_a3da_vec3(void* data, size_t length, a3da_vec3* value); +static void a3dc_write_a3da_vec3(stream* s, a3da_vec3* value); +static void a3dc_read_a3da_vec3_f16(void* data, size_t length, a3da_vec3* value, a3da_compress_f16 f16); +static void a3dc_write_a3da_vec3_f16(stream* s, a3da_vec3* value, a3da_compress_f16 f16); + +void a3da_init(a3da* a) { + memset(a, 0, sizeof(a3da)); +} + +void a3da_read(a3da* a, char* path) { + if (!a || !path) + return; + + char* path_a3da = str_utils_add(path, ".a3da"); + if (path_check_file_exists(path_a3da)) { + stream s; + io_open(&s, path_a3da, "rb"); + if (s.io.stream) + a3da_read_inner(a, &s); + io_free(&s); + } + free(path_a3da); +} + +void a3da_wread(a3da* a, wchar_t* path) { + if (!a || !path) + return; + + wchar_t* path_a3da = str_utils_wadd(path, L".a3da"); + if (path_wcheck_file_exists(path_a3da)) { + stream s; + io_wopen(&s, path_a3da, L"rb"); + if (s.io.stream) + a3da_read_inner(a, &s); + io_free(&s); + } + free(path_a3da); +} + +void a3da_mread(a3da* a, void* data, size_t length) { + if (!a || !data || !length) + return; + + stream s; + io_mopen(&s, data, length); + a3da_read_inner(a, &s); + io_free(&s); +} + +void a3da_write(a3da* a, char* path) { + if (!a || !path || !a->ready) + return; + + char* path_a3da = str_utils_add(path, ".a3da"); + stream s; + io_open(&s, path_a3da, "wb"); + if (s.io.stream) + a3da_write_inner(a, &s); + io_free(&s); + free(path_a3da); +} + +void a3da_wwrite(a3da* a, wchar_t* path) { + if (!a || !path || !a->ready) + return; + + wchar_t* path_a3da = str_utils_wadd(path, L".a3da"); + stream s; + io_wopen(&s, path_a3da, L"wb"); + if (s.io.stream) + a3da_write_inner(a, &s); + io_free(&s); + free(path_a3da); +} + +void a3da_mwrite(a3da* a, void** data, size_t* length) { + if (!a || !data || !a->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + a3da_write_inner(a, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool a3da_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + a3da* a = data; + a3da_read(a, string_data(&s)); + + string_free(&s); + return a->ready; +} + +void a3da_free(a3da* a) { + if (!a) + return; + + string_free(&a->_file_name); + string_free(&a->_property_version); + string_free(&a->_converter_version); + + vector_a3da_ambient_free(&a->ambient, a3da_ambient_free); + vector_string_free(&a->auth_2d, string_free); + a3da_camera_auxiliary_free(&a->camera_auxiliary); + vector_a3da_camera_root_free(&a->camera_root, a3da_camera_root_free); + vector_a3da_chara_free(&a->chara, a3da_chara_free); + vector_a3da_curve_free(&a->curve, a3da_curve_free); + a3da_dof_free(&a->dof); + vector_a3da_event_free(&a->event, a3da_event_free); + vector_a3da_fog_free(&a->fog, a3da_fog_free); + vector_a3da_light_free(&a->light, a3da_light_free); + vector_a3da_m_object_hrc_free(&a->m_object_hrc, a3da_m_object_hrc_free); + vector_string_free(&a->m_object_hrc_list, string_free); + vector_a3da_material_list_free(&a->material_list, a3da_material_list_free); + vector_string_free(&a->motion, string_free); + vector_a3da_object_free(&a->object, a3da_object_free); + vector_a3da_object_hrc_free(&a->object_hrc, a3da_object_hrc_free); + vector_string_free(&a->object_hrc_list, string_free); + vector_string_free(&a->object_list, string_free); + vector_a3da_point_free(&a->point, a3da_point_free); + a3da_post_process_free(&a->post_process); +} + +void a3da_key_free(a3da_key* k) { + vector_kft3_free(&k->keys, 0); +} + +void a3da_rgba_free(a3da_rgba* rgba) { + if (rgba->flags & A3DA_RGBA_R) + a3da_key_free(&rgba->r); + if (rgba->flags & A3DA_RGBA_G) + a3da_key_free(&rgba->g); + if (rgba->flags & A3DA_RGBA_B) + a3da_key_free(&rgba->b); + if (rgba->flags & A3DA_RGBA_A) + a3da_key_free(&rgba->a); +} + +void a3da_vec3_free(a3da_vec3* vec) { + a3da_key_free(&vec->x); + a3da_key_free(&vec->y); + a3da_key_free(&vec->z); +} + +void a3da_model_transform_free(a3da_model_transform* mt) { + a3da_vec3_free(&mt->rotation); + a3da_vec3_free(&mt->scale); + a3da_vec3_free(&mt->translation); + a3da_key_free(&mt->visibility); +} + +void a3da_ambient_free(a3da_ambient* a) { + if (a->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) + a3da_rgba_free(&a->light_diffuse); + string_free(&a->name); + if (a->flags & A3DA_AMBIENT_RIM_LIGHT_DIFFUSE) + a3da_rgba_free(&a->rim_light_diffuse); +} + +void a3da_camera_auxiliary_free(a3da_camera_auxiliary* ca) { + if (ca->flags & A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE) + a3da_key_free(&ca->auto_exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE) + a3da_key_free(&ca->exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE) + a3da_key_free(&ca->exposure_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA) + a3da_key_free(&ca->gamma); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA_RATE) + a3da_key_free(&ca->gamma_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_SATURATE) + a3da_key_free(&ca->saturate); +} + +void a3da_camera_root_free(a3da_camera_root* cr) { + a3da_model_transform_free(&cr->interest); + a3da_model_transform_free(&cr->model_transform); + a3da_camera_root_view_point_free(&cr->view_point); +} + +void a3da_camera_root_view_point_free(a3da_camera_root_view_point* crvp) { + if (crvp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_FOV) + a3da_key_free(&crvp->fov); + else + a3da_key_free(&crvp->focal_length); + a3da_model_transform_free(&crvp->model_transform); + if (crvp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_ROLL) + a3da_key_free(&crvp->roll); +} + +void a3da_chara_free(a3da_chara* c) { + a3da_model_transform_free(&c->model_transform); + string_free(&c->name); +} + +void a3da_curve_free(a3da_curve* c) { + a3da_key_free(&c->curve); + string_free(&c->name); +} + +void a3da_dof_free(a3da_dof* d) { + a3da_model_transform_free(&d->model_transform); +} + +void a3da_event_free(a3da_event* e) { + string_free(&e->name); + string_free(&e->param_1); + string_free(&e->ref); +} + +void a3da_fog_free(a3da_fog* f) { + if (f->flags & A3DA_FOG_COLOR) + a3da_rgba_free(&f->color); + if (f->flags & A3DA_FOG_DENSITY) + a3da_key_free(&f->density); + if (f->flags & A3DA_FOG_END) + a3da_key_free(&f->end); + if (f->flags & A3DA_FOG_START) + a3da_key_free(&f->start); +} + +void a3da_light_free(a3da_light* l) { + if (l->flags & A3DA_LIGHT_AMBIENT) + a3da_rgba_free(&l->ambient); + if (l->flags & A3DA_LIGHT_CONE_ANGLE) + a3da_key_free(&l->cone_angle); + if (l->flags & A3DA_LIGHT_CONSTANT) + a3da_key_free(&l->constant); + if (l->flags & A3DA_LIGHT_DIFFUSE) + a3da_rgba_free(&l->diffuse); + if (l->flags & A3DA_LIGHT_DROP_OFF) + a3da_key_free(&l->drop_off); + if (l->flags & A3DA_LIGHT_FAR) + a3da_key_free(&l->_far); + if (l->flags & A3DA_LIGHT_INTENSITY) + a3da_key_free(&l->intensity); + if (l->flags & A3DA_LIGHT_LINEAR) + a3da_key_free(&l->linear); + if (l->flags & A3DA_LIGHT_POSITION) + a3da_model_transform_free(&l->position); + if (l->flags & A3DA_LIGHT_QUADRATIC) + a3da_key_free(&l->quadratic); + if (l->flags & A3DA_LIGHT_SPECULAR) + a3da_rgba_free(&l->specular); + if (l->flags & A3DA_LIGHT_SPOT_DIRECTION) + a3da_model_transform_free(&l->spot_direction); + if (l->flags & A3DA_LIGHT_TONE_CURVE) + a3da_rgba_free(&l->tone_curve); + string_free(&l->type); +} + +void a3da_m_object_hrc_free(a3da_m_object_hrc* moh) { + vector_a3da_object_instance_free(&moh->instance, + a3da_object_instance_free); + a3da_model_transform_free(&moh->model_transform); + string_free(&moh->name); + vector_a3da_object_node_free(&moh->node, a3da_object_node_free); +} + +void a3da_material_list_free(a3da_material_list* ml) { + if (ml->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + a3da_rgba_free(&ml->blend_color); + if (ml->flags & A3DA_MATERIAL_LIST_GLOW_INTENSITY) + a3da_key_free(&ml->glow_intensity); + if (ml->flags & A3DA_MATERIAL_LIST_INCANDESCENCE) + a3da_rgba_free(&ml->incandescence); + string_free(&ml->name); +} + +void a3da_object_free(a3da_object* o) { + a3da_model_transform_free(&o->model_transform); + string_free(&o->morph); + string_free(&o->name); + string_free(&o->parent_name); + string_free(&o->parent_node); + string_free(&o->pattern); + vector_a3da_object_texture_pattern_free(&o->texture_pattern, + a3da_object_texture_pattern_free); + vector_a3da_object_texture_transform_free(&o->texture_transform, + a3da_object_texture_transform_free); + string_free(&o->uid_name); +} + +void a3da_object_hrc_free(a3da_object_hrc* oh) { + string_free(&oh->name); + vector_a3da_object_node_free(&oh->node, a3da_object_node_free); + string_free(&oh->parent_name); + string_free(&oh->parent_node); + string_free(&oh->uid_name); +} + +void a3da_object_instance_free(a3da_object_instance* oi) { + a3da_model_transform_free(&oi->model_transform); + string_free(&oi->name); + string_free(&oi->uid_name); +} + +void a3da_object_node_free(a3da_object_node* on) { + a3da_model_transform_free(&on->model_transform); + string_free(&on->name); +} + +void a3da_object_texture_pattern_free(a3da_object_texture_pattern* otp) { + string_free(&otp->name); + string_free(&otp->pattern); +} + +void a3da_object_texture_transform_free(a3da_object_texture_transform* ott) { + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + a3da_key_free(&ott->coverage_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + a3da_key_free(&ott->coverage_v); + string_free(&ott->name); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + a3da_key_free(&ott->offset_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + a3da_key_free(&ott->offset_v); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + a3da_key_free(&ott->repeat_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + a3da_key_free(&ott->repeat_v); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE) + a3da_key_free(&ott->rotate); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + a3da_key_free(&ott->rotate_frame); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + a3da_key_free(&ott->translate_frame_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + a3da_key_free(&ott->translate_frame_v); +} + +void a3da_point_free(a3da_point* p) { + a3da_model_transform_free(&p->model_transform); + string_free(&p->name); +} + +void a3da_post_process_free(a3da_post_process* pp) { + if (pp->flags & A3DA_POST_PROCESS_INTENSITY) + a3da_rgba_free(&pp->intensity); + if (pp->flags & A3DA_POST_PROCESS_LENS_FLARE) + a3da_key_free(&pp->lens_flare); + if (pp->flags & A3DA_POST_PROCESS_LENS_GHOST) + a3da_key_free(&pp->lens_ghost); + if (pp->flags & A3DA_POST_PROCESS_LENS_SHAFT) + a3da_key_free(&pp->lens_shaft); + if (pp->flags & A3DA_POST_PROCESS_RADIUS) + a3da_rgba_free(&pp->radius); + if (pp->flags & A3DA_POST_PROCESS_SCENE_FADE) + a3da_rgba_free(&pp->scene_fade); +} + +static void a3da_read_inner(a3da* a, stream* s) { + a3dc_header header; + memset(&header, 0, sizeof(a3dc_header)); + + a->format = A3DA_FORMAT_F; + uint32_t signature = io_read_uint32_t(s); + io_set_position(s, 0x00, SEEK_SET); + + stream _s; + if (signature == reverse_endianness_int32_t('A3DA')) { + f2_struct st; + f2_struct_sread(&st, s); + io_mopen(&_s, st.data, st.length); + a->format = A3DA_FORMAT_F2; + f2_struct_free(&st); + } + else { + size_t length = s->length; + void* data = force_malloc(length); + io_read(s, data, length); + io_mopen(&_s, data, length); + free(data); + } + + signature = io_read_uint32_t(&_s); + if (signature != reverse_endianness_int32_t('#A3D')) + goto End; + + signature = io_read_uint32_t(&_s); + if ((signature & 0xFF) == 'A') { + header.string_offset = 0x10; + header.string_length = (int32_t)(_s.length - 0x10); + } + else if ((signature & 0xFF) == 'C') { + io_set_position(&_s, 0x10, SEEK_SET); + io_read_int32_t(&_s); + io_read_int32_t(&_s); + uint32_t sub_headers_offset = io_read_uint32_t_reverse_endianness(&_s, true); + uint16_t sub_headers_count = io_read_uint16_t_reverse_endianness(&_s, true); + uint16_t sub_headers_stride = io_read_uint16_t_reverse_endianness(&_s, true); + + if (sub_headers_count != 0x02) + goto End; + + io_set_position(&_s, sub_headers_offset, SEEK_SET); + if (io_read_int32_t(&_s) != 0x50) + goto End; + header.string_offset = io_read_uint32_t_reverse_endianness(&_s, true); + header.string_length = io_read_uint32_t_reverse_endianness(&_s, true); + + io_set_position(&_s, (ssize_t)sub_headers_offset + sub_headers_stride, SEEK_SET); + if (io_read_int32_t(&_s) != 0x4C42) + goto End; + header.binary_offset = io_read_uint32_t_reverse_endianness(&_s, true); + header.binary_length = io_read_uint32_t_reverse_endianness(&_s, true); + } + else + goto End; + + io_set_position(&_s, header.string_offset, SEEK_SET); + void* a3da_data = force_malloc(header.string_length); + io_read(&_s, a3da_data, header.string_length); + a3da_read_text(a, a3da_data, header.string_length); + free(a3da_data); + + if (signature == reverse_endianness_int32_t('C___')) { + a->compressed = true; + io_set_position(&_s, header.binary_offset, SEEK_SET); + void* a3dc_data = force_malloc(header.binary_length); + io_read(&_s, a3dc_data, header.binary_length); + a3da_read_data(a, a3dc_data, header.binary_length); + free(a3dc_data); + } + a->ready = true; + +End: + io_free(&_s); +} + +static void a3da_write_inner(a3da* a, stream* s) { + bool a3dc = a->compressed || a->format > A3DA_FORMAT_AFT; + + void* a3dc_data = 0; + size_t a3dc_data_length = 0; + if (a3dc) + a3da_write_data(a, &a3dc_data, &a3dc_data_length); + + void* a3da_data = 0; + size_t a3da_data_length = 0; + a3da_write_text(a, &a3da_data, &a3da_data_length, a3dc); + + stream s_a3da; + stream* _s = s; + if (a->format > A3DA_FORMAT_AFT) { + io_mopen(&s_a3da, 0, 0); + _s = &s_a3da; + } + + if (a3dc) { + a3dc_header header; + memset(&header, 0, sizeof(a3dc_header)); + header.string_offset = (uint32_t)0x40; + header.string_length = (uint32_t)a3da_data_length; + header.binary_offset = (uint32_t)(0x40 + align_val(a3da_data_length, 0x20)); + header.binary_length = (uint32_t)a3dc_data_length; + + io_write(_s, "#A3DC__________\n", 16); + io_write_int32_t(_s, 0x2000); + io_write_int32_t(_s, 0x00); + io_write_uint32_t_reverse_endianness(_s, 0x20, true); + io_write_uint16_t_reverse_endianness(_s, 0x02, true); + io_write_uint16_t_reverse_endianness(_s, 0x10, true); + io_write_char(_s, 'P'); + io_align_write(_s, 0x04); + io_write_uint32_t_reverse_endianness(_s, header.string_offset, true); + io_write_uint32_t_reverse_endianness(_s, header.string_length, true); + io_write_uint32_t_reverse_endianness(_s, 0x01, true); + io_write_char(_s, 'B'); + io_write_char(_s, 'L'); + io_align_write(_s, 0x04); + io_write_uint32_t_reverse_endianness(_s, header.binary_offset, true); + io_write_uint32_t_reverse_endianness(_s, header.binary_length, true); + io_write_uint32_t_reverse_endianness(_s, 0x20, true); + io_write(_s, a3da_data, a3da_data_length); + io_align_write(_s, 0x20); + io_write(_s, a3dc_data, a3dc_data_length); + free(a3dc_data); + } + else + io_write(_s, a3da_data, a3da_data_length); + free(a3da_data); + + if (a->format > A3DA_FORMAT_AFT) { + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + + io_align_write(&s_a3da, 0x10); + io_mcopy(&s_a3da, &st.data, &st.length); + io_free(&s_a3da); + + st.header.signature = reverse_endianness_uint32_t('A3DA'); + st.header.length = 0x40; + st.header.use_big_endian = false; + st.header.use_section_size = true; + st.header.inner_signature = a->format == A3DA_FORMAT_XHD ? 0x00131010 : 0x01131010; + + f2_struct_swrite(&st, s, true, a->format == A3DA_FORMAT_X || a->format == A3DA_FORMAT_XHD); + f2_struct_free(&st); + } +} + +static void a3da_read_text(a3da* a, void* data, size_t length) { + char buf[A3DA_TEXT_BUF_SIZE]; + int32_t count; + int32_t count1; + size_t len; + size_t len1; + size_t len2; + size_t len3; + size_t off; + + key_val kv; + key_val_init(&kv, data, length); + key_val lkv; + if (key_val_get_local_key_val(&kv, "_", &lkv)) { + len = 1; + memcpy(buf, "_", 1); + off = len; + + key_val_read_int32_t(&lkv, + buf, off, ".compress_f16", 14, (int32_t*)&a->_compress_f16); + key_val_read_string(&lkv, + buf, off, ".converter.version", 19, &a->_converter_version); + key_val_read_string(&lkv, + buf, off, ".file_name", 11, &a->_file_name); + key_val_read_string(&lkv, + buf, off, ".property.version", 19, &a->_property_version); + key_val_free(&lkv); + } + + memset(&a->camera_auxiliary, 0, sizeof(a3da_camera_auxiliary)); + if (key_val_get_local_key_val(&kv, "camera_auxiliary", &lkv)) { + a3da_camera_auxiliary* ca = &a->camera_auxiliary; + + len = 16; + memcpy(buf, "camera_auxiliary", 16); + off = len; + + if (key_val_read_a3da_key(&lkv, + buf, off, ".auto_exposure", 15, &ca->auto_exposure)) + ca->flags |= A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".exposure", 10, &ca->exposure)) + ca->flags |= A3DA_CAMERA_AUXILIARY_EXPOSURE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".exposure_rate", 15, &ca->exposure_rate)) + ca->flags |= A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".gamma", 7, &ca->gamma)) + ca->flags |= A3DA_CAMERA_AUXILIARY_GAMMA; + if (key_val_read_a3da_key(&lkv, + buf, off, ".gamma_rate", 12, &ca->gamma_rate)) + ca->flags |= A3DA_CAMERA_AUXILIARY_GAMMA_RATE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".saturate", 10, &ca->saturate)) + ca->flags |= A3DA_CAMERA_AUXILIARY_SATURATE; + + if (ca->flags & (A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE | A3DA_CAMERA_AUXILIARY_GAMMA_RATE)) + if (a->format < A3DA_FORMAT_F || a->format == A3DA_FORMAT_AFT) + a->format = A3DA_FORMAT_F; + key_val_free(&lkv); + } + + memset(&a->play_control, 0, sizeof(a3da_play_control)); + if (key_val_get_local_key_val(&kv, "play_control", &lkv)) { + a3da_play_control* pc = &a->play_control; + + len = 12; + memcpy(buf, "play_control", 12); + off = len; + + key_val_read_float_t(&lkv, + buf, off, ".begin", 5, &pc->begin); + if (key_val_read_int32_t(&lkv, + buf, off, ".div", 5, &pc->div)) + pc->flags |= A3DA_PLAY_CONTROL_DIV; + key_val_read_float_t(&lkv, + buf, off, ".fps", 5, &pc->fps); + if (key_val_read_float_t(&lkv, + buf, off, ".offset", 8, &pc->offset)) + pc->flags |= A3DA_PLAY_CONTROL_OFFSET; + key_val_read_float_t(&lkv, + buf, off, ".size", 6, &pc->size); + key_val_free(&lkv); + } + + memset(&a->post_process, 0, sizeof(a3da_post_process)); + if (key_val_get_local_key_val(&kv, "post_process", &lkv)) { + a3da_post_process* pp = &a->post_process; + + len = 12; + memcpy(buf, "post_process", 12); + off = len; + + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Diffuse", 9, &pp->intensity)) + pp->flags |= A3DA_POST_PROCESS_INTENSITY; + if (key_val_read_a3da_key(&lkv, + buf, off, ".lens_flare", 12, &pp->lens_flare)) + pp->flags |= A3DA_POST_PROCESS_LENS_FLARE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".lens_ghost", 12, &pp->lens_ghost)) + pp->flags |= A3DA_POST_PROCESS_LENS_GHOST; + if (key_val_read_a3da_key(&lkv, + buf, off, ".lens_shaft", 12, &pp->lens_shaft)) + pp->flags |= A3DA_POST_PROCESS_LENS_SHAFT; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Ambient", 9, &pp->radius)) + pp->flags |= A3DA_POST_PROCESS_RADIUS; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Specular", 10, &pp->scene_fade)) + pp->flags |= A3DA_POST_PROCESS_SCENE_FADE; + key_val_free(&lkv); + } + + memset(&a->dof, 0, sizeof(a3da_dof)); + if (key_val_get_local_key_val(&kv, "dof", &lkv)) { + a3da_dof* d = &a->dof; + + len = 3; + memcpy(buf, "dof", 3); + off = len; + + d->has_dof = key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &d->model_transform); + key_val_free(&lkv); + } + + len = 7; + memcpy(buf, "ambient", 7); + off = len; + + a->ambient = vector_empty(a3da_ambient); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "ambient", &lkv)) { + vector_a3da_ambient* va = &a->ambient; + + vector_a3da_ambient_reserve(va, count); + va->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_ambient* a = &va->begin[i]; + memset(a, 0, sizeof(a3da_ambient)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".light.Diffuse", 15, &a->light_diffuse)) + a->flags |= A3DA_AMBIENT_LIGHT_DIFFUSE; + key_val_read_string(&lkv, + buf, off, ".name", 6, &a->name); + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".rim.light.Diffuse", 19, &a->rim_light_diffuse)) + a->flags |= A3DA_AMBIENT_RIM_LIGHT_DIFFUSE; + } + key_val_free(&lkv); + } + + len = 7; + memcpy(buf, "auth_2d", 7); + off = len; + + a->auth_2d = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "auth_2d", &lkv)) { + vector_string* va2 = &a->auth_2d; + + vector_string_reserve(va2, count); + va2->end += count; + for (int32_t i = 0; i < count; i++) { + string* a2 = &va2->begin[i]; + *a2 = string_empty; + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, ".name", 6, a2); + } + key_val_free(&lkv); + } + + len = 11; + memcpy(buf, "camera_root", 11); + off = len; + + a->camera_root = vector_empty(a3da_camera_root); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "camera_root", &lkv)) { + vector_a3da_camera_root* vcr = &a->camera_root; + + vector_a3da_camera_root_reserve(vcr, count); + vcr->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_camera_root* cr = &vcr->begin[i]; + memset(cr, 0, sizeof(a3da_camera_root)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_a3da_model_transform(&lkv, + buf, off, ".interest", 10, &cr->interest); + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &cr->model_transform); + + a3da_camera_root_view_point* vp = &cr->view_point; + + len2 = 11; + memcpy(buf + len + len1, ".view_point", 11); + off = len + len1 + len2; + + key_val_read_float_t(&lkv, + buf, off, ".aspect", 8, &vp->aspect); + + memcpy(buf + len + len1 + len2, ".fov_is_horizontal", 19); + if (key_val_has_key(&lkv, buf)) { + key_val_read_a3da_key(&lkv, + buf, off, ".fov", 5, &vp->fov); + key_val_read_bool(&lkv, + buf, off, ".fov_is_horizontal", 19, &vp->fov_is_horizontal); + vp->flags |= A3DA_CAMERA_ROOT_VIEW_POINT_FOV; + } + else { + key_val_read_float_t(&lkv, + buf, off, ".camera_aperture_h", 19, &vp->camera_aperture_h); + key_val_read_float_t(&lkv, + buf, off, ".camera_aperture_w", 19, &vp->camera_aperture_w); + key_val_read_a3da_key(&lkv, + buf, off, ".focal_length", 14, &vp->focal_length); + } + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &vp->model_transform); + if (key_val_read_a3da_key(&lkv, + buf, off, ".roll", 6, &vp->roll)) + vp->flags |= A3DA_CAMERA_ROOT_VIEW_POINT_ROLL; + } + key_val_free(&lkv); + } + + len = 5; + memcpy(buf, "chara", 5); + off = len; + + a->chara = vector_empty(a3da_chara); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "chara", &lkv)) { + vector_a3da_chara* vc = &a->chara; + + vector_a3da_chara_reserve(vc, count); + vc->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_chara* c = &vc->begin[i]; + memset(c, 0, sizeof(a3da_chara)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &c->model_transform); + key_val_read_string(&lkv, + buf, off, ".name", 6, &c->name); + } + } + + len = 5; + memcpy(buf, "curve", 5); + off = len; + + a->curve = vector_empty(a3da_curve); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "curve", &lkv)) { + vector_a3da_curve* vc = &a->curve; + + vector_a3da_curve_reserve(vc, count); + vc->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_curve* c = &vc->begin[i]; + memset(c, 0, sizeof(a3da_curve)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_a3da_key(&lkv, + buf, off, ".cv", 4, &c->curve); + key_val_read_string(&lkv, + buf, off, ".name", 6, &c->name); + } + key_val_free(&lkv); + } + + len = 5; + memcpy(buf, "event", 5); + off = len; + + a->event = vector_empty(a3da_event); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "event", &lkv)) { + vector_a3da_event* ve = &a->event; + + vector_a3da_event_reserve(ve, count); + ve->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_event* e = &ve->begin[i]; + memset(e, 0, sizeof(a3da_event)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_float_t(&lkv, + buf, off, ".begin", 7, &e->begin); + key_val_read_float_t(&lkv, + buf, off, ".clip_begin", 12, &e->clip_begin); + key_val_read_float_t(&lkv, + buf, off, ".clip_end", 10, &e->clip_end); + key_val_read_float_t(&lkv, + buf, off, ".end", 5, &e->end); + key_val_read_string(&lkv, + buf, off, ".name", 6, &e->name); + key_val_read_string(&lkv, + buf, off, ".param1", 8, &e->param_1); + key_val_read_string(&lkv, + buf, off, ".ref", 5, &e->ref); + key_val_read_float_t(&lkv, + buf, off, ".time_ref_scale", 16, &e->time_ref_scale); + key_val_read_int32_t(&lkv, + buf, off, ".type", 6, (int32_t*)&e->type); + } + key_val_free(&lkv); + } + + len = 3; + memcpy(buf, "fog", 3); + off = len; + + a->fog = vector_empty(a3da_fog); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "fog", &lkv)) { + vector_a3da_fog* vf = &a->fog; + + vector_a3da_fog_reserve(vf, count); + vf->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_fog* f = &vf->begin[i]; + memset(f, 0, sizeof(a3da_fog)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Diffuse", 9, &f->color)) + f->flags |= A3DA_FOG_COLOR; + if (key_val_read_a3da_key(&lkv, + buf, off, ".density", 9, &f->density)) + f->flags |= A3DA_FOG_DENSITY; + if (key_val_read_a3da_key(&lkv, + buf, off, ".end", 5, &f->end)) + f->flags |= A3DA_FOG_END; + key_val_read_int32_t(&lkv, + buf, off, ".id", 4, (int32_t*)&f->id); + string name; + if (key_val_read_string(&lkv, + buf, off, ".name", 7, &name)) { + if (str_utils_compare(string_data(&name), "Z")) + f->id = FOG_DEPTH; + else if (str_utils_compare(string_data(&name), "Height")) + f->id = FOG_HEIGHT; + string_free(&name); + } + if (key_val_read_a3da_key(&lkv, + buf, off, ".start", 7, &f->start)) + f->flags |= A3DA_FOG_START; + } + key_val_free(&lkv); + } + + len = 5; + memcpy(buf, "light", 5); + off = len; + + a->light = vector_empty(a3da_light); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "light", &lkv)) { + vector_a3da_light* vl = &a->light; + + vector_a3da_light_reserve(vl, count); + vl->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_light* l = &vl->begin[i]; + memset(l, 0, sizeof(a3da_light)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Ambient", 9, &l->ambient)) + l->flags |= A3DA_LIGHT_AMBIENT; + if (key_val_read_a3da_key(&lkv, + buf, off, ".ConeAngle", 11, &l->cone_angle)) + l->flags |= A3DA_LIGHT_CONE_ANGLE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".CONSTANT", 10, &l->constant)) + l->flags |= A3DA_LIGHT_CONSTANT; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Diffuse", 9, &l->diffuse)) + l->flags |= A3DA_LIGHT_DIFFUSE; + if (key_val_read_a3da_key(&lkv, + buf, off, ".DropOff", 9, &l->drop_off)) + l->flags |= A3DA_LIGHT_DROP_OFF; + if (key_val_read_a3da_key(&lkv, + buf, off, ".FAR", 5, &l->_far)) + l->flags |= A3DA_LIGHT_FAR; + key_val_read_int32_t(&lkv, + buf, off, ".id", 4, (int32_t*)&l->id); + if (key_val_read_a3da_key(&lkv, + buf, off, ".Intensity", 11, &l->intensity)) + l->flags |= A3DA_LIGHT_INTENSITY; + if (key_val_read_a3da_key(&lkv, + buf, off, ".LINEAR", 8, &l->linear)) + l->flags |= A3DA_LIGHT_LINEAR; + if (key_val_read_a3da_model_transform(&lkv, + buf, off, ".position", 10, &l->position)) + l->flags |= A3DA_LIGHT_POSITION; + if (key_val_read_a3da_key(&lkv, + buf, off, ".QUADRATIC", 11, &l->quadratic)) + l->flags |= A3DA_LIGHT_QUADRATIC; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Specular", 10, &l->specular)) + l->flags |= A3DA_LIGHT_SPECULAR; + if (key_val_read_a3da_model_transform(&lkv, + buf, off, ".spot_direction", 16, &l->spot_direction)) + l->flags |= A3DA_LIGHT_SPOT_DIRECTION; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".Incandescence", 15, &l->tone_curve)) + l->flags |= A3DA_LIGHT_TONE_CURVE; + key_val_read_string(&lkv, + buf, off, ".type", 6, &l->type); + } + key_val_free(&lkv); + } + + len = 8; + memcpy(buf, "m_objhrc", 8); + off = len; + + a->m_object_hrc = vector_empty(a3da_m_object_hrc); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "m_objhrc", &lkv)) { + vector_a3da_m_object_hrc* vmoh = &a->m_object_hrc; + + vector_a3da_m_object_hrc_reserve(vmoh, count); + vmoh->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_m_object_hrc* moh = &vmoh->begin[i]; + memset(moh, 0, sizeof(a3da_m_object_hrc)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + len2 = 9; + memcpy(buf + len + len1, ".instance", 9); + off = len + len1 + len2; + + buf[off] = 0; + key_val sub_local_key_val; + if (key_val_read_int32_t(&lkv, buf, off, ".length", 8, &count1) + && key_val_get_local_key_val(&lkv, buf, &sub_local_key_val) ) { + vector_a3da_object_instance* voi = &moh->instance; + + vector_a3da_object_instance_reserve(voi, count1); + voi->end += count1; + for (int32_t j = 0; j < count1; j++) { + a3da_object_instance* oi = &voi->begin[j]; + memset(oi, 0, sizeof(a3da_object_instance)); + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", j); + off = len + len1 + len2 + len3; + + key_val_read_a3da_model_transform(&sub_local_key_val, + buf, off, "", 1, &oi->model_transform); + key_val_read_string(&sub_local_key_val, + buf, off, ".name", 6, &oi->name); + key_val_read_bool(&sub_local_key_val, + buf, off, ".shadow", 8, &oi->shadow); + key_val_read_string(&sub_local_key_val, + buf, off, ".uid_name", 10, &oi->uid_name); + } + key_val_free(&sub_local_key_val); + } + + off = len + len1; + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &moh->model_transform); + key_val_read_string(&lkv, + buf, off, ".name", 6, &moh->name); + + len2 = 5; + memcpy(buf + len + len1, ".node", 5); + off = len + len1 + len2; + + buf[off] = 0; + if (key_val_read_int32_t(&lkv, buf, off, ".length", 8, &count1) + && key_val_get_local_key_val(&lkv, buf, &sub_local_key_val)) { + vector_a3da_object_node* vmohn = &moh->node; + + vector_a3da_object_node_reserve(vmohn, count1); + vmohn->end += count1; + for (int32_t j = 0; j < count1; j++) { + a3da_object_node* mohn = &vmohn->begin[j]; + memset(mohn, 0, sizeof(a3da_object_node)); + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", j); + off = len + len1 + len2 + len3; + + if (key_val_read_vec3(&sub_local_key_val, + buf, off, ".joint_orient", 14, &mohn->joint_orient)) + mohn->flags |= A3DA_OBJECT_NODE_JOINT_ORIENT; + key_val_read_a3da_model_transform(&sub_local_key_val, + buf, off, "", 1, &mohn->model_transform); + key_val_read_string(&sub_local_key_val, + buf, off, ".name", 6, &mohn->name); + key_val_read_int32_t(&sub_local_key_val, + buf, off, ".parent", 8, &mohn->parent); + } + key_val_free(&sub_local_key_val); + } + } + key_val_free(&lkv); + } + + len = 13; + memcpy(buf, "m_objhrc_list", 13); + off = len; + + a->m_object_hrc_list = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "m_objhrc_list", &lkv)) { + vector_string* vmohl = &a->m_object_hrc_list; + + vector_string_reserve(vmohl, count); + vmohl->end += count; + for (int32_t i = 0; i < count; i++) { + string* mohl = &vmohl->begin[i]; + *mohl = string_empty; + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, "", 1, mohl); + } + key_val_free(&lkv); + } + + len = 13; + memcpy(buf, "material_list", 13); + off = len; + + a->material_list = vector_empty(a3da_material_list); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "material_list", &lkv)) { + vector_a3da_material_list* vml = &a->material_list; + + vector_a3da_material_list_reserve(vml, count); + vml->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_material_list* ml = &vml->begin[i]; + memset(ml, 0, sizeof(a3da_material_list)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".blend_color", 15, &ml->blend_color)) + ml->flags |= A3DA_MATERIAL_LIST_BLEND_COLOR; + if (key_val_read_a3da_key(&lkv, + buf, off, ".glow_intensity", 15, &ml->glow_intensity)) + ml->flags |= A3DA_MATERIAL_LIST_GLOW_INTENSITY; + if (key_val_read_a3da_rgba(&lkv, + buf, off, ".incandescence", 15, &ml->incandescence)) + ml->flags |= A3DA_MATERIAL_LIST_INCANDESCENCE; + key_val_read_string(&lkv, + buf, off, ".name", 6, &ml->name); + } + key_val_free(&lkv); + } + + len = 6; + memcpy(buf, "motion", 6); + off = len; + + a->motion = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "motion", &lkv)) { + vector_string* vm = &a->motion; + + vector_string_reserve(vm, count); + vm->end += count; + for (int32_t i = 0; i < count; i++) { + string* m = &vm->begin[i]; + *m = string_empty; + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, "", 1, m); + } + key_val_free(&lkv); + } + + len = 6; + memcpy(buf, "object", 6); + off = len; + + a->object = vector_empty(a3da_object); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "object", &lkv)) { + vector_a3da_object* vo = &a->object; + + vector_a3da_object_reserve(vo, count); + vo->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_object* o = &vo->begin[i]; + memset(o, 0, sizeof(a3da_object)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &o->model_transform); + if (key_val_read_string(&lkv, + buf, off, ".morph", 7, &o->morph)) + key_val_read_float_t(&lkv, + buf, off, ".morph_offset", 14, &o->morph_offset); + key_val_read_string(&lkv, + buf, off, ".name", 6, &o->name); + key_val_read_string(&lkv, + buf, off, ".parent_name", 13, &o->parent_name); + key_val_read_string(&lkv, + buf, off, ".parent_node", 13, &o->parent_node); + if (key_val_read_string(&lkv, + buf, off, ".pat", 5, &o->pattern)) + key_val_read_float_t(&lkv, + buf, off, ".pat_offset", 12, &o->pattern_offset); + + len2 = 8; + memcpy(buf + len + len1, ".tex_pat", 8); + off = len + len1 + len2; + + buf[off] = 0; + key_val sub_local_key_val; + if (key_val_read_int32_t(&lkv, buf, off, ".length", 8, &count1) + && key_val_get_local_key_val(&lkv, buf, &sub_local_key_val)) { + vector_a3da_object_texture_pattern* votp = &o->texture_pattern; + + vector_a3da_object_texture_pattern_reserve(votp, count1); + votp->end += count1; + for (int32_t j = 0; j < count1; j++) { + a3da_object_texture_pattern* otp = &votp->begin[j]; + memset(otp, 0, sizeof(a3da_object_texture_pattern)); + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", j); + off = len + len1 + len2 + len3; + + key_val_read_string(&sub_local_key_val, + buf, off, ".name", 6, &otp->name); + if (key_val_read_string(&sub_local_key_val, + buf, off, ".pat", 5, &otp->pattern)) + key_val_read_float_t(&sub_local_key_val, + buf, off, ".pat_offset", 12, &otp->pattern_offset); + } + key_val_free(&sub_local_key_val); + } + + len2 = 14; + memcpy(buf + len + len1, ".tex_transform", 14); + off = len + len1 + len2; + + buf[off] = 0; + if (key_val_read_int32_t(&lkv, buf, off, ".length", 8, &count1) + && key_val_get_local_key_val(&lkv, buf, &sub_local_key_val)) { + vector_a3da_object_texture_transform* vott = &o->texture_transform; + + vector_a3da_object_texture_transform_reserve(vott, count1); + vott->end += count1; + for (int32_t j = 0; j < count1; j++) { + a3da_object_texture_transform* ott = &vott->begin[j]; + memset(ott, 0, sizeof(a3da_object_texture_transform)); + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", j); + off = len + len1 + len2 + len3; + + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".coverageU", 11, &ott->coverage_u)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".coverageV", 11, &ott->coverage_v)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V; + key_val_read_string(&sub_local_key_val, + buf, off, ".name", 6, &ott->name); + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".offsetU", 9, &ott->offset_u)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".offsetV", 9, &ott->offset_v)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".repeatU", 9, &ott->repeat_u)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".repeatV", 9, &ott->repeat_v)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".rotate", 8, &ott->rotate)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".rotateFrame", 13, &ott->rotate_frame)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".translateFrameU", 17, &ott->translate_frame_u)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U; + if (key_val_read_a3da_key(&sub_local_key_val, + buf, off, ".translateFrameV", 17, &ott->translate_frame_v)) + ott->flags |= A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V; + } + key_val_free(&sub_local_key_val); + } + + off = len + len1; + key_val_read_string(&lkv, + buf, off, ".uid_name", 10, &o->uid_name); + } + key_val_free(&lkv); + } + + len = 6; + memcpy(buf, "objhrc", 6); + off = len; + + a->object_hrc = vector_empty(a3da_object_hrc); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "objhrc", &lkv)) { + vector_a3da_object_hrc* voh = &a->object_hrc; + + vector_a3da_object_hrc_reserve(voh, count); + voh->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_object_hrc* oh = &voh->begin[i]; + memset(oh, 0, sizeof(a3da_object_hrc)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, ".name", 6, &oh->name); + + len2 = 5; + memcpy(buf + len + len1, ".node", 5); + off = len + len1 + len2; + + buf[off] = 0; + key_val sub_local_key_val; + if (key_val_read_int32_t(&lkv, buf, off, ".length", 8, &count1) + && key_val_get_local_key_val(&lkv, buf, &sub_local_key_val)) { + vector_a3da_object_node* vohn = &oh->node; + + vector_a3da_object_node_reserve(vohn, count1); + vohn->end += count1; + for (int32_t j = 0; j < count1; j++) { + a3da_object_node* ohn = &vohn->begin[j]; + memset(ohn, 0, sizeof(a3da_object_node)); + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", j); + off = len + len1 + len2 + len3; + + if (key_val_read_vec3(&sub_local_key_val, + buf, off, ".joint_orient", 14, &ohn->joint_orient)) + ohn->flags |= A3DA_OBJECT_NODE_JOINT_ORIENT; + key_val_read_a3da_model_transform(&sub_local_key_val, + buf, off, "", 1, &ohn->model_transform); + key_val_read_string(&sub_local_key_val, + buf, off, ".name", 6, &ohn->name); + key_val_read_int32_t(&sub_local_key_val, + buf, off, ".parent", 8, &ohn->parent); + } + key_val_free(&sub_local_key_val); + } + + off = len + len1; + key_val_read_string(&lkv, + buf, off, ".parent_name", 13, &oh->parent_name); + key_val_read_string(&lkv, + buf, off, ".parent_node", 13, &oh->parent_node); + key_val_read_bool(&lkv, + buf, off, ".shadow", 8, &oh->shadow); + key_val_read_string(&lkv, + buf, off, ".uid_name", 10, &oh->uid_name); + } + key_val_free(&lkv); + } + + len = 11; + memcpy(buf, "objhrc_list", 11); + off = len; + + a->object_hrc_list = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "objhrc_list", &lkv)) { + vector_string* vohl = &a->object_hrc_list; + + vector_string_reserve(vohl, count); + vohl->end += count; + for (int32_t i = 0; i < count; i++) { + string* ohl = &vohl->begin[i]; + *ohl = string_empty; + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, "", 1, ohl); + } + key_val_free(&lkv); + } + + len = 11; + memcpy(buf, "object_list", 11); + off = len; + + a->object_list = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "object_list", &lkv)) { + vector_string* vol = &a->object_list; + + vector_string_reserve(vol, count); + vol->end += count; + for (int32_t i = 0; i < count; i++) { + string* ol = &vol->begin[i]; + *ol = string_empty; + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, "", 1, ol); + } + key_val_free(&lkv); + } + + len = 5; + memcpy(buf, "point", 5); + off = len; + + a->point = vector_empty(a3da_point); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "point", &lkv)) { + vector_a3da_point* vp = &a->point; + + vector_a3da_point_reserve(vp, count); + vp->end += count; + for (int32_t i = 0; i < count; i++) { + a3da_point* p = &vp->begin[i]; + memset(p, 0, sizeof(a3da_point)); + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_a3da_model_transform(&lkv, + buf, off, "", 1, &p->model_transform); + key_val_read_string(&lkv, + buf, off, ".name", 6, &p->name); + } + key_val_free(&lkv); + } + + key_val_free(&kv); +} + +static void a3da_write_text(a3da* a, void** data, size_t* length, bool a3dc) { + char buf[A3DA_TEXT_BUF_SIZE]; + int32_t count; + int32_t count1; + size_t len; + size_t len1; + size_t len2; + size_t len3; + size_t off; + + char a3da_timestamp[0x100]; + a3da_get_time_stamp(a3da_timestamp, 0x100); + + stream s; + io_mopen(&s, 0, 0); + + if (a3dc) { + if (a->_compress_f16 != A3DA_COMPRESS_F32F32F32F32) + io_write(&s, "#-compress_f16\n", 15); + } + else + io_write(&s, "#A3DA__________\n", 16); + + io_write(&s, a3da_timestamp, utf8_length(a3da_timestamp)); + + len = 1; + memcpy(buf, "_", 1); + off = len; + + if (a3dc && a->format > A3DA_FORMAT_AFT) + key_val_write_int32_t(&s, buf, off, ".compress_f16", 14, a->_compress_f16); + key_val_write_string(&s, buf, off, ".converter.version", 19, &a->_converter_version); + key_val_write_string(&s, buf, off, ".file_name", 11, &a->_file_name); + key_val_write_string(&s, buf, off, ".property.version", 18, &a->_property_version); + + vector_int32_t sort_index = vector_empty(int32_t); + vector_int32_t sort_index1 = vector_empty(int32_t); + if (a->ambient.end - a->ambient.begin && a->format == A3DA_FORMAT_MGF) { + len = 7; + memcpy(buf, "ambient", 7); + off = len; + + vector_a3da_ambient* va = &a->ambient; + count = (int32_t)(va->end - va->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_ambient* a = &va->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + if (a->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) + key_val_write_a3da_rgba(&s, + buf, off, ".light.Diffuse", 15, &a->light_diffuse); + key_val_write_string(&s, buf, off, ".name", 6, &a->name); + if (a->flags & A3DA_AMBIENT_RIM_LIGHT_DIFFUSE) + key_val_write_a3da_rgba(&s, + buf, off, ".rimlight.Diffuse", 18, &a->rim_light_diffuse); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->auth_2d.end - a->auth_2d.begin) { + len = 7; + memcpy(buf, "auth_2d", 7); + off = len; + + vector_string* va2 = &a->auth_2d; + count = (int32_t)(va2->end - va2->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* a2 = &va2->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, ".name", 6, a2); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->camera_auxiliary.flags) { + len = 16; + memcpy(buf, "camera_auxiliary", 16); + off = len; + + a3da_camera_auxiliary* ca = &a->camera_auxiliary; + if (a->format == A3DA_FORMAT_F || a->format > A3DA_FORMAT_AFT) { + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE) + key_val_write_a3da_key(&s, buf, off, ".exposure_rate", 15, &ca->exposure_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA_RATE) + key_val_write_a3da_key(&s, buf, off, ".gamma_rate", 12, &ca->gamma_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_SATURATE) + key_val_write_a3da_key(&s, buf, off, ".saturate", 10, &ca->saturate); + } + else { + if (ca->flags & A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE) + key_val_write_a3da_key(&s, buf, off, ".auto_exposure", 15, &ca->auto_exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE) + key_val_write_a3da_key(&s, buf, off, ".exposure", 10, &ca->exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA) + key_val_write_a3da_key(&s, buf, off, ".gamma", 7, &ca->gamma); + if (ca->flags & A3DA_CAMERA_AUXILIARY_SATURATE) + key_val_write_a3da_key(&s, buf, off, ".saturate", 10, &ca->saturate); + } + } + + if (a->camera_root.end - a->camera_root.begin) { + len = 11; + memcpy(buf, "camera_root", 11); + off = len; + + vector_a3da_camera_root* vcr = &a->camera_root; + count = (int32_t)(vcr->end - vcr->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_camera_root* cr = &vcr->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_a3da_model_transform(&s, + buf, off, ".interest", 10, &cr->interest, 0x1F); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &cr->model_transform, 0x1E); + + a3da_camera_root_view_point* vp = &cr->view_point; + + len2 = 11; + memcpy(buf + len + len1, ".view_point", 11); + off = len + len1 + len2; + + key_val_write_float_t(&s, + buf, off, ".aspect", 8, vp->aspect); + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_FOV) { + key_val_write_a3da_key(&s, + buf, off, ".fov", 5, &vp->fov); + key_val_write_bool(&s, + buf, off, ".fov_is_horizontal", 19, vp->fov_is_horizontal); + } + else { + key_val_write_float_t(&s, + buf, off, ".camera_aperture_h", 19, vp->camera_aperture_h); + key_val_write_float_t(&s, + buf, off, ".camera_aperture_w", 19, vp->camera_aperture_w); + key_val_write_a3da_key(&s, + buf, off, ".focal_length", 14, &vp->focal_length); + } + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &vp->model_transform, 0x10); + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_ROLL) + key_val_write_a3da_key(&s, + buf, off, ".roll", 6, &vp->roll); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &vp->model_transform, 0x0F); + + off = len + len1; + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &cr->model_transform, 0x01); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->chara.end - a->chara.begin) { + len = 5; + memcpy(buf, "chara", 5); + off = len; + + vector_a3da_chara* vc = &a->chara; + count = (int32_t)(vc->end - vc->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_chara* c = &vc->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, ".name", 6, &c->name); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &c->model_transform, 0x1F); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->curve.end - a->curve.begin) { + len = 5; + memcpy(buf, "curve", 5); + off = len; + + vector_a3da_curve* vc = &a->curve; + count = (int32_t)(vc->end - vc->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_curve* c = &vc->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_a3da_key(&s, buf, off, ".cv", 4, &c->curve); + key_val_write_string(&s, buf, off, ".name", 6, &c->name); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->dof.has_dof && a->format == A3DA_FORMAT_AFT) { + len = 3; + memcpy(buf, "dof", 3); + off = len; + + a3da_dof* d = &a->dof; + + key_val_write_string_ptr(&s, buf, off, ".name", 6, "DOF"); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &d->model_transform, 0x1F); + } + + if (a->event.end - a->event.begin) { + len = 5; + memcpy(buf, "event", 5); + off = len; + + vector_a3da_event* ve = &a->event; + count = (int32_t)(ve->end - ve->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_event* e = &ve->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_float_t(&s, buf, off, ".begin", 7, e->begin); + key_val_write_float_t(&s, buf, off, ".clip_begin", 12, e->clip_begin); + key_val_write_float_t(&s, buf, off, ".clip_en", 9, e->clip_end); + key_val_write_float_t(&s, buf, off, ".end", 5, e->end); + key_val_write_string(&s, buf, off, ".name", 6, &e->name); + key_val_write_string(&s, buf, off, ".param1", 8, &e->param_1); + key_val_write_string(&s, buf, off, ".ref", 5, &e->ref); + key_val_write_float_t(&s, buf, off, ".time_ref_scale", 16, e->time_ref_scale); + key_val_write_int32_t(&s, buf, off, ".type", 6, e->type); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->fog.end - a->fog.begin) { + len = 3; + memcpy(buf, "fog", 3); + off = len; + + vector_a3da_fog* vf = &a->fog; + count = (int32_t)(vf->end - vf->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_fog* f = &vf->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + if (f->flags & A3DA_FOG_COLOR) + key_val_write_a3da_rgba(&s, buf, off, ".Diffuse", 9, &f->color); + if (f->flags & A3DA_FOG_DENSITY) + key_val_write_a3da_key(&s, buf, off, ".density", 4, &f->density); + if (f->flags & A3DA_FOG_END) + key_val_write_a3da_key(&s, buf, off, ".end", 5, &f->end); + key_val_write_int32_t(&s, buf, off, ".id", 4, f->id); + if (f->flags & A3DA_FOG_START) + key_val_write_a3da_key(&s, buf, off, ".start", 7, &f->start); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->light.end - a->light.begin) { + len = 5; + memcpy(buf, "light", 5); + off = len; + + bool xhd = a->format == A3DA_FORMAT_XHD; + + vector_a3da_light* vl = &a->light; + count = (int32_t)(vl->end - vl->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_light* l = &vl->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + if (l->flags & A3DA_LIGHT_AMBIENT) + key_val_write_a3da_rgba(&s, + buf, off, ".Ambient", 9, &l->ambient); + if (l->flags & A3DA_LIGHT_CONSTANT && xhd) + key_val_write_a3da_key(&s, + buf, off, ".CONSTANT", 10, &l->constant); + if (l->flags & A3DA_LIGHT_CONE_ANGLE && xhd) + key_val_write_a3da_key(&s, + buf, off, ".ConeAngle", 11, &l->cone_angle); + if (l->flags & A3DA_LIGHT_DIFFUSE) + key_val_write_a3da_rgba(&s, + buf, off, ".Diffuse", 9, &l->diffuse); + if (l->flags & A3DA_LIGHT_DROP_OFF && xhd) + key_val_write_a3da_key(&s, + buf, off, ".DropOff", 9, &l->drop_off); + if (l->flags & A3DA_LIGHT_FAR && xhd) + key_val_write_a3da_key(&s, + buf, off, ".FAR", 5, &l->_far); + if (l->flags & A3DA_LIGHT_TONE_CURVE) + key_val_write_a3da_rgba(&s, + buf, off, ".Incandescence", 15, &l->tone_curve); + if (l->flags & A3DA_LIGHT_INTENSITY && xhd) + key_val_write_a3da_key(&s, + buf, off, ".Intensity", 9, &l->intensity); + if (l->flags & A3DA_LIGHT_LINEAR && xhd) + key_val_write_a3da_key(&s, + buf, off, ".LINEAR", 6, &l->linear); + if (l->flags & A3DA_LIGHT_QUADRATIC && xhd) + key_val_write_a3da_key(&s, + buf, off, ".QUADRATIC", 11, &l->quadratic); + if (l->flags & A3DA_LIGHT_SPECULAR) + key_val_write_a3da_rgba(&s, + buf, off, ".Specular", 10, &l->specular); + key_val_write_int32_t(&s, + buf, off, ".id", 4, l->id); + char* name = "none"; + switch (l->id) { + case LIGHT_CHARA: + name = "Char"; + break; + case LIGHT_STAGE: + name = "Stage"; + break; + case LIGHT_SUN: + name = "Sun"; + break; + case LIGHT_REFLECT: + name = "Reflect"; + break; + case LIGHT_CHARA_COLOR: + name = "CharColor"; + break; + case LIGHT_TONE_CURVE: + name = "ToneCurve"; + break; + } + key_val_write_string_ptr(&s, + buf, off, ".name", 6, name); + if (l->flags & A3DA_LIGHT_POSITION) + key_val_write_a3da_model_transform(&s, + buf, off, ".position", 9, &l->position, 0x1F); + if (l->flags & A3DA_LIGHT_SPOT_DIRECTION) + key_val_write_a3da_model_transform(&s, + buf, off, ".spot_direction", 9, &l->spot_direction, 0x1F); + key_val_write_string(&s, + buf, off, ".type", 6, &l->type); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->m_object_hrc.end - a->m_object_hrc.begin) { + len = 8; + memcpy(buf, "m_objhrc", 8); + off = len; + + vector_a3da_m_object_hrc* vmoh = &a->m_object_hrc; + count = (int32_t)(vmoh->end - vmoh->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_m_object_hrc* moh = &vmoh->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + len2 = 9; + memcpy(buf + len + len1, ".instance", 9); + off = len + len1 + len2; + + vector_a3da_object_instance* voi = &moh->instance; + count1 = (int32_t)(voi->end - voi->begin); + key_val_get_lexicographic_order(&sort_index1, count1); + for (int32_t j = 0; j < count; j++) { + a3da_object_instance* oi = &voi->begin[sort_index1.begin[i]]; + + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", sort_index.begin[j]); + off = len + len1 + len2 + len3; + + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &oi->model_transform, 0x10); + key_val_write_string(&s, + buf, off, ".name", 6, &oi->name); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &oi->model_transform, 0x0C); + key_val_write_bool(&s, + buf, off, ".shadow", 6, &oi->shadow); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &oi->model_transform, 0x02); + key_val_write_string(&s, + buf, off, ".uid_name", 10, &oi->uid_name); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &oi->model_transform, 0x01); + } + + off = len + len1 + len2; + key_val_write_int32_t(&s, buf, off, ".length", 8, count1); + + off = len + len1; + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &moh->model_transform, 0x10); + key_val_write_string(&s, + buf, off, ".name", 6, &moh->name); + + len2 = 5; + memcpy(buf + len + len1, ".node", 5); + off = len + len1 + len2; + + vector_a3da_object_node* vmohn = &moh->node; + count1 = (int32_t)(vmohn->end - vmohn->begin); + key_val_get_lexicographic_order(&sort_index1, count1); + for (int32_t j = 0; j < count; j++) { + a3da_object_node* mohn = &vmohn->begin[sort_index1.begin[i]]; + + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", sort_index.begin[j]); + off = len + len1 + len2 + len3; + + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &mohn->model_transform, 0x10); + if (mohn->flags & A3DA_OBJECT_NODE_JOINT_ORIENT) + key_val_write_vec3(&s, + buf, off, ".joint_orient", 14, &mohn->joint_orient); + key_val_write_string(&s, + buf, off, ".name", 6, &mohn->name); + key_val_write_int32_t(&s, + buf, off, ".parent", 8, mohn->parent); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &mohn->model_transform, 0x0F); + } + + off = len + len1 + len2; + key_val_write_int32_t(&s, buf, off, ".length", 8, count1); + + off = len + len1; + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &moh->model_transform, 0x0F); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->m_object_hrc_list.end - a->m_object_hrc_list.begin) { + len = 13; + memcpy(buf, "m_objhrc_list", 13); + off = len; + + vector_string* vmohl = &a->m_object_hrc_list; + count = (int32_t)(vmohl->end - vmohl->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* mohl = &vmohl->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, "", 1, mohl); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->material_list.end - a->material_list.begin + && (a->format == A3DA_FORMAT_X || a->format == A3DA_FORMAT_XHD)) { + len = 13; + memcpy(buf, "material_list", 13); + off = len; + + vector_a3da_material_list* vml = &a->material_list; + count = (int32_t)(vml->end - vml->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_material_list* ml = &vml->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + if (ml->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + key_val_write_a3da_rgba(&s, buf, off, ".blend_color", 13, &ml->blend_color); + if (ml->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + key_val_write_a3da_key(&s, buf, off, ".glow_intensity", 16, &ml->glow_intensity); + key_val_write_uint32_t(&s, buf, off, ".hash_name", 11, + hash_murmurhash(string_data(&ml->name), ml->name.length, 0, false, false)); + if (ml->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + key_val_write_a3da_rgba(&s, buf, off, ".incandescence", 15, &ml->incandescence); + key_val_write_string(&s, buf, off, ".name", 6, &ml->name); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->motion.end - a->motion.begin) { + len = 6; + memcpy(buf, "motion", 6); + off = len; + + vector_string* vm = &a->motion; + count = (int32_t)(vm->end - vm->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* m = &vm->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, "", 1, m); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->object.end - a->object.begin) { + len = 6; + memcpy(buf, "object", 6); + off = len; + + vector_a3da_object* vo = &a->object; + count = (int32_t)(vo->end - vo->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_object* o = &vo->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &o->model_transform, 0x10); + if (string_data(&o->morph)) { + key_val_write_string(&s, + buf, off, ".morph", 7, &o->morph); + key_val_write_float_t(&s, + buf, off, ".morph_offset", 14, o->morph_offset); + } + key_val_write_string(&s, + buf, off, ".name", 6, &o->name); + key_val_write_string(&s, + buf, off, ".parent_name", 13, &o->parent_name); + key_val_write_string(&s, + buf, off, ".parent_node", 13, &o->parent_node); + if (string_data(&o->pattern)) { + key_val_write_string(&s, + buf, off, ".pat", 5, &o->pattern); + key_val_write_float_t(&s, + buf, off, ".pat_offset", 12, o->pattern_offset); + } + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &o->model_transform, 0x0C); + + len2 = 8; + memcpy(buf + len + len1, ".tex_pat", 8); + off = len + len1 + len2; + + vector_a3da_object_texture_pattern* votp = &o->texture_pattern; + count1 = (int32_t)(votp->end - votp->begin); + key_val_get_lexicographic_order(&sort_index1, count1); + for (int32_t j = 0; j < count; j++) { + a3da_object_texture_pattern* otp = &votp->begin[sort_index1.begin[i]]; + + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", sort_index.begin[j]); + off = len + len1 + len2 + len3; + + key_val_write_string(&s, + buf, off, ".name", 6, &otp->name); + if (string_data(&otp->pattern)) { + key_val_write_string(&s, + buf, off, ".pat", 5, &otp->pattern); + key_val_write_float_t(&s, + buf, off, ".pat_offset", 12, otp->pattern_offset); + } + } + + off = len + len1 + len2; + key_val_write_int32_t(&s, buf, off, ".length", 8, count1); + + len2 = 14; + memcpy(buf + len + len1, ".tex_transform", 14); + off = len + len1 + len2; + + vector_a3da_object_texture_transform* vott = &o->texture_transform; + count1 = (int32_t)(vott->end - vott->begin); + key_val_get_lexicographic_order(&sort_index1, count1); + for (int32_t j = 0; j < count; j++) { + a3da_object_texture_transform* ott = &vott->begin[sort_index1.begin[i]]; + + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", sort_index.begin[j]); + off = len + len1 + len2 + len3; + + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + key_val_write_a3da_key(&s, + buf, off, ".coverageU", 11, &ott->coverage_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + key_val_write_a3da_key(&s, + buf, off, ".coverageV", 11, &ott->coverage_v); + key_val_write_string(&s, + buf, off, ".name", 6, &ott->name); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + key_val_write_a3da_key(&s, + buf, off, ".offsetU", 9, &ott->offset_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + key_val_write_a3da_key(&s, + buf, off, ".offsetV", 9, &ott->offset_v); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + key_val_write_a3da_key(&s, + buf, off, ".repeatU", 9, &ott->repeat_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + key_val_write_a3da_key(&s, + buf, off, ".repeatV", 9, &ott->repeat_v); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE) + key_val_write_a3da_key(&s, + buf, off, ".rotate", 8, &ott->rotate); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + key_val_write_a3da_key(&s, + buf, off, ".rotateFrame", 13, &ott->rotate_frame); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + key_val_write_a3da_key(&s, + buf, off, ".translateFrameU", 17, &ott->translate_frame_u); + if (ott->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + key_val_write_a3da_key(&s, + buf, off, ".translateFrameV", 17, &ott->translate_frame_v); + } + + off = len + len1 + len2; + key_val_write_int32_t(&s, buf, off, ".length", 8, count1); + + off = len + len1; + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &o->model_transform, 0x02); + key_val_write_string(&s, + buf, off, ".uid_name", 10, &o->uid_name); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &o->model_transform, 0x01); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->object_list.end - a->object_list.begin) { + len = 11; + memcpy(buf, "object_list", 11); + off = len; + + vector_string* vol = &a->object_list; + count = (int32_t)(vol->end - vol->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* ol = &vol->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, "", 1, ol); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->object_hrc.end - a->object_hrc.begin) { + len = 6; + memcpy(buf, "objhrc", 6); + off = len; + + vector_a3da_object_hrc* voh = &a->object_hrc; + count = (int32_t)(voh->end - voh->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_object_hrc* oh = &voh->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, + buf, off, ".name", 6, &oh->name); + + len2 = 5; + memcpy(buf + len + len1, ".node", 5); + off = len + len1 + len2; + + vector_a3da_object_node* vohn = &oh->node; + count1 = (int32_t)(vohn->end - vohn->begin); + key_val_get_lexicographic_order(&sort_index1, count1); + for (int32_t j = 0; j < count; j++) { + a3da_object_node* ohn = &vohn->begin[sort_index1.begin[i]]; + + len3 = sprintf_s(buf + len + len1 + len2, + A3DA_TEXT_BUF_SIZE - len - len1 - len2, ".%d", sort_index.begin[j]); + off = len + len1 + len2 + len3; + + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &ohn->model_transform, 0x10); + if (ohn->flags & A3DA_OBJECT_NODE_JOINT_ORIENT) + key_val_write_vec3(&s, + buf, off, ".joint_orient", 14, &ohn->joint_orient); + key_val_write_string(&s, + buf, off, ".name", 6, &ohn->name); + key_val_write_int32_t(&s, + buf, off, ".parent", 8, ohn->parent); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &ohn->model_transform, 0x0F); + } + + off = len + len1 + len2; + key_val_write_int32_t(&s, buf, off, ".length", 8, count1); + + off = len + len1; + key_val_write_string(&s, + buf, off, ".parent_name", 13, &oh->parent_name); + key_val_write_string(&s, + buf, off, ".parent_node", 13, &oh->parent_node); + key_val_write_bool(&s, + buf, off, ".shadow", 6, &oh->shadow); + key_val_write_string(&s, + buf, off, ".uid_name", 10, &oh->uid_name); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (a->object_hrc_list.end - a->object_hrc_list.begin) { + len = 11; + memcpy(buf, "objhrc_list", 11); + off = len; + + vector_string* vohl = &a->object_hrc_list; + count = (int32_t)(vohl->end - vohl->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* ohl = &vohl->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, "", 1, ohl); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + { + a3da_play_control* pc = &a->play_control; + + len = 12; + memcpy(buf, "play_control", 12); + off = len; + + key_val_write_float_t(&s, + buf, off, ".begin", 6, pc->begin); + if (pc->flags & A3DA_PLAY_CONTROL_DIV && a->format > A3DA_FORMAT_AFT) + key_val_write_int32_t(&s, + buf, off, ".div", 5, pc->div); + key_val_write_float_t(&s, + buf, off, ".fps", 5, pc->fps); + if (pc->flags & A3DA_PLAY_CONTROL_OFFSET) { + if (a->format > A3DA_FORMAT_AFT) { + key_val_write_float_t(&s, + buf, off, ".offset", 8, pc->offset); + key_val_write_float_t(&s, + buf, off, ".size", 6, pc->size); + } + else + key_val_write_float_t(&s, + buf, off, ".size", 6, pc->size + pc->offset); + } + else + key_val_write_float_t(&s, + buf, off, ".size", 6, pc->size); + } + + if (a->post_process.flags) { + len = 12; + memcpy(buf, "post_process", 12); + off = len; + + a3da_post_process* pp = &a->post_process; + if (a->post_process.flags & A3DA_POST_PROCESS_RADIUS) + key_val_write_a3da_rgba(&s, buf, off, ".Ambient", 9, &pp->radius); + if (a->post_process.flags & A3DA_POST_PROCESS_INTENSITY) + key_val_write_a3da_rgba(&s, buf, off, ".Diffuse", 9, &pp->intensity); + if (a->post_process.flags & A3DA_POST_PROCESS_SCENE_FADE) + key_val_write_a3da_rgba(&s, buf, off, ".Specular", 10, &pp->scene_fade); + if (a->post_process.flags & A3DA_POST_PROCESS_LENS_FLARE) + key_val_write_a3da_key(&s, buf, off, ".lens_flare", 12, &pp->lens_flare); + if (a->post_process.flags & A3DA_POST_PROCESS_LENS_GHOST) + key_val_write_a3da_key(&s, buf, off, ".lens_ghost", 12, &pp->lens_ghost); + if (a->post_process.flags & A3DA_POST_PROCESS_LENS_SHAFT) + key_val_write_a3da_key(&s, buf, off, ".lens_shaft", 12, &pp->lens_shaft); + } + + if (a->point.end - a->point.begin) { + len = 5; + memcpy(buf, "point", 5); + off = len; + + vector_a3da_point* vp = &a->point; + count = (int32_t)(vp->end - vp->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + a3da_point* p = &vp->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, ".name", 6, &p->name); + key_val_write_a3da_model_transform(&s, + buf, off, "", 1, &p->model_transform, 0x1F); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + vector_int32_t_free(&sort_index1, 0); + vector_int32_t_free(&sort_index, 0); + + io_mcopy(&s, data, length); + io_free(&s); +} + +static void a3da_read_data(a3da* a, void* data, size_t length) { + for (a3da_ambient* i = a->ambient.begin; i != a->ambient.end; i++) { + if (i->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) + a3dc_read_a3da_rgba(data, length, &i->light_diffuse); + if (i->flags & A3DA_AMBIENT_RIM_LIGHT_DIFFUSE) + a3dc_read_a3da_rgba(data, length, &i->rim_light_diffuse); + } + + if (a->camera_auxiliary.flags) { + a3da_camera_auxiliary* ca = &a->camera_auxiliary; + + if (ca->flags & A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE) + a3dc_read_a3da_key(data, length, &ca->auto_exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE) + a3dc_read_a3da_key(data, length, &ca->exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE) + a3dc_read_a3da_key(data, length, &ca->exposure_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA) + a3dc_read_a3da_key(data, length, &ca->gamma); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA_RATE) + a3dc_read_a3da_key(data, length, &ca->gamma_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_SATURATE) + a3dc_read_a3da_key(data, length, &ca->saturate); + } + + for (a3da_camera_root* i = a->camera_root.begin; i != a->camera_root.end; i++) { + a3dc_read_a3da_model_transform(data, length, &i->interest, a->_compress_f16); + a3dc_read_a3da_model_transform(data, length, &i->model_transform, a->_compress_f16); + + a3da_camera_root_view_point* vp = &i->view_point; + + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_FOV) + a3dc_read_a3da_key(data, length, &vp->fov); + else + a3dc_read_a3da_key(data, length, &vp->focal_length); + a3dc_read_a3da_model_transform(data, length, &vp->model_transform, a->_compress_f16); + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_ROLL) + a3dc_read_a3da_key(data, length, &vp->roll); + } + + for (a3da_chara* i = a->chara.begin; i != a->chara.end; i++) + a3dc_read_a3da_model_transform(data, length, &i->model_transform, a->_compress_f16); + + for (a3da_curve* i = a->curve.begin; i != a->curve.end; i++) + a3dc_read_a3da_key(data, length, &i->curve); + + if (a->dof.has_dof) { + a3da_dof* d = &a->dof; + + a3dc_read_a3da_model_transform(data, length, &d->model_transform, a->_compress_f16); + } + + for (a3da_fog* i = a->fog.begin; i != a->fog.end; i++) { + if (i->flags & A3DA_FOG_COLOR) + a3dc_read_a3da_rgba(data, length, &i->color); + if (i->flags & A3DA_FOG_DENSITY) + a3dc_read_a3da_key(data, length, &i->density); + if (i->flags & A3DA_FOG_END) + a3dc_read_a3da_key(data, length, &i->end); + if (i->flags & A3DA_FOG_START) + a3dc_read_a3da_key(data, length, &i->start); + } + + for (a3da_light* i = a->light.begin; i != a->light.end; i++) { + if (i->flags & A3DA_LIGHT_AMBIENT) + a3dc_read_a3da_rgba(data, length, &i->ambient); + if (i->flags & A3DA_LIGHT_CONE_ANGLE) + a3dc_read_a3da_key(data, length, &i->cone_angle); + if (i->flags & A3DA_LIGHT_CONSTANT) + a3dc_read_a3da_key(data, length, &i->constant); + if (i->flags & A3DA_LIGHT_DIFFUSE) + a3dc_read_a3da_rgba(data, length, &i->diffuse); + if (i->flags & A3DA_LIGHT_DROP_OFF) + a3dc_read_a3da_key(data, length, &i->drop_off); + if (i->flags & A3DA_LIGHT_FAR) + a3dc_read_a3da_key(data, length, &i->_far); + if (i->flags & A3DA_LIGHT_INTENSITY) + a3dc_read_a3da_key(data, length, &i->intensity); + if (i->flags & A3DA_LIGHT_LINEAR) + a3dc_read_a3da_key(data, length, &i->linear); + if (i->flags & A3DA_LIGHT_POSITION) + a3dc_read_a3da_model_transform(data, length, &i->position, a->_compress_f16); + if (i->flags & A3DA_LIGHT_QUADRATIC) + a3dc_read_a3da_key(data, length, &i->quadratic); + if (i->flags & A3DA_LIGHT_SPECULAR) + a3dc_read_a3da_rgba(data, length, &i->specular); + if (i->flags & A3DA_LIGHT_SPOT_DIRECTION) + a3dc_read_a3da_model_transform(data, length, &i->spot_direction, a->_compress_f16); + if (i->flags & A3DA_LIGHT_TONE_CURVE) + a3dc_read_a3da_rgba(data, length, &i->tone_curve); + } + + for (a3da_m_object_hrc* i = a->m_object_hrc.begin; i != a->m_object_hrc.end; i++) { + for (a3da_object_instance* j = i->instance.begin; j != i->instance.end; j++) + a3dc_read_a3da_model_transform(data, length, &j->model_transform, a->_compress_f16); + + a3dc_read_a3da_model_transform(data, length, &i->model_transform, a->_compress_f16); + + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_read_a3da_model_transform(data, length, &j->model_transform, a->_compress_f16); + } + + for (a3da_material_list* i = a->material_list.begin; i != a->material_list.end; i++) { + if (i->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + a3dc_read_a3da_rgba(data, length, &i->blend_color); + if (i->flags & A3DA_MATERIAL_LIST_GLOW_INTENSITY) + a3dc_read_a3da_key(data, length, &i->glow_intensity); + if (i->flags & A3DA_MATERIAL_LIST_INCANDESCENCE) + a3dc_read_a3da_rgba(data, length, &i->incandescence); + } + + for (a3da_object* i = a->object.begin; i != a->object.end; i++) { + a3dc_read_a3da_model_transform(data, length, &i->model_transform, a->_compress_f16); + + for (a3da_object_texture_transform* j = i->texture_transform.begin; + j != i->texture_transform.end; j++) { + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + a3dc_read_a3da_key(data, length, &j->coverage_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + a3dc_read_a3da_key(data, length, &j->coverage_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + a3dc_read_a3da_key(data, length, &j->offset_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + a3dc_read_a3da_key(data, length, &j->offset_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + a3dc_read_a3da_key(data, length, &j->repeat_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + a3dc_read_a3da_key(data, length, &j->repeat_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE) + a3dc_read_a3da_key(data, length, &j->rotate); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + a3dc_read_a3da_key(data, length, &j->rotate_frame); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + a3dc_read_a3da_key(data, length, &j->translate_frame_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + a3dc_read_a3da_key(data, length, &j->translate_frame_v); + } + } + + for (a3da_object_hrc* i = a->object_hrc.begin; i != a->object_hrc.end; i++) + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_read_a3da_model_transform(data, length, &j->model_transform, a->_compress_f16); + + for (a3da_point* i = a->point.begin; i != a->point.end; i++) + a3dc_read_a3da_model_transform(data, length, &i->model_transform, a->_compress_f16); + + if (a->post_process.flags) { + a3da_post_process* pp = &a->post_process; + + if (pp->flags & A3DA_POST_PROCESS_INTENSITY) + a3dc_read_a3da_rgba(data, length, &pp->intensity); + if (pp->flags & A3DA_POST_PROCESS_LENS_FLARE) + a3dc_read_a3da_key(data, length, &pp->lens_flare); + if (pp->flags & A3DA_POST_PROCESS_LENS_GHOST) + a3dc_read_a3da_key(data, length, &pp->lens_ghost); + if (pp->flags & A3DA_POST_PROCESS_LENS_SHAFT) + a3dc_read_a3da_key(data, length, &pp->lens_shaft); + if (pp->flags & A3DA_POST_PROCESS_RADIUS) + a3dc_read_a3da_rgba(data, length, &pp->radius); + if (pp->flags & A3DA_POST_PROCESS_SCENE_FADE) + a3dc_read_a3da_rgba(data, length, &pp->scene_fade); + } +} + +static void a3da_write_data(a3da* a, void** data, size_t* length) { + stream s; + io_mopen(&s, 0, 0); + + for (a3da_camera_root* i = a->camera_root.begin; i != a->camera_root.end; i++) { + a3da_camera_root_view_point* vp = &i->view_point; + a3dc_write_a3da_model_transform_offset(&s, &i->model_transform); + a3dc_write_a3da_model_transform_offset(&s, &vp->model_transform); + a3dc_write_a3da_model_transform_offset(&s, &i->interest); + } + + for (a3da_chara* i = a->chara.begin; i != a->chara.end; i++) + a3dc_write_a3da_model_transform_offset(&s, &i->model_transform); + + if (a->dof.has_dof) { + a3da_dof* d = &a->dof; + + a3dc_write_a3da_model_transform_offset(&s, &d->model_transform); + } + + for (a3da_light* i = a->light.begin; i != a->light.end; i++) { + if (i->flags & A3DA_LIGHT_POSITION) + a3dc_write_a3da_model_transform_offset(&s, &i->position); + if (i->flags & A3DA_LIGHT_SPOT_DIRECTION) + a3dc_write_a3da_model_transform_offset(&s, &i->spot_direction); + } + + for (a3da_m_object_hrc* i = a->m_object_hrc.begin; i != a->m_object_hrc.end; i++) { + a3dc_write_a3da_model_transform_offset(&s, &i->model_transform); + + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform_offset(&s, &j->model_transform); + + for (a3da_object_instance* j = i->instance.begin; j != i->instance.end; j++) + a3dc_write_a3da_model_transform_offset(&s, &j->model_transform); + } + + for (a3da_object* i = a->object.begin; i != a->object.end; i++) + a3dc_write_a3da_model_transform_offset(&s, &i->model_transform); + + for (a3da_object_hrc* i = a->object_hrc.begin; i != a->object_hrc.end; i++) + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform_offset(&s, &j->model_transform); + + for (a3da_point* i = a->point.begin; i != a->point.end; i++) + a3dc_write_a3da_model_transform_offset(&s, &i->model_transform); + + for (a3da_ambient* i = a->ambient.begin; i != a->ambient.end; i++) { + if (i->flags & A3DA_AMBIENT_LIGHT_DIFFUSE) + a3dc_write_a3da_rgba(&s, &i->light_diffuse); + if (i->flags & A3DA_AMBIENT_RIM_LIGHT_DIFFUSE) + a3dc_write_a3da_rgba(&s, &i->rim_light_diffuse); + } + + if (a->camera_auxiliary.flags) { + a3da_camera_auxiliary* ca = &a->camera_auxiliary; + + if (ca->flags & A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE) + a3dc_write_a3da_key(&s, &ca->auto_exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE) + a3dc_write_a3da_key(&s, &ca->exposure); + if (ca->flags & A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE) + a3dc_write_a3da_key(&s, &ca->exposure_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA) + a3dc_write_a3da_key(&s, &ca->gamma); + if (ca->flags & A3DA_CAMERA_AUXILIARY_GAMMA_RATE) + a3dc_write_a3da_key(&s, &ca->gamma_rate); + if (ca->flags & A3DA_CAMERA_AUXILIARY_SATURATE) + a3dc_write_a3da_key(&s, &ca->saturate); + } + + for (a3da_camera_root* i = a->camera_root.begin; i != a->camera_root.end; i++) { + a3dc_write_a3da_model_transform(&s, &i->model_transform, a->_compress_f16); + + a3da_camera_root_view_point* vp = &i->view_point; + + a3dc_write_a3da_model_transform(&s, &vp->model_transform, a->_compress_f16); + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_ROLL) + a3dc_write_a3da_key(&s, &vp->roll); + if (vp->flags & A3DA_CAMERA_ROOT_VIEW_POINT_FOV) + a3dc_write_a3da_key(&s, &vp->fov); + else + a3dc_write_a3da_key(&s, &vp->focal_length); + a3dc_write_a3da_model_transform(&s, &i->interest, a->_compress_f16); + } + + for (a3da_chara* i = a->chara.begin; i != a->chara.end; i++) + a3dc_write_a3da_model_transform(&s, &i->model_transform, a->_compress_f16); + + for (a3da_curve* i = a->curve.begin; i != a->curve.end; i++) + a3dc_write_a3da_key(&s, &i->curve); + + if (a->dof.has_dof) { + a3da_dof* d = &a->dof; + + a3dc_write_a3da_model_transform(&s, &d->model_transform, a->_compress_f16); + } + + for (a3da_light* i = a->light.begin; i != a->light.end; i++) { + if (i->flags & A3DA_LIGHT_POSITION) + a3dc_write_a3da_model_transform(&s, &i->position, a->_compress_f16); + if (i->flags & A3DA_LIGHT_SPOT_DIRECTION) + a3dc_write_a3da_model_transform(&s, &i->spot_direction, a->_compress_f16); + if (i->flags & A3DA_LIGHT_AMBIENT) + a3dc_write_a3da_rgba(&s, &i->ambient); + if (i->flags & A3DA_LIGHT_DIFFUSE) + a3dc_write_a3da_rgba(&s, &i->diffuse); + if (i->flags & A3DA_LIGHT_SPECULAR) + a3dc_write_a3da_rgba(&s, &i->specular); + if (i->flags & A3DA_LIGHT_TONE_CURVE) + a3dc_write_a3da_rgba(&s, &i->tone_curve); + if (a->format == A3DA_FORMAT_XHD) { + if (i->flags & A3DA_LIGHT_INTENSITY) + a3dc_write_a3da_key(&s, &i->intensity); + if (i->flags & A3DA_LIGHT_FAR) + a3dc_write_a3da_key(&s, &i->_far); + if (i->flags & A3DA_LIGHT_CONSTANT) + a3dc_write_a3da_key(&s, &i->constant); + if (i->flags & A3DA_LIGHT_LINEAR) + a3dc_write_a3da_key(&s, &i->linear); + if (i->flags & A3DA_LIGHT_QUADRATIC) + a3dc_write_a3da_key(&s, &i->quadratic); + if (i->flags & A3DA_LIGHT_DROP_OFF) + a3dc_write_a3da_key(&s, &i->drop_off); + if (i->flags & A3DA_LIGHT_CONE_ANGLE) + a3dc_write_a3da_key(&s, &i->cone_angle); + } + } + + for (a3da_fog* i = a->fog.begin; i != a->fog.end; i++) { + if (i->flags & A3DA_FOG_DENSITY) + a3dc_write_a3da_key(&s, &i->density); + if (i->flags & A3DA_FOG_END) + a3dc_write_a3da_key(&s, &i->end); + if (i->flags & A3DA_FOG_START) + a3dc_write_a3da_key(&s, &i->start); + if (i->flags & A3DA_FOG_COLOR) + a3dc_write_a3da_rgba(&s, &i->color); + } + + for (a3da_m_object_hrc* i = a->m_object_hrc.begin; i != a->m_object_hrc.end; i++) { + a3dc_write_a3da_model_transform(&s, &i->model_transform, a->_compress_f16); + + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform(&s, &j->model_transform, a->_compress_f16); + + for (a3da_object_instance* j = i->instance.begin; j != i->instance.end; j++) + a3dc_write_a3da_model_transform(&s, &j->model_transform, a->_compress_f16); + } + + for (a3da_material_list* i = a->material_list.begin; i != a->material_list.end; i++) { + if (i->flags & A3DA_MATERIAL_LIST_GLOW_INTENSITY) + a3dc_write_a3da_key(&s, &i->glow_intensity); + if (i->flags & A3DA_MATERIAL_LIST_BLEND_COLOR) + a3dc_write_a3da_rgba(&s, &i->blend_color); + if (i->flags & A3DA_MATERIAL_LIST_INCANDESCENCE) + a3dc_write_a3da_rgba(&s, &i->incandescence); + } + + for (a3da_object* i = a->object.begin; i != a->object.end; i++) { + a3dc_write_a3da_model_transform(&s, &i->model_transform, a->_compress_f16); + + for (a3da_object_texture_transform* j = i->texture_transform.begin; + j != i->texture_transform.end; j++) { + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U) + a3dc_write_a3da_key(&s, &j->coverage_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V) + a3dc_write_a3da_key(&s, &j->coverage_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U) + a3dc_write_a3da_key(&s, &j->repeat_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V) + a3dc_write_a3da_key(&s, &j->repeat_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U) + a3dc_write_a3da_key(&s, &j->offset_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V) + a3dc_write_a3da_key(&s, &j->offset_v); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE) + a3dc_write_a3da_key(&s, &j->rotate); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME) + a3dc_write_a3da_key(&s, &j->rotate_frame); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U) + a3dc_write_a3da_key(&s, &j->translate_frame_u); + if (j->flags & A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V) + a3dc_write_a3da_key(&s, &j->translate_frame_v); + } + } + + for (a3da_object_hrc* i = a->object_hrc.begin; i != a->object_hrc.end; i++) + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform(&s, &j->model_transform, a->_compress_f16); + + for (a3da_point* i = a->point.begin; i != a->point.end; i++) + a3dc_write_a3da_model_transform(&s, &i->model_transform, a->_compress_f16); + + if (a->post_process.flags) { + a3da_post_process* pp = &a->post_process; + + if (pp->flags & A3DA_POST_PROCESS_LENS_FLARE) + a3dc_write_a3da_key(&s, &pp->lens_flare); + if (pp->flags & A3DA_POST_PROCESS_LENS_GHOST) + a3dc_write_a3da_key(&s, &pp->lens_ghost); + if (pp->flags & A3DA_POST_PROCESS_LENS_SHAFT) + a3dc_write_a3da_key(&s, &pp->lens_shaft); + if (pp->flags & A3DA_POST_PROCESS_INTENSITY) + a3dc_write_a3da_rgba(&s, &pp->intensity); + if (pp->flags & A3DA_POST_PROCESS_RADIUS) + a3dc_write_a3da_rgba(&s, &pp->radius); + if (pp->flags & A3DA_POST_PROCESS_SCENE_FADE) + a3dc_write_a3da_rgba(&s, &pp->scene_fade); + } + + for (a3da_camera_root* i = a->camera_root.begin; i != a->camera_root.end; i++) { + a3da_camera_root_view_point* vp = &i->view_point; + a3dc_write_a3da_model_transform_offset_data(&s, &i->model_transform); + a3dc_write_a3da_model_transform_offset_data(&s, &vp->model_transform); + a3dc_write_a3da_model_transform_offset_data(&s, &i->interest); + } + + for (a3da_chara* i = a->chara.begin; i != a->chara.end; i++) + a3dc_write_a3da_model_transform_offset_data(&s, &i->model_transform); + + if (a->dof.has_dof) { + a3da_dof* d = &a->dof; + + a3dc_write_a3da_model_transform_offset_data(&s, &d->model_transform); + } + + for (a3da_light* i = a->light.begin; i != a->light.end; i++) { + if (i->flags & A3DA_LIGHT_POSITION) + a3dc_write_a3da_model_transform_offset_data(&s, &i->position); + if (i->flags & A3DA_LIGHT_SPOT_DIRECTION) + a3dc_write_a3da_model_transform_offset_data(&s, &i->spot_direction); + } + + for (a3da_m_object_hrc* i = a->m_object_hrc.begin; i != a->m_object_hrc.end; i++) { + a3dc_write_a3da_model_transform_offset_data(&s, &i->model_transform); + + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform_offset_data(&s, &j->model_transform); + + for (a3da_object_instance* j = i->instance.begin; j != i->instance.end; j++) + a3dc_write_a3da_model_transform_offset_data(&s, &j->model_transform); + } + + for (a3da_object* i = a->object.begin; i != a->object.end; i++) + a3dc_write_a3da_model_transform_offset_data(&s, &i->model_transform); + + for (a3da_object_hrc* i = a->object_hrc.begin; i != a->object_hrc.end; i++) + for (a3da_object_node* j = i->node.begin; j != i->node.end; j++) + a3dc_write_a3da_model_transform_offset_data(&s, &j->model_transform); + + for (a3da_point* i = a->point.begin; i != a->point.end; i++) + a3dc_write_a3da_model_transform_offset_data(&s, &i->model_transform); + + io_align_write(&s, 0x10); + io_mcopy(&s, data, length); + io_free(&s); +} + +static void a3da_get_time_stamp(char* buf, size_t buf_size) { + time_t time_now; + struct tm tm; + time(&time_now); + gmtime_s(&tm, &time_now); + + const char* day_of_week[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + }; + + const char* month[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + + sprintf_s(buf, buf_size, "#%s %s %02d %02d:%02d:%02d %04d\n", + day_of_week[tm.tm_wday], month[tm.tm_mon], + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, 1900 + tm.tm_year); +} + +static bool key_val_read_a3da_key(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_key* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + memset(value, 0, sizeof(a3da_key)); + key_val lkv; + if (!key_val_get_local_key_val(kv, buf, &lkv)) + return false; + else if (key_val_read_int32_t(&lkv, buf, offset, ".bin_offset", 12, &value->bin_offset)) { + value->flags = A3DA_KEY_BIN_OFFSET; + key_val_free(&lkv); + return true; + } + else if (!key_val_read_int32_t(&lkv, buf, offset, ".type", 6, (int32_t*)&value->type)) { + key_val_free(&lkv); + return false; + } + + if (value->type == A3DA_KEY_NONE) { + key_val_free(&lkv); + return true; + } + else if (value->type == A3DA_KEY_STATIC) { + key_val_read_float_t(&lkv, buf, offset, ".value", 7, &value->value); + key_val_free(&lkv); + return true; + } + + key_val_read_int32_t(&lkv, buf, offset, + ".ep_type_post", 14, (int32_t*)&value->ep_type_post); + key_val_read_int32_t(&lkv, buf, offset, + ".ep_type_pre", 13, (int32_t*)&value->ep_type_pre); + key_val_read_float_t(&lkv, buf, offset, ".max", 5, &value->max); + + if (key_val_read_a3da_key_raw_data(&lkv, buf, offset, value)) { + key_val_free(&lkv); + return true; + } + + memcpy(buf + offset, ".key", 5); + offset += 4; + + key_val sub_local_key_val; + if (!key_val_get_local_key_val(&lkv, buf, &sub_local_key_val)) { + key_val_free(&lkv); + return false; + } + key_val_free(&lkv); + + int32_t length = 0; + key_val_read_int32_t(&sub_local_key_val, buf, offset, ".length", 8, &length); + vector_kft3_reserve(&value->keys, length); + + kft3 k = { 0.0f, 0.0f, 0.0f, 0.0f }; + size_t len = offset; + for (int32_t i = 0; i < length; i++) { + size_t len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", i); + offset = len + len1; + + char* data; + int32_t type = 0; + key_val_read_string_ptr(&sub_local_key_val, buf, offset, ".data", 6, &data); + key_val_read_int32_t(&sub_local_key_val, buf, offset, ".type", 6, &type); + + switch (type) { + case 0: { + float_t f; + if (sscanf_s(data, "%g", &f) == 1) + k = (kft3){ f, 0.0f, 0.0f, 0.0f }; + else + k = (kft3){ 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_push_back(&value->keys, &k); + } break; + case 1: { + float_t f; + float_t v; + if (sscanf_s(data, "(%g,%g)", &f, &v) == 2) + k = (kft3){ f, v, 0.0f, 0.0f }; + else + k = (kft3){ 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_push_back(&value->keys, &k); + } break; + case 2: { + float_t f; + float_t v; + float_t t; + if (sscanf_s(data, "(%g,%g,%g)", &f, &v, &t) == 3) + k = (kft3){ f, v, t, t }; + else + k = (kft3){ 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_push_back(&value->keys, &k); + } break; + case 3: { + float_t f; + float_t v; + float_t t1; + float_t t2; + if (sscanf_s(data, "(%g,%g,%g,%g)", &f, &v, &t1, &t2) == 4) + k = (kft3){ f, v, t1, t2 }; + else + k = (kft3){ 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_push_back(&value->keys, &k); + } break; + default: { + k = (kft3){ 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_push_back(&value->keys, &k); + } break; + } + } + key_val_free(&sub_local_key_val); + return true; +} + +static void key_val_write_a3da_key(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_key* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + if (value->flags & A3DA_KEY_BIN_OFFSET) { + key_val_write_int32_t(s, buf, offset, ".bin_offset", 12, value->bin_offset); + value->flags &= ~A3DA_KEY_BIN_OFFSET; + value->bin_offset = 0; + return; + } + + if (value->type == A3DA_KEY_NONE) { + key_val_write_int32_t(s, buf, offset, ".type", 6, 0);; + return; + } + else if (value->type == A3DA_KEY_STATIC) { + key_val_write_int32_t(s, buf, offset, ".type", 6, 1); + key_val_write_float_t(s, buf, offset, ".value", 7, value->value); + return; + } + + if (value->ep_type_post != A3DA_EP_NONE) + key_val_write_int32_t(s, buf, offset, + ".ep_type_post", 14, value->ep_type_post); + if (value->ep_type_pre != A3DA_EP_NONE) + key_val_write_int32_t(s, buf, offset, + ".ep_type_pre", 13, value->ep_type_pre); + + if (value->raw_data) { + key_val_write_a3da_key_raw_data(s, buf, offset, value); + return; + } + + memcpy(buf + offset, ".key", 5); + offset += 4; + + int32_t length = (int32_t)(value->keys.end - value->keys.begin); + + vector_int32_t sort_index = vector_empty(int32_t); + key_val_get_lexicographic_order(&sort_index, length); + size_t len = offset; + for (int32_t i = 0; i < length; i++) { + size_t len1 = sprintf_s(buf + len, A3DA_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + offset = len + len1; + + kft3 k = value->keys.begin[sort_index.begin[i]]; + kf_type kt = KEY_FRAME_TYPE_3; + kft_check(&k, kt, &k, &kt); + + char data_buf[0x200]; + switch (kt) { + case KEY_FRAME_TYPE_0: + sprintf_s(data_buf, sizeof(data_buf), "%g", + k.frame); + break; + case KEY_FRAME_TYPE_1: + sprintf_s(data_buf, sizeof(data_buf), "(%g,%g)", + k.frame, k.value); + break; + case KEY_FRAME_TYPE_2: + sprintf_s(data_buf, sizeof(data_buf), "(%g,%g,%g)", + k.frame, k.value, k.tangent1); + break; + case KEY_FRAME_TYPE_3: + sprintf_s(data_buf, sizeof(data_buf), "(%g,%g,%g,%g)", + k.frame, k.value, k.tangent1, k.tangent2); + break; + } + + key_val_write_string_ptr(s, buf, offset, ".data", 6, data_buf); + key_val_write_int32_t(s, buf, offset, ".type", 6, kt); + } + vector_int32_t_free(&sort_index, 0); + + offset = len; + key_val_write_int32_t(s, buf, offset, ".length", 8, length); + + offset -= 4; + key_val_write_float_t(s, buf, offset, ".max", 5, value->max); + key_val_write_int32_t(s, buf, offset, ".type", 6, value->type); +} + +static bool key_val_read_a3da_key_raw_data(key_val* kv, char* buf, + size_t offset, a3da_key* value) { + int32_t key_type = 0; + if (!key_val_read_int32_t(kv, buf, offset, ".raw_data_key_type", 19, &key_type)) + return false; + + char* value_type; + key_val_read_string_ptr(kv, buf, offset, ".raw_data.value_type", 21, &value_type); + if (str_utils_compare(value_type, "float")) + return false; + + int32_t value_list_size = 0; + key_val_read_int32_t(kv, buf, offset, ".raw_data.value_list_size", 26, &value_list_size); + + int32_t value_list_offset = 0; + if (key_val_read_int32_t(kv, buf, offset, ".raw_data.value_list_offset", 28, &value_list_offset)) { + if (key_type != 3) + return false; + + value->raw_data = true; + value->raw_data_binary = true; + value->raw_data_value_list_size = value_list_size; + value->raw_data_value_list_offset = value_list_offset; + return true; + } + + char* value_list; + key_val_read_string_ptr(kv, buf, offset, ".raw_data.value_list", 21, &value_list); + + char* s = value_list; + size_t c = 1; + while (s = strchr(s, ',')) { + s++; + c++; + } + + if (c != value_list_size) + return false; + + float_t* fs = force_malloc_s(float_t, c); + s = value_list; + for (size_t i = 0; i < c; i++) { + char* t = s; + s = strchr(s, ','); + if (s) + *s++ = 0; + fs[i] = (float_t)atof(t); + } + + switch (key_type) { + case 0: { + kft3 k = { 0.0f, 0.0f, 0.0f, 0.0f }; + vector_kft3_reserve(&value->keys, c); + for (size_t i = 0; i < c; i++) { + k.frame = *fs++; + vector_kft3_push_back(&value->keys, &k); + } + fs -= c; + } break; + case 1: { + kft3 k = { 0.0f, 0.0f, 0.0f, 0.0f }; + c /= 2; + vector_kft3_reserve(&value->keys, c); + for (size_t i = 0; i < c; i++) { + k.frame = *fs++; + k.value = *fs++; + vector_kft3_push_back(&value->keys, &k); + } + fs -= c * 2; + } break; + case 2: { + kft3 k = { 0.0f, 0.0f, 0.0f, 0.0f }; + c /= 3; + vector_kft3_reserve(&value->keys, c); + for (size_t i = 0; i < c; i++) { + k.frame = *fs++; + k.value = *fs++; + k.tangent1 = k.tangent2 = *fs++; + vector_kft3_push_back(&value->keys, &k); + } + fs -= c * 3; + } break; + case 3: { + kft3 k = { 0.0f, 0.0f, 0.0f, 0.0f }; + c /= 4; + vector_kft3_reserve(&value->keys, c); + for (size_t i = 0; i < c; i++) { + k.frame = *fs++; + k.value = *fs++; + k.tangent1 = *fs++; + k.tangent2 = *fs++; + vector_kft3_push_back(&value->keys, &k); + } + fs -= c * 4; + } break; + default: + free(fs); + return false; + } + free(fs); + + value->raw_data = true; + return true; +} + +static void key_val_write_a3da_key_raw_data(stream* s, char* buf, + size_t offset, a3da_key* value) { + key_val_write_float_t(s, buf, offset, ".max", 5, value->max); + + int32_t length = (int32_t)(value->keys.end - value->keys.begin); + if (value->raw_data_binary) { + key_val_write_int32_t(s, buf, offset, ".raw_data.value_list_offset", 6, + value->raw_data_value_list_offset); + key_val_write_int32_t(s, buf, offset, ".raw_data.value_list_size", 26, + value->raw_data_value_list_size); + key_val_write_string_ptr(s, buf, offset, ".raw_data.value_type", 21, "float"); + key_val_write_int32_t(s, buf, offset, ".raw_data_key_type", 19, 3); + key_val_write_int32_t(s, buf, offset, ".type", 6, value->type); + return; + } + + kf_type key_type = KEY_FRAME_TYPE_0; + for (int32_t i = 0; i < length; i++) { + kft3 k = value->keys.begin[i]; + kf_type kt = KEY_FRAME_TYPE_3; + kft_check(&k, kt, &k, &kt); + if (key_type < kt) + key_type = kt; + if (key_type == KEY_FRAME_TYPE_3) + break; + } + + memcpy(buf + offset, ".raw_data.value_list=", 22); + + io_write_utf8_string(s, buf); + char data_buf[0x200]; + switch (key_type) { + case KEY_FRAME_TYPE_0: + for (int32_t i = 0; i < length; i++) { + kft3 k = value->keys.begin[i]; + sprintf_s(data_buf, sizeof(data_buf), "%g", + k.frame); + io_write_utf8_string(s, data_buf); + if (i + 1 < length) + io_write_char(s, ','); + } + break; + case KEY_FRAME_TYPE_1: + for (int32_t i = 0; i < length; i++) { + kft3 k = value->keys.begin[i]; + sprintf_s(data_buf, sizeof(data_buf), "%g,%g", + k.frame, k.value); + io_write_utf8_string(s, data_buf); + if (i + 1 < length) + io_write_char(s, ','); + } + break; + case KEY_FRAME_TYPE_2: + for (int32_t i = 0; i < length; i++) { + kft3 k = value->keys.begin[i]; + sprintf_s(data_buf, sizeof(data_buf), "%g,%g,%g", + k.frame, k.value, k.tangent1); + io_write_utf8_string(s, data_buf); + if (i + 1 < length) + io_write_char(s, ','); + } + break; + case KEY_FRAME_TYPE_3: + for (int32_t i = 0; i < length; i++) { + kft3 k = value->keys.begin[i]; + sprintf_s(data_buf, sizeof(data_buf), "%g,%g,%g,%g", + k.frame, k.value, k.tangent1, k.tangent2); + io_write_utf8_string(s, data_buf); + if (i + 1 < length) + io_write_char(s, ','); + } + break; + } + io_write_char(s, '\n'); + + key_val_write_int32_t(s, buf, offset, ".raw_data.value_list_size", 26, + (int32_t)(length * ((size_t)key_type + 1))); + key_val_write_string_ptr(s, buf, offset, ".raw_data.value_type", 21, "float"); + key_val_write_int32_t(s, buf, offset, ".raw_data_key_type", 19, key_type); + key_val_write_int32_t(s, buf, offset, ".type", 6, value->type); +} + +static bool key_val_read_a3da_model_transform(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, + a3da_model_transform* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + memset(value, 0, sizeof(a3da_model_transform)); + key_val lkv; + if (!key_val_get_local_key_val(kv, buf, &lkv)) + return false; + else if (key_val_read_int32_t(&lkv, buf, offset, + ".model_transform.bin_offset", 28, &value->bin_offset)) { + value->flags = A3DA_MODEL_TRANSFORM_BIN_OFFSET; + key_val_free(&lkv); + return true; + } + + key_val_read_a3da_vec3(&lkv, buf, offset, ".rot", 5, &value->rotation); + key_val_read_a3da_vec3(&lkv, buf, offset, ".scale", 7, &value->scale); + key_val_read_a3da_vec3(&lkv, buf, offset, ".trans", 7, &value->translation); + key_val_read_a3da_key(&lkv, buf, offset,".visibility", 12, &value->visibility); + key_val_free(&lkv); + return true; +} + +static void key_val_write_a3da_model_transform(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_model_transform* value, int32_t write_mask) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + if (value->flags & A3DA_MODEL_TRANSFORM_BIN_OFFSET) { + if (write_mask & 0x10) { + key_val_write_int32_t(s, buf, offset, + ".model_transform.bin_offset", 28, value->bin_offset); + } + if (write_mask & 0x01) + if (value->flags & A3DA_MODEL_TRANSFORM_BIN_OFFSET) { + value->flags &= ~A3DA_MODEL_TRANSFORM_BIN_OFFSET; + value->bin_offset = 0; + } + } + else { + if (write_mask & 0x08) + key_val_write_a3da_vec3(s, buf, offset, ".rot", 5, &value->rotation); + if (write_mask & 0x04) + key_val_write_a3da_vec3(s, buf, offset, ".scale", 7, &value->scale); + if (write_mask & 0x02) + key_val_write_a3da_vec3(s, buf, offset, ".trans", 7, &value->translation); + if (write_mask & 0x01) + key_val_write_a3da_key(s, buf, offset, ".visibility", 12, &value->visibility); + } +} + +static bool key_val_read_a3da_rgba(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_rgba* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + memset(value, 0, sizeof(a3da_rgba)); + key_val lkv; + if (!key_val_get_local_key_val(kv, buf, &lkv)) + return false; + + if (key_val_read_a3da_key(&lkv, buf, offset, ".r", 3, &value->r)) + value->flags |= A3DA_RGBA_R; + if (key_val_read_a3da_key(&lkv, buf, offset, ".g", 3, &value->g)) + value->flags |= A3DA_RGBA_G; + if (key_val_read_a3da_key(&lkv, buf, offset, ".b", 3, &value->b)) + value->flags |= A3DA_RGBA_B; + if (key_val_read_a3da_key(&lkv, buf, offset, ".a", 3, &value->a)) + value->flags |= A3DA_RGBA_A; + key_val_free(&lkv); + return true; +} + +static void key_val_write_a3da_rgba(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_rgba* value) { + if (!value->flags) + return; + + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + if (value->flags & A3DA_RGBA_R) + key_val_write_a3da_key(s, buf, offset, ".r", 3, &value->r); + if (value->flags & A3DA_RGBA_G) + key_val_write_a3da_key(s, buf, offset, ".g", 3, &value->g); + if (value->flags & A3DA_RGBA_B) + key_val_write_a3da_key(s, buf, offset, ".b", 3, &value->b); + if (value->flags & A3DA_RGBA_A) + key_val_write_a3da_key(s, buf, offset, ".a", 3, &value->a); +} + +static bool key_val_read_a3da_vec3(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_vec3* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + memset(value, 0, sizeof(a3da_vec3)); + key_val lkv; + if (!key_val_get_local_key_val(kv, buf, &lkv)) + return false; + + key_val_read_a3da_key(&lkv, buf, offset, ".x", 3, &value->x); + key_val_read_a3da_key(&lkv, buf, offset, ".y", 3, &value->y); + key_val_read_a3da_key(&lkv, buf, offset, ".z", 3, &value->z); + key_val_free(&lkv); + return true; +} + +static void key_val_write_a3da_vec3(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, a3da_vec3* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + key_val_write_a3da_key(s, buf, offset, ".x", 3, &value->x); + key_val_write_a3da_key(s, buf, offset, ".y", 3, &value->y); + key_val_write_a3da_key(s, buf, offset, ".z", 3, &value->z); +} + +inline static void a3dc_read_a3da_key(void* data, size_t length, a3da_key* value) { + a3dc_read_a3da_key_f16(data, length, value, A3DA_COMPRESS_F32F32F32F32); +} + +inline static void a3dc_write_a3da_key(stream* s, a3da_key* value) { + a3dc_write_a3da_key_f16(s, value, A3DA_COMPRESS_F32F32F32F32); +} + +static void a3dc_read_a3da_key_f16(void* data, size_t length, a3da_key* value, a3da_compress_f16 f16) { + if (value->raw_data) { + if (!value->raw_data_binary) + return; + + size_t _d = (size_t)data + value->raw_data_value_list_offset; + value->raw_data_value_list_offset = 0; + + int32_t len = value->raw_data_value_list_size / 4; + vector_kft3_reserve(&value->keys, length); + for (int32_t i = 0; i < len; i++) { + kft3 k; + k.frame = *(float_t*)_d; + k.value = *(float_t*)(_d + 4); + k.tangent1 = *(float_t*)(_d + 8); + k.tangent2 = *(float_t*)(_d + 12); + vector_kft3_push_back(&value->keys, &k); + _d += 16; + } + return; + } + else if (~value->flags & A3DA_KEY_BIN_OFFSET) + return; + + a3dc_key_header* head = (void*)((size_t)data + value->bin_offset); + value->flags &= ~A3DA_KEY_BIN_OFFSET; + value->bin_offset = 0; + + size_t d = (size_t)head + sizeof(a3dc_key_header); + + if (head->type == A3DA_KEY_NONE) { + value->type = head->type; + return; + } + else if (head->type == A3DA_KEY_STATIC) { + value->type = head->type; + value->value = head->value; + return; + } + + value->type = head->type; + value->ep_type_pre = head->ep_type_pre; + value->ep_type_post = head->ep_type_post; + value->max = head->max; + uint32_t len = head->length; + + vector_kft3_reserve(&value->keys, len); + switch (f16) { + case A3DA_COMPRESS_F32F32F32F32: + for (uint32_t i = 0; i < len; i++) { + kft3 k; + k.frame = *(float_t*)d; + k.value = *(float_t*)(d + 4); + k.tangent1 = *(float_t*)(d + 8); + k.tangent2 = *(float_t*)(d + 12); + vector_kft3_push_back(&value->keys, &k); + d += 16; + } + break; + case A3DA_COMPRESS_I16F16F32F32: + for (uint32_t i = 0; i < len; i++) { + kft3 k; + k.frame = (float_t)*(int16_t*)d; + k.value = half_to_float(*(half_t*)(d + 2)); + k.tangent1 = *(float_t*)(d + 4); + k.tangent2 = *(float_t*)(d + 8); + vector_kft3_push_back(&value->keys, &k); + d += 12; + } + break; + case A3DA_COMPRESS_I16F16F16F16: + for (uint32_t i = 0; i < len; i++) { + kft3 k; + k.frame = (float_t)*(int16_t*)d; + k.value = half_to_float(*(half_t*)(d + 2)); + k.tangent1 = half_to_float(*(half_t*)(d + 4)); + k.tangent2 = half_to_float(*(half_t*)(d + 6)); + vector_kft3_push_back(&value->keys, &k); + d += 8; + } + break; + } +} + +static void a3dc_write_a3da_key_f16(stream* s, a3da_key* value, a3da_compress_f16 f16) { + if (value->raw_data) { + if ((int32_t)(value->keys.end - value->keys.begin) < 1) { + value->raw_data = false; + value->raw_data_binary = false; + value->type = A3DA_KEY_NONE; + vector_kft3_free(&value->keys, 0); + } + else if ((int32_t)(value->keys.end - value->keys.begin) == 1) { + value->raw_data = false; + value->raw_data_binary = false; + value->type = A3DA_KEY_STATIC; + value->value = value->keys.begin[0].value; + vector_kft3_free(&value->keys, 0); + } + } + + if (value->raw_data) { + if (!value->raw_data_binary) + return; + + value->raw_data_value_list_offset = (int32_t)io_get_position(s); + + int32_t len = (int32_t)(value->keys.end - value->keys.begin); + value->raw_data_value_list_size = len * 4; + for (int32_t i = 0; i < len; i++) { + kft3* k = &value->keys.begin[i]; + io_write_float_t(s, k->frame); + io_write_float_t(s, k->value); + io_write_float_t(s, k->tangent1); + io_write_float_t(s, k->tangent2); + } + return; + } + + value->bin_offset = (int32_t)io_get_position(s); + value->flags |= A3DA_KEY_BIN_OFFSET; + + if (value->type == A3DA_KEY_NONE) { + io_write_int32_t(s, A3DA_KEY_NONE); + io_write_float_t(s, 0.0f); + return; + } + else if (value->type == A3DA_KEY_STATIC) { + io_write_int32_t(s, A3DA_KEY_STATIC); + io_write_float_t(s, value->value); + return; + } + + uint32_t len = (uint32_t)(value->keys.end - value->keys.begin); + + a3dc_key_header head; + memset(&head, 0, sizeof(a3dc_key_header)); + head.type = value->type; + head.ep_type_pre = value->ep_type_pre; + head.ep_type_post = value->ep_type_post; + head.max = value->max; + head.length = len; + io_write(s, &head, sizeof(a3dc_key_header)); + + switch (f16) { + case A3DA_COMPRESS_F32F32F32F32: + for (uint32_t i = 0; i < len; i++) { + kft3* k = &value->keys.begin[i]; + io_write_float_t(s, k->frame); + io_write_float_t(s, k->value); + io_write_float_t(s, k->tangent1); + io_write_float_t(s, k->tangent2); + } + break; + case A3DA_COMPRESS_I16F16F32F32: + for (uint32_t i = 0; i < len; i++) { + kft3* k = &value->keys.begin[i]; + io_write_int16_t(s, (int16_t)roundf(k->frame)); + io_write_half_t(s, float_to_half(k->value)); + io_write_float_t(s, k->tangent1); + io_write_float_t(s, k->tangent2); + } + break; + case A3DA_COMPRESS_I16F16F16F16: + for (uint32_t i = 0; i < len; i++) { + kft3* k = &value->keys.begin[i]; + io_write_int16_t(s, (int16_t)roundf(k->frame)); + io_write_half_t(s, float_to_half(k->value)); + io_write_half_t(s, float_to_half(k->tangent1)); + io_write_half_t(s, float_to_half(k->tangent2)); + } + break; + } +} + +static void a3dc_read_a3da_model_transform(void* data, size_t length, + a3da_model_transform* value, a3da_compress_f16 f16) { + if (~value->flags & A3DA_MODEL_TRANSFORM_BIN_OFFSET) + return; + + a3da_model_transform_header* head = (void*)((size_t)data + value->bin_offset); + value->flags &= ~A3DA_MODEL_TRANSFORM_BIN_OFFSET; + value->bin_offset = 0; + + value->scale.x.bin_offset = head->scale.x; + value->scale.x.flags |= A3DA_KEY_BIN_OFFSET; + value->scale.y.bin_offset = head->scale.y; + value->scale.y.flags |= A3DA_KEY_BIN_OFFSET; + value->scale.z.bin_offset = head->scale.z; + value->scale.z.flags |= A3DA_KEY_BIN_OFFSET; + value->rotation.x.bin_offset = head->rotation.x; + value->rotation.x.flags |= A3DA_KEY_BIN_OFFSET; + value->rotation.y.bin_offset = head->rotation.y; + value->rotation.y.flags |= A3DA_KEY_BIN_OFFSET; + value->rotation.z.bin_offset = head->rotation.z; + value->rotation.z.flags |= A3DA_KEY_BIN_OFFSET; + value->translation.x.bin_offset = head->translation.x; + value->translation.x.flags |= A3DA_KEY_BIN_OFFSET; + value->translation.y.bin_offset = head->translation.y; + value->translation.y.flags |= A3DA_KEY_BIN_OFFSET; + value->translation.z.bin_offset = head->translation.z; + value->translation.z.flags |= A3DA_KEY_BIN_OFFSET; + value->visibility.bin_offset = head->visibility; + value->visibility.flags |= A3DA_KEY_BIN_OFFSET; + + a3dc_read_a3da_vec3(data, length, &value->scale); + a3dc_read_a3da_vec3_f16(data, length, &value->rotation, f16); + a3dc_read_a3da_vec3(data, length, &value->translation); + a3dc_read_a3da_key(data, length, &value->visibility); +} + +static void a3dc_write_a3da_model_transform(stream* s, + a3da_model_transform* value, a3da_compress_f16 f16) { + a3dc_write_a3da_vec3(s, &value->scale); + a3dc_write_a3da_vec3(s, &value->rotation); + a3dc_write_a3da_vec3(s, &value->translation); + a3dc_write_a3da_key(s, &value->visibility); +} + +static void a3dc_write_a3da_model_transform_offset(stream* s, + a3da_model_transform* value) { + value->bin_offset = (int32_t)io_get_position(s); + value->flags |= A3DA_MODEL_TRANSFORM_BIN_OFFSET; + io_write(s, 0, 0x30); +} + +static void a3dc_write_a3da_model_transform_offset_data(stream* s, + a3da_model_transform* value) { + io_position_push(s, value->bin_offset, SEEK_SET); + io_write_uint32_t(s, value->scale.x.bin_offset); + value->scale.x.flags &= ~A3DA_KEY_BIN_OFFSET; + value->scale.x.bin_offset = 0; + io_write_uint32_t(s, value->scale.y.bin_offset); + value->scale.y.flags &= ~A3DA_KEY_BIN_OFFSET; + value->scale.y.bin_offset = 0; + io_write_uint32_t(s, value->scale.z.bin_offset); + value->scale.z.flags &= ~A3DA_KEY_BIN_OFFSET; + value->scale.z.bin_offset = 0; + io_write_uint32_t(s, value->rotation.x.bin_offset); + value->rotation.x.flags &= ~A3DA_KEY_BIN_OFFSET; + value->rotation.x.bin_offset = 0; + io_write_uint32_t(s, value->rotation.y.bin_offset); + value->rotation.y.flags &= ~A3DA_KEY_BIN_OFFSET; + value->rotation.y.bin_offset = 0; + io_write_uint32_t(s, value->rotation.z.bin_offset); + value->rotation.z.flags &= ~A3DA_KEY_BIN_OFFSET; + value->rotation.z.bin_offset = 0; + io_write_uint32_t(s, value->translation.x.bin_offset); + value->translation.x.flags &= ~A3DA_KEY_BIN_OFFSET; + value->translation.x.bin_offset = 0; + io_write_uint32_t(s, value->translation.y.bin_offset); + value->translation.y.flags &= ~A3DA_KEY_BIN_OFFSET; + value->translation.y.bin_offset = 0; + io_write_uint32_t(s, value->translation.z.bin_offset); + value->translation.z.flags &= ~A3DA_KEY_BIN_OFFSET; + value->translation.z.bin_offset = 0; + io_write_uint32_t(s, value->visibility.bin_offset); + value->visibility.flags &= ~A3DA_KEY_BIN_OFFSET; + value->visibility.bin_offset = 0; + io_position_pop(s); +} + +static void a3dc_read_a3da_rgba(void* data, size_t length, a3da_rgba* value) { + if (!value->flags) + return; + + if (value->flags & A3DA_RGBA_R) + a3dc_read_a3da_key(data, length, &value->r); + if (value->flags & A3DA_RGBA_G) + a3dc_read_a3da_key(data, length, &value->g); + if (value->flags & A3DA_RGBA_B) + a3dc_read_a3da_key(data, length, &value->b); + if (value->flags & A3DA_RGBA_A) + a3dc_read_a3da_key(data, length, &value->a); +} + +static void a3dc_write_a3da_rgba(stream* s, a3da_rgba* value) { + if (!value->flags) + return; + + if (value->flags & A3DA_RGBA_R) + a3dc_write_a3da_key(s, &value->r); + if (value->flags & A3DA_RGBA_G) + a3dc_write_a3da_key(s, &value->g); + if (value->flags & A3DA_RGBA_B) + a3dc_write_a3da_key(s, &value->b); + if (value->flags & A3DA_RGBA_A) + a3dc_write_a3da_key(s, &value->a); +} + +static void a3dc_read_a3da_vec3(void* data, size_t length, a3da_vec3* value) { + a3dc_read_a3da_key(data, length, &value->x); + a3dc_read_a3da_key(data, length, &value->y); + a3dc_read_a3da_key(data, length, &value->z); +} + +static void a3dc_write_a3da_vec3(stream* s, a3da_vec3* value) { + a3dc_write_a3da_key(s, &value->x); + a3dc_write_a3da_key(s, &value->y); + a3dc_write_a3da_key(s, &value->z); +} + +static void a3dc_read_a3da_vec3_f16(void* data, size_t length, a3da_vec3* value, a3da_compress_f16 f16) { + a3dc_read_a3da_key_f16(data, length, &value->x, f16); + a3dc_read_a3da_key_f16(data, length, &value->y, f16); + a3dc_read_a3da_key_f16(data, length, &value->z, f16); +} + +static void a3dc_write_a3da_vec3_f16(stream* s, a3da_vec3* value, a3da_compress_f16 f16) { + a3dc_write_a3da_key_f16(s, &value->x, f16); + a3dc_write_a3da_key_f16(s, &value->y, f16); + a3dc_write_a3da_key_f16(s, &value->z, f16); +} diff --git a/src/KKdLib/a3da.h b/src/KKdLib/a3da.h new file mode 100644 index 00000000..b6b66730 --- /dev/null +++ b/src/KKdLib/a3da.h @@ -0,0 +1,488 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "default.h" +#include "light_param/fog.h" +#include "light_param/light.h" +#include "kf.h" +#include "mat.h" +#include "string.h" +#include "vec.h" +#include "vector.h" + +typedef enum a3da_ambient_flags { + A3DA_AMBIENT_LIGHT_DIFFUSE = 0x01, + A3DA_AMBIENT_RIM_LIGHT_DIFFUSE = 0x02, +} a3da_ambient_flags; + +typedef enum a3da_camera_auxiliary_flags { + A3DA_CAMERA_AUXILIARY_AUTO_EXPOSURE = 0x01, + A3DA_CAMERA_AUXILIARY_EXPOSURE = 0x02, + A3DA_CAMERA_AUXILIARY_EXPOSURE_RATE = 0x04, + A3DA_CAMERA_AUXILIARY_GAMMA = 0x08, + A3DA_CAMERA_AUXILIARY_GAMMA_RATE = 0x10, + A3DA_CAMERA_AUXILIARY_SATURATE = 0x20, +} a3da_camera_auxiliary_flags; + +typedef enum a3da_camera_root_view_point_flags { + A3DA_CAMERA_ROOT_VIEW_POINT_FOV = 0x01, + A3DA_CAMERA_ROOT_VIEW_POINT_ROLL = 0x02, +} a3da_camera_root_view_point_flags; + +typedef enum a3da_compress_f16 { + A3DA_COMPRESS_F32F32F32F32 = 0, + A3DA_COMPRESS_I16F16F32F32 = 1, + A3DA_COMPRESS_I16F16F16F16 = 2, +} a3da_compress_f16; + +typedef enum a3da_ep_type { + A3DA_EP_NONE = 0, + A3DA_EP_LINEAR = 1, + A3DA_EP_CYCLE = 2, + A3DA_EP_CYCLE_OFFSET = 3, +} a3da_ep_type; // Pre/Post Infinity + +typedef enum a3da_event_type { + A3DA_EVENT_MISC = 0x00, + A3DA_EVENT_FILT = 0x01, + A3DA_EVENT_FX = 0x02, + A3DA_EVENT_SND = 0x03, + A3DA_EVENT_MOT = 0x04, + A3DA_EVENT_A2D = 0x05, +} a3da_event_type; + +typedef enum a3da_fog_flags { + A3DA_FOG_COLOR = 0x01, + A3DA_FOG_DENSITY = 0x02, + A3DA_FOG_END = 0x04, + A3DA_FOG_START = 0x08, +} a3da_fog_flags; + +typedef enum a3da_format { + A3DA_FORMAT_DT = 0, + A3DA_FORMAT_F = 1, + A3DA_FORMAT_AFT = 2, + A3DA_FORMAT_F2 = 3, + A3DA_FORMAT_MGF = 4, + A3DA_FORMAT_X = 5, + A3DA_FORMAT_XHD = 6, +} a3da_format; + +typedef enum a3da_key_flags { + A3DA_KEY_BIN_OFFSET = 0x01, +} a3da_key_flags; + +typedef enum a3da_key_type { + A3DA_KEY_NONE = 0, + A3DA_KEY_STATIC = 1, + A3DA_KEY_LINEAR = 2, + A3DA_KEY_HERMITE = 3, + A3DA_KEY_HOLD = 4, +} a3da_key_type; + +typedef enum a3da_light_flags { + A3DA_LIGHT_AMBIENT = 0x0001, + A3DA_LIGHT_CONE_ANGLE = 0x0002, + A3DA_LIGHT_CONSTANT = 0x0004, + A3DA_LIGHT_DIFFUSE = 0x0008, + A3DA_LIGHT_DROP_OFF = 0x0010, + A3DA_LIGHT_FAR = 0x0020, + A3DA_LIGHT_INTENSITY = 0x0040, + A3DA_LIGHT_LINEAR = 0x0080, + A3DA_LIGHT_POSITION = 0x0100, + A3DA_LIGHT_QUADRATIC = 0x0200, + A3DA_LIGHT_SPECULAR = 0x0400, + A3DA_LIGHT_SPOT_DIRECTION = 0x0800, + A3DA_LIGHT_TONE_CURVE = 0x1000, +} a3da_light_flags; + +typedef enum a3da_material_list_flags { + A3DA_MATERIAL_LIST_BLEND_COLOR = 0x01, + A3DA_MATERIAL_LIST_GLOW_INTENSITY = 0x02, + A3DA_MATERIAL_LIST_INCANDESCENCE = 0x04, +} a3da_material_list_flags; + +typedef enum a3da_model_transform_flags { + A3DA_MODEL_TRANSFORM_BIN_OFFSET = 0x01, +} a3da_model_transform_flags; + +typedef enum a3da_object_node_flags { + A3DA_OBJECT_NODE_JOINT_ORIENT = 0x01, +} a3da_object_node_flags; + +typedef enum a3da_object_texture_transform_flags { + A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_U = 0x001, + A3DA_OBJECT_TEXTURE_TRANSFORM_COVERAGE_V = 0x002, + A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_U = 0x004, + A3DA_OBJECT_TEXTURE_TRANSFORM_OFFSET_V = 0x008, + A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_U = 0x010, + A3DA_OBJECT_TEXTURE_TRANSFORM_REPEAT_V = 0x020, + A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE = 0x040, + A3DA_OBJECT_TEXTURE_TRANSFORM_ROTATE_FRAME = 0x080, + A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_U = 0x100, + A3DA_OBJECT_TEXTURE_TRANSFORM_TRANSLATE_FRAME_V = 0x200, +} a3da_object_texture_transform_flags; + +typedef enum a3da_play_control_flags { + A3DA_PLAY_CONTROL_DIV = 0x01, + A3DA_PLAY_CONTROL_OFFSET = 0x02, +} a3da_play_control_flags; + +typedef enum a3da_post_process_flags { + A3DA_POST_PROCESS_INTENSITY = 0x01, + A3DA_POST_PROCESS_LENS_FLARE = 0x02, + A3DA_POST_PROCESS_LENS_GHOST = 0x04, + A3DA_POST_PROCESS_LENS_SHAFT = 0x08, + A3DA_POST_PROCESS_RADIUS = 0x10, + A3DA_POST_PROCESS_SCENE_FADE = 0x20, +} a3da_post_process_flags; + +typedef enum a3da_rgba_flags { + A3DA_RGBA_R = 0x01, + A3DA_RGBA_G = 0x02, + A3DA_RGBA_B = 0x04, + A3DA_RGBA_A = 0x08, +} a3da_rgba_flags; + +typedef struct a3da_ambient a3da_ambient; +typedef struct a3da_camera_auxiliary a3da_camera_auxiliary; +typedef struct a3da_camera_root a3da_camera_root; +typedef struct a3da_camera_root_view_point a3da_camera_root_view_point; +typedef struct a3da_chara a3da_chara; +typedef struct a3da_curve a3da_curve; +typedef struct a3da_dof a3da_dof; +typedef struct a3da_event a3da_event; +typedef struct a3da_fog a3da_fog; +typedef struct a3da_key a3da_key; +typedef struct a3da_light a3da_light; +typedef struct a3da_m_object_hrc a3da_m_object_hrc; +typedef struct a3da_material_list a3da_material_list; +typedef struct a3da_model_transform a3da_model_transform; +typedef struct a3da_object a3da_object; +typedef struct a3da_object_hrc a3da_object_hrc; +typedef struct a3da_object_instance a3da_object_instance; +typedef struct a3da_object_node a3da_object_node; +typedef struct a3da_object_texture_pattern a3da_object_texture_pattern; +typedef struct a3da_object_texture_transform a3da_object_texture_transform; +typedef struct a3da_play_control a3da_play_control; +typedef struct a3da_point a3da_point; +typedef struct a3da_post_process a3da_post_process; +typedef struct a3da_rgba a3da_rgba; +typedef struct a3da_vec3 a3da_vec3; + +vector(a3da_ambient) +vector(a3da_model_transform) +vector(a3da_camera_root) +vector(a3da_chara) +vector(a3da_curve) +vector(a3da_event) +vector(a3da_fog) +vector(a3da_light) +vector(a3da_m_object_hrc) +vector(a3da_material_list) +vector(a3da_object) +vector(a3da_object_hrc) +vector(a3da_object_instance) +vector(a3da_object_node) +vector(a3da_object_texture_pattern) +vector(a3da_object_texture_transform) +vector(a3da_point) + +struct a3da_key { + a3da_key_flags flags; + int32_t bin_offset; + a3da_key_type type; + a3da_ep_type ep_type_pre; + a3da_ep_type ep_type_post; + vector_kft3 keys; + float_t max; + bool raw_data; + bool raw_data_binary; + int32_t raw_data_value_list_size; + int32_t raw_data_value_list_offset; + float_t value; +}; + +struct a3da_rgba { + a3da_rgba_flags flags; + a3da_key r; + a3da_key g; + a3da_key b; + a3da_key a; +}; + +struct a3da_vec3 { + a3da_key x; + a3da_key y; + a3da_key z; +}; + +struct a3da_model_transform { + a3da_model_transform_flags flags; + int32_t bin_offset; + a3da_vec3 rotation; + a3da_vec3 scale; + a3da_vec3 translation; + a3da_key visibility; +}; + +struct a3da_ambient { + a3da_ambient_flags flags; + a3da_rgba light_diffuse; + string name; + a3da_rgba rim_light_diffuse; +}; + +struct a3da_camera_auxiliary { + a3da_camera_auxiliary_flags flags; + a3da_key auto_exposure; + a3da_key exposure; + a3da_key exposure_rate; + a3da_key gamma; + a3da_key gamma_rate; + a3da_key saturate; +}; + +struct a3da_camera_root_view_point { + a3da_camera_root_view_point_flags flags; + float_t aspect; + float_t camera_aperture_h; + float_t camera_aperture_w; + a3da_key focal_length; + a3da_key fov; + bool fov_is_horizontal; + a3da_model_transform model_transform; + a3da_key roll; +}; + +struct a3da_camera_root { + a3da_model_transform interest; + a3da_model_transform model_transform; + a3da_camera_root_view_point view_point; +}; + +struct a3da_chara { + a3da_model_transform model_transform; + string name; +}; + +struct a3da_curve { + a3da_key curve; + string name; +}; + +struct a3da_dof { + bool has_dof; + a3da_model_transform model_transform; +}; + +struct a3da_event { + float_t begin; + float_t clip_begin; + float_t clip_end; + float_t end; + string name; + string param_1; + string ref; + float_t time_ref_scale; + a3da_event_type type; +}; + +struct a3da_fog { + a3da_fog_flags flags; + a3da_rgba color; + a3da_key density; + a3da_key end; + fog_id id; + a3da_key start; +}; + +struct a3da_light { + a3da_light_flags flags; + a3da_rgba ambient; + a3da_key cone_angle; + a3da_key constant; + a3da_rgba diffuse; + a3da_key drop_off; + a3da_key _far; + light_id id; + a3da_key intensity; + a3da_key linear; + a3da_model_transform position; + a3da_key quadratic; + a3da_rgba specular; + a3da_model_transform spot_direction; + a3da_rgba tone_curve; + string type; +}; + +struct a3da_m_object_hrc { + vector_a3da_object_instance instance; + a3da_model_transform model_transform; + string name; + vector_a3da_object_node node; +}; + +struct a3da_material_list { + a3da_material_list_flags flags; + a3da_rgba blend_color; + a3da_key glow_intensity; + a3da_rgba incandescence; + string name; +}; + +struct a3da_object { + a3da_model_transform model_transform; + string morph; + float_t morph_offset; + string name; + string parent_name; + string parent_node; + string pattern; + float_t pattern_offset; + vector_a3da_object_texture_pattern texture_pattern; + vector_a3da_object_texture_transform texture_transform; + string uid_name; +}; + +struct a3da_object_hrc { + string name; + vector_a3da_object_node node; + string parent_name; + string parent_node; + bool shadow; + string uid_name; +}; + +struct a3da_object_instance { + a3da_model_transform model_transform; + string name; + bool shadow; + string uid_name; +}; + +struct a3da_object_node { + a3da_object_node_flags flags; + vec3 joint_orient; + a3da_model_transform model_transform; + string name; + int32_t parent; +}; + +struct a3da_object_texture_pattern { + string name; + string pattern; + float_t pattern_offset; +}; + +struct a3da_object_texture_transform { + a3da_object_texture_transform_flags flags; + a3da_key coverage_u; + a3da_key coverage_v; + string name; + a3da_key offset_u; + a3da_key offset_v; + a3da_key repeat_u; + a3da_key repeat_v; + a3da_key rotate; + a3da_key rotate_frame; + a3da_key translate_frame_u; + a3da_key translate_frame_v; +}; + +struct a3da_play_control { + a3da_play_control_flags flags; + float_t begin; + int32_t div; + float_t fps; + float_t offset; + float_t size; +}; + +struct a3da_point { + a3da_model_transform model_transform; + string name; +}; + +struct a3da_post_process { + a3da_post_process_flags flags; + a3da_rgba intensity; + a3da_key lens_flare; + a3da_key lens_ghost; + a3da_key lens_shaft; + a3da_rgba radius; + a3da_rgba scene_fade; +}; + +typedef struct a3da { + bool ready; + bool compressed; + a3da_format format; + + a3da_compress_f16 _compress_f16; + string _file_name; + string _property_version; + string _converter_version; + + vector_a3da_ambient ambient; + vector_string auth_2d; + a3da_camera_auxiliary camera_auxiliary; + vector_a3da_camera_root camera_root; + vector_a3da_chara chara; + vector_a3da_curve curve; + a3da_dof dof; + vector_a3da_event event; + vector_a3da_fog fog; + vector_a3da_light light; + vector_a3da_m_object_hrc m_object_hrc; + vector_string m_object_hrc_list; + vector_a3da_material_list material_list; + vector_string motion; + vector_a3da_object object; + vector_a3da_object_hrc object_hrc; + vector_string object_hrc_list; + vector_string object_list; + a3da_play_control play_control; + vector_a3da_point point; + a3da_post_process post_process; +} a3da; + +extern void a3da_init(a3da* a); +extern void a3da_read(a3da* a, char* path); +extern void a3da_wread(a3da* a, wchar_t* path); +extern void a3da_mread(a3da* a, void* data, size_t length); +extern void a3da_write(a3da* a, char* path); +extern void a3da_wwrite(a3da* a, wchar_t* path); +extern void a3da_mwrite(a3da* a, void** data, size_t* length); +extern bool a3da_load_file(void* data, char* path, char* file, uint32_t hash); +extern void a3da_free(a3da* a); + +extern void a3da_key_free(a3da_key* k); +extern void a3da_rgba_free(a3da_rgba* rgba); +extern void a3da_vec3_free(a3da_vec3* vec); +extern void a3da_model_transform_free(a3da_model_transform* mt); + +extern void a3da_ambient_free(a3da_ambient* a); +extern void a3da_camera_auxiliary_free(a3da_camera_auxiliary* ca); +extern void a3da_camera_root_free(a3da_camera_root* cr); +extern void a3da_camera_root_view_point_free(a3da_camera_root_view_point* crvp); +extern void a3da_chara_free(a3da_chara* c); +extern void a3da_curve_free(a3da_curve* c); +extern void a3da_dof_free(a3da_dof* d); +extern void a3da_event_free(a3da_event* e); +extern void a3da_fog_free(a3da_fog* f); +extern void a3da_light_free(a3da_light* l); +extern void a3da_m_object_hrc_free(a3da_m_object_hrc* moh); +extern void a3da_material_list_free(a3da_material_list* ml); +extern void a3da_object_free(a3da_object* o); +extern void a3da_object_hrc_free(a3da_object_hrc* oh); +extern void a3da_object_instance_free(a3da_object_instance* oi); +extern void a3da_object_node_free(a3da_object_node* on); +extern void a3da_object_texture_pattern_free(a3da_object_texture_pattern* otp); +extern void a3da_object_texture_transform_free(a3da_object_texture_transform* ott); +extern void a3da_point_free(a3da_point* p); +extern void a3da_post_process_free(a3da_post_process* pp); diff --git a/src/KKdLib/a3da_data.c b/src/KKdLib/a3da_data.c deleted file mode 100644 index 00e79773..00000000 --- a/src/KKdLib/a3da_data.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "a3da_data.h" - -auth_3d_data_struct* auth_3d_data_to_auth_3d_struct(auth_3d_data* d) { - if (!d) - return 0; - - auth_3d_data_struct* a = force_malloc(sizeof(auth_3d_data_struct)); - - if (!a) - return 0; - - memset(a, 0, sizeof(auth_3d_data_struct)); - - a->max_frames = d->max; - if (d->type > AUTH_3D_DATA_STATIC && d->length > 1) { - a->type = d->type; - a->length = d->length; - a->keys = d->keys; - a->ep_type_post = d->ep_type_post; - a->ep_type_pre = d->ep_type_pre; - a->frame_delta = d->keys[d->length - 1].frame - d->keys[0].frame; - a->value_delta = d->keys[d->length - 1].value - d->keys[0].value; - } - else { - a->type = d->type; - a->value = d->type > AUTH_3D_DATA_NONE ? d->value : 0.0f; - a->ep_type_post = d->ep_type_post; - a->ep_type_pre = d->ep_type_pre; - a->frame_delta = a->max_frames; - a->value_delta = a->value; - } - return a; -} diff --git a/src/KKdLib/a3da_data.h b/src/KKdLib/a3da_data.h deleted file mode 100644 index d9ba8711..00000000 --- a/src/KKdLib/a3da_data.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "default.h" -#include "kf.h" -#include "auth_3d.h" - -typedef struct auth_3d_data_struct { - auth_3d_data_type type; - float_t value; - float_t max_frames; - auth_3d_ep_type ep_type_pre; - auth_3d_ep_type ep_type_post; - float_t frame_delta; - float_t value_delta; - int32_t padding; - kft3* first_key; - kft3* second_key; - kft3* after_last_key; - size_t length; - kft3* keys; //Used only in-game and points to KFT3 Array -} auth_3d_data_struct; - -extern auth_3d_data_struct* auth_3d_data_to_auth_3d_data_struct(auth_3d_data* d); diff --git a/src/KKdLib/a3dai.c b/src/KKdLib/a3dai.c deleted file mode 100644 index e498cb98..00000000 --- a/src/KKdLib/a3dai.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "a3dai.h" -#include "interpolation.h" - -static void a3dai_interpolate(a3dai* interp); - -a3dai* a3da_data_to_a3dai(auth_3d_data* data, float_t interpolation_framerate, float_t requested_framerate) { - if (!data) - return 0; - - auth_3d_data_struct* s = auth_3d_data_to_auth_3d_data_struct(data); - - if (!s) - return 0; - - a3dai* interp = force_malloc(sizeof(a3dai)); - - if (!interp) - return 0; - - memset(interp, 0, sizeof(a3dai)); - - interp->time = 0.0f; - interp->auth_3d = s; - interp->frame = 0.0f; - interp->delta_frame = interpolation_framerate / requested_framerate; - interp->interpolation_framerate = interpolation_framerate; - interp->requested_framerate = requested_framerate; - interp->value = 0.0f; - interp->first_key = interp->last_key = 0; - a3dai_reset(interp); - - if (s->keys && s->length) { - interp->first_key = s->keys; - interp->last_key = s->keys + s->length - 1; - } - return interp; -} - -a3dai* a3da_head_to_a3dai(auth_3d_data_struct* s, float_t interpolation_framerate, float_t requested_framerate) { - if (!s) - return 0; - - a3dai* interp = force_malloc(sizeof(a3dai)); - - if (!interp) - return 0; - - memset(interp, 0, sizeof(a3dai)); - - interp->time = 0.0f; - interp->auth_3d = s; - interp->frame = 0.0f; - interp->delta_frame = interpolation_framerate / requested_framerate; - interp->interpolation_framerate = interpolation_framerate; - interp->requested_framerate = requested_framerate; - interp->value = 0.0f; - interp->first_key = interp->last_key = 0; - a3dai_reset(interp); - - if (s->keys && s->length) { - interp->first_key = s->keys; - interp->last_key = s->keys + s->length - 1; - } - return interp; -} - -inline void a3dai_set_interpolation_framerate(a3dai* interp, float_t interpolation_framerate) { - interp->interpolation_framerate = interpolation_framerate; - interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; -} - -inline void a3dai_set_requested_framerate(a3dai* interp, float_t requested_framerate) { - interp->requested_framerate = requested_framerate; - interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; -} - -inline void a3dai_update(a3dai* interp) { - interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; -} - -inline void a3dai_reset(a3dai* interp) { - interp->delta_frame = interp->interpolation_framerate / interp->requested_framerate; - interp->frame = 0.0f; - interp->time = interp->frame / interp->requested_framerate; -} - -float_t a3dai_set_time(a3dai* interp, float_t time) { - if (!interp || !interp->auth_3d || !interp->auth_3d->keys || !interp->auth_3d->length) - return 0.0f; - - interp->frame = time * interp->interpolation_framerate; - interp->time = time; - - switch (interp->auth_3d->type) { - case AUTH_3D_DATA_STATIC: - interp->value = interp->auth_3d->value; - break; - case AUTH_3D_DATA_LINEAR: - case AUTH_3D_DATA_HERMITE: - case AUTH_3D_DATA_HOLD: - a3dai_interpolate(interp); - break; - default: - interp->value = 0.0f; - break; - } - return interp->value; -} - -float_t a3dai_set_frame(a3dai* interp, float_t frame) { - if (!interp || !interp->auth_3d || !interp->auth_3d->keys || !interp->auth_3d->length) - return 0.0f; - - interp->frame = frame * interp->delta_frame; - interp->time = frame / interp->requested_framerate; - - switch (interp->auth_3d->type) { - case AUTH_3D_DATA_STATIC: - interp->value = interp->auth_3d->value; - break; - case AUTH_3D_DATA_LINEAR: - case AUTH_3D_DATA_HERMITE: - case AUTH_3D_DATA_HOLD: - a3dai_interpolate(interp); - break; - default: - interp->value = 0.0f; - break; - } - return interp->value; -} - -float_t a3dai_add_time(a3dai* interp, float_t time) { - if (!interp || !interp->auth_3d || !interp->auth_3d->keys || !interp->auth_3d->length) - return 0.0f; - - interp->frame = time * interp->interpolation_framerate; - interp->time += time; - - switch (interp->auth_3d->type) { - case AUTH_3D_DATA_STATIC: - interp->value = interp->auth_3d->value; - break; - case AUTH_3D_DATA_LINEAR: - case AUTH_3D_DATA_HERMITE: - case AUTH_3D_DATA_HOLD: - a3dai_interpolate(interp); - break; - default: - interp->value = 0.0f; - break; - } - return interp->value; -} - -float_t a3dai_next_frame(a3dai* interp) { - if (!interp || !interp->auth_3d || !interp->auth_3d->keys || !interp->auth_3d->length) - return 0.0f; - - interp->frame += interp->delta_frame; - interp->time = interp->frame / interp->interpolation_framerate; - - switch (interp->auth_3d->type) { - case AUTH_3D_DATA_STATIC: - interp->value = interp->auth_3d->value; - break; - case AUTH_3D_DATA_LINEAR: - case AUTH_3D_DATA_HERMITE: - case AUTH_3D_DATA_HOLD: - a3dai_interpolate(interp); - break; - default: - interp->value = 0.0f; - break; - } - return interp->value; -} - -static void a3dai_interpolate(a3dai* interp) { - float_t offset; - float_t frame = interp->frame; - - kft3* first_key = interp->first_key; - kft3* last_key = interp->last_key; - if (frame <= first_key->frame) { - float_t delta_frame = first_key->frame - frame; - switch (interp->auth_3d->ep_type_pre) { - case AUTH_3D_EP_NONE: - default: - interp->value = first_key->value; - return; - case AUTH_3D_EP_LINEAR: - interp->value = first_key->value - delta_frame * first_key->tangent1; - return; - case AUTH_3D_EP_CYCLE: - frame = last_key->frame - fmodf(delta_frame, interp->auth_3d->frame_delta); - offset = 0.0f; - break; - case AUTH_3D_EP_CYCLE_OFFSET: - frame = last_key->frame - fmodf(delta_frame, interp->auth_3d->frame_delta); - offset = -(float_t)((int32_t)(delta_frame / interp->auth_3d->frame_delta) + 1) - * interp->auth_3d->value_delta; - break; - } - } - else if (frame >= last_key->frame) { - float_t delta_frame = frame - last_key->frame; - switch (interp->auth_3d->ep_type_post) { - case AUTH_3D_EP_NONE: - default: - interp->value = last_key->value; - return; - case AUTH_3D_EP_LINEAR: - interp->value = last_key->value + delta_frame * last_key->tangent2; - return; - case AUTH_3D_EP_CYCLE: - frame = first_key->frame + fmodf(delta_frame, interp->auth_3d->frame_delta); - offset = 0.0f; - break; - case AUTH_3D_EP_CYCLE_OFFSET: - frame = first_key->frame + fmodf(delta_frame, interp->auth_3d->frame_delta); - offset = (float_t)((int32_t)(delta_frame / interp->auth_3d->frame_delta) + 1) - * interp->auth_3d->value_delta; - break; - } - } - else - offset = 0.0f; - - auth_3d_data_type type = interp->auth_3d->type; - kft3* keys = interp->auth_3d->keys; - size_t key = 0; - size_t length = interp->auth_3d->length; - size_t temp; - while (length > 0) - if (frame > keys[key + (temp = length >> 1)].frame) { - key += temp + 1; - length -= temp + 1; - } - else - length = temp; - - if (key == 0) { - interp->value = interp->first_key->value; - return; - } - else if (key == interp->auth_3d->length) { - interp->value = interp->last_key->value; - return; - } - - kft3* c, * n; - c = &keys[key - 1]; - n = &keys[key]; - - float_t value; - switch (interp->auth_3d->type) { - case AUTH_3D_DATA_LINEAR: - if (c->frame < n->frame) - value = interpolate_linear_value(c->value, n->value, c->frame, n->frame, frame); - else - value = c->value; - break; - case AUTH_3D_DATA_HERMITE: - if (c->frame < n->frame) - value = interpolate_chs_value(c->value, n->value, - c->tangent2, n->tangent1, c->frame, n->frame, frame); - else - value = c->value; - break; - case AUTH_3D_DATA_HOLD: - if (frame < n->frame) - value = c->value; - else - value = n->value; - break; - default: - value = 0.0f; - break; - } - interp->value = value + offset; -} diff --git a/src/KKdLib/a3dai.h b/src/KKdLib/a3dai.h deleted file mode 100644 index 4721f5bd..00000000 --- a/src/KKdLib/a3dai.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "default.h" -#include "kf.h" -#include "auth_3d.h" -#include "a3da_data.h" - -typedef struct a3dai { - auth_3d_data_struct* auth_3d; - float_t frame; - float_t time; - float_t value; - float_t delta_frame; - float_t interpolation_framerate; - float_t requested_framerate; - - kft3* first_key; - kft3* last_key; -} a3dai; - -extern a3dai* a3da_data_to_a3dai(auth_3d_data* data, - float_t interpolation_framerate, float_t requested_framerate); -extern a3dai* a3da_head_to_a3dai(auth_3d_data_struct* data, - float_t interpolation_framerate, float_t requested_framerate); -extern void a3dai_set_interpolation_framerate(a3dai* interp, float_t interpolation_framerate); -extern void a3dai_set_requested_framerate(a3dai* interp, float_t requested_framerate); -extern void a3dai_update(a3dai* interp); -extern void a3dai_reset(a3dai* interp); -extern float_t a3dai_set_time(a3dai* interp, float_t time); -extern float_t a3dai_set_frame(a3dai* interp, float_t frame); -extern float_t a3dai_add_time(a3dai* interp, float_t time); -extern float_t a3dai_next_frame(a3dai* interp); diff --git a/src/KKdLib/aet.c b/src/KKdLib/aet.c new file mode 100644 index 00000000..3901c367 --- /dev/null +++ b/src/KKdLib/aet.c @@ -0,0 +1,15 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "aet.h" + +vector_func(aet_marker) +vector_func(aet_layer_video) +vector_func(aet_layer_audio) +vector_func(aet_video_source) +vector_func(aet_camera) +vector_func(aet_composition) +vector_func(aet_video) +vector_func(aet_audio) diff --git a/src/KKdLib/aet.h b/src/KKdLib/aet.h index 1caccaa9..c9d38b4c 100644 --- a/src/KKdLib/aet.h +++ b/src/KKdLib/aet.h @@ -9,6 +9,7 @@ #include "default.h" #include "kf.h" +#include "string.h" #include "vec.h" typedef enum aet_layer_quality { @@ -113,17 +114,16 @@ typedef struct aet_audio { } aet_audio; typedef struct aet_video_source { - pointer_ptr_char name; + string name; + int32_t name_offset; uint32_t id; } aet_video_source; -count_pointer(kft2) - typedef struct aet_layer_audio { - count_pointer_kft2 volume_left; - count_pointer_kft2 volume_right; - count_pointer_kft2 pan_left; - count_pointer_kft2 pan_right; + vector_kft2 volume_left; + vector_kft2 volume_right; + vector_kft2 pan_left; + vector_kft2 pan_right; } aet_layer_audio; typedef struct aet_layer_transfer_mode { @@ -133,43 +133,43 @@ typedef struct aet_layer_transfer_mode { } aet_layer_transfer_mode; typedef struct aet_layer_video_3d { - count_pointer_kft2 anchor_z; - count_pointer_kft2 position_z; - count_pointer_kft2 direction_x; - count_pointer_kft2 direction_y; - count_pointer_kft2 direction_z; - count_pointer_kft2 rotation_x; - count_pointer_kft2 rotation_y; - count_pointer_kft2 scale_z; + vector_kft2 anchor_z; + vector_kft2 position_z; + vector_kft2 direction_x; + vector_kft2 direction_y; + vector_kft2 direction_z; + vector_kft2 rotation_x; + vector_kft2 rotation_y; + vector_kft2 scale_z; } aet_layer_video_3d; -pointer(aet_layer_video_3d); - typedef struct aet_layer_video { aet_layer_transfer_mode transfer_mode; uint8_t padding; - count_pointer_kft2 anchor_x; - count_pointer_kft2 anchor_y; - count_pointer_kft2 positionx; - count_pointer_kft2 position_y; - count_pointer_kft2 rotation; - count_pointer_kft2 scale_x; - count_pointer_kft2 scale_y; - count_pointer_kft2 opacit_y; - pointer_aet_layer_video_3d video_3d; + vector_kft2 anchor_x; + vector_kft2 anchor_y; + vector_kft2 positionx; + vector_kft2 position_y; + vector_kft2 rotation; + vector_kft2 scale_x; + vector_kft2 scale_y; + vector_kft2 opacit_y; + aet_layer_video_3d* video_3d; } aet_layer_video; typedef struct aet_marker { float_t frame; - pointer_ptr_char name; + string name; + int32_t name_offset; } aet_marker; -count_pointer(aet_marker) -count_pointer(aet_layer_video) -count_pointer(aet_layer_audio) +vector(aet_marker) +vector(aet_layer_video) +vector(aet_layer_audio) typedef struct aet_layer { - pointer_ptr_char name; + string name; + int32_t name_offset; float_t start_frame; float_t end_frame; float_t offset_frame; @@ -179,9 +179,9 @@ typedef struct aet_layer { aet_item_type type; int32_t video_item_offset; int32_t parent_layer_offset; - count_pointer_aet_marker marker; - count_pointer_aet_layer_video video; - count_pointer_aet_layer_audio audio; + vector_aet_marker marker; + vector_aet_layer_video video; + vector_aet_layer_audio audio; int32_t DataID; } aet_layer; @@ -192,7 +192,7 @@ typedef struct aet_composition { aet_layer* elements; } aet_composition; -count_pointer(aet_video_source); +vector(aet_video_source); typedef struct aet_video { int32_t offset; @@ -200,40 +200,45 @@ typedef struct aet_video { uint16_t width; uint16_t height; float_t frames; - count_pointer_aet_video_source video_source; + vector_aet_video_source video_source; } aet_video; -v3(count_pointer_kft2) - typedef struct aet_camera { - vec3_count_pointer_kft2 eye; - vec3_count_pointer_kft2 position; - vec3_count_pointer_kft2 direction; - vec3_count_pointer_kft2 rotation; - count_pointer_kft2 zoom; + vector_kft2 eye_x; + vector_kft2 eye_y; + vector_kft2 eye_z; + vector_kft2 position_x; + vector_kft2 position_y; + vector_kft2 position_z; + vector_kft2 direction_x; + vector_kft2 direction_y; + vector_kft2 direction_z; + vector_kft2 rotation_x; + vector_kft2 rotation_y; + vector_kft2 rotation_z; + vector_kft2 zoom; } aet_camera; -count_pointer(aet_composition) -count_pointer(aet_video) -count_pointer(aet_audio) -count_pointer(aet_camera) +vector(aet_camera) +vector(aet_composition) +vector(aet_video) +vector(aet_audio) typedef struct aet_scene { - pointer_ptr_char name; + string name; + int32_t name_offset; float_t start_frame; float_t end_frame; float_t frame_rate; uint32_t back_color; uint32_t width; uint32_t height; - count_pointer_aet_camera camera; - count_pointer_aet_composition composition; - count_pointer_aet_video video; - count_pointer_aet_audio audio; + vector_aet_camera camera; + vector_aet_composition composition; + vector_aet_video video; + vector_aet_audio audio; } aet_scene; -pointer(aet_scene) - typedef struct aet_header { - pointer_aet_scene scene; + aet_scene scene; } aet_header; diff --git a/src/KKdLib/auth_3d.h b/src/KKdLib/auth_3d.h deleted file mode 100644 index 8beaa470..00000000 --- a/src/KKdLib/auth_3d.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "default.h" -#include "vector.h" -#include "kf.h" -#include "vec.h" - -typedef enum auth_3d_compress_f16 { - AUTH_3D_COMPRESS_F32F32F32F32 = 0, - AUTH_3D_COMPRESS_I16F16F32F32 = 1, - AUTH_3D_COMPRESS_I16F16F16F16 = 2, -} auth_3d_compress_f16; - -typedef enum auth_3d_ep_type { - AUTH_3D_EP_NONE = 0, - AUTH_3D_EP_LINEAR = 1, - AUTH_3D_EP_CYCLE = 2, - AUTH_3D_EP_CYCLE_OFFSET = 3, -} auth_3d_ep_type; // Pre/Post Infinity - -typedef enum auth_3d_data_type { - AUTH_3D_DATA_NONE = 0, - AUTH_3D_DATA_STATIC = 1, - AUTH_3D_DATA_LINEAR = 2, - AUTH_3D_DATA_HERMITE = 3, - AUTH_3D_DATA_HOLD = 4, -} auth_3d_data_type; - -typedef enum auth_3d_camera_auxiliary_flags { - AUTH_3D_CAMERA_EXPOSURE = 0x01, - AUTH_3D_CAMERA_GAMMA = 0x02, - AUTH_3D_CAMERA_SATURATE = 0x04, - AUTH_3D_CAMERA_AUTO_EXPOSURE = 0x08, -} auth_3d_camera_auxiliary_flags; - -typedef enum auth_3d_post_process_flags { - AUTH_3D_POST_PROCESS_LENS_FLARE = 0x01, - AUTH_3D_POST_PROCESS_LENS_SHAFT = 0x02, - AUTH_3D_POST_PROCESS_LENS_GHOST = 0x04, - AUTH_3D_POST_PROCESS_RADIUS = 0x08, - AUTH_3D_POST_PROCESS_INTENSITY = 0x10, - AUTH_3D_POST_PROCESS_SCENE_FADE = 0x20, -} auth_3d_post_process_flags; - -typedef struct auth_3d_key_raw_data { - int32_t key_type; - char* value_type; - char** value_list; - int32_t value_list_size; -} auth_3d_key_raw_data; - -typedef struct auth_3d_comp_data_header { - auth_3d_data_type type : 8; - auth_3d_ep_type ep_type_pre : 4; - auth_3d_ep_type ep_type_post : 4; - uint32_t padding : 16; - float_t value; - float_t max; - uint32_t length; -} auth_3d_comp_data_header; - -typedef struct auth_3d_data { - auth_3d_data_type type; - size_t length; - size_t bin_offset; - auth_3d_ep_type ep_type_pre; - auth_3d_ep_type ep_type_post; - float_t max; - float_t value; - auth_3d_key_raw_data raw_data; - kft3* keys; -} auth_3d_data; - -typedef struct auth_3d_rgba_data { - auth_3d_data r_data; - auth_3d_data g_data; - auth_3d_data b_data; - auth_3d_data a_data; - bool has_r; - bool has_g; - bool has_b; - bool has_a; -} auth_3d_rgba_data; - -typedef struct auth_3d_vec3_data { - auth_3d_data x; - auth_3d_data y; - auth_3d_data z; -} auth_3d_vec3_data; - -typedef struct auth_3d_model_transform_data { - auth_3d_vec3_data scale_data; - auth_3d_vec3_data rotation_data; - auth_3d_vec3_data translation_data; - auth_3d_data visibility_data; - vec3 scale; - vec3 rotation; - vec3 translation; - bool visibility; -} auth_3d_model_transform_data; - diff --git a/src/KKdLib/auth_3d.c b/src/KKdLib/database/aet.c similarity index 73% rename from src/KKdLib/auth_3d.c rename to src/KKdLib/database/aet.c index 82ed8bd8..697a1055 100644 --- a/src/KKdLib/auth_3d.c +++ b/src/KKdLib/database/aet.c @@ -3,4 +3,4 @@ GitHub/GitLab: korenkonder */ -#include "auth_3d.h" +#include "aet.h" diff --git a/src/CLOUD/control.h b/src/KKdLib/database/aet.h similarity index 53% rename from src/CLOUD/control.h rename to src/KKdLib/database/aet.h index bee9a6da..ae73750d 100644 --- a/src/CLOUD/control.h +++ b/src/KKdLib/database/aet.h @@ -5,6 +5,4 @@ #pragma once -#include "shared.h" - -extern int32_t control_main(void* arg); +#include "../default.h" diff --git a/src/KKdLib/database/auth_3d.c b/src/KKdLib/database/auth_3d.c new file mode 100644 index 00000000..922628e5 --- /dev/null +++ b/src/KKdLib/database/auth_3d.c @@ -0,0 +1,466 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "auth_3d.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../key_val.h" +#include "../sort.h" +#include "../str_utils.h" + +vector_func(auth_3d_database_category) +vector_func(auth_3d_database_uid) +vector_func(auth_3d_database_uid_file) + +#define AUTH_3D_DATABASE_TEXT_BUF_SIZE 0x400 + +static void auth_3d_database_load_categories(auth_3d_database* auth_3d_db, + auth_3d_database_file* auth_3d_db_file, bool mdata); +static void auth_3d_database_load_uids(auth_3d_database* auth_3d_db, + auth_3d_database_file* auth_3d_db_file, bool mdata); + +static void auth_3d_database_file_read_inner(auth_3d_database_file* auth_3d_db_file, stream* s); +static void auth_3d_database_file_write_inner(auth_3d_database_file* auth_3d_db_file, stream* s); +static void auth_3d_database_file_read_text(auth_3d_database_file* auth_3d_db_file, void* data, size_t length); +static void auth_3d_database_file_write_text(auth_3d_database_file* auth_3d_db_file, void** data, size_t* length); + +void auth_3d_database_init(auth_3d_database* auth_3d_db) { + memset(auth_3d_db, 0, sizeof(auth_3d_database)); +} + +void auth_3d_database_merge_mdata(auth_3d_database* auth_3d_db, + auth_3d_database_file* base_auth_3d_db, auth_3d_database_file* mdata_auth_3d_db) { + if (!auth_3d_db || !base_auth_3d_db || !mdata_auth_3d_db + || !base_auth_3d_db->ready || !mdata_auth_3d_db->ready) + return; + + vector_auth_3d_database_category* category = &auth_3d_db->category; + vector_string* base_category = &base_auth_3d_db->category; + vector_string* mdata_category = &mdata_auth_3d_db->category; + + auth_3d_database_load_categories(auth_3d_db, base_auth_3d_db, false); + auth_3d_database_load_uids(auth_3d_db, base_auth_3d_db, false); + + auth_3d_database_load_categories(auth_3d_db, mdata_auth_3d_db, true); + auth_3d_database_load_uids(auth_3d_db, mdata_auth_3d_db, true); + + auth_3d_db->ready = true; +} + +void auth_3d_database_split_mdata(auth_3d_database* auth_3d_db, + auth_3d_database_file* base_auth_3d_db, auth_3d_database_file* mdata_auth_3d_db) { + if (!auth_3d_db || !base_auth_3d_db || !mdata_auth_3d_db + || !auth_3d_db->ready || !base_auth_3d_db->ready) + return; + +} + +void auth_3d_database_free(auth_3d_database* auth_3d_db) { + vector_auth_3d_database_category_free(&auth_3d_db->category, auth_3d_database_category_free); + vector_auth_3d_database_uid_free(&auth_3d_db->uid, auth_3d_database_uid_free); +} + +void auth_3d_database_file_init(auth_3d_database_file* auth_3d_db_file) { + memset(auth_3d_db_file, 0, sizeof(auth_3d_database_file)); + auth_3d_db_file->uid_max = -1; +} + +void auth_3d_database_file_read(auth_3d_database_file* auth_3d_db_file, char* path) { + if (!auth_3d_db_file || !path) + return; + + char* path_bin = str_utils_add(path, ".bin"); + if (path_check_file_exists(path_bin)) { + stream s; + io_open(&s, path_bin, "rb"); + if (s.io.stream) + auth_3d_database_file_read_inner(auth_3d_db_file, &s); + io_free(&s); + } + free(path_bin); +} + +void auth_3d_database_file_wread(auth_3d_database_file* auth_3d_db_file, wchar_t* path) { + if (!auth_3d_db_file || !path) + return; + + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + if (path_wcheck_file_exists(path_bin)) { + stream s; + io_wopen(&s, path_bin, L"rb"); + if (s.io.stream) + auth_3d_database_file_read_inner(auth_3d_db_file, &s); + io_free(&s); + } + free(path_bin); +} + +void auth_3d_database_file_mread(auth_3d_database_file* auth_3d_db_file, void* data, size_t length) { + if (!auth_3d_db_file || !data || !length) + return; + + stream s; + io_mopen(&s, data, length); + auth_3d_database_file_read_inner(auth_3d_db_file, &s); + io_free(&s); +} + +void auth_3d_database_file_write(auth_3d_database_file* auth_3d_db_file, char* path) { + if (!auth_3d_db_file || !path || !auth_3d_db_file->ready) + return; + + char* path_bin = str_utils_add(path, ".bin"); + stream s; + io_open(&s, path_bin, "wb"); + if (s.io.stream) + auth_3d_database_file_write_inner(auth_3d_db_file, &s); + io_free(&s); + free(path_bin); +} + +void auth_3d_database_file_wwrite(auth_3d_database_file* auth_3d_db_file, wchar_t* path) { + if (!auth_3d_db_file || !path || !auth_3d_db_file->ready) + return; + + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + stream s; + io_wopen(&s, path_bin, L"wb"); + if (s.io.stream) + auth_3d_database_file_write_inner(auth_3d_db_file, &s); + io_free(&s); + free(path_bin); +} + +void auth_3d_database_file_mwrite(auth_3d_database_file* auth_3d_db_file, void** data, size_t* length) { + if (!auth_3d_db_file || !data || !auth_3d_db_file->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + auth_3d_database_file_write_inner(auth_3d_db_file, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool auth_3d_database_file_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + auth_3d_database_file* auth_3d_db = data; + auth_3d_database_file_read(auth_3d_db, string_data(&s)); + + string_free(&s); + return auth_3d_db->ready; +} + +void auth_3d_database_file_free(auth_3d_database_file* auth_3d_db_file) { + vector_string_free(&auth_3d_db_file->category, string_free); + vector_auth_3d_database_uid_file_free(&auth_3d_db_file->uid, auth_3d_database_uid_file_free); +} + +void auth_3d_database_category_free(auth_3d_database_category* cat) { + string_free(&cat->name); + vector_int32_t_free(&cat->uid, 0); +} + +void auth_3d_database_uid_free(auth_3d_database_uid* uid) { + string_free(&uid->category); + string_free(&uid->name); +} + +void auth_3d_database_uid_file_free(auth_3d_database_uid_file* uid) { + string_free(&uid->category); + string_free(&uid->value); +} + +static void auth_3d_database_load_categories(auth_3d_database* auth_3d_db, + auth_3d_database_file* auth_3d_db_file, bool mdata) { + vector_auth_3d_database_category* category = &auth_3d_db->category; + vector_string* category_file = &auth_3d_db_file->category; + int32_t count_file = (int32_t)(category_file->end - category_file->begin); + + if (!mdata) + vector_auth_3d_database_category_reserve(category, count_file); + + for (int32_t i = 0; i < count_file; i++) { + string* m_cat = &category_file->begin[i]; + + char* str = string_data(m_cat); + size_t len = m_cat->length; + bool found = false; + for (auth_3d_database_category* i = category->begin; i != category->end; i++) + if (!memcmp(str, string_data(&i->name), min(len, i->name.length) + 1)) { + found = true; + break; + } + + if (found) + continue; + + auth_3d_database_category* cat = vector_auth_3d_database_category_reserve_back(category); + string_copy(m_cat, &cat->name); + cat->uid = vector_empty(int32_t); + } +} + +static void auth_3d_database_load_uids(auth_3d_database* auth_3d_db, + auth_3d_database_file* auth_3d_db_file, bool mdata) { + size_t uid_file_count = auth_3d_db_file->uid.end - auth_3d_db_file->uid.begin; + size_t uid_count = auth_3d_db->uid.end - auth_3d_db->uid.begin; + + bool reserve = true; + size_t uid_reserve = 0; + if (!mdata) + uid_reserve = uid_file_count; + else if (auth_3d_db_file->uid_max == -1) + uid_reserve = uid_count; + else if (auth_3d_db_file->uid_max >= uid_count) + uid_reserve = auth_3d_db_file->uid_max + 1ULL - uid_count; + else + reserve = false; + + if (reserve) { + vector_auth_3d_database_uid_reserve(&auth_3d_db->uid, uid_reserve); + auth_3d_db->uid.end += uid_reserve; + } + + vector_auth_3d_database_uid* uids = &auth_3d_db->uid; + vector_auth_3d_database_uid_file* uids_file = &auth_3d_db_file->uid; + for (size_t i = 0; i < uid_file_count; i++) { + auth_3d_database_uid_file* uid_file = &uids_file->begin[i]; + int32_t org_uid; + if (!mdata) + org_uid = (int32_t)i; + else if (uid_file->flags & AUTH_3D_DATABASE_UID_ORG_UID) + org_uid = uid_file->org_uid; + else + org_uid = (int32_t)(uid_count + i); + + auth_3d_database_uid* uid = &uids->begin[org_uid]; + uid->org_uid = org_uid; + uid->enabled = false; + + if (uid_file->value.length >= 3) { + if (string_data(&uid_file->value)[0] == 'A') + uid->enabled = true; + + if (mdata) + string_free(&uid->name); + string_init_length(&uid->name, string_data(&uid_file->value) + 2, uid_file->value.length - 2); + } + + if (uid->enabled) { + if (mdata) + string_replace(&uid_file->category, &uid->category); + else + string_copy(&uid_file->category, &uid->category); + + if (uid->category.length > 0) { + vector_auth_3d_database_category* category = &auth_3d_db->category; + for (auth_3d_database_category* j = category->begin; j != category->end; j++) { + if (!string_compare(&uid->category, &j->name)) + continue; + + bool found = false; + for (int32_t* k = j->uid.begin; k != j->uid.end; k++) + if (*k == org_uid) { + found = true; + break; + } + + if (!found) + vector_int32_t_push_back(&j->uid, &org_uid); + } + } + } + + if (uid_file->flags & AUTH_3D_DATABASE_UID_SIZE) + uid->size = uid_file->size; + else + uid->size = -1.0f; + } +} + +static void auth_3d_database_file_read_inner(auth_3d_database_file* auth_3d_db_file, stream* s) { + uint32_t signature = io_read_uint32_t(s); + if (signature != reverse_endianness_int32_t('#A3D')) + return; + + signature = io_read_uint32_t(s); + if ((signature & 0xFF) != 'A') + return; + + size_t string_offset = 0x10; + size_t string_length = (int32_t)(s->length - 0x10); + + io_set_position(s, string_offset, SEEK_SET); + void* a3da_data = force_malloc(string_length); + io_read(s, a3da_data, string_length); + auth_3d_database_file_read_text(auth_3d_db_file, a3da_data, string_length); + free(a3da_data); + + auth_3d_db_file->ready = true; +} + +static void auth_3d_database_file_write_inner(auth_3d_database_file* auth_3d_db_file, stream* s) { + void* a3da_data = 0; + size_t a3da_data_length = 0; + auth_3d_database_file_write_text(auth_3d_db_file, &a3da_data, &a3da_data_length); + io_write(s, a3da_data, a3da_data_length); + free(a3da_data); +} + +static void auth_3d_database_file_read_text(auth_3d_database_file* auth_3d_db_file, void* data, size_t length) { + char buf[AUTH_3D_DATABASE_TEXT_BUF_SIZE]; + int32_t count; + size_t len; + size_t len1; + size_t off; + + key_val kv; + key_val_init(&kv, data, length); + key_val lkv; + + len = 8; + memcpy(buf, "category", 8); + off = len; + + auth_3d_db_file->category = vector_empty(string); + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "category", &lkv)) { + vector_string* vc = &auth_3d_db_file->category; + + vector_string_reserve(vc, count); + vc->end += count; + for (int32_t i = 0; i < count; i++) { + string* c = &vc->begin[i]; + *c = string_empty; + len1 = sprintf_s(buf + len, AUTH_3D_DATABASE_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, ".value", 7, c); + } + key_val_free(&lkv); + } + + len = 3; + memcpy(buf, "uid", 3); + off = len; + + auth_3d_db_file->uid = vector_empty(auth_3d_database_uid_file); + if (!key_val_read_int32_t(&kv, buf, off, ".max", 5, &auth_3d_db_file->uid_max)) + auth_3d_db_file->uid_max = -1; + + if (key_val_read_int32_t(&kv, buf, off, ".length", 8, &count) + && key_val_get_local_key_val(&kv, "uid", &lkv)) { + vector_auth_3d_database_uid_file* vu = &auth_3d_db_file->uid; + + vector_auth_3d_database_uid_file_reserve(vu, count); + vu->end += count; + for (int32_t i = 0; i < count; i++) { + auth_3d_database_uid_file* u = &vu->begin[i]; + memset(u, 0, sizeof(auth_3d_database_uid_file)); + len1 = sprintf_s(buf + len, AUTH_3D_DATABASE_TEXT_BUF_SIZE - len, ".%d", i); + off = len + len1; + + key_val_read_string(&lkv, + buf, off, ".category", 10, &u->category); + if (key_val_read_int32_t(&lkv, + buf, off, ".org_uid", 9, &u->org_uid)) + u->flags |= AUTH_3D_DATABASE_UID_ORG_UID; + if (key_val_read_float_t(&lkv, + buf, off, ".size", 6, &u->size)) + u->flags |= AUTH_3D_DATABASE_UID_SIZE; + key_val_read_string(&lkv, + buf, off, ".value", 7, &u->value); + } + key_val_free(&lkv); + } + + key_val_free(&kv); +} + +static void auth_3d_database_file_write_text(auth_3d_database_file* auth_3d_db_file, void** data, size_t* length) { + char buf[AUTH_3D_DATABASE_TEXT_BUF_SIZE]; + int32_t count; + size_t len; + size_t len1; + size_t off; + + stream s; + io_mopen(&s, 0, 0); + + io_write(&s, "#A3DA__________\n", 16); + io_write(&s, "# date time was eliminated.\n", 28); + + vector_int32_t sort_index = vector_empty(int32_t); + if (auth_3d_db_file->category.end - auth_3d_db_file->category.begin) { + len = 8; + memcpy(buf, "category", 8); + off = len; + + vector_string* vc = &auth_3d_db_file->category; + count = (int32_t)(vc->end - vc->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + string* c = &vc->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, AUTH_3D_DATABASE_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, ".value", 7, c); + } + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + } + + if (auth_3d_db_file->uid.end - auth_3d_db_file->uid.begin) { + len = 3; + memcpy(buf, "uid", 3); + off = len; + + int32_t uid_max = -1; + vector_auth_3d_database_uid_file* vu = &auth_3d_db_file->uid; + count = (int32_t)(vu->end - vu->begin); + key_val_get_lexicographic_order(&sort_index, count); + for (int32_t i = 0; i < count; i++) { + auth_3d_database_uid_file* u = &vu->begin[sort_index.begin[i]]; + + len1 = sprintf_s(buf + len, AUTH_3D_DATABASE_TEXT_BUF_SIZE - len, ".%d", sort_index.begin[i]); + off = len + len1; + + key_val_write_string(&s, buf, off, ".category", 10, &u->category); + if (u->flags & AUTH_3D_DATABASE_UID_ORG_UID) + key_val_write_int32_t(&s, buf, off, ".org_uid", 9, u->org_uid); + if (u->flags & AUTH_3D_DATABASE_UID_SIZE) + key_val_write_float_t(&s, buf, off, ".size", 6, u->size); + key_val_write_string(&s, buf, off, ".value", 7, &u->value); + + if (u->flags & AUTH_3D_DATABASE_UID_ORG_UID && u->org_uid > uid_max) + uid_max = u->org_uid; + } + + if (uid_max == 0) + uid_max = count; + + off = len; + key_val_write_int32_t(&s, buf, off, ".length", 8, count); + key_val_write_int32_t(&s, buf, off, ".max", 5, uid_max); + } + + vector_int32_t_free(&sort_index, 0); + + io_mcopy(&s, data, length); + io_free(&s); +} diff --git a/src/KKdLib/database/auth_3d.h b/src/KKdLib/database/auth_3d.h new file mode 100644 index 00000000..5db3ebc1 --- /dev/null +++ b/src/KKdLib/database/auth_3d.h @@ -0,0 +1,78 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" + +typedef enum auth_3d_database_uid_flags { + AUTH_3D_DATABASE_UID_ORG_UID = 0x01, + AUTH_3D_DATABASE_UID_SIZE = 0x02, +} auth_3d_database_uid_flags; + +typedef struct auth_3d_database_uid { + bool enabled; + string category; + string name; + int32_t org_uid; + float_t size; +} auth_3d_database_uid; + +typedef struct auth_3d_database_uid_file { + auth_3d_database_uid_flags flags; + string category; + int32_t org_uid; + float_t size; + string value; +} auth_3d_database_uid_file; + +typedef struct auth_3d_database_category { + string name; + vector_int32_t uid; +} auth_3d_database_category; + +vector(auth_3d_database_category) + +vector(auth_3d_database_uid) + +typedef struct auth_3d_database { + bool ready; + + vector_auth_3d_database_category category; + vector_auth_3d_database_uid uid; +} auth_3d_database; + +vector(auth_3d_database_uid_file) + +typedef struct auth_3d_database_file { + bool ready; + + vector_string category; + vector_auth_3d_database_uid_file uid; + int32_t uid_max; +} auth_3d_database_file; + +extern void auth_3d_database_init(auth_3d_database* auth_3d_db); +extern void auth_3d_database_merge_mdata(auth_3d_database* auth_3d_db, + auth_3d_database_file* base_auth_3d_db, auth_3d_database_file* mdata_auth_3d_db); +extern void auth_3d_database_split_mdata(auth_3d_database* auth_3d_db, + auth_3d_database_file* base_auth_3d_db, auth_3d_database_file* mdata_auth_3d_db); +extern void auth_3d_database_free(auth_3d_database* auth_3d_db); + +extern void auth_3d_database_file_init(auth_3d_database_file* auth_3d_db_file); +extern void auth_3d_database_file_read(auth_3d_database_file* auth_3d_db_file, char* path); +extern void auth_3d_database_file_wread(auth_3d_database_file* auth_3d_db_file, wchar_t* path); +extern void auth_3d_database_file_mread(auth_3d_database_file* auth_3d_db_file, void* data, size_t length); +extern void auth_3d_database_file_write(auth_3d_database_file* auth_3d_db_file, char* path); +extern void auth_3d_database_file_wwrite(auth_3d_database_file* auth_3d_d_fileb, wchar_t* path); +extern void auth_3d_database_file_mwrite(auth_3d_database_file* auth_3d_db_file, void** data, size_t* length); +extern bool auth_3d_database_file_load_file(void* data, char* path, char* file, uint32_t hash); +extern void auth_3d_database_file_free(auth_3d_database_file* auth_3d_db_file); + +extern void auth_3d_database_category_free(auth_3d_database_category* cat); +extern void auth_3d_database_uid_free(auth_3d_database_uid* uid); +extern void auth_3d_database_uid_file_free(auth_3d_database_uid_file* uid); diff --git a/src/KKdLib/database/bone.c b/src/KKdLib/database/bone.c new file mode 100644 index 00000000..aa32117e --- /dev/null +++ b/src/KKdLib/database/bone.c @@ -0,0 +1,1479 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "bone.h" +#include "../f2/struct.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +typedef struct bone_database_skeleton_header { + ssize_t offset; + ssize_t bones_offset; + ssize_t positions_offset; + ssize_t unknown_value_offset; + ssize_t object_bone_names_offset; + ssize_t motion_bone_names_offset; + ssize_t parent_indices_offset; +} bone_database_skeleton_header; + +vector_func(bone_database_bone) +vector_func(bone_database_skeleton) + +static void bone_database_classic_read_inner(bone_database* bone_data, stream* s); +static void bone_database_classic_write_inner(bone_database* bone_data, stream* s); +static void bone_database_modern_read_inner(bone_database* bone_data, stream* s, uint32_t header_length); +static void bone_database_modern_write_inner(bone_database* bone_data, stream* s); +static ssize_t bone_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str); +static bool bone_database_strings_push_back_check(vector_string* vec, char* str); + +void bone_database_init(bone_database* bone_data) { + memset(bone_data, 0, sizeof(bone_database)); +} + +void bone_database_read(bone_database* bone_data, char* path, bool modern) { + if (!bone_data || !path) + return; + + if (!modern) { + char* path_bin = str_utils_add(path, ".bin"); + if (path_check_file_exists(path_bin)) { + stream s; + io_open(&s, path_bin, "rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + bone_database_classic_read_inner(bone_data, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + char* path_bon = str_utils_add(path, ".bon"); + if (path_check_file_exists(path_bon)) { + f2_struct st; + f2_struct_read(&st, path_bon); + if (st.header.signature == reverse_endianness_uint32_t('BONE')); { + stream s_bone; + io_mopen(&s_bone, st.data, st.length); + s_bone.is_big_endian = st.header.use_big_endian; + bone_database_modern_read_inner(bone_data, &s_bone, st.header.length); + io_free(&s_bone); + } + f2_struct_free(&st); + } + free(path_bon); + } +} + +void bone_database_wread(bone_database* bone_data, wchar_t* path, bool modern) { + if (!bone_data || !path) + return; + + if (!modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + if (path_wcheck_file_exists(path_bin)) { + stream s; + io_wopen(&s, path_bin, L"rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + bone_database_classic_read_inner(bone_data, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + wchar_t* path_bon = str_utils_wadd(path, L".bon"); + if (path_wcheck_file_exists(path_bon)) { + f2_struct st; + f2_struct_wread(&st, path_bon); + if (st.header.signature == reverse_endianness_uint32_t('BONE')); { + stream s_bone; + io_mopen(&s_bone, st.data, st.length); + s_bone.is_big_endian = st.header.use_big_endian; + bone_database_modern_read_inner(bone_data, &s_bone, st.header.length); + io_free(&s_bone); + } + f2_struct_free(&st); + } + free(path_bon); + } +} + +void bone_database_mread(bone_database* bone_data, void* data, size_t length, bool modern) { + if (!bone_data || !data || !length) + return; + + if (!modern) { + stream s; + io_mopen(&s, data, length); + bone_database_classic_read_inner(bone_data, &s); + io_free(&s); + } + else { + f2_struct st; + f2_struct_mread(&st, data, length); + if (st.header.signature == reverse_endianness_uint32_t('BONE')); { + stream s_bone; + io_mopen(&s_bone, st.data, st.length); + s_bone.is_big_endian = st.header.use_big_endian; + bone_database_modern_read_inner(bone_data, &s_bone, st.header.length); + io_free(&s_bone); + } + f2_struct_free(&st); + } +} + +void bone_database_write(bone_database* bone_data, char* path) { + if (!bone_data || !path || !bone_data->ready) + return; + + if (!bone_data->modern) { + char* path_bin = str_utils_add(path, ".bin"); + stream s; + io_open(&s, path_bin, "wb"); + if (s.io.stream) + bone_database_classic_write_inner(bone_data, &s); + io_free(&s); + free(path_bin); + } + else { + char* path_bon = str_utils_add(path, ".bon"); + stream s; + io_open(&s, path_bon, "wb"); + if (s.io.stream) + bone_database_modern_write_inner(bone_data, &s); + io_free(&s); + free(path_bon); + } +} + +void bone_database_wwrite(bone_database* bone_data, wchar_t* path) { + if (!bone_data || !path || !bone_data->ready) + return; + + if (!bone_data->modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + stream s; + io_wopen(&s, path_bin, L"wb"); + if (s.io.stream) + bone_database_classic_write_inner(bone_data, &s); + io_free(&s); + free(path_bin); + } + else { + wchar_t* path_bon = str_utils_wadd(path, L".bon"); + stream s; + io_wopen(&s, path_bon, L"wb"); + if (s.io.stream) + bone_database_modern_write_inner(bone_data, &s); + io_free(&s); + free(path_bon); + } +} + +void bone_database_mwrite(bone_database* bone_data, void** data, size_t* length) { + if (!bone_data || !data || !bone_data->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + if (!bone_data->modern) + bone_database_classic_write_inner(bone_data, &s); + else + bone_database_modern_write_inner(bone_data, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool bone_database_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + bone_database* bone_data = data; + bone_database_read(bone_data, string_data(&s), bone_data->modern); + + string_free(&s); + return bone_data->ready; +} + +void bone_database_bones_calculate_count(vector_bone_database_bone* bones, size_t* object_bone_count, + size_t* motion_bone_count, size_t* total_bone_count, size_t* ik_bone_count, size_t* chain_pos) { + size_t _object_bone_count = 0; + size_t _motion_bone_count = 0; + size_t _total_bone_count = 0; + size_t _ik_bone_count = 0; + size_t _chain_pos = 0; + for (bone_database_bone* i = bones->begin; i != bones->end; i++) + switch (i->type) { + case BONE_DATABASE_BONE_ROTATION: + case BONE_DATABASE_BONE_TYPE_1: + case BONE_DATABASE_BONE_POSITION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count++; + _chain_pos++; + break; + case BONE_DATABASE_BONE_POSITION_ROTATION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count++; + _ik_bone_count++; + _chain_pos++; + break; + case BONE_DATABASE_BONE_HEAD_IK_ROTATION: + _object_bone_count++; + _motion_bone_count++; + _total_bone_count += 3; + _ik_bone_count++; + _chain_pos += 2; + break; + case BONE_DATABASE_BONE_ARM_IK_ROTATION: + case BONE_DATABASE_BONE_LEGS_IK_ROTATION: + _object_bone_count += 3; + _motion_bone_count++; + _total_bone_count += 4; + _ik_bone_count++; + _chain_pos += 3; + break; + } + *object_bone_count = _object_bone_count; + *motion_bone_count = _motion_bone_count; + *total_bone_count = _total_bone_count; + *ik_bone_count = _ik_bone_count; + *chain_pos = _chain_pos; +} + +bool bone_database_get_skeleton(bone_database* bone_data, + char* name, bone_database_skeleton** skeleton) { + if (!skeleton) + return false; + + *skeleton = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *skeleton = i; + return true; + } + return false; +} + +int32_t bone_database_get_skeleton_bone_index(bone_database* bone_data, char* name, char* bone_name) { + if (!bone_data || !name || !bone_name) + return -1; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + for (bone_database_bone* j = i->bone.begin; j != i->bone.end; j++) + if (!str_utils_compare(string_data(&j->name), bone_name)) + return (int32_t)(j - i->bone.begin); + return -1; + } + return -1; +} + +bool bone_database_get_skeleton_bones(bone_database* bone_data, + char* name, vector_bone_database_bone** bone) { + if (!bone) + return false; + + *bone = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *bone = &i->bone; + return true; + } + return false; +} + +bool bone_database_get_skeleton_positions(bone_database* bone_data, + char* name, vector_vec3** positions) { + if (!positions) + return false; + + *positions = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *positions = &i->position; + return true; + } + return false; +} + +int32_t bone_database_get_skeleton_object_bone_index(bone_database* bone_data, + char* name, char* bone_name) { + if (!bone_data || !name || !bone_name) + return -1; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + vector_string* object_bones = &i->object_bone; + for (string* j = object_bones->begin; j != object_bones->end; j++) + if (!str_utils_compare(string_data(j), bone_name)) + return (int32_t)(j - object_bones->begin); + return -1; + } + return -1; +} + +bool bone_database_get_skeleton_object_bones(bone_database* bone_data, + char* name, vector_string** object_bones) { + if (!object_bones) + return false; + + *object_bones = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *object_bones = &i->object_bone; + return true; + } + return false; +} + +int32_t bone_database_get_skeleton_motion_bone_index(bone_database* bone_data, + char* name, char* bone_name) { + if (!bone_data || !name || !bone_name) + return -1; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + vector_string* motion_bones = &i->motion_bone; + for (string* j = motion_bones->begin; j != motion_bones->end; j++) + if (!str_utils_compare(string_data(j), bone_name)) + return (int32_t)(j - motion_bones->begin); + return -1; + } + return -1; +} + +bool bone_database_get_skeleton_motion_bones(bone_database* bone_data, + char* name, vector_string** motion_bones) { + if (!motion_bones) + return false; + + *motion_bones = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *motion_bones = &i->motion_bone; + return true; + } + return false; +} + +bool bone_database_get_skeleton_parent_indices(bone_database* bone_data, + char* name, vector_uint16_t** parent_indices) { + if (!parent_indices) + return false; + + *parent_indices = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *parent_indices = &i->parent_index; + return true; + } + return false; +} + +bool bone_database_get_skeleton_heel_height(bone_database* bone_data, + char* name, float_t** unknown_value) { + if (!unknown_value) + return false; + + *unknown_value = 0; + if (!bone_data || !name) + return false; + + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + if (!str_utils_compare(string_data(&i->name), name)) { + *unknown_value = &i->heel_height; + return true; + } + return false; +} + +void bone_database_free(bone_database* bone_data) { + vector_bone_database_skeleton_free(&bone_data->skeleton, bone_database_skeleton_free); +} + +char* bone_database_skeleton_type_to_string(bone_database_skeleton_type type) { + switch (type) { + case BONE_DATABASE_SKELETON_COMMON: + return "CMN"; + case BONE_DATABASE_SKELETON_MIKU: + return "MIK"; + case BONE_DATABASE_SKELETON_KAITO: + return "KAI"; + case BONE_DATABASE_SKELETON_LEN: + return "LEN"; + case BONE_DATABASE_SKELETON_LUKA: + return "LUK"; + case BONE_DATABASE_SKELETON_MEIKO: + return "MEI"; + case BONE_DATABASE_SKELETON_RIN: + return "RIN"; + case BONE_DATABASE_SKELETON_HAKU: + return "HAK"; + case BONE_DATABASE_SKELETON_NERU: + return "NER"; + case BONE_DATABASE_SKELETON_SAKINE: + return "SAK"; + case BONE_DATABASE_SKELETON_TETO: + return "TET"; + default: + return 0; + } +} + +void bone_database_bone_free(bone_database_bone* bone) { + string_free(&bone->name); +} + +void bone_database_skeleton_free(bone_database_skeleton* skel) { + vector_bone_database_bone_free(&skel->bone, bone_database_bone_free); + vector_vec3_free(&skel->position, 0);; + vector_string_free(&skel->object_bone, string_free); + vector_string_free(&skel->motion_bone, string_free); + vector_uint16_t_free(&skel->parent_index, 0); + string_free(&skel->name); +} + +static void bone_database_classic_read_inner(bone_database* bone_data, stream* s) { + uint32_t signature = io_read_uint32_t(s); + if (signature != 0x09102720) + return; + + uint32_t skeleton_count = io_read_uint32_t(s); + uint32_t skeleton_offsets_offset = io_read_uint32_t(s); + uint32_t skeleton_name_offsets_offset = io_read_uint32_t(s); + io_read(s, 0, 0x14); + + vector_bone_database_skeleton_reserve(&bone_data->skeleton, skeleton_count); + bone_data->skeleton.end += skeleton_count; + + io_position_push(s, skeleton_offsets_offset, SEEK_SET); + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + uint32_t skeleton_offset = io_read_uint32_t(s); + + io_position_push(s, skeleton_offset, SEEK_SET); + uint32_t bones_offset = io_read_uint32_t(s); + uint32_t position_count = io_read_uint32_t(s); + uint32_t positions_offset = io_read_uint32_t(s); + uint32_t unknown_value_offset = io_read_uint32_t(s); + uint32_t object_bone_count = io_read_uint32_t(s); + uint32_t object_bone_names_offset = io_read_uint32_t(s); + uint32_t motion_bone_count = io_read_uint32_t(s); + uint32_t motion_bone_names_offset = io_read_uint32_t(s); + uint32_t parent_indices_offset = io_read_uint32_t(s); + io_read(s, 0, 0x14); + + uint32_t bone_count = 0; + io_position_push(s, bones_offset, SEEK_SET); + while (true) { + if (io_read_uint8_t(s) == 0xFF) + break; + + io_read(s, 0, 0x0B); + bone_count++; + } + io_position_pop(s); + + vector_bone_database_bone_reserve(&skel->bone, bone_count); + skel->bone.end += bone_count; + + io_position_push(s, bones_offset, SEEK_SET); + for (uint32_t j = 0; j < bone_count; j++) { + bone_database_bone* bone = &skel->bone.begin[j]; + bone->type = io_read_uint8_t(s); + bone->has_parent = io_read_uint8_t(s) ? true : false; + bone->parent = io_read_uint8_t(s); + bone->pole_target = io_read_uint8_t(s); + bone->mirror = io_read_uint8_t(s); + bone->flags = io_read_uint8_t(s); + io_read(s, 0, 0x02); + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &bone->name); + } + io_position_pop(s); + + vector_vec3_reserve(&skel->position, position_count); + skel->position.end += position_count; + + io_position_push(s, positions_offset, SEEK_SET); + for (uint32_t j = 0; j < position_count; j++) { + vec3* position = &skel->position.begin[j]; + position->x = io_read_float_t(s); + position->y = io_read_float_t(s); + position->z = io_read_float_t(s); + } + io_position_pop(s); + + io_position_push(s, unknown_value_offset, SEEK_SET); + skel->heel_height = io_read_float_t(s); + io_position_pop(s); + + vector_string_reserve(&skel->object_bone, object_bone_count); + skel->object_bone.end += object_bone_count; + + io_position_push(s, object_bone_names_offset, SEEK_SET); + for (uint32_t j = 0; j < object_bone_count; j++) { + string* object_bone_name = &skel->object_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), object_bone_name); + } + io_position_pop(s); + + vector_string_reserve(&skel->motion_bone, motion_bone_count); + skel->motion_bone.end += motion_bone_count; + + io_position_push(s, motion_bone_names_offset, SEEK_SET); + for (uint32_t j = 0; j < motion_bone_count; j++) { + string* motion_bone_name = &skel->motion_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), motion_bone_name); + } + io_position_pop(s); + + vector_uint16_t_reserve(&skel->parent_index, motion_bone_count); + skel->parent_index.end += motion_bone_count; + + io_position_push(s, parent_indices_offset, SEEK_SET); + io_read(s, skel->parent_index.begin, motion_bone_count * sizeof(uint16_t)); + io_position_pop(s); + io_position_pop(s); + } + io_position_pop(s); + + io_position_push(s, skeleton_name_offsets_offset, SEEK_SET); + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skeleton = &bone_data->skeleton.begin[i]; + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &skeleton->name); + } + io_position_pop(s); + + bone_data->is_x = false; + bone_data->modern = false; + bone_data->ready = true; +} + +static void bone_database_classic_write_inner(bone_database* bone_data, stream* s) { + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + + uint32_t skeleton_count = (uint32_t)(bone_data->skeleton.end - bone_data->skeleton.begin); + ssize_t skeleton_offsets_offset = io_get_position(s); + io_write(s, 0, skeleton_count * 0x04ULL); + + ssize_t skeleton_name_offset = io_get_position(s); + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_string_null_terminated(s, &i->name); + + ssize_t skeleton_name_offsets_offset = io_get_position(s); + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) { + io_write_uint32_t(s, (uint32_t)skeleton_name_offset); + skeleton_name_offset += i->name.length + 1; + } + + vector_string strings = vector_empty(string); + vector_ssize_t string_offsets = vector_empty(ssize_t); + + ssize_t* skeleton_offsets = force_malloc_s(ssize_t, skeleton_count); + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + vector_string_reserve(&strings, bone_count); + vector_ssize_t_reserve(&string_offsets, bone_count); + + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(&j->name))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &j->name); + } + + if (bone_database_strings_push_back_check(&strings, "End")) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_utf8_string_null_terminated(s, "End"); + } + io_align_write(s, 0x04); + + ssize_t bones_offset = io_get_position(s); + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) { + io_write_uint8_t(s, (uint8_t)j->type); + io_write_uint8_t(s, j->has_parent ? 1 : 0); + io_write_uint8_t(s, j->parent); + io_write_uint8_t(s, j->pole_target); + io_write_uint8_t(s, j->mirror); + io_write_uint8_t(s, j->flags); + io_write(s, 0, 0x02); + io_write_uint32_t(s, (uint32_t)bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&j->name))); + } + + io_write_uint32_t(s, 0xFF); + io_write_uint32_t(s, 0xFF); + io_write_uint32_t(s, (uint32_t)bone_database_strings_get_string_offset(&strings, + &string_offsets, "End")); + + ssize_t positions_offset = io_get_position(s); + io_write(s, skel->position.begin, sizeof(vec3) * position_count); + + ssize_t unknown_value_offset = io_get_position(s); + io_write_float_t(s, skel->heel_height); + + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(j))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, j); + } + io_align_write(s, 0x04); + + ssize_t object_bone_names_offset = io_get_position(s); + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + io_write_uint32_t(s, (uint32_t)bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j))); + + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(j))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, j); + } + io_align_write(s, 0x04); + + ssize_t motion_bone_names_offset = io_get_position(s); + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + io_write_uint32_t(s, (uint32_t)bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j))); + + ssize_t parent_indices_offset = io_get_position(s); + io_write(s, skel->parent_index.begin, sizeof(uint16_t) * motion_bone_count); + io_align_write(s, 0x04); + + skeleton_offsets[skel - bone_data->skeleton.begin] = io_get_position(s); + io_write_uint32_t(s, (uint32_t)bones_offset); + io_write_uint32_t(s, position_count); + io_write_uint32_t(s, (uint32_t)positions_offset); + io_write_uint32_t(s, (uint32_t)unknown_value_offset); + io_write_uint32_t(s, object_bone_count); + io_write_uint32_t(s, (uint32_t)object_bone_names_offset); + io_write_uint32_t(s, motion_bone_count); + io_write_uint32_t(s, (uint32_t)motion_bone_names_offset); + io_write_uint32_t(s, (uint32_t)parent_indices_offset); + io_write(s, 0, 0x14); + + vector_string_clear(&strings, string_free); + vector_ssize_t_clear(&string_offsets, 0); + } + + io_position_push(s, 0x00, SEEK_SET); + io_write_uint32_t(s, 0x09102720); + io_write_uint32_t(s, skeleton_count); + io_write_uint32_t(s, (uint32_t)skeleton_offsets_offset); + io_write_uint32_t(s, (uint32_t)skeleton_name_offsets_offset); + io_write(s, 0, 0x14); + io_position_pop(s); + + io_position_push(s, skeleton_offsets_offset, SEEK_SET); + for (uint32_t i = 0; i < skeleton_count; i++) + io_write_uint32_t(s, (uint32_t)skeleton_offsets[i]); + io_position_pop(s); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + free(skeleton_offsets); +} + +static void bone_database_modern_read_inner(bone_database* bone_data, stream* s, uint32_t header_length) { + uint32_t signature = io_read_uint32_t_stream_reverse_endianness(s); + if (signature != 0x09102720) + return; + + bool is_x = true; + + io_set_position(s, 0x0C, SEEK_SET); + is_x &= io_read_uint32_t_stream_reverse_endianness(s) == 0; + + io_set_position(s, 0x04, SEEK_SET); + + uint32_t skeleton_count = io_read_uint32_t_stream_reverse_endianness(s); + ssize_t skeleton_offsets_offset = io_read_offset(s, header_length, is_x); + ssize_t skeleton_name_offsets_offset = io_read_offset(s, header_length, is_x); + + vector_bone_database_skeleton_reserve(&bone_data->skeleton, skeleton_count); + bone_data->skeleton.end += skeleton_count; + + io_position_push(s, skeleton_offsets_offset, SEEK_SET); + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skeleton = &bone_data->skeleton.begin[i]; + ssize_t skeleton_offset = io_read_offset(s, header_length, is_x); + + io_position_push(s, skeleton_offset, SEEK_SET); + ssize_t bones_offset; + uint32_t position_count; + ssize_t positions_offset; + ssize_t unknown_value_offset; + uint32_t object_bone_count; + ssize_t object_bone_names_offset; + uint32_t motion_bone_count; + ssize_t motion_bone_names_offset; + ssize_t parent_indices_offset; + if (!is_x) { + bones_offset = io_read_offset_f2(s, header_length); + position_count = io_read_uint32_t_stream_reverse_endianness(s); + positions_offset = io_read_offset_f2(s, header_length); + unknown_value_offset = io_read_offset_f2(s, header_length); + object_bone_count = io_read_uint32_t_stream_reverse_endianness(s); + object_bone_names_offset = io_read_offset_f2(s, header_length); + motion_bone_count = io_read_uint32_t_stream_reverse_endianness(s); + motion_bone_names_offset = io_read_offset_f2(s, header_length); + parent_indices_offset = io_read_offset_f2(s, header_length); + io_read(s, 0, 0x14); + } + else { + bones_offset = io_read_offset_x(s); + position_count = io_read_uint32_t_stream_reverse_endianness(s); + positions_offset = io_read_offset_x(s); + unknown_value_offset = io_read_offset_x(s); + object_bone_count = io_read_uint32_t_stream_reverse_endianness(s); + object_bone_names_offset = io_read_offset_x(s); + motion_bone_count = io_read_uint32_t_stream_reverse_endianness(s); + motion_bone_names_offset = io_read_offset_x(s); + parent_indices_offset = io_read_offset_x(s); + io_read(s, 0, 0x28); + } + + uint32_t bone_count = 0; + io_position_push(s, bones_offset, SEEK_SET); + if (!is_x) + while (true) { + if (io_read_uint8_t(s) == 0xFF) + break; + + io_read(s, 0, 0x0B); + bone_count++; + } + else + while (true) { + if (io_read_uint8_t(s) == 0xFF) + break; + + io_read(s, 0, 0x0F); + bone_count++; + } + io_position_pop(s); + + vector_bone_database_bone_reserve(&skeleton->bone, bone_count); + skeleton->bone.end += bone_count; + + io_position_push(s, bones_offset, SEEK_SET); + if (!is_x) + for (uint32_t j = 0; j < bone_count; j++) { + bone_database_bone* bone = &skeleton->bone.begin[j]; + bone->type = io_read_uint8_t(s); + bone->has_parent = io_read_uint8_t(s) ? true : false; + bone->parent = io_read_uint8_t(s); + bone->pole_target = io_read_uint8_t(s); + bone->mirror = io_read_uint8_t(s); + bone->flags = io_read_uint8_t(s); + io_read(s, 0, 0x02); + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), &bone->name); + } + else + for (uint32_t j = 0; j < bone_count; j++) { + bone_database_bone* bone = &skeleton->bone.begin[j]; + bone->type = io_read_uint8_t(s); + bone->has_parent = io_read_uint8_t(s) ? true : false; + bone->parent = io_read_uint8_t(s); + bone->pole_target = io_read_uint8_t(s); + bone->mirror = io_read_uint8_t(s); + bone->flags = io_read_uint8_t(s); + io_read(s, 0, 0x02); + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &bone->name); + } + io_position_pop(s); + + vector_vec3_reserve(&skeleton->position, position_count); + skeleton->position.end += position_count; + + io_position_push(s, positions_offset, SEEK_SET); + for (uint32_t j = 0; j < position_count; j++) { + vec3* position = &skeleton->position.begin[j]; + position->x = io_read_float_t_stream_reverse_endianness(s); + position->y = io_read_float_t_stream_reverse_endianness(s); + position->z = io_read_float_t_stream_reverse_endianness(s); + } + io_position_pop(s); + + io_position_push(s, unknown_value_offset, SEEK_SET); + skeleton->heel_height = io_read_float_t_stream_reverse_endianness(s); + io_position_pop(s); + + vector_string_reserve(&skeleton->object_bone, object_bone_count); + skeleton->object_bone.end += object_bone_count; + + io_position_push(s, object_bone_names_offset, SEEK_SET); + if (!is_x) + for (uint32_t j = 0; j < object_bone_count; j++) { + string* object_bone_name = &skeleton->object_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), object_bone_name); + } + else + for (uint32_t j = 0; j < object_bone_count; j++) { + string* object_bone_name = &skeleton->object_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_offset_x(s), object_bone_name); + } + io_position_pop(s); + + vector_string_reserve(&skeleton->motion_bone, motion_bone_count); + skeleton->motion_bone.end += motion_bone_count; + + io_position_push(s, motion_bone_names_offset, SEEK_SET); + if (!is_x) + for (uint32_t j = 0; j < motion_bone_count; j++) { + string* motion_bone_name = &skeleton->motion_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), motion_bone_name); + } + else + for (uint32_t j = 0; j < motion_bone_count; j++) { + string* motion_bone_name = &skeleton->motion_bone.begin[j]; + io_read_string_null_terminated_offset(s, io_read_offset_x(s), motion_bone_name); + } + io_position_pop(s); + + vector_uint16_t_reserve(&skeleton->parent_index, motion_bone_count); + skeleton->parent_index.end += motion_bone_count; + + io_position_push(s, parent_indices_offset, SEEK_SET); + io_read(s, skeleton->parent_index.begin, motion_bone_count * sizeof(uint16_t)); + if (s->is_big_endian) { + uint16_t* parent_indices = skeleton->parent_index.begin; + for (uint32_t j = 0; j < motion_bone_count; j++) + parent_indices[j] = reverse_endianness_uint16_t(parent_indices[j]); + } + io_position_pop(s); + io_position_pop(s); + } + io_position_pop(s); + + io_position_push(s, skeleton_name_offsets_offset, SEEK_SET); + if (!is_x) + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skeleton = &bone_data->skeleton.begin[i]; + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), &skeleton->name); + } + else + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skeleton = &bone_data->skeleton.begin[i]; + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &skeleton->name); + } + io_position_pop(s); + + bone_data->is_x = is_x; + bone_data->modern = true; + bone_data->ready = true; +} + +static void bone_database_modern_write_inner(bone_database* bone_data, stream* s) { + stream s_bone; + io_mopen(&s_bone, 0, 0); + uint32_t off; + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + vector_size_t pof = vector_empty(size_t); + + bool is_x = bone_data->is_x; + + uint32_t skeleton_count = (uint32_t)(bone_data->skeleton.end - bone_data->skeleton.begin); + + if (!is_x) { + uint32_t pos; + ee = (enrs_entry){ 0, 1, 16, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 4, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + pos = off = 16; + + skeleton_count *= 2; + ee = (enrs_entry){ off, 1, (uint32_t)(skeleton_count * 4ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, skeleton_count, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + pos += off = (uint32_t)(skeleton_count * 4ULL); + skeleton_count /= 2; + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + ee = (enrs_entry){ off, 1, 56, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 14, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + pos += off = 56; + + bone_count++; + off += 8; + pos += 8; + ee = (enrs_entry){ off, 1, 12, bone_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(bone_count * 12ULL); + if (pos + off % 0x10) + off -= 8; + pos += off = align_val(pos + off, 0x10) - pos; + bone_count--; + + ee = (enrs_entry){ off, 1, 12, position_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(position_count * 12ULL); + pos += off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, 4, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + pos += off = 4; + + object_bone_count += motion_bone_count; + ee = (enrs_entry){ off, 1, (uint32_t)(object_bone_count * 4ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, object_bone_count, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + pos += off = (uint32_t)(object_bone_count * 4ULL); + object_bone_count -= motion_bone_count; + + ee = (enrs_entry){ off, 1, (uint32_t)(motion_bone_count * 2ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, motion_bone_count, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(motion_bone_count * 2ULL); + pos += off = align_val(off, 0x04); + } + } + else { + ee = (enrs_entry){ 0, 2, 24, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 24; + off = align_val(off, 0x10); + + if (skeleton_count % 2) { + ee = (enrs_entry){ off, 1, (uint32_t)(skeleton_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, skeleton_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(skeleton_count * 8ULL); + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, (uint32_t)(skeleton_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, skeleton_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(skeleton_count * 8ULL); + off = align_val(off, 0x10); + } + else { + skeleton_count *= 2; + ee = (enrs_entry){ off, 1, (uint32_t)(skeleton_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, skeleton_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(skeleton_count * 8ULL); + off = align_val(off, 0x10); + skeleton_count /= 2; + } + + ee = (enrs_entry){ off, 7, 112, skeleton_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 2, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 7, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(skeleton_count * 112ULL); + off = align_val(off, 0x10); + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + bone_count++; + off += 8; + ee = (enrs_entry){ off, 1, 16, bone_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(bone_count * 16ULL); + bone_count--; + + ee = (enrs_entry){ off, 1, 12, position_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(position_count * 12ULL); + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, 4, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 4; + off = align_val(off, 0x10); + + if (object_bone_count % 1) { + ee = (enrs_entry){ off, 1, 12, position_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(position_count * 12ULL); + off = align_val(off, 0x10); + } + + if (skeleton_count % 2) { + ee = (enrs_entry){ off, 1, (uint32_t)(object_bone_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, object_bone_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_bone_count * 8ULL); + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, (uint32_t)(motion_bone_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, motion_bone_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(motion_bone_count * 8ULL); + off = align_val(off, 0x10); + } + else { + object_bone_count += motion_bone_count; + ee = (enrs_entry){ off, 1, (uint32_t)(object_bone_count * 8ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, object_bone_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_bone_count * 8ULL); + off = align_val(off, 0x10); + object_bone_count -= motion_bone_count; + } + + ee = (enrs_entry){ off, 1, (uint32_t)(motion_bone_count * 2ULL), 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, motion_bone_count, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(motion_bone_count * 2ULL); + off = align_val(off, 0x10); + } + } + + io_write_int32_t(&s_bone, 0); + io_write_int32_t(&s_bone, 0); + io_write_offset_pof_add(&s_bone, 0, 0x40, is_x, &pof); + io_write_offset_pof_add(&s_bone, 0, 0x40, is_x, &pof); + io_align_write(&s_bone, 0x10); + + ssize_t skeleton_offsets_offset = io_get_position(&s_bone); + if (!is_x) + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + else { + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_align_write(&s_bone, 0x10); + } + + ssize_t skeleton_name_offsets_offset = io_get_position(&s_bone); + if (!is_x) + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + else { + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_align_write(&s_bone, 0x10); + } + + bone_database_skeleton_header* skh = force_malloc_s(bone_database_skeleton_header, skeleton_count); + + if (!is_x) + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + skh[i].offset = io_get_position(&s_bone); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_write(&s_bone, 0, 0x14); + + skh[i].bones_offset = io_get_position(&s_bone); + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) { + io_write(&s_bone, 0, 0x08); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + } + + io_write(&s_bone, 0, 0x08); + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + io_align_write(&s_bone, 0x10); + + skh[i].positions_offset = io_get_position(&s_bone); + io_write(&s_bone, 0, sizeof(vec3) * position_count); + io_align_write(&s_bone, 0x10); + + skh[i].unknown_value_offset = io_get_position(&s_bone); + io_write_float_t(&s_bone, 0.0f); + + skh[i].object_bone_names_offset = io_get_position(&s_bone); + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + + skh[i].motion_bone_names_offset = io_get_position(&s_bone); + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + io_write_offset_f2_pof_add(&s_bone, 0, 0x40, &pof); + + skh[i].parent_indices_offset = io_get_position(&s_bone); + io_write(&s_bone, 0, sizeof(uint16_t) * motion_bone_count); + io_align_write(&s_bone, 0x04); + } + else { + for (uint32_t i = 0; i < skeleton_count; i++) { + skh[i].offset = io_get_position(&s_bone); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write_uint32_t(&s_bone, 0); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_write(&s_bone, 0, 0x28); + io_align_write(&s_bone, 0x10); + } + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + + skh[i].bones_offset = io_get_position(&s_bone); + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) { + io_write(&s_bone, 0, 0x08); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + } + + io_write(&s_bone, 0, 0x08); + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_align_write(&s_bone, 0x10); + + skh[i].positions_offset = io_get_position(&s_bone); + io_write(&s_bone, 0, sizeof(vec3) * position_count); + io_align_write(&s_bone, 0x10); + + skh[i].unknown_value_offset = io_get_position(&s_bone); + io_write_float_t(&s_bone, 0.0f); + io_align_write(&s_bone, 0x10); + + skh[i].object_bone_names_offset = io_get_position(&s_bone); + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_align_write(&s_bone, 0x10); + + skh[i].motion_bone_names_offset = io_get_position(&s_bone); + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + io_write_offset_x_pof_add(&s_bone, 0, &pof); + io_align_write(&s_bone, 0x10); + + skh[i].parent_indices_offset = io_get_position(&s_bone); + io_write(&s_bone, 0, sizeof(uint16_t) * motion_bone_count); + io_align_write(&s_bone, 0x10); + } + } + + vector_string strings = vector_empty(string); + vector_ssize_t string_offsets = vector_empty(ssize_t); + + if (is_x) + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + if (bone_database_strings_push_back_check(&strings, string_data(&skel->name))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_utf8_string_null_terminated(&s_bone, string_data(&skel->name)); + } + } + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(&j->name))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_string_null_terminated(&s_bone, &j->name); + } + + if (bone_database_strings_push_back_check(&strings, "End")) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_utf8_string_null_terminated(&s_bone, "End"); + } + + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(j))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_string_null_terminated(&s_bone, j); + } + + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + if (bone_database_strings_push_back_check(&strings, string_data(j))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_string_null_terminated(&s_bone, j); + } + } + + if (!is_x) + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + if (bone_database_strings_push_back_check(&strings, string_data(&skel->name))) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_bone); + io_write_utf8_string_null_terminated(&s_bone, string_data(&skel->name)); + } + } + io_align_write(&s_bone, 0x10); + + for (uint32_t i = 0; i < skeleton_count; i++) { + bone_database_skeleton* skel = &bone_data->skeleton.begin[i]; + + uint32_t bone_count = (uint32_t)(skel->bone.end - skel->bone.begin); + uint32_t position_count = (uint32_t)(skel->position.end - skel->position.begin); + uint32_t object_bone_count = (uint32_t)(skel->object_bone.end - skel->object_bone.begin); + uint32_t motion_bone_count = (uint32_t)(skel->motion_bone.end - skel->motion_bone.begin); + + io_position_push(&s_bone, skh[i].offset, SEEK_SET); + if (!is_x) { + io_write_offset_f2(&s_bone, skh[i].bones_offset, 0x40); + io_write_uint32_t(&s_bone, position_count); + io_write_offset_f2(&s_bone, skh[i].positions_offset, 0x40); + io_write_offset_f2(&s_bone, skh[i].unknown_value_offset, 0x40); + io_write_uint32_t(&s_bone, object_bone_count); + io_write_offset_f2(&s_bone, skh[i].object_bone_names_offset, 0x40); + io_write_uint32_t(&s_bone, motion_bone_count); + io_write_offset_f2(&s_bone, skh[i].motion_bone_names_offset, 0x40); + io_write_offset_f2(&s_bone, skh[i].parent_indices_offset, 0x40); + io_write(&s_bone, 0, 0x14); + } + else { + io_write_offset_x(&s_bone, skh[i].bones_offset); + io_write_uint32_t(&s_bone, position_count); + io_write_offset_x(&s_bone, skh[i].positions_offset); + io_write_offset_x(&s_bone, skh[i].unknown_value_offset); + io_write_uint32_t(&s_bone, object_bone_count); + io_write_offset_x(&s_bone, skh[i].object_bone_names_offset); + io_write_uint32_t(&s_bone, motion_bone_count); + io_write_offset_x(&s_bone, skh[i].motion_bone_names_offset); + io_write_offset_x(&s_bone, skh[i].parent_indices_offset); + io_write(&s_bone, 0, 0x28); + } + io_position_pop(&s_bone); + + io_position_push(&s_bone, skh[i].bones_offset, SEEK_SET); + if (!is_x) + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) { + io_write_uint8_t(&s_bone, (uint8_t)j->type); + io_write_uint8_t(&s_bone, j->has_parent ? 1 : 0); + io_write_uint8_t(&s_bone, j->parent); + io_write_uint8_t(&s_bone, j->pole_target); + io_write_uint8_t(&s_bone, j->mirror); + io_write_uint8_t(&s_bone, j->flags); + io_write(&s_bone, 0, 0x02); + io_write_offset_f2(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&j->name)), 0x40); + } + else + for (bone_database_bone* j = skel->bone.begin; j != skel->bone.end; j++) { + io_write_uint8_t(&s_bone, (uint8_t)j->type); + io_write_uint8_t(&s_bone, j->has_parent ? 1 : 0); + io_write_uint8_t(&s_bone, j->parent); + io_write_uint8_t(&s_bone, j->pole_target); + io_write_uint8_t(&s_bone, j->mirror); + io_write_uint8_t(&s_bone, j->flags); + io_write(&s_bone, 0, 0x02); + io_write_offset_x(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&j->name))); + } + + if (!is_x) { + io_write_uint32_t(&s_bone, 0xFF); + io_write_uint32_t(&s_bone, 0xFF); + io_write_offset_f2(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, "End"), 0x40); + } + else { + + io_write_uint32_t(&s_bone, 0xFF); + io_write_uint32_t(&s_bone, 0xFF); + io_write_offset_x(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, "End")); + } + io_position_pop(&s_bone); + + io_position_push(&s_bone, skh[i].positions_offset, SEEK_SET); + io_write(&s_bone, skel->position.begin, sizeof(vec3)* position_count); + io_position_pop(&s_bone); + + io_position_push(&s_bone, skh[i].unknown_value_offset, SEEK_SET); + io_write_float_t(&s_bone, skel->heel_height); + io_position_pop(&s_bone); + + io_position_push(&s_bone, skh[i].object_bone_names_offset, SEEK_SET); + if (!is_x) + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + io_write_offset_f2(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j)), 0x40); + else + for (string* j = skel->object_bone.begin; j != skel->object_bone.end; j++) + io_write_offset_x(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j))); + + io_position_push(&s_bone, skh[i].motion_bone_names_offset, SEEK_SET); + if (!is_x) + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + io_write_offset_f2(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j)), 0x40); + else + for (string* j = skel->motion_bone.begin; j != skel->motion_bone.end; j++) + io_write_offset_x(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(j))); + io_position_pop(&s_bone); + + io_position_push(&s_bone, skh[i].parent_indices_offset, SEEK_SET); + io_write(&s_bone, skel->parent_index.begin, sizeof(uint16_t) * motion_bone_count); + io_position_pop(&s_bone); + } + + io_position_push(&s_bone, 0x00, SEEK_SET); + io_write_uint32_t(&s_bone, 0x09102720); + io_write_uint32_t(&s_bone, skeleton_count); + io_write_offset(&s_bone, skeleton_offsets_offset, 0x40, is_x); + io_write_offset(&s_bone, skeleton_name_offsets_offset, 0x40, is_x); + io_position_pop(&s_bone); + + io_position_push(&s_bone, skeleton_offsets_offset, SEEK_SET); + if (!is_x) + for (uint32_t i = 0; i < skeleton_count; i++) + io_write_offset_f2(&s_bone, skh[i].offset, 0x40); + else + for (uint32_t i = 0; i < skeleton_count; i++) + io_write_offset_x(&s_bone, skh[i].offset); + io_position_pop(&s_bone); + + io_position_push(&s_bone, skeleton_name_offsets_offset, SEEK_SET); + if (!is_x) + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_f2(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name)), 0x40); + else + for (bone_database_skeleton* i = bone_data->skeleton.begin; i != bone_data->skeleton.end; i++) + io_write_offset_x(&s_bone, bone_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name))); + io_position_pop(&s_bone); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + free(skh); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + io_align_write(&s_bone, 0x10); + io_mcopy(&s_bone, &st.data, &st.length); + io_free(&s_bone); + + st.enrs = e; + st.pof = pof; + + st.header.signature = reverse_endianness_uint32_t('BONE'); + st.header.length = is_x ? 0x20 : 0x40; + st.header.use_big_endian = false; + st.header.use_section_size = true; + + f2_struct_swrite(&st, s, true, is_x); + f2_struct_free(&st); +} + +inline static ssize_t bone_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return vec_off->begin[i - vec->begin]; + return 0; +} + +inline static bool bone_database_strings_push_back_check(vector_string* vec, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return false; + + string* s = vector_string_reserve_back(vec); + string_init_length(s, str, len); + return true; +} diff --git a/src/KKdLib/database/bone.h b/src/KKdLib/database/bone.h new file mode 100644 index 00000000..63984419 --- /dev/null +++ b/src/KKdLib/database/bone.h @@ -0,0 +1,103 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vec.h" +#include "../vector.h" + +typedef enum bone_database_bone_type { + BONE_DATABASE_BONE_ROTATION = 0x00, + BONE_DATABASE_BONE_TYPE_1 = 0x01, + BONE_DATABASE_BONE_POSITION = 0x02, + BONE_DATABASE_BONE_POSITION_ROTATION = 0x03, + BONE_DATABASE_BONE_HEAD_IK_ROTATION = 0x04, + BONE_DATABASE_BONE_ARM_IK_ROTATION = 0x05, + BONE_DATABASE_BONE_LEGS_IK_ROTATION = 0x06, +} bone_database_bone_type; + +typedef enum bone_database_skeleton_type { + BONE_DATABASE_SKELETON_COMMON = 0, + BONE_DATABASE_SKELETON_MIKU = 1, + BONE_DATABASE_SKELETON_KAITO = 2, + BONE_DATABASE_SKELETON_LEN = 3, + BONE_DATABASE_SKELETON_LUKA = 4, + BONE_DATABASE_SKELETON_MEIKO = 5, + BONE_DATABASE_SKELETON_RIN = 6, + BONE_DATABASE_SKELETON_HAKU = 7, + BONE_DATABASE_SKELETON_NERU = 8, + BONE_DATABASE_SKELETON_SAKINE = 9, + BONE_DATABASE_SKELETON_TETO = 10, + BONE_DATABASE_SKELETON_NONE = -1, +} bone_database_skeleton_type; + +typedef struct bone_database_bone { + bone_database_bone_type type; + bool has_parent; + uint8_t parent; + uint8_t pole_target; + uint8_t mirror; + uint8_t flags; + string name; +} bone_database_bone; + +vector(bone_database_bone) + +typedef struct bone_database_skeleton { + vector_bone_database_bone bone; + vector_vec3 position; + float_t heel_height; + vector_string object_bone; + vector_string motion_bone; + vector_uint16_t parent_index; + string name; +} bone_database_skeleton; + +vector(bone_database_skeleton) + +typedef struct bone_database { + bool ready; + bool modern; + bool is_x; + + vector_bone_database_skeleton skeleton; +} bone_database; + +extern void bone_database_init(bone_database* bone_data); +extern void bone_database_read(bone_database* bone_data, char* path, bool modern); +extern void bone_database_wread(bone_database* bone_data, wchar_t* path, bool modern); +extern void bone_database_mread(bone_database* bone_data, void* data, size_t length, bool modern); +extern void bone_database_write(bone_database* bone_data, char* path); +extern void bone_database_wwrite(bone_database* bone_data, wchar_t* path); +extern void bone_database_mwrite(bone_database* bone_data, void** data, size_t* length); +extern bool bone_database_load_file(void* data, char* path, char* file, uint32_t hash); +extern void bone_database_bones_calculate_count(vector_bone_database_bone* bones, size_t* object_bone_count, + size_t* motion_bone_count, size_t* total_bone_count, size_t* ik_bone_count, size_t* chain_pos); +extern bool bone_database_get_skeleton(bone_database* bone_data, + char* name, bone_database_skeleton** skeleton); +extern int32_t bone_database_get_skeleton_bone_index(bone_database* bone_data, char* name, char* bone_name); +extern bool bone_database_get_skeleton_bones(bone_database* bone_data, + char* name, vector_bone_database_bone** bone); +extern bool bone_database_get_skeleton_positions(bone_database* bone_data, + char* name, vector_vec3** positions); +extern int32_t bone_database_get_skeleton_object_bone_index(bone_database* bone_data, + char* name, char* bone_name); +extern bool bone_database_get_skeleton_object_bones(bone_database* bone_data, + char* name, vector_string** object_bones); +extern int32_t bone_database_get_skeleton_motion_bone_index(bone_database* bone_data, + char* name, char* bone_name); +extern bool bone_database_get_skeleton_motion_bones(bone_database* bone_data, + char* name, vector_string** motion_bones); +extern bool bone_database_get_skeleton_parent_indices(bone_database* bone_data, + char* name, vector_uint16_t** parent_indices); +extern bool bone_database_get_skeleton_heel_height(bone_database* bone_data, + char* name, float_t** unknown_value); +extern void bone_database_free(bone_database* bone_data); + +extern char* bone_database_skeleton_type_to_string(bone_database_skeleton_type type); +extern void bone_database_bone_free(bone_database_bone* bone); +extern void bone_database_skeleton_free(bone_database_skeleton* skel); diff --git a/src/KKdLib/database/motion.c b/src/KKdLib/database/motion.c new file mode 100644 index 00000000..bd754d13 --- /dev/null +++ b/src/KKdLib/database/motion.c @@ -0,0 +1,519 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "motion.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../farc.h" +#include "../hash.h" +#include "../str_utils.h" + +vector_func(motion_info) +vector_func(motion_set_info) + +static void motion_database_read_inner(motion_database* mot_db, stream* s); +static void motion_database_write_inner(motion_database* mot_db, stream* s); + +void motion_database_init(motion_database* mot_db) { + memset(mot_db, 0, sizeof(motion_database)); +} + +void motion_database_read(motion_database* mot_db, char* path) { + if (!mot_db || !path) + return; + + char* path_farc = str_utils_add(path, ".farc"); + if (path_check_file_exists(path_farc)) { + farc f; + farc_init(&f); + farc_read(&f, path_farc, true, false); + + farc_file* ff = farc_read_file(&f, "mot_db.bin"); + if (ff) { + stream s; + io_mopen(&s, ff->data, ff->size); + motion_database_read_inner(mot_db, &s); + io_free(&s); + } + farc_free(&f); + } + free(path_farc); +} + +void motion_database_wread(motion_database* mot_db, wchar_t* path) { + if (!mot_db || !path) + return; + + wchar_t* path_farc = str_utils_wadd(path, L".farc"); + if (path_wcheck_file_exists(path_farc)) { + farc f; + farc_init(&f); + farc_wread(&f, path_farc, true, false); + + farc_file* ff = farc_read_file(&f, "mot_db.bin"); + if (ff) { + stream s; + io_mopen(&s, ff->data, ff->size); + motion_database_read_inner(mot_db, &s); + io_free(&s); + } + farc_free(&f); + } + free(path_farc); +} + +void motion_database_mread(motion_database* mot_db, void* data, size_t length) { + if (!mot_db || !data || !length) + return; + + stream s; + io_mopen(&s, data, length); + motion_database_read_inner(mot_db, &s); + io_free(&s); +} + +void motion_database_write(motion_database* mot_db, char* path) { + if (!mot_db || !path || !mot_db->ready) + return; + + farc f; + farc_init(&f); + + farc_file* ff = vector_farc_file_reserve_back(&f.files); + string_init_length(&ff->name, "mot_db.bin", 10); + stream s; + io_mopen(&s, 0, 0); + motion_database_write_inner(mot_db, &s); + io_mcopy(&s, &ff->data, &ff->size); + io_free(&s); + + farc_write(&f, path, FARC_COMPRESS_FArc, false); + farc_free(&f); +} + +void motion_database_wwrite(motion_database* mot_db, wchar_t* path) { + if (!mot_db || !path || !mot_db->ready) + return; + + farc f; + farc_init(&f); + + farc_file* ff = vector_farc_file_reserve_back(&f.files); + string_init_length(&ff->name, "mot_db.bin", 10); + stream s; + io_mopen(&s, 0, 0); + motion_database_write_inner(mot_db, &s); + io_mcopy(&s, &ff->data, &ff->size); + io_free(&s); + + farc_wwrite(&f, path, FARC_COMPRESS_FArC, false); + farc_free(&f); +} + +void motion_database_mwrite(motion_database* mot_db, void** data, size_t* length) { + if (!mot_db || !data || !mot_db->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + motion_database_write_inner(mot_db, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool motion_database_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + motion_database* mot_db = data; + motion_database_read(mot_db, string_data(&s)); + + string_free(&s); + return mot_db->ready; +} + +void motion_database_merge_mdata(motion_database* mot_db, + motion_database* base_mot_db, motion_database* mdata_mot_db) { + if (!mot_db || !base_mot_db || !mdata_mot_db + || !base_mot_db->ready || !mdata_mot_db->ready) + return; + + vector_string* bone_name = &mot_db->bone_name; + vector_string* base_bone_name = &base_mot_db->bone_name; + + int32_t bone_count = (int32_t)(base_bone_name->end - base_bone_name->begin); + vector_string_reserve(bone_name, bone_count); + bone_name->end += bone_count; + + for (int32_t i = 0; i < bone_count; i++) + string_copy(&base_bone_name->begin[i], &bone_name->begin[i]); + + vector_motion_set_info* motion_set = &mot_db->motion_set; + vector_motion_set_info* base_motion_set = &base_mot_db->motion_set; + vector_motion_set_info* mdata_motion_set = &mdata_mot_db->motion_set; + + int32_t count = (int32_t)(base_motion_set->end - base_motion_set->begin); + vector_motion_set_info_reserve(motion_set, count); + motion_set->end += count; + + for (int32_t i = 0; i < count; i++) { + motion_set_info* b_set_info = &base_motion_set->begin[i]; + motion_set_info* set_info = &motion_set->begin[i]; + + set_info->id = b_set_info->id; + string_copy(&b_set_info->name, &set_info->name); + set_info->name_hash = hash_fnv1a64m(string_data(&set_info->name), set_info->name.length); + + int32_t info_count = (int32_t)(b_set_info->motion.end - b_set_info->motion.begin); + vector_motion_info_reserve(&set_info->motion, info_count); + set_info->motion.end += info_count; + + for (int32_t j = 0; j < info_count; j++) { + motion_info* b_info = &b_set_info->motion.begin[j]; + motion_info* info = &set_info->motion.begin[j]; + + info->id = b_info->id; + string_copy(&b_info->name, &info->name); + info->name_hash = hash_fnv1a64m(string_data(&info->name), info->name.length); + } + } + + int32_t mdata_count = (int32_t)(mdata_motion_set->end - mdata_motion_set->begin); + for (int32_t i = 0; i < mdata_count; i++) { + motion_set_info* m_set_info = &mdata_motion_set->begin[i]; + + char* name_str = string_data(&m_set_info->name); + size_t name_len = m_set_info->name.length; + + motion_set_info* set_info = 0; + for (set_info = motion_set->begin; set_info != motion_set->end; set_info++) + if (!memcmp(name_str, string_data(&set_info->name), min(name_len, set_info->name.length) + 1)) + break; + + if (set_info == motion_set->end) + set_info = vector_motion_set_info_reserve_back(motion_set); + + set_info->id = m_set_info->id; + string_replace(&m_set_info->name, &set_info->name); + set_info->name_hash = hash_fnv1a64m(string_data(&set_info->name), set_info->name.length); + + vector_motion_info_clear(&set_info->motion, motion_info_free); + int32_t info_count = (int32_t)(m_set_info->motion.end - m_set_info->motion.begin); + vector_motion_info_reserve(&set_info->motion, info_count); + set_info->motion.end += info_count; + + for (int32_t j = 0; j < info_count; j++) { + motion_info* m_info = &m_set_info->motion.begin[j]; + motion_info* info = &set_info->motion.begin[j]; + + info->id = m_info->id; + string_copy(&m_info->name, &info->name); + info->name_hash = hash_fnv1a64m(string_data(&info->name), info->name.length); + } + } + + mot_db->ready = true; +} + +void motion_database_split_mdata(motion_database* mot_db, + motion_database* base_mot_db, motion_database* mdata_mot_db) { + if (!mot_db || !base_mot_db || !mdata_mot_db + || !mot_db->ready || !base_mot_db->ready) + return; + +} + +motion_set_info* motion_database_get_motion_set_by_id(motion_database* mot_db, uint32_t id) { + if (!mot_db || !id == -1) + return 0; + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + if (id == i->id) + return i; + return 0; +} + +motion_set_info* motion_database_get_motion_set_by_name(motion_database* mot_db, char* name) { + if (!mot_db || !name) + return 0; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + if (name_hash == i->name_hash) + return i; + return 0; +} + +uint32_t motion_database_get_motion_set_id(motion_database* mot_db, char* name) { + if (!mot_db || !name) + return -1; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + if (name_hash == i->name_hash) + return i->id; + return -1; +} + +char* motion_database_get_motion_set_name(motion_database* mot_db, uint32_t id) { + if (!mot_db || id == -1) + return 0; + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + if (id == i->id) + return string_data(&i->name); + return 0; +} + +motion_info* motion_database_get_motion_by_id(motion_database* mot_db, uint32_t id) { + if (!mot_db || id == -1) + return 0; + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + if (id == j->id) + return j; + return 0; +} + +motion_info* motion_database_get_motion_by_name(motion_database* mot_db, char* name) { + if (!mot_db || !name) + return 0; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + if (name_hash == j->name_hash) + return j; + return 0; +} + +uint32_t motion_database_get_motion_id(motion_database* mot_db, char* name) { + if (!mot_db || !name) + return -1; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + if (name_hash == j->name_hash) + return j->id; + return -1; +} + +char* motion_database_get_motion_name(motion_database* mot_db, uint32_t id) { + if (!mot_db || id == -1) + return 0; + + for (motion_set_info* i = mot_db->motion_set.begin; i != mot_db->motion_set.end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + if (id == j->id) + return string_data(&j->name); + return 0; +} + +void motion_database_free(motion_database* mot_db) { + vector_string_free(&mot_db->bone_name, string_free); + vector_motion_set_info_free(&mot_db->motion_set, motion_set_info_free); +} + +void motion_info_free(motion_info* info) { + string_free(&info->name); +} + +void motion_set_info_free(motion_set_info* set_info) { + string_free(&set_info->name); + vector_motion_info_free(&set_info->motion, motion_info_free); +} + +static void motion_database_read_inner(motion_database* mot_db, stream* s) { + if (io_read_uint32_t(s) != 0x01) + return; + + uint32_t motion_sets_offset = io_read_uint32_t(s); + uint32_t motion_set_ids_offset = io_read_uint32_t(s); + uint32_t motion_set_count = io_read_uint32_t(s); + uint32_t bone_name_offsets_offset = io_read_uint32_t(s); + uint32_t bone_name_count = io_read_uint32_t(s); + + vector_motion_set_info_reserve(&mot_db->motion_set, motion_set_count); + mot_db->motion_set.end += motion_set_count; + + io_position_push(s, motion_sets_offset, SEEK_SET); + for (uint32_t i = 0; i < motion_set_count; i++) { + motion_set_info* set_info = &mot_db->motion_set.begin[i]; + + uint32_t name_offset = io_read_uint32_t(s); + uint32_t motion_name_offsets_offset = io_read_uint32_t(s); + uint32_t motion_count = io_read_uint32_t(s); + uint32_t motion_ids_offset = io_read_uint32_t(s); + + io_read_string_null_terminated_offset(s, name_offset, &set_info->name); + + vector_motion_info_reserve(&set_info->motion, motion_count); + set_info->motion.end += motion_count; + + io_position_push(s, motion_name_offsets_offset, SEEK_SET); + for (uint32_t j = 0; j < motion_count; j++) { + motion_info* motion = &set_info->motion.begin[j]; + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &motion->name); + } + io_position_pop(s); + + io_position_push(s, motion_ids_offset, SEEK_SET); + for (uint32_t j = 0; j < motion_count; j++) { + motion_info* motion = &set_info->motion.begin[j]; + motion->id = io_read_uint32_t(s); + } + io_position_pop(s); + } + io_position_pop(s); + + io_position_push(s, motion_set_ids_offset, SEEK_SET); + for (uint32_t i = 0; i < motion_set_count; i++) { + motion_set_info* set_info = &mot_db->motion_set.begin[i]; + set_info->id = io_read_uint32_t(s); + } + io_position_pop(s); + + vector_string_reserve(&mot_db->bone_name, bone_name_count); + mot_db->bone_name.end += bone_name_count; + + io_position_push(s, bone_name_offsets_offset, SEEK_SET); + for (uint32_t i = 0; i < bone_name_count; i++) { + string* bone_name = &mot_db->bone_name.begin[i]; + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), bone_name); + } + io_position_pop(s); + + mot_db->ready = true; +} + +static void motion_database_write_inner(motion_database* mot_db, stream* s) { + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_write_int32_t(s, 0); + io_align_write(s, 0x40); + + vector_string* bone_name = &mot_db->bone_name; + vector_motion_set_info* motion_set = &mot_db->motion_set; + + ssize_t bone_name_count = bone_name->end - bone_name->begin; + ssize_t motion_set_count = motion_set->end - motion_set->begin; + + ssize_t motion_sets_offset = io_get_position(s); + io_write(s, 0, 0x10 * motion_set_count + 0x10); + io_align_write(s, 0x20); + + size_t size = 0; + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + size += i->name.length + 1; + + ssize_t motion_set_name_offset = io_get_position(s); + io_write(s, 0, size); + + size = 0; + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + size += j->name.length + 1; + + ssize_t motion_name_offset = io_get_position(s); + io_write(s, 0, size); + io_align_write(s, 0x20); + + ssize_t motion_names_offset = io_get_position(s); + size = 0; + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + size += 0x04 * (i->motion.end - i->motion.begin); + io_write(s, 0, size); + io_align_write(s, 0x20); + + ssize_t motion_ids_offset = io_get_position(s); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + io_write_uint32_t(s, j->id); + io_align_write(s, 0x20); + + ssize_t motion_set_ids_offset = io_get_position(s); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + io_write_uint32_t(s, i->id); + + ssize_t bone_name_offset = io_get_position(s); + size = 0; + for (string* i = bone_name->begin; i != bone_name->end; i++) + size += i->length + 1; + io_write(s, 0, size); + io_align_write(s, 0x20); + + io_position_push(s, motion_set_name_offset, SEEK_SET); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + io_write_string_null_terminated(s, &i->name); + io_position_pop(s); + + io_position_push(s, motion_name_offset, SEEK_SET); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) + io_write_string_null_terminated(s, &j->name); + io_position_pop(s); + + io_position_push(s, bone_name_offset, SEEK_SET); + for (string* i = bone_name->begin; i != bone_name->end; i++) + io_write_string_null_terminated(s, i); + io_position_pop(s); + + ssize_t bone_name_offsets_offset = io_get_position(s); + io_write(s, 0, 0x04 * bone_name_count); + io_align_write(s, 0x20); + + io_position_push(s, motion_names_offset, SEEK_SET); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) + for (motion_info* j = i->motion.begin; j != i->motion.end; j++) { + io_write_uint32_t(s, (uint32_t)motion_name_offset); + motion_name_offset += j->name.length + 1; + } + io_position_pop(s); + + io_position_push(s, motion_sets_offset, SEEK_SET); + for (motion_set_info* i = motion_set->begin; i != motion_set->end; i++) { + io_write_uint32_t(s, (uint32_t)motion_set_name_offset); + io_write_uint32_t(s, (uint32_t)motion_names_offset); + io_write_uint32_t(s, (uint32_t)(i->motion.end - i->motion.begin)); + io_write_uint32_t(s, (uint32_t)motion_ids_offset); + motion_set_name_offset += i->name.length + 1; + motion_names_offset += 0x04 * (i->motion.end - i->motion.begin); + motion_ids_offset += 0x04 * (i->motion.end - i->motion.begin); + } + io_write(s, 0, 0x10); + io_position_pop(s); + + io_position_push(s, bone_name_offsets_offset, SEEK_SET); + for (string* i = bone_name->begin; i != bone_name->end; i++) { + io_write_uint32_t(s, (uint32_t)bone_name_offset); + bone_name_offset += i->length + 1; + } + io_position_pop(s); + + io_position_push(s, 0x00, SEEK_SET); + io_write_uint32_t(s, 0x01); + io_write_uint32_t(s, (uint32_t)motion_sets_offset); + io_write_uint32_t(s, (uint32_t)motion_set_ids_offset); + io_write_uint32_t(s, (uint32_t)motion_set_count); + io_write_uint32_t(s, (uint32_t)bone_name_offsets_offset); + io_write_uint32_t(s, (uint32_t)bone_name_count); + io_position_pop(s); +} diff --git a/src/KKdLib/database/motion.h b/src/KKdLib/database/motion.h new file mode 100644 index 00000000..3dafeddc --- /dev/null +++ b/src/KKdLib/database/motion.h @@ -0,0 +1,59 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" + +typedef struct motion_info { + string name; + uint64_t name_hash; + uint32_t id; +} motion_info; + +vector(motion_info) + +typedef struct motion_set_info { + string name; + uint64_t name_hash; + uint32_t id; + vector_motion_info motion; +} motion_set_info; + +vector(motion_set_info) + +typedef struct motion_database { + bool ready; + + vector_string bone_name; + vector_motion_set_info motion_set; +} motion_database; + +extern void motion_database_init(motion_database* mot_db); +extern void motion_database_read(motion_database* mot_db, char* path); +extern void motion_database_wread(motion_database* mot_db, wchar_t* path); +extern void motion_database_mread(motion_database* mot_db, void* data, size_t length); +extern void motion_database_write(motion_database* mot_db, char* path); +extern void motion_database_wwrite(motion_database* mot_db, wchar_t* path); +extern void motion_database_mwrite(motion_database* mot_db, void** data, size_t* length); +extern bool motion_database_load_file(void* data, char* path, char* file, uint32_t hash); +extern void motion_database_merge_mdata(motion_database* mot_db, + motion_database* base_mot_db, motion_database* mdata_mot_db); +extern void motion_database_split_mdata(motion_database* mot_db, + motion_database* base_mot_db, motion_database* mdata_mot_db); +extern motion_set_info* motion_database_get_motion_set_by_id(motion_database* mot_db, uint32_t id); +extern motion_set_info* motion_database_get_motion_set_by_name(motion_database* mot_db, char* name); +extern uint32_t motion_database_get_motion_set_id(motion_database* mot_db, char* name); +extern char* motion_database_get_motion_set_name(motion_database* mot_db, uint32_t id); +extern motion_info* motion_database_get_motion_by_id(motion_database* mot_db, uint32_t id); +extern motion_info* motion_database_get_motion_by_name(motion_database* mot_db, char* name); +extern uint32_t motion_database_get_motion_id(motion_database* mot_db, char* name); +extern char* motion_database_get_motion_name(motion_database* mot_db, uint32_t id); +extern void motion_database_free(motion_database* mot_db); + +extern void motion_info_free(motion_info* info); +extern void motion_set_info_free(motion_set_info* set_info); diff --git a/src/KKdLib/database/object.c b/src/KKdLib/database/object.c new file mode 100644 index 00000000..15e9ca2c --- /dev/null +++ b/src/KKdLib/database/object.c @@ -0,0 +1,906 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "object.h" +#include "../f2/struct.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../hash.h" +#include "../str_utils.h" + +vector_func(object_info) +vector_func(object_info_data) +vector_func(object_set_info) + +static void object_database_classic_read_inner(object_database* obj_db, stream* s); +static void object_database_classic_write_inner(object_database* obj_db, stream* s); +static void object_database_modern_read_inner(object_database* obj_db, stream* s, uint32_t header_length); +static void object_database_modern_write_inner(object_database* obj_db, stream* s); +static ssize_t object_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str); +static void object_database_strings_push_back_check(vector_string* vec, char* str); + +const object_info object_info_null = { -1, -1 }; + +void object_database_init(object_database* obj_db) { + memset(obj_db, 0, sizeof(object_database)); +} + +void object_database_read(object_database* obj_db, char* path, bool modern) { + if (!obj_db || !path) + return; + + if (!modern) { + char* path_bin = str_utils_add(path, ".bin"); + if (path_check_file_exists(path_bin)) { + stream s; + io_open(&s, path_bin, "rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + object_database_classic_read_inner(obj_db, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + char* path_osi = str_utils_add(path, ".osi"); + if (path_check_file_exists(path_osi)) { + f2_struct st; + f2_struct_read(&st, path_osi); + if (st.header.signature == reverse_endianness_uint32_t('MOSI')); { + stream s_mosi; + io_mopen(&s_mosi, st.data, st.length); + s_mosi.is_big_endian = st.header.use_big_endian; + object_database_modern_read_inner(obj_db, &s_mosi, st.header.length); + io_free(&s_mosi); + } + f2_struct_free(&st); + } + free(path_osi); + } +} + +void object_database_wread(object_database* obj_db, wchar_t* path, bool modern) { + if (!obj_db || !path) + return; + + if (!modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + if (path_wcheck_file_exists(path_bin)) { + stream s; + io_wopen(&s, path_bin, L"rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + object_database_classic_read_inner(obj_db, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + wchar_t* path_osi = str_utils_wadd(path, L".osi"); + if (path_wcheck_file_exists(path_osi)) { + f2_struct st; + f2_struct_wread(&st, path_osi); + if (st.header.signature == reverse_endianness_uint32_t('MOSI')); { + stream s_mosi; + io_mopen(&s_mosi, st.data, st.length); + s_mosi.is_big_endian = st.header.use_big_endian; + object_database_modern_read_inner(obj_db, &s_mosi, st.header.length); + io_free(&s_mosi); + } + f2_struct_free(&st); + } + free(path_osi); + } +} + +void object_database_mread(object_database* obj_db, void* data, size_t length, bool modern) { + if (!obj_db || !data || !length) + return; + + if (!modern) { + stream s; + io_mopen(&s, data, length); + object_database_classic_read_inner(obj_db, &s); + io_free(&s); + } + else { + f2_struct st; + f2_struct_mread(&st, data, length); + if (st.header.signature == reverse_endianness_uint32_t('MOSI')); { + stream s_mosi; + io_mopen(&s_mosi, st.data, st.length); + s_mosi.is_big_endian = st.header.use_big_endian; + object_database_modern_read_inner(obj_db, &s_mosi, st.header.length); + io_free(&s_mosi); + } + f2_struct_free(&st); + } +} + +void object_database_write(object_database* obj_db, char* path) { + if (!obj_db || !path || !obj_db->ready) + return; + + if (!obj_db->modern) { + char* path_bin = str_utils_add(path, ".bin"); + stream s; + io_open(&s, path_bin, "wb"); + if (s.io.stream) + object_database_classic_write_inner(obj_db, &s); + io_free(&s); + free(path_bin); + } + else { + char* path_osi = str_utils_add(path, ".osi"); + stream s; + io_open(&s, path_osi, "wb"); + if (s.io.stream) + object_database_modern_write_inner(obj_db, &s); + io_free(&s); + free(path_osi); + } +} + +void object_database_wwrite(object_database* obj_db, wchar_t* path) { + if (!obj_db || !path || !obj_db->ready) + return; + + if (!obj_db->modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + stream s; + io_wopen(&s, path_bin, L"wb"); + if (s.io.stream) + object_database_classic_write_inner(obj_db, &s); + io_free(&s); + free(path_bin); + } + else { + wchar_t* path_osi = str_utils_wadd(path, L".osi"); + stream s; + io_wopen(&s, path_osi, L"wb"); + if (s.io.stream) + object_database_modern_write_inner(obj_db, &s); + io_free(&s); + free(path_osi); + } +} + +void object_database_mwrite(object_database* obj_db, void** data, size_t* length) { + if (!obj_db || !data || !obj_db->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + if (!obj_db->modern) + object_database_classic_write_inner(obj_db, &s); + else + object_database_modern_write_inner(obj_db, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool object_database_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + object_database* obj_db = data; + object_database_read(obj_db, string_data(&s), obj_db->modern); + + string_free(&s); + return obj_db->ready; +} + +void object_database_merge_mdata(object_database* obj_db, + object_database* base_obj_db, object_database* mdata_obj_db) { + if (!obj_db || !base_obj_db || !mdata_obj_db + || !base_obj_db->ready || !mdata_obj_db->ready) + return; + + vector_string* bone_name = &obj_db->bone_name; + vector_string* base_bone_name = &base_obj_db->bone_name; + + int32_t bone_count = (int32_t)(base_bone_name->end - base_bone_name->begin); + vector_string_reserve(bone_name, bone_count); + bone_name->end += bone_count; + + for (int32_t i = 0; i < bone_count; i++) + string_copy(&base_bone_name->begin[i], &bone_name->begin[i]); + + vector_object_set_info* object_set = &obj_db->object_set; + vector_object_set_info* base_object_set = &base_obj_db->object_set; + vector_object_set_info* mdata_object_set = &mdata_obj_db->object_set; + + int32_t count = (int32_t)(base_object_set->end - base_object_set->begin); + vector_object_set_info_reserve(object_set, count); + object_set->end += count; + + for (int32_t i = 0; i < count; i++) { + object_set_info* b_set_info = &base_object_set->begin[i]; + object_set_info* set_info = &object_set->begin[i]; + + string_copy(&b_set_info->name, &set_info->name); + set_info->name_hash = hash_fnv1a64m(string_data(&set_info->name), set_info->name.length); + set_info->id = b_set_info->id; + string_copy(&b_set_info->object_file_name, &set_info->object_file_name); + string_copy(&b_set_info->texture_file_name, &set_info->texture_file_name); + string_copy(&b_set_info->archive_file_name, &set_info->archive_file_name); + + int32_t info_count = (int32_t)(b_set_info->object.end - b_set_info->object.begin); + vector_object_info_data_reserve(&set_info->object, info_count); + set_info->object.end += info_count; + + for (int32_t j = 0; j < info_count; j++) { + object_info_data* b_info = &b_set_info->object.begin[j]; + object_info_data* info = &set_info->object.begin[j]; + + info->id = b_info->id; + string_copy(&b_info->name, &info->name); + info->name_hash_fnv1a64m = hash_fnv1a64m(string_data(&info->name), info->name.length); + info->name_hash_fnv1a64m_upper = hash_fnv1a64m_upper(string_data(&info->name), info->name.length); + info->name_hash_murmurhash = hash_murmurhash(string_data(&info->name), + info->name.length, 0, false, false); + } + } + + int32_t mdata_count = (int32_t)(mdata_object_set->end - mdata_object_set->begin); + for (int32_t i = 0; i < mdata_count; i++) { + object_set_info* m_set_info = &mdata_object_set->begin[i]; + + uint64_t name_hash = m_set_info->name_hash; + size_t name_len = m_set_info->name.length; + + object_set_info* set_info = 0; + for (set_info = object_set->begin; set_info != object_set->end; set_info++) + if (name_hash == set_info->name_hash) + break; + + if (set_info == object_set->end) + set_info = vector_object_set_info_reserve_back(object_set); + + string_replace(&m_set_info->name, &set_info->name); + set_info->name_hash = hash_fnv1a64m(string_data(&set_info->name), set_info->name.length); + set_info->id = m_set_info->id; + string_replace(&m_set_info->object_file_name, &set_info->object_file_name); + string_replace(&m_set_info->texture_file_name, &set_info->texture_file_name); + string_replace(&m_set_info->archive_file_name, &set_info->archive_file_name); + + vector_object_info_data_clear(&set_info->object, object_info_data_free); + int32_t info_count = (int32_t)(m_set_info->object.end - m_set_info->object.begin); + vector_object_info_data_reserve(&set_info->object, info_count); + set_info->object.end += info_count; + + for (int32_t j = 0; j < info_count; j++) { + object_info_data* m_info = &m_set_info->object.begin[j]; + object_info_data* info = &set_info->object.begin[j]; + + info->id = m_info->id; + string_copy(&m_info->name, &info->name); + info->name_hash_fnv1a64m = hash_fnv1a64m(string_data(&info->name), info->name.length); + info->name_hash_fnv1a64m_upper = hash_fnv1a64m_upper(string_data(&info->name), info->name.length); + info->name_hash_murmurhash = hash_murmurhash(string_data(&info->name), + info->name.length, 0, false, false); + } + } + + obj_db->ready = true; +} + +void object_database_split_mdata(object_database* obj_db, + object_database* base_obj_db, object_database* mdata_obj_db) { + if (!obj_db || !base_obj_db || !mdata_obj_db + || !obj_db->ready || !base_obj_db->ready) + return; +} + +bool object_database_get_object_set_info(object_database* obj_db, + char* name, object_set_info** set_info) { + if (!set_info) + return false; + *set_info = 0; + + if (!obj_db || !name) + return false; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + if (name_hash == i->name_hash) { + *set_info = i; + return true; + } + return false; +} + +bool object_database_get_object_set_info_by_set_id(object_database* obj_db, + uint32_t set_id, object_set_info** set_info) { + if (!set_info) + return false; + *set_info = 0; + + if (!obj_db || set_id == -1) + return false; + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + if (set_id == i->id) { + *set_info = i; + return true; + } + return false; +} + +bool object_database_get_object_info_data(object_database* obj_db, + char* name, object_info_data** info) { + if (!info) + return false; + *info = 0; + + if (!obj_db || !name) + return false; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (name_hash == j->name_hash_fnv1a64m) { + *info = j; + return true; + } + return false; +} + +bool object_database_get_object_info_data_by_fnv1a64m_hash(object_database* obj_db, + uint64_t hash, object_info_data** info) { + if (!info) + return false; + *info = 0; + + if (!obj_db) + return false; + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (hash == j->name_hash_fnv1a64m) { + *info = j; + return true; + } + return false; +} + +bool object_database_get_object_info_data_by_fnv1a64m_hash_upper(object_database* obj_db, + uint64_t hash, object_info_data** info) { + if (!info) + return false; + *info = 0; + + if (!obj_db) + return false; + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (hash == j->name_hash_fnv1a64m_upper) { + *info = j; + return true; + } + return false; +} + +bool object_database_get_object_info_data_by_murmurhash(object_database* obj_db, + uint32_t hash, object_info_data** info) { + if (!info) + return false; + *info = 0; + + if (!obj_db) + return false; + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (hash == j->name_hash_murmurhash) { + *info = j; + return true; + } + return false; +} +object_info object_database_get_object_info(object_database* obj_db, char* name) { + if (!obj_db || !name) + return object_info_null; + + size_t name_len = utf8_length(name); + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + if (!str_utils_compare_length(name, name_len, "NULL", 5)) + return object_info_null; + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + if (name_hash == j->name_hash_fnv1a64m) + return (object_info) { j->id, i->id }; + } + + return object_info_null; +} + +void object_database_free(object_database* obj_db) { + vector_object_set_info_free(&obj_db->object_set, object_set_info_free); +} + +void object_info_data_free(object_info_data* info) { + string_free(&info->name); +} + +void object_set_info_free(object_set_info* set_info) { + string_free(&set_info->name); + vector_object_info_data_free(&set_info->object, object_info_data_free); + string_free(&set_info->object_file_name); + string_free(&set_info->texture_file_name); + string_free(&set_info->archive_file_name); +} + +static void object_database_classic_read_inner(object_database* obj_db, stream* s) { + uint32_t object_set_count = io_read_uint32_t(s); + uint32_t max_object_set_id = io_read_uint32_t(s); + uint32_t object_sets_offset = io_read_uint32_t(s); + uint32_t object_count = io_read_uint32_t(s); + uint32_t objects_offset = io_read_uint32_t(s); + + vector_object_set_info_reserve(&obj_db->object_set, object_set_count); + obj_db->object_set.end += object_set_count; + + io_position_push(s, object_sets_offset, SEEK_SET); + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + io_read_string_null_terminated_offset(s, + io_read_uint32_t(s), &set_info->name); + set_info->id = io_read_uint32_t(s); + io_read_string_null_terminated_offset(s, + io_read_uint32_t(s), &set_info->object_file_name); + io_read_string_null_terminated_offset(s, + io_read_uint32_t(s), &set_info->texture_file_name); + io_read_string_null_terminated_offset(s, + io_read_uint32_t(s), &set_info->archive_file_name); + io_read(s, 0, 0x10); + } + io_position_pop(s); + + io_position_push(s, objects_offset, SEEK_SET); + for (uint32_t i = 0; i < object_count; i++) { + object_info_data info; + info.id = io_read_uint16_t(s); + uint32_t set_id = io_read_uint16_t(s); + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &info.name); + + if (info.id == 0xFFFF) + info.id = -1; + if (set_id == 0xFFFF) + set_id = -1; + + bool found = false; + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + if (set_id != set_info->id) + continue; + + vector_object_info_data_push_back(&set_info->object, &info); + found = true; + break; + } + + if (!found) + string_free(&info.name); + } + io_position_pop(s); + + obj_db->is_x = false; + obj_db->modern = false; + obj_db->ready = true; +} + +static void object_database_classic_write_inner(object_database* obj_db, stream* s) { + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_align_write(s, 0x20); + + uint32_t object_set_count = (uint32_t)(obj_db->object_set.end - obj_db->object_set.begin); + + vector_ssize_t string_offsets = vector_empty(ssize_t); + vector_ssize_t_reserve(&string_offsets, object_set_count * 4ULL); + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &i->name); + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &i->object_file_name); + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &i->texture_file_name); + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &i->archive_file_name); + } + io_align_write(s, 0x20); + + uint32_t max_object_set_id = 0; + uint32_t object_count = 0; + ssize_t object_sets_offset = io_get_position(s); + size_t off_idx = 0; + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + io_write_uint32_t(s, i->id); + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + io_write(s, 0, 0x10); + if (max_object_set_id < i->id) + max_object_set_id = i->id; + object_count += (uint32_t)(i->object.end - i->object.begin); + } + + vector_ssize_t_clear(&string_offsets, 0); + vector_ssize_t_reserve(&string_offsets, object_count); + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + for (object_info_data* j = i->object.begin; j != i->object.end; j++) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, &j->name); + } + io_align_write(s, 0x20); + + ssize_t objects_offset = io_get_position(s); + off_idx = 0; + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + uint16_t set_id = (uint16_t)i->id; + for (object_info_data* j = i->object.begin; j != i->object.end; j++) { + io_write_uint16_t(s, (uint16_t)j->id); + io_write_uint16_t(s, set_id); + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + } + } + io_align_write(s, 0x20); + + vector_ssize_t_free(&string_offsets, 0); + + io_position_push(s, 0x00, SEEK_SET); + io_write_uint32_t(s, object_set_count); + io_write_uint32_t(s, max_object_set_id); + io_write_uint32_t(s, (uint32_t)object_sets_offset); + io_write_uint32_t(s, object_count); + io_write_uint32_t(s, (uint32_t)objects_offset); + io_write(s, 0, 0x08); + io_position_pop(s); +} + +static void object_database_modern_read_inner(object_database* obj_db, stream* s, uint32_t header_length) { + bool is_x = true; + + io_set_position(s, 0x0C, SEEK_SET); + is_x &= io_read_uint32_t_stream_reverse_endianness(s) == 0; + io_set_position(s, 0x14, SEEK_SET); + is_x &= io_read_uint32_t_stream_reverse_endianness(s) == 0; + + io_set_position(s, 0x00, SEEK_SET); + + io_read_uint32_t_stream_reverse_endianness(s); + uint32_t object_set_count = io_read_uint32_t_stream_reverse_endianness(s); + uint32_t max_object_set_id = io_read_uint32_t_stream_reverse_endianness(s); + ssize_t object_sets_offset = io_read_offset(s, header_length, is_x); + uint32_t object_count = io_read_uint32_t_stream_reverse_endianness(s); + ssize_t objects_offset = io_read_offset(s, header_length, is_x); + + vector_object_set_info_reserve(&obj_db->object_set, object_set_count); + obj_db->object_set.end += object_set_count; + + io_position_push(s, object_sets_offset, SEEK_SET); + if (!is_x) + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + io_read_string_null_terminated_offset(s, + io_read_offset_f2(s, header_length), &set_info->name); + set_info->id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, + io_read_offset_f2(s, header_length), &set_info->object_file_name); + io_read_string_null_terminated_offset(s, + io_read_offset_f2(s, header_length), &set_info->texture_file_name); + io_read_string_null_terminated_offset(s, + io_read_offset_f2(s, header_length), &set_info->archive_file_name); + io_read(s, 0, 0x10); + } + else + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + io_read_string_null_terminated_offset(s, + io_read_offset_x(s), &set_info->name); + set_info->id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, + io_read_offset_x(s), &set_info->object_file_name); + io_read_string_null_terminated_offset(s, + io_read_offset_x(s), &set_info->texture_file_name); + io_read_string_null_terminated_offset(s, + io_read_offset_x(s), &set_info->archive_file_name); + io_read(s, 0, 0x10); + } + io_position_pop(s); + + io_position_push(s, objects_offset, SEEK_SET); + if (!is_x) + for (uint32_t i = 0; i < object_count; i++) { + object_info_data info; + info.id = io_read_uint32_t_stream_reverse_endianness(s); + uint32_t set_id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), &info.name); + + bool found = false; + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + if (set_id != set_info->id) + continue; + + vector_object_info_data_push_back(&set_info->object, &info); + found = true; + break; + } + + if (!found) + string_free(&info.name); + } + else + for (uint32_t i = 0; i < object_count; i++) { + object_info_data info; + info.id = io_read_uint32_t_stream_reverse_endianness(s); + uint32_t set_id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &info.name); + + bool found = false; + for (uint32_t i = 0; i < object_set_count; i++) { + object_set_info* set_info = &obj_db->object_set.begin[i]; + if (set_id != set_info->id) + continue; + + vector_object_info_data_push_back(&set_info->object, &info); + found = true; + break; + } + + if (!found) + string_free(&info.name); + } + io_position_pop(s); + + obj_db->is_x = is_x; + obj_db->modern = true; + obj_db->ready = true; +} + +static void object_database_modern_write_inner(object_database* obj_db, stream* s) { + stream s_mosi; + io_mopen(&s_mosi, 0, 0); + uint32_t off; + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + vector_size_t pof = vector_empty(size_t); + + bool is_x = obj_db->is_x; + + uint32_t object_set_count = (uint32_t)(obj_db->object_set.end - obj_db->object_set.begin); + + uint32_t object_count = 0; + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) + object_count += (uint32_t)(i->object.end - i->object.begin); + + if (!is_x) { + ee = (enrs_entry){ 0, 1, 1, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 6, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 32; + + ee = (enrs_entry){ off, 1, 36, object_set_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 5, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_set_count * 36ULL); + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 1, 12, object_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_count * 12ULL); + off = align_val(off, 0x10); + } + else { + ee = (enrs_entry){ 0, 4, 48, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 48; + + ee = (enrs_entry){ off, 3, 56, object_set_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 3, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_set_count * 56ULL); + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 2, 16, object_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(object_count * 16ULL); + off = align_val(off, 0x10); + } + + io_write_int32_t(&s_mosi, 0); + io_write_int32_t(&s_mosi, 0); + io_write_offset(&s_mosi, 0, 0, is_x); + io_write_int32_t(&s_mosi, 0); + io_write_offset(&s_mosi, 0, 0, is_x); + io_write(&s_mosi, 0, 0x08); + io_align_write(&s_mosi, 0x10); + + ssize_t object_sets_offset = io_get_position(&s_mosi); + io_write(&s_mosi, 0, object_set_count * (is_x ? 0x38ULL : 0x24ULL)); + io_align_write(&s_mosi, 0x10); + + ssize_t objects_offset = io_get_position(&s_mosi); + io_write(&s_mosi, 0, object_count * (is_x ? 0x10ULL : 0x0CULL)); + io_align_write(&s_mosi, 0x10); + + vector_string strings = vector_empty(string); + vector_ssize_t string_offsets = vector_empty(ssize_t); + + vector_string_reserve(&strings, (ssize_t)object_set_count + object_count); + + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + object_database_strings_push_back_check(&strings, string_data(&i->name)); + object_database_strings_push_back_check(&strings, string_data(&i->object_file_name)); + object_database_strings_push_back_check(&strings, string_data(&i->texture_file_name)); + object_database_strings_push_back_check(&strings, string_data(&i->archive_file_name)); + for (object_info_data* j = i->object.begin; j != i->object.end; j++) + object_database_strings_push_back_check(&strings, string_data(&j->name)); + } + + for (string* i = strings.begin; i != &strings.end[-1]; i++) { + char* i_str = string_data(i); + for (string* j = i + 1; j != strings.end; j++) + if (str_utils_compare(i_str, string_data(j)) > 0) { + string temp = *i; + *i = *j; + *j = temp; + i_str = string_data(i); + } + } + + vector_ssize_t_reserve(&string_offsets, strings.end - strings.begin); + + for (string* i = strings.begin; i != strings.end; i++) { + ssize_t off = io_get_position(&s_mosi); + io_write_string_null_terminated(&s_mosi, i); + vector_ssize_t_push_back(&string_offsets, &off); + } + io_align_write(&s_mosi, 0x10); + + io_position_push(&s_mosi, 0x00, SEEK_SET); + io_write_uint32_t(&s_mosi, 0); + io_write_uint32_t(&s_mosi, object_set_count); + io_write_uint32_t(&s_mosi, 0); + io_write_offset_pof_add(&s_mosi, object_sets_offset, 0x20, is_x, &pof); + io_write_uint32_t(&s_mosi, object_count); + io_write_offset_pof_add(&s_mosi, objects_offset, 0x20, is_x, &pof); + io_write(&s_mosi, 0, 0x08); + io_align_write(&s_mosi, 0x10); + + if (!is_x) + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + io_write_offset_f2_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name)), 0x20, &pof); + io_write_uint32_t(&s_mosi, i->id); + io_write_offset_f2_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->object_file_name)), 0x20, &pof); + io_write_offset_f2_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->texture_file_name)), 0x20, &pof); + io_write_offset_f2_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->archive_file_name)), 0x20, &pof); + io_write(&s_mosi, 0, 0x10); + } + else + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + io_write_offset_x_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name)), &pof); + io_write_uint32_t(&s_mosi, i->id); + io_write_offset_x_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->object_file_name)), &pof); + io_write_offset_x_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->texture_file_name)), &pof); + io_write_offset_x_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->archive_file_name)), &pof); + io_write(&s_mosi, 0, 0x10); + } + io_align_write(&s_mosi, 0x10); + + if (!is_x) + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + uint32_t set_id = i->id; + for (object_info_data* j = i->object.begin; j != i->object.end; j++) { + io_write_uint32_t(&s_mosi, j->id); + io_write_uint32_t(&s_mosi, set_id); + io_write_offset_f2_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&j->name)), 0x20, &pof); + } + } + else + for (object_set_info* i = obj_db->object_set.begin; i != obj_db->object_set.end; i++) { + uint32_t set_id = i->id; + for (object_info_data* j = i->object.begin; j != i->object.end; j++) { + io_write_uint32_t(&s_mosi, j->id); + io_write_uint32_t(&s_mosi, set_id); + io_write_offset_x_pof_add(&s_mosi, object_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&j->name)), &pof); + } + } + io_position_pop(&s_mosi); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + io_align_write(&s_mosi, 0x10); + io_mcopy(&s_mosi, &st.data, &st.length); + io_free(&s_mosi); + + st.enrs = e; + st.pof = pof; + + st.header.signature = reverse_endianness_uint32_t('MOSI'); + st.header.length = 0x20; + st.header.use_big_endian = false; + st.header.use_section_size = true; + + f2_struct_swrite(&st, s, true, is_x); + f2_struct_free(&st); +} + +inline static ssize_t object_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return vec_off->begin[i - vec->begin]; + return 0; +} + +inline static void object_database_strings_push_back_check(vector_string* vec, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return; + + string* s = vector_string_reserve_back(vec); + string_init_length(s, str, len); +} diff --git a/src/KKdLib/database/object.h b/src/KKdLib/database/object.h new file mode 100644 index 00000000..1e83772e --- /dev/null +++ b/src/KKdLib/database/object.h @@ -0,0 +1,80 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" + +typedef struct object_info { + uint32_t id; + uint32_t set_id; +} object_info; + +vector(object_info) + +typedef struct object_info_data { + uint32_t id; + string name; + uint64_t name_hash_fnv1a64m; + uint64_t name_hash_fnv1a64m_upper; + uint32_t name_hash_murmurhash; +} object_info_data; + +vector(object_info_data) + +typedef struct object_set_info { + string name; + uint64_t name_hash; + uint32_t id; + string object_file_name; + string texture_file_name; + string archive_file_name; + vector_object_info_data object; +} object_set_info; + +vector(object_set_info) + +typedef struct object_database { + bool ready; + bool modern; + bool is_x; + + vector_string bone_name; + vector_object_set_info object_set; +} object_database; + +extern const object_info object_info_null; + +extern void object_database_init(object_database* obj_db); +extern void object_database_read(object_database* obj_db, char* path, bool modern); +extern void object_database_wread(object_database* obj_db, wchar_t* path, bool modern); +extern void object_database_mread(object_database* obj_db, void* data, size_t length, bool modern); +extern void object_database_write(object_database* obj_db, char* path); +extern void object_database_wwrite(object_database* obj_db, wchar_t* path); +extern void object_database_mwrite(object_database* obj_db, void** data, size_t* length); +extern bool object_database_load_file(void* data, char* path, char* file, uint32_t hash); +extern void object_database_merge_mdata(object_database* obj_db, + object_database* base_obj_db, object_database* mdata_obj_db); +extern void object_database_split_mdata(object_database* obj_db, + object_database* base_obj_db, object_database* mdata_obj_db); +extern bool object_database_get_object_set_info(object_database* obj_db, + char* name, object_set_info** set_info); +extern bool object_database_get_object_set_info_by_set_id(object_database* obj_db, + uint32_t set_id, object_set_info** set_info); +extern bool object_database_get_object_info_data(object_database* obj_db, + char* name, object_info_data** info); +extern bool object_database_get_object_info_data_by_fnv1a64m_hash(object_database* obj_db, + uint64_t hash, object_info_data** info); +extern bool object_database_get_object_info_data_by_fnv1a64m_hash_upper(object_database* obj_db, + uint64_t hash, object_info_data** info); +extern bool object_database_get_object_info_data_by_murmurhash(object_database* obj_db, + uint32_t hash, object_info_data** info); +extern object_info object_database_get_object_info(object_database* obj_db, char* name); +extern void object_database_free(object_database* obj_db); + +extern void object_info_data_free(object_info_data* info); +extern void object_set_info_free(object_set_info* set_info); diff --git a/src/KKdLib/database/sprite.c b/src/KKdLib/database/sprite.c new file mode 100644 index 00000000..057035c8 --- /dev/null +++ b/src/KKdLib/database/sprite.c @@ -0,0 +1,6 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "sprite.h" diff --git a/src/CLOUD/video.h b/src/KKdLib/database/sprite.h similarity index 53% rename from src/CLOUD/video.h rename to src/KKdLib/database/sprite.h index 1d27a3b0..ae73750d 100644 --- a/src/CLOUD/video.h +++ b/src/KKdLib/database/sprite.h @@ -5,8 +5,4 @@ #pragma once -#include "shared.h" - - - -extern int32_t video_main(void* arg); +#include "../default.h" diff --git a/src/KKdLib/database/stage.c b/src/KKdLib/database/stage.c new file mode 100644 index 00000000..dd872319 --- /dev/null +++ b/src/KKdLib/database/stage.c @@ -0,0 +1,525 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "stage.h" +#include "../f2/struct.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +vector_func(stage_info) +vector_func(stage_info_modern) + +static void stage_database_classic_read_inner(stage_database* stage_data, stream* s); +static void stage_database_classic_write_inner(stage_database* stage_data, stream* s); +static void stage_database_modern_read_inner(stage_database* stage_data, stream* s, uint32_t header_length); +static void stage_database_modern_write_inner(stage_database* stage_data, stream* s); + +void stage_database_init(stage_database* stage_data) { + memset(stage_data, 0, sizeof(stage_database)); +} + +void stage_database_read(stage_database* stage_data, char* path, bool modern) { + if (!stage_data || !path) + return; + + if (!modern) { + char* path_bin = str_utils_add(path, ".bin"); + if (path_check_file_exists(path_bin)) { + stream s; + io_open(&s, path_bin, "rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + stage_database_classic_read_inner(stage_data, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + char* path_stg = str_utils_add(path, ".stg"); + if (path_check_file_exists(path_stg)) { + f2_struct st; + f2_struct_read(&st, path_stg); + if (st.header.signature == reverse_endianness_uint32_t('STGC')); { + stream s_stgc; + io_mopen(&s_stgc, st.data, st.length); + s_stgc.is_big_endian = st.header.use_big_endian; + stage_database_modern_read_inner(stage_data, &s_stgc, st.header.length); + io_free(&s_stgc); + } + f2_struct_free(&st); + } + free(path_stg); + } +} + +void stage_database_wread(stage_database* stage_data, wchar_t* path, bool modern) { + if (!stage_data || !path) + return; + + if (!modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + if (path_wcheck_file_exists(path_bin)) { + stream s; + io_wopen(&s, path_bin, L"rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + stage_database_classic_read_inner(stage_data, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + wchar_t* path_stg = str_utils_wadd(path, L".stg"); + if (path_wcheck_file_exists(path_stg)) { + f2_struct st; + f2_struct_wread(&st, path_stg); + if (st.header.signature == reverse_endianness_uint32_t('STGC')); { + stream s_stgc; + io_mopen(&s_stgc, st.data, st.length); + s_stgc.is_big_endian = st.header.use_big_endian; + stage_database_modern_read_inner(stage_data, &s_stgc, st.header.length); + io_free(&s_stgc); + } + f2_struct_free(&st); + } + free(path_stg); + } +} + +void stage_database_mread(stage_database* stage_data, void* data, size_t length, bool modern) { + if (!stage_data || !data || !length) + return; + + if (!modern) { + stream s; + io_mopen(&s, data, length); + stage_database_classic_read_inner(stage_data, &s); + io_free(&s); + } + else { + f2_struct st; + f2_struct_mread(&st, data, length); + if (st.header.signature == reverse_endianness_uint32_t('STGC')); { + stream s_stgc; + io_mopen(&s_stgc, st.data, st.length); + s_stgc.is_big_endian = st.header.use_big_endian; + stage_database_modern_read_inner(stage_data, &s_stgc, st.header.length); + io_free(&s_stgc); + } + f2_struct_free(&st); + } +} + +void stage_database_write(stage_database* stage_data, char* path) { + if (!stage_data || !path || !stage_data->ready) + return; + + if (!stage_data->modern) { + char* path_bin = str_utils_add(path, ".bin"); + stream s; + io_open(&s, path_bin, "wb"); + if (s.io.stream) + stage_database_classic_write_inner(stage_data, &s); + io_free(&s); + free(path_bin); + } + else { + char* path_stg = str_utils_add(path, ".stg"); + stream s; + io_open(&s, path_stg, "wb"); + if (s.io.stream) + stage_database_modern_write_inner(stage_data, &s); + io_free(&s); + free(path_stg); + } +} + +void stage_database_wwrite(stage_database* stage_data, wchar_t* path) { + if (!stage_data || !path || !stage_data->ready) + return; + + if (!stage_data->modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + stream s; + io_wopen(&s, path_bin, L"wb"); + if (s.io.stream) + stage_database_classic_write_inner(stage_data, &s); + io_free(&s); + free(path_bin); + } + else { + wchar_t* path_stg = str_utils_wadd(path, L".stg"); + stream s; + io_wopen(&s, path_stg, L"wb"); + if (s.io.stream) + stage_database_modern_write_inner(stage_data, &s); + io_free(&s); + free(path_stg); + } +} + +void stage_database_mwrite(stage_database* stage_data, void** data, size_t* length) { + if (!stage_data || !data || !stage_data->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + if (!stage_data->modern) + stage_database_classic_write_inner(stage_data, &s); + else + stage_database_modern_write_inner(stage_data, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool stage_database_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + stage_database* stage_data = data; + stage_database_read(stage_data, string_data(&s), stage_data->modern); + + string_free(&s); + return stage_data->ready; +} + +void stage_database_merge_mdata(stage_database* stage_data, + stage_database* base_stage_data, stage_database* mdata_stage_data) { + if (!stage_data || !base_stage_data || !mdata_stage_data + || !base_stage_data->ready || !mdata_stage_data->ready) + return; + + vector_stage_info* stage = &stage_data->stage; + vector_stage_info* base_stage = &base_stage_data->stage; + vector_stage_info* mdata_stage = &mdata_stage_data->stage; + + int32_t count = (int32_t)(base_stage->end - base_stage->begin); + vector_stage_info_reserve(stage, count); + stage->end += count; + + for (int32_t i = 0; i < count; i++) { + stage_info* b_info = &base_stage->begin[i]; + stage_info* info = &stage->begin[i]; + + *info = *b_info; + string_copy(&b_info->name, &info->name); + string_copy(&b_info->auth_3d_name, &info->auth_3d_name); + string_copy(&b_info->collision_file_path, &info->collision_file_path); + if (b_info->auth_3d_count) { + info->auth_3d_count = b_info->auth_3d_count; + info->auth_3d_ids = force_malloc_s(uint32_t, b_info->auth_3d_count); + memcpy(info->auth_3d_ids, b_info->auth_3d_ids, sizeof(uint32_t) * b_info->auth_3d_count); + } + else { + info->auth_3d_count = 0; + info->auth_3d_ids = 0; + } + } + + int32_t mdata_count = (int32_t)(mdata_stage->end - mdata_stage->begin); + mdata_count -= count; + if (mdata_count > 0) + vector_stage_info_reserve(stage, mdata_count); + mdata_count += count; + for (int32_t i = 0; i < mdata_count; i++) { + stage_info* m_info = &mdata_stage->begin[i]; + + char* name_str = string_data(&m_info->name); + size_t name_len = m_info->name.length; + + stage_info* info = 0; + for (info = stage->begin; info != stage->end; info++) + if (!memcmp(name_str, string_data(&info->name), min(name_len, info->name.length) + 1)) + break; + + if (info == stage->end) + info = vector_stage_info_reserve_back(stage); + else + stage_info_free(info); + + *info = *m_info; + string_copy(&m_info->name, &info->name); + string_copy(&m_info->auth_3d_name, &info->auth_3d_name); + string_copy(&m_info->collision_file_path, &info->collision_file_path); + if (m_info->auth_3d_count) { + info->auth_3d_count = m_info->auth_3d_count; + info->auth_3d_ids = force_malloc_s(uint32_t, m_info->auth_3d_count); + memcpy(info->auth_3d_ids, m_info->auth_3d_ids, sizeof(uint32_t) * m_info->auth_3d_count); + } + else { + info->auth_3d_count = 0; + info->auth_3d_ids = 0; + } + } + + stage_data->ready = true; +} + +void stage_database_split_mdata(stage_database* stage_data, + stage_database* base_stage_data, stage_database* mdata_stage_data) { + if (!stage_data || !base_stage_data || !mdata_stage_data + || !stage_data->ready || !base_stage_data->ready) + return; + +} + +void stage_database_free(stage_database* stage_data) { + vector_stage_info_free(&stage_data->stage, stage_info_free); +} + +void stage_info_free(stage_info* info) { + string_free(&info->name); + string_free(&info->auth_3d_name); + string_free(&info->collision_file_path); + free(info->auth_3d_ids); +} + +void stage_info_modern_free(stage_info_modern* info) { + string_free(&info->name); + string_free(&info->auth_3d_name); + free(info->auth_3d_ids); +} + +static void stage_database_classic_read_inner(stage_database* stage_data, stream* s) { + int32_t count = io_read_int32_t(s); + int32_t stages_offset = io_read_int32_t(s); + int32_t stage_effects_offset = io_read_int32_t(s); + int32_t auth3d_id_counts_offset = io_read_int32_t(s); + int32_t auth3d_ids_offsets_offset = io_read_int32_t(s); + + int32_t size = (stage_effects_offset - stages_offset) / count; + stage_data->format = size == 104 ? STAGE_DATA_AC + : (size == 108 ? STAGE_DATA_F + : (size >= 112 ? STAGE_DATA_FT : STAGE_DATA_UNK)); + + if (stage_data->format == STAGE_DATA_UNK) { + stage_data->ready = false; + return; + } + + stage_data->stage = vector_empty(stage_info); + vector_stage_info_reserve(&stage_data->stage, count); + stage_data->stage.end += count; + + io_position_push(s, stages_offset, SEEK_SET); + for (int32_t i = 0; i < count; i++) { + stage_info* stage = &stage_data->stage.begin[i]; + + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &stage->name); + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &stage->auth_3d_name); + stage->object_set_id = io_read_uint32_t(s); + stage->object_ground.id = io_read_uint16_t(s); + stage->object_ground.set_id = io_read_uint16_t(s); + stage->object_unknown.id = io_read_uint16_t(s); + stage->object_unknown.set_id = io_read_uint16_t(s); + stage->object_sky.id = io_read_uint16_t(s); + stage->object_sky.set_id = io_read_uint16_t(s); + stage->object_shadow.id = io_read_uint16_t(s); + stage->object_shadow.set_id = io_read_uint16_t(s); + stage->object_reflect.id = io_read_uint16_t(s); + stage->object_reflect.set_id = io_read_uint16_t(s); + stage->object_refract.id = io_read_uint16_t(s); + stage->object_refract.set_id = io_read_uint16_t(s); + stage->lens_flare_texture = io_read_uint32_t(s); + stage->lens_shaft_texture = io_read_uint32_t(s); + stage->lens_ghost_texture = io_read_uint32_t(s); + stage->lens_shaft_inv_scale = io_read_float_t(s); + stage->unknown = io_read_uint32_t(s); + stage->render_texture = io_read_uint32_t(s); + + if (stage_data->format > STAGE_DATA_AC) + stage->movie_texture = io_read_uint32_t(s); + else + stage->movie_texture = -1; + + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &stage->collision_file_path); + stage->reflect_type = io_read_uint32_t(s); + stage->refract_enable = io_read_uint32_t(s) ? true : false; + + int32_t reflect_offset = io_read_uint32_t(s); + if (reflect_offset) { + io_position_push(s, reflect_offset, SEEK_SET); + stage->reflect_data = true; + stage->reflect.mode = io_read_uint32_t(s); + stage->reflect.blur_num = io_read_uint32_t(s); + stage->reflect.blur_filter = io_read_uint32_t(s); + io_position_pop(s); + } + else + stage->reflect_data = false; + + int32_t refract_offset = io_read_uint32_t(s); + if (refract_offset) { + io_position_push(s, refract_offset, SEEK_SET); + stage->refract_data = true; + stage->refract.mode = io_read_uint32_t(s); + io_position_pop(s); + } + else + stage->refract_data = false; + + if (stage_data->format > STAGE_DATA_F) + stage->flags = io_read_uint32_t(s); + + stage->ring_rectangle_x = io_read_float_t(s); + stage->ring_rectangle_y = io_read_float_t(s); + stage->ring_rectangle_width = io_read_float_t(s); + stage->ring_rectangle_height = io_read_float_t(s); + stage->ring_height = io_read_float_t(s); + stage->ring_out_height = io_read_float_t(s); + + if (stage->object_ground.id == 0xFFFF) + stage->object_ground.id = -1; + if (stage->object_ground.set_id == 0xFFFF) + stage->object_ground.set_id = -1; + + if (stage->object_unknown.id == 0xFFFF) + stage->object_unknown.id = -1; + if (stage->object_unknown.set_id == 0xFFFF) + stage->object_unknown.set_id = -1; + + if (stage->object_sky.id == 0xFFFF) + stage->object_sky.id = -1; + if (stage->object_sky.set_id == 0xFFFF) + stage->object_sky.set_id = -1; + + if (stage->object_shadow.id == 0xFFFF) + stage->object_shadow.id = -1; + if (stage->object_shadow.set_id == 0xFFFF) + stage->object_shadow.set_id = -1; + + if (stage->object_reflect.id == 0xFFFF) + stage->object_reflect.id = -1; + if (stage->object_reflect.set_id == 0xFFFF) + stage->object_reflect.set_id = -1; + + if (stage->object_refract.id == 0xFFFF) + stage->object_refract.id = -1; + if (stage->object_refract.set_id == 0xFFFF) + stage->object_refract.set_id = -1; + } + io_position_pop(s); + + io_position_push(s, stage_effects_offset, SEEK_SET); + for (int32_t i = 0; i < count; i++) { + stage_info* stage = &stage_data->stage.begin[i]; + stage_effects* effects = &stage->effects; + + for (int32_t j = 0; j < 8; j++) + effects->field_0[j] = io_read_uint32_t(s); + + for (int32_t j = 0; j < 16; j++) + effects->parent_bone_node[j] = io_read_uint32_t(s); + } + io_position_pop(s); + + io_position_push(s, auth3d_id_counts_offset, SEEK_SET); + for (int32_t i = 0; i < count; i++) { + stage_info* stage = &stage_data->stage.begin[i]; + + stage->auth_3d_count = io_read_uint32_t(s); + } + io_position_pop(s); + + io_position_push(s, auth3d_ids_offsets_offset, SEEK_SET); + for (int32_t i = 0; i < count; i++) { + stage_info* stage = &stage_data->stage.begin[i]; + + uint32_t id = io_read_uint32_t(s); + uint32_t offset = io_read_uint32_t(s); + if (!offset) { + stage->auth_3d_count = 0; + continue; + } + + io_position_push(s, offset, SEEK_SET); + for (uint32_t j = 0; j < stage->auth_3d_count; j++) { + if (io_read_uint32_t(s) == -1) { + stage->auth_3d_count = j; + break; + } + } + io_position_pop(s); + + if (stage->auth_3d_count) { + io_position_push(s, offset, SEEK_SET); + stage->auth_3d_ids = force_malloc_s(uint32_t, stage->auth_3d_count); + for (uint32_t j = 0; j < stage->auth_3d_count; j++) + stage->auth_3d_ids[j] = io_read_uint32_t(s); + io_position_pop(s); + } + + } + io_position_pop(s); + + stage_data->ready = true; + stage_data->modern = false; +} + +static void stage_database_classic_write_inner(stage_database* stage_data, stream* s) { + /*writer.AddStringToStringTable( Name ); + writer.AddStringToStringTable( Auth3dName ); + writer.Write( ObjectSetID ); + Objects.WriteClassic( writer ); + writer.Write( LensFlareTexture ); + writer.Write( LensShaftTexture ); + writer.Write( LensGhostTexture ); + writer.Write( LensShaftInvScale ); + writer.Write( Field00 ); + writer.Write( RenderTextureId ); + + if ( format > BinaryFormat.DT ) + writer.Write( MovieTextureId ); + + writer.AddStringToStringTable( CollisionFilePath ); + writer.Write( ReflectType ); + writer.Write( RefractEnable ? 1u : 0u ); + + writer.ScheduleWriteOffsetIf( Reflect != null && Reflect.BlurNum != 0 , 4, AlignmentMode.Left, + () => Reflect.Write( writer ) ); + + writer.ScheduleWriteOffsetIf( Refract != null , 4, AlignmentMode.Left, + () => Refract.Write( writer ) ); + + if ( format == BinaryFormat.FT ) + writer.Write( ( int ) Flags ); + + writer.Write( RingRectangleX ); + writer.Write( RingRectangleY ); + writer.Write( RingRectangleWidth) ; + writer.Write( RingRectangleHeight ); + writer.Write( RingRingHeight ); + writer.Write( RingOutHeight );*/ +} + +static void stage_database_modern_read_inner(stage_database* stage_data, stream* s, uint32_t header_length) { + +} + +static void stage_database_modern_write_inner(stage_database* stage_data, stream* s) { + +} + diff --git a/src/KKdLib/database/stage.h b/src/KKdLib/database/stage.h new file mode 100644 index 00000000..4578c2d9 --- /dev/null +++ b/src/KKdLib/database/stage.h @@ -0,0 +1,163 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" +#include "object.h" + +typedef enum stage_data_format { + STAGE_DATA_UNK = 0, + STAGE_DATA_AC, + STAGE_DATA_F, + STAGE_DATA_FT, +} stage_data_format; + +typedef enum stage_data_flags { + STAGE_DATA_FLAG_1 = 0x1, + STAGE_DATA_LIGHT_CHARA_AMBIENT = 0x2, + STAGE_DATA_FLAG_4 = 0x4, + STAGE_DATA_FLAG_8 = 0x8, +} stage_data_flags; + +typedef enum stage_data_reflect_refract_resolution_mode { + STAGE_DATA_REFLECT_REFRACT_RESOLUTION_256x256 = 0x00, + STAGE_DATA_REFLECT_REFRACT_RESOLUTION_512x256 = 0x01, + STAGE_DATA_REFLECT_REFRACT_RESOLUTION_512x512 = 0x02, +} stage_data_reflect_refract_resolution_mode; + +typedef enum stage_data_blur_filter_mode { + STAGE_DATA_BLUR_FILTER_4 = 0x00, + STAGE_DATA_BLUR_FILTER_9 = 0x01, + STAGE_DATA_BLUR_FILTER_16 = 0x02, + STAGE_DATA_BLUR_FILTER_32 = 0x03, +} stage_data_blur_filter_mode; + +typedef struct stage_data_reflect { + stage_data_reflect_refract_resolution_mode mode; + int32_t blur_num; + stage_data_blur_filter_mode blur_filter; +} stage_data_reflect; + +typedef struct stage_data_refract { + stage_data_reflect_refract_resolution_mode mode; +} stage_data_refract; + +typedef struct stage_effects { + int32_t field_0[8]; + int32_t parent_bone_node[16]; +} stage_effects; + +typedef struct stage_info { + string name; + string auth_3d_name; + uint32_t object_set_id; + object_info object_ground; + object_info object_unknown; + object_info object_sky; + object_info object_shadow; + object_info object_reflect; + object_info object_refract; + uint32_t lens_flare_texture; + uint32_t lens_shaft_texture; + uint32_t lens_ghost_texture; + float_t lens_shaft_inv_scale; + uint32_t unknown; + uint32_t render_texture; + uint32_t movie_texture; + string collision_file_path; + uint32_t reflect_type; + bool refract_enable; + bool reflect_data; + stage_data_reflect reflect; + bool refract_data; + stage_data_refract refract; + stage_data_flags flags; + float_t ring_rectangle_x; + float_t ring_rectangle_y; + float_t ring_rectangle_width; + float_t ring_rectangle_height; + float_t ring_height; + float_t ring_out_height; + stage_effects effects; + uint32_t auth_3d_count; + uint32_t* auth_3d_ids; +} stage_info; + +typedef struct stage_info_modern { + uint64_t id; + string name; + string auth_3d_name; + object_info object_ground; + object_info object_sky; + object_info object_shadow; + object_info object_reflect; + object_info object_refract; + float_t lens_shaft_inv_scale; + uint32_t unknown; + uint32_t render_texture; + uint32_t render_texture_flag; + uint32_t movie_texture; + uint32_t movie_texture_flag; + uint32_t field_04; + uint32_t field_04_flag; + uint32_t field_05; + uint32_t field_05_flag; + uint32_t field_06; + uint32_t field_06_flag; + uint32_t field_07; + uint32_t field_07_flag; + uint32_t field_08; + uint32_t field_09; + uint32_t field_10; + size_t field_11; + size_t field_12; + float_t ring_rectangle_x; + float_t ring_rectangle_y; + float_t ring_rectangle_width; + float_t ring_rectangle_height; + float_t ring_height; + float_t ring_out_height; + uint32_t field_13; + stage_effects effects; + uint32_t auth_3d_count; + uint32_t* auth_3d_ids; +} stage_info_modern; + +vector(stage_info) +vector(stage_info_modern) + +typedef struct stage_database { + bool ready; + bool modern; + union { + bool is_x; + stage_data_format format; + }; + + union { + vector_stage_info stage; + vector_stage_info_modern stage_modern; + }; +} stage_database; + +extern void stage_database_init(stage_database* stage_data); +extern void stage_database_read(stage_database* stage_data, char* path, bool modern); +extern void stage_database_wread(stage_database* stage_data, wchar_t* path, bool modern); +extern void stage_database_mread(stage_database* stage_data, void* data, size_t length, bool modern); +extern void stage_database_write(stage_database* stage_data, char* path); +extern void stage_database_wwrite(stage_database* stage_data, wchar_t* path); +extern void stage_database_mwrite(stage_database* stage_data, void** data, size_t* length); +extern bool stage_database_load_file(void* data, char* path, char* file, uint32_t hash); +extern void stage_database_merge_mdata(stage_database* stage_data, + stage_database* base_stage_data, stage_database* mdata_stage_data); +extern void stage_database_split_mdata(stage_database* stage_data, + stage_database* base_stage_data, stage_database* mdata_stage_data); +extern void stage_database_free(stage_database* stage_data); + +extern void stage_info_free(stage_info* info); +extern void stage_info_modern_free(stage_info_modern* info); diff --git a/src/KKdLib/database/string_array.c b/src/KKdLib/database/string_array.c new file mode 100644 index 00000000..369e07b9 --- /dev/null +++ b/src/KKdLib/database/string_array.c @@ -0,0 +1,6 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "string_array.h" diff --git a/src/KKdLib/database/string_array.h b/src/KKdLib/database/string_array.h new file mode 100644 index 00000000..ae73750d --- /dev/null +++ b/src/KKdLib/database/string_array.h @@ -0,0 +1,8 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" diff --git a/src/KKdLib/database/texture.c b/src/KKdLib/database/texture.c new file mode 100644 index 00000000..5673eeb9 --- /dev/null +++ b/src/KKdLib/database/texture.c @@ -0,0 +1,516 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "texture.h" +#include "../f2/struct.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../hash.h" +#include "../str_utils.h" + +vector_func(texture_info) + +static void texture_database_classic_read_inner(texture_database* tex_db, stream* s); +static void texture_database_classic_write_inner(texture_database* tex_db, stream* s); +static void texture_database_modern_read_inner(texture_database* tex_db, stream* s, uint32_t header_length); +static void texture_database_modern_write_inner(texture_database* tex_db, stream* s); +static ssize_t texture_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str); +static void texture_database_strings_push_back_check(vector_string* vec, char* str); + +void texture_database_init(texture_database* tex_db) { + memset(tex_db, 0, sizeof(texture_database)); +} + +void texture_database_read(texture_database* tex_db, char* path, bool modern) { + if (!tex_db || !path) + return; + + if (!modern) { + char* path_bin = str_utils_add(path, ".bin"); + if (path_check_file_exists(path_bin)) { + stream s; + io_open(&s, path_bin, "rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + texture_database_classic_read_inner(tex_db, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + char* path_txi = str_utils_add(path, ".txi"); + if (path_check_file_exists(path_txi)) { + f2_struct st; + f2_struct_read(&st, path_txi); + if (st.header.signature == reverse_endianness_uint32_t('MTXI')); { + stream s_mtxi; + io_mopen(&s_mtxi, st.data, st.length); + s_mtxi.is_big_endian = st.header.use_big_endian; + texture_database_modern_read_inner(tex_db, &s_mtxi, st.header.length); + io_free(&s_mtxi); + } + f2_struct_free(&st); + } + free(path_txi); + } +} + +void texture_database_wread(texture_database* tex_db, wchar_t* path, bool modern) { + if (!tex_db || !path) + return; + + if (!modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + if (path_wcheck_file_exists(path_bin)) { + stream s; + io_wopen(&s, path_bin, L"rb"); + if (s.io.stream) { + uint8_t* data = force_malloc(s.length); + io_read(&s, data, s.length); + stream s_bin; + io_mopen(&s_bin, data, s.length); + texture_database_classic_read_inner(tex_db, &s_bin); + io_free(&s_bin); + free(data); + } + io_free(&s); + } + free(path_bin); + } + else { + wchar_t* path_txi = str_utils_wadd(path, L".txi"); + if (path_wcheck_file_exists(path_txi)) { + f2_struct st; + f2_struct_wread(&st, path_txi); + if (st.header.signature == reverse_endianness_uint32_t('MTXI')); { + stream s_mtxi; + io_mopen(&s_mtxi, st.data, st.length); + s_mtxi.is_big_endian = st.header.use_big_endian; + texture_database_modern_read_inner(tex_db, &s_mtxi, st.header.length); + io_free(&s_mtxi); + } + f2_struct_free(&st); + } + free(path_txi); + } +} + +void texture_database_mread(texture_database* tex_db, void* data, size_t length, bool modern) { + if (!tex_db || !data || !length) + return; + + if (!modern) { + stream s; + io_mopen(&s, data, length); + texture_database_classic_read_inner(tex_db, &s); + io_free(&s); + } + else { + f2_struct st; + f2_struct_mread(&st, data, length); + if (st.header.signature == reverse_endianness_uint32_t('MTXI')); { + stream s_mtxi; + io_mopen(&s_mtxi, st.data, st.length); + s_mtxi.is_big_endian = st.header.use_big_endian; + texture_database_modern_read_inner(tex_db, &s_mtxi, st.header.length); + io_free(&s_mtxi); + } + f2_struct_free(&st); + } +} + +void texture_database_write(texture_database* tex_db, char* path) { + if (!tex_db || !path || !tex_db->ready) + return; + + if (!tex_db->modern) { + char* path_bin = str_utils_add(path, ".bin"); + stream s; + io_open(&s, path_bin, "wb"); + if (s.io.stream) + texture_database_classic_write_inner(tex_db, &s); + io_free(&s); + free(path_bin); + } + else { + char* path_txi = str_utils_add(path, ".txi"); + stream s; + io_open(&s, path_txi, "wb"); + if (s.io.stream) + texture_database_modern_write_inner(tex_db, &s); + io_free(&s); + free(path_txi); + } +} + +void texture_database_wwrite(texture_database* tex_db, wchar_t* path) { + if (!tex_db || !path || !tex_db->ready) + return; + + if (!tex_db->modern) { + wchar_t* path_bin = str_utils_wadd(path, L".bin"); + stream s; + io_wopen(&s, path_bin, L"wb"); + if (s.io.stream) + texture_database_classic_write_inner(tex_db, &s); + io_free(&s); + free(path_bin); + } + else { + wchar_t* path_txi = str_utils_wadd(path, L".txi"); + stream s; + io_wopen(&s, path_txi, L"wb"); + if (s.io.stream) + texture_database_modern_write_inner(tex_db, &s); + io_free(&s); + free(path_txi); + } +} + +void texture_database_mwrite(texture_database* tex_db, void** data, size_t* length) { + if (!tex_db || !data || !tex_db->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + if (!tex_db->modern) + texture_database_classic_write_inner(tex_db, &s); + else + texture_database_modern_write_inner(tex_db, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool texture_database_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + texture_database* tex_db = data; + texture_database_read(tex_db, string_data(&s), tex_db->modern); + + string_free(&s); + return tex_db->ready; +} + +void texture_database_merge_mdata(texture_database* tex_db, + texture_database* base_tex_db, texture_database* mdata_tex_db) { + if (!tex_db || !base_tex_db || !mdata_tex_db + || !base_tex_db->ready || !mdata_tex_db->ready) + return; + + vector_texture_info* texture = &tex_db->texture; + vector_texture_info* base_texture = &base_tex_db->texture; + vector_texture_info* mdata_texture = &mdata_tex_db->texture; + + int32_t count = (int32_t)(base_texture->end - base_texture->begin); + vector_texture_info_reserve(texture, count); + texture->end += count; + + for (int32_t i = 0; i < count; i++) { + texture_info* b_info = &base_texture->begin[i]; + texture_info* info = &texture->begin[i]; + + info->id = b_info->id; + string_copy(&b_info->name, &info->name); + info->name_hash = hash_fnv1a64m(string_data(&info->name), info->name.length); + } + + int32_t mdata_count = (int32_t)(mdata_texture->end - mdata_texture->begin); + for (int32_t i = 0; i < mdata_count; i++) { + texture_info* m_info = &mdata_texture->begin[i]; + + uint32_t id = m_info->id; + + texture_info* info = 0; + for (info = texture->begin; info != texture->end; info++) + if (id == info->id) + break; + + if (info == texture->end) + info = vector_texture_info_reserve_back(texture); + + info->id = m_info->id; + string_replace(&m_info->name, &info->name); + info->name_hash = hash_fnv1a64m(string_data(&info->name), info->name.length); + } + + tex_db->ready = true; +} + +void texture_database_split_mdata(texture_database* tex_db, + texture_database* base_tex_db, texture_database* mdata_tex_db) { + if (!tex_db || !base_tex_db || !mdata_tex_db + || !tex_db->ready || !mdata_tex_db->ready) + return; + +} + +uint32_t texture_database_get_texture_id(texture_database* tex_db, char* name) { + if (!tex_db || !name) + return -1; + + uint64_t name_hash = hash_fnv1a64m(name, utf8_length(name)); + + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) + if (name_hash == i->name_hash) + return i->id; + return -1; +} + +char* texture_database_get_texture_name(texture_database* tex_db, uint32_t id) { + if (!tex_db || id == -1) + return 0; + + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) + if (id == i->id) + return string_data(&i->name); + return 0; +} + +void texture_database_free(texture_database* tex_db) { + vector_texture_info_free(&tex_db->texture, texture_info_free); +} + +void texture_info_free(texture_info* info) { + string_free(&info->name); +} + +static void texture_database_classic_read_inner(texture_database* tex_db, stream* s) { + uint32_t texture_count = io_read_uint32_t(s); + uint32_t textures_offset = io_read_uint32_t(s); + + vector_texture_info_reserve(&tex_db->texture, texture_count); + tex_db->texture.end += texture_count; + + io_position_push(s, textures_offset, SEEK_SET); + for (uint32_t i = 0; i < texture_count; i++) { + texture_info* info = &tex_db->texture.begin[i]; + info->id = io_read_uint32_t(s); + io_read_string_null_terminated_offset(s, io_read_uint32_t(s), &info->name); + } + io_position_pop(s); + + tex_db->is_x = false; + tex_db->modern = false; + tex_db->ready = true; +} + +static void texture_database_classic_write_inner(texture_database* tex_db, stream* s) { + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_write_uint32_t(s, 0x90669066); + io_align_write(s, 0x20); + + uint32_t texture_count = (uint32_t)(tex_db->texture.end - tex_db->texture.begin); + + vector_ssize_t string_offsets = vector_empty(ssize_t); + vector_ssize_t_reserve(&string_offsets, texture_count); + + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) { + ssize_t off = io_get_position(s); + io_write_string_null_terminated(s, &i->name); + vector_ssize_t_push_back(&string_offsets, &off); + } + io_align_write(s, 0x20); + + ssize_t textures_offset = io_get_position(s); + size_t off_idx = 0; + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) { + io_write_uint32_t(s, i->id); + io_write_uint32_t(s, (uint32_t)string_offsets.begin[off_idx++]); + } + io_align_write(s, 0x20); + + vector_ssize_t_free(&string_offsets, 0); + + io_position_push(s, 0x00, SEEK_SET); + io_write_uint32_t(s, texture_count); + io_write_uint32_t(s, (uint32_t)textures_offset); + io_position_pop(s); +} + +static void texture_database_modern_read_inner(texture_database* tex_db, stream* s, uint32_t header_length) { + bool is_x = true; + + io_set_position(s, 0x04, SEEK_SET); + is_x &= io_read_uint32_t_stream_reverse_endianness(s) == 0; + + io_set_position(s, 0x00, SEEK_SET); + + uint32_t texture_count = io_read_uint32_t_stream_reverse_endianness(s); + ssize_t textures_offset = io_read_offset(s, header_length, is_x); + + vector_texture_info_reserve(&tex_db->texture, texture_count); + tex_db->texture.end += texture_count; + + io_position_push(s, textures_offset, SEEK_SET); + if (!is_x) + for (uint32_t i = 0; i < texture_count; i++) { + texture_info* info = &tex_db->texture.begin[i]; + info->id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, io_read_offset_f2(s, header_length), &info->name); + } + else + for (uint32_t i = 0; i < texture_count; i++) { + texture_info* info = &tex_db->texture.begin[i]; + info->id = io_read_uint32_t_stream_reverse_endianness(s); + io_read_string_null_terminated_offset(s, io_read_offset_x(s), &info->name); + } + io_position_pop(s); + + tex_db->is_x = is_x; + tex_db->modern = true; + tex_db->ready = true; +} + +static void texture_database_modern_write_inner(texture_database* tex_db, stream* s) { + stream s_mtxi; + io_mopen(&s_mtxi, 0, 0); + uint32_t off; + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + vector_size_t pof = vector_empty(size_t); + + bool is_x = tex_db->is_x; + + uint32_t texture_count = (uint32_t)(tex_db->texture.end - tex_db->texture.begin); + + if (!is_x) { + ee = (enrs_entry){ 0, 2, 8, texture_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 9, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = 8; + off = align_val(off, 0x10); + + ee = (enrs_entry){ off, 2, 8, texture_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(texture_count * 16ULL); + } + else { + texture_count++; + ee = (enrs_entry){ 0, 2, 16, texture_count, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + off = (uint32_t)(texture_count * 16ULL); + texture_count--; + } + + io_write_int32_t(&s_mtxi, 0); + io_write_offset(&s_mtxi, 0, 0x20, is_x); + io_align_write(&s_mtxi, 0x10); + + ssize_t textures_offset = io_get_position(&s_mtxi); + io_write(&s_mtxi, 0, texture_count * (is_x ? 0x10ULL : 0x08ULL)); + io_align_write(&s_mtxi, 0x10); + + vector_string strings = vector_empty(string); + vector_ssize_t string_offsets = vector_empty(ssize_t); + + vector_string_reserve(&strings, texture_count); + + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) + texture_database_strings_push_back_check(&strings, string_data(&i->name)); + + for (string* i = strings.begin; i != &strings.end[-1]; i++) { + char* i_str = string_data(i); + for (string* j = i + 1; j != strings.end; j++) + if (str_utils_compare(i_str, string_data(j)) > 0) { + string temp = *i; + *i = *j; + *j = temp; + i_str = string_data(i); + } + } + + vector_ssize_t_reserve(&string_offsets, strings.end - strings.begin); + + for (string* i = strings.begin; i != strings.end; i++) { + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(&s_mtxi); + io_write_string_null_terminated(&s_mtxi, i); + } + io_align_write(&s_mtxi, 0x10); + + io_position_push(&s_mtxi, 0x00, SEEK_SET); + io_write_uint32_t(&s_mtxi, texture_count); + io_write_offset_pof_add(&s_mtxi, textures_offset, 0x20, is_x, &pof); + io_align_write(&s_mtxi, 0x10); + + if (!is_x) + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) { + io_write_uint32_t(&s_mtxi, i->id); + ssize_t offset = texture_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name)); + io_write_offset_f2_pof_add(&s_mtxi, offset, 0x20, &pof); + } + else + for (texture_info* i = tex_db->texture.begin; i != tex_db->texture.end; i++) { + io_write_uint32_t(&s_mtxi, i->id); + ssize_t offset = texture_database_strings_get_string_offset(&strings, + &string_offsets, string_data(&i->name)); + io_write_offset_x_pof_add(&s_mtxi, offset, &pof); + } + io_position_pop(&s_mtxi); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + io_align_write(&s_mtxi, 0x10); + io_mcopy(&s_mtxi, &st.data, &st.length); + io_free(&s_mtxi); + + st.enrs = e; + st.pof = pof; + + st.header.signature = reverse_endianness_uint32_t('MTXI'); + st.header.length = 0x20; + st.header.use_big_endian = false; + st.header.use_section_size = true; + + f2_struct_swrite(&st, s, true, tex_db->is_x); + f2_struct_free(&st); +} + +inline static ssize_t texture_database_strings_get_string_offset(vector_string* vec, + vector_ssize_t* vec_off, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return vec_off->begin[i - vec->begin]; + return 0; +} + +inline static void texture_database_strings_push_back_check(vector_string* vec, char* str) { + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return; + + string* s = vector_string_reserve_back(vec); + string_init_length(s, str, len); +} diff --git a/src/KKdLib/database/texture.h b/src/KKdLib/database/texture.h new file mode 100644 index 00000000..056b0aed --- /dev/null +++ b/src/KKdLib/database/texture.h @@ -0,0 +1,44 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" + +typedef struct texture_info { + string name; + uint64_t name_hash; + uint32_t id; +} texture_info; + +vector(texture_info) + +typedef struct texture_database { + bool ready; + bool modern; + bool is_x; + + vector_texture_info texture; +} texture_database; + +extern void texture_database_init(texture_database* tex_db); +extern void texture_database_read(texture_database* tex_db, char* path, bool modern); +extern void texture_database_wread(texture_database* tex_db, wchar_t* path, bool modern); +extern void texture_database_mread(texture_database* tex_db, void* data, size_t length, bool modern); +extern void texture_database_write(texture_database* tex_db, char* path); +extern void texture_database_wwrite(texture_database* tex_db, wchar_t* path); +extern void texture_database_mwrite(texture_database* tex_db, void** data, size_t* length); +extern bool texture_database_load_file(void* data, char* path, char* file, uint32_t hash); +extern void texture_database_merge_mdata(texture_database* tex_db, + texture_database* base_tex_db, texture_database* mdata_tex_db); +extern void texture_database_split_mdata(texture_database* tex_db, + texture_database* base_tex_db, texture_database* mdata_tex_db); +extern uint32_t texture_database_get_texture_id(texture_database* tex_db, char* name); +extern char* texture_database_get_texture_name(texture_database* tex_db, uint32_t id); +extern void texture_database_free(texture_database* tex_db); + +extern void texture_info_free(texture_info* info); diff --git a/src/KKdLib/dds.c b/src/KKdLib/dds.c index 51fdafcf..4561e451 100644 --- a/src/KKdLib/dds.c +++ b/src/KKdLib/dds.c @@ -4,7 +4,7 @@ */ #include "dds.h" -#include "io_stream.h" +#include "io/stream.h" #include "str_utils.h" #pragma pack(push, 1) @@ -253,7 +253,7 @@ void dds_wread(dds* d, wchar_t* path) { d->mipmaps_count = dds_h.flags & DDSD_MIPMAPCOUNT ? dds_h.mipMapCount : 1; d->has_cube_map = dds_h.caps2 & DDS_cube_map ? true : false; d->data = vector_ptr_empty(void); - vector_ptr_void_reserve(&d->data, d->has_cube_map ? d->mipmaps_count * 6LL : d->mipmaps_count); + vector_ptr_void_reserve(&d->data, d->has_cube_map ? d->mipmaps_count * 6ULL : d->mipmaps_count); do for (uint32_t i = 0; i < d->mipmaps_count; i++) { diff --git a/src/KKdLib/default.c b/src/KKdLib/default.c index fd365b3f..c4d930e8 100644 --- a/src/KKdLib/default.c +++ b/src/KKdLib/default.c @@ -6,6 +6,9 @@ #include "default.h" void* force_malloc(size_t size) { + if (!size) + return 0; + void* buf = 0; while (!buf) buf = malloc(size); diff --git a/src/KKdLib/default.h b/src/KKdLib/default.h index 09df47e7..17eab96b 100644 --- a/src/KKdLib/default.h +++ b/src/KKdLib/default.h @@ -42,31 +42,15 @@ null(double_t) null(size_t) null(ssize_t) +#define ptr_t(t) \ +typedef t* ptr_##t; + #define pair(t0, t1) \ typedef struct pair_##t0##_##t1 { \ t0 key; \ t1 val; \ } pair_##t0##_##t1; -#define pointer_ptr(t) \ -typedef struct pointer_ptr_##t { \ - int32_t offset; \ - t* value; \ -} pointer_ptr_##t; - -#define pointer(t) \ -typedef struct pointer_##t { \ - int32_t offset; \ - t value; \ -} pointer_##t; - -#define count_pointer(t) \ -typedef struct count_pointer_##t { \ - int32_t count; \ - int32_t offset; \ - t value; \ -} count_pointer_##t; - #ifndef max #define max(a, b) (((a) > (b)) ? (a) : (b)) #endif @@ -79,7 +63,7 @@ typedef struct count_pointer_##t { \ #define div_min_max(a, b, c) (((a) >= 0) ? ((a) / (b)) : ((a) / (c))) -#define clamp(a, b, c) (min(max(a, b), c)) +#define clamp(a, b, c) (((((a) > (b)) ? (a) : (b)) < (c)) ? (((a) > (b)) ? (a) : (b)) : (c)) #define align_val(a, b) ((((a) + (b) - 1) / (b)) * (b)) diff --git a/src/KKdLib/io_deflate.c b/src/KKdLib/deflate.c similarity index 99% rename from src/KKdLib/io_deflate.c rename to src/KKdLib/deflate.c index 86fedbfa..e14b7514 100644 --- a/src/KKdLib/io_deflate.c +++ b/src/KKdLib/deflate.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "io_deflate.h" +#include "deflate.h" #include static size_t compress_static(struct libdeflate_compressor* c, void* src, size_t src_length, diff --git a/src/KKdLib/io_deflate.h b/src/KKdLib/deflate.h similarity index 100% rename from src/KKdLib/io_deflate.h rename to src/KKdLib/deflate.h diff --git a/src/KKdLib/divafile.c b/src/KKdLib/divafile.c index 94076dce..da4d12d8 100644 --- a/src/KKdLib/divafile.c +++ b/src/KKdLib/divafile.c @@ -5,7 +5,6 @@ #include "divafile.h" #include "aes.h" -#include "io_stream.h" #include "str_utils.h" static const uint8_t key[] = { @@ -46,6 +45,57 @@ void divafile_wdecrypt(wchar_t* path) { free(file_temp); } +void divafile_mdecrypt(void* enc_data, void** dec_data, size_t* dec_size) { + if (!enc_data || !dec_data || !dec_size) + return; + + *dec_data = 0; + *dec_size = 0; + + size_t d = (size_t)enc_data; + + uint64_t signature = *(uint64_t*)d; + if (signature != 0x454C494641564944) + return; + + uint32_t stream_length = *(uint32_t*)(d + 8); + uint32_t file_length = *(uint32_t*)(d + 12); + void* data = force_malloc(stream_length); + memcpy(data, (void*)(d + 16), stream_length); + + struct aes_ctx ctx; + aes_init_ctx(&ctx, (uint8_t*)key); + aes_ecb_decrypt_buffer(&ctx, data, stream_length); + + *dec_data = data; + *dec_size = file_length; +} + +void divafile_sdecrypt(stream* s) { + if (!s) + return; + + size_t pos = io_get_position(s); + uint64_t signature = io_read_uint64_t(s); + if (signature != 0x454C494641564944) { + io_set_position(s, pos, SEEK_SET); + return; + } + + uint32_t stream_length = io_read_uint32_t(s); + uint32_t file_length = io_read_uint32_t(s); + void* data = force_malloc(stream_length); + io_read(s, data, stream_length); + + struct aes_ctx ctx; + aes_init_ctx(&ctx, (uint8_t*)key); + aes_ecb_decrypt_buffer(&ctx, data, stream_length); + + io_free(s); + io_mopen(s, data, file_length); + free(data); +} + void divafile_encrypt(char* path) { wchar_t* file_buf = utf8_to_utf16(path); divafile_wencrypt(file_buf); @@ -79,3 +129,26 @@ void divafile_wencrypt(wchar_t* path) { io_free(&s_dec); free(file_temp); } + +void divafile_mencrypt(void* dec_data, size_t dec_size, void** enc_data, size_t* enc_size) { + if (!dec_data || !dec_size || !enc_data || !enc_size) + return; + + size_t len = dec_size; + size_t len_align = align_val(len, 0x10); + + void* data = force_malloc(len_align + 0x10); + size_t d = (size_t)data; + memcpy((void*)(d + 16), dec_data, len); + + struct aes_ctx ctx; + aes_init_ctx(&ctx, (uint8_t*)key); + aes_ecb_encrypt_buffer(&ctx, (void*)(d + 16), len_align); + + *(uint64_t*)d = 0x454C494641564944; + *(uint32_t*)(d + 8) = (uint32_t)len_align; + *(uint32_t*)(d + 12) = (uint32_t)len; + + *enc_data = data; + *enc_size = len_align + 0x10; +} diff --git a/src/KKdLib/divafile.h b/src/KKdLib/divafile.h index 8599b925..b9ff0be7 100644 --- a/src/KKdLib/divafile.h +++ b/src/KKdLib/divafile.h @@ -6,8 +6,12 @@ #pragma once #include "default.h" +#include "io/stream.h" extern void divafile_decrypt(char* path); extern void divafile_wdecrypt(wchar_t* path); +extern void divafile_mdecrypt(void* enc_data, void** dec_data, size_t* dec_size); +extern void divafile_sdecrypt(stream* s); extern void divafile_encrypt(char* path); extern void divafile_wencrypt(wchar_t* path); +extern void divafile_mencrypt(void* dec_data, size_t dec_size, void** enc_data, size_t* enc_size); diff --git a/src/KKdLib/dsc.c b/src/KKdLib/dsc.c index 54c1d368..187cfb04 100644 --- a/src/KKdLib/dsc.c +++ b/src/KKdLib/dsc.c @@ -4,691 +4,694 @@ */ #include "dsc.h" +#include "f2/struct.h" + +vector_func(dsc_data) static const dsc_func dsc_ac101_func[] = { - { 0, 0, L"END" }, - { 1, 1, L"TIME" }, - { 2, 3, L"MIKU_MOVE" }, - { 3, 1, L"MIKU_ROT" }, - { 4, 1, L"MIKU_DISP" }, - { 5, 1, L"MIKU_SHADOW" }, - { 6, 7, L"TARGET" }, - { 7, 3, L"SET_MOTION" }, - { 8, 1, L"SET_PLAYDATA" }, - { 9, 5, L"EFFECT" }, - { 10, 2, L"FADEIN_FIELD" }, - { 11, 1, L"EFFECT_OFF" }, - { 12, 6, L"SET_CAMERA" }, - { 13, 2, L"DATA_CAMERA" }, - { 14, 1, L"CHANGE_FIELD" }, - { 15, 1, L"HIDE_FIELD" }, - { 16, 3, L"MOVE_FIELD" }, - { 17, 2, L"FADEOUT_FIELD" }, - { 18, 2, L"EYE_ANIM" }, - { 19, 3, L"MOUTH_ANIM" }, - { 20, 4, L"HAND_ANIM" }, - { 21, 3, L"LOOK_ANIM" }, - { 22, 3, L"EXPRESSION" }, - { 23, 4, L"LOOK_CAMERA" }, - { 24, 1, L"LYRIC" }, - { 25, 0, L"MUSIC_PLAY" }, - { 26, 1, L"MODE_SELECT" }, - { 27, 2, L"EDIT_MOTION" }, - { 28, 2, L"BAR_TIME_SET" }, - { 29, 1, L"SHADOWHEIGHT" }, - { 30, 2, L"EDIT_FACE" }, - { 31, 19, L"MOVE_CAMERA" }, - { 32, 0, L"PV_END" }, - { 33, 2, L"SHADOWPOS" }, - { 34, 2, L"NEAR_CLIP" }, - { 35, 1, L"CLOTH_WET" }, - { 36, 6, L"SCENE_FADE" }, // AC110 - { 37, 6, L"TONE_TRANS" }, // AC120 - { 38, 1, L"SATURATE" }, - { 39, 1, L"FADE_MODE" }, + { 0, 0, "END" }, + { 1, 1, "TIME" }, + { 2, 3, "MIKU_MOVE" }, + { 3, 1, "MIKU_ROT" }, + { 4, 1, "MIKU_DISP" }, + { 5, 1, "MIKU_SHADOW" }, + { 6, 7, "TARGET" }, + { 7, 3, "SET_MOTION" }, + { 8, 1, "SET_PLAYDATA" }, + { 9, 5, "EFFECT" }, + { 10, 2, "FADEIN_FIELD" }, + { 11, 1, "EFFECT_OFF" }, + { 12, 6, "SET_CAMERA" }, + { 13, 2, "DATA_CAMERA" }, + { 14, 1, "CHANGE_FIELD" }, + { 15, 1, "HIDE_FIELD" }, + { 16, 3, "MOVE_FIELD" }, + { 17, 2, "FADEOUT_FIELD" }, + { 18, 2, "EYE_ANIM" }, + { 19, 3, "MOUTH_ANIM" }, + { 20, 4, "HAND_ANIM" }, + { 21, 3, "LOOK_ANIM" }, + { 22, 3, "EXPRESSION" }, + { 23, 4, "LOOK_CAMERA" }, + { 24, 1, "LYRIC" }, + { 25, 0, "MUSIC_PLAY" }, + { 26, 1, "MODE_SELECT" }, + { 27, 2, "EDIT_MOTION" }, + { 28, 2, "BAR_TIME_SET" }, + { 29, 1, "SHADOWHEIGHT" }, + { 30, 2, "EDIT_FACE" }, + { 31, 19, "MOVE_CAMERA" }, + { 32, 0, "PV_END" }, + { 33, 2, "SHADOWPOS" }, + { 34, 2, "NEAR_CLIP" }, + { 35, 1, "CLOTH_WET" }, + { 36, 6, "SCENE_FADE" }, // AC110 + { 37, 6, "TONE_TRANS" }, // AC120 + { 38, 1, "SATURATE" }, + { 39, 1, "FADE_MODE" }, }; static const dsc_func_ac dsc_ac_func[] = { - { 0, 0, 0, L"END" }, - { 1, 1, 1, L"TIME" }, - { 2, 3, 4, L"MIKU_MOVE" }, - { 3, 1, 2, L"MIKU_ROT" }, - { 4, 1, 2, L"MIKU_DISP" }, - { 5, 1, 2, L"MIKU_SHADOW" }, - { 6, 7, 7, L"TARGET" }, - { 7, 3, 4, L"SET_MOTION" }, - { 8, 1, 2, L"SET_PLAYDATA" }, - { 9, 5, 6, L"EFFECT" }, - { 10, 2, 2, L"FADEIN_FIELD" }, - { 11, 1, 1, L"EFFECT_OFF" }, - { 12, 6, 6, L"SET_CAMERA" }, - { 13, 2, 2, L"DATA_CAMERA" }, - { 14, 1, 1, L"CHANGE_FIELD" }, - { 15, 1, 1, L"HIDE_FIELD" }, - { 16, 3, 3, L"MOVE_FIELD" }, - { 17, 2, 2, L"FADEOUT_FIELD" }, - { 18, 2, 3, L"EYE_ANIM" }, - { 19, 3, 5, L"MOUTH_ANIM" }, - { 20, 4, 5, L"HAND_ANIM" }, - { 21, 3, 4, L"LOOK_ANIM" }, - { 22, 3, 4, L"EXPRESSION" }, - { 23, 4, 5, L"LOOK_CAMERA" }, - { 24, 1, 2, L"LYRIC" }, - { 25, 0, 0, L"MUSIC_PLAY" }, - { 26, 1, 2, L"MODE_SELECT" }, - { 27, 2, 4, L"EDIT_MOTION" }, - { 28, 2, 2, L"BAR_TIME_SET" }, - { 29, 1, 2, L"SHADOWHEIGHT" }, - { 30, 2, 1, L"EDIT_FACE" }, - { 31, 19, 21, L"MOVE_CAMERA" }, - { 32, 0, 0, L"PV_END" }, - { 33, 2, 3, L"SHADOWPOS" }, - { 34, 2, 2, L"EDIT_LYRIC" }, - { 35, 5, 5, L"EDIT_TARGET" }, - { 36, 1, 1, L"EDIT_MOUTH" }, - { 37, 1, 1, L"SET_CHARA" }, - { 38, 7, 7, L"EDIT_MOVE" }, - { 39, 1, 1, L"EDIT_SHADOW" }, - { 40, 1, 1, L"EDIT_EYELID" }, - { 41, 2, 2, L"EDIT_EYE" }, - { 42, 1, 1, L"EDIT_ITEM" }, - { 43, 2, 2, L"EDIT_EFFECT" }, - { 44, 1, 1, L"EDIT_DISP" }, - { 45, 2, 2, L"EDIT_HAND_ANIM" }, - { 46, 3, 3, L"AIM" }, - { 47, 3, 3, L"HAND_ITEM" }, - { 48, 1, 1, L"EDIT_BLUSH" }, - { 49, 2, 2, L"NEAR_CLIP" }, - { 50, 1, 2, L"CLOTH_WET" }, - { 51, 3, 3, L"LIGHT_ROT" }, - { 52, 6, 6, L"SCENE_FADE" }, - { 53, 6, 6, L"TONE_TRANS" }, - { 54, 1, 1, L"SATURATE" }, - { 55, 1, 1, L"FADE_MODE" }, - { 56, 2, 2, L"AUTO_BLINK" }, - { 57, 3, 3, L"PARTS_DISP" }, - { 58, 1, 1, L"TARGET_FLYING_TIME" }, // AC210 - { 59, 2, 2, L"CHARA_SIZE" }, - { 60, 2, 2, L"CHARA_HEIGHT_ADJUST" }, - { 61, 4, 4, L"ITEM_ANIM" }, - { 62, 4, 4, L"CHARA_POS_ADJUST" }, - { 63, 1, 1, L"SCENE_ROT" }, - { 64, 2, 2, L"EDIT_MOT_SMOOTH_LEN" }, // AC500 - { 65, 1, 1, L"PV_BRANCH_MODE" }, // AC510 - { 66, 2, 2, L"DATA_CAMERA_START" }, - { 67, 1, 1, L"MOVIE_PLAY" }, - { 68, 1, 1, L"MOVIE_DISP" }, - { 69, 3, 3, L"WIND" }, - { 70, 3, 3, L"OSAGE_STEP" }, - { 71, 3, 3, L"OSAGE_MV_CCL" }, - { 72, 2, 2, L"CHARA_COLOR" }, - { 73, 1, 1, L"SE_EFFECT" }, - { 74, 9, 9, L"EDIT_MOVE_XYZ" }, - { 75, 3, 3, L"EDIT_EYELID_ANIM" }, - { 76, 2, 2, L"EDIT_INSTRUMENT_ITEM" }, - { 77, 4, 4, L"EDIT_MOTION_LOOP" }, - { 78, 2, 2, L"EDIT_EXPRESSION" }, - { 79, 3, 3, L"EDIT_EYE_ANIM" }, - { 80, 2, 2, L"EDIT_MOUTH_ANIM" }, - { 81, 24, 24, L"EDIT_CAMERA" }, - { 82, 1, 1, L"EDIT_MODE_SELECT" }, - { 83, 2, 2, L"PV_END_FADEOUT" }, - { 84, 1, 1, L"TARGET_FLAG" }, - { 85, 3, 3, L"ITEM_ANIM_ATTACH" }, - { 86, 1, 1, L"SHADOW_RANGE" }, - { 87, 3, 3, L"HAND_SCALE" }, // AFT101 - { 88, 4, 4, L"LIGHT_POS" }, - { 89, 1, 1, L"FACE_TYPE" }, // AFT200 - { 90, 2, 2, L"SHADOW_CAST" }, // AFT300 - { 91, 6, 6, L"EDIT_MOTION_F" }, // AFT310 - { 92, 3, 3, L"FOG" }, // AFT410 - { 93, 2, 2, L"BLOOM" }, - { 94, 3, 3, L"COLOR_COLLE" }, - { 95, 3, 3, L"DOF" }, - { 96, 4, 4, L"CHARA_ALPHA" }, - { 97, 1, 1, L"AOTO_CAP" }, - { 98, 1, 1, L"MAN_CAP" }, - { 99, 3, 3, L"TOON" }, - { 100, 3, 3, L"SHIMMER" }, - { 101, 4, 4, L"ITEM_ALPHA" }, - { 102, 1, 1, L"MOVIE_CUT_CHG" }, - { 103, 3, 3, L"CHARA_LIGHT" }, - { 104, 3, 3, L"STAGE_LIGHT" }, - { 105, 8, 8, L"AGEAGE_CTRL" }, // AFT701 - { 106, 2, 2, L"PSE" }, // FT + { 0, 0, 0, "END" }, + { 1, 1, 1, "TIME" }, + { 2, 3, 4, "MIKU_MOVE" }, + { 3, 1, 2, "MIKU_ROT" }, + { 4, 1, 2, "MIKU_DISP" }, + { 5, 1, 2, "MIKU_SHADOW" }, + { 6, 7, 7, "TARGET" }, + { 7, 3, 4, "SET_MOTION" }, + { 8, 1, 2, "SET_PLAYDATA" }, + { 9, 5, 6, "EFFECT" }, + { 10, 2, 2, "FADEIN_FIELD" }, + { 11, 1, 1, "EFFECT_OFF" }, + { 12, 6, 6, "SET_CAMERA" }, + { 13, 2, 2, "DATA_CAMERA" }, + { 14, 1, 1, "CHANGE_FIELD" }, + { 15, 1, 1, "HIDE_FIELD" }, + { 16, 3, 3, "MOVE_FIELD" }, + { 17, 2, 2, "FADEOUT_FIELD" }, + { 18, 2, 3, "EYE_ANIM" }, + { 19, 3, 5, "MOUTH_ANIM" }, + { 20, 4, 5, "HAND_ANIM" }, + { 21, 3, 4, "LOOK_ANIM" }, + { 22, 3, 4, "EXPRESSION" }, + { 23, 4, 5, "LOOK_CAMERA" }, + { 24, 1, 2, "LYRIC" }, + { 25, 0, 0, "MUSIC_PLAY" }, + { 26, 1, 2, "MODE_SELECT" }, + { 27, 2, 4, "EDIT_MOTION" }, + { 28, 2, 2, "BAR_TIME_SET" }, + { 29, 1, 2, "SHADOWHEIGHT" }, + { 30, 2, 1, "EDIT_FACE" }, + { 31, 19, 21, "MOVE_CAMERA" }, + { 32, 0, 0, "PV_END" }, + { 33, 2, 3, "SHADOWPOS" }, + { 34, 2, 2, "EDIT_LYRIC" }, + { 35, 5, 5, "EDIT_TARGET" }, + { 36, 1, 1, "EDIT_MOUTH" }, + { 37, 1, 1, "SET_CHARA" }, + { 38, 7, 7, "EDIT_MOVE" }, + { 39, 1, 1, "EDIT_SHADOW" }, + { 40, 1, 1, "EDIT_EYELID" }, + { 41, 2, 2, "EDIT_EYE" }, + { 42, 1, 1, "EDIT_ITEM" }, + { 43, 2, 2, "EDIT_EFFECT" }, + { 44, 1, 1, "EDIT_DISP" }, + { 45, 2, 2, "EDIT_HAND_ANIM" }, + { 46, 3, 3, "AIM" }, + { 47, 3, 3, "HAND_ITEM" }, + { 48, 1, 1, "EDIT_BLUSH" }, + { 49, 2, 2, "NEAR_CLIP" }, + { 50, 1, 2, "CLOTH_WET" }, + { 51, 3, 3, "LIGHT_ROT" }, + { 52, 6, 6, "SCENE_FADE" }, + { 53, 6, 6, "TONE_TRANS" }, + { 54, 1, 1, "SATURATE" }, + { 55, 1, 1, "FADE_MODE" }, + { 56, 2, 2, "AUTO_BLINK" }, + { 57, 3, 3, "PARTS_DISP" }, + { 58, 1, 1, "TARGET_FLYING_TIME" }, // AC210 + { 59, 2, 2, "CHARA_SIZE" }, + { 60, 2, 2, "CHARA_HEIGHT_ADJUST" }, + { 61, 4, 4, "ITEM_ANIM" }, + { 62, 4, 4, "CHARA_POS_ADJUST" }, + { 63, 1, 1, "SCENE_ROT" }, + { 64, 2, 2, "EDIT_MOT_SMOOTH_LEN" }, // AC500 + { 65, 1, 1, "PV_BRANCH_MODE" }, // AC510 + { 66, 2, 2, "DATA_CAMERA_START" }, + { 67, 1, 1, "MOVIE_PLAY" }, + { 68, 1, 1, "MOVIE_DISP" }, + { 69, 3, 3, "WIND" }, + { 70, 3, 3, "OSAGE_STEP" }, + { 71, 3, 3, "OSAGE_MV_CC" }, + { 72, 2, 2, "CHARA_COLOR" }, + { 73, 1, 1, "SE_EFFECT" }, + { 74, 9, 9, "EDIT_MOVE_XYZ" }, + { 75, 3, 3, "EDIT_EYELID_ANIM" }, + { 76, 2, 2, "EDIT_INSTRUMENT_ITEM" }, + { 77, 4, 4, "EDIT_MOTION_LOOP" }, + { 78, 2, 2, "EDIT_EXPRESSION" }, + { 79, 3, 3, "EDIT_EYE_ANIM" }, + { 80, 2, 2, "EDIT_MOUTH_ANIM" }, + { 81, 24, 24, "EDIT_CAMERA" }, + { 82, 1, 1, "EDIT_MODE_SELECT" }, + { 83, 2, 2, "PV_END_FADEOUT" }, + { 84, 1, 1, "TARGET_FLAG" }, + { 85, 3, 3, "ITEM_ANIM_ATTACH" }, + { 86, 1, 1, "SHADOW_RANGE" }, + { 87, 3, 3, "HAND_SCALE" }, // AFT101 + { 88, 4, 4, "LIGHT_POS" }, + { 89, 1, 1, "FACE_TYPE" }, // AFT200 + { 90, 2, 2, "SHADOW_CAST" }, // AFT300 + { 91, 6, 6, "EDIT_MOTION_F" }, // AFT310 + { 92, 3, 3, "FOG" }, // AFT410 + { 93, 2, 2, "BLOOM" }, + { 94, 3, 3, "COLOR_COLLE" }, + { 95, 3, 3, "DOF" }, + { 96, 4, 4, "CHARA_ALPHA" }, + { 97, 1, 1, "AOTO_CAP" }, + { 98, 1, 1, "MAN_CAP" }, + { 99, 3, 3, "TOON" }, + { 100, 3, 3, "SHIMMER" }, + { 101, 4, 4, "ITEM_ALPHA" }, + { 102, 1, 1, "MOVIE_CUT_CHG" }, + { 103, 3, 3, "CHARA_LIGHT" }, + { 104, 3, 3, "STAGE_LIGHT" }, + { 105, 8, 8, "AGEAGE_CTR" }, // AFT701 + { 106, 2, 2, "PSE" }, // FT }; static const dsc_func_ac dsc_f_func[] = { - { 0, 0, 0, L"END" }, - { 1, 1, 1, L"TIME" }, - { 2, 3, 4, L"MIKU_MOVE" }, - { 3, 1, 2, L"MIKU_ROT" }, - { 4, 1, 2, L"MIKU_DISP" }, - { 5, 1, 2, L"MIKU_SHADOW" }, - { 6, 7, 11, L"TARGET" }, - { 7, 3, 4, L"SET_MOTION" }, - { 8, 1, 2, L"SET_PLAYDATA" }, - { 9, 5, 6, L"EFFECT" }, - { 10, 2, 2, L"FADEIN_FIELD" }, - { 11, 1, 1, L"EFFECT_OFF" }, - { 12, 6, 6, L"SET_CAMERA" }, - { 13, 2, 2, L"DATA_CAMERA" }, - { 14, 1, 1, L"CHANGE_FIELD" }, - { 15, 1, 1, L"HIDE_FIELD" }, - { 16, 3, 3, L"MOVE_FIELD" }, - { 17, 2, 2, L"FADEOUT_FIELD" }, - { 18, 2, 3, L"EYE_ANIM" }, - { 19, 3, 5, L"MOUTH_ANIM" }, - { 20, 4, 5, L"HAND_ANIM" }, - { 21, 3, 4, L"LOOK_ANIM" }, - { 22, 3, 4, L"EXPRESSION" }, - { 23, 4, 5, L"LOOK_CAMERA" }, - { 24, 1, 2, L"LYRIC" }, - { 25, 0, 0, L"MUSIC_PLAY" }, - { 26, 1, 2, L"MODE_SELECT" }, - { 27, 2, 4, L"EDIT_MOTION" }, - { 28, 2, 2, L"BAR_TIME_SET" }, - { 29, 1, 2, L"SHADOWHEIGHT" }, - { 30, 2, 1, L"EDIT_FACE" }, - { 31, 19, 21, L"MOVE_CAMERA" }, - { 32, 0, 0, L"PV_END" }, - { 33, 2, 3, L"SHADOWPOS" }, - { 34, 2, 2, L"EDIT_LYRIC" }, - { 35, 5, 5, L"EDIT_TARGET" }, - { 36, 1, 1, L"EDIT_MOUTH" }, - { 37, 1, 1, L"SET_CHARA" }, - { 38, 7, 7, L"EDIT_MOVE" }, - { 39, 1, 1, L"EDIT_SHADOW" }, - { 40, 1, 1, L"EDIT_EYELID" }, - { 41, 2, 2, L"EDIT_EYE" }, - { 42, 1, 1, L"EDIT_ITEM" }, - { 43, 2, 2, L"EDIT_EFFECT" }, - { 44, 1, 1, L"EDIT_DISP" }, - { 45, 2, 2, L"EDIT_HAND_ANIM" }, - { 46, 3, 3, L"AIM" }, - { 47, 3, 3, L"HAND_ITEM" }, - { 48, 1, 1, L"EDIT_BLUSH" }, - { 49, 2, 2, L"NEAR_CLIP" }, - { 50, 1, 2, L"CLOTH_WET" }, - { 51, 3, 3, L"LIGHT_ROT" }, - { 52, 6, 6, L"SCENE_FADE" }, - { 53, 6, 6, L"TONE_TRANS" }, - { 54, 1, 1, L"SATURATE" }, - { 55, 1, 1, L"FADE_MODE" }, - { 56, 2, 2, L"AUTO_BLINK" }, - { 57, 3, 3, L"PARTS_DISP" }, - { 58, 1, 1, L"TARGET_FLYING_TIME" }, - { 59, 2, 2, L"CHARA_SIZE" }, - { 60, 2, 2, L"CHARA_HEIGHT_ADJUST" }, - { 61, 4, 4, L"ITEM_ANIM" }, - { 62, 4, 4, L"CHARA_POS_ADJUST" }, - { 63, 1, 1, L"SCENE_ROT" }, - { 64, 2, 2, L"EDIT_MOT_SMOOTH_LEN" }, - { 65, 1, 1, L"PV_BRANCH_MODE" }, - { 66, 2, 2, L"DATA_CAMERA_START" }, - { 67, 1, 1, L"MOVIE_PLAY" }, - { 68, 1, 1, L"MOVIE_DISP" }, - { 69, 3, 3, L"WIND" }, - { 70, 3, 3, L"OSAGE_STEP" }, - { 71, 3, 3, L"OSAGE_MV_CCL" }, - { 72, 2, 2, L"CHARA_COLOR" }, - { 73, 1, 1, L"SE_EFFECT" }, - { 74, 9, 9, L"EDIT_MOVE_XYZ" }, - { 75, 3, 3, L"EDIT_EYELID_ANIM" }, - { 76, 2, 2, L"EDIT_INSTRUMENT_ITEM" }, - { 77, 4, 4, L"EDIT_MOTION_LOOP" }, - { 78, 2, 2, L"EDIT_EXPRESSION" }, - { 79, 3, 3, L"EDIT_EYE_ANIM" }, - { 80, 2, 2, L"EDIT_MOUTH_ANIM" }, - { 81, 24, 24, L"EDIT_CAMERA" }, - { 82, 1, 1, L"EDIT_MODE_SELECT" }, - { 83, 2, 2, L"PV_END_FADEOUT" }, + { 0, 0, 0, "END" }, + { 1, 1, 1, "TIME" }, + { 2, 3, 4, "MIKU_MOVE" }, + { 3, 1, 2, "MIKU_ROT" }, + { 4, 1, 2, "MIKU_DISP" }, + { 5, 1, 2, "MIKU_SHADOW" }, + { 6, 7, 11, "TARGET" }, + { 7, 3, 4, "SET_MOTION" }, + { 8, 1, 2, "SET_PLAYDATA" }, + { 9, 5, 6, "EFFECT" }, + { 10, 2, 2, "FADEIN_FIELD" }, + { 11, 1, 1, "EFFECT_OFF" }, + { 12, 6, 6, "SET_CAMERA" }, + { 13, 2, 2, "DATA_CAMERA" }, + { 14, 1, 1, "CHANGE_FIELD" }, + { 15, 1, 1, "HIDE_FIELD" }, + { 16, 3, 3, "MOVE_FIELD" }, + { 17, 2, 2, "FADEOUT_FIELD" }, + { 18, 2, 3, "EYE_ANIM" }, + { 19, 3, 5, "MOUTH_ANIM" }, + { 20, 4, 5, "HAND_ANIM" }, + { 21, 3, 4, "LOOK_ANIM" }, + { 22, 3, 4, "EXPRESSION" }, + { 23, 4, 5, "LOOK_CAMERA" }, + { 24, 1, 2, "LYRIC" }, + { 25, 0, 0, "MUSIC_PLAY" }, + { 26, 1, 2, "MODE_SELECT" }, + { 27, 2, 4, "EDIT_MOTION" }, + { 28, 2, 2, "BAR_TIME_SET" }, + { 29, 1, 2, "SHADOWHEIGHT" }, + { 30, 2, 1, "EDIT_FACE" }, + { 31, 19, 21, "MOVE_CAMERA" }, + { 32, 0, 0, "PV_END" }, + { 33, 2, 3, "SHADOWPOS" }, + { 34, 2, 2, "EDIT_LYRIC" }, + { 35, 5, 5, "EDIT_TARGET" }, + { 36, 1, 1, "EDIT_MOUTH" }, + { 37, 1, 1, "SET_CHARA" }, + { 38, 7, 7, "EDIT_MOVE" }, + { 39, 1, 1, "EDIT_SHADOW" }, + { 40, 1, 1, "EDIT_EYELID" }, + { 41, 2, 2, "EDIT_EYE" }, + { 42, 1, 1, "EDIT_ITEM" }, + { 43, 2, 2, "EDIT_EFFECT" }, + { 44, 1, 1, "EDIT_DISP" }, + { 45, 2, 2, "EDIT_HAND_ANIM" }, + { 46, 3, 3, "AIM" }, + { 47, 3, 3, "HAND_ITEM" }, + { 48, 1, 1, "EDIT_BLUSH" }, + { 49, 2, 2, "NEAR_CLIP" }, + { 50, 1, 2, "CLOTH_WET" }, + { 51, 3, 3, "LIGHT_ROT" }, + { 52, 6, 6, "SCENE_FADE" }, + { 53, 6, 6, "TONE_TRANS" }, + { 54, 1, 1, "SATURATE" }, + { 55, 1, 1, "FADE_MODE" }, + { 56, 2, 2, "AUTO_BLINK" }, + { 57, 3, 3, "PARTS_DISP" }, + { 58, 1, 1, "TARGET_FLYING_TIME" }, + { 59, 2, 2, "CHARA_SIZE" }, + { 60, 2, 2, "CHARA_HEIGHT_ADJUST" }, + { 61, 4, 4, "ITEM_ANIM" }, + { 62, 4, 4, "CHARA_POS_ADJUST" }, + { 63, 1, 1, "SCENE_ROT" }, + { 64, 2, 2, "EDIT_MOT_SMOOTH_LEN" }, + { 65, 1, 1, "PV_BRANCH_MODE" }, + { 66, 2, 2, "DATA_CAMERA_START" }, + { 67, 1, 1, "MOVIE_PLAY" }, + { 68, 1, 1, "MOVIE_DISP" }, + { 69, 3, 3, "WIND" }, + { 70, 3, 3, "OSAGE_STEP" }, + { 71, 3, 3, "OSAGE_MV_CC" }, + { 72, 2, 2, "CHARA_COLOR" }, + { 73, 1, 1, "SE_EFFECT" }, + { 74, 9, 9, "EDIT_MOVE_XYZ" }, + { 75, 3, 3, "EDIT_EYELID_ANIM" }, + { 76, 2, 2, "EDIT_INSTRUMENT_ITEM" }, + { 77, 4, 4, "EDIT_MOTION_LOOP" }, + { 78, 2, 2, "EDIT_EXPRESSION" }, + { 79, 3, 3, "EDIT_EYE_ANIM" }, + { 80, 2, 2, "EDIT_MOUTH_ANIM" }, + { 81, 24, 24, "EDIT_CAMERA" }, + { 82, 1, 1, "EDIT_MODE_SELECT" }, + { 83, 2, 2, "PV_END_FADEOUT" }, }; static const dsc_func dsc_f2_func[] = { - { 0, 0, L"END" }, - { 1, 1, L"TIME" }, - { 2, 4, L"MIKU_MOVE" }, - { 3, 2, L"MIKU_ROT" }, - { 4, 2, L"MIKU_DISP" }, - { 5, 2, L"MIKU_SHADOW" }, - { 6, 12, L"TARGET" }, - { 7, 4, L"SET_MOTION" }, - { 8, 2, L"SET_PLAYDATA" }, - { 9, 6, L"EFFECT" }, - { 10, 2, L"FADEIN_FIELD" }, - { 11, 1, L"EFFECT_OFF" }, - { 12, 6, L"SET_CAMERA" }, - { 13, 2, L"DATA_CAMERA" }, - { 14, 2, L"CHANGE_FIELD" }, - { 15, 1, L"HIDE_FIELD" }, - { 16, 3, L"MOVE_FIELD" }, - { 17, 2, L"FADEOUT_FIELD" }, - { 18, 3, L"EYE_ANIM" }, - { 19, 5, L"MOUTH_ANIM" }, - { 20, 5, L"HAND_ANIM" }, - { 21, 4, L"LOOK_ANIM" }, - { 22, 4, L"EXPRESSION" }, - { 23, 5, L"LOOK_CAMERA" }, - { 24, 2, L"LYRIC" }, - { 25, 0, L"MUSIC_PLAY" }, - { 26, 2, L"MODE_SELECT" }, - { 27, 4, L"EDIT_MOTION" }, - { 28, 2, L"BAR_TIME_SET" }, - { 29, 2, L"SHADOWHEIGHT" }, - { 30, 1, L"EDIT_FACE" }, - { 31, 21, L"MOVE_CAMERA" }, - { 32, 0, L"PV_END" }, - { 33, 3, L"SHADOWPOS" }, - { 34, 2, L"EDIT_LYRIC" }, - { 35, 5, L"EDIT_TARGET" }, - { 36, 1, L"EDIT_MOUTH" }, - { 37, 1, L"SET_CHARA" }, - { 38, 7, L"EDIT_MOVE" }, - { 39, 1, L"EDIT_SHADOW" }, - { 40, 1, L"EDIT_EYELID" }, - { 41, 2, L"EDIT_EYE" }, - { 42, 1, L"EDIT_ITEM" }, - { 43, 2, L"EDIT_EFFECT" }, - { 44, 1, L"EDIT_DISP" }, - { 45, 2, L"EDIT_HAND_ANIM" }, - { 46, 3, L"AIM" }, - { 47, 3, L"HAND_ITEM" }, - { 48, 1, L"EDIT_BLUSH" }, - { 49, 2, L"NEAR_CLIP" }, - { 50, 2, L"CLOTH_WET" }, - { 51, 3, L"LIGHT_ROT" }, - { 52, 6, L"SCENE_FADE" }, - { 53, 6, L"TONE_TRANS" }, - { 54, 1, L"SATURATE" }, - { 55, 1, L"FADE_MODE" }, - { 56, 2, L"AUTO_BLINK" }, - { 57, 3, L"PARTS_DISP" }, - { 58, 1, L"TARGET_FLYING_TIME" }, - { 59, 2, L"CHARA_SIZE" }, - { 60, 2, L"CHARA_HEIGHT_ADJUST" }, - { 61, 4, L"ITEM_ANIM" }, - { 62, 4, L"CHARA_POS_ADJUST" }, - { 63, 1, L"SCENE_ROT" }, - { 64, 2, L"EDIT_MOT_SMOOTH_LEN" }, - { 65, 1, L"PV_BRANCH_MODE" }, - { 66, 2, L"DATA_CAMERA_START" }, - { 67, 1, L"MOVIE_PLAY" }, - { 68, 1, L"MOVIE_DISP" }, - { 69, 3, L"WIND" }, - { 70, 3, L"OSAGE_STEP" }, - { 71, 3, L"OSAGE_MV_CCL" }, - { 72, 2, L"CHARA_COLOR" }, - { 73, 1, L"SE_EFFECT" }, - { 74, 9, L"EDIT_MOVE_XYZ" }, - { 75, 3, L"EDIT_EYELID_ANIM" }, - { 76, 2, L"EDIT_INSTRUMENT_ITEM" }, - { 77, 4, L"EDIT_MOTION_LOOP" }, - { 78, 2, L"EDIT_EXPRESSION" }, - { 79, 3, L"EDIT_EYE_ANIM" }, - { 80, 2, L"EDIT_MOUTH_ANIM" }, - { 81, 22, L"EDIT_CAMERA" }, - { 82, 1, L"EDIT_MODE_SELECT" }, - { 83, 2, L"PV_END_FADEOUT" }, - { 84, 1, L"RESERVE" }, - { 85, 6, L"RESERVE" }, - { 86, 1, L"RESERVE" }, - { 87, 9, L"RESERVE" }, - { 88, 2, L"PV_AUTH_LIGHT_PRIORITY" }, - { 89, 3, L"PV_CHARA_LIGHT" }, - { 90, 3, L"PV_STAGE_LIGHT" }, - { 91, 11, L"TARGET_EFFECT" }, - { 92, 3, L"FOG" }, - { 93, 2, L"BLOOM" }, - { 94, 3, L"COLOR_CORRECTION" }, - { 95, 3, L"DOF" }, - { 96, 4, L"CHARA_ALPHA" }, - { 97, 1, L"AUTO_CAPTURE_BEGIN" }, - { 98, 1, L"MANUAL_CAPTURE" }, - { 99, 3, L"TOON_EDGE" }, - { 100, 3, L"SHIMMER" }, - { 101, 4, L"ITEM_ALPHA" }, - { 102, 1, L"MOVIE_CUT" }, - { 103, 1, L"CROSSFADE" }, - { 104, 1, L"SUBFRAMERENDER" }, - { 105, 36, L"EVENT_JUDGE" }, - { 106, 2, L"TOON\uFF3FEDGE" }, - { 107, 2, L"FOG_ENABLE" }, - { 108, 112, L"EDIT_CAMERA_BOX" }, - { 109, 1, L"EDIT_STAGE_PARAM" }, - { 110, 1, L"EDIT_CHANGE_FIELD" }, + { 0, 0, "END" }, + { 1, 1, "TIME" }, + { 2, 4, "MIKU_MOVE" }, + { 3, 2, "MIKU_ROT" }, + { 4, 2, "MIKU_DISP" }, + { 5, 2, "MIKU_SHADOW" }, + { 6, 12, "TARGET" }, + { 7, 4, "SET_MOTION" }, + { 8, 2, "SET_PLAYDATA" }, + { 9, 6, "EFFECT" }, + { 10, 2, "FADEIN_FIELD" }, + { 11, 1, "EFFECT_OFF" }, + { 12, 6, "SET_CAMERA" }, + { 13, 2, "DATA_CAMERA" }, + { 14, 2, "CHANGE_FIELD" }, + { 15, 1, "HIDE_FIELD" }, + { 16, 3, "MOVE_FIELD" }, + { 17, 2, "FADEOUT_FIELD" }, + { 18, 3, "EYE_ANIM" }, + { 19, 5, "MOUTH_ANIM" }, + { 20, 5, "HAND_ANIM" }, + { 21, 4, "LOOK_ANIM" }, + { 22, 4, "EXPRESSION" }, + { 23, 5, "LOOK_CAMERA" }, + { 24, 2, "LYRIC" }, + { 25, 0, "MUSIC_PLAY" }, + { 26, 2, "MODE_SELECT" }, + { 27, 4, "EDIT_MOTION" }, + { 28, 2, "BAR_TIME_SET" }, + { 29, 2, "SHADOWHEIGHT" }, + { 30, 1, "EDIT_FACE" }, + { 31, 21, "MOVE_CAMERA" }, + { 32, 0, "PV_END" }, + { 33, 3, "SHADOWPOS" }, + { 34, 2, "EDIT_LYRIC" }, + { 35, 5, "EDIT_TARGET" }, + { 36, 1, "EDIT_MOUTH" }, + { 37, 1, "SET_CHARA" }, + { 38, 7, "EDIT_MOVE" }, + { 39, 1, "EDIT_SHADOW" }, + { 40, 1, "EDIT_EYELID" }, + { 41, 2, "EDIT_EYE" }, + { 42, 1, "EDIT_ITEM" }, + { 43, 2, "EDIT_EFFECT" }, + { 44, 1, "EDIT_DISP" }, + { 45, 2, "EDIT_HAND_ANIM" }, + { 46, 3, "AIM" }, + { 47, 3, "HAND_ITEM" }, + { 48, 1, "EDIT_BLUSH" }, + { 49, 2, "NEAR_CLIP" }, + { 50, 2, "CLOTH_WET" }, + { 51, 3, "LIGHT_ROT" }, + { 52, 6, "SCENE_FADE" }, + { 53, 6, "TONE_TRANS" }, + { 54, 1, "SATURATE" }, + { 55, 1, "FADE_MODE" }, + { 56, 2, "AUTO_BLINK" }, + { 57, 3, "PARTS_DISP" }, + { 58, 1, "TARGET_FLYING_TIME" }, + { 59, 2, "CHARA_SIZE" }, + { 60, 2, "CHARA_HEIGHT_ADJUST" }, + { 61, 4, "ITEM_ANIM" }, + { 62, 4, "CHARA_POS_ADJUST" }, + { 63, 1, "SCENE_ROT" }, + { 64, 2, "EDIT_MOT_SMOOTH_LEN" }, + { 65, 1, "PV_BRANCH_MODE" }, + { 66, 2, "DATA_CAMERA_START" }, + { 67, 1, "MOVIE_PLAY" }, + { 68, 1, "MOVIE_DISP" }, + { 69, 3, "WIND" }, + { 70, 3, "OSAGE_STEP" }, + { 71, 3, "OSAGE_MV_CC" }, + { 72, 2, "CHARA_COLOR" }, + { 73, 1, "SE_EFFECT" }, + { 74, 9, "EDIT_MOVE_XYZ" }, + { 75, 3, "EDIT_EYELID_ANIM" }, + { 76, 2, "EDIT_INSTRUMENT_ITEM" }, + { 77, 4, "EDIT_MOTION_LOOP" }, + { 78, 2, "EDIT_EXPRESSION" }, + { 79, 3, "EDIT_EYE_ANIM" }, + { 80, 2, "EDIT_MOUTH_ANIM" }, + { 81, 22, "EDIT_CAMERA" }, + { 82, 1, "EDIT_MODE_SELECT" }, + { 83, 2, "PV_END_FADEOUT" }, + { 84, 1, "RESERVE" }, + { 85, 6, "RESERVE" }, + { 86, 1, "RESERVE" }, + { 87, 9, "RESERVE" }, + { 88, 2, "PV_AUTH_LIGHT_PRIORITY" }, + { 89, 3, "PV_CHARA_LIGHT" }, + { 90, 3, "PV_STAGE_LIGHT" }, + { 91, 11, "TARGET_EFFECT" }, + { 92, 3, "FOG" }, + { 93, 2, "BLOOM" }, + { 94, 3, "COLOR_CORRECTION" }, + { 95, 3, "DOF" }, + { 96, 4, "CHARA_ALPHA" }, + { 97, 1, "AUTO_CAPTURE_BEGIN" }, + { 98, 1, "MANUAL_CAPTURE" }, + { 99, 3, "TOON_EDGE" }, + { 100, 3, "SHIMMER" }, + { 101, 4, "ITEM_ALPHA" }, + { 102, 1, "MOVIE_CUT" }, + { 103, 1, "CROSSFADE" }, + { 104, 1, "SUBFRAMERENDER" }, + { 105, 36, "EVENT_JUDGE" }, + { 106, 2, "TOON_EDGE" }, + { 107, 2, "FOG_ENABLE" }, + { 108, 112, "EDIT_CAMERA_BOX" }, + { 109, 1, "EDIT_STAGE_PARAM" }, + { 110, 1, "EDIT_CHANGE_FIELD" }, }; static const dsc_func dsc_x_func[] = { - { 0, 0, L"END" }, - { 1, 1, L"TIME" }, - { 2, 4, L"MIKU_MOVE" }, - { 3, 2, L"MIKU_ROT" }, - { 4, 2, L"MIKU_DISP" }, - { 5, 2, L"MIKU_SHADOW" }, - { 6, 12, L"TARGET" }, - { 7, 4, L"SET_MOTION" }, - { 8, 2, L"SET_PLAYDATA" }, - { 9, 6, L"EFFECT" }, - { 10, 2, L"FADEIN_FIELD" }, - { 11, 1, L"EFFECT_OFF" }, - { 12, 6, L"SET_CAMERA" }, - { 13, 2, L"DATA_CAMERA" }, - { 14, 2, L"CHANGE_FIELD" }, - { 15, 1, L"HIDE_FIELD" }, - { 16, 3, L"MOVE_FIELD" }, - { 17, 2, L"FADEOUT_FIELD" }, - { 18, 3, L"EYE_ANIM" }, - { 19, 5, L"MOUTH_ANIM" }, - { 20, 5, L"HAND_ANIM" }, - { 21, 4, L"LOOK_ANIM" }, - { 22, 4, L"EXPRESSION" }, - { 23, 5, L"LOOK_CAMERA" }, - { 24, 2, L"LYRIC" }, - { 25, 0, L"MUSIC_PLAY" }, - { 26, 2, L"MODE_SELECT" }, - { 27, 4, L"EDIT_MOTION" }, - { 28, 2, L"BAR_TIME_SET" }, - { 29, 2, L"SHADOWHEIGHT" }, - { 30, 1, L"EDIT_FACE" }, - { 31, 21, L"DUMMY" }, - { 32, 0, L"PV_END" }, - { 33, 3, L"SHADOWPOS" }, - { 34, 2, L"EDIT_LYRIC" }, - { 35, 5, L"EDIT_TARGET" }, - { 36, 1, L"EDIT_MOUTH" }, - { 37, 1, L"SET_CHARA" }, - { 38, 7, L"EDIT_MOVE" }, - { 39, 1, L"EDIT_SHADOW" }, - { 40, 1, L"EDIT_EYELID" }, - { 41, 2, L"EDIT_EYE" }, - { 42, 1, L"EDIT_ITEM" }, - { 43, 2, L"EDIT_EFFECT" }, - { 44, 1, L"EDIT_DISP" }, - { 45, 2, L"EDIT_HAND_ANIM" }, - { 46, 3, L"AIM" }, - { 47, 3, L"HAND_ITEM" }, - { 48, 1, L"EDIT_BLUSH" }, - { 49, 2, L"NEAR_CLIP" }, - { 50, 2, L"CLOTH_WET" }, - { 51, 3, L"LIGHT_ROT" }, - { 52, 6, L"SCENE_FADE" }, - { 53, 6, L"TONE_TRANS" }, - { 54, 1, L"SATURATE" }, - { 55, 1, L"FADE_MODE" }, - { 56, 2, L"AUTO_BLINK" }, - { 57, 3, L"PARTS_DISP" }, - { 58, 1, L"TARGET_FLYING_TIME" }, - { 59, 2, L"CHARA_SIZE" }, - { 60, 2, L"CHARA_HEIGHT_ADJUST" }, - { 61, 4, L"ITEM_ANIM" }, - { 62, 4, L"CHARA_POS_ADJUST" }, - { 63, 1, L"SCENE_ROT" }, - { 64, 2, L"EDIT_MOT_SMOOTH_LEN" }, - { 65, 1, L"PV_BRANCH_MODE" }, - { 66, 2, L"DATA_CAMERA_START" }, - { 67, 1, L"MOVIE_PLAY" }, - { 68, 1, L"MOVIE_DISP" }, - { 69, 3, L"WIND" }, - { 70, 3, L"OSAGE_STEP" }, - { 71, 3, L"OSAGE_MV_CCL" }, - { 72, 2, L"CHARA_COLOR" }, - { 73, 1, L"SE_EFFECT" }, - { 74, 2, L"CHARA_SHADOW_QUALITY" }, - { 75, 2, L"STAGE_SHADOW_QUALITY" }, - { 76, 2, L"COMMON_LIGHT" }, - { 77, 2, L"TONE_MAP" }, - { 78, 2, L"IBL_COLOR" }, - { 79, 2, L"REFLECTION" }, - { 80, 3, L"CHROMATIC_ABERRATION" }, - { 81, 2, L"STAGE_SHADOW" }, - { 82, 2, L"REFLECTION_QUALITY" }, - { 83, 2, L"PV_END_FADEOUT" }, - { 84, 1, L"CREDIT_TITLE" }, - { 85, 1, L"BAR_POINT" }, - { 86, 1, L"BEAT_POINT" }, - { 87, 0, L"RESERVE" }, - { 88, 2, L"PV_AUTH_LIGHT_PRIORITY" }, - { 89, 3, L"PV_CHARA_LIGHT" }, - { 90, 3, L"PV_STAGE_LIGHT" }, - { 91, 11, L"TARGET_EFFECT" }, - { 92, 3, L"FOG" }, - { 93, 2, L"BLOOM" }, - { 94, 3, L"COLOR_CORRECTION" }, - { 95, 3, L"DOF" }, - { 96, 4, L"CHARA_ALPHA" }, - { 97, 1, L"AUTO_CAPTURE_BEGIN" }, - { 98, 1, L"MANUAL_CAPTURE" }, - { 99, 3, L"TOON_EDGE" }, - { 100, 3, L"SHIMMER" }, - { 101, 4, L"ITEM_ALPHA" }, - { 102, 1, L"MOVIE_CUT" }, - { 103, 112, L"EDIT_CAMERA_BOX" }, - { 104, 1, L"EDIT_STAGE_PARAM" }, - { 105, 1, L"EDIT_CHANGE_FIELD" }, - { 106, 7, L"MIKUDAYO_ADJUST" }, - { 107, 2, L"LYRIC_2" }, - { 108, 2, L"LYRIC_READ" }, - { 109, 2, L"LYRIC_READ_2" }, - { 110, 5, L"ANNOTATION" }, - { 111, 2, L"STAGE_EFFECT" }, - { 112, 3, L"SONG_EFFECT" }, - { 113, 3, L"SONG_EFFECT_ATTACH" }, - { 114, 2, L"LIGHT_AUTH" }, - { 115, 2, L"FADE" }, - { 116, 2, L"SET_STAGE_EFFECT_ENV" }, - { 117, 2, L"RESERVE" }, - { 118, 2, L"COMMON_EFFECT_AET_FRONT" }, - { 119, 2, L"COMMON_EFFECT_AET_FRONT_LOW" }, - { 120, 2, L"COMMON_EFFECT_PARTICLE" }, - { 121, 3, L"SONG_EFFECT_ALPHA_SORT" }, - { 122, 5, L"LOOK_CAMERA_FACE_LIMIT" }, - { 123, 3, L"ITEM_LIGHT" }, - { 124, 3, L"CHARA_EFFECT" }, - { 125, 2, L"MARKER" }, - { 126, 3, L"CHARA_EFFECT_CHARA_LIGHT" }, - { 127, 2, L"ENABLE_COMMON_LIGHT_TO_CHARA" }, - { 128, 2, L"ENABLE_FXAA" }, - { 129, 2, L"ENABLE_TEMPORAL_AA" }, - { 130, 2, L"ENABLE_REFLECTION" }, - { 131, 2, L"BANK_BRANCH" }, - { 132, 2, L"BANK_END" }, - { 133, 2, L"" }, - { 134, 2, L"" }, - { 135, 2, L"" }, - { 136, 2, L"" }, - { 137, 2, L"" }, - { 138, 2, L"" }, - { 139, 2, L"" }, - { 140, 2, L"" }, - { 141, 2, L"VR_LIVE_MOVIE" }, - { 142, 2, L"VR_CHEER" }, - { 143, 2, L"VR_CHARA_PSMOVE" }, - { 144, 2, L"VR_MOVE_PATH" }, - { 145, 2, L"VR_SET_BASE" }, - { 146, 2, L"VR_TECH_DEMO_EFFECT" }, - { 147, 2, L"VR_TRANSFORM" }, - { 148, 2, L"GAZE" }, - { 149, 2, L"TECH_DEMO_GESUTRE" }, - { 150, 2, L"VR_CHEMICAL_LIGHT_COLOR" }, - { 151, 5, L"VR_LIVE_MOB" }, - { 152, 9, L"VR_LIVE_HAIR_OSAGE" }, - { 153, 9, L"VR_LIVE_LOOK_CAMERA" }, - { 154, 5, L"VR_LIVE_CHEER" }, - { 155, 3, L"VR_LIVE_GESTURE" }, - { 156, 7, L"VR_LIVE_CLONE" }, - { 157, 7, L"VR_LOOP_EFFECT" }, - { 158, 6, L"VR_LIVE_ONESHOT_EFFECT" }, - { 159, 9, L"VR_LIVE_PRESENT" }, - { 160, 5, L"VR_LIVE_TRANSFORM" }, - { 161, 5, L"VR_LIVE_FLY" }, - { 162, 2, L"VR_LIVE_CHARA_VOICE" }, + { 0, 0, "END" }, + { 1, 1, "TIME" }, + { 2, 4, "MIKU_MOVE" }, + { 3, 2, "MIKU_ROT" }, + { 4, 2, "MIKU_DISP" }, + { 5, 2, "MIKU_SHADOW" }, + { 6, 12, "TARGET" }, + { 7, 4, "SET_MOTION" }, + { 8, 2, "SET_PLAYDATA" }, + { 9, 6, "EFFECT" }, + { 10, 2, "FADEIN_FIELD" }, + { 11, 1, "EFFECT_OFF" }, + { 12, 6, "SET_CAMERA" }, + { 13, 2, "DATA_CAMERA" }, + { 14, 2, "CHANGE_FIELD" }, + { 15, 1, "HIDE_FIELD" }, + { 16, 3, "MOVE_FIELD" }, + { 17, 2, "FADEOUT_FIELD" }, + { 18, 3, "EYE_ANIM" }, + { 19, 5, "MOUTH_ANIM" }, + { 20, 5, "HAND_ANIM" }, + { 21, 4, "LOOK_ANIM" }, + { 22, 4, "EXPRESSION" }, + { 23, 5, "LOOK_CAMERA" }, + { 24, 2, "LYRIC" }, + { 25, 0, "MUSIC_PLAY" }, + { 26, 2, "MODE_SELECT" }, + { 27, 4, "EDIT_MOTION" }, + { 28, 2, "BAR_TIME_SET" }, + { 29, 2, "SHADOWHEIGHT" }, + { 30, 1, "EDIT_FACE" }, + { 31, 21, "DUMMY" }, + { 32, 0, "PV_END" }, + { 33, 3, "SHADOWPOS" }, + { 34, 2, "EDIT_LYRIC" }, + { 35, 5, "EDIT_TARGET" }, + { 36, 1, "EDIT_MOUTH" }, + { 37, 1, "SET_CHARA" }, + { 38, 7, "EDIT_MOVE" }, + { 39, 1, "EDIT_SHADOW" }, + { 40, 1, "EDIT_EYELID" }, + { 41, 2, "EDIT_EYE" }, + { 42, 1, "EDIT_ITEM" }, + { 43, 2, "EDIT_EFFECT" }, + { 44, 1, "EDIT_DISP" }, + { 45, 2, "EDIT_HAND_ANIM" }, + { 46, 3, "AIM" }, + { 47, 3, "HAND_ITEM" }, + { 48, 1, "EDIT_BLUSH" }, + { 49, 2, "NEAR_CLIP" }, + { 50, 2, "CLOTH_WET" }, + { 51, 3, "LIGHT_ROT" }, + { 52, 6, "SCENE_FADE" }, + { 53, 6, "TONE_TRANS" }, + { 54, 1, "SATURATE" }, + { 55, 1, "FADE_MODE" }, + { 56, 2, "AUTO_BLINK" }, + { 57, 3, "PARTS_DISP" }, + { 58, 1, "TARGET_FLYING_TIME" }, + { 59, 2, "CHARA_SIZE" }, + { 60, 2, "CHARA_HEIGHT_ADJUST" }, + { 61, 4, "ITEM_ANIM" }, + { 62, 4, "CHARA_POS_ADJUST" }, + { 63, 1, "SCENE_ROT" }, + { 64, 2, "EDIT_MOT_SMOOTH_LEN" }, + { 65, 1, "PV_BRANCH_MODE" }, + { 66, 2, "DATA_CAMERA_START" }, + { 67, 1, "MOVIE_PLAY" }, + { 68, 1, "MOVIE_DISP" }, + { 69, 3, "WIND" }, + { 70, 3, "OSAGE_STEP" }, + { 71, 3, "OSAGE_MV_CC" }, + { 72, 2, "CHARA_COLOR" }, + { 73, 1, "SE_EFFECT" }, + { 74, 2, "CHARA_SHADOW_QUALITY" }, + { 75, 2, "STAGE_SHADOW_QUALITY" }, + { 76, 2, "COMMON_LIGHT" }, + { 77, 2, "TONE_MAP" }, + { 78, 2, "IBL_COLOR" }, + { 79, 2, "REFLECTION" }, + { 80, 3, "CHROMATIC_ABERRATION" }, + { 81, 2, "STAGE_SHADOW" }, + { 82, 2, "REFLECTION_QUALITY" }, + { 83, 2, "PV_END_FADEOUT" }, + { 84, 1, "CREDIT_TITLE" }, + { 85, 1, "BAR_POINT" }, + { 86, 1, "BEAT_POINT" }, + { 87, 0, "RESERVE" }, + { 88, 2, "PV_AUTH_LIGHT_PRIORITY" }, + { 89, 3, "PV_CHARA_LIGHT" }, + { 90, 3, "PV_STAGE_LIGHT" }, + { 91, 11, "TARGET_EFFECT" }, + { 92, 3, "FOG" }, + { 93, 2, "BLOOM" }, + { 94, 3, "COLOR_CORRECTION" }, + { 95, 3, "DOF" }, + { 96, 4, "CHARA_ALPHA" }, + { 97, 1, "AUTO_CAPTURE_BEGIN" }, + { 98, 1, "MANUAL_CAPTURE" }, + { 99, 3, "TOON_EDGE" }, + { 100, 3, "SHIMMER" }, + { 101, 4, "ITEM_ALPHA" }, + { 102, 1, "MOVIE_CUT" }, + { 103, 112, "EDIT_CAMERA_BOX" }, + { 104, 1, "EDIT_STAGE_PARAM" }, + { 105, 1, "EDIT_CHANGE_FIELD" }, + { 106, 7, "MIKUDAYO_ADJUST" }, + { 107, 2, "LYRIC_2" }, + { 108, 2, "LYRIC_READ" }, + { 109, 2, "LYRIC_READ_2" }, + { 110, 5, "ANNOTATION" }, + { 111, 2, "STAGE_EFFECT" }, + { 112, 3, "SONG_EFFECT" }, + { 113, 3, "SONG_EFFECT_ATTACH" }, + { 114, 2, "LIGHT_AUTH" }, + { 115, 2, "FADE" }, + { 116, 2, "SET_STAGE_EFFECT_ENV" }, + { 117, 2, "RESERVE" }, + { 118, 2, "COMMON_EFFECT_AET_FRONT" }, + { 119, 2, "COMMON_EFFECT_AET_FRONT_LOW" }, + { 120, 2, "COMMON_EFFECT_PARTICLE" }, + { 121, 3, "SONG_EFFECT_ALPHA_SORT" }, + { 122, 5, "LOOK_CAMERA_FACE_LIMIT" }, + { 123, 3, "ITEM_LIGHT" }, + { 124, 3, "CHARA_EFFECT" }, + { 125, 2, "MARKER" }, + { 126, 3, "CHARA_EFFECT_CHARA_LIGHT" }, + { 127, 2, "ENABLE_COMMON_LIGHT_TO_CHARA" }, + { 128, 2, "ENABLE_FXAA" }, + { 129, 2, "ENABLE_TEMPORAL_AA" }, + { 130, 2, "ENABLE_REFLECTION" }, + { 131, 2, "BANK_BRANCH" }, + { 132, 2, "BANK_END" }, + { 133, 2, "" }, + { 134, 2, "" }, + { 135, 2, "" }, + { 136, 2, "" }, + { 137, 2, "" }, + { 138, 2, "" }, + { 139, 2, "" }, + { 140, 2, "" }, + { 141, 2, "VR_LIVE_MOVIE" }, + { 142, 2, "VR_CHEER" }, + { 143, 2, "VR_CHARA_PSMOVE" }, + { 144, 2, "VR_MOVE_PATH" }, + { 145, 2, "VR_SET_BASE" }, + { 146, 2, "VR_TECH_DEMO_EFFECT" }, + { 147, 2, "VR_TRANSFORM" }, + { 148, 2, "GAZE" }, + { 149, 2, "TECH_DEMO_GESUTRE" }, + { 150, 2, "VR_CHEMICAL_LIGHT_COLOR" }, + { 151, 5, "VR_LIVE_MOB" }, + { 152, 9, "VR_LIVE_HAIR_OSAGE" }, + { 153, 9, "VR_LIVE_LOOK_CAMERA" }, + { 154, 5, "VR_LIVE_CHEER" }, + { 155, 3, "VR_LIVE_GESTURE" }, + { 156, 7, "VR_LIVE_CLONE" }, + { 157, 7, "VR_LOOP_EFFECT" }, + { 158, 6, "VR_LIVE_ONESHOT_EFFECT" }, + { 159, 9, "VR_LIVE_PRESENT" }, + { 160, 5, "VR_LIVE_TRANSFORM" }, + { 161, 5, "VR_LIVE_FLY" }, + { 162, 2, "VR_LIVE_CHARA_VOICE" }, }; static const dsc_func dsc_vrfl_func[] = { - { 0, 0, L"END" }, - { 1, 1, L"TIME" }, - { 2, 4, L"MIKU_MOVE" }, - { 3, 2, L"MIKU_ROT" }, - { 4, 2, L"MIKU_DISP" }, - { 5, 2, L"MIKU_SHADOW" }, - { 6, 12, L"TARGET" }, - { 7, 4, L"SET_MOTION" }, - { 8, 2, L"SET_PLAYDATA" }, - { 9, 6, L"EFFECT" }, - { 10, 2, L"FADEIN_FIELD" }, - { 11, 1, L"EFFECT_OFF" }, - { 12, 6, L"SET_CAMERA" }, - { 13, 2, L"DATA_CAMERA" }, - { 14, 2, L"CHANGE_FIELD" }, - { 15, 1, L"HIDE_FIELD" }, - { 16, 3, L"MOVE_FIELD" }, - { 17, 2, L"FADEOUT_FIELD" }, - { 18, 3, L"EYE_ANIM" }, - { 19, 5, L"MOUTH_ANIM" }, - { 20, 5, L"HAND_ANIM" }, - { 21, 4, L"LOOK_ANIM" }, - { 22, 4, L"EXPRESSION" }, - { 23, 5, L"LOOK_CAMERA" }, - { 24, 2, L"LYRIC" }, - { 25, 0, L"MUSIC_PLAY" }, - { 26, 2, L"MODE_SELECT" }, - { 27, 4, L"EDIT_MOTION" }, - { 28, 2, L"BAR_TIME_SET" }, - { 29, 2, L"SHADOWHEIGHT" }, - { 30, 1, L"EDIT_FACE" }, - { 31, 21, L"DUMMY" }, - { 32, 0, L"PV_END" }, - { 33, 3, L"SHADOWPOS" }, - { 34, 2, L"EDIT_LYRIC" }, - { 35, 5, L"EDIT_TARGET" }, - { 36, 1, L"EDIT_MOUTH" }, - { 37, 1, L"SET_CHARA" }, - { 38, 7, L"EDIT_MOVE" }, - { 39, 1, L"EDIT_SHADOW" }, - { 40, 1, L"EDIT_EYELID" }, - { 41, 2, L"EDIT_EYE" }, - { 42, 1, L"EDIT_ITEM" }, - { 43, 2, L"EDIT_EFFECT" }, - { 44, 1, L"EDIT_DISP" }, - { 45, 2, L"EDIT_HAND_ANIM" }, - { 46, 3, L"AIM" }, - { 47, 3, L"HAND_ITEM" }, - { 48, 1, L"EDIT_BLUSH" }, - { 49, 2, L"NEAR_CLIP" }, - { 50, 2, L"CLOTH_WET" }, - { 51, 3, L"LIGHT_ROT" }, - { 52, 6, L"SCENE_FADE" }, - { 53, 6, L"TONE_TRANS" }, - { 54, 1, L"SATURATE" }, - { 55, 1, L"FADE_MODE" }, - { 56, 2, L"AUTO_BLINK" }, - { 57, 3, L"PARTS_DISP" }, - { 58, 1, L"TARGET_FLYING_TIME" }, - { 59, 2, L"CHARA_SIZE" }, - { 60, 2, L"CHARA_HEIGHT_ADJUST" }, - { 61, 4, L"ITEM_ANIM" }, - { 62, 4, L"CHARA_POS_ADJUST" }, - { 63, 1, L"SCENE_ROT" }, - { 64, 2, L"EDIT_MOT_SMOOTH_LEN" }, - { 65, 1, L"PV_BRANCH_MODE" }, - { 66, 2, L"DATA_CAMERA_START" }, - { 67, 1, L"MOVIE_PLAY" }, - { 68, 1, L"MOVIE_DISP" }, - { 69, 3, L"WIND" }, - { 70, 3, L"OSAGE_STEP" }, - { 71, 3, L"OSAGE_MV_CCL" }, - { 72, 2, L"CHARA_COLOR" }, - { 73, 1, L"SE_EFFECT" }, - { 74, 2, L"CHARA_SHADOW_QUALITY" }, - { 75, 2, L"STAGE_SHADOW_QUALITY" }, - { 76, 2, L"COMMON_LIGHT" }, - { 77, 2, L"TONE_MAP" }, - { 78, 2, L"IBL_COLOR" }, - { 79, 2, L"REFLECTION" }, - { 80, 3, L"CHROMATIC_ABERRATION" }, - { 81, 2, L"STAGE_SHADOW" }, - { 82, 2, L"REFLECTION_QUALITY" }, - { 83, 2, L"PV_END_FADEOUT" }, - { 84, 1, L"CREDIT_TITLE" }, - { 85, 1, L"BAR_POINT" }, - { 86, 1, L"BEAT_POINT" }, - { 87, 0, L"RESERVE" }, - { 88, 2, L"PV_AUTH_LIGHT_PRIORITY" }, - { 89, 3, L"PV_CHARA_LIGHT" }, - { 90, 3, L"PV_STAGE_LIGHT" }, - { 91, 11, L"TARGET_EFFECT" }, - { 92, 3, L"FOG" }, - { 93, 2, L"BLOOM" }, - { 94, 3, L"COLOR_CORRECTION" }, - { 95, 3, L"DOF" }, - { 96, 4, L"CHARA_ALPHA" }, - { 97, 1, L"AUTO_CAPTURE_BEGIN" }, - { 98, 1, L"MANUAL_CAPTURE" }, - { 99, 3, L"TOON_EDGE" }, - { 100, 3, L"SHIMMER" }, - { 101, 4, L"ITEM_ALPHA" }, - { 102, 1, L"MOVIE_CUT" }, - { 103, 112, L"EDIT_CAMERA_BOX" }, - { 104, 1, L"EDIT_STAGE_PARAM" }, - { 105, 1, L"EDIT_CHANGE_FIELD" }, - { 106, 7, L"MIKUDAYO_ADJUST" }, - { 107, 2, L"LYRIC_2" }, - { 108, 2, L"LYRIC_READ" }, - { 109, 2, L"LYRIC_READ_2" }, - { 110, 5, L"ANNOTATION" }, - { 111, 2, L"STAGE_EFFECT" }, - { 112, 3, L"SONG_EFFECT" }, - { 113, 3, L"SONG_EFFECT_ATTACH" }, - { 114, 2, L"LIGHT_AUTH" }, - { 115, 2, L"FADE" }, - { 116, 2, L"SET_STAGE_EFFECT_ENV" }, - { 117, 2, L"RESERVE" }, - { 118, 2, L"COMMON_EFFECT_AET_FRONT" }, - { 119, 2, L"COMMON_EFFECT_AET_FRONT_LOW" }, - { 120, 2, L"COMMON_EFFECT_PARTICLE" }, - { 121, 3, L"SONG_EFFECT_ALPHA_SORT" }, - { 122, 5, L"LOOK_CAMERA_FACE_LIMIT" }, - { 123, 3, L"ITEM_LIGHT" }, - { 124, 3, L"CHARA_EFFECT" }, - { 125, 2, L"MARKER" }, - { 126, 3, L"CHARA_EFFECT_CHARA_LIGHT" }, - { 127, 2, L"ENABLE_COMMON_LIGHT_TO_CHARA" }, - { 128, 2, L"ENABLE_FXAA" }, - { 129, 2, L"ENABLE_TEMPORAL_AA" }, - { 130, 2, L"ENABLE_REFLECTION" }, - { 131, 2, L"BANK_BRANCH" }, - { 132, 2, L"BANK_END" }, - { 133, 2, L"" }, - { 134, 2, L"" }, - { 135, 2, L"" }, - { 136, 2, L"" }, - { 137, 2, L"" }, - { 138, 2, L"VR_LIVE_CHARA_MONITOR_UPDATE_Y" }, - { 139, 2, L"VR_LIVE_POINT_FINGER" }, - { 140, 2, L"VR_LIVE_CHARA_MONITOR" }, - { 141, 2, L"VR_LIVE_MOVIE" }, - { 142, 2, L"VR_CHEER" }, - { 143, 2, L"VR_CHARA_PSMOVE" }, - { 144, 2, L"VR_MOVE_PATH" }, - { 145, 2, L"VR_SET_BASE" }, - { 146, 2, L"VR_TECH_DEMO_EFFECT" }, - { 147, 2, L"VR_TRANSFORM" }, - { 148, 2, L"GAZE" }, - { 149, 2, L"TECH_DEMO_GESUTRE" }, - { 150, 2, L"VR_CHEMICAL_LIGHT_COLOR" }, - { 151, 5, L"VR_LIVE_MOB" }, - { 152, 9, L"VR_LIVE_HAIR_OSAGE" }, - { 153, 9, L"VR_LIVE_LOOK_CAMERA" }, - { 154, 5, L"VR_LIVE_CHEER" }, - { 155, 3, L"VR_LIVE_GESTURE" }, - { 156, 7, L"VR_LIVE_CLONE" }, - { 157, 7, L"VR_LOOP_EFFECT" }, - { 158, 6, L"VR_LIVE_ONESHOT_EFFECT" }, - { 159, 9, L"VR_LIVE_PRESENT" }, - { 160, 7, L"VR_LIVE_TRANSFORM" }, - { 161, 5, L"VR_LIVE_FLY" }, - { 162, 2, L"VR_LIVE_CHARA_VOICE" }, + { 0, 0, "END" }, + { 1, 1, "TIME" }, + { 2, 4, "MIKU_MOVE" }, + { 3, 2, "MIKU_ROT" }, + { 4, 2, "MIKU_DISP" }, + { 5, 2, "MIKU_SHADOW" }, + { 6, 12, "TARGET" }, + { 7, 4, "SET_MOTION" }, + { 8, 2, "SET_PLAYDATA" }, + { 9, 6, "EFFECT" }, + { 10, 2, "FADEIN_FIELD" }, + { 11, 1, "EFFECT_OFF" }, + { 12, 6, "SET_CAMERA" }, + { 13, 2, "DATA_CAMERA" }, + { 14, 2, "CHANGE_FIELD" }, + { 15, 1, "HIDE_FIELD" }, + { 16, 3, "MOVE_FIELD" }, + { 17, 2, "FADEOUT_FIELD" }, + { 18, 3, "EYE_ANIM" }, + { 19, 5, "MOUTH_ANIM" }, + { 20, 5, "HAND_ANIM" }, + { 21, 4, "LOOK_ANIM" }, + { 22, 4, "EXPRESSION" }, + { 23, 5, "LOOK_CAMERA" }, + { 24, 2, "LYRIC" }, + { 25, 0, "MUSIC_PLAY" }, + { 26, 2, "MODE_SELECT" }, + { 27, 4, "EDIT_MOTION" }, + { 28, 2, "BAR_TIME_SET" }, + { 29, 2, "SHADOWHEIGHT" }, + { 30, 1, "EDIT_FACE" }, + { 31, 21, "DUMMY" }, + { 32, 0, "PV_END" }, + { 33, 3, "SHADOWPOS" }, + { 34, 2, "EDIT_LYRIC" }, + { 35, 5, "EDIT_TARGET" }, + { 36, 1, "EDIT_MOUTH" }, + { 37, 1, "SET_CHARA" }, + { 38, 7, "EDIT_MOVE" }, + { 39, 1, "EDIT_SHADOW" }, + { 40, 1, "EDIT_EYELID" }, + { 41, 2, "EDIT_EYE" }, + { 42, 1, "EDIT_ITEM" }, + { 43, 2, "EDIT_EFFECT" }, + { 44, 1, "EDIT_DISP" }, + { 45, 2, "EDIT_HAND_ANIM" }, + { 46, 3, "AIM" }, + { 47, 3, "HAND_ITEM" }, + { 48, 1, "EDIT_BLUSH" }, + { 49, 2, "NEAR_CLIP" }, + { 50, 2, "CLOTH_WET" }, + { 51, 3, "LIGHT_ROT" }, + { 52, 6, "SCENE_FADE" }, + { 53, 6, "TONE_TRANS" }, + { 54, 1, "SATURATE" }, + { 55, 1, "FADE_MODE" }, + { 56, 2, "AUTO_BLINK" }, + { 57, 3, "PARTS_DISP" }, + { 58, 1, "TARGET_FLYING_TIME" }, + { 59, 2, "CHARA_SIZE" }, + { 60, 2, "CHARA_HEIGHT_ADJUST" }, + { 61, 4, "ITEM_ANIM" }, + { 62, 4, "CHARA_POS_ADJUST" }, + { 63, 1, "SCENE_ROT" }, + { 64, 2, "EDIT_MOT_SMOOTH_LEN" }, + { 65, 1, "PV_BRANCH_MODE" }, + { 66, 2, "DATA_CAMERA_START" }, + { 67, 1, "MOVIE_PLAY" }, + { 68, 1, "MOVIE_DISP" }, + { 69, 3, "WIND" }, + { 70, 3, "OSAGE_STEP" }, + { 71, 3, "OSAGE_MV_CC" }, + { 72, 2, "CHARA_COLOR" }, + { 73, 1, "SE_EFFECT" }, + { 74, 2, "CHARA_SHADOW_QUALITY" }, + { 75, 2, "STAGE_SHADOW_QUALITY" }, + { 76, 2, "COMMON_LIGHT" }, + { 77, 2, "TONE_MAP" }, + { 78, 2, "IBL_COLOR" }, + { 79, 2, "REFLECTION" }, + { 80, 3, "CHROMATIC_ABERRATION" }, + { 81, 2, "STAGE_SHADOW" }, + { 82, 2, "REFLECTION_QUALITY" }, + { 83, 2, "PV_END_FADEOUT" }, + { 84, 1, "CREDIT_TITLE" }, + { 85, 1, "BAR_POINT" }, + { 86, 1, "BEAT_POINT" }, + { 87, 0, "RESERVE" }, + { 88, 2, "PV_AUTH_LIGHT_PRIORITY" }, + { 89, 3, "PV_CHARA_LIGHT" }, + { 90, 3, "PV_STAGE_LIGHT" }, + { 91, 11, "TARGET_EFFECT" }, + { 92, 3, "FOG" }, + { 93, 2, "BLOOM" }, + { 94, 3, "COLOR_CORRECTION" }, + { 95, 3, "DOF" }, + { 96, 4, "CHARA_ALPHA" }, + { 97, 1, "AUTO_CAPTURE_BEGIN" }, + { 98, 1, "MANUAL_CAPTURE" }, + { 99, 3, "TOON_EDGE" }, + { 100, 3, "SHIMMER" }, + { 101, 4, "ITEM_ALPHA" }, + { 102, 1, "MOVIE_CUT" }, + { 103, 112, "EDIT_CAMERA_BOX" }, + { 104, 1, "EDIT_STAGE_PARAM" }, + { 105, 1, "EDIT_CHANGE_FIELD" }, + { 106, 7, "MIKUDAYO_ADJUST" }, + { 107, 2, "LYRIC_2" }, + { 108, 2, "LYRIC_READ" }, + { 109, 2, "LYRIC_READ_2" }, + { 110, 5, "ANNOTATION" }, + { 111, 2, "STAGE_EFFECT" }, + { 112, 3, "SONG_EFFECT" }, + { 113, 3, "SONG_EFFECT_ATTACH" }, + { 114, 2, "LIGHT_AUTH" }, + { 115, 2, "FADE" }, + { 116, 2, "SET_STAGE_EFFECT_ENV" }, + { 117, 2, "RESERVE" }, + { 118, 2, "COMMON_EFFECT_AET_FRONT" }, + { 119, 2, "COMMON_EFFECT_AET_FRONT_LOW" }, + { 120, 2, "COMMON_EFFECT_PARTICLE" }, + { 121, 3, "SONG_EFFECT_ALPHA_SORT" }, + { 122, 5, "LOOK_CAMERA_FACE_LIMIT" }, + { 123, 3, "ITEM_LIGHT" }, + { 124, 3, "CHARA_EFFECT" }, + { 125, 2, "MARKER" }, + { 126, 3, "CHARA_EFFECT_CHARA_LIGHT" }, + { 127, 2, "ENABLE_COMMON_LIGHT_TO_CHARA" }, + { 128, 2, "ENABLE_FXAA" }, + { 129, 2, "ENABLE_TEMPORAL_AA" }, + { 130, 2, "ENABLE_REFLECTION" }, + { 131, 2, "BANK_BRANCH" }, + { 132, 2, "BANK_END" }, + { 133, 2, "" }, + { 134, 2, "" }, + { 135, 2, "" }, + { 136, 2, "" }, + { 137, 2, "" }, + { 138, 2, "VR_LIVE_CHARA_MONITOR_UPDATE_Y" }, + { 139, 2, "VR_LIVE_POINT_FINGER" }, + { 140, 2, "VR_LIVE_CHARA_MONITOR" }, + { 141, 2, "VR_LIVE_MOVIE" }, + { 142, 2, "VR_CHEER" }, + { 143, 2, "VR_CHARA_PSMOVE" }, + { 144, 2, "VR_MOVE_PATH" }, + { 145, 2, "VR_SET_BASE" }, + { 146, 2, "VR_TECH_DEMO_EFFECT" }, + { 147, 2, "VR_TRANSFORM" }, + { 148, 2, "GAZE" }, + { 149, 2, "TECH_DEMO_GESUTRE" }, + { 150, 2, "VR_CHEMICAL_LIGHT_COLOR" }, + { 151, 5, "VR_LIVE_MOB" }, + { 152, 9, "VR_LIVE_HAIR_OSAGE" }, + { 153, 9, "VR_LIVE_LOOK_CAMERA" }, + { 154, 5, "VR_LIVE_CHEER" }, + { 155, 3, "VR_LIVE_GESTURE" }, + { 156, 7, "VR_LIVE_CLONE" }, + { 157, 7, "VR_LOOP_EFFECT" }, + { 158, 6, "VR_LIVE_ONESHOT_EFFECT" }, + { 159, 9, "VR_LIVE_PRESENT" }, + { 160, 7, "VR_LIVE_TRANSFORM" }, + { 161, 5, "VR_LIVE_FLY" }, + { 162, 2, "VR_LIVE_CHARA_VOICE" }, }; inline int32_t dsc_ac101_get_func_length(int32_t id) { @@ -822,3 +825,268 @@ inline int32_t dsc_ft_get_func_length_old(int32_t id) { inline int32_t dsc_f_get_func_length_old(int32_t id) { return id > -1 && id < 84 ? dsc_f_func[id].length_old : -1; } + +const dsc_get_func_length dsc_get_func_length_array[] = { + [DSC_AC101] = dsc_ac101_get_func_length, + [DSC_AC110] = dsc_ac110_get_func_length, + [DSC_AC120] = dsc_ac120_get_func_length, + [DSC_AC200] = dsc_ac200_get_func_length, + [DSC_AC210] = dsc_ac210_get_func_length, + [DSC_AC500] = dsc_ac500_get_func_length, + [DSC_AC510] = dsc_ac510_get_func_length, + [DSC_AFT101] = dsc_aft101_get_func_length, + [DSC_AFT200] = dsc_aft200_get_func_length, + [DSC_AFT300] = dsc_aft300_get_func_length, + [DSC_AFT310] = dsc_aft310_get_func_length, + [DSC_AFT410] = dsc_aft410_get_func_length, + [DSC_AFT701] = dsc_aft701_get_func_length, + [DSC_FT] = dsc_ft_get_func_length, + [DSC_PSP] = dsc_psp_get_func_length, + [DSC_2ND] = dsc_2nd_get_func_length, + [DSC_F] = dsc_f_get_func_length, + [DSC_F2] = dsc_f2_get_func_length, + [DSC_MGF] = dsc_mgf_get_func_length, + [DSC_X] = dsc_x_get_func_length, + [DSC_VRFL] = dsc_vrfl_get_func_length, +}; + +const dsc_get_func_length dsc_get_func_length_old_array[] = { + [DSC_AC101] = dsc_ac101_get_func_length, + [DSC_AC110] = dsc_ac110_get_func_length, + [DSC_AC120] = dsc_ac120_get_func_length, + [DSC_AC200] = dsc_ac200_get_func_length_old, + [DSC_AC210] = dsc_ac210_get_func_length_old, + [DSC_AC500] = dsc_ac500_get_func_length_old, + [DSC_AC510] = dsc_ac510_get_func_length_old, + [DSC_AFT101] = dsc_aft101_get_func_length_old, + [DSC_AFT200] = dsc_aft200_get_func_length_old, + [DSC_AFT300] = dsc_aft300_get_func_length_old, + [DSC_AFT310] = dsc_aft310_get_func_length_old, + [DSC_AFT410] = dsc_aft410_get_func_length_old, + [DSC_AFT701] = dsc_aft701_get_func_length_old, + [DSC_FT] = dsc_ft_get_func_length, + [DSC_PSP] = dsc_psp_get_func_length, + [DSC_2ND] = dsc_2nd_get_func_length, + [DSC_F] = dsc_f_get_func_length_old, + [DSC_F2] = dsc_f2_get_func_length, + [DSC_MGF] = dsc_mgf_get_func_length, + [DSC_X] = dsc_x_get_func_length, + [DSC_VRFL] = dsc_vrfl_get_func_length, +}; + +void dsc_init(dsc* d) { + memset(d, 0, sizeof(dsc)); +} + +void dsc_data_buffer_rebuild(dsc* d) { + dsc_get_func_length func = dsc_get_func_length_array[d->type]; + size_t size = 0; + for (dsc_data* i = d->data.begin; i != d->data.end; i++) + size += func(i->func); + + vector_uint32_t data_buffer = vector_empty(uint32_t); + vector_uint32_t_reserve(&data_buffer, size); + for (dsc_data* i = d->data.begin; i != d->data.end; i++) { + uint32_t* func_data = dsc_data_get_func_data(d, i); + i->data_offset = (uint32_t)(data_buffer.end - data_buffer.begin); + + for (int32_t j = func(i->func); j; j--) + vector_uint32_t_push_back(&data_buffer, func_data++); + } + vector_uint32_t_free(&d->data_buffer, 0); + d->data_buffer = data_buffer; +} + +inline void* dsc_data_get_func_data(dsc* d, dsc_data* data) { + return d->data_buffer.begin + data->data_offset; +} + +void dsc_parse(dsc* d, void* data, size_t length, dsc_type type) { + if (!d || !data || !(length / 4)) + return; + + uint32_t* data_dsc = data; + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + switch (type) { + case DSC_AC200: + case DSC_AC210: + case DSC_AC500: + case DSC_AC510: + case DSC_AFT101: + case DSC_AFT200: + case DSC_AFT300: + case DSC_AFT310: + case DSC_AFT410: + case DSC_AFT701: + case DSC_FT: + case DSC_F: + d->signature = *data_dsc++; + break; + case DSC_F2: + case DSC_MGF: + case DSC_X: + case DSC_VRFL: { + f2_struct_mread(&st, data, length); + data_dsc = st.data; + if (st.header.use_big_endian) + for (size_t i = length / 4; i; i--, data_dsc++) + *data_dsc = load_reverse_endianness_uint32_t(data_dsc); + + data_dsc = st.data; + if (*data_dsc++ != 0x13120420) { + f2_struct_free(&st); + return; + } + d->id = *data_dsc++; + } break; + } + + length /= 4; + + d->type = type; + dsc_get_func_length func = dsc_get_func_length_array[type]; + + size_t func_count = 0; + size_t data_size = 0; + uint32_t* func_data = data_dsc; + for (size_t i = 0; i < length; i++) { + if (!*func_data) { + length = i; + break; + } + + int32_t func_length = func(*func_data++); + if (func_length < 0) { + length = i; + break; + } + + data_size += func_length; + func_data += func_length; + i += func_length; + func_count++; + } + + d->data = vector_empty(dsc_data); + d->data_buffer = vector_empty(uint32_t); + vector_dsc_data_reserve(&d->data, func_count); + vector_uint32_t_reserve(&d->data_buffer, data_size); + + func_data = data_dsc; + for (size_t i = 0; i < func_count; i++) { + dsc_data* data = vector_dsc_data_reserve_back(&d->data); + data->func = *func_data++; + data->data_offset = (uint32_t)(d->data_buffer.end - d->data_buffer.begin); + for (int32_t j = func(data->func); j; j--) + vector_uint32_t_push_back(&d->data_buffer, func_data++); + } + f2_struct_free(&st); +} + +void dsc_unparse(dsc* d, void** data, size_t* length) { + if (!d || !data || !length) + return; + + dsc_get_func_length func = dsc_get_func_length_array[d->type]; + + bool f2 = false; + size_t size = 1; + switch (d->type) { + case DSC_AC200: + case DSC_AC210: + case DSC_AC500: + case DSC_AC510: + case DSC_AFT101: + case DSC_AFT200: + case DSC_AFT300: + case DSC_AFT310: + case DSC_AFT410: + case DSC_AFT701: + case DSC_FT: + case DSC_F: + size++; + break; + case DSC_F2: + case DSC_MGF: + case DSC_X: + case DSC_VRFL: + size += 2; + f2 = true; + break; + } + + for (dsc_data* i = d->data.begin; i != d->data.end; i++) + size += func(i->func) + 1ULL; + + size_t data_size = size; + if (f2) + data_size = align_val(size, 4); + + uint32_t* data_dsc = force_malloc_s(uint32_t, data_size); + uint32_t* func_data = data_dsc; + + switch (d->type) { + case DSC_AC200: + case DSC_AC210: + case DSC_AC500: + case DSC_AC510: + case DSC_AFT101: + case DSC_AFT200: + case DSC_AFT300: + case DSC_AFT310: + case DSC_AFT410: + case DSC_AFT701: + case DSC_FT: + case DSC_F: + *func_data++ = d->signature; + break; + case DSC_F2: + case DSC_MGF: + case DSC_X: + case DSC_VRFL: { + *func_data++ = 0x13120420; + *func_data++ = d->id; + } break; + } + + for (dsc_data* i = d->data.begin; i != d->data.end; i++) { + *func_data++ = i->func; + uint32_t* data = dsc_data_get_func_data(d, i); + for (int32_t j = func(i->func); j; j--) + *func_data++ = *data++; + } + *func_data++ = 0; + + if (f2) { + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + + ee = (enrs_entry){ 0, 1, 4, (uint32_t)size, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + st.data = data_dsc; + st.length = data_size * sizeof(uint32_t); + st.enrs = e; + + st.header.signature = reverse_endianness_uint32_t('PVSC'); + st.header.length = 0x40; + st.header.use_section_size = true; + st.header.inner_signature = 0x13120420; + f2_struct_mwrite(&st, data, length, true, false); + f2_struct_free(&st); + } + else { + *data = data_dsc; + *length = data_size * sizeof(uint32_t); + } +} + +void dsc_free(dsc* d) { + vector_dsc_data_free(&d->data, 0); + vector_uint32_t_free(&d->data_buffer, 0); +} diff --git a/src/KKdLib/dsc.h b/src/KKdLib/dsc.h index 9c23db44..ab9ca717 100644 --- a/src/KKdLib/dsc.h +++ b/src/KKdLib/dsc.h @@ -6,6 +6,7 @@ #pragma once #include "default.h" +#include "vector.h" typedef enum dsc_diff { DSC_DIFF_EASY = 0, @@ -22,6 +23,31 @@ typedef enum dsc_f2_mode { DSC_MODE_DAYO = 3, } dsc_f2_mode; +typedef enum dsc_type { + DSC_NONE = 0, + DSC_AC101, + DSC_AC110, + DSC_AC120, + DSC_AC200, + DSC_AC210, + DSC_AC500, + DSC_AC510, + DSC_AFT101, + DSC_AFT200, + DSC_AFT300, + DSC_AFT310, + DSC_AFT410, + DSC_AFT701, + DSC_FT, + DSC_PSP, + DSC_2ND, + DSC_F, + DSC_F2, + DSC_MGF, + DSC_X, + DSC_VRFL, +} dsc_type; + #pragma region dsc_note typedef struct dsc_note7 { int32_t type; @@ -67,14 +93,14 @@ typedef struct dsc_note12 { typedef struct dsc_func { int32_t id; int32_t length; - wchar_t* name; + char* name; } dsc_func; typedef struct dsc_func_ac { int32_t id; int32_t length_old; int32_t length; - wchar_t* name; + char* name; } dsc_func_ac; #pragma endregion @@ -235,6 +261,25 @@ typedef enum dsc_target_id_x { } dsc_target_id_x; #pragma endregion +typedef struct dsc_data { + int32_t func; + uint32_t data_offset; +} dsc_data; + +vector(dsc_data) + +typedef struct dsc { + dsc_type type; + union { + uint32_t signature; + uint32_t id; + }; + vector_dsc_data data; + vector_uint32_t data_buffer; +} dsc; + +typedef int32_t(*dsc_get_func_length)(int32_t id); + extern int32_t dsc_ac101_get_func_length(int32_t id); extern int32_t dsc_ac110_get_func_length(int32_t id); extern int32_t dsc_ac120_get_func_length(int32_t id); @@ -269,3 +314,13 @@ extern int32_t dsc_aft410_get_func_length_old(int32_t id); extern int32_t dsc_aft701_get_func_length_old(int32_t id); extern int32_t dsc_ft_get_func_length_old(int32_t id); extern int32_t dsc_f_get_func_length_old(int32_t id); + +extern const dsc_get_func_length dsc_get_func_length_array[]; +extern const dsc_get_func_length dsc_get_func_length_old_array[]; + +extern void dsc_init(dsc* d); +extern void dsc_data_buffer_rebuild(dsc* d); +extern void* dsc_data_get_func_data(dsc* d, dsc_data* data); +extern void dsc_parse(dsc* d, void* data, size_t length, dsc_type type); +extern void dsc_unparse(dsc* d, void** data, size_t* length); +extern void dsc_free(dsc* d); diff --git a/src/KKdLib/f2_enrs.c b/src/KKdLib/f2/enrs.c similarity index 95% rename from src/KKdLib/f2_enrs.c rename to src/KKdLib/f2/enrs.c index 984d35d2..a54f6c50 100644 --- a/src/KKdLib/f2_enrs.c +++ b/src/KKdLib/f2/enrs.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "f2_enrs.h" +#include "enrs.h" typedef enum enrs_value_type { ENRS_VALUE_INT8 = 0x0, @@ -17,10 +17,10 @@ vector_func(enrs_entry) inline static bool enrs_length_get_size_type(uint32_t* length, size_t val); inline static bool enrs_length_get_size(uint32_t* length, size_t val); -static bool enrs_read_packed_value_type(stream* s, uint32_t* val, enrs_type* type); static bool enrs_read_packed_value(stream* s, uint32_t* val); -static bool enrs_write_packed_value_type(stream* s, uint32_t val, enrs_type type); static bool enrs_write_packed_value(stream* s, uint32_t val); +static bool enrs_read_packed_value_type(stream* s, uint32_t* val, enrs_type* type); +static bool enrs_write_packed_value_type(stream* s, uint32_t val, enrs_type type); void enrs_apply(vector_enrs_entry* enrs, void* data) { if (!enrs || !data) @@ -105,13 +105,12 @@ End: } void enrs_read(stream* s, vector_enrs_entry* enrs) { - enrs_entry entry; enrs_sub_entry sub_entry; vector_enrs_entry e; vector_enrs_sub_entry sub; size_t i, j, l; - vector_enrs_entry_free(enrs); + vector_enrs_entry_free(enrs, 0); io_read_uint32_t(s); l = io_read_uint32_t(s); @@ -121,6 +120,7 @@ void enrs_read(stream* s, vector_enrs_entry* enrs) { e = vector_empty(enrs_entry); vector_enrs_entry_reserve(&e, l); for (i = 0; i < l; i++) { + enrs_entry entry; memset(&entry, 0, sizeof(enrs_entry)); if (enrs_read_packed_value(s, &entry.offset) || enrs_read_packed_value(s, &entry.count) @@ -194,10 +194,7 @@ void enrs_write(stream* s, vector_enrs_entry* enrs) { } End: - {} - ssize_t pos = io_get_position(s); - for (ssize_t c = align_val(pos, 0x10) - pos; c > 0; c--) - io_write_uint8_t(s, 0); + io_align_write(s, 0x10); } void enrs_free(vector_enrs_entry* e) { @@ -205,8 +202,8 @@ void enrs_free(vector_enrs_entry* e) { return; for (enrs_entry* i = e->begin; i != e->end; i++) - vector_enrs_sub_entry_free(&i->sub); - vector_enrs_entry_free(e); + vector_enrs_sub_entry_free(&i->sub, 0); + vector_enrs_entry_free(e, 0); } inline static bool enrs_length_get_size_type(uint32_t* length, size_t val) { @@ -222,16 +219,15 @@ inline static bool enrs_length_get_size(uint32_t* length, size_t val) { return val >= 0x40000000; } -static bool enrs_read_packed_value_type(stream* s, uint32_t* val, enrs_type* type) { - *val = io_read_char(s); +static bool enrs_read_packed_value(stream* s, uint32_t* val) { + *val = io_read_uint8_t(s); enrs_value_type value = (enrs_value_type)((*val >> 6) & 0x3); - *type = (enrs_type)((*val >> 4) & 0x3); - *val &= 0xF; + *val &= 0x3F; if (value == ENRS_VALUE_INT32) - *val = (((((*val << 8) | io_read_char(s)) << 8) | io_read_char(s)) << 8) | io_read_char(s); + *val = (((((*val << 8) | io_read_uint8_t(s)) << 8) | io_read_uint8_t(s)) << 8) | io_read_uint8_t(s); else if (value == ENRS_VALUE_INT16) - *val = (*val << 8) | io_read_char(s); + *val = (*val << 8) | io_read_uint8_t(s); else if (value == ENRS_VALUE_INVALID) { *val = 0; return true; @@ -239,10 +235,31 @@ static bool enrs_read_packed_value_type(stream* s, uint32_t* val, enrs_type* typ return false; } -static bool enrs_read_packed_value(stream* s, uint32_t* val) { +static bool enrs_write_packed_value(stream* s, uint32_t val) { + if (val < 0x40) + io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT8 << 6) | (val & 0x3F))); + else if (val < 0x4000) { + io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT16 << 6) | ((val >> 8) & 0x3F))); + io_write_uint8_t(s, (uint8_t)val); + } + else if (val < 0x40000000) { + io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT32 << 6) | ((val >> 24) & 0x3F))); + io_write_uint8_t(s, (uint8_t)(val >> 16)); + io_write_uint8_t(s, (uint8_t)(val >> 8)); + io_write_uint8_t(s, (uint8_t)val); + } + else { + io_write_uint8_t(s, ENRS_VALUE_INVALID << 6); + return true; + } + return false; +} + +static bool enrs_read_packed_value_type(stream* s, uint32_t* val, enrs_type* type) { *val = io_read_uint8_t(s); enrs_value_type value = (enrs_value_type)((*val >> 6) & 0x3); - *val &= 0x3F; + *type = (enrs_type)((*val >> 4) & 0x3); + *val &= 0xF; if (value == ENRS_VALUE_INT32) *val = (((((*val << 8) | io_read_uint8_t(s)) << 8) | io_read_uint8_t(s)) << 8) | io_read_uint8_t(s); @@ -275,23 +292,3 @@ static bool enrs_write_packed_value_type(stream* s, uint32_t val, enrs_type type } return false; } - -static bool enrs_write_packed_value(stream* s, uint32_t val) { - if (val < 0x40) - io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT8 << 6) | (val & 0x3F))); - else if (val < 0x4000) { - io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT16 << 6) | ((val >> 8) & 0x3F))); - io_write_uint8_t(s, (uint8_t)val); - } - else if (val < 0x40000000) { - io_write_uint8_t(s, (uint8_t)((ENRS_VALUE_INT32 << 6) | ((val >> 24) & 0x3F))); - io_write_uint8_t(s, (uint8_t)(val >> 16)); - io_write_uint8_t(s, (uint8_t)(val >> 8)); - io_write_uint8_t(s, (uint8_t)val); - } - else { - io_write_uint8_t(s, ENRS_VALUE_INVALID << 6); - return true; - } - return false; -} diff --git a/src/KKdLib/f2_enrs.h b/src/KKdLib/f2/enrs.h similarity index 91% rename from src/KKdLib/f2_enrs.h rename to src/KKdLib/f2/enrs.h index 3c9d3193..fecbb43e 100644 --- a/src/KKdLib/f2_enrs.h +++ b/src/KKdLib/f2/enrs.h @@ -5,9 +5,9 @@ #pragma once -#include "default.h" -#include "io_stream.h" -#include "vector.h" +#include "../default.h" +#include "../vector.h" +#include "../io/stream.h" typedef enum enrs_type { ENRS_WORD = 0x0, diff --git a/src/KKdLib/f2_header.c b/src/KKdLib/f2/header.c similarity index 98% rename from src/KKdLib/f2_header.c rename to src/KKdLib/f2/header.c index e62dac2a..faddf1c5 100644 --- a/src/KKdLib/f2_header.c +++ b/src/KKdLib/f2/header.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "f2_header.h" +#include "header.h" void f2_header_read(stream* s, f2_header* h) { memset(h, 0, sizeof(f2_header)); diff --git a/src/KKdLib/f2_header.h b/src/KKdLib/f2/header.h similarity index 95% rename from src/KKdLib/f2_header.h rename to src/KKdLib/f2/header.h index 697aa547..b05a8447 100644 --- a/src/KKdLib/f2_header.h +++ b/src/KKdLib/f2/header.h @@ -5,8 +5,8 @@ #pragma once -#include "default.h" -#include "io_stream.h" +#include "../default.h" +#include "../io/stream.h" typedef struct f2_header { union { diff --git a/src/KKdLib/f2_pof.c b/src/KKdLib/f2/pof.c similarity index 92% rename from src/KKdLib/f2_pof.c rename to src/KKdLib/f2/pof.c index 49941ac9..82240801 100644 --- a/src/KKdLib/f2_pof.c +++ b/src/KKdLib/f2/pof.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "f2_pof.h" +#include "pof.h" typedef enum pof_value_type { POF_VALUE_INVALID = 0x0, @@ -16,7 +16,7 @@ inline static bool pof_length_get_size(uint32_t* length, size_t val); static size_t pof_read_offsets_count(stream* s); inline static bool pof_write_packed_value(stream* s, size_t val); -inline void io_write_offset_pof_add(stream* s, int64_t val, +inline void io_write_offset_pof_add(stream* s, ssize_t val, int32_t offset, bool is_x, vector_size_t* pof) { if (!is_x) { if (val) @@ -31,7 +31,7 @@ inline void io_write_offset_pof_add(stream* s, int64_t val, } } -inline void io_write_offset_f2_pof_add(stream* s, int64_t val, +inline void io_write_offset_f2_pof_add(stream* s, ssize_t val, int32_t offset, vector_size_t* pof) { if (val) val += offset; @@ -39,7 +39,7 @@ inline void io_write_offset_f2_pof_add(stream* s, int64_t val, io_write_int32_t_stream_reverse_endianness(s, (int32_t)val); } -inline void io_write_offset_x_pof_add(stream* s, int64_t val, vector_size_t* pof) { +inline void io_write_offset_x_pof_add(stream* s, ssize_t val, vector_size_t* pof) { io_align_write(s, 0x08); pof_add(s, pof, 0); io_write_int64_t_stream_reverse_endianness(s, val); @@ -49,9 +49,7 @@ inline void pof_add(stream* s, vector_size_t* pof, size_t offset) { if (!s || !pof) return; - size_t position = io_get_position(s); - position += offset; - vector_size_t_push_back(pof, &position); + *vector_size_t_reserve_back(pof) = io_get_position(s) + offset; } void pof_read(stream* s, vector_size_t* pof, bool shift_x) { @@ -60,12 +58,12 @@ void pof_read(stream* s, vector_size_t* pof, bool shift_x) { uint8_t bit_shift; pof_value_type value; - vector_size_t_free(pof); + vector_size_t_free(pof, 0); length = pof_read_offsets_count(s); bit_shift = (uint8_t)(shift_x ? 3 : 2); - l = io_read_uint32_t(s) - 4LL; + l = io_read_uint32_t(s) - 4ULL; p = vector_empty(size_t); vector_size_t_reserve(&p, length); @@ -181,7 +179,7 @@ static size_t pof_read_offsets_count(stream* s) { size_t i, j, l; pof_value_type val; - l = io_read_uint32_t(s) - 4LL; + l = io_read_uint32_t(s) - 4ULL; i = 0; j = 0; while (i < l) { diff --git a/src/KKdLib/f2_pof.h b/src/KKdLib/f2/pof.h similarity index 63% rename from src/KKdLib/f2_pof.h rename to src/KKdLib/f2/pof.h index 60728253..5a8def99 100644 --- a/src/KKdLib/f2_pof.h +++ b/src/KKdLib/f2/pof.h @@ -5,15 +5,15 @@ #pragma once -#include "default.h" -#include "io_stream.h" -#include "vector.h" +#include "../default.h" +#include "../vector.h" +#include "../io/stream.h" -extern void io_write_offset_pof_add(stream* s, int64_t val, +extern void io_write_offset_pof_add(stream* s, ssize_t val, int32_t offset, bool is_x, vector_size_t* pof); -extern void io_write_offset_f2_pof_add(stream* s, int64_t val, +extern void io_write_offset_f2_pof_add(stream* s, ssize_t val, int32_t offset, vector_size_t* pof); -extern void io_write_offset_x_pof_add(stream* s, int64_t val, vector_size_t* pof); +extern void io_write_offset_x_pof_add(stream* s, ssize_t val, vector_size_t* pof); extern void pof_add(stream* s, vector_size_t* pof, size_t offset); extern void pof_read(stream* s, vector_size_t* pof, bool shift_x); extern void pof_write(stream* s, vector_size_t* pof, bool shift_x); diff --git a/src/KKdLib/f2_struct.c b/src/KKdLib/f2/struct.c similarity index 92% rename from src/KKdLib/f2_struct.c rename to src/KKdLib/f2/struct.c index b6bc30c9..fc6341ac 100644 --- a/src/KKdLib/f2_struct.c +++ b/src/KKdLib/f2/struct.c @@ -3,9 +3,10 @@ GitHub/GitLab: korenkonder */ -#include "f2_struct.h" -#include "io_path.h" -#include "io_stream.h" +#include "struct.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../divafile.h" vector_func(f2_struct) @@ -15,28 +16,14 @@ static void f2_struct_get_length(f2_struct* s, bool shift_x); static void f2_struct_write_pof(stream* s, vector_size_t* pof, uint32_t depth, bool shift_x); static void f2_struct_write_enrs(stream* s, vector_enrs_entry* enrs, uint32_t depth); -void f2_struct_free(f2_struct* st) { - if (st->data) - free(st->data); - st->length = 0; - if (st->pof.begin) - vector_size_t_free(&st->pof); - if (st->enrs.begin) - enrs_free(&st->enrs); - if (st->sub_structs.begin) { - for (f2_struct* i = st->sub_structs.begin; i != st->sub_structs.end; i++) - f2_struct_free(i); - vector_f2_struct_free(&st->sub_structs); - } - memset(st, 0, sizeof(f2_struct)); -} - void f2_struct_read(f2_struct* st, char* path) { memset(st, 0, sizeof(f2_struct)); stream s; io_open(&s, path, "rb"); if (&s.io.stream) { + divafile_sdecrypt(&s); + f2_header h; f2_header_read(&s, &h); f2_struct_read_data(&s, st, &h); @@ -50,6 +37,8 @@ void f2_struct_wread(f2_struct* st, wchar_t* path) { stream s; io_wopen(&s, path, L"rb"); if (&s.io.stream) { + divafile_sdecrypt(&s); + f2_header h; f2_header_read(&s, &h); f2_struct_read_data(&s, st, &h); @@ -63,6 +52,8 @@ void f2_struct_mread(f2_struct* st, void* data, size_t length) { stream s; io_mopen(&s, data, length); if (&s.io.data.data) { + divafile_sdecrypt(&s); + f2_header h; f2_header_read(&s, &h); f2_struct_read_data(&s, st, &h); @@ -74,6 +65,8 @@ void f2_struct_sread(f2_struct* st, stream* s) { memset(st, 0, sizeof(f2_struct)); if (s->io.stream || s->io.data.data) { + divafile_sdecrypt(s); + f2_header h; f2_header_read(s, &h); f2_struct_read_data(s, st, &h); @@ -120,6 +113,19 @@ void f2_struct_swrite(f2_struct* st, stream* s, bool use_depth, bool shift_x) { } } +void f2_struct_free(f2_struct* st) { + if (st->data) + free(st->data); + st->length = 0; + if (st->pof.begin) + vector_size_t_free(&st->pof, 0); + if (st->enrs.begin) + enrs_free(&st->enrs); + if (st->sub_structs.begin) + vector_f2_struct_free(&st->sub_structs, f2_struct_free); + memset(st, 0, sizeof(f2_struct)); +} + static void f2_struct_get_length(f2_struct* s, bool shift_x) { bool has_enrs, has_pof, has_sub_structs; f2_struct* i; @@ -191,14 +197,13 @@ static void f2_struct_read_data(stream* s, f2_struct* st, f2_header* h) { io_set_position(s, pos + l, SEEK_SET); } else { - f2_struct str; - f2_struct_read_data(s, &str, h); - vector_f2_struct_push_back(&st->sub_structs, &str); + f2_struct* s_st = vector_f2_struct_reserve_back(&st->sub_structs); + f2_struct_read_data(s, s_st, h); } } if (st->sub_structs.end - st->sub_structs.begin < 1) - vector_f2_struct_free(&st->sub_structs); + vector_f2_struct_free(&st->sub_structs, f2_struct_free); } static void f2_struct_write_inner(stream* s, f2_struct* st, uint32_t depth, bool use_depth, bool shift_x) { diff --git a/src/KKdLib/f2_struct.h b/src/KKdLib/f2/struct.h similarity index 85% rename from src/KKdLib/f2_struct.h rename to src/KKdLib/f2/struct.h index 8f6e0cfa..702475b8 100644 --- a/src/KKdLib/f2_struct.h +++ b/src/KKdLib/f2/struct.h @@ -5,11 +5,11 @@ #pragma once -#include "default.h" -#include "f2_enrs.h" -#include "f2_header.h" -#include "f2_pof.h" -#include "vector.h" +#include "../default.h" +#include "../vector.h" +#include "enrs.h" +#include "header.h" +#include "pof.h" typedef struct f2_struct f2_struct; @@ -25,7 +25,6 @@ struct f2_struct { vector_size_t pof; }; -extern void f2_struct_free(f2_struct* s); extern void f2_struct_read(f2_struct* st, char* path); extern void f2_struct_wread(f2_struct* st, wchar_t* path); extern void f2_struct_mread(f2_struct* st, void* data, size_t length); @@ -34,3 +33,4 @@ extern void f2_struct_write(f2_struct* st, char* path, bool use_depth, bool shif extern void f2_struct_wwrite(f2_struct* st, wchar_t* path, bool use_depth, bool shift_x); extern void f2_struct_mwrite(f2_struct* st, void** data, size_t* length, bool use_depth, bool shift_x); extern void f2_struct_swrite(f2_struct* st, stream* s, bool use_depth, bool shift_x); +extern void f2_struct_free(f2_struct* st); diff --git a/src/KKdLib/farc.c b/src/KKdLib/farc.c index 896805f3..d385ed56 100644 --- a/src/KKdLib/farc.c +++ b/src/KKdLib/farc.c @@ -4,9 +4,9 @@ */ #include "farc.h" +#include "io/path.h" #include "aes.h" -#include "io_deflate.h" -#include "io_path.h" +#include "deflate.h" #include "str_utils.h" static const char key[] = { @@ -27,10 +27,9 @@ static errno_t farc_read_header(farc* f, stream* s); static void farc_unpack_files(farc* f, stream* s, bool save); static void farc_unpack_file(farc* f, stream* s, farc_file* ff); -farc* farc_init() { - farc* f = force_malloc(sizeof(farc)); +void farc_init(farc* f) { + memset(f, 0, sizeof(farc)); f->compression_level = 12; - return f; } void farc_read(farc* f, char* path, bool unpack, bool save) { @@ -46,14 +45,8 @@ void farc_wread(farc* f, wchar_t* path, bool unpack, bool save) { if (!f || !path) return; - for (farc_file* i = f->files.begin; i != f->files.end; i++) { - string_free(&i->name); - free(i->data); - free(i->data_compressed); - } - int32_t compression_level = f->compression_level; - vector_farc_file_free(&f->files); + vector_farc_file_free(&f->files, farc_file_free); memset(f, 0, sizeof(farc)); f->compression_level = compression_level; @@ -66,11 +59,11 @@ void farc_wread(farc* f, wchar_t* path, bool unpack, bool save) { return; size_t full_path_buf_len = utf16_length(full_path_buf); - wcsncpy_s(f->file_path, MAX_PATH, full_path_buf, full_path_buf_len + 1); - wcsncpy_s(f->directory_path, MAX_PATH, full_path_buf, full_path_buf_len + 1); + wcsncpy_s(f->file_path, MAX_PATH, full_path_buf, full_path_buf_len); + wcsncpy_s(f->directory_path, MAX_PATH, full_path_buf, full_path_buf_len); wchar_t* dot = wcsrchr(f->directory_path, L'.'); if (dot) - memset(dot, 0, utf16_length(dot) * 2 + 2); + memset(dot, 0, utf16_length(dot) * 2 - 2); stream s; io_wopen(&s, f->file_path, L"rb"); @@ -79,12 +72,31 @@ void farc_wread(farc* f, wchar_t* path, bool unpack, bool save) { io_free(&s); } +void farc_mread(farc* f, void* data, size_t length, bool unpack) { + if (!f || !data || !length) + return; + + int32_t compression_level = f->compression_level; + vector_farc_file_free(&f->files, farc_file_free); + memset(f, 0, sizeof(farc)); + f->compression_level = compression_level; + + wcsncpy_s(f->file_path, MAX_PATH, L"", 0); + wcsncpy_s(f->directory_path, MAX_PATH, L"", 0); + + stream s; + io_mopen(&s, data, length); + if (!farc_read_header(f, &s) && unpack) + farc_unpack_files(f, &s, false); + io_free(&s); +} + farc_file* farc_read_file(farc* f, char* name) { if (!f || !name) return 0; for (farc_file* i = f->files.begin; i != f->files.end; i++) { - if (strcmp(string_data(&i->name), name)) + if (str_utils_compare(string_data(&i->name), name)) continue; if (!i->data && i->data_compressed) @@ -108,7 +120,7 @@ farc_file* farc_wread_file(farc* f, wchar_t* name) { char* name_temp = utf16_to_utf8(name); for (farc_file* i = f->files.begin; i != f->files.end; i++) { - if (strcmp(string_data(&i->name), name_temp)) + if (str_utils_compare(string_data(&i->name), name_temp)) continue; if (!i->data) { @@ -139,14 +151,8 @@ void farc_wwrite(farc* f, wchar_t* path, farc_compress_mode mode, bool get_files return; if (get_files) { - for (farc_file* i = f->files.begin; i != f->files.end; i++) { - string_free(&i->name); - free(i->data); - free(i->data_compressed); - } - int32_t compression_level = f->compression_level; - vector_farc_file_free(&f->files); + vector_farc_file_free(&f->files, farc_file_free); memset(f, 0, sizeof(farc)); f->compression_level = compression_level; } @@ -160,8 +166,8 @@ void farc_wwrite(farc* f, wchar_t* path, farc_compress_mode mode, bool get_files return; size_t full_path_buf_len = utf16_length(full_path_buf); - wcsncpy_s(f->directory_path, MAX_PATH, full_path_buf, full_path_buf_len + 1); - wcsncpy_s(f->file_path, MAX_PATH, full_path_buf, full_path_buf_len + 1); + wcsncpy_s(f->directory_path, MAX_PATH, full_path_buf, full_path_buf_len); + wcsncpy_s(f->file_path, MAX_PATH, full_path_buf, full_path_buf_len); wcsncat_s(f->file_path, MAX_PATH, L".farc", 6); if (!get_files || (get_files && !farc_get_files(f))) { @@ -173,33 +179,62 @@ void farc_wwrite(farc* f, wchar_t* path, farc_compress_mode mode, bool get_files } } -void farc_dispose(farc* f) { +void farc_mwrite(farc* f, void** data, size_t* length, farc_compress_mode mode) { + if (!f || !data || !length) + return; + + wcsncpy_s(f->directory_path, MAX_PATH, L"", 0); + wcsncpy_s(f->file_path, MAX_PATH, L"", 0); + + stream s; + io_mopen(&s, 0, 0); + farc_pack_files(f, &s, mode, false); + io_free(&s); +} + +bool farc_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + if (file_len >= 5 && memcmp(&file[file_len - 5], ".farc", 6)) + return false; + + size_t path_len = utf8_length(path); + if (path_len + file_len + 2 > 0x1000) + return false; + + char buf[0x1000]; + memcpy(buf, path, path_len); + memcpy(buf + path_len, file, file_len + 1); + if (!path_check_file_exists(buf)) + return false; + + farc* f = data; + farc_read(f, buf, true, false); + bool ret = f->files.end - f->files.begin ? true : false; + if (!ret) + farc_free(f); + return ret; +} + +void farc_free(farc* f) { if (!f) return; - for (farc_file* i = f->files.begin; i != f->files.end; i++) { - string_free(&i->name); - free(i->data); - free(i->data_compressed); - } + vector_farc_file_free(&f->files, farc_file_free); +} - vector_farc_file_free(&f->files); - free(f); +extern void farc_file_free(farc_file* ff) { + string_free(&ff->name); + free(ff->data); + free(ff->data_compressed); } static errno_t farc_get_files(farc* f) { - for (farc_file* i = f->files.begin; i != f->files.end; i++) { - string_free(&i->name); - free(i->data); - free(i->data_compressed); - } - - vector_farc_file_free(&f->files); + vector_farc_file_free(&f->files, farc_file_free); vector_wstring files = vector_empty(wstring); path_wget_files(&files, f->directory_path); if (files.end - files.begin < 1) { - vector_wstring_free(&files); + vector_wstring_free(&files, wstring_free); return -1; } @@ -211,9 +246,7 @@ static errno_t farc_get_files(farc* f) { string_copy_wstring(&files.begin[i - f->files.begin], &i->name); } - for (wstring* i = files.begin; i != files.end; i++) - wstring_free(i); - vector_wstring_free(&files); + vector_wstring_free(&files, wstring_free); return 0; } @@ -221,9 +254,9 @@ static void farc_pack_files(farc* f, stream* s, farc_compress_mode mode, bool ge bool plain = false; for (farc_file* i = f->files.begin; i != f->files.end; i++) { char* ext = str_utils_get_extension(string_data(&i->name)); - bool is_a3da = strcmp(ext, ".a3da") == 0; - bool is_diva = strcmp(ext, ".diva") == 0; - bool is_vag = strcmp(ext, ".vag") == 0; + bool is_a3da = str_utils_compare(ext, ".a3da") == 0; + bool is_diva = str_utils_compare(ext, ".diva") == 0; + bool is_vag = str_utils_compare(ext, ".vag") == 0; free(ext); if (is_a3da || is_diva || is_vag) { @@ -237,16 +270,16 @@ static void farc_pack_files(farc* f, stream* s, farc_compress_mode mode, bool ge switch (mode) { case FARC_COMPRESS_FARC_GZIP: - f->type = FARC_DATA_TYPE_GZIP; + f->flags = FARC_GZIP; break; case FARC_COMPRESS_FARC_AES: - f->type = FARC_DATA_TYPE_AES; + f->flags = FARC_AES; break; case FARC_COMPRESS_FARC_GZIP_AES: - f->type = FARC_DATA_TYPE_GZIP | FARC_DATA_TYPE_AES; + f->flags = FARC_GZIP | FARC_AES; break; default: - f->type = 0; + f->flags = 0; break; } @@ -265,12 +298,12 @@ static void farc_pack_files(farc* f, stream* s, farc_compress_mode mode, bool ge if (mode == FARC_COMPRESS_FArc) for (farc_file* i = f->files.begin; i != f->files.end; i++) { - header_length += string_length(&i->name) + 1; + header_length += i->name.length + 1; header_length += sizeof(int32_t) * 2; } else for (farc_file* i = f->files.begin; i != f->files.end; i++) { - header_length += string_length(&i->name) + 1; + header_length += i->name.length + 1; header_length += sizeof(int32_t) * 3; } @@ -442,7 +475,7 @@ static void farc_pack_files(farc* f, stream* s, farc_compress_mode mode, bool ge case FARC_COMPRESS_FARC_GZIP_AES: io_write_int32_t_reverse_endianness(s, FARC_FARC, true); io_write_int32_t_reverse_endianness(s, (int32_t)header_length, true); - io_write_int32_t_reverse_endianness(s, f->type, true); + io_write_int32_t_reverse_endianness(s, f->flags, true); io_write_int32_t_reverse_endianness(s, 0x00, true); io_write_int32_t_reverse_endianness(s, 0x40, true); io_write_int32_t_reverse_endianness(s, 0x00, true); @@ -490,11 +523,11 @@ static errno_t farc_read_header(farc* f, stream* s) { int32_t header_length = io_read_int32_t_reverse_endianness(s, true); if (f->signature == FARC_FARC) { - f->type = io_read_int32_t_reverse_endianness(s, true); + f->flags = io_read_int32_t_reverse_endianness(s, true); io_read_int32_t(s); int32_t farc_mode = io_read_int32_t_reverse_endianness(s, true); - f->ft = (f->type & FARC_DATA_TYPE_AES) && (farc_mode & (farc_mode - 1)); + f->ft = (f->flags & FARC_AES) && (farc_mode & (farc_mode - 1)); if (f->ft) { header_length -= 0x08; io_set_position(s, -0x04, SEEK_CUR); @@ -503,12 +536,7 @@ static errno_t farc_read_header(farc* f, stream* s) { header_length -= 0x0C; } - for (farc_file* i = f->files.begin; i != f->files.end; i++) { - string_free(&i->name); - free(i->data); - free(i->data_compressed); - } - vector_farc_file_free(&f->files); + vector_farc_file_free(&f->files, farc_file_free); uint8_t* d_t; uint8_t* dt; @@ -562,7 +590,7 @@ static errno_t farc_read_header(farc* f, stream* s) { if (has_per_file_flags) for (farc_file* i = f->files.begin; i != f->files.end; i++) { string_init(&i->name, dt); - dt += string_length(&i->name) + 1; + dt += i->name.length + 1; i->offset = (size_t)load_reverse_endianness_int32_t((void*)dt); i->size_compressed = (size_t)load_reverse_endianness_int32_t((void*)(dt + 4)); i->size = (size_t)load_reverse_endianness_int32_t((void*)(dt + 8)); @@ -572,7 +600,7 @@ static errno_t farc_read_header(farc* f, stream* s) { else if (f->signature != FARC_FArc) for (farc_file* i = f->files.begin; i != f->files.end; i++) { string_init(&i->name, dt); - dt += string_length(&i->name) + 1; + dt += i->name.length + 1; i->offset = (size_t)load_reverse_endianness_int32_t((void*)dt); i->size_compressed = (size_t)load_reverse_endianness_int32_t((void*)(dt + 4)); i->size = (size_t)load_reverse_endianness_int32_t((void*)(dt + 8)); @@ -581,7 +609,7 @@ static errno_t farc_read_header(farc* f, stream* s) { else for (farc_file* i = f->files.begin; i != f->files.end; i++) { string_init(&i->name, dt); - dt += string_length(&i->name) + 1; + dt += i->name.length + 1; i->offset = (size_t)load_reverse_endianness_int32_t((void*)dt); i->size = (size_t)load_reverse_endianness_int32_t((void*)(dt + 4)); dt += sizeof(int32_t) * 2; @@ -660,8 +688,8 @@ static void farc_unpack_file(farc* f, stream* s, farc_file* ff) { } } else { - bool aes = (f->type | ff->type) & FARC_DATA_TYPE_AES; - bool gzip = (f->type | ff->type) & FARC_DATA_TYPE_GZIP; + bool aes = (f->flags | ff->type) & FARC_AES; + bool gzip = (f->flags | ff->type) & FARC_GZIP; if (!aes && !gzip) { ff->data_compressed = 0; ff->data = force_malloc(ff->size); diff --git a/src/KKdLib/farc.h b/src/KKdLib/farc.h index 4a13b1ef..60b25f89 100644 --- a/src/KKdLib/farc.h +++ b/src/KKdLib/farc.h @@ -6,7 +6,7 @@ #pragma once #include "default.h" -#include "io_stream.h" +#include "io/stream.h" #include "vector.h" typedef enum farc_signature { @@ -15,10 +15,10 @@ typedef enum farc_signature { FARC_FARC = 'FARC', } farc_signature; -typedef enum farc_data_type { - FARC_DATA_TYPE_GZIP = 0x2, - FARC_DATA_TYPE_AES = 0x4, -} farc_data_type; +typedef enum farc_flags { + FARC_GZIP = 0x02, + FARC_AES = 0x04, +} farc_flags; typedef enum farc_compress_mode { FARC_COMPRESS_FArc = 0, @@ -36,7 +36,7 @@ typedef struct farc_file { string name; void* data; void* data_compressed; - farc_data_type type; + farc_flags type; bool data_changed; } farc_file; @@ -47,16 +47,21 @@ typedef struct farc { wchar_t directory_path[MAX_PATH]; vector_farc_file files; farc_signature signature; - farc_data_type type; + farc_flags flags; int32_t compression_level; bool ft; } farc; -extern farc* farc_init(); +extern void farc_init(farc* f); extern void farc_read(farc* f, char* path, bool unpack, bool save); extern void farc_wread(farc* f, wchar_t* path, bool unpack, bool save); +extern void farc_mread(farc* f, void* data, size_t length, bool unpack); extern farc_file* farc_read_file(farc* f, char* name); extern farc_file* farc_wread_file(farc* f, wchar_t* name); extern void farc_write(farc* f, char* path, farc_compress_mode mode, bool get_files); extern void farc_wwrite(farc* f, wchar_t* path, farc_compress_mode mode, bool get_files); -extern void farc_dispose(farc* f); +extern void farc_mwrite(farc* f, void** data, size_t* length, farc_compress_mode mode); +extern bool farc_load_file(void* data, char* path, char* file, uint32_t hash); +extern void farc_free(farc* f); + +extern void farc_file_free(farc_file* ff); diff --git a/src/KKdLib/half_t.c b/src/KKdLib/half_t.c index 29db3f60..40de524b 100644 --- a/src/KKdLib/half_t.c +++ b/src/KKdLib/half_t.c @@ -5,6 +5,11 @@ #include "half_t.h" +vector_func(half_t) +vector_ptr_func(half_t) + +// Crutch for vector_func definition + inline half_t load_reverse_endianness_half_t(void* ptr) { return (half_t)_byteswap_ushort(*(uint16_t*)ptr); } diff --git a/src/KKdLib/half_t.h b/src/KKdLib/half_t.h index 630f548d..7625f15a 100644 --- a/src/KKdLib/half_t.h +++ b/src/KKdLib/half_t.h @@ -6,6 +6,7 @@ #pragma once #include "default.h" +#include "vector.h" #define FLOAT16_NAN ((half_t)0x7FFF) #define FLOAT16_POSITIVE_NAN ((half_t)0x7FFF) @@ -20,6 +21,9 @@ typedef unsigned short half_t; +vector(half_t) +vector_ptr(half_t) + extern half_t load_reverse_endianness_half_t(void* ptr); extern void store_reverse_endianness_half_t(half_t value, void* ptr); extern half_t reverse_endianness_half_t(half_t value); diff --git a/src/KKdLib/hash.c b/src/KKdLib/hash.c index 92a8220f..7771531b 100644 --- a/src/KKdLib/hash.c +++ b/src/KKdLib/hash.c @@ -5,35 +5,60 @@ #include "hash.h" -const uint64_t hash_fnv1a64_empty = 0xCBF29CE44FD0BFC1; +const uint64_t hash_fnv1a64m_empty = 0xCBF29CE44FD0BFC1; const uint32_t hash_murmurhash_empty = 0x0CAD3078; -uint64_t hash_fnv1a64(uint8_t* data, size_t length) { // 0x1403B04D0 in SBZV_7.10; FNV 1a 64-bit +inline uint64_t hash_fnv1a64m(uint8_t* data, size_t length) { // 0x1403B04D0 in SBZV_7.10; FNV 1a 64-bit Modified uint64_t hash = 0xCBF29CE484222325; if (data) for (size_t i = 0; i < length; i++) { hash ^= data[i]; hash *= 0x100000001B3; } - return (hash >> 32) ^ hash; + return (hash >> 32) ^ hash; // Actual Modification } -inline uint64_t hash_utf8_fnv1a64(char* data) { - uint64_t hash = hash_fnv1a64((uint8_t*)data, utf8_length(data)); +inline uint64_t hash_utf8_fnv1a64m(char* data) { + uint64_t hash = hash_fnv1a64m((uint8_t*)data, utf8_length(data)); return hash; } -inline uint64_t hash_utf16_fnv1a64(wchar_t* data) { +inline uint64_t hash_utf16_fnv1a64m(wchar_t* data) { char* temp = utf16_to_utf8(data); - uint64_t hash = hash_fnv1a64((uint8_t*)temp, utf8_length(temp)); + uint64_t hash = hash_fnv1a64m((uint8_t*)temp, utf8_length(temp)); + free(temp); + return hash; +} + +inline uint64_t hash_fnv1a64m_upper(uint8_t* data, size_t length) { // FNV 1a 64-bit Modified; Always Upper + uint64_t hash = 0xCBF29CE484222325; + if (data) + for (size_t i = 0; i < length; i++) { + uint8_t a = data[i]; + if (a > 0x60 && a < 0x7B) + a -= 0x20; + hash ^= a; + hash *= 0x100000001B3; + } + return (hash >> 32) ^ hash; // Actual Modification +} + +inline uint64_t hash_utf8_fnv1a64m_upper(char* data) { + uint64_t hash = hash_fnv1a64m_upper((uint8_t*)data, utf8_length(data)); + return hash; +} + +inline uint64_t hash_utf16_fnv1a64m_upper(wchar_t* data) { + char* temp = utf16_to_utf8(data); + uint64_t hash = hash_fnv1a64m_upper((uint8_t*)temp, utf8_length(temp)); free(temp); return hash; } uint32_t hash_murmurhash(uint8_t* data, size_t length, - uint32_t seed, bool already_upper, bool big_endian) { // 0x814D7A9C in PCSB00554; MurmurHash - // 0x8134C304 in PCSB01007 - // 0x0069CEA4 in NPEB02013 + uint32_t seed, bool upper, bool big_endian) { // 0x814D7A9C in PCSB00554; MurmurHash + // 0x8134C304 in PCSB01007 + // 0x0069CEA4 in NPEB02013 uint32_t a, b, hash; size_t i; @@ -42,7 +67,7 @@ uint32_t hash_murmurhash(uint8_t* data, size_t length, hash = seed + 0xDEADBEEF; if (data) - if (already_upper) { + if (upper) { if (big_endian) for (i = 0; length > 3; length -= 4, i += 4) { b = load_reverse_endianness_uint32_t(&data[i]); @@ -159,14 +184,14 @@ uint32_t hash_murmurhash(uint8_t* data, size_t length, return hash; } -inline uint32_t hash_utf8_murmurhash(char* data, uint32_t seed, bool already_upper) { - uint32_t hash = hash_murmurhash((uint8_t*)data, utf8_length(data), seed, already_upper, false); +inline uint32_t hash_utf8_murmurhash(char* data, uint32_t seed, bool upper) { + uint32_t hash = hash_murmurhash((uint8_t*)data, utf8_length(data), seed, upper, false); return hash; } -inline uint32_t hash_utf16_murmurhash(wchar_t* data, uint32_t seed, bool already_upper) { +inline uint32_t hash_utf16_murmurhash(wchar_t* data, uint32_t seed, bool upper) { char* temp = utf16_to_utf8(data); - uint32_t hash = hash_murmurhash((uint8_t*)temp, utf8_length(temp), seed, already_upper, false); + uint32_t hash = hash_murmurhash((uint8_t*)temp, utf8_length(temp), seed, upper, false); free(temp); return hash; } diff --git a/src/KKdLib/hash.h b/src/KKdLib/hash.h index c7150c86..9ee37959 100644 --- a/src/KKdLib/hash.h +++ b/src/KKdLib/hash.h @@ -7,12 +7,15 @@ #include "default.h" -extern const uint64_t hash_fnv1a64_empty; +extern const uint64_t hash_fnv1a64m_empty; extern const uint32_t hash_murmurhash_empty; -extern uint64_t hash_fnv1a64(uint8_t* data, size_t length); -extern uint64_t hash_utf8_fnv1a64(char* data); -extern uint64_t hash_utf16_fnv1a64(wchar_t* data); -extern uint32_t hash_murmurhash(uint8_t* data, size_t length, uint32_t seed, bool already_upper, bool big_endian); -extern uint32_t hash_utf8_murmurhash(char* data, uint32_t seed, bool already_upper); -extern uint32_t hash_utf16_murmurhash(wchar_t* data, uint32_t seed, bool already_upper); +extern uint64_t hash_fnv1a64m(uint8_t* data, size_t length); +extern uint64_t hash_utf8_fnv1a64m(char* data); +extern uint64_t hash_utf16_fnv1a64m(wchar_t* data); +extern uint64_t hash_fnv1a64m_upper(uint8_t* data, size_t length); +extern uint64_t hash_utf8_fnv1a64m_upper(char* data); +extern uint64_t hash_utf16_fnv1a64m_upper(wchar_t* data); +extern uint32_t hash_murmurhash(uint8_t* data, size_t length, uint32_t seed, bool upper, bool big_endian); +extern uint32_t hash_utf8_murmurhash(char* data, uint32_t seed, bool upper); +extern uint32_t hash_utf16_murmurhash(wchar_t* data, uint32_t seed, bool upper); diff --git a/src/KKdLib/io_json.c b/src/KKdLib/io/json.c similarity index 96% rename from src/KKdLib/io_json.c rename to src/KKdLib/io/json.c index a27172b1..ad298770 100644 --- a/src/KKdLib/io_json.c +++ b/src/KKdLib/io/json.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "io_json.h" +#include "json.h" #define IO_JSON_READ_BUF_SIZE 0x200 @@ -197,17 +197,17 @@ static void io_json_read_float(stream* s, io_json_read_buffer* buf, char* name, if (sscanf_s(dig_buf, "%lli", &val) == EOF) return; - if (val >= 0 && val < 0x0100) + if (val >= 0x00 && val < 0xFF) msgpack_set_uint8_t(msg, name, (uint8_t)val); - else if (val >= -0x80 && val < 0x80) + else if (val >= (int8_t)0x80 && val <= (int8_t)0x7F) msgpack_set_int8_t(msg, name, (int8_t)val); - else if (val >= 0 && val < 0x10000) + else if (val >= 0x0000 && val < 0xFFFF) msgpack_set_uint16_t(msg, name, (uint16_t)val); - else if (val >= -0x8000 && val < 0x8000) + else if (val >= (int16_t)0x8000 && val <= (int16_t)0x7FFF) msgpack_set_int16_t(msg, name, (int16_t)val); - else if (val >= 0 && val < 0x100000000) + else if (val >= 0x00000000 && val <= 0xFFFFFFFF) msgpack_set_uint32_t(msg, name, (uint32_t)val); - else if (val >= -0x80000000LL && val < 0x80000000) + else if (val >= (int32_t)0x80000000 && val <= (int32_t)0x7FFFFFFF) msgpack_set_int32_t(msg, name, (int32_t)val); else msgpack_set_int64_t(msg, name, val); @@ -413,9 +413,8 @@ static void io_json_read_map(stream* s, io_json_read_buffer* buf, char* name, ms } io_json_read_skip_whitespace(s, buf, c); - msgpack m; - io_json_read_inner(s, buf, key, &m, c); - vector_msgpack_push_back(&map, &m); + msgpack* m = vector_msgpack_reserve_back(&map); + io_json_read_inner(s, buf, key, m, c); free(key); io_json_read_skip_whitespace(s, buf, c); @@ -451,9 +450,8 @@ static void io_json_read_array(stream* s, io_json_read_buffer* buf, char* name, if (*c == ']') break; - msgpack m; - io_json_read_inner(s, buf, 0, &m, c); - vector_msgpack_push_back(&array, &m); + msgpack* m = vector_msgpack_reserve_back(&array); + io_json_read_inner(s, buf, 0, m, c); io_json_read_skip_whitespace(s, buf, c); @@ -520,7 +518,7 @@ void io_json_write_inner(stream* s, msgpack* msg, size_t tabs) { for (size_t i = 0; i < tabs; i++) io_write(s, " ", 2); - if (string_length(&msg->name)) { + if (msg->name.length) { io_json_write_string(s, &msg->name); io_write(s, ": ", 2); } @@ -529,7 +527,7 @@ void io_json_write_inner(stream* s, msgpack* msg, size_t tabs) { case MSGPACK_NULL: io_json_write_null(s); break; - case MSGPACK_BOOL: + case MSGPACK_bool: io_json_write_bool(s, *MSGPACK_SELECT_PTR(bool, msg)); break; case MSGPACK_INT8: { @@ -677,7 +675,7 @@ static void io_json_write_string(stream* s, string* val) { io_write_char(s, '\"'); char* str = string_data(val); - size_t len = string_length(val); + size_t len = val->length; for (size_t i = 0; i < len; i++) { char c = str[i]; if (c == 0x22) diff --git a/src/KKdLib/io_json.h b/src/KKdLib/io/json.h similarity index 72% rename from src/KKdLib/io_json.h rename to src/KKdLib/io/json.h index 9742cd27..6da6e7cc 100644 --- a/src/KKdLib/io_json.h +++ b/src/KKdLib/io/json.h @@ -5,9 +5,9 @@ #pragma once -#include "default.h" -#include "io_stream.h" -#include "msgpack.h" +#include "../default.h" +#include "../msgpack.h" +#include "stream.h" extern void io_json_read(stream* s, msgpack* msg); extern void io_json_write(stream* s, msgpack* msg); diff --git a/src/KKdLib/io_msgpack.c b/src/KKdLib/io/msgpack.c similarity index 96% rename from src/KKdLib/io_msgpack.c rename to src/KKdLib/io/msgpack.c index 1f6b0f87..fd24cad4 100644 --- a/src/KKdLib/io_msgpack.c +++ b/src/KKdLib/io/msgpack.c @@ -3,7 +3,7 @@ GitHub/GitLab: korenkonder */ -#include "io_msgpack.h" +#include "msgpack.h" static void io_msgpack_read_inner(stream* s, char* name, msgpack* msg); static void io_msgpack_read_string(stream* s, char* name, msgpack* msg, size_t length); @@ -68,13 +68,13 @@ static void io_msgpack_read_inner(stream* s, char* name, msgpack* msg) { io_set_position(s, io_read_uint32_t_reverse_endianness(s, true), SEEK_CUR); break; case 0xC7: - io_set_position(s, io_read_uint8_t(s) + 1LL, SEEK_CUR); + io_set_position(s, io_read_uint8_t(s) + 1ULL, SEEK_CUR); break; case 0xC8: - io_set_position(s, io_read_uint16_t_reverse_endianness(s, true) + 1LL, SEEK_CUR); + io_set_position(s, io_read_uint16_t_reverse_endianness(s, true) + 1ULL, SEEK_CUR); break; case 0xC9: - io_set_position(s, io_read_uint32_t_reverse_endianness(s, true) + 1LL, SEEK_CUR); + io_set_position(s, io_read_uint32_t_reverse_endianness(s, true) + 1ULL, SEEK_CUR); break; case 0xCA: msgpack_set_float_t(msg, name, io_read_float_t_reverse_endianness(s, true)); @@ -146,12 +146,10 @@ static void io_msgpack_read_inner(stream* s, char* name, msgpack* msg) { } static void io_msgpack_read_string(stream* s, char* name, msgpack* msg, size_t length) { - char* temp = force_malloc(length + 1); - io_read(s, temp, length); - temp[length] = 0; - - msgpack_set_utf8_string(msg, name, temp); - free(temp); + string str; + io_read_string(s, &str, length); + msgpack_set_string(msg, name, &str); + string_free(&str); } static void io_msgpack_read_array(stream* s, char* name, msgpack* msg, size_t length) { @@ -179,9 +177,8 @@ static void io_msgpack_read_map(stream* s, char* name, msgpack* msg, size_t leng if (t_m.type == MSGPACK_STRING) n = string_data(MSGPACK_SELECT(string, t_m)); - msgpack m; - io_msgpack_read_inner(s, n, &m); - vector_msgpack_push_back(ptr, &m); + msgpack* m = vector_msgpack_reserve_back(ptr); + io_msgpack_read_inner(s, n, m); msgpack_free(&t_m); } msgpack_set_map(msg, name, ptr); @@ -196,14 +193,14 @@ void io_msgpack_write(stream* s, msgpack* msg) { } static void io_msgpack_write_inner(stream* s, msgpack* msg) { - if (string_length(&msg->name)) + if (msg->name.length) io_msgpack_write_string(s, &msg->name); switch (msg->type) { case MSGPACK_NULL: io_msgpack_write_null(s); break; - case MSGPACK_BOOL: + case MSGPACK_bool: io_msgpack_write_bool(s, *MSGPACK_SELECT_PTR(bool, msg)); break; case MSGPACK_INT8: { @@ -368,7 +365,7 @@ static void io_msgpack_write_string(stream* s, string* val) { return; } - size_t len = string_length(val); + size_t len = val->length; if (len < 0x20) io_write_uint8_t(s, 0xA0 | (len & 0x1F)); else if (len < 0x100) { diff --git a/src/KKdLib/io_msgpack.h b/src/KKdLib/io/msgpack.h similarity index 72% rename from src/KKdLib/io_msgpack.h rename to src/KKdLib/io/msgpack.h index fa9aa61c..6f92abee 100644 --- a/src/KKdLib/io_msgpack.h +++ b/src/KKdLib/io/msgpack.h @@ -5,9 +5,9 @@ #pragma once -#include "default.h" -#include "io_stream.h" -#include "msgpack.h" +#include "../default.h" +#include "../msgpack.h" +#include "stream.h" extern void io_msgpack_read(stream* s, msgpack* msg); extern void io_msgpack_write(stream* s, msgpack* msg); diff --git a/src/KKdLib/io/path.c b/src/KKdLib/io/path.c new file mode 100644 index 00000000..41194ba2 --- /dev/null +++ b/src/KKdLib/io/path.c @@ -0,0 +1,544 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "path.h" +#include "../str_utils.h" + +bool path_check_path_exists(char* path) { + wchar_t* path_temp = utf8_to_utf16(path); + DWORD ftyp = GetFileAttributesW(path_temp); + free(path_temp); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return true; +} + +bool path_wcheck_path_exists(wchar_t* path) { + DWORD ftyp = GetFileAttributesW(path); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return true; +} + +bool path_check_file_exists(char* path) { + wchar_t* path_temp = utf8_to_utf16(path); + DWORD ftyp = GetFileAttributesW(path_temp); + free(path_temp); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return ftyp & FILE_ATTRIBUTE_DIRECTORY ? false : true; +} + +bool path_wcheck_file_exists(wchar_t* file_path) { + DWORD ftyp = GetFileAttributesW(file_path); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return ftyp & FILE_ATTRIBUTE_DIRECTORY ? false : true; +} + +bool path_check_directory_exists(char* path) { + wchar_t* path_temp = utf8_to_utf16(path); + DWORD ftyp = GetFileAttributesW(path_temp); + free(path_temp); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return ftyp & FILE_ATTRIBUTE_DIRECTORY ? true : false; +} + +bool path_wcheck_directory_exists(wchar_t* path) { + DWORD ftyp = GetFileAttributesW(path); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + else + return ftyp & FILE_ATTRIBUTE_DIRECTORY ? true : false; +} + +void path_get_files(vector_string* files, char* path) { + vector_string_free(files, string_free); + + wchar_t* dir_temp = utf8_to_utf16(path); + size_t dir_len = utf16_length(dir_temp); + if (!dir_temp) + return; + + wchar_t* dir; + if (dir_temp[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + } + free(dir_temp); + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + return; + } + + do { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + char* file_temp = utf16_to_utf8(fdata.cFileName); + string* file = vector_string_reserve_back(files); + string_init(file, file_temp); + free(file_temp); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(dir); +} + +void path_wget_files(vector_wstring* files, wchar_t* path) { + vector_wstring_free(files, wstring_free); + + size_t dir_len = utf16_length(path); + + wchar_t* dir; + if (path[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + } + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + return; + } + + do { + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + wstring* file = vector_wstring_reserve_back(files); + wstring_init(file, fdata.cFileName); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(dir); +} + +void path_get_directories(vector_string* directories, char* path, + char** exclude_list, size_t exclude_count) { + vector_string_free(directories, string_free); + + wchar_t* dir_temp = utf8_to_utf16(path); + size_t dir_len = utf16_length(dir_temp); + if (!dir_temp) + return; + + wchar_t* dir; + wchar_t* temp; + if (dir_temp[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); + memcpy(temp, dir_temp, sizeof(wchar_t) * dir_len); + temp[dir_len] = L'\\'; + dir_len++; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 1 + MAX_PATH); + memcpy(temp, dir_temp, sizeof(wchar_t) * dir_len); + } + free(dir_temp); + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + free(temp); + return; + } + + do { + if (~fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + else if (!str_utils_wcompare(fdata.cFileName, L".") + || !str_utils_wcompare(fdata.cFileName, L"..")) + continue; + + if (exclude_list && exclude_count) { + size_t len = utf16_length(fdata.cFileName); + memcpy(temp + dir_len, fdata.cFileName, sizeof(wchar_t) * len); + temp[dir_len + len] = L'\0'; + + bool exclude = false; + char* temp_utf8 = utf16_to_utf8(temp); + for (size_t i = 0; i < exclude_count; i++) + if (!str_utils_compare(exclude_list[i], temp_utf8)) { + exclude = true; + break; + } + free(temp_utf8); + + if (exclude) + continue; + } + + + char* directory_temp = utf16_to_utf8(fdata.cFileName); + string* directory = vector_string_reserve_back(directories); + string_init(directory, directory_temp); + free(directory_temp); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(temp); + free(dir); +} + +void path_wget_directories(vector_wstring* directories, wchar_t* path, + wchar_t** exclude_list, size_t exclude_count) { + vector_wstring_free(directories, wstring_free); + + size_t dir_len = utf16_length(path); + + wchar_t* dir; + wchar_t* temp; + if (path[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); + memcpy(temp, path, sizeof(wchar_t) * dir_len); + temp[dir_len] = L'\\'; + dir_len++; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 1 + MAX_PATH); + memcpy(temp, path, sizeof(wchar_t) * dir_len); + } + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + free(temp); + return; + } + + do { + if (~fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + else if (!str_utils_wcompare(fdata.cFileName, L".") + || !str_utils_wcompare(fdata.cFileName, L"..")) + continue; + + if (exclude_list && exclude_count) { + size_t len = utf16_length(fdata.cFileName); + memcpy(temp + dir_len + 1, fdata.cFileName, sizeof(wchar_t) * len); + temp[dir_len + 1 + len] = L'\0'; + + bool exclude = false; + for (size_t i = 0; i < exclude_count; i++) + if (!str_utils_wcompare(exclude_list[i], temp)) { + exclude = true; + break; + } + + if (exclude) + continue; + } + + wstring* directory = vector_wstring_reserve_back(directories); + wstring_init(directory, fdata.cFileName); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(temp); + free(dir); +} + +void path_get_directories_recursive(vector_string* directories, char* path, + char** exclude_list, size_t exclude_count) { + vector_string_free(directories, string_free); + + wchar_t* dir_temp = utf8_to_utf16(path); + size_t dir_len = utf16_length(dir_temp); + if (!dir_temp) + return; + + wchar_t* dir; + wchar_t* temp; + if (dir_temp[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); + memcpy(temp, dir_temp, sizeof(wchar_t) * dir_len); + temp[dir_len] = L'\\'; + dir_len++; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 1 + MAX_PATH); + memcpy(temp, dir_temp, sizeof(wchar_t) * dir_len); + } + free(dir_temp); + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + free(temp); + return; + } + + vector_string temp_vec = vector_empty(string); + do { + if (~fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + else if (!str_utils_wcompare(fdata.cFileName, L".") + || !str_utils_wcompare(fdata.cFileName, L"..")) + continue; + + if (exclude_list && exclude_count) { + size_t len = utf16_length(fdata.cFileName); + memcpy(temp + dir_len + 1, fdata.cFileName, sizeof(wchar_t) * len); + temp[dir_len + 1 + len] = L'\0'; + + bool exclude = false; + char* temp_utf8 = utf16_to_utf8(temp); + for (size_t i = 0; i < exclude_count; i++) + if (!str_utils_compare(exclude_list[i], temp_utf8)) { + exclude = true; + break; + } + free(temp_utf8); + + if (exclude) + continue; + } + + char* directory_temp = utf16_to_utf8(fdata.cFileName); + string* directory = vector_string_reserve_back(&temp_vec); + string_init(directory, directory_temp); + free(directory_temp); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(temp); + free(dir); + + size_t max_len = 0; + for (string* i = temp_vec.begin; i != temp_vec.end; i++) { + size_t len = i->length; + if (max_len < len) + max_len = len; + } + + size_t path_length = utf8_length(path); + char* path_temp = force_malloc(path_length + max_len + 2); + memcpy(path_temp, path, path_length); + path_temp[path_length] = '\\'; + for (string* i = temp_vec.begin; i != temp_vec.end; i++) { + memcpy(&path_temp[path_length + 1], string_data(i), i->length + 1); + + vector_string temp = vector_empty(string); + path_get_directories_recursive(&temp, path_temp, exclude_list, exclude_count); + + vector_string_push_back(directories, i); + + if (!(temp.end - temp.begin)) { + vector_string_free(&temp, string_free); + continue; + } + + max_len = 0; + for (string* j = temp.begin; j != temp.end; j++) { + size_t len = j->length; + if (max_len < len) + max_len = len; + } + + size_t sub_path_length = i->length; + char* sub_path_temp = force_malloc(sub_path_length + max_len + 1); + if (sub_path_temp) { + memcpy(sub_path_temp, string_data(i), sub_path_length); + sub_path_temp[sub_path_length] = '\\'; + for (string* j = temp.begin; j != temp.end; j++) { + memcpy(&sub_path_temp[sub_path_length + 1], string_data(j), j->length); + + string* directory = vector_string_reserve_back(&temp_vec); + string_init_length(directory, sub_path_temp, sub_path_length + 1 + j->length); + } + } + free(sub_path_temp); + + vector_string_free(&temp, string_free); + } + free(path_temp); + vector_string_free(&temp_vec, 0); +} + +void path_wget_directories_recursive(vector_wstring* directories, wchar_t* path, + wchar_t** exclude_list, size_t exclude_count) { + vector_wstring_free(directories, wstring_free); + + size_t dir_len = utf16_length(path); + + wchar_t* dir; + wchar_t* temp; + if (path[dir_len - 1] != L'\\') { + dir = force_malloc_s(wchar_t, dir_len + 3); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'\\'; + dir[dir_len + 1] = L'*'; + dir[dir_len + 2] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); + memcpy(temp, path, sizeof(wchar_t) * dir_len); + temp[dir_len] = L'\\'; + dir_len++; + } + else { + dir = force_malloc_s(wchar_t, dir_len + 2); + memcpy(dir, path, sizeof(wchar_t) * dir_len); + dir[dir_len] = L'*'; + dir[dir_len + 1] = 0; + + temp = force_malloc_s(wchar_t, dir_len + 1 + MAX_PATH); + memcpy(temp, path, sizeof(wchar_t) * dir_len); + } + + WIN32_FIND_DATAW fdata; + memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); + HANDLE h = FindFirstFileW(dir, &fdata); + if (h == INVALID_HANDLE_VALUE) { + free(dir); + free(temp); + return; + } + + vector_wstring temp_vec = vector_empty(wstring); + do { + if (~fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + else if (!str_utils_wcompare(fdata.cFileName, L".") + || !str_utils_wcompare(fdata.cFileName, L"..")) + continue; + + if (exclude_list && exclude_count) { + size_t len = utf16_length(fdata.cFileName); + memcpy(temp + dir_len + 1, fdata.cFileName, sizeof(wchar_t) * len); + temp[dir_len + 1 + len] = L'\0'; + + bool exclude = false; + for (size_t i = 0; i < exclude_count; i++) + if (!str_utils_wcompare(exclude_list[i], temp)) { + exclude = true; + break; + } + + if (exclude) + continue; + } + + wstring* directory = vector_wstring_reserve_back(&temp_vec); + wstring_init(directory, fdata.cFileName); + } while (FindNextFileW(h, &fdata)); + FindClose(h); + free(temp); + free(dir); + + size_t max_len = 0; + for (wstring* i = temp_vec.begin; i != temp_vec.end; i++) { + size_t len = i->length; + if (max_len < len) + max_len = len; + } + + size_t path_length = utf16_length(path); + wchar_t* path_temp = force_malloc_s(wchar_t, path_length + max_len + 2); + memcpy(path_temp, path, path_length); + path_temp[path_length] = '\\'; + for (wstring* i = temp_vec.begin; i != temp_vec.end; i++) { + memcpy(&path_temp[path_length + 1], wstring_data(i), sizeof(wchar_t) * (i->length + 1)); + + vector_wstring temp = vector_empty(wstring); + path_wget_directories_recursive(&temp, path_temp, exclude_list, exclude_count); + + vector_wstring_push_back(directories, i); + + if (!(temp.end - temp.begin)) { + vector_wstring_free(&temp, wstring_free); + continue; + } + + max_len = 0; + for (wstring* j = temp.begin; j != temp.end; j++) { + size_t len = j->length; + if (max_len < len) + max_len = len; + } + + size_t sub_path_length = i->length; + wchar_t* sub_path_temp = force_malloc_s(wchar_t, sub_path_length + max_len + 1); + if (sub_path_temp) { + memcpy(sub_path_temp, wstring_data(i), sub_path_length); + sub_path_temp[sub_path_length] = '\\'; + for (wstring* j = temp.begin; j != temp.end; j++) { + memcpy(&sub_path_temp[sub_path_length + 1], wstring_data(j), sizeof(wchar_t) * j->length); + + wstring* directory = vector_wstring_reserve_back(directories); + wstring_init_length(directory, sub_path_temp, sub_path_length + 1 + j->length); + } + } + free(sub_path_temp); + + vector_wstring_free(&temp, wstring_free); + } + free(path_temp); + vector_wstring_free(&temp_vec, 0); +} diff --git a/src/KKdLib/io/path.h b/src/KKdLib/io/path.h new file mode 100644 index 00000000..d9718e80 --- /dev/null +++ b/src/KKdLib/io/path.h @@ -0,0 +1,27 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../string.h" +#include "../vector.h" + +extern bool path_check_path_exists(char* path); +extern bool path_wcheck_path_exists(wchar_t* path); +extern bool path_check_file_exists(char* path); +extern bool path_wcheck_file_exists(wchar_t* path); +extern bool path_check_directory_exists(char* path); +extern bool path_wcheck_directory_exists(wchar_t* path); +extern void path_get_files(vector_string* files, char* path); +extern void path_wget_files(vector_wstring* files, wchar_t* path); +extern void path_get_directories(vector_string* directories, char* path, + char** exclude_list, size_t exclude_count); +extern void path_wget_directories(vector_wstring* directories, wchar_t* path, + wchar_t** exclude_list, size_t exclude_count); +extern void path_get_directories_recursive(vector_string* directories, char* path, + char** exclude_list, size_t exclude_count); +extern void path_wget_directories_recursive(vector_wstring* directories, wchar_t* path, + wchar_t** exclude_list, size_t exclude_count); \ No newline at end of file diff --git a/src/KKdLib/io_stream.c b/src/KKdLib/io/stream.c similarity index 90% rename from src/KKdLib/io_stream.c rename to src/KKdLib/io/stream.c index 8b7f712b..387b14c8 100644 --- a/src/KKdLib/io_stream.c +++ b/src/KKdLib/io/stream.c @@ -3,20 +3,9 @@ GitHub/GitLab: korenkonder */ -#include "io_stream.h" +#include "stream.h" #include -inline static void io_get_length(stream* s) { - if (s->io.stream) { - size_t temp = _ftelli64(s->io.stream); - _fseeki64(s->io.stream, 0, SEEK_END); - s->length = _ftelli64(s->io.stream); - _fseeki64(s->io.stream, temp, SEEK_SET); - } - else - s->length = 0; -} - void io_open(stream* s, char* path, char* mode) { memset(s, 0, sizeof(stream)); if (!path || !mode) @@ -156,6 +145,28 @@ int io_flush(stream* s) { } } +inline ssize_t io_get_length(stream* s) { + switch (s->type) { + case STREAM_FILE: + if (s->io.stream) { + size_t temp = _ftelli64(s->io.stream); + _fseeki64(s->io.stream, 0, SEEK_END); + s->length = _ftelli64(s->io.stream); + _fseeki64(s->io.stream, temp, SEEK_SET); + } + else + s->length = 0; + break; + case STREAM_MEMORY: + s->length = s->io.data.vec.end - s->io.data.vec.begin; + break; + default: + s->length = 0; + break; + } + return s->length; +} + inline ssize_t io_get_position(stream* s) { switch (s->type) { case STREAM_FILE: @@ -226,8 +237,7 @@ int32_t io_set_position(stream* s, ssize_t pos, int32_t seek) { } inline int32_t io_position_push(stream* s, ssize_t pos, int32_t seek) { - ssize_t position = io_get_position(s); - vector_ssize_t_push_back(&s->position_stack, &position); + *vector_ssize_t_reserve_back(&s->position_stack) = io_get_position(s); return io_set_position(s, pos, seek); } @@ -236,7 +246,7 @@ inline void io_position_pop(stream* s) { return; ssize_t position = s->position_stack.end[-1]; - vector_ssize_t_pop_back(&s->position_stack); + vector_ssize_t_pop_back(&s->position_stack, 0); io_set_position(s, position, SEEK_SET); io_flush(s); } @@ -362,6 +372,22 @@ inline void io_write_uint8_t(stream* s, uint8_t val) { io_write_char(s, (char)val); } +inline void io_read_string(stream* s, string* str, size_t length) { + char* temp = force_malloc(length + 1); + io_read(s, temp, length); + temp[length] = 0; + string_init_length(str, temp, length); + free(temp); +} + +inline void io_read_wstring(stream* s, wstring* str, size_t length) { + wchar_t* temp = force_malloc_s(wchar_t, length + 1); + io_read(s, temp, sizeof(wchar_t) * length); + temp[length] = 0; + wstring_init_length(str, temp, length); + free(temp); +} + inline void io_read_string_null_terminated(stream* s, string* str) { ssize_t offset = io_get_position(s); char* temp = io_read_utf8_string_null_terminated_offset(s, offset); @@ -384,7 +410,7 @@ inline void io_read_string_null_terminated_offset(stream* s, free(temp); } else - string_init(str, 0); + *str = string_empty; } inline void io_read_wstring_null_terminated_offset(stream* s, @@ -395,7 +421,7 @@ inline void io_read_wstring_null_terminated_offset(stream* s, free(temp); } else - wstring_init(str, 0); + *str = wstring_empty; } inline char* io_read_utf8_string_null_terminated(stream* s) { @@ -453,20 +479,20 @@ wchar_t* io_read_utf16_string_null_terminated_offset(stream* s, ssize_t offset) } inline void io_write_string(stream* s, string* str) { - io_write(s, string_data(str), string_length(str)); + io_write(s, string_data(str), str->length); } inline void io_write_wstring(stream* s, wstring* str) { - io_write(s, wstring_access(str), sizeof(wchar_t) * wstring_length(str)); + io_write(s, wstring_data(str), sizeof(wchar_t) * str->length); } inline void io_write_string_null_terminated(stream* s, string* str) { - io_write(s, string_data(str), string_length(str)); + io_write(s, string_data(str), str->length); io_write_uint8_t(s, 0); } inline void io_write_wstring_null_terminated(stream* s, wstring* str) { - io_write(s, wstring_access(str), sizeof(wchar_t) * wstring_length(str)); + io_write(s, wstring_data(str), sizeof(wchar_t) * str->length); io_write_uint16_t(s, 0); } @@ -550,10 +576,10 @@ void io_free(stream* s) { } break; case STREAM_MEMORY: - vector_uint8_t_free(&s->io.data.vec); + vector_uint8_t_free(&s->io.data.vec, 0); break; } - vector_ssize_t_free(&s->position_stack); + vector_ssize_t_free(&s->position_stack, 0); memset(s, 0, sizeof(stream)); } diff --git a/src/KKdLib/io_stream.h b/src/KKdLib/io/stream.h similarity index 93% rename from src/KKdLib/io_stream.h rename to src/KKdLib/io/stream.h index 71fef753..a5a8cafb 100644 --- a/src/KKdLib/io_stream.h +++ b/src/KKdLib/io/stream.h @@ -5,10 +5,10 @@ #pragma once -#include "default.h" -#include "string.h" -#include "half_t.h" -#include "vector.h" +#include "../default.h" +#include "../string.h" +#include "../half_t.h" +#include "../vector.h" typedef enum stream_type { STREAM_NONE = 0, @@ -38,6 +38,7 @@ extern void io_mcopy(stream* s, void** data, size_t* length); extern void io_align_read(stream* s, ssize_t align); extern void io_align_write(stream* s, ssize_t align); extern int io_flush(stream* s); +extern ssize_t io_get_length(stream* s); extern ssize_t io_get_position(stream* s); extern int32_t io_set_position(stream* s, ssize_t pos, int32_t seek); extern int32_t io_position_push(stream* s, ssize_t pos, int32_t seek); @@ -52,10 +53,12 @@ extern uint8_t io_read_uint8_t(stream* s); extern void io_write_int8_t(stream* s, int8_t val); extern void io_write_uint8_t(stream* s, uint8_t val); +extern void io_read_string(stream* s, string* str, size_t length); +extern void io_read_wstring(stream* s, wstring* str, size_t length); extern void io_read_string_null_terminated(stream* s, string* str); extern void io_read_wstring_null_terminated(stream* s, wstring* str); -extern void io_read_string_null_terminated_offset(stream* s, ssize_t offset, string* c); -extern void io_read_wstring_null_terminated_offset(stream* s, ssize_t offset, wstring* c); +extern void io_read_string_null_terminated_offset(stream* s, ssize_t offset, string* str); +extern void io_read_wstring_null_terminated_offset(stream* s, ssize_t offset, wstring* str); extern char* io_read_utf8_string_null_terminated(stream* s); extern wchar_t* io_read_utf16_string_null_terminated(stream* s); extern char* io_read_utf8_string_null_terminated_offset(stream* s, ssize_t offset); diff --git a/src/KKdLib/io_path.c b/src/KKdLib/io_path.c deleted file mode 100644 index cea7615a..00000000 --- a/src/KKdLib/io_path.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#include "io_path.h" - -bool path_check_path_exists(char* path) { - wchar_t* path_temp = utf8_to_utf16(path); - DWORD ftyp = GetFileAttributesW(path_temp); - free(path_temp); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return true; -} - -bool path_wcheck_path_exists(wchar_t* path) { - DWORD ftyp = GetFileAttributesW(path); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return true; -} - -bool path_check_file_exists(char* path) { - wchar_t* path_temp = utf8_to_utf16(path); - DWORD ftyp = GetFileAttributesW(path_temp); - free(path_temp); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return ftyp & FILE_ATTRIBUTE_DIRECTORY ? false : true; -} - -bool path_wcheck_file_exists(wchar_t* file_path) { - DWORD ftyp = GetFileAttributesW(file_path); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return ftyp & FILE_ATTRIBUTE_DIRECTORY ? false : true; -} - -bool path_check_directory_exists(char* path) { - wchar_t* path_temp = utf8_to_utf16(path); - DWORD ftyp = GetFileAttributesW(path_temp); - free(path_temp); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return ftyp & FILE_ATTRIBUTE_DIRECTORY ? true : false; -} - -bool path_wcheck_directory_exists(wchar_t* path) { - DWORD ftyp = GetFileAttributesW(path); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - else - return ftyp & FILE_ATTRIBUTE_DIRECTORY ? true : false; -} - -void path_get_files(vector_string* files, char* path) { - vector_string_free(files); - - wchar_t* dir_temp = utf8_to_utf16(path); - size_t dir_len = utf16_length(dir_temp); - if (!dir_temp) - return; - - wchar_t* dir = force_malloc_s(wchar_t, dir_len + 3); - memcpy(dir, dir_temp, sizeof(wchar_t) * dir_len); - dir[dir_len] = L'\\'; - dir[dir_len + 1] = L'*'; - dir[dir_len + 2] = 0; - - wchar_t* temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); - memcpy(temp, dir_temp, sizeof(wchar_t) * dir_len); - temp[dir_len] = L'\\'; - free(dir_temp); - - WIN32_FIND_DATAW fdata; - memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); - HANDLE h = FindFirstFileW(dir, &fdata); - if (h == INVALID_HANDLE_VALUE) { - free(dir); - free(temp); - return; - } - - do { - size_t len = utf16_length(fdata.cFileName); - memcpy(temp + dir_len + 1, fdata.cFileName, sizeof(wchar_t) * len); - temp[dir_len + 1 + len] = L'\0'; - - if (path_wcheck_file_exists(temp)) { - char* file_temp = utf16_to_utf8(fdata.cFileName); - string file; - string_init(&file, file_temp); - vector_string_push_back(files, &file); - free(file_temp); - } - } while (FindNextFileW(h, &fdata)); - FindClose(h); - free(temp); - free(dir); -} - -void path_wget_files(vector_wstring* files, wchar_t* path) { - vector_wstring_free(files); - - size_t dir_len = utf16_length(path); - wchar_t* dir = force_malloc_s(wchar_t, dir_len + 3); - memcpy(dir, path, sizeof(wchar_t) * dir_len); - dir[dir_len] = L'\\'; - dir[dir_len + 1] = L'*'; - dir[dir_len + 2] = 0; - - wchar_t* temp = force_malloc_s(wchar_t, dir_len + 2 + MAX_PATH); - memcpy(temp, path, sizeof(wchar_t) * dir_len); - temp[dir_len] = L'\\'; - - WIN32_FIND_DATAW fdata; - memset(&fdata, 0, sizeof(WIN32_FIND_DATAW)); - HANDLE h = FindFirstFileW(dir, &fdata); - if (h == INVALID_HANDLE_VALUE) { - free(dir); - free(temp); - return; - } - - do { - size_t len = utf16_length(fdata.cFileName); - memcpy(temp + dir_len + 1, fdata.cFileName, sizeof(wchar_t) * len); - temp[dir_len + 1 + len] = L'\0'; - - if (path_wcheck_file_exists(temp)) { - wstring file; - wstring_init(&file, fdata.cFileName); - vector_wstring_push_back(files, &file); - } - } while (FindNextFileW(h, &fdata)); - FindClose(h); - free(temp); - free(dir); -} diff --git a/src/KKdLib/io_path.h b/src/KKdLib/io_path.h deleted file mode 100644 index d1c792fb..00000000 --- a/src/KKdLib/io_path.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "default.h" -#include "string.h" -#include "vector.h" - -extern bool path_check_path_exists(char* path); -extern bool path_wcheck_path_exists(wchar_t* path); -extern bool path_check_file_exists(char* path); -extern bool path_wcheck_file_exists(wchar_t* path); -extern bool path_check_directory_exists(char* path); -extern bool path_wcheck_directory_exists(wchar_t* path); -extern void path_get_files(vector_string* files, char* path); -extern void path_wget_files(vector_wstring* files, wchar_t* path); \ No newline at end of file diff --git a/src/KKdLib/key_val.c b/src/KKdLib/key_val.c new file mode 100644 index 00000000..b7d31422 --- /dev/null +++ b/src/KKdLib/key_val.c @@ -0,0 +1,495 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "key_val.h" +#include "hash.h" +#include "str_utils.h" + +static ssize_t key_val_get_key_index(key_val* kv, char* str, size_t length); +static void key_val_sort(key_val* kv); + +void key_val_init(key_val* kv, uint8_t* data, size_t length) { + kv->buf = 0; + kv->key = vector_ptr_empty(char); + kv->key_len = vector_empty(size_t); + kv->val = vector_ptr_empty(char); + kv->val_len = vector_empty(size_t); + kv->key_hash = vector_empty(uint64_t); + kv->key_index = vector_empty(size_t); + + if (!data || !length) + return; + + char** lines; + size_t count; + if (!str_utils_text_file_parse(data, length, &kv->buf, &lines, &count)) + return; + + vector_ptr_char_reserve(&kv->key, count); + vector_size_t_reserve(&kv->key_len, count); + vector_ptr_char_reserve(&kv->val, count); + vector_size_t_reserve(&kv->val_len, count); + + for (size_t i = 0, j = 0; i < count; i++) { + char* s = lines[i]; + if (*s == '#') + continue; + + size_t len = utf8_length(s); + char* c = memchr(s, '=', len); + if (!c) + continue; + + *c = 0; + + char* key_str_data = s; + char* val_str_data = c + 1; + + size_t key_length = c - s; + size_t val_length = len - (key_length + 1); + + uint64_t key_hash = hash_fnv1a64m(key_str_data, key_length); + + vector_ptr_char_push_back(&kv->key, &key_str_data); + vector_size_t_push_back(&kv->key_len, &key_length); + vector_ptr_char_push_back(&kv->val, &val_str_data); + vector_size_t_push_back(&kv->val_len, &val_length); + j++; + } + key_val_sort(kv); + free(lines) +} + +bool key_val_get_local_key_val(key_val* kv, char* str, key_val* lkv) { + lkv->buf = 0; + lkv->key = vector_ptr_empty(char); + lkv->key_len = vector_empty(size_t); + lkv->val = vector_ptr_empty(char); + lkv->key_hash = vector_empty(uint64_t); + lkv->key_index = vector_empty(size_t); + + if (!str) + return false; + + char** first = 0; + char** last = 0; + size_t str_length = utf8_length(str); + + char** i = kv->key.begin; + size_t* i_len = kv->key_len.begin; + size_t j = kv->key.end - kv->key.begin; + for (; j; i++, i_len++, j--) + if (str_length <= *i_len && !memcmp(str, (char*)*i, str_length)) { + if (!first) + first = i; + last = i + 1; + } + else if (first) + break; + + if (!first) + return false; + + size_t index = first - kv->key.begin; + size_t count = last - first; + lkv->key.begin = &kv->key.begin[index]; + lkv->key.end = &kv->key.begin[index + count]; + lkv->key_len.begin = &kv->key_len.begin[index]; + lkv->val.begin = &kv->val.begin[index]; + lkv->val_len.begin = &kv->val_len.begin[index]; + + key_val_sort(lkv); + return true; +} + +bool key_val_has_key(key_val* kv, char* str) { + size_t str_length = utf8_length(str); + + char** i = kv->key.begin; + size_t* i_len = kv->key_len.begin; + size_t j = kv->key.end - kv->key.begin; + for (; j; i++, i_len++, j--) { + size_t len = min(str_length, *i_len); + if (len && str_length <= *i_len && !memcmp(str, *i, len)) + return true; + } + return false; +} + +bool key_val_read_bool(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, bool* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = false; + return false; + } + *value = atoi(kv->val.begin[index]) ? true : false; + return true; +} + +void key_val_write_bool(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, bool value) { + if (!value) + return; + + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + io_write_utf8_string(s, buf); + io_write(s, "=1\n", 3); +} + +bool key_val_read_float_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, float_t* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = 0.0f; + return false; + } + *value = (float_t)atof(kv->val.begin[index]); + return true; +} + +void key_val_write_float_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, float_t value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + char val_buf[0x100]; + sprintf_s(val_buf, 0x100, "%g", value); + + io_write_utf8_string(s, buf); + io_write_char(s, '='); + io_write_utf8_string(s, val_buf); + io_write_char(s, '\n'); +} + +bool key_val_read_int32_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, int32_t* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = 0; + return false; + } + *value = atoi(kv->val.begin[index]); + return true; +} + +void key_val_write_int32_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, int32_t value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + char val_buf[0x100]; + sprintf_s(val_buf, 0x100, "%d", value); + + io_write_utf8_string(s, buf); + io_write_char(s, '='); + io_write_utf8_string(s, val_buf); + io_write_char(s, '\n'); +} + +bool key_val_read_uint32_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, uint32_t* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = 0; + return false; + } + *value = atoi(kv->val.begin[index]); + return true; +} + +void key_val_write_uint32_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, uint32_t value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + char val_buf[0x100]; + sprintf_s(val_buf, 0x100, "%u", value); + + io_write_utf8_string(s, buf); + io_write_char(s, '='); + io_write_utf8_string(s, val_buf); + io_write_char(s, '\n'); +} + +bool key_val_read_string(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, string* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = string_empty; + return false; + } + string_init_length(value, kv->val.begin[index], kv->val_len.begin[index]); + return true; +} + +bool key_val_read_string_ptr(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, char** value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + ssize_t index = key_val_get_key_index(kv, buf, offset); + buf[offset - (str_add_len - 1)] = 0; + if (index == -1) { + *value = 0; + return false; + } + *value = kv->val.begin[index]; + return true; +} + +void key_val_write_string(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, string* value) { + if (!string_data(value)) + return; + + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + io_write_utf8_string(s, buf); + io_write_char(s, '='); + io_write(s, string_data(value), value->length); + io_write_char(s, '\n'); +} + +void key_val_write_string_ptr(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, char* value) { + if (!value) + return; + + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + io_write_utf8_string(s, buf); + io_write_char(s, '='); + io_write_utf8_string(s, value); + io_write_char(s, '\n'); +} + +bool key_val_read_vec3(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, vec3* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + key_val lkv; + if (!key_val_get_local_key_val(kv, buf, &lkv)) { + memset(value, 0, sizeof(vec3)); + return false; + } + + key_val_read_float_t(&lkv, buf, offset, ".x", 3, &value->x); + key_val_read_float_t(&lkv, buf, offset, ".y", 3, &value->y); + key_val_read_float_t(&lkv, buf, offset, ".z", 3, &value->z); + key_val_free(&lkv); + return true; +} + +void key_val_write_vec3(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, vec3* value) { + memcpy(buf + offset, str_add, str_add_len); + offset += str_add_len - 1; + + key_val_write_float_t(s, buf, offset, ".x", 3, value->x); + key_val_write_float_t(s, buf, offset, ".y", 3, value->y); + key_val_write_float_t(s, buf, offset, ".z", 3, value->z); +} + +void key_val_free(key_val* kv) { + if (kv->buf) { + size_t count = kv->key.end - kv->key.begin; + memset(kv->key.begin, 0, sizeof(char*) * count); + memset(kv->val.begin, 0, sizeof(char*) * count); + + vector_ptr_char_free(&kv->key, 0); + vector_size_t_free(&kv->key_len, 0); + vector_ptr_char_free(&kv->val, 0); + vector_size_t_free(&kv->val_len, 0); + } + vector_uint64_t_free(&kv->key_hash, 0); + vector_size_t_free(&kv->key_index, 0); + free(kv->buf); +} + +void key_val_get_lexicographic_order(vector_int32_t* vec, int32_t length) { + vector_int32_t_clear(vec, 0); + + int32_t i, j, m; + + if (length <= 0) + return; + + vector_int32_t_reserve(vec, length); + + j = 0; + vector_int32_t_push_back(vec, &j); + i = 1; + j = 1; + + m = 1; + while (m < length) + m *= 10; + + while (i < length) { + if (j * 10 < m) { + vector_int32_t_push_back(vec, &j); + i++; + j *= 10; + } + else if (j >= length) { + m /= 10; + j /= 10; + while (j % 10 == 9) + j /= 10; + j++; + } + else if (j % 10 != 9) { + vector_int32_t_push_back(vec, &j); + i++; + j++; + } + + if (i < length) + if (j == length && j % 10 != 9) { + m /= 10; + j /= 10; + while (j % 10 == 9) + j /= 10; + j++; + } + else if (j < length && j % 10 == 9) { + vector_int32_t_push_back(vec, &j); + i++; + while (j % 10 == 9) + j /= 10; + j++; + } + } +} + +static ssize_t key_val_get_key_index(key_val* kv, char* str, size_t length) { + if (!(kv->key_hash.end - kv->key_hash.begin)) + return -1; + + uint64_t hash = hash_fnv1a64m(str, length); + + uint64_t* key = kv->key_hash.begin; + size_t len = kv->key.end - kv->key.begin; + size_t temp; + while (len > 0) { + if (hash < key[temp = len / 2]) + len = temp; + else { + key += temp + 1; + len -= temp + 1; + } + } + + if (key - kv->key_hash.begin == 0) + if (key[0] == hash) + return kv->key_index.begin[key - kv->key_hash.begin]; + else + return -1; + else if (key[-1] == hash) + return kv->key_index.begin[key - kv->key_hash.begin - 1]; + else if (key[0] == hash) + return kv->key_index.begin[key - kv->key_hash.begin]; + return -1; +} + +#define RADIX_BASE 8 +#define RADIX (1 << RADIX_BASE) + +static void key_val_sort(key_val* kv) { + size_t count = kv->key.end - kv->key.begin; + + kv->key_hash = vector_empty(uint64_t); + kv->key_index = vector_empty(size_t); + vector_uint64_t_reserve(&kv->key_hash, count); + vector_size_t_reserve(&kv->key_index, count); + kv->key_hash.end += count; + kv->key_index.end += count; + + char** key = kv->key.begin; + size_t* key_len = kv->key_len.begin; + uint64_t* key_hash = kv->key_hash.begin; + size_t* key_index = kv->key_index.begin; + for (size_t i = 0; i < count; i++) { + *key_index++ = i; + *key_hash++ = hash_fnv1a64m(*key++, *key_len++); + } + + if (count < 2) + return; + + uint64_t* o_key_hash = force_malloc_s(uint64_t, count); + size_t* o_key_index = force_malloc_s(size_t, count); + size_t* c = force_malloc_s(size_t, (1 << 8)); + uint64_t* arr_key_hash = kv->key_hash.begin; + size_t* arr_key_index = kv->key_index.begin; + uint64_t* org_arr = arr_key_hash; + + for (size_t shift = 0, s = 0; shift < sizeof(uint64_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < count; i++) + c[(arr_key_hash[i] >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = count - 1; i >= 0; i--) { + size_t index = --c[(arr_key_hash[i] >> s) & (RADIX - 1)]; + o_key_hash[index] = arr_key_hash[i]; + o_key_index[index] = arr_key_index[i]; + } + + uint64_t* t_key_hash = arr_key_hash; + arr_key_hash = o_key_hash; + o_key_hash = t_key_hash; + + size_t* t_key_index = arr_key_index; + arr_key_index = o_key_index; + o_key_index = t_key_index; + } + + if (org_arr == o_key_hash) { + uint64_t* t_key_hash = arr_key_hash; + arr_key_hash = o_key_hash; + o_key_hash = t_key_hash; + + size_t* t_key_index = arr_key_index; + arr_key_index = o_key_index; + o_key_index = t_key_index; + + memmove(arr_key_hash, o_key_hash, sizeof(uint64_t) * count); + memmove(arr_key_index, o_key_index, sizeof(size_t) * count); + } + + free(o_key_hash); + free(o_key_index); + free(c); +} diff --git a/src/KKdLib/key_val.h b/src/KKdLib/key_val.h new file mode 100644 index 00000000..c3e3f884 --- /dev/null +++ b/src/KKdLib/key_val.h @@ -0,0 +1,56 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "default.h" +#include "io/stream.h" +#include "vec.h" +#include "vector.h" + +typedef struct key_val { + vector_ptr_char key; + vector_size_t key_len; + vector_ptr_char val; + vector_size_t val_len; + char* buf; + vector_uint64_t key_hash; + vector_size_t key_index; +} key_val; + +extern void key_val_init(key_val* kv, uint8_t* data, size_t length); +extern bool key_val_get_local_key_val(key_val* kv, char* str, key_val* lkv); +extern bool key_val_has_key(key_val* kv, char* str); +extern bool key_val_read_bool(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, bool* value); +extern void key_val_write_bool(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, bool value); +extern bool key_val_read_float_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, float_t* value); +extern void key_val_write_float_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, float_t value); +extern bool key_val_read_int32_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, int32_t* value); +extern void key_val_write_int32_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, int32_t value); +extern bool key_val_read_uint32_t(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, uint32_t* value); +extern void key_val_write_uint32_t(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, uint32_t value); +extern bool key_val_read_string(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, string* value); +extern bool key_val_read_string_ptr(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, char** value); +extern void key_val_write_string(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, string* value); +extern void key_val_write_string_ptr(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, char* value); +extern bool key_val_read_vec3(key_val* kv, char* buf, + size_t offset, char* str_add, size_t str_add_len, vec3* value); +extern void key_val_write_vec3(stream* s, char* buf, + size_t offset, char* str_add, size_t str_add_len, vec3* value); +extern void key_val_free(key_val* kv); + +extern void key_val_get_lexicographic_order(vector_int32_t* vec, int32_t length); diff --git a/src/KKdLib/kf.c b/src/KKdLib/kf.c index 758fd93b..83ef3d70 100644 --- a/src/KKdLib/kf.c +++ b/src/KKdLib/kf.c @@ -5,6 +5,17 @@ #include "kf.h" +vector_func(kft0) +vector_func(kft1) +vector_func(kft2) +vector_func(kft3) +vector_ptr_func(kft0) +vector_ptr_func(kft1) +vector_ptr_func(kft2) +vector_ptr_func(kft3) + +#define KFT_NULL + void kft_check(void* src_key, kf_type src_type, void* dst_key, kf_type* dst_type) { switch (src_type) { case KEY_FRAME_TYPE_0: { @@ -56,7 +67,7 @@ void kft_check(void* src_key, kf_type src_type, void* dst_key, kf_type* dst_type dk->value = sk->value; dk->tangent1 = sk->tangent1; dk->tangent2 = sk->tangent2; - *dst_type = KEY_FRAME_TYPE_2; + *dst_type = KEY_FRAME_TYPE_3; } else if (*(uint32_t*)&sk->tangent1 != 0) { kft2* dk = dst_key; diff --git a/src/KKdLib/kf.h b/src/KKdLib/kf.h index 4f3845f3..a57918fa 100644 --- a/src/KKdLib/kf.h +++ b/src/KKdLib/kf.h @@ -6,6 +6,7 @@ #pragma once #include "default.h" +#include "vector.h" typedef enum kf_type { KEY_FRAME_TYPE_0 = 0, @@ -36,4 +37,13 @@ typedef struct kft3 { float_t tangent2; } kft3; +vector(kft0) +vector(kft1) +vector(kft2) +vector(kft3) +vector_ptr(kft0) +vector_ptr(kft1) +vector_ptr(kft2) +vector_ptr(kft3) + extern void kft_check(void* src_key, kf_type src_type, void* dst_key, kf_type* dst_type); diff --git a/src/KKdLib/kkc.c b/src/KKdLib/kkc.c index 0cf19df1..657c3791 100644 --- a/src/KKdLib/kkc.c +++ b/src/KKdLib/kkc.c @@ -166,15 +166,15 @@ void kkc_prepare_cipher_table(kkc* c) { return; memcpy(arr, c->key.data, kl); - if (c->k) - free(c->k); + if (c->i) + free(c->i); - c->k = force_malloc_s(uint32_t, kl); - if (!c->k) + c->i = force_malloc_s(uint32_t, kl); + if (!c->i) return; size_t n = kl / 2; - uint32_t* k = c->k; + uint32_t* k = c->i; size_t i; uint32_t a, b, q, seed; while (true) { @@ -268,7 +268,7 @@ void kkc_cipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t length bool ret = true; if (c->error) return; - else if (!c->k) + else if (!c->i) c->error = KKC_ERROR_UNINITIALIZED_TABLE; else if (!c->key.data) c->error = KKC_ERROR_INVALID_KEY; @@ -285,7 +285,7 @@ void kkc_cipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t length kkc e = *c; uint32_t* s = (uint32_t*)src; uint32_t* d = (uint32_t*)dst; - uint32_t* k = e.k; + uint32_t* k = e.i; size_t kl = (size_t)e.key.type * 8; size_t n = length / 0x10; size_t i; @@ -297,22 +297,22 @@ void kkc_cipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t length e.p = e.f; e.f = e.e; - t = c0 = e.k[e.p]; + t = c0 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c1 = e.k[e.p]; + t = c1 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c2 = e.k[e.p]; + t = c2 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c3 = e.k[e.p]; + t = c3 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; b = *s++; @@ -331,22 +331,22 @@ void kkc_cipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t length for (i = 0; i < n; i++) { e.p = e.f; e.f = e.e; - t = c0 = e.o2 ^ e.k[e.p]; + t = c0 = e.o2 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c1 = e.o0 ^ e.k[e.p]; + t = c1 = e.o0 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c2 = e.o3 ^ e.k[e.p]; + t = c2 = e.o3 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c3 = e.o1 ^ e.k[e.p]; + t = c3 = e.o1 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; b = *s++; @@ -372,7 +372,7 @@ void kkc_decipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t leng bool ret = true; if (c->error) return; - else if (!c->k) + else if (!c->i) c->error = KKC_ERROR_UNINITIALIZED_TABLE; else if (!c->key.data) c->error = KKC_ERROR_INVALID_KEY; @@ -389,7 +389,7 @@ void kkc_decipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t leng kkc e = *c; uint32_t* s = (uint32_t*)src; uint32_t* d = (uint32_t*)dst; - uint32_t* k = e.k; + uint32_t* k = e.i; size_t kl = (size_t)e.key.type * 8; size_t n = length / 0x10; size_t i; @@ -401,22 +401,22 @@ void kkc_decipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t leng e.p = e.f; e.f = e.e; - t = c0 = e.k[e.p]; + t = c0 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c1 = e.k[e.p]; + t = c1 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c2 = e.k[e.p]; + t = c2 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c3 = e.k[e.p]; + t = c3 = e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; b = *s++; @@ -435,22 +435,22 @@ void kkc_decipher(kkc* c, kkc_mode mode, uint8_t* src, uint8_t* dst, size_t leng for (i = 0; i < n; i++) { e.p = e.f; e.f = e.e; - t = c0 = e.o2 ^ e.k[e.p]; + t = c0 = e.o2 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c1 = e.o0 ^ e.k[e.p]; + t = c1 = e.o0 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c2 = e.o3 ^ e.k[e.p]; + t = c2 = e.o3 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; e.p = e.f; e.f = e.e; - t = c3 = e.o1 ^ e.k[e.p]; + t = c3 = e.o1 ^ e.i[e.p]; e.e ^= e.f ^= e.p = XOR32(t) % kl; b = *s++; @@ -478,7 +478,7 @@ void kkc_dispose(kkc* c) { return; free(c->key.data); - free(c->k); + free(c->i); free(c); } diff --git a/src/KKdLib/kkc.h b/src/KKdLib/kkc.h index 81077b22..84a7212b 100644 --- a/src/KKdLib/kkc.h +++ b/src/KKdLib/kkc.h @@ -49,7 +49,7 @@ typedef struct kkc { uint32_t state; - uint32_t* k; + uint32_t* i; } kkc; extern kkc* kkc_init(); diff --git a/src/KKdLib/kkfs.c b/src/KKdLib/kkfs.c index 66b6522e..22680ac3 100644 --- a/src/KKdLib/kkfs.c +++ b/src/KKdLib/kkfs.c @@ -4,7 +4,7 @@ */ #include "kkfs.h" -#include "io_path.h" +#include "io/path.h" #include "hash.h" #include #include @@ -104,7 +104,9 @@ void kkfs_winitialize(kkfs* fs, wchar_t* path, uint32_t sector_size, size_t leng fs->data.jmp_code[1] = 0x58; fs->data.jmp_code[2] = 0x90; memcpy(fs->data.signature, "KKFS ", 0x08); - memcpy(fs->data.header.name, path, min(utf16_length(path), 0x14)); + size_t path_length = utf16_length(path); + memcpy(fs->data.header.name, path, sizeof(wchar_t) * (min(path_length, 0x0F) + 1)); + fs->data.header.name[0x0F] = 0; next_rand_uint8_t_pointer((uint8_t*)&fs->data.header.hash, 0x04, &state); fs->data.header.key_hash = kkfs_calculate_key_hash(curse); fs->data.header.flags = flags; @@ -212,7 +214,8 @@ bool kkfs_wcreate_directory(kkfs* fs, wchar_t* path, kkfs_directory_flags flags) memset(&data, 0, sizeof(kkfs_data)); data.type = KKFS_DIRECTORY; data.dir.data_sector = free_sector; - memcpy(data.dir.name, path, sizeof(wchar_t) * min(utf16_length(path) + 1, KKFS_NAME_LENGTH)); + size_t path_length = utf16_length(path) + 1; + memcpy(data.dir.name, path, sizeof(wchar_t) * min(path_length, KKFS_NAME_LENGTH)); data.dir.flags = flags; bool result = kkfs_write_kkfs_data(fs, &data); @@ -304,7 +307,8 @@ bool kkfs_wcreate_file(kkfs* fs, wchar_t* path, uint64_t size, kkfs_file_flags f memset(&data, 0, sizeof(kkfs_data)); data.type = KKFS_FILE; data.file.data_sector = free_sector; - memcpy(data.file.name, path, sizeof(wchar_t) * min(utf16_length(path) + 1, KKFS_NAME_LENGTH)); + size_t path_length = utf16_length(path) + 1; + memcpy(data.file.name, path, sizeof(wchar_t) * min(path_length, KKFS_NAME_LENGTH)); data.file.size = size; data.file.flags = flags; if (flags & KKFS_FILE_CIPHER) @@ -617,7 +621,7 @@ static uint64_t kkfs_get_current_time_ticks() { static uint32_t kkfs_get_free_sector(kkfs* fs, uint32_t sector) { if (sector) { - for (size_t i = sector + 1LL; i < fs->data.header.sectors_count; i++) + for (size_t i = sector + 1ULL; i < fs->data.header.sectors_count; i++) if (fs->sector_info[i] == KKFS_SECTOR_FREE) return (uint32_t)i; diff --git a/src/KKdLib/kkfs.h b/src/KKdLib/kkfs.h index 846fca93..6f563125 100644 --- a/src/KKdLib/kkfs.h +++ b/src/KKdLib/kkfs.h @@ -21,19 +21,19 @@ typedef enum kkfs_sector_info { } kkfs_sector_info; typedef enum kkfs_directory_flags { - KKFS_DIRECTORY_READ_ONLY = 0x1, + KKFS_DIRECTORY_READ_ONLY = 0x1, } kkfs_directory_flags; typedef enum kkfs_file_flags { - KKFS_FILE_READ_ONLY = 0x1, - KKFS_FILE_CIPHER = 0x2, + KKFS_FILE_READ_ONLY = 0x1, + KKFS_FILE_CIPHER = 0x2, } kkfs_file_flags; typedef enum kkfs_type { - KKFS_EMPTY = 0x00000000, - KKFS_DELETED = 0x00000001, - KKFS_DIRECTORY = 0xFFFFFFFE, - KKFS_FILE = 0xFFFFFFFF, + KKFS_EMPTY = 0x00000000, + KKFS_DELETED = 0x00000001, + KKFS_DIRECTORY = 0xFFFFFFFE, + KKFS_FILE = 0xFFFFFFFF, } kkfs_type; typedef struct kkfs_deleted { diff --git a/src/KKdLib/light_param/face.c b/src/KKdLib/light_param/face.c new file mode 100644 index 00000000..4fef92f1 --- /dev/null +++ b/src/KKdLib/light_param/face.c @@ -0,0 +1,214 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "face.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_face_read_inner(light_param_face* face, stream* s); +static void light_param_face_write_inner(light_param_face* face, stream* s); +static char* light_param_face_read_line(char* buf, int32_t size, char* src); +static void light_param_face_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value); +static void light_param_face_write_float_t(stream* s, char* buf, size_t buf_size, float_t value); + +void light_param_face_init(light_param_face* face) { + memset(face, 0, sizeof(light_param_face)); +} + +void light_param_face_read(light_param_face* face, char* path) { + char* path_txt = str_utils_add(path, ".txt"); + if (path_check_file_exists(path_txt)) { + stream s; + io_open(&s, path_txt, "rb"); + if (s.io.stream) + light_param_face_read_inner(face, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_face_wread(light_param_face* face, wchar_t* path) { + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + if (path_wcheck_file_exists(path_txt)) { + stream s; + io_wopen(&s, path_txt, L"rb"); + if (s.io.stream) + light_param_face_read_inner(face, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_face_mread(light_param_face* face, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_face_read_inner(face, &s); + io_free(&s); +} + +void light_param_face_write(light_param_face* face, char* path) { + if (!face || !path || !face->ready) + return; + + char* path_txt = str_utils_add(path, ".txt"); + stream s; + io_open(&s, path_txt, "wb"); + if (s.io.stream) + light_param_face_write_inner(face, &s); + io_free(&s); + free(path_txt); +} + +void light_param_face_wwrite(light_param_face* face, wchar_t* path) { + if (!face || !path || !face->ready) + return; + + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + stream s; + io_wopen(&s, path_txt, L"wb"); + if (s.io.stream) + light_param_face_write_inner(face, &s); + io_free(&s); + free(path_txt); +} + +void light_param_face_mwrite(light_param_face* face, void** data, size_t* length) { + if (!face || !data || !face->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + light_param_face_write_inner(face, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool light_param_face_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_face* face = data; + light_param_face_read(face, string_data(&s)); + + string_free(&s); + return face->ready; +} + +void light_param_face_free(light_param_face* face) { + +} + +static void light_param_face_read_inner(light_param_face* face, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = data; + + while (d = light_param_face_read_line(buf, sizeof(buf), d)) { + if (!str_utils_compare_length(buf, sizeof(buf), "offset", 6)) { + if (buf[6] != ' ' || sscanf_s(buf + 7, "%f", &face->offset) != 1) + goto End; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "scale", 5)) { + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f", &face->scale) != 1) + goto End; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "position", 8)) { + vec3* position = &face->position; + if (buf[8] != ' ' || sscanf_s(buf + 9, "%f %f %f", + &position->x, &position->y, &position->z) != 3) + goto End; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "direction", 10)) { + vec3* direction = &face->direction; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%f %f %f", + &direction->x, &direction->y, &direction->z) != 3) + goto End; + } + } + + free(data); + face->ready = true; + return; + +End: + free(data); +} + +static void light_param_face_write_inner(light_param_face* face, stream* s) { + char buf[0x100]; + + io_write(s, "offset", 6); + light_param_face_write_float_t(s, buf, sizeof(buf), face->offset); + io_write_char(s, '\n'); + + io_write(s, "scale", 5); + light_param_face_write_float_t(s, buf, sizeof(buf), face->scale); + io_write_char(s, '\n'); + + vec3* position = &face->position; + io_write(s, "position", 8); + light_param_face_write_float_t(s, buf, sizeof(buf), position->x); + light_param_face_write_float_t(s, buf, sizeof(buf), position->y); + light_param_face_write_float_t(s, buf, sizeof(buf), position->z); + io_write_char(s, '\n'); + + vec3* direction = &face->direction; + io_write(s, "direction", 9); + light_param_face_write_float_t(s, buf, sizeof(buf), direction->x); + light_param_face_write_float_t(s, buf, sizeof(buf), direction->y); + light_param_face_write_float_t(s, buf, sizeof(buf), direction->z); + io_write_char(s, '\n'); + + io_write(s, "EOF", 3); + io_write_char(s, '\n'); +} + +static char* light_param_face_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +inline static void light_param_face_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value) { + sprintf_s(buf, buf_size, " %d", value); + io_write_utf8_string(s, buf); +} + +inline static void light_param_face_write_float_t(stream* s, char* buf, size_t buf_size, float_t value) { + sprintf_s(buf, buf_size, " %g", value); + io_write_utf8_string(s, buf); +} diff --git a/src/KKdLib/light_param/face.h b/src/KKdLib/light_param/face.h new file mode 100644 index 00000000..87884df6 --- /dev/null +++ b/src/KKdLib/light_param/face.h @@ -0,0 +1,28 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../vec.h" + +typedef struct light_param_face { + bool ready; + + float_t offset; + float_t scale; + vec3 position; + vec3 direction; +} light_param_face; + +extern void light_param_face_init(light_param_face* face); +extern void light_param_face_read(light_param_face* face, char* path); +extern void light_param_face_wread(light_param_face* face, wchar_t* path); +extern void light_param_face_mread(light_param_face* face, void* data, size_t length); +extern void light_param_face_write(light_param_face* face, char* path); +extern void light_param_face_wwrite(light_param_face* face, wchar_t* path); +extern void light_param_face_mwrite(light_param_face* face, void** data, size_t* length); +extern bool light_param_face_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_face_free(light_param_face* face); diff --git a/src/KKdLib/light_param/fog.c b/src/KKdLib/light_param/fog.c new file mode 100644 index 00000000..9b95ee6b --- /dev/null +++ b/src/KKdLib/light_param/fog.c @@ -0,0 +1,270 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "fog.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_fog_read_inner(light_param_fog* fog, stream* s); +static void light_param_fog_write_inner(light_param_fog* fog, stream* s); +static char* light_param_fog_read_line(char* buf, int32_t size, char* src); +static void light_param_fog_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value); +static void light_param_fog_write_float_t(stream* s, char* buf, size_t buf_size, float_t value); + +void light_param_fog_init(light_param_fog* fog) { + memset(fog, 0, sizeof(light_param_fog)); +} + +void light_param_fog_read(light_param_fog* fog, char* path) { + char* path_txt = str_utils_add(path, ".txt"); + if (path_check_file_exists(path_txt)) { + stream s; + io_open(&s, path_txt, "rb"); + if (s.io.stream) + light_param_fog_read_inner(fog, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_fog_wread(light_param_fog* fog, wchar_t* path) { + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + if (path_wcheck_file_exists(path_txt)) { + stream s; + io_wopen(&s, path_txt, L"rb"); + if (s.io.stream) + light_param_fog_read_inner(fog, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_fog_mread(light_param_fog* fog, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_fog_read_inner(fog, &s); + io_free(&s); +} + +void light_param_fog_write(light_param_fog* fog, char* path) { + if (!fog || !path || !fog->ready) + return; + + char* path_txt = str_utils_add(path, ".txt"); + stream s; + io_open(&s, path_txt, "wb"); + if (s.io.stream) + light_param_fog_write_inner(fog, &s); + io_free(&s); + free(path_txt); +} + +void light_param_fog_wwrite(light_param_fog* fog, wchar_t* path) { + if (!fog || !path || !fog->ready) + return; + + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + stream s; + io_wopen(&s, path_txt, L"wb"); + if (s.io.stream) + light_param_fog_write_inner(fog, &s); + io_free(&s); + free(path_txt); +} + +void light_param_fog_mwrite(light_param_fog* fog, void** data, size_t* length) { + if (!fog || !data || !fog->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + light_param_fog_write_inner(fog, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool light_param_fog_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_fog* fog = data; + light_param_fog_read(fog, string_data(&s)); + + string_free(&s); + return fog->ready; +} + +void light_param_fog_free(light_param_fog* fog) { + +} + +static void light_param_fog_read_inner(light_param_fog* fog, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = data; + + int32_t group_id = -1; + while (d = light_param_fog_read_line(buf, sizeof(buf), d)) { + light_param_fog_group* group = &fog->group[group_id]; + + if (!str_utils_compare_length(buf, sizeof(buf), "group_start", 11)) { + if (group_id != -1) + goto End; + + int32_t index = 0; + if (buf[11] != ' ' || sscanf_s(buf + 12, "%d", &index) != 1) + goto End; + + group_id = index; + continue; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "group_end", 9)) { + if (group_id == -1) + goto End; + + int32_t index = 0; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%d", &index) != 1) + goto End; + + if (group_id != index) + goto End; + + group_id = -1; + continue; + } + else if (group_id == -1) + continue; + + if (!str_utils_compare_length(buf, sizeof(buf), "type", 4)) { + if (buf[4] != ' ' || sscanf_s(buf + 5, "%d", (int32_t*)&group->type) != 1) + goto End; + + group->has_type = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "density", 7)) { + if (buf[7] != ' ' || sscanf_s(buf + 8, "%f", &group->density) != 1) + goto End; + + group->has_density = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "linear", 6)) { + if (buf[6] != ' ' || sscanf_s(buf + 7, "%f %f", + &group->linear_start, &group->linear_end) != 2) + goto End; + + group->has_linear = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "color", 5)) { + vec4u* color = &group->color; + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f %f %f %f", + &color->x, &color->y, &color->z, &color->w) != 4) + goto End; + + group->has_color = true; + } + } + + free(data); + fog->ready = true; + return; + +End: + free(data); +} + +static void light_param_fog_write_inner(light_param_fog* fog, stream* s) { + char buf[0x100]; + + for (int32_t i = 0; i < FOG_MAX; i++) { + light_param_fog_group* group = &fog->group[i]; + io_write(s, "group_start", 11); + light_param_fog_write_int32_t(s, buf, sizeof(buf), i); + io_write_char(s, '\n'); + + if (group->has_type) { + io_write(s, "type", 4); + light_param_fog_write_int32_t(s, buf, sizeof(buf), (int32_t)group->type); + io_write_char(s, '\n'); + } + + if (group->has_density) { + io_write(s, "density", 7); + light_param_fog_write_float_t(s, buf, sizeof(buf), group->density); + io_write_char(s, '\n'); + } + + if (group->has_linear) { + io_write(s, "linear", 6); + light_param_fog_write_float_t(s, buf, sizeof(buf), group->linear_start); + light_param_fog_write_float_t(s, buf, sizeof(buf), group->linear_end); + io_write_char(s, '\n'); + } + + if (group->has_color) { + vec4u* color = &group->color; + io_write(s, "color", 5); + light_param_fog_write_float_t(s, buf, sizeof(buf), color->x); + light_param_fog_write_float_t(s, buf, sizeof(buf), color->y); + light_param_fog_write_float_t(s, buf, sizeof(buf), color->z); + light_param_fog_write_float_t(s, buf, sizeof(buf), color->w); + io_write_char(s, '\n'); + } + + io_write(s, "group_end", 9); + light_param_fog_write_int32_t(s, buf, sizeof(buf), i); + io_write_char(s, '\n'); + } + + io_write(s, "EOF", 3); + io_write_char(s, '\n'); +} + +static char* light_param_fog_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +inline static void light_param_fog_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value) { + sprintf_s(buf, buf_size, " %d", value); + io_write_utf8_string(s, buf); +} + +inline static void light_param_fog_write_float_t(stream* s, char* buf, size_t buf_size, float_t value) { + sprintf_s(buf, buf_size, " %#.6g", value); + io_write_utf8_string(s, buf); +} diff --git a/src/KKdLib/light_param/fog.h b/src/KKdLib/light_param/fog.h new file mode 100644 index 00000000..59df542a --- /dev/null +++ b/src/KKdLib/light_param/fog.h @@ -0,0 +1,51 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../vec.h" + +typedef enum fog_id { + FOG_DEPTH = 0x00, + FOG_HEIGHT = 0x01, + FOG_BUMP = 0x02, + FOG_MAX = 0x03, +} fog_id; + +typedef enum fog_type { + FOG_NONE = 0x00, + FOG_LINEAR = 0x01, + FOG_EXP = 0x02, + FOG_EXP2 = 0x03, +} fog_type; + +typedef struct light_param_fog_group { + bool has_type; + fog_type type; + bool has_density; + float_t density; + bool has_linear; + float_t linear_start; + float_t linear_end; + bool has_color; + vec4u color; +} light_param_fog_group; + +typedef struct light_param_fog { + bool ready; + + light_param_fog_group group[FOG_MAX]; +} light_param_fog; + +extern void light_param_fog_init(light_param_fog* fog); +extern void light_param_fog_read(light_param_fog* fog, char* path); +extern void light_param_fog_wread(light_param_fog* fog, wchar_t* path); +extern void light_param_fog_mread(light_param_fog* fog, void* data, size_t length); +extern void light_param_fog_write(light_param_fog* fog, char* path); +extern void light_param_fog_wwrite(light_param_fog* fog, wchar_t* path); +extern void light_param_fog_mwrite(light_param_fog* fog, void** data, size_t* length); +extern bool light_param_fog_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_fog_free(light_param_fog* fog); diff --git a/src/KKdLib/light_param/glow.c b/src/KKdLib/light_param/glow.c new file mode 100644 index 00000000..30ba51cf --- /dev/null +++ b/src/KKdLib/light_param/glow.c @@ -0,0 +1,340 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "glow.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_glow_read_inner(light_param_glow* glow, stream* s); +static void light_param_glow_write_inner(light_param_glow* glow, stream* s); +static char* light_param_glow_read_line(char* buf, int32_t size, char* src); +static void light_param_glow_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value); +static void light_param_glow_write_float_t(stream* s, char* buf, size_t buf_size, float_t value); + +void light_param_glow_init(light_param_glow* glow) { + memset(glow, 0, sizeof(light_param_glow)); +} + +void light_param_glow_read(light_param_glow* glow, char* path) { + char* path_txt = str_utils_add(path, ".txt"); + if (path_check_file_exists(path_txt)) { + stream s; + io_open(&s, path_txt, "rb"); + if (s.io.stream) + light_param_glow_read_inner(glow, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_glow_wread(light_param_glow* glow, wchar_t* path) { + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + if (path_wcheck_file_exists(path_txt)) { + stream s; + io_wopen(&s, path_txt, L"rb"); + if (s.io.stream) + light_param_glow_read_inner(glow, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_glow_mread(light_param_glow* glow, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_glow_read_inner(glow, &s); + io_free(&s); +} + +void light_param_glow_write(light_param_glow* glow, char* path) { + if (!glow || !path || !glow->ready) + return; + + char* path_txt = str_utils_add(path, ".txt"); + stream s; + io_open(&s, path_txt, "wb"); + if (s.io.stream) + light_param_glow_write_inner(glow, &s); + io_free(&s); + free(path_txt); +} + +void light_param_glow_wwrite(light_param_glow* glow, wchar_t* path) { + if (!glow || !path || !glow->ready) + return; + + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + stream s; + io_wopen(&s, path_txt, L"wb"); + if (s.io.stream) + light_param_glow_write_inner(glow, &s); + io_free(&s); + free(path_txt); +} + +void light_param_glow_mwrite(light_param_glow* glow, void** data, size_t* length) { + if (!glow || !data || !glow->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + light_param_glow_write_inner(glow, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool light_param_glow_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_glow* glow = data; + light_param_glow_read(glow, string_data(&s)); + + string_free(&s); + return glow->ready; +} + +void light_param_glow_free(light_param_glow* glow) { + +} + +static void light_param_glow_read_inner(light_param_glow* glow, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = data; + + while (d = light_param_glow_read_line(buf, sizeof(buf), d)) { + if (!str_utils_compare_length(buf, sizeof(buf), "exposure", 8)) { + if (buf[8] != ' ' || sscanf_s(buf + 9, "%f", &glow->exposure) != 1) + goto End; + + glow->has_exposure = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "gamma", 5)) { + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f", &glow->gamma) != 1) + goto End; + + glow->has_gamma = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "saturate_power", 14)) { + if (buf[14] != ' ' || sscanf_s(buf + 15, "%d", &glow->saturate_power) != 1) + goto End; + + glow->has_saturate_power = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "saturate_coef", 13)) { + if (buf[13] != ' ' || sscanf_s(buf + 14, "%f", &glow->saturate_coef) != 1) + goto End; + + glow->has_saturate_coef = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "flare", 5)) { + vec3* flare = &glow->flare; + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f %f %f", + &flare->x, &flare->y, &flare->z) != 3) + goto End; + + glow->has_flare = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "sigma", 5)) { + vec3* sigma = &glow->sigma; + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f %f %f", + &sigma->x, &sigma->y, &sigma->z) != 3) + goto End; + + glow->has_sigma = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "intensity", 9)) { + vec3* intensity = &glow->intensity; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%f %f %f", + &intensity->x, &intensity->y, &intensity->z) != 3) + goto End; + + glow->has_intensity = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "auto_exposure", 13)) { + int32_t auto_exposure = 0; + if (buf[13] != ' ' || sscanf_s(buf + 14, "%d", &auto_exposure) != 1) + goto End; + + glow->auto_exposure = auto_exposure ? true : false; + glow->has_auto_exposure = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "tone_map_method", 15)) { + if (buf[15] != ' ' || sscanf_s(buf + 16, "%d", (int32_t*)&glow->tone_map_method) != 1) + goto End; + + glow->has_tone_map_method = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "fade_color", 10)) { + vec4u* fade_color = &glow->fade_color; + int32_t* blend_func = &glow->fade_color_blend_func; + if (buf[10] != ' ' || sscanf_s(buf + 11, "%f %f %f %f %d", + &fade_color->x, &fade_color->y, &fade_color->z, &fade_color->w, blend_func) != 5) + goto End; + + glow->has_fade_color = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "tone_transform", 14)) { + vec3* start = &glow->tone_transform_start; + vec3* end = &glow->tone_transform_end; + if (buf[14] != ' ' || sscanf_s(buf + 15, "%f %f %f %f %f %f", + &start->x, &start->y, &start->z, &end->x, &end->y, &end->z) != 6) + goto End; + + glow->has_tone_transform = true; + } + } + + free(data); + glow->ready = true; + return; + +End: + free(data); +} + +static void light_param_glow_write_inner(light_param_glow* glow, stream* s) { + char buf[0x100]; + + if (glow->has_exposure) { + io_write(s, "exposure", 8); + light_param_glow_write_float_t(s, buf, sizeof(buf), glow->exposure); + io_write_char(s, '\n'); + } + + if (glow->has_gamma) { + io_write(s, "gamma", 5); + light_param_glow_write_float_t(s, buf, sizeof(buf), glow->gamma); + io_write_char(s, '\n'); + } + + if (glow->has_saturate_power) { + io_write(s, "saturate_power", 14); + light_param_glow_write_int32_t(s, buf, sizeof(buf), glow->saturate_power); + io_write_char(s, '\n'); + } + + if (glow->has_saturate_coef) { + io_write(s, "saturate_coef", 13); + light_param_glow_write_float_t(s, buf, sizeof(buf), glow->saturate_coef); + io_write_char(s, '\n'); + } + + if (glow->has_flare) { + vec3* flare = &glow->flare; + io_write(s, "flare", 5); + light_param_glow_write_float_t(s, buf, sizeof(buf), flare->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), flare->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), flare->z); + io_write_char(s, '\n'); + } + + if (glow->has_sigma) { + vec3* sigma = &glow->sigma; + io_write(s, "sigma", 5); + light_param_glow_write_float_t(s, buf, sizeof(buf), sigma->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), sigma->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), sigma->z); + io_write_char(s, '\n'); + } + + if (glow->has_intensity) { + vec3* intensity = &glow->intensity; + io_write(s, "intensity", 9); + light_param_glow_write_float_t(s, buf, sizeof(buf), intensity->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), intensity->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), intensity->z); + io_write_char(s, '\n'); + } + + if (glow->has_auto_exposure) { + io_write(s, "exposure", 8); + light_param_glow_write_int32_t(s, buf, sizeof(buf), glow->auto_exposure ? 1 : 0); + io_write_char(s, '\n'); + } + + if (glow->has_tone_map_method) { + io_write(s, "tone_map_method", 15); + light_param_glow_write_int32_t(s, buf, sizeof(buf), (int32_t)glow->tone_map_method); + io_write_char(s, '\n'); + } + + if (glow->has_fade_color) { + vec4u* fade_color = &glow->fade_color; + int32_t blend_func = glow->fade_color_blend_func; + io_write(s, "fade_color", 10); + light_param_glow_write_float_t(s, buf, sizeof(buf), fade_color->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), fade_color->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), fade_color->z); + light_param_glow_write_float_t(s, buf, sizeof(buf), fade_color->w); + light_param_glow_write_int32_t(s, buf, sizeof(buf), blend_func); + io_write_char(s, '\n'); + } + + if (glow->has_tone_transform) { + vec3* start = &glow->tone_transform_start; + vec3* end = &glow->tone_transform_end; + io_write(s, "tone_transform", 14); + light_param_glow_write_float_t(s, buf, sizeof(buf), start->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), start->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), start->z); + light_param_glow_write_float_t(s, buf, sizeof(buf), end->x); + light_param_glow_write_float_t(s, buf, sizeof(buf), end->y); + light_param_glow_write_float_t(s, buf, sizeof(buf), end->z); + io_write_char(s, '\n'); + } + + io_write(s, "EOF", 3); + io_write_char(s, '\n'); +} + +static char* light_param_glow_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +inline static void light_param_glow_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value) { + sprintf_s(buf, buf_size, " %d", value); + io_write_utf8_string(s, buf); +} + +inline static void light_param_glow_write_float_t(stream* s, char* buf, size_t buf_size, float_t value) { + sprintf_s(buf, buf_size, " %#.6g", value); + io_write_utf8_string(s, buf); +} diff --git a/src/KKdLib/light_param/glow.h b/src/KKdLib/light_param/glow.h new file mode 100644 index 00000000..7f6dc3e2 --- /dev/null +++ b/src/KKdLib/light_param/glow.h @@ -0,0 +1,54 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../vec.h" + +typedef enum tone_map_method { + TONE_MAP_YCC_EXPONENT = 0, + TONE_MAP_RGB_LINEAR = 1, + TONE_MAP_RGB_LINEAR2 = 2, +} tone_map_method; + +typedef struct light_param_glow { + bool ready; + + bool has_exposure; + float_t exposure; + bool has_gamma; + float_t gamma; + bool has_saturate_power; + int32_t saturate_power; + bool has_saturate_coef; + float_t saturate_coef; + bool has_flare; + vec3 flare; + bool has_sigma; + vec3 sigma; + bool has_intensity; + vec3 intensity; + bool has_auto_exposure; + bool auto_exposure; + bool has_tone_map_method; + tone_map_method tone_map_method; + bool has_fade_color; + vec4u fade_color; + int32_t fade_color_blend_func; + bool has_tone_transform; + vec3 tone_transform_start; + vec3 tone_transform_end; +} light_param_glow; + +extern void light_param_glow_init(light_param_glow* glow); +extern void light_param_glow_read(light_param_glow* glow, char* path); +extern void light_param_glow_wread(light_param_glow* glow, wchar_t* path); +extern void light_param_glow_mread(light_param_glow* glow, void* data, size_t length); +extern void light_param_glow_write(light_param_glow* glow, char* path); +extern void light_param_glow_wwrite(light_param_glow* glow, wchar_t* path); +extern void light_param_glow_mwrite(light_param_glow* glow, void** data, size_t* length); +extern bool light_param_glow_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_glow_free(light_param_glow* glow); diff --git a/src/KKdLib/light_param/ibl.c b/src/KKdLib/light_param/ibl.c new file mode 100644 index 00000000..ab5db95a --- /dev/null +++ b/src/KKdLib/light_param/ibl.c @@ -0,0 +1,445 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "ibl.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_ibl_read_inner(light_param_ibl* ibl, stream* s); +static char* light_param_ibl_read_line(char* buf, int32_t size, char* src); +static void light_param_ibl_specular_generate_mipmaps(light_param_ibl_specular* specular); +static void light_param_ibl_specular_generate_mipmap(float_t* src, float_t* dst, size_t size); + +void light_param_ibl_init(light_param_ibl* ibl) { + memset(ibl, 0, sizeof(light_param_ibl)); +} + +void light_param_ibl_read(light_param_ibl* ibl, char* path) { + char* path_ibl = str_utils_add(path, ".ibl"); + if (path_check_file_exists(path_ibl)) { + stream s; + io_open(&s, path_ibl, "rb"); + if (s.io.stream) + light_param_ibl_read_inner(ibl, &s); + io_free(&s); + } + free(path_ibl); +} + +void light_param_ibl_wread(light_param_ibl* ibl, wchar_t* path) { + wchar_t* path_ibl = str_utils_wadd(path, L".ibl"); + if (path_wcheck_file_exists(path_ibl)) { + stream s; + io_wopen(&s, path_ibl, L"rb"); + if (s.io.stream) + light_param_ibl_read_inner(ibl, &s); + io_free(&s); + } + free(path_ibl); +} + +void light_param_ibl_mread(light_param_ibl* ibl, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_ibl_read_inner(ibl, &s); + io_free(&s); +} + +bool light_param_ibl_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_ibl* ibl = data; + light_param_ibl_read(ibl, string_data(&s)); + + string_free(&s); + return ibl->ready; +} + +void light_param_ibl_free(light_param_ibl* ibl) { + for (int32_t i = 0; i < 2; i++) + free(ibl->diffuse[i].data); + + for (int32_t i = 0; i < 4; i++) { + light_param_ibl_specular* specular = &ibl->specular[i]; + if (specular->data) + for (int32_t j = 0; j <= specular->max_level; j++) + free(specular->data[j]); + free(specular->data); + } +} + +static void light_param_ibl_read_inner(light_param_ibl* ibl, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = light_param_ibl_read_line(buf, sizeof(buf), data); + if (str_utils_compare(buf, "VF5_IBL")) + return; + + int32_t widths[6] = { 0 }; + int32_t heights[6] = { 0 }; + while (d) { + do + d = light_param_ibl_read_line(buf, sizeof(buf), d); + while (buf[0] == '#'); + + if (!str_utils_compare(buf, "VERSION")) + d = light_param_ibl_read_line(buf, sizeof(buf), d); + else if (!str_utils_compare(buf, "LIT_DIR")) { + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + int32_t index; + if (sscanf_s(buf, "%d", &index) != 1) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + vec4 dir; + if (sscanf_s(buf, "%f %f %f", &dir.x, &dir.y, &dir.z) != 3) + goto End; + + dir.w = 0.0f; + ibl->lit_dir[index] = dir; + } + else if (!str_utils_compare(buf, "LIT_COL")) { + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + int32_t index; + if (sscanf_s(buf, "%d", &index) != 1) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + vec4 col; + if (sscanf_s(buf, "%f %f %f", &col.x, &col.y, &col.z) != 3) + goto End; + + col.w = 0.0f; + ibl->lit_col[index] = col; + } + else if (!str_utils_compare(buf, "DIFF_COEF")) { + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + int32_t index; + if (sscanf_s(buf, "%d", &index) != 1) + goto End; + + for (int32_t i = 0; i < 3; i++) { + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + mat4* mat = &ibl->diff_coef[index][i]; + if (sscanf_s(buf, "%f %f %f %f", &mat->row0.x, &mat->row1.x, &mat->row2.x, &mat->row3.x) != 4) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + if (sscanf_s(buf, "%f %f %f %f", &mat->row0.y, &mat->row1.y, &mat->row2.y, &mat->row3.y) != 4) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + if (sscanf_s(buf, "%f %f %f %f", &mat->row0.z, &mat->row1.z, &mat->row2.z, &mat->row3.z) != 4) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + if (sscanf_s(buf, "%f %f %f %f", &mat->row0.w, &mat->row1.w, &mat->row2.w, &mat->row3.w) != 4) + goto End; + } + } + else if (!str_utils_compare(buf, "LIGHT_MAP")) { + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + int32_t index; + if (sscanf_s(buf, "%d", &index) != 1) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + if (str_utils_compare(buf, "RGBA16F_CUBE")) + goto End; + + d = light_param_ibl_read_line(buf, sizeof(buf), d); + + int32_t w; + int32_t h; + if (sscanf_s(buf, "%d %d", &w, &h) != 2) + goto End; + + widths[index] = w; + heights[index] = h; + } + else if (!str_utils_compare(buf, "BINARY")) { + half_t* dh = (half_t*)d; + for (int32_t i = 0, j = -2; i < 6; i++, j++) { + size_t size = widths[i]; + size = 4 * (size * size); + + if (i < 2) { + light_param_ibl_diffuse* diffuse = &ibl->diffuse[i]; + diffuse->data = force_malloc_s(half_t, size * 6); + diffuse->size = widths[i]; + for (int32_t k = 0; k < 6; k++, dh += size) + memcpy(&diffuse->data[size * k], dh, sizeof(half_t) * size); + } + else { + const int32_t max_level = 2; + + light_param_ibl_specular* specular = &ibl->specular[j]; + specular->data = force_malloc_s(half_t*, max_level + 1ULL); + specular->max_level = max_level; + specular->size = widths[i]; + + size_t img_size = widths[i]; + for (int32_t i = 0; i <= max_level; i++, img_size /= 2) + specular->data[i] = force_malloc_s(half_t, 4 * (img_size * img_size) * 6); + + half_t* specular_data = specular->data[0]; + for (int32_t k = 0; k < 6; k++, dh += size) + memcpy(&specular_data[size * k], dh, sizeof(half_t) * size); + + light_param_ibl_specular_generate_mipmaps(specular); + } + } + break; + } + else + goto End; + } + + free(data); + ibl->ready = true; + return; + +End: + free(data); +} + +static char* light_param_ibl_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +static void light_param_ibl_specular_generate_mipmaps(light_param_ibl_specular* specular) { + size_t size = specular->size; + int32_t max_level = specular->max_level; + + float_t* data_f32[2]; + data_f32[0] = force_malloc_s(float_t, 4 * (size * size) * 6); + data_f32[1] = force_malloc_s(float_t, 4 * ((size / 2) * (size / 2)) * 6); + for (int32_t i = 0; i < max_level; i++, size /= 2) { + size_t data_size = 4 * (size * size) * 6; + size_t data_size_2 = 4 * ((size / 2) * (size / 2)) * 6; + + if (!i) { + half_t* data = specular->data[i]; + float_t* temp = data_f32[0]; + for (size_t j = 0; j < data_size; j++) + temp[j] = half_to_float(data[j]); + } + + light_param_ibl_specular_generate_mipmap(data_f32[0], data_f32[1], (int32_t)size); + + float_t* temp = data_f32[0]; + data_f32[0] = data_f32[1]; + data_f32[1] = temp; + + half_t* data = specular->data[i + 1]; + temp = data_f32[0]; + for (size_t j = 0; j < data_size_2; j++) + data[j] = float_to_half(temp[j]); + } + free(data_f32[0]); + free(data_f32[1]); +} + +static void light_param_ibl_specular_generate_mipmap(float_t* src, float_t* dst, size_t size) { + const float_t kernel[] = { + 0.025f, 0.050f, 0.050f, 0.025f, + 0.050f, 0.125f, 0.125f, 0.050f, + 0.050f, 0.125f, 0.125f, 0.050f, + 0.025f, 0.050f, 0.050f, 0.025f, + }; + + size_t v2; + size_t v5; + size_t v6; + size_t v7; + size_t v8; + size_t v9; + size_t v10; + size_t v11; + size_t v12; + size_t v13; + size_t v14; + size_t v15; + size_t v16; + size_t v17; + float_t v18; + size_t v19; + float_t v20; + float_t v21; + size_t v22; + float_t v23; + float_t* v24; + size_t v25; + float_t* v26; + float_t* v27; + size_t v28; + float_t v29; + float_t v30; + float_t v31; + float_t* v32; + float_t* v33; + size_t v34; + float_t v35; + size_t v36; + size_t v37; + size_t v38; + size_t v39; + size_t v40; + size_t v41; + size_t v43; + size_t v44; + + v2 = size; + v5 = size / 2; + v6 = 0; + v7 = 0; + v44 = 0; + v40 = v5; + v43 = 4 * v5 * v5; + v8 = v43; + v9 = 6; + v10 = 4 * v2 * v2; + v37 = 6; + do { + v11 = 0; + if (v5) { + v12 = v5 - 1; + v39 = v5 - 1; + do { + v13 = 0; + v14 = 4; + if (!v11) + v13 = 1; + if (v11 == v12) + v14 = 3; + v15 = 0; + v41 = v13; + v16 = v5 * v11; + v38 = v5 * v11; + do { + v17 = 0; + v18 = 0.0; + if (!v15) + v17 = 1; + v19 = 4; + if (v15 == v12) + v19 = 3; + v20 = 0.0; + v21 = 0.0; + v22 = v13; + v23 = 0.0; + if (v13 < v14) { + v24 = (float_t*)&kernel[4 * v13 + 1 + v17]; + do { + v25 = v17; + if (v17 < v19) { + if ((v19 - v17) >= 4) { + v26 = v24; + v27 = &src[8 * v15 + 6 + 4 * v17 + 4 * v2 * (v22 + 2 * v11 - 1) + v7]; + v28 = ((v19 - v17 - 4) >> 2) + 1; + v25 = v17 + 4 * v28; + do { + v29 = *(v26 - 1); + v30 = *v26; + v27 += 16; + v26 += 4; + v31 = *(v26 - 2); + v18 += v29 + v30 + *(v26 - 3) + v31; + v21 += v29 * *(v27 - 25) + v30 * *(v27 - 21) + *(v26 - 3) * *(v27 - 17) + v31 * *(v27 - 13); + v23 += v29 * *(v27 - 26) + v30 * *(v27 - 22) + *(v26 - 3) * *(v27 - 18) + v31 * *(v27 - 14); + v20 += v29 * *(v27 - 24) + v30 * *(v27 - 20) + *(v26 - 3) * *(v27 - 16) + v31 * *(v27 - 12); + --v28; + } while (v28); + } + + if (v25 < v19) { + v32 = (float_t*)&kernel[4 * v22 + v25]; + v33 = &src[8 * v15 - 2 + 4 * v25 + 4 * v2 * (v22 + 2 * v11 - 1) + v7]; + v34 = v19 - v25; + do { + v35 = *v32; + v33 += 4; + ++v32; + v18 = v18 + v35; + v23 += v35 * *(v33 - 6); + v21 += v35 * *(v33 - 5); + v20 += v35 * *(v33 - 4); + --v34; + } while (v34); + } + } + ++v22; + v24 += 4; + } while (v22 < v14); + v16 = v38; + v12 = v39; + v6 = v44; + } + v36 = v6 + 4 * (v16 + v15++); + v18 = 1.0f / v18; + dst[v36] = v18 * v23; + dst[v36 + 1] = v18 * v21; + dst[v36 + 2] = v18 * v20; + dst[v36 + 3] = 1.0f; + v5 = v40; + v13 = v41; + } while (v15 < v40); + ++v11; + } while (v11 < v40); + v9 = v37; + v8 = v43; + v10 = 4 * v2 * v2; + } + v6 += v8; + v7 += v10; + v37 = --v9; + v44 = v6; + } while (v9); +} diff --git a/src/KKdLib/light_param/ibl.h b/src/KKdLib/light_param/ibl.h new file mode 100644 index 00000000..a0ff674d --- /dev/null +++ b/src/KKdLib/light_param/ibl.h @@ -0,0 +1,39 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../half_t.h" +#include "../mat.h" +#include "../vec.h" + +typedef struct light_param_ibl_diffuse { + half_t* data; + int32_t size; +} light_param_ibl_diffuse; + +typedef struct light_param_ibl_specular { + half_t** data; + int32_t max_level; + int32_t size; +} light_param_ibl_specular; + +typedef struct light_param_ibl { + bool ready; + + vec4 lit_col[4]; + vec4 lit_dir[4]; + mat4 diff_coef[4][3]; + light_param_ibl_diffuse diffuse[2]; + light_param_ibl_specular specular[4]; +} light_param_ibl; + +extern void light_param_ibl_init(light_param_ibl* id); +extern void light_param_ibl_read(light_param_ibl* id, char* path); +extern void light_param_ibl_wread(light_param_ibl* id, wchar_t* path); +extern void light_param_ibl_mread(light_param_ibl* id, void* data, size_t length); +extern bool light_param_ibl_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_ibl_free(light_param_ibl* id); diff --git a/src/KKdLib/light_param/light.c b/src/KKdLib/light_param/light.c new file mode 100644 index 00000000..4bc9a051 --- /dev/null +++ b/src/KKdLib/light_param/light.c @@ -0,0 +1,436 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "light.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_light_read_inner(light_param_light* light, stream* s); +static void light_param_light_write_inner(light_param_light* light, stream* s); +static char* light_param_light_read_line(char* buf, int32_t size, char* src); +static void light_param_light_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value); +static void light_param_light_write_float_t(stream* s, char* buf, size_t buf_size, float_t value); + +void light_param_light_init(light_param_light* light) { + memset(light, 0, sizeof(light_param_light)); +} + +void light_param_light_read(light_param_light* light, char* path) { + char* path_txt = str_utils_add(path, ".txt"); + if (path_check_file_exists(path_txt)) { + stream s; + io_open(&s, path_txt, "rb"); + if (s.io.stream) + light_param_light_read_inner(light, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_light_wread(light_param_light* light, wchar_t* path) { + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + if (path_wcheck_file_exists(path_txt)) { + stream s; + io_wopen(&s, path_txt, L"rb"); + if (s.io.stream) + light_param_light_read_inner(light, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_light_mread(light_param_light* light, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_light_read_inner(light, &s); + io_free(&s); +} + +void light_param_light_write(light_param_light* light, char* path) { + if (!light || !path || !light->ready) + return; + + char* path_txt = str_utils_add(path, ".txt"); + stream s; + io_open(&s, path_txt, "wb"); + if (s.io.stream) + light_param_light_write_inner(light, &s); + io_free(&s); + free(path_txt); +} + +void light_param_light_wwrite(light_param_light* light, wchar_t* path) { + if (!light || !path || !light->ready) + return; + + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + stream s; + io_wopen(&s, path_txt, L"wb"); + if (s.io.stream) + light_param_light_write_inner(light, &s); + io_free(&s); + free(path_txt); +} + +void light_param_light_mwrite(light_param_light* light, void** data, size_t* length) { + if (!light || !data || !light->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + light_param_light_write_inner(light, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool light_param_light_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_light* light = data; + light_param_light_read(light, string_data(&s)); + + string_free(&s); + return light->ready; +} + +void light_param_light_free(light_param_light* light) { + +} + +static void light_param_light_read_inner(light_param_light* light, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = data; + + int32_t group_id = -1; + int32_t light_id = -1; + while (d = light_param_light_read_line(buf, sizeof(buf), d)) { + light_param_light_group* group = &light->group[group_id]; + light_param_light_data* light = &group->data[light_id]; + + if (!str_utils_compare_length(buf, sizeof(buf), "group_start", 11)) { + if (group_id != -1) + goto End; + + int32_t index = 0; + if (buf[11] != ' ' || sscanf_s(buf + 12, "%d", &index) != 1) + goto End; + + group_id = index; + continue; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "group_end", 9)) { + if (group_id == -1) + goto End; + + int32_t index = 0; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%d", &index) != 1) + goto End; + + if (group_id != index) + goto End; + + group_id = -1; + continue; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "id_start", 8)) { + if (light_id != -1) + goto End; + + int32_t index = 0; + if (buf[8] != ' ' || sscanf_s(buf + 9, "%d", &index) != 1) + goto End; + + light_id = index; + continue; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "id_end", 6)) { + if (light_id == -1) + goto End; + + int32_t index = 0; + if (buf[6] != ' ' || sscanf_s(buf + 7, "%d", &index) != 1) + goto End; + + if (light_id != index) + goto End; + + light_id = -1; + continue; + } + else if (group_id == -1 || light_id == -1) + continue; + + if (!str_utils_compare_length(buf, sizeof(buf), "type", 4)) { + if (buf[4] != ' ' || sscanf_s(buf + 5, "%d", (int32_t*)&light->type) != 1) + goto End; + + light->has_type = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "ambient", 7)) { + vec4u* ambient = &light->ambient; + if (buf[7] != ' ' || sscanf_s(buf + 8, "%f %f %f %f", + &ambient->x, &ambient->y, &ambient->z, &ambient->w) != 4) + goto End; + + light->has_ambient = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "diffuse", 7)) { + vec4u* diffuse = &light->diffuse; + if (buf[7] != ' ' || sscanf_s(buf + 8, "%f %f %f %f", + &diffuse->x, &diffuse->y, &diffuse->z, &diffuse->w) != 4) + goto End; + + light->has_diffuse = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "specular", 8)) { + vec4u* specular = &light->specular; + if (buf[8] != ' ' || sscanf_s(buf + 9, "%f %f %f %f", + &specular->x, &specular->y, &specular->z, &specular->w) != 4) + goto End; + + light->has_specular = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "position", 8)) { + vec3* position = &light->position; + float_t position_w = 0.0f; + if (buf[8] != ' ' || sscanf_s(buf + 9, "%f %f %f %f", + &position->x, &position->y, &position->z, &position_w) != 4) + goto End; + + light->has_position = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "spot_direction", 14)) { + vec3* spot_direction = &light->spot_direction; + if (buf[14] != ' ' || sscanf_s(buf + 15, "%f %f %f", + &spot_direction->x, &spot_direction->y, &spot_direction->z) != 3) + goto End; + + light->has_spot_direction = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "spot_exponent", 13)) { + if (buf[13] != ' ' || sscanf_s(buf + 14, "%f", &light->spot_exponent) != 1) + goto End; + + light->has_spot_exponent = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "spot_cutoff", 11)) { + if (buf[11] != ' ' || sscanf_s(buf + 12, "%f", &light->spot_cutoff) != 1) + goto End; + + light->has_spot_cutoff = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "attenuation", 11)) { + vec3* attenuation = &light->attenuation; + if (buf[11] != ' ' || sscanf_s(buf + 12, "%f %f %f", + &attenuation->x, &attenuation->y, &attenuation->z) != 3) + goto End; + + light->has_attenuation = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "clipplane", 9)) { + int32_t clip_plane[4]; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%d %d %d %d", + &clip_plane[0], &clip_plane[1], &clip_plane[2], &clip_plane[3]) != 4) + goto End; + + light->clip_plane[0] = clip_plane[0] ? true : false; + light->clip_plane[1] = clip_plane[1] ? true : false; + light->clip_plane[2] = clip_plane[2] ? true : false; + light->clip_plane[3] = clip_plane[3] ? true : false; + light->has_clip_plane = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "tonecurve", 9)) { + vec3* tone_curve = &light->tone_curve; + if (buf[9] != ' ' || sscanf_s(buf + 10, "%f %f %f", + &tone_curve->x, &tone_curve->y, &tone_curve->z) != 3) + goto End; + + light->has_tone_curve = true; + } + } + + free(data); + light->ready = true; + return; + +End: + free(data); +} + +static void light_param_light_write_inner(light_param_light* light, stream* s) { + char buf[0x100]; + + for (int32_t i = 0; i < LIGHT_SET_MAX; i++) { + light_param_light_group* group = &light->group[i]; + io_write(s, "group_start", 11); + light_param_light_write_int32_t(s, buf, sizeof(buf), i); + io_write_char(s, '\n'); + + for (int32_t j = 0; j < LIGHT_MAX; j++) { + light_param_light_data* light = &group->data[j]; + io_write(s, "id_start", 8); + light_param_light_write_int32_t(s, buf, sizeof(buf), j); + io_write_char(s, '\n'); + + if (light->has_type) { + io_write(s, "type", 4); + light_param_light_write_int32_t(s, buf, sizeof(buf), (int32_t)light->type); + io_write_char(s, '\n'); + } + + if (light->has_ambient) { + vec4u* ambient = &light->ambient; + io_write(s, "ambient", 7); + light_param_light_write_float_t(s, buf, sizeof(buf), ambient->x); + light_param_light_write_float_t(s, buf, sizeof(buf), ambient->y); + light_param_light_write_float_t(s, buf, sizeof(buf), ambient->z); + light_param_light_write_float_t(s, buf, sizeof(buf), ambient->w); + io_write_char(s, '\n'); + } + + if (light->has_diffuse) { + vec4u* diffuse = &light->diffuse; + io_write(s, "diffuse", 7); + light_param_light_write_float_t(s, buf, sizeof(buf), diffuse->x); + light_param_light_write_float_t(s, buf, sizeof(buf), diffuse->y); + light_param_light_write_float_t(s, buf, sizeof(buf), diffuse->z); + light_param_light_write_float_t(s, buf, sizeof(buf), diffuse->w); + io_write_char(s, '\n'); + } + + if (light->has_specular) { + vec4u* specular = &light->specular; + io_write(s, "specular", 8); + light_param_light_write_float_t(s, buf, sizeof(buf), specular->x); + light_param_light_write_float_t(s, buf, sizeof(buf), specular->y); + light_param_light_write_float_t(s, buf, sizeof(buf), specular->z); + light_param_light_write_float_t(s, buf, sizeof(buf), specular->w); + io_write_char(s, '\n'); + } + + if (light->has_position) { + vec3* position = &light->position; + io_write(s, "position", 8); + light_param_light_write_float_t(s, buf, sizeof(buf), position->x); + light_param_light_write_float_t(s, buf, sizeof(buf), position->y); + light_param_light_write_float_t(s, buf, sizeof(buf), position->z); + light_param_light_write_float_t(s, buf, sizeof(buf), 0.0f); + io_write_char(s, '\n'); + } + + if (light->has_spot_direction) { + vec3* spot_direction = &light->spot_direction; + io_write(s, "spot_direction", 14); + light_param_light_write_float_t(s, buf, sizeof(buf), spot_direction->x); + light_param_light_write_float_t(s, buf, sizeof(buf), spot_direction->y); + light_param_light_write_float_t(s, buf, sizeof(buf), spot_direction->z); + io_write_char(s, '\n'); + } + + if (light->has_spot_exponent) { + float_t spot_exponent = light->spot_exponent; + io_write(s, "spot_exponent", 13); + light_param_light_write_float_t(s, buf, sizeof(buf), spot_exponent); + io_write_char(s, '\n'); + } + + if (light->has_spot_cutoff) { + float_t spot_cutoff = light->spot_cutoff; + io_write(s, "spot_cutoff", 11); + light_param_light_write_float_t(s, buf, sizeof(buf), spot_cutoff); + io_write_char(s, '\n'); + } + + if (light->has_attenuation) { + vec3* attenuation = &light->attenuation; + io_write(s, "attenuation", 11); + light_param_light_write_float_t(s, buf, sizeof(buf), attenuation->x); + light_param_light_write_float_t(s, buf, sizeof(buf), attenuation->y); + light_param_light_write_float_t(s, buf, sizeof(buf), attenuation->z); + io_write_char(s, '\n'); + } + + if (light->has_clip_plane) { + bool* clip_plane = light->clip_plane; + io_write(s, "clipplane", 10); + light_param_light_write_int32_t(s, buf, sizeof(buf), clip_plane[0] ? 1 : 0); + light_param_light_write_int32_t(s, buf, sizeof(buf), clip_plane[1] ? 1 : 0); + light_param_light_write_int32_t(s, buf, sizeof(buf), clip_plane[2] ? 1 : 0); + light_param_light_write_int32_t(s, buf, sizeof(buf), clip_plane[3] ? 1 : 0); + io_write_char(s, '\n'); + } + + if (light->has_tone_curve) { + vec3* tone_curve = &light->tone_curve; + io_write(s, "tonecurve", 10); + light_param_light_write_float_t(s, buf, sizeof(buf), tone_curve->x); + light_param_light_write_float_t(s, buf, sizeof(buf), tone_curve->y); + light_param_light_write_float_t(s, buf, sizeof(buf), tone_curve->z); + io_write_char(s, '\n'); + } + + io_write(s, "id_end", 6); + light_param_light_write_int32_t(s, buf, sizeof(buf), j); + io_write_char(s, '\n'); + } + + io_write(s, "group_end", 9); + light_param_light_write_int32_t(s, buf, sizeof(buf), i); + io_write_char(s, '\n'); + } + + io_write(s, "EOF", 3); + io_write_char(s, '\n'); +} + +static char* light_param_light_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +inline static void light_param_light_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value) { + sprintf_s(buf, buf_size, " %d", value); + io_write_utf8_string(s, buf); +} + +inline static void light_param_light_write_float_t(stream* s, char* buf, size_t buf_size, float_t value) { + sprintf_s(buf, buf_size, " %#.6g", value); + io_write_utf8_string(s, buf); +} diff --git a/src/KKdLib/light_param/light.h b/src/KKdLib/light_param/light.h new file mode 100644 index 00000000..c9572d4b --- /dev/null +++ b/src/KKdLib/light_param/light.h @@ -0,0 +1,78 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../vec.h" + +typedef enum light_id { + LIGHT_CHARA = 0x00, + LIGHT_STAGE = 0x01, + LIGHT_SUN = 0x02, + LIGHT_REFLECT = 0x03, + LIGHT_SHADOW = 0x04, + LIGHT_CHARA_COLOR = 0x05, + LIGHT_TONE_CURVE = 0x06, + LIGHT_PROJECTION = 0x07, + LIGHT_MAX = 0x08, +} light_id; + +typedef enum light_set_id { + LIGHT_SET_MAIN = 0x00, + LIGHT_SET_MAX = 0x01, +} light_set_id; + +typedef enum light_type { + LIGHT_OFF = 0x00, + LIGHT_PARALLEL = 0x01, + LIGHT_POINT = 0x02, + LIGHT_SPOT = 0x03, +} light_type; + +typedef struct light_param_light_data { + bool has_type; + light_type type; + bool has_ambient; + vec4u ambient; + bool has_diffuse; + vec4u diffuse; + bool has_specular; + vec4u specular; + bool has_position; + vec3 position; + bool has_spot_direction; + bool has_spot_exponent; + bool has_spot_cutoff; + bool has_attenuation; + vec3 spot_direction; + float_t spot_exponent; + float_t spot_cutoff; + vec3 attenuation; + bool has_clip_plane; + bool clip_plane[4]; + bool has_tone_curve; + vec3 tone_curve; +} light_param_light_data; + +typedef struct light_param_light_group { + light_param_light_data data[LIGHT_MAX]; +} light_param_light_group; + +typedef struct light_param_light { + bool ready; + + light_param_light_group group[LIGHT_SET_MAX]; +} light_param_light; + +extern void light_param_light_init(light_param_light* light); +extern void light_param_light_read(light_param_light* light, char* path); +extern void light_param_light_wread(light_param_light* light, wchar_t* path); +extern void light_param_light_mread(light_param_light* light, void* data, size_t length); +extern void light_param_light_write(light_param_light* light, char* path); +extern void light_param_light_wwrite(light_param_light* light, wchar_t* path); +extern void light_param_light_mwrite(light_param_light* light, void** data, size_t* length); +extern bool light_param_light_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_light_free(light_param_light* light); diff --git a/src/KKdLib/light_param/wind.c b/src/KKdLib/light_param/wind.c new file mode 100644 index 00000000..d0631fbf --- /dev/null +++ b/src/KKdLib/light_param/wind.c @@ -0,0 +1,240 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "wind.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" + +static void light_param_wind_read_inner(light_param_wind* wind, stream* s); +static void light_param_wind_write_inner(light_param_wind* wind, stream* s); +static char* light_param_wind_read_line(char* buf, int32_t size, char* src); +static void light_param_wind_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value); +static void light_param_wind_write_float_t(stream* s, char* buf, size_t buf_size, float_t value); + +void light_param_wind_init(light_param_wind* wind) { + memset(wind, 0, sizeof(light_param_wind)); +} + +void light_param_wind_read(light_param_wind* wind, char* path) { + char* path_txt = str_utils_add(path, ".txt"); + if (path_check_file_exists(path_txt)) { + stream s; + io_open(&s, path_txt, "rb"); + if (s.io.stream) + light_param_wind_read_inner(wind, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_wind_wread(light_param_wind* wind, wchar_t* path) { + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + if (path_wcheck_file_exists(path_txt)) { + stream s; + io_wopen(&s, path_txt, L"rb"); + if (s.io.stream) + light_param_wind_read_inner(wind, &s); + io_free(&s); + } + free(path_txt); +} + +void light_param_wind_mread(light_param_wind* wind, void* data, size_t length) { + stream s; + io_mopen(&s, data, length); + light_param_wind_read_inner(wind, &s); + io_free(&s); +} + +void light_param_wind_write(light_param_wind* wind, char* path) { + if (!wind || !path || !wind->ready) + return; + + char* path_txt = str_utils_add(path, ".txt"); + stream s; + io_open(&s, path_txt, "wb"); + if (s.io.stream) + light_param_wind_write_inner(wind, &s); + io_free(&s); + free(path_txt); +} + +void light_param_wind_wwrite(light_param_wind* wind, wchar_t* path) { + if (!wind || !path || !wind->ready) + return; + + wchar_t* path_txt = str_utils_wadd(path, L".txt"); + stream s; + io_wopen(&s, path_txt, L"wb"); + if (s.io.stream) + light_param_wind_write_inner(wind, &s); + io_free(&s); + free(path_txt); +} + +void light_param_wind_mwrite(light_param_wind* wind, void** data, size_t* length) { + if (!wind || !data || !wind->ready) + return; + + stream s; + io_mopen(&s, 0, 0); + light_param_wind_write_inner(wind, &s); + io_mcopy(&s, data, length); + io_free(&s); +} + +bool light_param_wind_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + light_param_wind* wind = data; + light_param_wind_read(wind, string_data(&s)); + + string_free(&s); + return wind->ready; +} + +void light_param_wind_free(light_param_wind* wind) { + +} + +static void light_param_wind_read_inner(light_param_wind* wind, stream* s) { + char* data = force_malloc(s->length + 1); + io_read(s, data, s->length); + data[s->length] = 0; + + char buf[0x100]; + char* d = data; + + while (d = light_param_wind_read_line(buf, sizeof(buf), d)) { + if (!str_utils_compare_length(buf, sizeof(buf), "scale", 5)) { + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f", &wind->scale) != 1) + goto End; + + wind->has_scale = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "cycle", 5)) { + if (buf[5] != ' ' || sscanf_s(buf + 6, "%f", &wind->cycle) != 1) + goto End; + + wind->has_cycle = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "rot", 3)) { + if (buf[3] != ' ' || sscanf_s(buf + 4, "%f %f", &wind->rot_y, &wind->rot_z) != 2) + goto End; + + wind->has_rot = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "bias", 4)) { + if (buf[4] != ' ' || sscanf_s(buf + 5, "%f", &wind->bias) != 1) + goto End; + + wind->has_bias = true; + } + else if (!str_utils_compare_length(buf, sizeof(buf), "spc", 3)) { + int32_t index = 0; + light_param_wind_spc spc; + if (buf[3] != ' ' || sscanf_s(buf + 4, "%d %f %f", + &index, &spc.cos, &spc.sin) != 3) + goto End; + + if (index >= 16) + index = 0; + + wind->spc[index] = spc; + wind->has_spc[index] = true; + } + } + + free(data); + wind->ready = true; + return; + +End: + free(data); +} + +static void light_param_wind_write_inner(light_param_wind* wind, stream* s) { + char buf[0x100]; + + if (wind->has_scale) { + io_write(s, "scale", 5); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->scale); + io_write_char(s, '\n'); + } + + if (wind->has_cycle) { + io_write(s, "cycle", 5); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->cycle); + io_write_char(s, '\n'); + } + + if (wind->has_rot) { + io_write(s, "rot", 3); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->rot_y); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->rot_z); + io_write_char(s, '\n'); + } + + if (wind->has_bias) { + io_write(s, "bias", 4); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->bias); + io_write_char(s, '\n'); + } + + for (int32_t i = 0; i < 16; i++) + if (wind->has_spc[i]) { + io_write(s, "spc", 3); + light_param_wind_write_int32_t(s, buf, sizeof(buf), i); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->spc[i].cos); + light_param_wind_write_float_t(s, buf, sizeof(buf), wind->spc[i].sin); + io_write_char(s, '\n'); + } +} + +static char* light_param_wind_read_line(char* buf, int32_t size, char* src) { + char* b = buf; + if (!src || !*src) + return 0; + + for (int32_t i = 0; i < size - 1; i++, b++) { + char c = b[0] = *src++; + if (!c) { + b++; + break; + } + else if (c == '\n') { + *b++ = 0; + break; + } + else if (c == '\r' && *src == '\n') { + *b++ = 0; + src++; + break; + } + } + + if (!str_utils_compare(buf, "EOF")) + return 0; + return src; +} + +inline static void light_param_wind_write_int32_t(stream* s, char* buf, size_t buf_size, int32_t value) { + sprintf_s(buf, buf_size, " %d", value); + io_write_utf8_string(s, buf); +} + +inline static void light_param_wind_write_float_t(stream* s, char* buf, size_t buf_size, float_t value) { + sprintf_s(buf, buf_size, " %g", value); + io_write_utf8_string(s, buf); +} diff --git a/src/KKdLib/light_param/wind.h b/src/KKdLib/light_param/wind.h new file mode 100644 index 00000000..5aee8efa --- /dev/null +++ b/src/KKdLib/light_param/wind.h @@ -0,0 +1,40 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../default.h" +#include "../vec.h" + +typedef struct light_param_wind_spc { + float_t cos; + float_t sin; +} light_param_wind_spc; + +typedef struct light_param_wind { + bool ready; + + bool has_scale; + float_t scale; + bool has_cycle; + float_t cycle; + bool has_rot; + float_t rot_y; + float_t rot_z; + bool has_bias; + float_t bias; + bool has_spc[16]; + light_param_wind_spc spc[16]; +} light_param_wind; + +extern void light_param_wind_init(light_param_wind* wind); +extern void light_param_wind_read(light_param_wind* wind, char* path); +extern void light_param_wind_wread(light_param_wind* wind, wchar_t* path); +extern void light_param_wind_mread(light_param_wind* wind, void* data, size_t length); +extern void light_param_wind_write(light_param_wind* wind, char* path); +extern void light_param_wind_wwrite(light_param_wind* wind, wchar_t* path); +extern void light_param_wind_mwrite(light_param_wind* wind, void** data, size_t* length); +extern bool light_param_wind_load_file(void* data, char* path, char* file, uint32_t hash); +extern void light_param_wind_free(light_param_wind* wind); diff --git a/src/KKdLib/mat.c b/src/KKdLib/mat.c index 3c1d7094..a9eb8e98 100644 --- a/src/KKdLib/mat.c +++ b/src/KKdLib/mat.c @@ -32,6 +32,27 @@ const mat4 mat4_null = { { 0.0f, 0.0f, 0.0f, 0.0f }, }; +const mat4u mat4u_identity = { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 1.0f }, +}; + +const mat4u mat4u_null = { + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, +}; + +vector_func(mat3) +vector_func(mat4) +vector_ptr_func(mat3) +vector_ptr_func(mat4) + +// Crutch for vector_func definition + inline void mat3_add(mat3* x, mat3* y, mat3* z) { __m128 xt; __m128 yt; @@ -150,6 +171,9 @@ inline void mat3_transpose(mat3* x, mat3* z) { *(vec3*)&xt0 = x->row0; *(vec3*)&xt1 = x->row1; *(vec3*)&xt2 = x->row2; + xt0 = _mm_and_ps(xt0, vec4_mask_vec3); + xt1 = _mm_and_ps(xt1, vec4_mask_vec3); + xt2 = _mm_and_ps(xt2, vec4_mask_vec3); xt3 = vec4_null.data; yt0 = _mm_unpacklo_ps(xt0, xt1); yt1 = _mm_unpackhi_ps(xt0, xt1); @@ -208,7 +232,7 @@ void mat3_inverse(mat3* x, mat3* z) { wt = _mm_movelh_ps(_mm_unpacklo_ps(zt0, zt1), zt2); *(vec3*)&yt = xt0; - yt.m128_f32[3] = 0.0f; + yt = _mm_and_ps(yt, vec4_mask_vec3); wt = _mm_mul_ps(yt, wt); wt = _mm_hadd_ps(wt, wt); wt = _mm_hadd_ps(wt, wt); @@ -230,6 +254,10 @@ inline void mat3_invtrans(mat3* x, mat3* z) { *z = t; } +inline void mat3_inverse_normalized(mat3* x, mat3* z) { + mat3_transpose(x, z); +} + inline void mat3_normalize(mat3* x, mat3* z) { __m128 det; __m128 xt0; @@ -254,7 +282,7 @@ void mat3_normalize_rotation(mat3* x, mat3* z) { __m128 xt; __m128 yt; *(vec3*)&xt = x->row0; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(xt, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); @@ -263,7 +291,7 @@ void mat3_normalize_rotation(mat3* x, mat3* z) { xt = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0)); z->row0 = *(vec3*)&xt; *(vec3*)&xt = x->row1; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(xt, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); @@ -272,7 +300,7 @@ void mat3_normalize_rotation(mat3* x, mat3* z) { xt = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0)); z->row1 = *(vec3*)&xt; *(vec3*)&xt = x->row2; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(xt, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); @@ -302,11 +330,19 @@ inline void mat3_rotate(float_t x, float_t y, float_t z, mat3* d) { mat3 dt; dt = mat3_identity; if (z != 0.0f) - mat3_rotate_z_mult(&dt, z, &dt); + mat3_rotate_z(z, &dt); + if (y != 0.0f) - mat3_rotate_y_mult(&dt, y, &dt); + if (z != 0.0f) + mat3_rotate_y_mult(&dt, y, &dt); + else + mat3_rotate_y(y, &dt); + if (x != 0.0f) - mat3_rotate_x_mult(&dt, x, &dt); + if (y != 0.0f || z != 0.0f) + mat3_rotate_x_mult(&dt, x, &dt); + else + mat3_rotate_x(x, &dt); *d = dt; } @@ -367,7 +403,7 @@ inline void mat3_rotate_x_mult(mat3* x, float_t y, mat3* z) { yt.row1.z = y_sin; yt.row2.y = -y_sin; yt.row2.z = y_cos; - mat3_mult(x, &yt, z); + mat3_mult(&yt, x, z); } inline void mat3_rotate_y_mult(mat3* x, float_t y, mat3* z) { @@ -379,7 +415,7 @@ inline void mat3_rotate_y_mult(mat3* x, float_t y, mat3* z) { yt.row0.z = -y_sin; yt.row2.x = y_sin; yt.row2.z = y_cos; - mat3_mult(x, &yt, z); + mat3_mult(&yt, x, z); } inline void mat3_rotate_z_mult(mat3* x, float_t y, mat3* z) { @@ -391,7 +427,7 @@ inline void mat3_rotate_z_mult(mat3* x, float_t y, mat3* z) { yt.row0.y = y_sin; yt.row1.x = -y_sin; yt.row1.y = y_cos; - mat3_mult(x, &yt, z); + mat3_mult(&yt, x, z); } inline void mat3_scale(float_t x, float_t y, float_t z, mat3* d) { @@ -506,6 +542,13 @@ inline void mat3_from_quat(quat* quat, mat3* mat) { mat->row2.z = 1.0f - yy - xx; } +inline void mat3_from_axis_angle(vec3* axis, float_t angle, mat3* mat) { + quat quat; + + quat_from_axis_angle(axis, angle, &quat); + mat3_from_quat(&quat, mat); +} + inline void mat3_from_mat4(mat4* x, mat3* z) { z->row0 = *(vec3*)&x->row0; z->row1 = *(vec3*)&x->row1; @@ -522,9 +565,9 @@ inline void mat3_from_mat4_inverse(mat4* x, mat3* z) { } inline void mat3_get_rotation(mat3* x, vec3* z) { - if (-x->row0.z >= 1.0) + if (-x->row0.z >= 1.0f) z->y = (float_t)M_PI_2; - else if (-x->row0.z <= -1.0) + else if (-x->row0.z <= -1.0f) z->y = (float_t)-M_PI_2; else z->y = asinf(-x->row0.z); @@ -546,6 +589,24 @@ inline void mat3_get_scale(mat3* x, vec3* z) { vec3_length(x->row2, z->z); } +inline float_t mat3_get_max_scale(mat3* x) { + mat3 mat; + mat3_transpose(x, &mat); + + float_t length; + float_t max = 0.0f; + vec3_length(mat.row0, length); + if (length > 0.0f) + max = length; + vec3_length(mat.row1, length); + if (length > 0.0f) + max = length; + vec3_length(mat.row2, length); + if (length > 0.0f) + max = length; + return max; +} + inline void mat4_add(mat4* x, mat4* y, mat4* z) { z->row0.data = _mm_add_ps(x->row0.data, y->row0.data); z->row1.data = _mm_add_ps(x->row1.data, y->row1.data); @@ -601,25 +662,38 @@ inline void mat4_mult(mat4* x, mat4* y, mat4* z) { } inline void mat4_mult_vec3(mat4* x, vec3* y, vec3* z) { - __m128 xt; __m128 yt; __m128 zt; __m128 zt0; __m128 zt1; __m128 zt2; *(vec3*)&yt = *y; - *(vec3*)&xt = *(vec3*)&x->row0; - zt0 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x00)); - *(vec3*)&xt = *(vec3*)&x->row1; - zt1 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x55)); - *(vec3*)&xt = *(vec3*)&x->row2; - zt2 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0xAA)); + zt0 = _mm_mul_ps(x->row0.data, _mm_shuffle_ps(yt, yt, 0x00)); + zt1 = _mm_mul_ps(x->row1.data, _mm_shuffle_ps(yt, yt, 0x55)); + zt2 = _mm_mul_ps(x->row2.data, _mm_shuffle_ps(yt, yt, 0xAA)); zt = _mm_add_ps(_mm_add_ps(zt0, zt1), zt2); *z = *(vec3*)&zt; } +inline void mat4_mult_vec3_inv(mat4* x, vec3* y, vec3* z) { + __m128 yt; + __m128 zt; + + *(vec3*)&yt = *y; + yt = _mm_and_ps(yt, vec4_mask_vec3); + yt = _mm_sub_ps(yt, x->row3.data); + zt = _mm_mul_ps(yt, x->row0.data); + zt = _mm_hadd_ps(zt, zt); + z->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); + zt = _mm_mul_ps(yt, x->row1.data); + zt = _mm_hadd_ps(zt, zt); + z->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); + zt = _mm_mul_ps(yt, x->row2.data); + zt = _mm_hadd_ps(zt, zt); + z->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); +} + inline void mat4_mult_vec3_trans(mat4* x, vec3* y, vec3* z) { - __m128 xt; __m128 yt; __m128 zt; __m128 zt0; @@ -627,17 +701,32 @@ inline void mat4_mult_vec3_trans(mat4* x, vec3* y, vec3* z) { __m128 zt2; __m128 zt3; *(vec3*)&yt = *y; - *(vec3*)&xt = *(vec3*)&x->row0; - zt0 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x00)); - *(vec3*)&xt = *(vec3*)&x->row1; - zt1 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x55)); - *(vec3*)&xt = *(vec3*)&x->row2; - zt2 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0xAA)); - *(vec3*)&zt3 = *(vec3*)&x->row3; + zt0 = _mm_mul_ps(x->row0.data, _mm_shuffle_ps(yt, yt, 0x00)); + zt1 = _mm_mul_ps(x->row1.data, _mm_shuffle_ps(yt, yt, 0x55)); + zt2 = _mm_mul_ps(x->row2.data, _mm_shuffle_ps(yt, yt, 0xAA)); + zt3 = x->row3.data; zt = _mm_add_ps(_mm_add_ps(zt0, zt1), _mm_add_ps(zt2, zt3)); *z = *(vec3*)&zt; } +inline void mat4_mult_vec3_inv_trans(mat4* x, vec3* y, vec3* z) { + __m128 yt; + __m128 zt; + + *(vec3*)&yt = *y; + yt = _mm_and_ps(yt, vec4_mask_vec3); + yt = _mm_sub_ps(yt, x->row3.data); + zt = _mm_mul_ps(yt, x->row0.data); + zt = _mm_hadd_ps(zt, zt); + z->x = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); + zt = _mm_mul_ps(yt, x->row1.data); + zt = _mm_hadd_ps(zt, zt); + z->y = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); + zt = _mm_mul_ps(yt, x->row2.data); + zt = _mm_hadd_ps(zt, zt); + z->z = _mm_cvtss_f32(_mm_hadd_ps(zt, zt)); +} + inline void mat4_mult_vec(mat4* x, vec4* y, vec4* z) { __m128 yt; __m128 zt0; @@ -783,6 +872,33 @@ inline void mat4_invrot(mat4* x, mat4* z) { z->row3 = x->row3; } +inline void mat4_inverse_normalized(mat4* x, mat4* z) { + mat3 yt; + mat3_from_mat4(x, &yt); + vec3 row3; + vec3_dot(*(vec3*)&x->row0, *(vec3*)&x->row3, row3.x); + vec3_dot(*(vec3*)&x->row1, *(vec3*)&x->row3, row3.y); + vec3_dot(*(vec3*)&x->row2, *(vec3*)&x->row3, row3.z); + mat3_transpose(&yt, &yt); + mat4_from_mat3(&yt, z); + vec3_negate(row3, *(vec3*)&z->row3); + z->row0.w = 0.0f; + z->row1.w = 0.0f; + z->row2.w = 0.0f; + z->row3.w = 1.0f; +} + +inline void mat4_invrot_normalized(mat4* x, mat4* z) { + mat3 yt; + mat3_from_mat4(x, &yt); + mat3_transpose(&yt, &yt); + mat4_from_mat3(&yt, z); + z->row0.w = x->row0.w; + z->row1.w = x->row1.w; + z->row2.w = x->row2.w; + z->row3 = x->row3; +} + inline void mat4_normalize(mat4* x, mat4* z) { __m128 det; det = _mm_set_ss(mat4_determinant(x)); @@ -798,8 +914,7 @@ inline void mat4_normalize(mat4* x, mat4* z) { void mat4_normalize_rotation(mat4* x, mat4* z) { __m128 xt; __m128 yt; - *(vec3*)&xt = *(vec3*)&x->row0; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(x->row0.data, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); @@ -807,8 +922,7 @@ void mat4_normalize_rotation(mat4* x, mat4* z) { yt.m128_f32[0] = 1.0f / yt.m128_f32[0]; xt = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0)); *(vec3*)&z->row0 = *(vec3*)&xt; - *(vec3*)&xt = *(vec3*)&x->row1; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(x->row1.data, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); @@ -816,15 +930,14 @@ void mat4_normalize_rotation(mat4* x, mat4* z) { yt.m128_f32[0] = 1.0f / yt.m128_f32[0]; xt = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0)); *(vec3*)&z->row1 = *(vec3*)&xt; - *(vec3*)&xt = *(vec3*)&x->row2; - xt.m128_f32[3] = 0.0f; + xt = _mm_and_ps(x->row2.data, vec4_mask_vec3); yt = _mm_mul_ps(xt, xt); yt = _mm_hadd_ps(yt, yt); yt = _mm_sqrt_ss(_mm_hadd_ps(yt, yt)); if (yt.m128_f32[0] != 0.0f) yt.m128_f32[0] = 1.0f / yt.m128_f32[0]; xt = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0)); - *(vec3*)&z->row2 = *(vec3*)&xt; + *(vec3*)&z->row2.data = *(vec3*)&xt; z->row0.w = x->row0.w; z->row1.w = x->row1.w; z->row2.w = x->row2.w; @@ -859,11 +972,19 @@ inline void mat4_rotate(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; if (z != 0.0f) - mat4_rotate_z_mult(&dt, z, &dt); + mat4_rotate_z(z, &dt); + if (y != 0.0f) - mat4_rotate_y_mult(&dt, y, &dt); + if (z != 0.0f) + mat4_rotate_y_mult(&dt, y, &dt); + else + mat4_rotate_y(y, &dt); + if (x != 0.0f) - mat4_rotate_x_mult(&dt, x, &dt); + if (y != 0.0f || z != 0.0f) + mat4_rotate_x_mult(&dt, x, &dt); + else + mat4_rotate_x(x, &dt); *d = dt; } @@ -916,39 +1037,195 @@ inline void mat4_rotate_mult(mat4* s, float_t x, float_t y, float_t z, mat4* d) } inline void mat4_rotate_x_mult(mat4* x, float_t y, mat4* z) { - mat4 yt; + __m128 t1; + __m128 t2; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); - yt = mat4_identity; - yt.row1.y = y_cos; - yt.row1.z = y_sin; - yt.row2.y = -y_sin; - yt.row2.z = y_cos; - mat4_mult(x, &yt, z); + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + z->row0.data = y0; + xt = _mm_set_ss(y_cos); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(y_sin); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row1.data = _mm_add_ps(t1, t2); + xt = _mm_set_ss(-y_sin); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(y_cos); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row2.data = _mm_add_ps(t1, t2); + z->row3.data = y3; } inline void mat4_rotate_y_mult(mat4* x, float_t y, mat4* z) { - mat4 yt; + __m128 t0; + __m128 t2; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); - yt = mat4_identity; - yt.row0.x = y_cos; - yt.row0.z = -y_sin; - yt.row2.x = y_sin; - yt.row2.z = y_cos; - mat4_mult(x, &yt, z); + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + xt = _mm_set_ss(y_cos); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(-y_sin); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row0.data = _mm_add_ps(t0, t2); + z->row1.data = y1; + xt = _mm_set_ss(y_sin); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(y_cos); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row2.data = _mm_add_ps(t0, t2); + z->row3.data = y3; } inline void mat4_rotate_z_mult(mat4* x, float_t y, mat4* z) { - mat4 yt; + __m128 t0; + __m128 t1; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; float_t y_sin = sinf(y); float_t y_cos = cosf(y); + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + xt = _mm_set_ss(y_cos); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(y_sin); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + z->row0.data = _mm_add_ps(t0, t1); + xt = _mm_set_ss(-y_sin); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(y_cos); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + z->row1.data = _mm_add_ps(t0, t1); + z->row2.data = y2; + z->row3.data = y3; +} + +inline void mat4_rotate_x_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { + mat4 yt; yt = mat4_identity; - yt.row0.x = y_cos; - yt.row0.y = y_sin; - yt.row1.x = -y_sin; - yt.row1.y = y_cos; - mat4_mult(x, &yt, z); + yt.row1.y = cos_val; + yt.row1.z = sin_val; + yt.row2.y = -sin_val; + yt.row2.z = cos_val; + *y = yt; +} + +inline void mat4_rotate_y_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { + mat4 yt; + yt = mat4_identity; + yt.row0.x = cos_val; + yt.row0.z = -sin_val; + yt.row2.x = sin_val; + yt.row2.z = cos_val; + *y = yt; +} + +inline void mat4_rotate_z_sin_cos(float_t sin_val, float_t cos_val, mat4* y) { + mat4 yt; + yt = mat4_identity; + yt.row0.x = cos_val; + yt.row0.y = sin_val; + yt.row1.x = -sin_val; + yt.row1.y = cos_val; + *y = yt; +} + +inline void mat4_rotate_x_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + __m128 t1; + __m128 t2; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + z->row0.data = y0; + xt = _mm_set_ss(cos_val); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(sin_val); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row1.data = _mm_add_ps(t1, t2); + xt = _mm_set_ss(-sin_val); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(cos_val); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row2.data = _mm_add_ps(t1, t2); + z->row3.data = y3; +} + +inline void mat4_rotate_y_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + __m128 t0; + __m128 t2; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + xt = _mm_set_ss(cos_val); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(-sin_val); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row0.data = _mm_add_ps(t0, t2); + z->row1.data = y1; + xt = _mm_set_ss(sin_val); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(cos_val); + t2 = _mm_mul_ps(y2, _mm_shuffle_ps(xt, xt, 0x00)); + z->row2.data = _mm_add_ps(t0, t2); + z->row3.data = y3; +} + +inline void mat4_rotate_z_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + __m128 t0; + __m128 t1; + __m128 xt; + __m128 y0; + __m128 y1; + __m128 y2; + __m128 y3; + y0 = x->row0.data; + y1 = x->row1.data; + y2 = x->row2.data; + y3 = x->row3.data; + xt = _mm_set_ss(cos_val); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(sin_val); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + z->row0.data = _mm_add_ps(t0, t1); + xt = _mm_set_ss(-sin_val); + t0 = _mm_mul_ps(y0, _mm_shuffle_ps(xt, xt, 0x00)); + xt = _mm_set_ss(cos_val); + t1 = _mm_mul_ps(y1, _mm_shuffle_ps(xt, xt, 0x00)); + z->row1.data = _mm_add_ps(t0, t1); + z->row2.data = y2; + z->row3.data = y3; } inline void mat4_rot(mat4* s, float_t x, float_t y, float_t z, mat4* d) { @@ -1035,6 +1312,72 @@ inline void mat4_rot_z(mat4* x, float_t y, mat4* z) { z->row3 = x->row3; } +inline void mat4_rot_x_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + mat3 xt; + mat3 yt; + mat3 zt; + xt.row0 = *(vec3*)&x->row0; + xt.row1 = *(vec3*)&x->row1; + xt.row2 = *(vec3*)&x->row2; + yt = mat3_identity; + yt.row1.y = cos_val; + yt.row1.z = sin_val; + yt.row2.y = -sin_val; + yt.row2.z = cos_val; + mat3_mult(&xt, &yt, &zt); + *(vec3*)&z->row0 = zt.row0; + *(vec3*)&z->row1 = zt.row1; + *(vec3*)&z->row2 = zt.row2; + z->row0.w = x->row0.w; + z->row1.w = x->row1.w; + z->row2.w = x->row2.w; + z->row3 = x->row3; +} + +inline void mat4_rot_y_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + mat3 xt; + mat3 yt; + mat3 zt; + xt.row0 = *(vec3*)&x->row0; + xt.row1 = *(vec3*)&x->row1; + xt.row2 = *(vec3*)&x->row2; + yt = mat3_identity; + yt.row0.x = cos_val; + yt.row0.z = -sin_val; + yt.row2.x = sin_val; + yt.row2.z = cos_val; + mat3_mult(&xt, &yt, &zt); + *(vec3*)&z->row0 = zt.row0; + *(vec3*)&z->row1 = zt.row1; + *(vec3*)&z->row2 = zt.row2; + z->row0.w = x->row0.w; + z->row1.w = x->row1.w; + z->row2.w = x->row2.w; + z->row3 = x->row3; +} + +inline void mat4_rot_z_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z) { + mat3 xt; + mat3 yt; + mat3 zt; + xt.row0 = *(vec3*)&x->row0; + xt.row1 = *(vec3*)&x->row1; + xt.row2 = *(vec3*)&x->row2; + yt = mat3_identity; + yt.row0.x = cos_val; + yt.row0.y = sin_val; + yt.row1.x = -sin_val; + yt.row1.y = cos_val; + mat3_mult(&xt, &yt, &zt); + *(vec3*)&z->row0 = zt.row0; + *(vec3*)&z->row1 = zt.row1; + *(vec3*)&z->row2 = zt.row2; + z->row0.w = x->row0.w; + z->row1.w = x->row1.w; + z->row2.w = x->row2.w; + z->row3 = x->row3; +} + inline void mat4_scale(float_t x, float_t y, float_t z, mat4* d) { mat4 dt; dt = mat4_identity; @@ -1068,13 +1411,14 @@ inline void mat4_scale_z(float_t x, mat4* y) { *y = yt; } -inline void mat4_scale_mult(mat4* s, float_t x, float_t y, float_t z, mat4* d) { +inline void mat4_scale_mult(mat4* s, float_t x, float_t y, float_t z, float_t w, mat4* d) { mat4 dt; if (x != 1.0f || y != 1.0f || z != 1.0f) { dt = mat4_identity; dt.row0.x = x; dt.row1.y = y; dt.row2.z = z; + dt.row3.z = w; mat4_mult(s, &dt, d); } else if (s != d) @@ -1102,6 +1446,13 @@ inline void mat4_scale_z_mult(mat4* x, float_t y, mat4* z) { mat4_mult(x, &yt, z); } +inline void mat4_scale_w_mult(mat4* x, float_t y, mat4* z) { + mat4 yt; + yt = mat4_identity; + yt.row3.w = y; + mat4_mult(x, &yt, z); +} + inline void mat4_scale_rot(mat4* s, float_t x, float_t y, float_t z, mat4* d) { mat3 st; mat3 dt; @@ -1219,13 +1570,13 @@ inline void mat4_translate_mult(mat4* s, float_t x, float_t y, float_t z, mat4* __m128 yt2; __m128 yt3; __m128 yt4; + if (s != d) + *d = *s; if (x != 0.0f || y != 0.0f || z != 0.0f) { - if (s != d) - *d = *s; - *(vec3*)&yt0 = *(vec3*)&s->row0; - *(vec3*)&yt1 = *(vec3*)&s->row1; - *(vec3*)&yt2 = *(vec3*)&s->row2; - *(vec3*)&yt3 = *(vec3*)&s->row3; + yt0 = s->row0.data; + yt1 = s->row1.data; + yt2 = s->row2.data; + yt3 = s->row3.data; yt4 = _mm_set_ss(x); yt0 = _mm_mul_ps(yt0, _mm_shuffle_ps(yt4, yt4, 0)); yt4 = _mm_set_ss(y); @@ -1235,99 +1586,79 @@ inline void mat4_translate_mult(mat4* s, float_t x, float_t y, float_t z, mat4* yt4 = _mm_add_ps(_mm_add_ps(yt0, yt1), _mm_add_ps(yt2, yt3)); *(vec3*)&d->row3 = *(vec3*)&yt4; } - else if (s != d) - *d = *s; } inline void mat4_translate_x_mult(mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; __m128 yt2; + if (x != z) + *z = *x; if (y != 0.0f) { - if (x != z) - *z = *x; - *(vec3*)&yt0 = *(vec3*)&x->row0; - *(vec3*)&yt1 = *(vec3*)&x->row3; + yt0 = x->row0.data; + yt1 = x->row3.data; yt2 = _mm_set_ss(y); yt0 = _mm_add_ps(_mm_mul_ps(yt0, _mm_shuffle_ps(yt2, yt2, 0)), yt1); *(vec3*)&z->row3 = *(vec3*)&yt0; } - else if (x != z) - *z = *x; } inline void mat4_translate_y_mult(mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; __m128 yt2; + if (x != z) + *z = *x; if (y != 0.0f) { - if (x != z) - *z = *x; - *(vec3*)&yt0 = *(vec3*)&x->row1; - *(vec3*)&yt1 = *(vec3*)&x->row3; + yt0 = x->row1.data; + yt1 = x->row3.data; yt2 = _mm_set_ss(y); yt0 = _mm_add_ps(_mm_mul_ps(yt0, _mm_shuffle_ps(yt2, yt2, 0)), yt1); *(vec3*)&z->row3 = *(vec3*)&yt0; } - else if (x != z) - *z = *x; } inline void mat4_translate_z_mult(mat4* x, float_t y, mat4* z) { __m128 yt0; __m128 yt1; __m128 yt2; + if (x != z) + *z = *x; if (y != 0.0f) { - if (x != z) - *z = *x; - *(vec3*)&yt0 = *(vec3*)&x->row2; - *(vec3*)&yt1 = *(vec3*)&x->row3; + yt0 = x->row2.data; + yt1 = x->row3.data; yt2 = _mm_set_ss(y); yt0 = _mm_add_ps(_mm_mul_ps(yt0, _mm_shuffle_ps(yt2, yt2, 0)), yt1); *(vec3*)&z->row3 = *(vec3*)&yt0; } - else if (x != z) - *z = *x; } inline void mat4_translate_add(mat4* s, float_t x, float_t y, float_t z, mat4* d) { - if (x != 0.0f || y != 0.0f || z != 0.0f) { - if (s != d) - *d = *s; - d->row3.data = _mm_add_ps(s->row3.data, _mm_set_ps(x, y, z, 0.0f)); - } - else if (s != d) + if (s != d) *d = *s; + if (x != 0.0f || y != 0.0f || z != 0.0f) + d->row3.data = _mm_add_ps(s->row3.data, _mm_set_ps(x, y, z, 0.0f)); } inline void mat4_translate_x_add(mat4* x, float_t y, mat4* z) { - if (y != 0.0f) { - if (x != z) - *z = *x; - z->row3.x += y; - } - else if (x != z) + if (x != z) *z = *x; + if (y != 0.0f) + z->row3.x += y; } inline void mat4_translate_y_add(mat4* x, float_t y, mat4* z) { - if (y != 0.0f) { - if (x != z) - *z = *x; - z->row3.y += y; - } - else if (x != z) + if (x != z) *z = *x; + if (y != 0.0f) + z->row3.y += y; } inline void mat4_translate_z_add(mat4* x, float_t y, mat4* z) { - if (y != 0.0f) { - if (x != z) - *z = *x; - z->row3.z += y; - } - else if (x != z) + if (x != z) *z = *x; + if (y != 0.0f) + z->row3.z += y; } inline void mat4_from_quat(quat* quat, mat4* mat) { @@ -1376,6 +1707,37 @@ inline void mat4_from_quat(quat* quat, mat4* mat) { mat->row3 = (vec4){ 0.0f, 0.0f, 0.0f, 1.0f }; } +inline void mat4_from_axis_angle(vec3* axis, float_t angle, mat4* mat) { + float_t angle_sin; + float_t angle_cos; + float_t angle_cos_1; + vec3 _axis; + vec3 temp; + + angle_sin = sinf(angle); + angle_cos = cosf(angle); + angle_cos_1 = 1.0f - angle_cos; + + vec3_normalize(*axis, _axis); + + vec3_mult_scalar(_axis, _axis.x * angle_cos_1, temp); + mat->row0.x = temp.x + angle_cos; + mat->row0.y = temp.x - angle_sin * _axis.z; + mat->row0.z = temp.x + angle_sin * _axis.y; + vec3_mult_scalar(_axis, _axis.y * angle_cos_1, temp); + mat->row1.x = temp.x + angle_sin * _axis.z; + mat->row1.y = temp.y + angle_cos; + mat->row1.z = temp.z - angle_sin * _axis.x; + vec3_mult_scalar(_axis, _axis.z * angle_cos_1, temp); + mat->row2.x = temp.x - angle_sin * _axis.y; + mat->row2.y = temp.y + angle_sin * _axis.x; + mat->row2.z = temp.z + angle_cos; + mat->row0.w = 0.0f; + mat->row1.w = 0.0f; + mat->row2.w = 0.0f; + mat->row3 = (vec4){ 0.0f, 0.0f, 0.0f, 1.0f }; +} + inline void mat4_from_mat3(mat3* x, mat4* z) { *(vec3*)&z->row0 = x->row0; z->row0.w = 0.0f; @@ -1416,12 +1778,13 @@ inline void mat4_clear_trans(mat4* x, mat4* z) { } inline void mat4_get_rotation(mat4* x, vec3* z) { - if (-x->row0.z >= 1.0) + if (-x->row0.z >= 1.0f) z->y = (float_t)M_PI_2; - else if (-x->row0.z <= -1.0) + else if (-x->row0.z <= -1.0f) z->y = (float_t)-M_PI_2; else z->y = asinf(-x->row0.z); + if (fabs(x->row0.z) < 0.99999899f) { z->x = atan2f(x->row1.z, x->row2.z); z->z = atan2f(x->row0.y, x->row0.x); @@ -1429,7 +1792,7 @@ inline void mat4_get_rotation(mat4* x, vec3* z) { else { z->x = 0.0f; z->z = atan2f(x->row2.y, x->row1.y); - if (-x->row0.z < 0.0f) + if (x->row0.z > 0.0f) z->z = -z->z; } } @@ -1447,3 +1810,121 @@ inline void mat4_get_translation(mat4* x, vec3* z) { inline void mat4_set_translation(mat4* x, vec3* z) { *(vec3*)&x->row3 = *z; } + +inline void mat4_blend_rotation(mat4* x, mat4* y, mat4* z, float_t blend) { + quat q0; + quat q1; + quat q2; + + quat_from_mat3(x->row0.x, x->row1.x, x->row2.x, x->row0.y, + x->row1.y, x->row2.y, x->row0.z, x->row1.z, x->row2.z, &q1); + quat_from_mat3(y->row0.x, y->row1.x, y->row2.x, y->row0.y, + y->row1.y, y->row2.y, y->row0.z, y->row1.z, y->row2.z, &q1); + quat_slerp(&q0, &q1, &q2, blend); + mat4_from_quat(&q2, z); +} + +inline float_t mat4_get_max_scale(mat4* x) { + mat4 mat; + mat4_transpose(x, &mat); + + float_t length; + float_t max = 0.0f; + vec3_length(*(vec3*)&mat.row0, length); + if (length > 0.0f) + max = length; + vec3_length(*(vec3*)&mat.row1, length); + if (length > 0.0f) + max = length; + vec3_length(*(vec3*)&mat.row2, length); + if (length > 0.0f) + max = length; + return max; +} + +inline void mat4_ortho(double_t left, double_t right, + double_t bottom, double_t top, double_t z_near, double_t z_far, mat4* mat) { + *mat = mat4_identity; + mat->row0.x = (float_t)(2.0 / (right - left)); + mat->row1.y = (float_t)(2.0 / (top - bottom)); + mat->row2.z = (float_t)(-2.0 / (z_far - z_near)); + mat->row3.x = -(float_t)((right + left) / (right - left)); + mat->row3.y = -(float_t)((top + bottom) / (top - bottom)); + mat->row3.z = -(float_t)((z_far + z_near) / (z_far - z_near)); +} + +inline void mat4_persp(double_t fov_y, double_t aspect, double_t z_near, double_t z_far, mat4* mat) { + double_t tan_fov = tan(fov_y * 0.5); + + double_t x = 1.0 / (aspect * tan_fov); + double_t y = 1.0 / tan_fov; + double_t d = -(2.0 * z_far * z_near) / (z_far - z_near); + double_t e = -(z_far + z_near) / (z_far - z_near); + + *mat = mat4_null; + mat->row0.x = (float_t)x; + mat->row1.y = (float_t)y; + mat->row2.z = (float_t)e; + mat->row2.w = -1.0f; + mat->row3.z = (float_t)d; +} + +inline void mat4_look_at(vec3* eye, vec3* target, vec3* up, mat4* mat) { + vec3 x_axis, y_axis, z_axis; + float_t t; + vec3 xyz; + + vec3_sub(*eye, *target, z_axis); + vec3_normalize(z_axis, z_axis); + + vec3_cross(*up, z_axis, x_axis); + vec3_normalize(x_axis, x_axis); + vec3_length(x_axis, t); + if (t == 0.0f) + x_axis = (vec3){ 1.0f, 0.0f, 0.0f }; + vec3_cross(z_axis, x_axis, y_axis); + vec3_normalize(y_axis, y_axis); + + vec3_dot(x_axis, *eye, xyz.x); + vec3_dot(y_axis, *eye, xyz.y); + vec3_dot(z_axis, *eye, xyz.z); + + mat->row0 = (vec4){ x_axis.x, y_axis.x, z_axis.x, 0.0f }; + mat->row1 = (vec4){ x_axis.y, y_axis.y, z_axis.y, 0.0f }; + mat->row2 = (vec4){ x_axis.z, y_axis.z, z_axis.z, 0.0f }; + vec3_negate(xyz, xyz); + *(vec3*)&mat->row3 = xyz; + mat->row3.w = 1.0f; +} + +inline void mat4_to_mat4u(mat4* x, mat4u* z) { + vec4_to_vec4u(x->row0, z->row0); + vec4_to_vec4u(x->row1, z->row1); + vec4_to_vec4u(x->row2, z->row2); + vec4_to_vec4u(x->row3, z->row3); +} + +inline void mat4u_to_mat4(mat4u* x, mat4* z) { + vec4u_to_vec4(x->row0, z->row0); + vec4u_to_vec4(x->row1, z->row1); + vec4u_to_vec4(x->row2, z->row2); + vec4u_to_vec4(x->row3, z->row3); +} + +inline void mat4_to_mat4u_transpose(mat4* x, mat4u* z) { + mat4 y; + mat4_transpose(x, &y); + vec4_to_vec4u(y.row0, z->row0); + vec4_to_vec4u(y.row1, z->row1); + vec4_to_vec4u(y.row2, z->row2); + vec4_to_vec4u(y.row3, z->row3); +} + +inline void mat4u_to_mat4_transpose(mat4u* x, mat4* z) { + mat4 y; + vec4u_to_vec4(x->row0, y.row0); + vec4u_to_vec4(x->row1, y.row1); + vec4u_to_vec4(x->row2, y.row2); + vec4u_to_vec4(x->row3, y.row3); + mat4_transpose(&y, z); +} diff --git a/src/KKdLib/mat.h b/src/KKdLib/mat.h index 786042a5..0b0c6431 100644 --- a/src/KKdLib/mat.h +++ b/src/KKdLib/mat.h @@ -22,10 +22,24 @@ typedef struct mat4 { vec4 row3; } mat4; +typedef struct mat4u { + vec4u row0; + vec4u row1; + vec4u row2; + vec4u row3; +} mat4u; + extern const mat3 mat3_identity; extern const mat3 mat3_null; extern const mat4 mat4_identity; extern const mat4 mat4_null; +extern const mat4u mat4u_identity; +extern const mat4u mat4u_null; + +vector(mat3) +vector(mat4) +vector_ptr(mat3) +vector_ptr(mat4) extern void mat3_add(mat3* x, mat3* y, mat3* z); extern void mat3_sub(mat3* x, mat3* y, mat3* z); @@ -35,6 +49,7 @@ extern void mat3_mult_scalar(mat3* x, float_t y, mat3* z); extern void mat3_transpose(mat3* x, mat3* z); extern void mat3_inverse(mat3* x, mat3* z); extern void mat3_invtrans(mat3* x, mat3* z); +extern void mat3_inverse_normalized(mat3* x, mat3* z); extern void mat3_normalize(mat3* x, mat3* z); extern void mat3_normalize_rotation(mat3* x, mat3* z); extern float_t mat3_determinant(mat3* x); @@ -55,22 +70,28 @@ extern void mat3_scale_x_mult(mat3* x, float_t y, mat3* z); extern void mat3_scale_y_mult(mat3* x, float_t y, mat3* z); extern void mat3_scale_z_mult(mat3* x, float_t y, mat3* z); extern void mat3_from_quat(quat* quat, mat3* mat); +extern void mat3_from_axis_angle(vec3* axis, float_t angle, mat3* mat); extern void mat3_from_mat4(mat4* x, mat3* z); extern void mat3_from_mat4_inverse(mat4* x, mat3* z); extern void mat3_get_rotation(mat3* x, vec3* z); extern void mat3_get_scale(mat3* x, vec3* z); +extern float_t mat3_get_max_scale(mat3* x); extern void mat4_add(mat4* x, mat4* y, mat4* z); extern void mat4_sub(mat4* x, mat4* y, mat4* z); extern void mat4_mult(mat4* x, mat4* y, mat4* z); extern void mat4_mult_vec3(mat4* x, vec3* y, vec3* z); +extern void mat4_mult_vec3_inv(mat4* x, vec3* y, vec3* z); extern void mat4_mult_vec3_trans(mat4* x, vec3* y, vec3* z); +extern void mat4_mult_vec3_inv_trans(mat4* x, vec3* y, vec3* z); extern void mat4_mult_vec(mat4* x, vec4* y, vec4* z); extern void mat4_mult_scalar(mat4* x, float_t y, mat4* z); extern void mat4_transpose(mat4* x, mat4* z); extern void mat4_inverse(mat4* x, mat4* z); extern void mat4_invtrans(mat4* x, mat4* z); extern void mat4_invrot(mat4* x, mat4* z); +extern void mat4_inverse_normalized(mat4* x, mat4* z); +extern void mat4_invrot_normalized(mat4* x, mat4* z); extern void mat4_normalize(mat4* x, mat4* z); extern void mat4_normalize_rotation(mat4* x, mat4* z); extern float_t mat4_determinant(mat4* x); @@ -82,18 +103,28 @@ extern void mat4_rotate_mult(mat4* s, float_t x, float_t y, float_t z, mat4* d); extern void mat4_rotate_x_mult(mat4* x, float_t y, mat4* z); extern void mat4_rotate_y_mult(mat4* x, float_t y, mat4* z); extern void mat4_rotate_z_mult(mat4* x, float_t y, mat4* z); +extern void mat4_rotate_x_sin_cos(float_t sin_val, float_t cos_val, mat4* y); +extern void mat4_rotate_y_sin_cos(float_t sin_val, float_t cos_val, mat4* y); +extern void mat4_rotate_z_sin_cos(float_t sin_val, float_t cos_val, mat4* y); +extern void mat4_rotate_x_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); +extern void mat4_rotate_y_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); +extern void mat4_rotate_z_mult_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); extern void mat4_rot(mat4* s, float_t x, float_t y, float_t z, mat4* d); extern void mat4_rot_x(mat4* x, float_t y, mat4* z); extern void mat4_rot_y(mat4* x, float_t y, mat4* z); extern void mat4_rot_z(mat4* x, float_t y, mat4* z); +extern void mat4_rot_x_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); +extern void mat4_rot_y_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); +extern void mat4_rot_z_sin_cos(mat4* x, float_t sin_val, float_t cos_val, mat4* z); extern void mat4_scale(float_t x, float_t y, float_t z, mat4* d); extern void mat4_scale_x(float_t x, mat4* y); extern void mat4_scale_y(float_t x, mat4* y); extern void mat4_scale_z(float_t x, mat4* y); -extern void mat4_scale_mult(mat4* s, float_t x, float_t y, float_t z, mat4* d); +extern void mat4_scale_mult(mat4* s, float_t x, float_t y, float_t z, float_t w, mat4* d); extern void mat4_scale_x_mult(mat4* x, float_t y, mat4* z); extern void mat4_scale_y_mult(mat4* x, float_t y, mat4* z); extern void mat4_scale_z_mult(mat4* x, float_t y, mat4* z); +extern void mat4_scale_w_mult(mat4* x, float_t y, mat4* z); extern void mat4_scale_rot(mat4* s, float_t x, float_t y, float_t z, mat4* d);; extern void mat4_scale_x_rot(mat4* x, float_t y, mat4* z); extern void mat4_scale_y_rot(mat4* x, float_t y, mat4* z); @@ -111,6 +142,7 @@ extern void mat4_translate_x_add(mat4* x, float_t y, mat4* z); extern void mat4_translate_y_add(mat4* x, float_t y, mat4* z); extern void mat4_translate_z_add(mat4* x, float_t y, mat4* z); extern void mat4_from_quat(quat* quat, mat4* mat); +extern void mat4_from_axis_angle(vec3* axis, float_t angle, mat4* mat); extern void mat4_from_mat3(mat3* x, mat4* z); extern void mat4_from_mat3_inverse(mat3* x, mat4* z); extern void mat4_clear_rot(mat4* x, mat4* z); @@ -119,3 +151,14 @@ extern void mat4_get_scale(mat4* x, vec3* z); extern void mat4_get_rotation(mat4* x, vec3* z); extern void mat4_get_translation(mat4* x, vec3* z); extern void mat4_set_translation(mat4* x, vec3* z); +extern void mat4_blend_rotation(mat4* x, mat4* y, mat4* z, float_t blend); +extern void mat4_ortho(double_t left, double_t right, + double_t bottom, double_t top, double_t z_near, double_t z_far, mat4* mat); +extern void mat4_persp(double_t fov_y, double_t aspect, double_t z_near, double_t z_far, mat4* mat); +extern void mat4_look_at(vec3* eye, vec3* target, vec3* up, mat4* mat); +extern float_t mat4_get_max_scale(mat4* x); + +extern void mat4_to_mat4u(mat4* x, mat4u* z); +extern void mat4u_to_mat4(mat4u* x, mat4* z); +extern void mat4_to_mat4u_transpose(mat4* x, mat4u* z); +extern void mat4u_to_mat4_transpose(mat4u* x, mat4* z); diff --git a/src/KKdLib/mot.c b/src/KKdLib/mot.c index cd134a4c..02b47d81 100644 --- a/src/KKdLib/mot.c +++ b/src/KKdLib/mot.c @@ -4,11 +4,11 @@ */ #include "mot.h" -#include "f2_struct.h" +#include "f2/struct.h" +#include "io/path.h" +#include "io/stream.h" #include "half_t.h" #include "hash.h" -#include "io_path.h" -#include "io_stream.h" #include "str_utils.h" typedef struct mot_header_classic { @@ -29,726 +29,975 @@ typedef struct mot_header_modern { int32_t bone_info_count; } mot_header_modern; -vector_func(mot) +vector_func(mot_data) +vector_func(mot_set) -static void mot_read_inner(mot_set* ms, stream* s, bool modern); -static void mot_write_inner(mot_set* ms, stream* s); +static bool mot_classic_read_inner(mot_set* ms, stream* s); +static void mot_classic_write_inner(mot_set* ms, stream* s); +static bool mot_modern_read_inner(mot_set* ms, stream* s); +static void mot_modern_write_inner(mot_set* ms, stream* s); -mot_set* mot_init() { - mot_set* ms = force_malloc(sizeof(mot_set)); +void mot_init(mot_set_farc* msf) { + memset(msf, 0, sizeof(mot_set_farc)); +} + +void mot_read(mot_set_farc* msf, char* path, bool modern) { + if (!msf || !path) + return; + + char* path_farc = str_utils_add(path, ".farc"); + if (path_check_file_exists(path_farc)) { + farc f; + farc_init(&f); + farc_read(&f, path_farc, true, false); + + vector_mot_set_reserve(&msf->vec, f.files.end - f.files.begin); + if (!modern) + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || str_utils_compare_length(string_data(&i->name), i->name.length, "mot_", 4) + || !str_utils_check_ends_with(string_data(&i->name), ".bin")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_copy(&i->name, &ms.name); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = false; + } + else + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || !str_utils_check_ends_with(string_data(&i->name), ".mot")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_copy(&i->name, &ms.name); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = true; + } + farc_free(&f); + } + free(path_farc); +} + +void mot_wread(mot_set_farc* msf, wchar_t* path, bool modern) { + if (!msf || !path) + return; + + wchar_t* path_farc = str_utils_wadd(path, L".farc"); + if (path_wcheck_file_exists(path_farc)) { + farc f; + farc_init(&f); + farc_wread(&f, path_farc, true, false); + + vector_mot_set_reserve(&msf->vec, f.files.end - f.files.begin); + if (!modern) + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || str_utils_compare_length(string_data(&i->name), i->name.length, "mot_", 4) + || !str_utils_check_ends_with(string_data(&i->name), ".bin")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_copy(&i->name, &ms.name); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = false; + } + else + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || !str_utils_check_ends_with(string_data(&i->name), ".mot")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_copy(&i->name, &ms.name); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = true; + } + } + free(path_farc); +} + +void mot_mread(mot_set_farc* msf, void* data, size_t length, bool modern) { + if (!msf || !data || !length) + return; + + farc f; + farc_init(&f); + farc_mread(&f, data, length, true); + + vector_mot_set_reserve(&msf->vec, f.files.end - f.files.begin); + if (!modern) + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || str_utils_compare_length(string_data(&i->name), i->name.length, "mot_", 4) + || !str_utils_check_ends_with(string_data(&i->name), ".bin")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_init_length(&ms.name, string_data(&i->name), i->name.length - 4); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = false; + } + else + for (farc_file* i = f.files.begin; i != f.files.end; i++) { + if (!i->data || !i->size + || !str_utils_check_ends_with(string_data(&i->name), ".mot")) + continue; + + mot_set ms; + mot_set_init(&ms); + + stream s; + io_mopen(&s, i->data, i->size); + bool ret = mot_classic_read_inner(&ms, &s); + io_free(&s); + + if (!ret) { + mot_set_free(&ms); + continue; + } + + string_init_length(&ms.name, string_data(&i->name), i->name.length - 4); + vector_mot_set_push_back(&msf->vec, &ms); + msf->ready = true; + msf->modern = true; + } + farc_free(&f); +} + +void mot_write(mot_set_farc* msf, char* path, farc_compress_mode mode) { + if (!msf || !path || !msf->ready) + return; + + char* path_farc = str_utils_add(path, ".farc"); + + farc f; + farc_init(&f); + if (!msf->modern) + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_classic_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".bin"); + + vector_farc_file_push_back(&f.files, &ff); + } + else + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_modern_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".mot"); + + vector_farc_file_push_back(&f.files, &ff); + } + farc_write(&f, path_farc, mode, false); + free(path_farc); +} + +void mot_wwrite(mot_set_farc* msf, wchar_t* path, farc_compress_mode mode) { + if (!msf || !path || !msf->ready) + return; + + wchar_t* path_farc = str_utils_wadd(path, L".farc"); + + farc f; + farc_init(&f); + if (!msf->modern) + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_classic_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".bin"); + + vector_farc_file_push_back(&f.files, &ff); + } + else + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_modern_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".mot"); + + vector_farc_file_push_back(&f.files, &ff); + } + farc_wwrite(&f, path_farc, mode, false); + free(path_farc); +} + +void mot_mwrite(mot_set_farc* msf, void** data, size_t* length, farc_compress_mode mode) { + if (!msf || !data || !msf->ready) + return; + + farc f; + farc_init(&f); + if (!msf->modern) + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_classic_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".bin"); + + vector_farc_file_push_back(&f.files, &ff); + } + else + for (mot_set* i = msf->vec.begin; i != msf->vec.end; i++) { + farc_file ff; + memset(&ff, 0, sizeof(farc_file)); + + stream s; + io_mopen(&s, 0, 0); + mot_modern_write_inner(i, &s); + io_align_write(&s, 0x10); + io_mcopy(&s, &ff.data, &ff.size); + io_free(&s); + + string_copy(&i->name, &ff.name); + string_add(&ff.name, ".mot"); + + vector_farc_file_push_back(&f.files, &ff); + } + farc_mwrite(&f, data, length, mode); +} + +bool mot_load_file(void* data, char* path, char* file, uint32_t hash) { + size_t file_len = utf8_length(file); + + char* t = strrchr(file, '.'); + if (t) + file_len = t - file; + + string s; + string_init(&s, path); + string_add_length(&s, file, file_len); + + mot_set_farc* msf = data; + mot_read(msf, string_data(&s), msf->modern); + + string_free(&s); + return msf->ready; +} + +void mot_free(mot_set_farc* msf) { + if (!msf) + return; + + vector_mot_set_free(&msf->vec, mot_set_free); +} + +void mot_set_init(mot_set* ms) { memset(ms, 0, sizeof(mot_set)); - return ms; } -void mot_read(mot_set* ms, char* path, bool modern) { - if (!ms || !path) - return; - - if (!modern) { - char* path_bin = str_utils_add(path, ".bin"); - if (path_check_file_exists(path_bin)) { - stream s; - io_open(&s, path_bin, "rb"); - if (s.io.stream) - mot_read_inner(ms, &s, false); - io_free(&s); - } - free(path_bin); - } - else { - char* path_mot = str_utils_add(path, ".mot"); - if (path_check_file_exists(path_mot)) { - stream s; - io_open(&s, path_mot, "rb"); - if (s.io.stream) - mot_read_inner(ms, &s, true); - io_free(&s); - } - free(path_mot); - } -} - -void mot_wread(mot_set* ms, wchar_t* path, bool modern) { - if (!ms || !path) - return; - - if (!modern) { - wchar_t* path_bin = str_utils_wadd(path, L".bin"); - if (path_wcheck_file_exists(path_bin)) { - stream s; - io_wopen(&s, path_bin, L"rb"); - if (s.io.stream) - mot_read_inner(ms, &s, false); - io_free(&s); - } - free(path_bin); - } - else { - wchar_t* path_mot = str_utils_wadd(path, L".mot"); - if (path_wcheck_file_exists(path_mot)) { - stream s; - io_wopen(&s, path_mot, L"rb"); - if (s.io.stream) - mot_read_inner(ms, &s, true); - io_free(&s); - } - free(path_mot); - } -} - -void mot_mread(mot_set* ms, void* data, size_t length, bool modern) { - if (!ms || !data) - return; - - stream s; - io_mopen(&s, data, length); - mot_read_inner(ms, &s, modern); - io_free(&s); -} - -void mot_write(mot_set* ms, char* path) { - if (!ms || !path || !ms->ready) - return; - - if (!ms->modern) { - char* path_bin = str_utils_add(path, ".bin"); - stream s; - io_open(&s, path_bin, "wb"); - if (s.io.stream) - mot_write_inner(ms, &s); - io_free(&s); - free(path_bin); - } - else { - char* path_mot = str_utils_add(path, ".mot"); - stream s; - io_open(&s, path_mot, "wb"); - if (s.io.stream) - mot_write_inner(ms, &s); - io_free(&s); - free(path_mot); - } -} - -void mot_wwrite(mot_set* ms, wchar_t* path) { - if (!ms || !path || !ms->ready) - return; - - if (!ms->modern) { - wchar_t* path_bin = str_utils_wadd(path, L".bin"); - stream s; - io_wopen(&s, path_bin, L"wb"); - if (s.io.stream) - mot_write_inner(ms, &s); - io_free(&s); - free(path_bin); - } - else { - wchar_t* path_mot = str_utils_wadd(path, L".mot"); - stream s; - io_wopen(&s, path_mot, L"wb"); - if (s.io.stream) - mot_write_inner(ms, &s); - io_free(&s); - free(path_mot); - } -} - -void mot_mwrite(mot_set* ms, void** data, size_t* length) { - if (!ms || !data) - return; - - stream s; - io_mopen(&s, 0, 0); - mot_write_inner(ms, &s); - - io_align_write(&s, 0x10); - io_mcopy(&s, data, length); - io_free(&s); -} - -void mot_dispose(mot_set* ms) { +void mot_set_free(mot_set* ms) { if (!ms) return; - for (mot* i = ms->vec.begin; i != ms->vec.end; i++) { - if (ms->modern) - if (i->bone_info) - for (size_t j = 0; j < i->bone_info_count; j++) - string_free(&i->bone_info[j].name); + for (mot_data* i = ms->vec.begin; i != ms->vec.end; i++) { + if (i->bone_info) + for (size_t j = 0; j < i->bone_info_count; j++) + string_free(&i->bone_info[j].name); free(i->bone_info); if (i->key_set) - for (size_t j = 0; j < i->key_set_count; j++) - free(i->key_set[j].keys); + for (size_t j = 0; j < i->key_set_count; j++) { + free(i->key_set[j].frames); + free(i->key_set[j].values); + } free(i->key_set); string_free(&i->name); } - vector_mot_free(&ms->vec); - free(ms); + + string_free(&ms->name); + vector_mot_data_free(&ms->vec, 0); } -static void mot_read_inner(mot_set* ms, stream* s, bool modern) { - if (!modern) { - size_t count = 0; - while (io_read_uint64_t(s) != 0) { - io_read_uint64_t(s); - count++; - } - - if (count == 0) { - ms->is_x = false; - ms->modern = false; - ms->ready = false; - return; - } - - io_set_position(s, 0x00, SEEK_SET); - vector_mot_reserve(&ms->vec, count); - mot_header_classic* mh = force_malloc_s(mot_header_classic, count); - for (size_t i = 0; i < count; i++) { - mh[i].key_set_count_offset = io_read_uint32_t(s); - mh[i].key_set_types_offset = io_read_uint32_t(s); - mh[i].key_set_offset = io_read_uint32_t(s); - mh[i].bone_info_offset = io_read_uint32_t(s); - } - - for (size_t i = 0; i < count; i++) { - mot m; - memset(&m, 0, sizeof(mot)); - - io_set_position(s, mh[i].bone_info_offset, SEEK_SET); - m.bone_info_count = 0; - io_read_uint16_t(s); - do - m.bone_info_count++; - while (io_read_uint16_t(s) != 0 && io_get_position(s) < s->length); - - io_set_position(s, mh[i].bone_info_offset, SEEK_SET); - m.bone_info = force_malloc_s(mot_bone_info, m.bone_info_count); - for (size_t j = 0; j < m.bone_info_count; j++) - m.bone_info[j].index = io_read_uint16_t(s); - - io_set_position(s, mh[i].key_set_count_offset, SEEK_SET); - m.info = io_read_uint16_t(s); - m.frame_count = io_read_uint16_t(s); - - m.key_set = force_malloc_s(mot_key_set, m.key_set_count); - io_set_position(s, mh[i].key_set_types_offset, SEEK_SET); - for (int32_t j = 0, b = 0; j < m.key_set_count; j++) { - if (j % 8 == 0) - b = io_read_uint16_t(s); - - m.key_set[j].type = (b >> (j % 8 * 2)) & 0x03; - } - - io_set_position(s, mh[i].key_set_offset, SEEK_SET); - for (int32_t j = 0; j < m.key_set_count; j++) { - mot_key_set* mks = &m.key_set[j]; - if (mks->type == MOT_KEY_SET_NONE) { - mks->keys_count = 0; - mks->keys = 0; - } - else if (mks->type == MOT_KEY_SET_STATIC) { - mks->keys_count = 1; - mks->keys = force_malloc_s(kft2, mks->keys_count); - mks->keys[0].frame = 0.0f; - mks->keys[0].value = io_read_float_t(s); - } - else if (mks->type == MOT_KEY_SET_HERMITE - || mks->type == MOT_KEY_SET_HERMITE_TANGENT) { - mks->keys_count = io_read_uint16_t(s); - mks->keys = force_malloc_s(kft2, mks->keys_count); - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].frame = io_read_uint16_t(s); - io_align_read(s, 0x04); - - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - for (uint32_t k = 0; k < mks->keys_count; k++) { - mks->keys[k].value = io_read_float_t(s); - mks->keys[k].tangent = io_read_float_t(s); - } - else - for (uint32_t k = 0; k < mks->keys_count; k++) { - mks->keys[k].value = io_read_float_t(s); - mks->keys[k].tangent = 0.0f; - } - } - } - vector_mot_push_back(&ms->vec, &m); - } - free(mh); - - ms->is_x = false; - ms->modern = false; - ms->ready = true; +static bool mot_classic_read_inner(mot_set* ms, stream* s) { + size_t count = 0; + while (io_read_uint64_t(s) != 0) { + io_read_uint64_t(s); + count++; } - else { - f2_struct st; - f2_struct_sread(&st, s); - if (st.header.signature == reverse_endianness_uint32_t('MOTC') && st.data) { - stream s_motc; - io_mopen(&s_motc, st.data, st.length); - s_motc.is_big_endian = st.header.use_big_endian; - io_set_position(&s_motc, 0x0C, SEEK_SET); - bool is_x = io_read_uint32_t_stream_reverse_endianness(&s_motc) == 0; + if (count == 0) { + ms->is_x = false; + return false; + } - io_set_position(&s_motc, 0x00, SEEK_SET); - vector_mot_reserve(&ms->vec, 1); - mot_header_modern mh; - memset(&mh, 0, sizeof(mot_header_modern)); - if (!is_x) { - mh.hash = (uint32_t)io_read_uint64_t_stream_reverse_endianness(&s_motc); - mh.name_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.key_set_count_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.key_set_types_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.key_set_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.bone_info_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.bone_hash_offset = io_read_offset_f2(&s_motc, st.header.length); - mh.bone_info_count = io_read_int32_t_stream_reverse_endianness(&s_motc); + io_set_position(s, 0x00, SEEK_SET); + vector_mot_data_reserve(&ms->vec, count); + mot_header_classic* mh = force_malloc_s(mot_header_classic, count); + for (size_t i = 0; i < count; i++) { + mh[i].key_set_count_offset = io_read_uint32_t(s); + mh[i].key_set_types_offset = io_read_uint32_t(s); + mh[i].key_set_offset = io_read_uint32_t(s); + mh[i].bone_info_offset = io_read_uint32_t(s); + } + + for (size_t i = 0; i < count; i++) { + mot_data* m = vector_mot_data_reserve_back(&ms->vec); + + io_set_position(s, mh[i].bone_info_offset, SEEK_SET); + m->bone_info_count = 0; + io_read_uint16_t(s); + do + m->bone_info_count++; + while (io_read_uint16_t(s) != 0 && io_get_position(s) < s->length); + + io_set_position(s, mh[i].bone_info_offset, SEEK_SET); + m->bone_info = force_malloc_s(mot_bone_info, m->bone_info_count); + for (size_t j = 0; j < m->bone_info_count; j++) + m->bone_info[j].index = io_read_uint16_t(s); + + io_set_position(s, mh[i].key_set_count_offset, SEEK_SET); + m->info = io_read_uint16_t(s); + m->frame_count = io_read_uint16_t(s); + + m->key_set = force_malloc_s(mot_key_set_data, m->key_set_count); + io_set_position(s, mh[i].key_set_types_offset, SEEK_SET); + for (int32_t j = 0, b = 0; j < m->key_set_count; j++) { + if (j % 8 == 0) + b = io_read_uint16_t(s); + + m->key_set[j].type = (b >> (j % 8 * 2)) & 0x03; + } + + io_set_position(s, mh[i].key_set_offset, SEEK_SET); + for (int32_t j = 0; j < m->key_set_count; j++) { + mot_key_set_data* mks = &m->key_set[j]; + if (mks->type == MOT_KEY_SET_NONE) { + mks->keys_count = 0; + mks->frames = 0; + mks->values = 0; + } + else if (mks->type == MOT_KEY_SET_STATIC) { + mks->keys_count = 1; + mks->frames = 0; + mks->values = force_malloc_s(float_t, 1); + mks->values[0] = io_read_float_t(s); } else { - mh.hash = (uint32_t)io_read_uint64_t_stream_reverse_endianness(&s_motc); - mh.name_offset = io_read_offset_x(&s_motc); - mh.key_set_count_offset = io_read_offset_x(&s_motc); - mh.key_set_types_offset = io_read_offset_x(&s_motc); - mh.key_set_offset = io_read_offset_x(&s_motc); - mh.bone_info_offset = io_read_offset_x(&s_motc); - mh.bone_hash_offset = io_read_offset_x(&s_motc); - mh.bone_info_count = io_read_int32_t_stream_reverse_endianness(&s_motc); + bool has_tangents = mks->type != MOT_KEY_SET_HERMITE; + uint16_t keys_count = io_read_uint16_t(s); + mks->keys_count = keys_count; + + mks->frames = force_malloc_s(uint16_t, keys_count); + mks->values = force_malloc_s(float_t, has_tangents ? keys_count * 2ULL : keys_count); + + uint16_t* frames = mks->frames; + for (int32_t k = 0; k < keys_count; k++) + *frames++ = io_read_uint16_t(s); + io_align_read(s, 0x04); + + float_t* values = mks->values; + if (!has_tangents) + for (int32_t k = 0; k < keys_count; k++) + *values++ = io_read_float_t(s); + else + for (int32_t k = 0; k < keys_count; k++) { + *values++ = io_read_float_t(s); + *values++ = io_read_float_t(s); + } } - - mot m; - memset(&m, 0, sizeof(mot)); - m.div_frames = io_read_uint16_t_stream_reverse_endianness(&s_motc);; - m.div_count = io_read_uint8_t(&s_motc);; - - io_read_string_null_terminated_offset(&s_motc, mh.name_offset, &m.name); - - io_set_position(&s_motc, mh.bone_info_offset, SEEK_SET); - m.bone_info_count = mh.bone_info_count; - m.bone_info = force_malloc_s(mot_bone_info, m.bone_info_count); - if (!is_x) - for (size_t j = 0; j < mh.bone_info_count; j++) - io_read_string_null_terminated_offset(&s_motc, - io_read_offset_f2(&s_motc, st.header.length), &m.bone_info[j].name); - else - for (size_t j = 0; j < mh.bone_info_count; j++) - io_read_string_null_terminated_offset(&s_motc, - io_read_offset_x(&s_motc), &m.bone_info[j].name); - - io_set_position(&s_motc, mh.bone_hash_offset, SEEK_SET); - for (size_t j = 0; j < mh.bone_info_count; j++) - io_read_uint64_t_stream_reverse_endianness(&s_motc); - - io_set_position(&s_motc, mh.key_set_count_offset, SEEK_SET); - m.info = io_read_uint16_t_stream_reverse_endianness(&s_motc); - m.frame_count = io_read_uint16_t_stream_reverse_endianness(&s_motc); - - m.key_set = force_malloc_s(mot_key_set, m.key_set_count); - io_set_position(&s_motc, mh.key_set_types_offset, SEEK_SET); - for (int32_t j = 0, b = 0; j < m.key_set_count; j++) { - if (j % 8 == 0) - b = io_read_uint16_t_stream_reverse_endianness(&s_motc); - - m.key_set[j].type = (b >> (j % 8 * 2)) & 0x03; - } - - io_set_position(&s_motc, mh.key_set_offset, SEEK_SET); - for (int32_t j = 0; j < m.key_set_count; j++) { - mot_key_set* mks = &m.key_set[j]; - if (mks->type == MOT_KEY_SET_NONE) { - mks->keys_count = 0; - mks->keys = 0; - } - else if (mks->type == MOT_KEY_SET_STATIC) { - mks->keys_count = 1; - mks->keys = force_malloc_s(kft2, mks->keys_count); - mks->keys[0].frame = 0.0f; - mks->keys[0].value = io_read_float_t_stream_reverse_endianness(&s_motc); - } - else if (mks->type == MOT_KEY_SET_HERMITE - || mks->type == MOT_KEY_SET_HERMITE_TANGENT) { - mks->keys_count = io_read_uint16_t_stream_reverse_endianness(&s_motc); - mks->data_type = io_read_uint16_t_stream_reverse_endianness(&s_motc); - mks->keys = force_malloc_s(kft2, mks->keys_count); - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].tangent = io_read_float_t_stream_reverse_endianness(&s_motc); - else - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].tangent = 0.0f; - - if (mks->data_type == MOT_KEY_SET_DATA_F16) - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].value = half_to_float(io_read_half_t_stream_reverse_endianness(&s_motc)); - else - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].value = io_read_float_t_stream_reverse_endianness(&s_motc); - io_align_read(&s_motc, 0x04); - - for (uint32_t k = 0; k < mks->keys_count; k++) - mks->keys[k].frame = (float_t)io_read_uint16_t_stream_reverse_endianness(&s_motc); - io_align_read(&s_motc, 0x04); - } - } - - m.murmurhash = st.header.murmurhash; - vector_mot_push_back(&ms->vec, &m); - - io_free(&s_motc); - - ms->is_x = is_x; - ms->modern = true; - ms->ready = true; } - f2_struct_free(&st); } + free(mh); + + ms->is_x = false; + return true; } -static void mot_write_inner(mot_set* ms, stream* s) { - if (!ms->modern) { - size_t count = ms->vec.end - ms->vec.begin; - io_set_position(s, count * 0x10 + 0x10, SEEK_SET); - mot_header_classic* mh = force_malloc_s(mot_header_classic, count); - for (size_t i = 0; i < count; i++) { - mot* m = &ms->vec.begin[i]; +static void mot_classic_write_inner(mot_set* ms, stream* s) { + size_t count = ms->vec.end - ms->vec.begin; + io_set_position(s, count * 0x10 + 0x10, SEEK_SET); + mot_header_classic* mh = force_malloc_s(mot_header_classic, count); + for (size_t i = 0; i < count; i++) { + mot_data* m = &ms->vec.begin[i]; - mh[i].key_set_count_offset = (uint32_t)io_get_position(s); - io_write_uint16_t(s, m->info); - io_write_uint16_t(s, m->frame_count); + mh[i].key_set_count_offset = (uint32_t)io_get_position(s); + io_write_uint16_t(s, m->info); + io_write_uint16_t(s, m->frame_count); - mh[i].key_set_types_offset = (uint32_t)io_get_position(s); - uint16_t key_set_type_buf = 0; - for (int32_t j = 0; j < m->key_set_count; j++) { - key_set_type_buf |= ((uint16_t)m->key_set[j].type & 0x03) << (j % 8 * 2); + mh[i].key_set_types_offset = (uint32_t)io_get_position(s); + uint16_t key_set_type_buf = 0; + for (int32_t j = 0; j < m->key_set_count; j++) { + key_set_type_buf |= ((uint16_t)m->key_set[j].type & 0x03) << (j % 8 * 2); - if (j % 8 == 7) { - io_write_uint16_t(s, key_set_type_buf); - key_set_type_buf = 0; - } - } - - if (m->key_set_count % 8 != 0) + if (j % 8 == 7) { io_write_uint16_t(s, key_set_type_buf); - io_align_write(s, 0x04); - - mh[i].key_set_offset = (uint32_t)io_get_position(s); - for (int32_t j = 0; j < m->key_set_count; j++) { - mot_key_set* mks = &m->key_set[j]; - if (mks->type == MOT_KEY_SET_STATIC) - io_write_float_t(s, mks->keys[0].value); - else if (mks->type == MOT_KEY_SET_HERMITE - || mks->type == MOT_KEY_SET_HERMITE_TANGENT) { - io_write_uint16_t(s, (uint16_t)mks->keys_count); - for (size_t k = 0; k < mks->keys_count; k++) - io_write_uint16_t(s, (uint16_t)mks->keys[k].frame); - - if (io_get_position(s) % 4 != 0) - io_write_uint16_t(s, 0x00); - - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - for (size_t k = 0; k < mks->keys_count; k++) { - io_write_float_t(s, mks->keys[k].value); - io_write_float_t(s, mks->keys[k].tangent); - } - else - for (size_t k = 0; k < mks->keys_count; k++) - io_write_float_t(s, mks->keys[k].value); - } + key_set_type_buf = 0; } - io_align_write(s, 0x04); + } - mh[i].bone_info_offset = (uint32_t)io_get_position(s); - if (m->bone_info_count) - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_uint16_t(s, m->bone_info[j].index); - else - io_write_uint16_t(s, 0x00); - io_write_uint16_t(s, 0x00); + if (m->key_set_count % 8 != 0) + io_write_uint16_t(s, key_set_type_buf); + io_align_write(s, 0x04); + + mh[i].key_set_offset = (uint32_t)io_get_position(s); + for (int32_t j = 0; j < m->key_set_count; j++) { + mot_key_set_data* mks = &m->key_set[j]; + if (mks->type == MOT_KEY_SET_STATIC) + io_write_float_t(s, mks->values[0]); + else { + bool has_tangents = mks->type != MOT_KEY_SET_HERMITE; + uint16_t keys_count = mks->keys_count; + io_write_uint16_t(s, keys_count); + + uint16_t* frames = mks->frames; + for (int32_t k = 0; k < keys_count; k++) + io_write_uint16_t(s, *frames++); + io_align_write(s, 0x04); + + float_t* values = mks->values; + if (!has_tangents) + for (int32_t k = 0; k < keys_count; k++) + io_write_float_t(s, *values++); + else + for (int32_t k = 0; k < keys_count; k++) { + io_write_float_t(s, *values++); + io_write_float_t(s, *values++); + } + } } io_align_write(s, 0x04); - io_set_position(s, 0x00, SEEK_SET); - for (size_t i = 0; i < count; i++) { - io_write_uint32_t(s, mh[i].key_set_count_offset); - io_write_uint32_t(s, mh[i].key_set_types_offset); - io_write_uint32_t(s, mh[i].key_set_offset); - io_write_uint32_t(s, mh[i].bone_info_offset); - } - free(mh); + mh[i].bone_info_offset = (uint32_t)io_get_position(s); + if (m->bone_info_count) + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_uint16_t(s, m->bone_info[j].index); + else + io_write_uint16_t(s, 0x00); + io_write_uint16_t(s, 0x00); + } + io_align_write(s, 0x04); + + io_set_position(s, 0x00, SEEK_SET); + for (size_t i = 0; i < count; i++) { + io_write_uint32_t(s, mh[i].key_set_count_offset); + io_write_uint32_t(s, mh[i].key_set_types_offset); + io_write_uint32_t(s, mh[i].key_set_offset); + io_write_uint32_t(s, mh[i].bone_info_offset); + } + free(mh); +} + +static bool mot_modern_read_inner(mot_set* ms, stream* s) { + bool ret = false; + f2_struct st; + f2_struct_sread(&st, s); + if (st.header.signature != reverse_endianness_uint32_t('MOTC') || !st.data) { + f2_struct_free(&st); + return false; + } + + stream s_motc; + io_mopen(&s_motc, st.data, st.length); + s_motc.is_big_endian = st.header.use_big_endian; + + io_set_position(&s_motc, 0x0C, SEEK_SET); + bool is_x = io_read_uint32_t_stream_reverse_endianness(&s_motc) == 0; + + io_set_position(&s_motc, 0x00, SEEK_SET); + vector_mot_data_reserve(&ms->vec, 1); + mot_header_modern mh; + memset(&mh, 0, sizeof(mot_header_modern)); + if (!is_x) { + mh.hash = (uint32_t)io_read_uint64_t_stream_reverse_endianness(&s_motc); + mh.name_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.key_set_count_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.key_set_types_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.key_set_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.bone_info_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.bone_hash_offset = io_read_offset_f2(&s_motc, st.header.length); + mh.bone_info_count = io_read_int32_t_stream_reverse_endianness(&s_motc); } else { - stream s_motc; - io_open(&s_motc, 0, 0); - uint32_t o; - vector_enrs_entry e = vector_empty(enrs_entry); - enrs_entry ee; - vector_size_t pof = vector_empty(size_t); - uint32_t murmurhash = 0; - if (ms->vec.end - ms->vec.begin > 0) { - mot_header_modern mh; - memset(&mh, 0, sizeof(mot_header_modern)); - mot* m = ms->vec.begin; + mh.hash = (uint32_t)io_read_uint64_t_stream_reverse_endianness(&s_motc); + mh.name_offset = io_read_offset_x(&s_motc); + mh.key_set_count_offset = io_read_offset_x(&s_motc); + mh.key_set_types_offset = io_read_offset_x(&s_motc); + mh.key_set_offset = io_read_offset_x(&s_motc); + mh.bone_info_offset = io_read_offset_x(&s_motc); + mh.bone_hash_offset = io_read_offset_x(&s_motc); + mh.bone_info_count = io_read_int32_t_stream_reverse_endianness(&s_motc); + } - if (!ms->is_x) { - ee = (enrs_entry){ 0, 3, 48, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 7, ENRS_DWORD }); - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); - vector_enrs_entry_push_back(&e, &ee); - o = 48; + mot_data* m = vector_mot_data_reserve_back(&ms->vec); + m->div_frames = io_read_uint16_t_stream_reverse_endianness(&s_motc);; + m->div_count = io_read_uint8_t(&s_motc);; + + io_read_string_null_terminated_offset(&s_motc, mh.name_offset, &m->name); + + io_set_position(&s_motc, mh.bone_info_offset, SEEK_SET); + m->bone_info_count = mh.bone_info_count; + m->bone_info = force_malloc_s(mot_bone_info, m->bone_info_count); + if (!is_x) + for (size_t j = 0; j < mh.bone_info_count; j++) + io_read_string_null_terminated_offset(&s_motc, + io_read_offset_f2(&s_motc, st.header.length), &m->bone_info[j].name); + else + for (size_t j = 0; j < mh.bone_info_count; j++) + io_read_string_null_terminated_offset(&s_motc, + io_read_offset_x(&s_motc), &m->bone_info[j].name); + + io_set_position(&s_motc, mh.bone_hash_offset, SEEK_SET); + for (size_t j = 0; j < mh.bone_info_count; j++) + io_read_uint64_t_stream_reverse_endianness(&s_motc); + + io_set_position(&s_motc, mh.key_set_count_offset, SEEK_SET); + m->info = io_read_uint16_t_stream_reverse_endianness(&s_motc); + m->frame_count = io_read_uint16_t_stream_reverse_endianness(&s_motc); + + m->key_set = force_malloc_s(mot_key_set_data, m->key_set_count); + io_set_position(&s_motc, mh.key_set_types_offset, SEEK_SET); + for (int32_t j = 0, b = 0; j < m->key_set_count; j++) { + if (j % 8 == 0) + b = io_read_uint16_t_stream_reverse_endianness(&s_motc); + + m->key_set[j].type = (b >> (j % 8 * 2)) & 0x03; + } + + io_set_position(&s_motc, mh.key_set_offset, SEEK_SET); + for (int32_t j = 0; j < m->key_set_count; j++) { + mot_key_set_data* mks = &m->key_set[j]; + if (mks->type == MOT_KEY_SET_NONE) { + mks->keys_count = 0; + mks->frames_modern = 0; + mks->values = 0; + } + else if (mks->type == MOT_KEY_SET_STATIC) { + mks->keys_count = 1; + mks->frames_modern = 0; + mks->values = force_malloc_s(float_t, 1); + mks->values[0] = io_read_float_t_stream_reverse_endianness(&s_motc); + } + else { + bool has_tangents = mks->type != MOT_KEY_SET_HERMITE; + uint16_t keys_count = io_read_uint16_t_stream_reverse_endianness(s); + mot_key_set_data_type data_type = io_read_uint16_t_stream_reverse_endianness(&s_motc); + mks->keys_count = keys_count; + mks->data_type = data_type; + + mks->frames_modern = force_malloc_s(int16_t, keys_count); + mks->values = force_malloc_s(float_t, has_tangents ? keys_count * 2ULL : keys_count); + + uint8_t step = has_tangents ? 2 : 1; + if (has_tangents) { + float_t* values = &mks->values[1]; + for (int32_t k = 0; k < keys_count; k++, values += step) + *values = io_read_float_t_stream_reverse_endianness(&s_motc); } - else { - ee = (enrs_entry){ 0, 3, 64, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 7, ENRS_QWORD }); + + float_t* values = mks->values; + if (data_type == MOT_KEY_SET_DATA_F16) + for (int32_t k = 0; k < keys_count; k++, values += step) + *values = half_to_float(io_read_half_t_stream_reverse_endianness(&s_motc)); + else + for (int32_t k = 0; k < keys_count; k++, values += step) + *values = io_read_float_t_stream_reverse_endianness(&s_motc); + io_align_read(&s_motc, 0x04); + + int16_t* frames = mks->frames_modern; + for (int32_t k = 0; k < keys_count; k++) + *frames++ = io_read_int16_t_stream_reverse_endianness(&s_motc); + io_align_read(&s_motc, 0x04); + } + } + + m->murmurhash = st.header.murmurhash; + + io_free(&s_motc); + f2_struct_free(&st); + + ms->is_x = is_x; + return true; +} + +static void mot_modern_write_inner(mot_set* ms, stream* s) { + stream s_motc; + io_open(&s_motc, 0, 0); + uint32_t o; + vector_enrs_entry e = vector_empty(enrs_entry); + enrs_entry ee; + vector_size_t pof = vector_empty(size_t); + uint32_t murmurhash = 0; + if (ms->vec.end - ms->vec.begin > 0) { + mot_header_modern mh; + memset(&mh, 0, sizeof(mot_header_modern)); + mot_data* m = ms->vec.begin; + + if (!ms->is_x) { + ee = (enrs_entry){ 0, 3, 48, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 7, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + o = 48; + } + else { + ee = (enrs_entry){ 0, 3, 64, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 7, ENRS_QWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + o = 64; + }; + + ee = (enrs_entry){ o, 1, 4, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + o = 4; + + ee = (enrs_entry){ o, 1, (m->key_set_count + 3) / 4, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ 0, (m->key_set_count + 7) / 8, ENRS_WORD }); + vector_enrs_entry_push_back(&e, &ee); + o = (m->key_set_count + 3) / 4; + o = align_val(o, 4); + + for (int32_t j = 0; j < m->key_set_count; j++) { + mot_key_set_data* mks = &m->key_set[j]; + if (mks->type == MOT_KEY_SET_STATIC) { + ee = (enrs_entry){ o, 1, 4, 1, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - o = 64; - }; - - ee = (enrs_entry){ o, 1, 4, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_WORD }); - vector_enrs_entry_push_back(&e, &ee); - o = 4; - - ee = (enrs_entry){ o, 1, (m->key_set_count + 3) / 4, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ 0, (m->key_set_count + 7) / 8, ENRS_WORD }); - vector_enrs_entry_push_back(&e, &ee); - o = (m->key_set_count + 3) / 4; - o = align_val(o, 4); - - for (int32_t j = 0; j < m->key_set_count; j++) { - mot_key_set* mks = &m->key_set[j]; - if (mks->type == MOT_KEY_SET_STATIC) { + o = 4; + } + else if (mks->type != MOT_KEY_SET_NONE) { + bool has_tangents = mks->type != MOT_KEY_SET_HERMITE; + if (has_tangents) ee = (enrs_entry){ o, 1, 4, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); - vector_enrs_entry_push_back(&e, &ee); - o = 4; + else + ee = (enrs_entry){ o, 1, 3, 1, vector_empty(enrs_sub_entry) }; + + uint16_t keys_count = mks->keys_count; + mot_key_set_data_type data_type = mks->data_type; + o = 4; + if (has_tangents) + o += keys_count * 4; + + if (data_type == MOT_KEY_SET_DATA_F16) + o += align_val(keys_count * 2, 4); + else + o += keys_count * 4; + o += align_val(keys_count * 2, 4); + o = align_val(o, 4); + ee.size = o; + + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_WORD }); + if (has_tangents) + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ 0, keys_count, ENRS_DWORD }); + if (data_type == MOT_KEY_SET_DATA_F16) { + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ 0, keys_count, ENRS_WORD }); + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ keys_count % 2 == 1 ? 2 : 0, keys_count, ENRS_WORD }); } - else if (mks->type == MOT_KEY_SET_HERMITE - || mks->type == MOT_KEY_SET_HERMITE_TANGENT) { - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - ee = (enrs_entry){ o, 1, 4, 1, vector_empty(enrs_sub_entry) }; - else - ee = (enrs_entry){ o, 1, 3, 1, vector_empty(enrs_sub_entry) }; - - o = 4; - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - o += mks->keys_count * 4; - - if (mks->data_type == MOT_KEY_SET_DATA_F16) - o += align_val(mks->keys_count * 2, 4); - else - o += mks->keys_count * 4; - o += align_val(mks->keys_count * 2, 4); - o = align_val(o, 4); - ee.size = o; - - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_WORD }); - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ 0, mks->keys_count, ENRS_DWORD }); - if (mks->data_type == MOT_KEY_SET_DATA_F16) { - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ 0, mks->keys_count, ENRS_WORD }); - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ mks->keys_count % 2 == 1 ? 2 : 0, mks->keys_count, ENRS_WORD }); - } - else { - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ 0, mks->keys_count, ENRS_DWORD }); - vector_enrs_sub_entry_push_back(&ee.sub, - &(enrs_sub_entry){ 0, mks->keys_count, ENRS_WORD }); - } - vector_enrs_entry_push_back(&e, &ee); + else { + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ 0, keys_count, ENRS_DWORD }); + vector_enrs_sub_entry_push_back(&ee.sub, + &(enrs_sub_entry){ 0, keys_count, ENRS_WORD }); } - } - o = align_val(o, 16); - - if (!ms->is_x) { - ee = (enrs_entry){ o, 1, m->bone_info_count * 4, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, m->bone_info_count, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - o = m->bone_info_count * 4; } - else { - ee = (enrs_entry){ o, 1, m->bone_info_count * 8, 1, vector_empty(enrs_sub_entry) }; - vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, m->bone_info_count, ENRS_QWORD }); - vector_enrs_entry_push_back(&e, &ee); - o = m->bone_info_count * 8; - } - o = align_val(o, 16); + } + o = align_val(o, 16); + if (!ms->is_x) { + ee = (enrs_entry){ o, 1, m->bone_info_count * 4, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, m->bone_info_count, ENRS_DWORD }); + vector_enrs_entry_push_back(&e, &ee); + o = m->bone_info_count * 4; + } + else { ee = (enrs_entry){ o, 1, m->bone_info_count * 8, 1, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, m->bone_info_count, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); o = m->bone_info_count * 8; + } + o = align_val(o, 16); - if (!ms->is_x) { - io_write_uint64_t(&s_motc, 0); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - io_write_int32_t(&s_motc, 0); - io_write_int32_t(&s_motc, 0); - } - else { - io_write_uint64_t(&s_motc, 0); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_write_int32_t(&s_motc, 0); - } - io_write_uint16_t(&s_motc, 0); - io_write_uint8_t(&s_motc, 0); - io_align_write(&s_motc, 0x10); + ee = (enrs_entry){ o, 1, m->bone_info_count * 8, 1, vector_empty(enrs_sub_entry) }; + vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, m->bone_info_count, ENRS_QWORD }); + vector_enrs_entry_push_back(&e, &ee); + o = m->bone_info_count * 8; - mh.hash = hash_utf8_murmurhash(string_data(&m->name), 0, false); + if (!ms->is_x) { + io_write_uint64_t(&s_motc, 0); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + io_write_int32_t(&s_motc, 0); + io_write_int32_t(&s_motc, 0); + } + else { + io_write_uint64_t(&s_motc, 0); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_write_int32_t(&s_motc, 0); + } + io_write_uint16_t(&s_motc, 0); + io_write_uint8_t(&s_motc, 0); + io_align_write(&s_motc, 0x10); - mh.key_set_count_offset = io_get_position(&s_motc); - io_write_uint16_t(&s_motc, m->info); - io_write_uint16_t(&s_motc, m->frame_count); + mh.hash = hash_utf8_murmurhash(string_data(&m->name), 0, false); - mh.key_set_types_offset = io_get_position(&s_motc); - uint16_t key_set_type_buf = 0; - for (int32_t j = 0; j < m->key_set_count; j++) { - key_set_type_buf |= ((uint16_t)m->key_set[j].type & 0x03) << (j % 8 * 2); + mh.key_set_count_offset = io_get_position(&s_motc); + io_write_uint16_t(&s_motc, m->info); + io_write_uint16_t(&s_motc, m->frame_count); - if (j % 8 == 7) { - io_write_uint16_t(&s_motc, key_set_type_buf); - key_set_type_buf = 0; - } - } + mh.key_set_types_offset = io_get_position(&s_motc); + uint16_t key_set_type_buf = 0; + for (int32_t j = 0; j < m->key_set_count; j++) { + key_set_type_buf |= ((uint16_t)m->key_set[j].type & 0x03) << (j % 8 * 2); - if (m->key_set_count % 8 != 0) + if (j % 8 == 7) { io_write_uint16_t(&s_motc, key_set_type_buf); - io_align_write(&s_motc, 0x04); - - mh.key_set_offset = io_get_position(&s_motc); - for (int32_t j = 0; j < m->key_set_count; j++) { - mot_key_set* mks = &m->key_set[j]; - if (mks->type == MOT_KEY_SET_STATIC) - io_write_float_t(&s_motc, mks->keys[0].value); - else if (mks->type == MOT_KEY_SET_HERMITE - || mks->type == MOT_KEY_SET_HERMITE_TANGENT) { - io_write_uint16_t(&s_motc, (uint16_t)mks->keys_count); - io_write_uint16_t(&s_motc, (uint16_t)mks->data_type); - if (mks->type == MOT_KEY_SET_HERMITE_TANGENT) - for (uint32_t k = 0; k < mks->keys_count; k++) - io_write_float_t(&s_motc, mks->keys[k].tangent); - - if (mks->data_type == MOT_KEY_SET_DATA_F16) - for (uint32_t k = 0; k < mks->keys_count; k++) - io_write_half_t(&s_motc, float_to_half(mks->keys[k].value)); - else - for (uint32_t k = 0; k < mks->keys_count; k++) - io_write_float_t(&s_motc, mks->keys[k].value); - io_align_read(&s_motc, 0x04); - - for (uint32_t k = 0; k < mks->keys_count; k++) - io_write_uint16_t(&s_motc, (uint16_t)mks->keys[k].frame); - io_align_read(&s_motc, 0x04); - } + key_set_type_buf = 0; } - io_align_write(&s_motc, 0x10); - - size_t* bone_info_offsets = force_malloc_s(size_t, m->bone_info_count); - mh.bone_info_offset = io_get_position(&s_motc); - if (!ms->is_x) - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); - else - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_offset_x_pof_add(&s_motc, 0, &pof); - io_align_write(&s_motc, 0x10); - - mh.bone_hash_offset = io_get_position(&s_motc); - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_uint64_t(&s_motc, hash_utf8_murmurhash( - string_data(&m->bone_info[j].name), 0, false)); - io_align_write(&s_motc, 0x10); - - mh.name_offset = io_get_position(&s_motc); - io_write_string_null_terminated(&s_motc, &m->name); - - for (int32_t j = 0; j < m->bone_info_count; j++) { - bone_info_offsets[j] = io_get_position(&s_motc); - io_write_string_null_terminated(&s_motc, &m->bone_info[j].name); - } - io_align_write(&s_motc, 0x10); - - io_set_position(&s_motc, mh.bone_info_offset, SEEK_SET); - mh.bone_info_count = m->bone_info_count; - if (!ms->is_x) - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_offset_f2(&s_motc, bone_info_offsets[j], 0x40); - else - for (int32_t j = 0; j < m->bone_info_count; j++) - io_write_offset_x(&s_motc, bone_info_offsets[j]); - free(bone_info_offsets); - - io_set_position(&s_motc, 0x00, SEEK_SET); - if (!ms->is_x) { - io_write_uint64_t(&s_motc, (uint64_t)mh.hash); - io_write_offset_f2(&s_motc, mh.name_offset, 0x40); - io_write_offset_f2(&s_motc, mh.key_set_count_offset, 0x40); - io_write_offset_f2(&s_motc, mh.key_set_types_offset, 0x40); - io_write_offset_f2(&s_motc, mh.key_set_offset, 0x40); - io_write_offset_f2(&s_motc, mh.bone_info_offset, 0x40); - io_write_offset_f2(&s_motc, mh.bone_hash_offset, 0x40); - io_write_int32_t(&s_motc, mh.bone_info_count); - } - else { - io_write_uint64_t(&s_motc, (uint64_t)mh.hash); - io_write_offset_x(&s_motc, mh.name_offset); - io_write_offset_x(&s_motc, mh.key_set_count_offset); - io_write_offset_x(&s_motc, mh.key_set_types_offset); - io_write_offset_x(&s_motc, mh.key_set_offset); - io_write_offset_x(&s_motc, mh.bone_info_offset); - io_write_offset_x(&s_motc, mh.bone_hash_offset); - io_write_int32_t(&s_motc, mh.bone_info_count); - } - - if (m->div_frames > 0) { - io_write_uint16_t(&s_motc, m->div_frames); - io_write_uint8_t(&s_motc, m->div_count); - } - else { - io_write_uint16_t(&s_motc, 0); - io_write_uint8_t(&s_motc, 0); - } - - murmurhash = m->murmurhash; } - f2_struct st; - memset(&st, 0, sizeof(f2_struct)); + if (m->key_set_count % 8 != 0) + io_write_uint16_t(&s_motc, key_set_type_buf); + io_align_write(&s_motc, 0x04); + mh.key_set_offset = io_get_position(&s_motc); + for (int32_t j = 0; j < m->key_set_count; j++) { + mot_key_set_data* mks = &m->key_set[j]; + if (mks->type == MOT_KEY_SET_STATIC) + io_write_float_t(&s_motc, mks->values[0]); + else if (mks->type != MOT_KEY_SET_NONE) { + bool has_tangents = mks->type != MOT_KEY_SET_HERMITE; + uint16_t keys_count = mks->keys_count; + mot_key_set_data_type data_type = mks->data_type; + io_write_uint16_t(&s_motc, keys_count); + io_write_uint16_t(&s_motc, (uint16_t)data_type); + + uint8_t step = has_tangents ? 2 : 1; + if (has_tangents) { + float_t* values = &mks->values[1]; + for (int32_t k = 0; k < keys_count; k++, values += step) + io_write_float_t(&s_motc, *values); + } + + float_t* values = mks->values; + if (data_type == MOT_KEY_SET_DATA_F16) + for (int32_t k = 0; k < keys_count; k++, values += step) + io_write_half_t(&s_motc, float_to_half(*values)); + else + for (int32_t k = 0; k < keys_count; k++, values += step) + io_write_float_t(&s_motc, *values); + io_align_write(&s_motc, 0x04); + + int16_t* frames = mks->frames_modern; + for (int32_t k = 0; k < keys_count; k++) + io_write_int16_t(&s_motc, *frames++); + io_align_write(&s_motc, 0x04); + } + } io_align_write(&s_motc, 0x10); - io_mcopy(&s_motc, &st.data, &st.length); - io_free(&s_motc); - st.enrs = e; - st.pof = pof; + size_t* bone_info_offsets = force_malloc_s(size_t, m->bone_info_count); + mh.bone_info_offset = io_get_position(&s_motc); + if (!ms->is_x) + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_offset_f2_pof_add(&s_motc, 0, 0x40, &pof); + else + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_offset_x_pof_add(&s_motc, 0, &pof); + io_align_write(&s_motc, 0x10); - st.header.signature = reverse_endianness_uint32_t('MOTC'); - st.header.length = 0x40; - st.header.use_big_endian = false; - st.header.use_section_size = true; - st.header.murmurhash = murmurhash; - st.header.inner_signature = 0xFF010008; + mh.bone_hash_offset = io_get_position(&s_motc); + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_uint64_t(&s_motc, hash_utf8_murmurhash( + string_data(&m->bone_info[j].name), 0, false)); + io_align_write(&s_motc, 0x10); - f2_struct_swrite(&st, s, true, ms->is_x); - f2_struct_free(&st); + mh.name_offset = io_get_position(&s_motc); + io_write_string_null_terminated(&s_motc, &m->name); + + for (int32_t j = 0; j < m->bone_info_count; j++) { + bone_info_offsets[j] = io_get_position(&s_motc); + io_write_string_null_terminated(&s_motc, &m->bone_info[j].name); + } + io_align_write(&s_motc, 0x10); + + io_set_position(&s_motc, mh.bone_info_offset, SEEK_SET); + mh.bone_info_count = m->bone_info_count; + if (!ms->is_x) + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_offset_f2(&s_motc, bone_info_offsets[j], 0x40); + else + for (int32_t j = 0; j < m->bone_info_count; j++) + io_write_offset_x(&s_motc, bone_info_offsets[j]); + free(bone_info_offsets); + + io_set_position(&s_motc, 0x00, SEEK_SET); + if (!ms->is_x) { + io_write_uint64_t(&s_motc, (uint64_t)mh.hash); + io_write_offset_f2(&s_motc, mh.name_offset, 0x40); + io_write_offset_f2(&s_motc, mh.key_set_count_offset, 0x40); + io_write_offset_f2(&s_motc, mh.key_set_types_offset, 0x40); + io_write_offset_f2(&s_motc, mh.key_set_offset, 0x40); + io_write_offset_f2(&s_motc, mh.bone_info_offset, 0x40); + io_write_offset_f2(&s_motc, mh.bone_hash_offset, 0x40); + io_write_int32_t(&s_motc, mh.bone_info_count); + } + else { + io_write_uint64_t(&s_motc, (uint64_t)mh.hash); + io_write_offset_x(&s_motc, mh.name_offset); + io_write_offset_x(&s_motc, mh.key_set_count_offset); + io_write_offset_x(&s_motc, mh.key_set_types_offset); + io_write_offset_x(&s_motc, mh.key_set_offset); + io_write_offset_x(&s_motc, mh.bone_info_offset); + io_write_offset_x(&s_motc, mh.bone_hash_offset); + io_write_int32_t(&s_motc, mh.bone_info_count); + } + + if (m->div_frames > 0) { + io_write_uint16_t(&s_motc, m->div_frames); + io_write_uint8_t(&s_motc, m->div_count); + } + else { + io_write_uint16_t(&s_motc, 0); + io_write_uint8_t(&s_motc, 0); + } + + murmurhash = m->murmurhash; } + + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + + io_align_write(&s_motc, 0x10); + io_mcopy(&s_motc, &st.data, &st.length); + io_free(&s_motc); + + st.enrs = e; + st.pof = pof; + + st.header.signature = reverse_endianness_uint32_t('MOTC'); + st.header.length = 0x40; + st.header.use_big_endian = false; + st.header.use_section_size = true; + st.header.murmurhash = murmurhash; + st.header.inner_signature = 0xFF010008; + + f2_struct_swrite(&st, s, true, ms->is_x); + f2_struct_free(&st); } diff --git a/src/KKdLib/mot.h b/src/KKdLib/mot.h index 7d923f7f..792b49c5 100644 --- a/src/KKdLib/mot.h +++ b/src/KKdLib/mot.h @@ -6,8 +6,9 @@ #pragma once #include "default.h" +#include "farc.h" #include "string.h" -#include "kf.h" +#include "vec.h" #include "vector.h" typedef enum mot_key_set_type { @@ -27,18 +28,23 @@ typedef union mot_bone_info { uint16_t index; } mot_bone_info; -typedef struct mot_key_set { +typedef struct mot_key_set_data { mot_key_set_type type; - kft2* keys; - uint32_t keys_count; - mot_key_set_data_type data_type; -} mot_key_set; + union { + uint16_t* frames; + int16_t* frames_modern; + }; + float_t* values; + uint16_t keys_count : 16; + mot_key_set_data_type data_type : 16; +} mot_key_set_data; -typedef struct mot { +typedef struct mot_data { union { struct { uint16_t key_set_count : 14; - uint16_t high_bits : 2; + uint16_t skeleton_select : 1; + uint16_t high_bit : 1; }; uint16_t info; }; @@ -50,30 +56,34 @@ typedef struct mot { uint8_t div_count; string name; mot_bone_info* bone_info; - mot_key_set* key_set; -} mot; + mot_key_set_data* key_set; +} mot_data; -vector(mot) +vector(mot_data) typedef struct mot_set { - bool ready; - bool modern; bool is_x; - vector_mot vec; + string name; + vector_mot_data vec; } mot_set; -typedef struct mot_skeleton_rotation_reverse { - bool x; - bool y; - bool z; - vec3 rotation; -} mot_skeleton_rotation_reverse; +vector(mot_set) -extern mot_set* mot_init(); -extern void mot_read(mot_set* ms, char* path, bool modern); -extern void mot_wread(mot_set* ms, wchar_t* path, bool modern); -extern void mot_mread(mot_set* ms, void* data, size_t length, bool modern); -extern void mot_write(mot_set* ms, char* path); -extern void mot_wwrite(mot_set* ms, wchar_t* path); -extern void mot_mwrite(mot_set* ms, void** data, size_t* length); -extern void mot_dispose(mot_set* ms); +typedef struct mot_set_farc { + bool ready; + bool modern; + vector_mot_set vec; +} mot_set_farc; + +extern void mot_init(mot_set_farc* msf); +extern void mot_read(mot_set_farc* msf, char* path, bool modern); +extern void mot_wread(mot_set_farc* msf, wchar_t* path, bool modern); +extern void mot_mread(mot_set_farc* msf, void* data, size_t length, bool modern); +extern void mot_write(mot_set_farc* msf, char* path, farc_compress_mode mode); +extern void mot_wwrite(mot_set_farc* msf, wchar_t* path, farc_compress_mode mode); +extern void mot_mwrite(mot_set_farc* msf, void** data, size_t* length, farc_compress_mode mode); +extern bool mot_load_file(void* data, char* path, char* file, uint32_t hash); +extern void mot_free(mot_set_farc* msf); + +extern void mot_set_init(mot_set* ms); +extern void mot_set_free(mot_set* ms); diff --git a/src/KKdLib/moti.h b/src/KKdLib/moti.h deleted file mode 100644 index d90fe86e..00000000 --- a/src/KKdLib/moti.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - by korenkonder - GitHub/GitLab: korenkonder -*/ - -#pragma once - -#include "default.h" -#include "kf.h" - -typedef struct moti { - kft2* array; - size_t length; - - float_t frame; - float_t time; - float_t value; - float_t delta_frame; - float_t interpolation_framerate; - float_t requested_framerate; - - kft2* first_key; - kft2* last_key; -} moti; - -extern moti* kft2_array_to_moti(kft2* array, size_t length, - float_t interpolation_framerate, float_t requested_framerate); -extern void moti_set_interpolation_framerate(moti* interp, float_t interpolation_framerate); -extern void moti_set_requested_framerate(moti* interp, float_t requested_framerate); -extern void moti_update(moti* interp); -extern void moti_reset(moti* interp); -extern float_t moti_set_time(moti* interp, float_t time); -extern float_t moti_set_frame(moti* interp, float_t frame); -extern float_t moti_add_time(moti* interp, float_t time); -extern float_t moti_next_frame(moti* interp); - diff --git a/src/KKdLib/msgpack.c b/src/KKdLib/msgpack.c index e6e95d3e..8683d4f9 100644 --- a/src/KKdLib/msgpack.c +++ b/src/KKdLib/msgpack.c @@ -4,6 +4,7 @@ */ #include "msgpack.h" +#include "str_utils.h" #define MSGPACK_ALLOCATE(a, b) \ if (MSGPACK_CHECK(a)) \ @@ -40,7 +41,7 @@ void msgpack_init_null(msgpack* msg, char* name) { } void msgpack_init_bool(msgpack* msg, char* name, bool val) { - msg->type = MSGPACK_BOOL; + msg->type = MSGPACK_bool; MSGPACK_ALLOCATE_PTR(bool, msg); string_init(&msg->name, name); @@ -158,16 +159,14 @@ void msgpack_init_string(msgpack* msg, char* name, string* val) { msg->type = MSGPACK_STRING; MSGPACK_ALLOCATE_PTR(string, msg); string_init(&msg->name, name); - string_init(MSGPACK_SELECT_PTR(string, msg), string_data(val)); + string_copy(val, MSGPACK_SELECT_PTR(string, msg)); } void msgpack_init_wstring(msgpack* msg, char* name, wstring* val) { - char* temp = utf16_to_utf8(wstring_access(val)); msg->type = MSGPACK_STRING; MSGPACK_ALLOCATE_PTR(string, msg); string_init(&msg->name, name); - string_init(MSGPACK_SELECT_PTR(string, msg), temp); - free(temp); + string_copy_wstring(val, MSGPACK_SELECT_PTR(string, msg)); } bool msgpack_check_null(msgpack* msg) { @@ -213,7 +212,7 @@ msgpack* msgpack_get_by_name(msgpack* msg, char* name) { msgpack_map* ptr = MSGPACK_SELECT_PTR(msgpack_map, msg); for (msgpack* i = ptr->begin; i != ptr->end; i++) - if (!strcmp(string_data(&i->name), name)) + if (!str_utils_compare(string_data(&i->name), name)) return i; return 0; @@ -225,7 +224,7 @@ void msgpack_set_by_name(msgpack* msg, msgpack* m) { msgpack_map* ptr = MSGPACK_SELECT_PTR(msgpack_map, msg); for (msgpack* i = ptr->begin; i != ptr->end; i++) - if (!strcmp(string_data(&i->name), string_data(&m->name))) { + if (!str_utils_compare(string_data(&i->name), string_data(&m->name))) { msgpack_free(i); *i = *m; return; @@ -245,7 +244,7 @@ void msgpack_append(msgpack* msg, msgpack* m) { void msgpack_append_bool(msgpack* msg, char* name, bool val) { msgpack m; - m.type = MSGPACK_BOOL; + m.type = MSGPACK_bool; MSGPACK_ALLOCATE(bool, m); string_init(&m.name, name); @@ -389,18 +388,16 @@ void msgpack_append_string(msgpack* msg, char* name, string* val) { m.type = MSGPACK_STRING; MSGPACK_ALLOCATE(string, m); string_init(&m.name, name); - string_init(MSGPACK_SELECT(string, m), string_data(val)); + string_copy(val, MSGPACK_SELECT(string, m)); msgpack_append(msg, &m); } void msgpack_append_wstring(msgpack* msg, char* name, wstring* val) { msgpack m; - char* temp = utf16_to_utf8(wstring_access(val)); m.type = MSGPACK_STRING; MSGPACK_ALLOCATE(string, m); string_init(&m.name, name); - string_init(MSGPACK_SELECT(string, m), temp); - free(temp); + string_copy_wstring(val, MSGPACK_SELECT(string, m)); msgpack_append(msg, &m); } @@ -472,7 +469,7 @@ void msgpack_set_bool(msgpack* msg, char* name, bool val) { return; msgpack_free(msg); - msg->type = MSGPACK_BOOL; + msg->type = MSGPACK_bool; MSGPACK_ALLOCATE_PTR(bool, msg); string_init(&msg->name, name); @@ -642,20 +639,18 @@ void msgpack_set_string(msgpack* msg, char* name, string* val) { msg->type = MSGPACK_STRING; MSGPACK_ALLOCATE_PTR(string, msg); string_init(&msg->name, name); - string_init(MSGPACK_SELECT_PTR(string, msg), string_data(val)); + string_copy(val, MSGPACK_SELECT_PTR(string, msg)); } void msgpack_set_wstring(msgpack* msg, char* name, wstring* val) { if (!msg) return; - char* temp = utf16_to_utf8(wstring_access(val)); msgpack_free(msg); msg->type = MSGPACK_STRING; MSGPACK_ALLOCATE_PTR(string, msg); string_init(&msg->name, name); - string_init(MSGPACK_SELECT_PTR(string, msg), temp); - free(temp); + string_copy_wstring(val, MSGPACK_SELECT_PTR(string, msg)); } msgpack* msgpack_read(msgpack* msg, char* name) { @@ -670,7 +665,7 @@ bool msgpack_read_bool(msgpack* msg, char* name) { return 0; msgpack* m = name ? msgpack_get_by_name(msg, name) : msg; - if (m && m->type == MSGPACK_BOOL) + if (m && m->type == MSGPACK_bool) return *MSGPACK_SELECT_PTR(bool, m); return 0; } @@ -913,9 +908,10 @@ char* msgpack_read_utf8_string(msgpack* msg, char* name) { if (m && m->type == MSGPACK_STRING) { string* ptr = MSGPACK_SELECT_PTR(string, m); - size_t length = string_length(ptr) + 1; - char* val = force_malloc(length); + size_t length = ptr->length; + char* val = force_malloc(length + 1); memcpy(val, string_data(ptr), length); + val[length] = 0; return val; } return 0; @@ -930,9 +926,10 @@ wchar_t* msgpack_read_utf16_string(msgpack* msg, char* name) { if (m && m->type == MSGPACK_STRING) { string* ptr = MSGPACK_SELECT_PTR(string, m); wchar_t* temp = utf8_to_utf16(string_data(ptr)); - size_t length = utf16_length(temp) + 1; - wchar_t* val = force_malloc_s(wchar_t, length); + size_t length = utf16_length(temp); + wchar_t* val = force_malloc_s(wchar_t, length + 1); memcpy(val, temp, sizeof(wchar_t) * length); + val[length] = 0; free(temp); return val; } @@ -941,7 +938,7 @@ wchar_t* msgpack_read_utf16_string(msgpack* msg, char* name) { void msgpack_read_string(msgpack* msg, char* name, string* str) { if (!msg) { - string_init(str, 0); + *str = string_empty; return; } @@ -949,15 +946,15 @@ void msgpack_read_string(msgpack* msg, char* name, string* str) { if (m && m->type == MSGPACK_STRING) { string* ptr = MSGPACK_SELECT_PTR(string, m); - string_init(str, string_data(ptr)); + string_init_length(str, string_data(ptr), ptr->length); } else - string_init(str, 0); + *str = string_empty; } void msgpack_read_wstring(msgpack* msg, char* name, wstring* str) { if (!msg) { - wstring_init(str, 0); + *str = wstring_empty; return; } @@ -970,7 +967,7 @@ void msgpack_read_wstring(msgpack* msg, char* name, wstring* str) { free(temp); } else - wstring_init(str, 0); + *str = wstring_empty; } void msgpack_free(msgpack* msg) { @@ -985,15 +982,11 @@ void msgpack_free(msgpack* msg) { break; case MSGPACK_ARRAY: { msgpack_array* ptr = MSGPACK_SELECT_PTR(msgpack_array, msg); - for (msgpack* i = ptr->begin; i != ptr->end; i++) - msgpack_free(i); - vector_msgpack_free(ptr); + vector_msgpack_free(ptr, msgpack_free); } break; case MSGPACK_MAP: { msgpack_map* ptr = MSGPACK_SELECT_PTR(msgpack_map, msg); - for (msgpack* i = ptr->begin; i != ptr->end; i++) - msgpack_free(i); - vector_msgpack_free(ptr); + vector_msgpack_free(ptr, msgpack_free); } break; } memset(msg, 0, sizeof(msgpack)); diff --git a/src/KKdLib/msgpack.h b/src/KKdLib/msgpack.h index f9a14e2c..9beb324c 100644 --- a/src/KKdLib/msgpack.h +++ b/src/KKdLib/msgpack.h @@ -12,7 +12,7 @@ typedef enum msgpack_type { MSGPACK_NONE = 0, MSGPACK_NULL, - MSGPACK_BOOL, + MSGPACK_bool, MSGPACK_INT8, MSGPACK_UINT8, MSGPACK_INT16, diff --git a/src/KKdLib/obj.c b/src/KKdLib/obj.c index 93896729..9683acf6 100644 --- a/src/KKdLib/obj.c +++ b/src/KKdLib/obj.c @@ -4,12 +4,13 @@ */ #include "obj.h" -#include "f2_struct.h" +#include "f2/struct.h" +#include "io/path.h" +#include "io/stream.h" #include "half_t.h" #include "hash.h" -#include "io_path.h" -#include "io_stream.h" #include "str_utils.h" +#include "vector.h" typedef enum obj_vertex_attrib_type { OBJ_VERTEX_ATTRIB_POSITION = 0x00000001, @@ -35,12 +36,11 @@ typedef struct obj_skin_block_header { typedef struct obj_skin_ex_data_header { int32_t osage_count; - int32_t osage_nodes_count; ssize_t osage_nodes_offset; ssize_t osage_names_offset; ssize_t blocks_offset; - int32_t strings_count; - ssize_t strings_offset; + int32_t bone_names_count; + ssize_t bone_names_offset; ssize_t osage_sibling_infos_offset; int32_t cloth_count; } obj_skin_ex_data_header; @@ -50,19 +50,15 @@ typedef struct obj_skin_header { ssize_t bone_matrices_offset; ssize_t bone_names_offset; ssize_t ex_data_offset; - int32_t bone_count; ssize_t bone_parent_ids_offset; } obj_skin_header; typedef struct obj_sub_mesh_header { - int32_t bone_index_count; ssize_t bone_indices_offset; - int32_t indices_count; ssize_t indices_offset; } obj_sub_mesh_header; typedef struct obj_mesh_header { - int32_t sub_meshes_count; ssize_t sub_meshes_offset; obj_vertex_attrib_type attrib_type; int32_t vertex_size; @@ -72,21 +68,17 @@ typedef struct obj_mesh_header { } obj_mesh_header; typedef struct obj_header { - int32_t meshes_count; ssize_t meshes_offset; - int32_t materials_count; ssize_t materials_offset; } obj_header; typedef struct obj_set_header { - int32_t objects_count; int32_t max_object_id; ssize_t objects_offset; ssize_t object_skins_offset; ssize_t object_names_offset; ssize_t object_ids_offset; ssize_t texture_ids_offset; - int32_t texture_ids_count; } obj_set_header; const char obj_material_texture_enrs_table_bin[] = @@ -120,144 +112,134 @@ const char obj_material_texture_enrs_table_bin[] = static vector_enrs_entry obj_material_texture_enrs_table; static bool obj_material_texture_enrs_table_initialized; -vector_func(obj_material_parent) -vector_func(obj_sub_mesh) -vector_func(obj_mesh) -vector_func(obj_skin_block_cloth_field_1C) -vector_func(obj_skin_block_cloth_field_20) -vector_func(obj_skin_motion_node) -vector_func(obj_skin_osage_node) -vector_func(obj_skin_block) -vector_func(obj_skin_bone) -vector_func(obj) - static void obj_material_texture_enrs_table_init(); static void obj_material_texture_enrs_table_free(void); static void obj_classic_read_inner(obj_set* os, stream* s); static void obj_classic_write_inner(obj_set* os, stream* s); -static void obj_classic_read_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t indices_count); -static void obj_classic_write_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t* indices_count); -static void obj_classic_read_model(obj* o, stream* s, ssize_t base_offset); -static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset); -static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset); -static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset); +static void obj_classic_read_index(obj* obj, stream* s, obj_sub_mesh* sub_mesh); +static void obj_classic_write_index(obj* obj, stream* s, obj_sub_mesh* sub_mesh); +static void obj_classic_read_model(obj* obj, stream* s, ssize_t base_offset); +static void obj_classic_write_model(obj* obj, stream* s, ssize_t base_offset); +static void obj_classic_read_skin(obj* obj, stream* s, ssize_t base_offset); +static void obj_classic_write_skin(obj* obj, stream* s, ssize_t base_offset); static void obj_classic_read_skin_block_cloth(obj_skin_block_cloth* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_cloth(obj_skin_block_cloth* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* field_18_offset, ssize_t* field_1C_offset, ssize_t* field_20_offset, ssize_t* field_24_offset, ssize_t* field_28_offset); static void obj_classic_read_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, stream* s, vector_string* strings, vector_ssize_t* string_offsets); static void obj_classic_read_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, stream* s, vector_string* strings, vector_ssize_t* string_offsets); static void obj_classic_read_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* offsets); + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, ssize_t* offsets); static void obj_classic_read_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, stream* s, vector_string* strings, vector_ssize_t* string_offsets); static void obj_classic_read_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, stream* s, vector_string* strings, vector_ssize_t* string_offsets); static void obj_classic_read_skin_block_expression(obj_skin_block_expression* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_expression(obj_skin_block_expression* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets); + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names); static void obj_classic_read_skin_block_motion(obj_skin_block_motion* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_motion(obj_skin_block_motion* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, - vector_string* string_set, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset); + char** bone_names, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset); static void obj_classic_read_skin_block_node(obj_skin_block_node* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_node(obj_skin_block_node* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets); static void obj_classic_read_skin_block_osage(obj_skin_block_osage* b, - stream* s, string* str); + stream* s, char** str); static void obj_classic_write_skin_block_osage(obj_skin_block_osage* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, - vector_string* string_set, ssize_t* nodes_offset); -static void obj_classic_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, + stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* nodes_offset); +static void obj_classic_read_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, ssize_t base_offset, int32_t vertex_count, obj_vertex_attrib_type attrib_type); -static void obj_classic_write_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, +static void obj_classic_write_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, ssize_t base_offset, int32_t* vertex_count, obj_vertex_attrib_type* attrib_type, int32_t* vertex_size); static void obj_modern_read_inner(obj_set* os, stream* s); static void obj_modern_write_inner(obj_set* os, stream* s); -static void obj_modern_read_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t indices_count); -static void obj_modern_write_index(obj* o, stream* s, bool is_x, - obj_sub_mesh* sub_mesh, int32_t* indices_count, f2_struct* ovtx); -static void obj_modern_read_model(obj* o, stream* s, ssize_t base_offset, +static void obj_modern_read_index(obj* obj, stream* s, + obj_sub_mesh* sub_mesh); +static void obj_modern_write_index(obj* obj, stream* s, bool is_x, + obj_sub_mesh* sub_mesh, f2_struct* ovtx); +static void obj_modern_read_model(obj* obj, stream* s, ssize_t base_offset, uint32_t header_length, bool is_x, stream* s_oidx, stream* s_ovtx); -static void obj_modern_write_model(obj* o, stream* s, +static void obj_modern_write_model(obj* obj, stream* s, ssize_t base_offset, bool is_x, f2_struct* omdl); -static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, +static void obj_modern_read_skin(obj* obj, stream* s, ssize_t base_offset, uint32_t header_length, bool is_x); -static void obj_modern_write_skin(obj* o, stream* s, +static void obj_modern_write_skin(obj* obj, stream* s, ssize_t base_offset, bool is_x, f2_struct* oskn); static void obj_modern_read_skin_block_cloth(obj_skin_block_cloth* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, ssize_t* field_18_offset, ssize_t* field_1C_offset, ssize_t* field_20_offset, ssize_t* field_24_offset, ssize_t* field_28_offset); static void obj_modern_read_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); static void obj_modern_read_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); static void obj_modern_read_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, ssize_t* offsets); + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, + bool is_x, ssize_t* offsets); static void obj_modern_read_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); static void obj_modern_read_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); static void obj_modern_read_skin_block_expression(obj_skin_block_expression* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_expression(obj_skin_block_expression* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, bool is_x); static void obj_modern_read_skin_block_motion(obj_skin_block_motion* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_motion(obj_skin_block_motion* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, - vector_string* string_set, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset); + char** bone_names, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset); static void obj_modern_read_skin_block_node(obj_skin_block_node* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_node(obj_skin_block_node* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); static void obj_modern_read_skin_block_osage(obj_skin_block_osage* b, - stream* s, uint32_t header_length, string* str, bool is_x); + stream* s, uint32_t header_length, char** str, bool is_x); static void obj_modern_write_skin_block_osage(obj_skin_block_osage* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, - vector_string* string_set); -static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, + stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x); +static void obj_modern_read_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, const uint32_t attrib_flags, int32_t vertex_count, int32_t vertex_size); -static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, +static void obj_modern_write_vertex(obj* obj, stream* s, bool is_x, ssize_t* attrib_offsets, obj_mesh* mesh, uint32_t* attrib_flags, int32_t* vertex_count, int32_t* vertex_size, f2_struct* ovtx); +static void obj_skin_block_node_free(obj_skin_block_node* b); static uint32_t obj_skin_strings_get_string_index(vector_string* vec, char* str); static ssize_t obj_skin_strings_get_string_offset(vector_string* vec, vector_ssize_t* vec_off, char* str); +static ssize_t obj_skin_strings_get_string_offset_by_index(vector_string* vec, + vector_ssize_t* vec_off, char** strings, uint32_t index); static void obj_skin_strings_push_back_check(vector_string* vec, char* str); +static void obj_skin_strings_push_back_check_by_index(vector_string* vec, char** strings, uint32_t index); void obj_init(obj_set* os) { if (!os) @@ -282,15 +264,15 @@ void obj_read(obj_set* os, char* path, bool modern) { free(path_bin); } else { - char* path_obj = str_utils_add(path, ".osd"); - if (path_check_file_exists(path_obj)) { + char* path_osd = str_utils_add(path, ".osd"); + if (path_check_file_exists(path_osd)) { stream s; - io_open(&s, path_obj, "rb"); + io_open(&s, path_osd, "rb"); if (s.io.stream) obj_modern_read_inner(os, &s); io_free(&s); } - free(path_obj); + free(path_osd); } } @@ -310,20 +292,20 @@ void obj_wread(obj_set* os, wchar_t* path, bool modern) { free(path_bin); } else { - wchar_t* path_obj = str_utils_wadd(path, L".osd"); - if (path_wcheck_file_exists(path_obj)) { + wchar_t* path_osd = str_utils_wadd(path, L".osd"); + if (path_wcheck_file_exists(path_osd)) { stream s; - io_wopen(&s, path_obj, L"rb"); + io_wopen(&s, path_osd, L"rb"); if (s.io.stream) obj_modern_read_inner(os, &s); io_free(&s); } - free(path_obj); + free(path_osd); } } void obj_mread(obj_set* os, void* data, size_t length, bool modern) { - if (!os || !data) + if (!os || !data || !length) return; stream s; @@ -349,13 +331,13 @@ void obj_write(obj_set* os, char* path) { free(path_bin); } else { - char* path_obj = str_utils_add(path, ".osd"); + char* path_osd = str_utils_add(path, ".osd"); stream s; - io_open(&s, path_obj, "wb"); + io_open(&s, path_osd, "wb"); if (s.io.stream) obj_modern_write_inner(os, &s); io_free(&s); - free(path_obj); + free(path_osd); } } @@ -373,18 +355,18 @@ void obj_wwrite(obj_set* os, wchar_t* path) { free(path_bin); } else { - wchar_t* path_obj = str_utils_wadd(path, L".osd"); + wchar_t* path_osd = str_utils_wadd(path, L".osd"); stream s; - io_wopen(&s, path_obj, L"wb"); + io_wopen(&s, path_osd, L"wb"); if (s.io.stream) obj_modern_write_inner(os, &s); io_free(&s); - free(path_obj); + free(path_osd); } } void obj_mwrite(obj_set* os, void** data, size_t* length) { - if (!os || !data) + if (!os || !data || !os->ready) return; stream s; @@ -393,7 +375,6 @@ void obj_mwrite(obj_set* os, void** data, size_t* length) { obj_classic_write_inner(os, &s); else obj_modern_write_inner(os, &s); - io_align_write(&s, 0x10); io_mcopy(&s, data, length); io_free(&s); @@ -403,83 +384,102 @@ void obj_free(obj_set* os) { if (!os) return; - for (obj* i = os->vec.begin; i != os->vec.end; i++) { - for (obj_skin_bone* j = i->skin.bones.begin; j != i->skin.bones.end; j++) - string_free(&j->name); - vector_obj_skin_bone_free(&i->skin.bones); + bool is_x = os->is_x; + for (int32_t i = 0; i < os->objects_count; i++) { + obj* obj = &os->objects[i]; + for (int32_t j = 0; j < obj->skin.bones_count; j++) + string_free(&obj->skin.bones[j].name); + free(obj->skin.bones); + obj->skin.bones_count = 0; - for (obj_skin_block* j = i->skin.ex_data.blocks.begin; - j != i->skin.ex_data.blocks.end; j++) - switch (j->type) { + for (int32_t j = 0; j < obj->skin.ex_data.blocks_count; j++) { + obj_skin_block* block = &obj->skin.ex_data.blocks[j]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: { - obj_skin_block_cloth* cloth = &j->cloth; + obj_skin_block_cloth* cloth = &block->cloth; string_free(&cloth->mesh_name); string_free(&cloth->backface_mesh_name); - for (obj_skin_block_cloth_field_1C* k = cloth->field_1C.begin; - k != cloth->field_1C.end; k++) { - string_free(&k->sub_data_0.bone_name); - string_free(&k->sub_data_1.bone_name); - string_free(&k->sub_data_2.bone_name); - string_free(&k->sub_data_3.bone_name); + for (uint32_t k = 0; k < cloth->count; k++) { + obj_skin_block_cloth_field_1C* sub = &cloth->field_1C[k]; + string_free(&sub->sub_data_0.bone_name); + string_free(&sub->sub_data_1.bone_name); + string_free(&sub->sub_data_2.bone_name); + string_free(&sub->sub_data_3.bone_name); } - vector_obj_skin_block_cloth_field_1C_free(&cloth->field_1C); - vector_obj_skin_block_cloth_field_20_free(&cloth->field_20); - vector_uint16_t_free(&cloth->field_24); - vector_uint16_t_free(&cloth->field_28); + free(cloth->field_1C); + free(cloth->field_20); + free(cloth->field_24); + free(cloth->field_28); + cloth->count = 0; } break; case OBJ_SKIN_BLOCK_CONSTRAINT: { - obj_skin_block_constraint* constraint = &j->constraint; - string_free(&constraint->base.parent_name); - string_free(&constraint->base.name); + obj_skin_block_constraint* constraint = &block->constraint; + obj_skin_block_node_free(&constraint->base); string_free(&constraint->source_node_name); } break; case OBJ_SKIN_BLOCK_EXPRESSION: { - obj_skin_block_expression* expression = &j->expression; + obj_skin_block_expression* expression = &block->expression; + obj_skin_block_node_free(&expression->base); for (int32_t k = 0; k < 9; k++) string_free(&expression->expressions[k]); + expression->expressions_count = 0; } break; case OBJ_SKIN_BLOCK_MOTION: { - obj_skin_block_motion* motion = &j->motion; - for (obj_skin_motion_node* k = motion->nodes.begin; k != motion->nodes.end; k++) - string_free(&k->name); - vector_obj_skin_motion_node_free(&motion->nodes); + obj_skin_block_motion* motion = &block->motion; + obj_skin_block_node_free(&motion->base); + if (is_x) + string_free(&motion->name); + free(motion->nodes); + motion->nodes_count = 0; } break; case OBJ_SKIN_BLOCK_OSAGE: { - obj_skin_block_osage* osage = &j->osage; - string_free(&osage->base.parent_name); - string_free(&osage->base.name); - string_free(&osage->external_name); - for (obj_skin_osage_node* k = osage->nodes.begin; k != osage->nodes.end; k++) { - string_free(&k->name); - string_free(&k->sibling_name); - } - vector_obj_skin_osage_node_free(&osage->nodes); + obj_skin_block_osage* osage = &block->osage; + obj_skin_block_node_free(&osage->base); + free(osage->nodes); + osage->nodes_count = 0; } break; } - vector_obj_skin_block_free(&i->skin.ex_data.blocks); - - for (obj_skin_osage_node* j = i->skin.ex_data.osage_nodes.begin; - j != i->skin.ex_data.osage_nodes.end; j++) { - string_free(&j->name); - string_free(&j->sibling_name); } - vector_obj_skin_osage_node_free(&i->skin.ex_data.osage_nodes); + free(obj->skin.ex_data.blocks); + obj->skin.ex_data.blocks_count = 0; - for (obj_mesh* j = i->meshes.begin; j != i->meshes.end; j++) { - for (obj_sub_mesh* k = j->sub_meshes.begin; k != j->sub_meshes.end; k++) { - free(k->bone_index); - free(k->indices); + free(obj->skin.ex_data.osage_nodes); + obj->skin.ex_data.osage_nodes_count = 0; + + free(obj->skin.ex_data.bone_names_buf); + free(obj->skin.ex_data.bone_names); + obj->skin.ex_data.bone_names_count = 0; + + free(obj->skin.ex_data.osage_sibling_infos); + obj->skin.ex_data.osage_sibling_infos_count = 0; + + if (obj->meshes) + for (int32_t j = 0; j < obj->meshes_count; j++) { + obj_mesh* mesh = &obj->meshes[j]; + if (mesh->sub_meshes) + for (int32_t k = 0; k < mesh->sub_meshes_count; k++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[k]; + free(sub_mesh->bone_indices); + sub_mesh->bone_indices_count = 0; + free(sub_mesh->indices); + sub_mesh->indices_count = 0; + } + free(mesh->vertex); + mesh->vertex_count = 0; + free(mesh->sub_meshes); + mesh->sub_meshes_count = 0; } - free(j->vertex); - vector_obj_sub_mesh_free(&j->sub_meshes); - } - vector_obj_mesh_free(&i->meshes); - vector_obj_material_parent_free(&i->materials); - string_free(&i->name); + free(obj->meshes); + obj->meshes_count = 0; + free(obj->materials); + obj->materials_count = 0; + string_free(&obj->name); } - vector_obj_free(&os->vec); - vector_uint32_t_free(&os->tex_ids); + free(os->objects); + os->objects_count = 0; + free(os->texture_ids); + os->texture_ids_count = 0; } static void obj_material_texture_enrs_table_init() { @@ -496,6 +496,7 @@ static void obj_material_texture_enrs_table_init() { static void obj_material_texture_enrs_table_free(void) { enrs_free(&obj_material_texture_enrs_table); + obj_material_texture_enrs_table_initialized = false; } static void obj_classic_read_inner(obj_set* os, stream* s) { @@ -509,18 +510,17 @@ static void obj_classic_read_inner(obj_set* os, stream* s) { obj_set_header osh; memset(&osh, 0, sizeof(obj_set_header)); - osh.objects_count = io_read_int32_t(s); + os->objects_count = io_read_int32_t(s); osh.max_object_id = io_read_int32_t(s); osh.objects_offset = io_read_int32_t(s); osh.object_skins_offset = io_read_int32_t(s); osh.object_names_offset = io_read_int32_t(s); osh.object_ids_offset = io_read_int32_t(s); osh.texture_ids_offset = io_read_int32_t(s); - osh.texture_ids_count = io_read_int32_t(s); + os->texture_ids_count = io_read_int32_t(s); - int32_t count = osh.objects_count; - os->vec = vector_empty(obj); - vector_obj_reserve(&os->vec, osh.objects_count); + int32_t count = os->objects_count; + os->objects = force_malloc_s(obj, os->objects_count); int32_t* objects_offsets = 0; if (osh.objects_offset) { @@ -548,35 +548,27 @@ static void obj_classic_read_inner(obj_set* os, stream* s) { if (osh.objects_offset) { for (int32_t i = 0; i < count; i++) { - obj o; - memset(&o, 0, sizeof(obj)); - + obj* obj = &os->objects[i]; if (objects_offsets[i]) - obj_classic_read_model(&o, s, objects_offsets[i]); + obj_classic_read_model(obj, s, objects_offsets[i]); if (osh.object_skins_offset && object_skins_offsets[i]) - obj_classic_read_skin(&o, s, object_skins_offsets[i]); + obj_classic_read_skin(obj, s, object_skins_offsets[i]); if (osh.object_names_offset && object_names_offsets[i]) - io_read_string_null_terminated_offset(s, object_names_offsets[i], &o.name); - - vector_obj_push_back(&os->vec, &o); + io_read_string_null_terminated_offset(s, object_names_offsets[i], &obj->name); } io_set_position(s, osh.object_ids_offset, SEEK_SET); for (int32_t i = 0; i < count; i++) - os->vec.begin[i].id = io_read_uint32_t(s); + os->objects[i].id = io_read_uint32_t(s); } if (osh.texture_ids_offset) { + os->texture_ids = force_malloc_s(uint32_t, os->texture_ids_count); io_set_position(s, osh.texture_ids_offset, SEEK_SET); - int32_t count = osh.texture_ids_count; - os->tex_ids = vector_empty(uint32_t); - vector_uint32_t_reserve(&os->tex_ids, count); - for (int32_t i = 0; i < count; i++) { - uint32_t tex_id = io_read_uint32_t(s); - vector_uint32_t_push_back(&os->tex_ids, &tex_id); - } + for (int32_t i = 0; i < os->texture_ids_count; i++) + os->texture_ids[i] = io_read_uint32_t(s); } free(objects_offsets); @@ -590,7 +582,6 @@ static void obj_classic_read_inner(obj_set* os, stream* s) { static void obj_classic_write_inner(obj_set* os, stream* s) { - io_set_position(s, 0x00, SEEK_SET); io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -608,11 +599,9 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { obj_set_header osh; memset(&osh, 0, sizeof(obj_set_header)); - osh.objects_count = (int32_t)(os->vec.end - os->vec.begin); osh.max_object_id = -1; - osh.texture_ids_count = (int32_t)(os->tex_ids.end - os->tex_ids.begin); - int32_t count = osh.objects_count; + int32_t count = os->objects_count; osh.objects_offset = io_get_position(s); for (int32_t i = 0; i < count; i++) @@ -622,7 +611,7 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { int32_t* objects_offsets = force_malloc_s(int32_t, count); for (int32_t i = 0; i < count; i++) { objects_offsets[i] = (int32_t)io_get_position(s); - obj_classic_write_model(&os->vec.begin[i], s, objects_offsets[i]); + obj_classic_write_model(&os->objects[i], s, objects_offsets[i]); } io_align_write(s, 0x10); @@ -634,7 +623,7 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { osh.object_ids_offset = io_get_position(s); for (int32_t i = 0; i < count; i++) { - int32_t object_id = os->vec.begin[i].id; + int32_t object_id = os->objects[i].id; io_write_uint32_t(s, object_id); if (osh.max_object_id < object_id) osh.max_object_id = object_id; @@ -644,7 +633,7 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { int32_t* object_names_offsets = force_malloc_s(int32_t, count); for (int32_t i = 0; i < count; i++) { object_names_offsets[i] = (int32_t)io_get_position(s); - io_write_string_null_terminated(s, &os->vec.begin[i].name); + io_write_string_null_terminated(s, &os->objects[i].name); } io_align_write(s, 0x10); @@ -655,8 +644,8 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { free(object_names_offsets); osh.texture_ids_offset = io_get_position(s); - for (int32_t i = 0; i < osh.texture_ids_count; i++) - io_write_uint32_t(s, os->tex_ids.begin[i]); + for (int32_t i = 0; i < os->texture_ids_count; i++) + io_write_uint32_t(s, os->texture_ids[i]); io_align_write(s, 0x10); osh.object_skins_offset = io_get_position(s); @@ -666,13 +655,13 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { int32_t* object_skins_offsets = force_malloc_s(int32_t, count); for (int32_t i = 0; i < count; i++) { - if (!os->vec.begin[i].skin_init) { + if (!os->objects[i].skin_init) { object_skins_offsets[i] = 0; continue; } object_skins_offsets[i] = (int32_t)io_get_position(s); - obj_classic_write_skin(&os->vec.begin[i], s, object_skins_offsets[i]); + obj_classic_write_skin(&os->objects[i], s, object_skins_offsets[i]); } io_align_write(s, 0x10); @@ -684,46 +673,45 @@ static void obj_classic_write_inner(obj_set* os, stream* s) { io_position_push(s, 0x00, SEEK_SET); io_write_uint32_t(s, 0x5062500); - io_write_int32_t(s, osh.objects_count); + io_write_int32_t(s, os->objects_count); io_write_uint32_t(s, osh.max_object_id); io_write_int32_t(s, (int32_t)osh.objects_offset); io_write_int32_t(s, (int32_t)osh.object_skins_offset); io_write_int32_t(s, (int32_t)osh.object_names_offset); io_write_int32_t(s, (int32_t)osh.object_ids_offset); io_write_int32_t(s, (int32_t)osh.texture_ids_offset); - io_write_int32_t(s, osh.texture_ids_count); + io_write_int32_t(s, os->texture_ids_count); io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_position_pop(s); } -static void obj_classic_read_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t indices_count) { - uint32_t* indices = force_malloc_s(uint32_t, indices_count); +static void obj_classic_read_index(obj* obj, stream* s, + obj_sub_mesh* sub_mesh) { + bool tri_strip = sub_mesh->primitive_type == OBJ_PRIMITIVE_TRIANGLE_STRIP; + uint32_t* indices = force_malloc_s(uint32_t, sub_mesh->indices_count); switch (sub_mesh->index_format) { case OBJ_INDEX_U8: - for (int32_t i = 0; i < indices_count; i++) { + for (int32_t i = 0; i < sub_mesh->indices_count; i++) { uint8_t idx = io_read_uint8_t(s); - indices[i] = idx == 0xFF ? 0xFFFFFFFF : idx; + indices[i] = tri_strip && idx == 0xFF ? 0xFFFFFFFF : idx; } break; case OBJ_INDEX_U16: - for (int32_t i = 0; i < indices_count; i++) { + for (int32_t i = 0; i < sub_mesh->indices_count; i++) { uint16_t idx = io_read_uint16_t(s); - indices[i] = idx == 0xFFFF ? 0xFFFFFFFF : idx; + indices[i] = tri_strip && idx == 0xFFFF ? 0xFFFFFFFF : idx; } break; case OBJ_INDEX_U32: - for (int32_t i = 0; i < indices_count; i++) + for (int32_t i = 0; i < sub_mesh->indices_count; i++) indices[i] = io_read_uint32_t(s); break; } sub_mesh->indices = indices; - sub_mesh->indices_count = indices_count; } -static void obj_classic_write_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t* indices_count) { +static void obj_classic_write_index(obj* obj, stream* s, obj_sub_mesh* sub_mesh) { uint32_t* indices = sub_mesh->indices; int32_t _indices_count = sub_mesh->indices_count; switch (sub_mesh->index_format) { @@ -741,10 +729,9 @@ static void obj_classic_write_index(obj* o, stream* s, break; } io_align_write(s, 0x04); - *indices_count = _indices_count; } -static void obj_classic_read_model(obj* o, stream* s, ssize_t base_offset) { +static void obj_classic_read_model(obj* obj, stream* s, ssize_t base_offset) { const size_t mesh_size = 0xD8; const size_t sub_mesh_size = 0x5C; @@ -753,33 +740,31 @@ static void obj_classic_read_model(obj* o, stream* s, ssize_t base_offset) { obj_header oh; memset(&oh, 0, sizeof(obj_header)); io_read(s, 0, 0x08); - o->bounding_sphere.center.x = io_read_float_t(s); - o->bounding_sphere.center.y = io_read_float_t(s); - o->bounding_sphere.center.z = io_read_float_t(s); - o->bounding_sphere.radius = io_read_float_t(s); - oh.meshes_count = io_read_int32_t(s); + obj->bounding_sphere.center.x = io_read_float_t(s); + obj->bounding_sphere.center.y = io_read_float_t(s); + obj->bounding_sphere.center.z = io_read_float_t(s); + obj->bounding_sphere.radius = io_read_float_t(s); + obj->meshes_count = io_read_int32_t(s); oh.meshes_offset = io_read_int32_t(s); - oh.materials_count = io_read_int32_t(s); + obj->materials_count = io_read_int32_t(s); oh.materials_offset = io_read_int32_t(s); io_read(s, 0, 0x28); if (oh.meshes_offset > 0) { - o->meshes = vector_empty(obj_mesh); - vector_obj_mesh_reserve(&o->meshes, oh.meshes_count); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh mesh; - memset(&mesh, 0, sizeof(obj_mesh)); + obj->meshes = force_malloc_s(obj_mesh, obj->meshes_count); + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; io_set_position(s, base_offset + oh.meshes_offset + mesh_size * i, SEEK_SET); obj_mesh_header mh; memset(&mh, 0, sizeof(obj_mesh_header)); io_read(s, 0, 0x04); - mesh.bounding_sphere.center.x = io_read_float_t(s); - mesh.bounding_sphere.center.y = io_read_float_t(s); - mesh.bounding_sphere.center.z = io_read_float_t(s); - mesh.bounding_sphere.radius = io_read_float_t(s); - mh.sub_meshes_count = io_read_int32_t(s); + mesh->bounding_sphere.center.x = io_read_float_t(s); + mesh->bounding_sphere.center.y = io_read_float_t(s); + mesh->bounding_sphere.center.z = io_read_float_t(s); + mesh->bounding_sphere.radius = io_read_float_t(s); + mesh->sub_meshes_count = io_read_int32_t(s); mh.sub_meshes_offset = io_read_int32_t(s); mh.attrib_type = io_read_uint32_t(s); mh.vertex_size = io_read_int32_t(s); @@ -788,81 +773,67 @@ static void obj_classic_read_model(obj* o, stream* s, ssize_t base_offset) { for (int32_t j = 0; j < 20; j++) mh.attrib_offsets[j] = io_read_int32_t(s); - mesh.flags = io_read_int32_t(s); + mesh->flags = io_read_int32_t(s); mh.attrib_flags = io_read_uint32_t(s); io_read(s, 0, 0x18); - io_read(s, &mesh.name, sizeof(mesh.name)); - mesh.name[sizeof(mesh.name) - 1] = 0; + io_read(s, &mesh->name, sizeof(mesh->name)); + mesh->name[sizeof(mesh->name) - 1] = 0; if (mh.sub_meshes_offset) { - mesh.sub_meshes = vector_empty(obj_sub_mesh); - vector_obj_sub_mesh_reserve(&mesh.sub_meshes, mh.sub_meshes_count); - for (int32_t j = 0; j < mh.sub_meshes_count; j++) { - obj_sub_mesh sub_mesh; - memset(&sub_mesh, 0, sizeof(obj_sub_mesh)); + mesh->sub_meshes = force_malloc_s(obj_sub_mesh, mesh->sub_meshes_count); + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; io_set_position(s, base_offset + mh.sub_meshes_offset + sub_mesh_size * j, SEEK_SET); obj_sub_mesh_header smh; memset(&smh, 0, sizeof(obj_sub_mesh_header)); io_read(s, 0, 0x04); - sub_mesh.bounding_sphere.center.x = io_read_float_t(s); - sub_mesh.bounding_sphere.center.y = io_read_float_t(s); - sub_mesh.bounding_sphere.center.z = io_read_float_t(s); - sub_mesh.bounding_sphere.radius = io_read_float_t(s); - sub_mesh.material_index = io_read_uint32_t(s); - io_read(s, &sub_mesh.texcoord_indices, 0x08); - smh.bone_index_count = io_read_int32_t(s); + sub_mesh->bounding_sphere.center.x = io_read_float_t(s); + sub_mesh->bounding_sphere.center.y = io_read_float_t(s); + sub_mesh->bounding_sphere.center.z = io_read_float_t(s); + sub_mesh->bounding_sphere.radius = io_read_float_t(s); + sub_mesh->material_index = io_read_uint32_t(s); + io_read(s, &sub_mesh->texcoord_indices, 0x08); + sub_mesh->bone_indices_count = io_read_int32_t(s); smh.bone_indices_offset = io_read_int32_t(s); - sub_mesh.bones_per_vertex = io_read_uint32_t(s); - sub_mesh.primitive_type = io_read_uint32_t(s); - sub_mesh.index_format = io_read_uint32_t(s); - smh.indices_count = io_read_int32_t(s); + sub_mesh->bones_per_vertex = io_read_uint32_t(s); + sub_mesh->primitive_type = io_read_uint32_t(s); + sub_mesh->index_format = io_read_uint32_t(s); + sub_mesh->indices_count = io_read_int32_t(s); smh.indices_offset = io_read_int32_t(s); - sub_mesh.flags = io_read_uint32_t(s); - sub_mesh.bounding_box.center = sub_mesh.bounding_sphere.center; - sub_mesh.bounding_box.size.x = sub_mesh.bounding_sphere.radius * 2.0f; - sub_mesh.bounding_box.size.y = sub_mesh.bounding_sphere.radius * 2.0f; - sub_mesh.bounding_box.size.z = sub_mesh.bounding_sphere.radius * 2.0f; + sub_mesh->flags = io_read_uint32_t(s); + sub_mesh->bounding_box.center = sub_mesh->bounding_sphere.center; + sub_mesh->bounding_box.size.x = sub_mesh->bounding_sphere.radius * 2.0f; + sub_mesh->bounding_box.size.y = sub_mesh->bounding_sphere.radius * 2.0f; + sub_mesh->bounding_box.size.z = sub_mesh->bounding_sphere.radius * 2.0f; io_read(s, 0, 0x18); - sub_mesh.index_offset = io_read_uint32_t(s); + sub_mesh->indices_offset = io_read_uint32_t(s); - if (sub_mesh.bones_per_vertex == 4 && smh.bone_indices_offset) { - uint16_t* bone_index = force_malloc_s(uint16_t, smh.bone_index_count); + if (sub_mesh->bones_per_vertex == 4 && smh.bone_indices_offset) { + sub_mesh->bone_indices = force_malloc_s(uint16_t, sub_mesh->bone_indices_count); io_set_position(s, base_offset + smh.bone_indices_offset, SEEK_SET); - for (int32_t k = 0; k < smh.bone_index_count; k++) - bone_index[k] = io_read_uint16_t(s); - sub_mesh.bone_index = bone_index; - sub_mesh.bone_index_count = smh.bone_index_count; + io_read(s, sub_mesh->bone_indices, sub_mesh->bone_indices_count * sizeof(uint16_t)); } io_set_position(s, base_offset + smh.indices_offset, SEEK_SET); - obj_classic_read_index(o, s, &sub_mesh, smh.indices_count); - - vector_obj_sub_mesh_push_back(&mesh.sub_meshes, &sub_mesh); + obj_classic_read_index(obj, s, sub_mesh); } } - obj_classic_read_vertex(o, s, mh.attrib_offsets, &mesh, + obj_classic_read_vertex(obj, s, mh.attrib_offsets, mesh, base_offset, mh.vertex_count, mh.attrib_type); - - vector_obj_mesh_push_back(&o->meshes, &mesh); } } if (oh.materials_offset > 0) { io_set_position(s, base_offset + oh.materials_offset, SEEK_SET); - o->materials = vector_empty(obj_material_parent); - vector_obj_material_parent_reserve(&o->materials, oh.materials_count); - for (int32_t i = 0; i < oh.materials_count; i++) { - obj_material_parent m; - io_read(s, &m, sizeof(obj_material_parent)); - vector_obj_material_parent_push_back(&o->materials, &m); - } + obj->materials = force_malloc_s(obj_material_data, obj->materials_count); + io_read(s, obj->materials, obj->materials_count * sizeof(obj_material_data)); } } -static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { +static void obj_classic_write_model(obj* obj, stream* s, ssize_t base_offset) { const size_t mesh_size = 0xD8; const size_t sub_mesh_size = 0x5C; @@ -881,13 +852,12 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { obj_header oh; memset(&oh, 0, sizeof(obj_header)); - oh.meshes_count = (int32_t)(o->meshes.end - o->meshes.begin); - if (oh.meshes_count) { + if (obj->meshes_count) { oh.meshes_offset = io_get_position(s) - base_offset; - obj_mesh_header* mhs = force_malloc_s(obj_mesh_header, oh.meshes_count); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + obj_mesh_header* mhs = force_malloc_s(obj_mesh_header, obj->meshes_count); + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; io_write(s, 0, 0x04); io_write_float_t(s, 0.0f); @@ -909,15 +879,13 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { io_write(s, 0, sizeof(mesh->name)); } - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; - mh->sub_meshes_count = (int32_t)(mesh->sub_meshes.end - mesh->sub_meshes.begin); - if (mh->sub_meshes_count) { - + if (mesh->sub_meshes_count) { mh->sub_meshes_offset = io_get_position(s) - base_offset; - for (int32_t j = 0; j < mh->sub_meshes_count; j++) { + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { io_write(s, 0, 0x04); io_write_float_t(s, 0.0f); io_write_float_t(s, 0.0f); @@ -938,26 +906,22 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { } } - obj_classic_write_vertex(o, s, mh->attrib_offsets, + obj_classic_write_vertex(obj, s, mh->attrib_offsets, mesh, base_offset, &mh->vertex_count, &mh->attrib_type, &mh->vertex_size); - for (int32_t j = 0; j < mh->sub_meshes_count; j++) { - obj_sub_mesh* sub_mesh = &mesh->sub_meshes.begin[j]; + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; obj_sub_mesh_header smh; memset(&smh, 0, sizeof(obj_sub_mesh_header)); - if (sub_mesh->bones_per_vertex == 4 && sub_mesh->bone_index_count) { + if (sub_mesh->bones_per_vertex == 4 && sub_mesh->bone_indices_count) { smh.bone_indices_offset = io_get_position(s) - base_offset; - - smh.bone_index_count = sub_mesh->bone_index_count; - uint16_t* bone_index = sub_mesh->bone_index; - for (int32_t k = 0; k < smh.bone_index_count; k++) - io_write_uint16_t(s, bone_index[k]); + io_write(s, sub_mesh->bone_indices, sub_mesh->bone_indices_count * sizeof(uint16_t)); io_align_write(s, 0x04); } smh.indices_offset = io_get_position(s) - base_offset; - obj_classic_write_index(o, s, sub_mesh, &smh.indices_count); + obj_classic_write_index(obj, s, sub_mesh); io_position_push(s, base_offset + mh->sub_meshes_offset + sub_mesh_size * j, SEEK_SET); io_write(s, 0, 0x04); @@ -967,23 +931,23 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { io_write_float_t(s, sub_mesh->bounding_sphere.radius); io_write_uint32_t(s, sub_mesh->material_index); io_write(s, &sub_mesh->texcoord_indices, 0x08); - io_write_int32_t(s, smh.bone_index_count); + io_write_int32_t(s, sub_mesh->bone_indices_count); io_write_int32_t(s, (int32_t)smh.bone_indices_offset); io_write_uint32_t(s, sub_mesh->bones_per_vertex); io_write_uint32_t(s, sub_mesh->primitive_type); io_write_uint32_t(s, sub_mesh->index_format); - io_write_int32_t(s, smh.indices_count); + io_write_int32_t(s, sub_mesh->indices_count); io_write_int32_t(s, (int32_t)smh.indices_offset); io_write_uint32_t(s, sub_mesh->flags); io_write(s, 0, 0x18); - io_write_uint32_t(s, sub_mesh->index_offset); + io_write_uint32_t(s, sub_mesh->indices_offset); io_position_pop(s); } } io_position_push(s, base_offset + oh.meshes_offset, SEEK_SET); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; io_write(s, 0, 0x04); @@ -991,7 +955,7 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { io_write_float_t(s, mesh->bounding_sphere.center.y); io_write_float_t(s, mesh->bounding_sphere.center.z); io_write_float_t(s, mesh->bounding_sphere.radius); - io_write_int32_t(s, mh->sub_meshes_count); + io_write_int32_t(s, mesh->sub_meshes_count); io_write_int32_t(s, (int32_t)mh->sub_meshes_offset); io_write_uint32_t(s, mh->attrib_type); io_write_int32_t(s, mh->vertex_size); @@ -1010,31 +974,29 @@ static void obj_classic_write_model(obj* o, stream* s, ssize_t base_offset) { free(mhs); } - oh.materials_count = (int32_t)(o->materials.end - o->materials.begin); - if (oh.materials_count) { + if (obj->materials_count) { oh.materials_offset = io_get_position(s) - base_offset; - for (int32_t i = 0; i < oh.materials_count; i++) - io_write(s, &o->materials.begin[i], sizeof(obj_material_parent)); + io_write(s, obj->materials, obj->materials_count * sizeof(obj_material_data)); } io_align_write(s, 0x10); io_position_push(s, base_offset, SEEK_SET); io_write_uint32_t(s, 0x10000); io_write_uint32_t(s, 0x00); - io_write_float_t(s, o->bounding_sphere.center.x); - io_write_float_t(s, o->bounding_sphere.center.y); - io_write_float_t(s, o->bounding_sphere.center.z); - io_write_float_t(s, o->bounding_sphere.radius); - io_write_int32_t(s, oh.meshes_count); + io_write_float_t(s, obj->bounding_sphere.center.x); + io_write_float_t(s, obj->bounding_sphere.center.y); + io_write_float_t(s, obj->bounding_sphere.center.z); + io_write_float_t(s, obj->bounding_sphere.radius); + io_write_int32_t(s, obj->meshes_count); io_write_int32_t(s, (int32_t)oh.meshes_offset); - io_write_int32_t(s, oh.materials_count); + io_write_int32_t(s, obj->materials_count); io_write_int32_t(s, (int32_t)oh.materials_offset); io_position_pop(s); } -static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset) { - obj_skin* sk = &o->skin; - o->skin_init = true; +static void obj_classic_read_skin(obj* obj, stream* s, ssize_t base_offset) { + obj_skin* sk = &obj->skin; + obj->skin_init = true; io_set_position(s, base_offset, SEEK_SET); obj_skin_header sh; @@ -1043,36 +1005,30 @@ static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset) { sh.bone_matrices_offset = io_read_int32_t(s); sh.bone_names_offset = io_read_int32_t(s); sh.ex_data_offset = io_read_int32_t(s); - sh.bone_count = io_read_int32_t(s); + sk->bones_count = io_read_int32_t(s); sh.bone_parent_ids_offset = io_read_int32_t(s); io_read(s, 0, 0x0C); if (sh.bone_ids_offset) { - sk->bones = vector_empty(obj_skin_bone); - vector_obj_skin_bone_reserve(&sk->bones, sh.bone_count); + sk->bones = force_malloc_s(obj_skin_bone, sk->bones_count); int32_t* bone_names_offsets = 0; if (sh.bone_names_offset) { - bone_names_offsets = force_malloc_s(int32_t, sh.bone_count); + bone_names_offsets = force_malloc_s(int32_t, sk->bones_count); io_set_position(s, sh.bone_names_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) + for (int32_t i = 0; i < sk->bones_count; i++) bone_names_offsets[i] = io_read_int32_t(s); } if (sh.bone_ids_offset) { - obj_skin_bone bone; - memset(&bone, 0, sizeof(obj_skin_bone)); - io_set_position(s, sh.bone_ids_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) { - bone.id = io_read_uint32_t(s); - vector_obj_skin_bone_push_back(&sk->bones, &bone); - } + for (int32_t i = 0; i < sk->bones_count; i++) + sk->bones[i].id = io_read_uint32_t(s); if (sh.bone_matrices_offset) { io_set_position(s, sh.bone_matrices_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { mat4 mat; mat.row0.x = io_read_float_t(s); mat.row0.y = io_read_float_t(s); @@ -1090,19 +1046,20 @@ static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset) { mat.row3.y = io_read_float_t(s); mat.row3.z = io_read_float_t(s); mat.row3.w = io_read_float_t(s); - mat4_transpose(&mat, &sk->bones.begin[i].inv_bind_pose_mat); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &sk->bones[i].inv_bind_pose_mat); } } if (sh.bone_names_offset) - for (int32_t i = 0; i < sh.bone_count; i++) + for (int32_t i = 0; i < sk->bones_count; i++) io_read_string_null_terminated_offset(s, - bone_names_offsets[i], &sk->bones.begin[i].name); + bone_names_offsets[i], &sk->bones[i].name); if (sh.bone_parent_ids_offset) { io_set_position(s, sh.bone_parent_ids_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) - sk->bones.begin[i].parent = io_read_uint32_t(s); + for (int32_t i = 0; i < sk->bones_count; i++) + sk->bones[i].parent = io_read_uint32_t(s); } } free(bone_names_offsets); @@ -1116,64 +1073,86 @@ static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset) { obj_skin_ex_data_header exh; memset(&exh, 0, sizeof(obj_skin_ex_data_header)); exh.osage_count = io_read_int32_t(s); - exh.osage_nodes_count = io_read_int32_t(s); + ex->osage_nodes_count = io_read_int32_t(s); io_read(s, 0, 0x04); exh.osage_nodes_offset = io_read_int32_t(s); exh.osage_names_offset = io_read_int32_t(s); exh.blocks_offset = io_read_int32_t(s); - exh.strings_count = io_read_int32_t(s); - exh.strings_offset = io_read_int32_t(s); + exh.bone_names_count = io_read_int32_t(s); + exh.bone_names_offset = io_read_int32_t(s); exh.osage_sibling_infos_offset = io_read_int32_t(s); exh.cloth_count = io_read_int32_t(s); io_read(s, 0, 0x1C); - vector_string string_set = vector_empty(string); - vector_string_reserve(&string_set, exh.strings_count); - if (exh.strings_offset) { - int32_t* strings_offsets = force_malloc_s(int32_t, exh.strings_count); - io_set_position(s, exh.strings_offset, SEEK_SET); - for (int32_t i = 0; i < exh.strings_count; i++) + if (exh.bone_names_offset) { + vector_string bone_names = vector_empty(string); + vector_string_reserve(&bone_names, exh.bone_names_count); + int32_t* strings_offsets = force_malloc_s(int32_t, exh.bone_names_count); + io_set_position(s, exh.bone_names_offset, SEEK_SET); + for (int32_t i = 0; i < exh.bone_names_count; i++) strings_offsets[i] = io_read_int32_t(s); - for (int32_t i = 0; i < exh.strings_count; i++) { - string str; - io_read_string_null_terminated_offset(s, strings_offsets[i], &str); - vector_string_push_back(&string_set, &str); + size_t buf_size = 0; + for (int32_t i = 0; i < exh.bone_names_count; i++) { + string* str = vector_string_reserve_back(&bone_names); + if (strings_offsets[i]) + io_read_string_null_terminated_offset(s, strings_offsets[i], str); + else + *str = string_empty; + buf_size += str->length + 1; } free(strings_offsets); + + ex->bone_names_buf = force_malloc(buf_size); + ex->bone_names = force_malloc_s(char*, buf_size + 1); + ex->bone_names_count = exh.bone_names_count; + + char* bone_names_buf = ex->bone_names_buf; + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < exh.bone_names_count; i++) { + string* str = &bone_names.begin[i]; + *bone_names_ptr++ = bone_names_buf; + memcpy(bone_names_buf, string_data(str), str->length); + bone_names_buf[str->length] = 0; + bone_names_buf += str->length + 1; + } + *bone_names_ptr = 0; + vector_string_free(&bone_names, string_free); + } + else { + ex->bone_names_buf = 0; + ex->bone_names = 0; + ex->bone_names_count = 0; } - ex->osage_nodes = vector_empty(obj_skin_osage_node); - vector_obj_skin_osage_node_reserve(&ex->osage_nodes, exh.osage_nodes_count); + char** bone_names = ex->bone_names; + if (!bone_names) + return; + if (exh.osage_nodes_offset) { - obj_skin_osage_node osage_node; - memset(&osage_node, 0, sizeof(obj_skin_osage_node)); + ex->osage_nodes = force_malloc_s(obj_skin_osage_node, ex->osage_nodes_count); io_set_position(s, exh.osage_nodes_offset, SEEK_SET); - for (int32_t i = 0; i < exh.osage_nodes_count; i++) { - int32_t name = io_read_uint32_t(s); - if (name & 0x8000) - string_copy(&string_set.begin[name & 0x7FFF], &osage_node.name); - else - memset(&osage_node.name, 0, sizeof(string)); + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[i]; - osage_node.length = io_read_float_t(s); + osage_node->name_index = io_read_uint32_t(s); + osage_node->length = io_read_float_t(s); io_read(s, 0, 0x04); - vector_obj_skin_osage_node_push_back(&ex->osage_nodes, &osage_node); } } if (exh.blocks_offset) { - int32_t blocks_count = 0; + ex->blocks_count = 0; io_set_position(s, exh.blocks_offset, SEEK_SET); while (io_read_int32_t(s)) { io_read(s, 0, 0x04); - blocks_count++; + ex->blocks_count++; } - obj_skin_block_header* bhs = force_malloc_s(obj_skin_block_header, blocks_count); + obj_skin_block_header* bhs = force_malloc_s(obj_skin_block_header, ex->blocks_count); io_set_position(s, exh.blocks_offset, SEEK_SET); - for (int32_t i = 0; i < blocks_count; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { bhs[i].block_signature_offset = io_read_int32_t(s); bhs[i].block_offset = io_read_int32_t(s); } @@ -1181,121 +1160,101 @@ static void obj_classic_read_skin(obj* o, stream* s, ssize_t base_offset) { obj_skin_block block; memset(&block, 0, sizeof(obj_skin_block)); - ex->blocks = vector_empty(obj_skin_block); - vector_obj_skin_block_reserve(&ex->blocks, blocks_count); - for (int32_t i = 0; i < blocks_count; i++) { - bool valid = false; + ex->blocks = force_malloc_s(obj_skin_block, ex->blocks_count); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; char* block_signature = io_read_utf8_string_null_terminated_offset(s, bhs[i].block_signature_offset); - if (utf8_length(block_signature) == 3) { - valid = true; + if (!block_signature || utf8_length(block_signature) != 3) { + free(block_signature); + continue; + } - uint32_t signature = load_reverse_endianness_uint32_t(block_signature); - switch (signature) { - case 'CLS\0': - block.type = OBJ_SKIN_BLOCK_CLOTH; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_classic_read_skin_block_cloth(&block.cloth, - s, string_set.begin); - break; - case 'CNS\0': - block.type = OBJ_SKIN_BLOCK_CONSTRAINT; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_classic_read_skin_block_constraint(&block.constraint, - s, string_set.begin); - break; - case 'EXP\0': - block.type = OBJ_SKIN_BLOCK_EXPRESSION; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_classic_read_skin_block_expression(&block.expression, - s, string_set.begin); - break; - case 'MOT\0': - block.type = OBJ_SKIN_BLOCK_MOTION; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_classic_read_skin_block_motion(&block.motion, - s, string_set.begin); - break; - case 'OSG\0': - block.type = OBJ_SKIN_BLOCK_OSAGE; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_classic_read_skin_block_osage(&block.osage, - s, string_set.begin); - break; - default: - valid = false; - break; - } + uint32_t signature = load_reverse_endianness_uint32_t(block_signature); + switch (signature) { + case 'CLS\0': + block->type = OBJ_SKIN_BLOCK_CLOTH; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_classic_read_skin_block_cloth(&block->cloth, + s, bone_names); + break; + case 'CNS\0': + block->type = OBJ_SKIN_BLOCK_CONSTRAINT; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_classic_read_skin_block_constraint(&block->constraint, + s, bone_names); + break; + case 'EXP\0': + block->type = OBJ_SKIN_BLOCK_EXPRESSION; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_classic_read_skin_block_expression(&block->expression, + s, bone_names); + break; + case 'MOT\0': + block->type = OBJ_SKIN_BLOCK_MOTION; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_classic_read_skin_block_motion(&block->motion, + s, bone_names); + break; + case 'OSG\0': + block->type = OBJ_SKIN_BLOCK_OSAGE; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_classic_read_skin_block_osage(&block->osage, + s, bone_names); + break; } free(block_signature); - - if (valid) - vector_obj_skin_block_push_back(&ex->blocks, &block); } free(bhs); } - io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); - while (true) { - uint32_t bone_name_index = io_read_uint32_t(s); - if (!bone_name_index) - break; + if (exh.osage_sibling_infos_offset) { + ex->osage_sibling_infos_count = 0; + io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); + while (io_read_uint32_t(s)) { + io_read(s, 0, 0x08); + ex->osage_sibling_infos_count++; + } - uint32_t sibling_name = io_read_uint32_t(s); - float_t sibling_distance = io_read_float_t(s); + obj_skin_osage_sibling_info* osis = force_malloc_s( + obj_skin_osage_sibling_info, ex->osage_sibling_infos_count); + ex->osage_sibling_infos = osis; + io_set_position(s, exh.blocks_offset, SEEK_SET); + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { + osis[i].name_index = io_read_uint32_t(s); + osis[i].sibling_name_index = io_read_uint32_t(s); + osis[i].distance = io_read_float_t(s); + } - if (!(bone_name_index & 0x8000)) - continue; - - char* bone_name = string_data(&string_set.begin[bone_name_index & 0x7FFF]); - - obj_skin_osage_node* osage_node = 0; - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) - if (!strcmp(string_data(&i->name), bone_name)) { - string_free(&i->sibling_name); - if (sibling_name & 0x8000) - string_copy(&string_set.begin[sibling_name & 0x7FFF], &i->sibling_name); - else - memset(&i->sibling_name, 0, sizeof(string)); - - i->sibling_max_distance = sibling_distance; - break; - } + io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_OSAGE) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) continue; - obj_skin_block_osage* osage = &i->osage; - if (!(osage->nodes.end - osage->nodes.begin)) + obj_skin_block_osage* osage = &block->osage; + if (!osage->nodes) continue; int32_t count = osage->count; - obj_skin_osage_node* donor_osage_node = &ex->osage_nodes.begin[osage->start_index]; - obj_skin_osage_node* osage_node = osage->nodes.begin; + obj_skin_osage_node* child_osage_node = &ex->osage_nodes[osage->start_index]; + obj_skin_osage_node* osage_node = osage->nodes; for (int32_t j = 0; j < count; j++) { - string_free(&osage_node->name); - string_free(&osage_node->sibling_name); - string_copy(&donor_osage_node->name, &osage_node->name); - osage_node->length = donor_osage_node->length; - string_copy(&donor_osage_node->sibling_name, &osage_node->sibling_name); - osage_node->sibling_max_distance = donor_osage_node->sibling_max_distance; + osage_node->name_index = child_osage_node->name_index; + osage_node->length = child_osage_node->length; - donor_osage_node++; + child_osage_node++; osage_node++; } } - - for (string* i = string_set.begin; i != string_set.end; i++) - string_free(i); - vector_string_free(&string_set); } } -static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { - obj_skin* sk = &o->skin; +static void obj_classic_write_skin(obj* obj, stream* s, ssize_t base_offset) { + obj_skin* sk = &obj->skin; obj_skin_header sh; memset(&sh, 0, sizeof(obj_skin_header)); @@ -1310,30 +1269,30 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { vector_string strings = vector_empty(string); vector_ssize_t string_offsets = vector_empty(ssize_t); - vector_string string_set = vector_empty(string); - sh.bone_count = (int32_t)(sk->bones.end - sk->bones.begin); - if (sh.bone_count) { + vector_string bone_names = vector_empty(string); + if (sk->bones) { sh.bone_ids_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) - io_write_int32_t(s, sk->bones.begin[i].id); + for (int32_t i = 0; i < sk->bones_count; i++) + io_write_int32_t(s, sk->bones[i].id); io_align_write(s, 0x10); sh.bone_parent_ids_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) - io_write_int32_t(s, sk->bones.begin[i].parent); + for (int32_t i = 0; i < sk->bones_count; i++) + io_write_int32_t(s, sk->bones[i].parent); io_align_write(s, 0x10); sh.bone_names_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { io_write_int32_t(s, 0); - obj_skin_strings_push_back_check(&strings, string_data(&sk->bones.begin[i].name)); + obj_skin_strings_push_back_check(&strings, string_data(&sk->bones[i].name)); } io_align_write(s, 0x10); sh.bone_matrices_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { mat4 mat; - mat4_transpose(&sk->bones.begin[i].inv_bind_pose_mat, &mat); + mat4u_to_mat4(&sk->bones[i].inv_bind_pose_mat, &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -1363,7 +1322,6 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { ssize_t field_20 = 0; ssize_t field_24 = 0; ssize_t field_28 = 0; - ssize_t blocks_count = 0; obj_skin_ex_data_header exh; memset(&exh, 0, sizeof(obj_skin_ex_data_header)); @@ -1384,10 +1342,9 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_write(s, 0, 0x1C); io_align_write(s, 0x10); - exh.osage_nodes_count = (int32_t)(ex->osage_nodes.end - ex->osage_nodes.begin); - if (exh.osage_nodes_count) { + if (ex->osage_nodes_count) { exh.osage_nodes_offset = io_get_position(s); - for (int32_t i = 0; i < exh.osage_nodes_count; i++) { + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -1395,10 +1352,7 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_align_write(s, 0x10); exh.osage_sibling_infos_offset = io_get_position(s); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - if (!string_length(&i->sibling_name)) - continue; - + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -1411,11 +1365,13 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { exh.cloth_count = 0; exh.osage_count = 0; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type == OBJ_SKIN_BLOCK_CLOTH) exh.cloth_count++; - else if (i->type == OBJ_SKIN_BLOCK_OSAGE) + else if (block->type == OBJ_SKIN_BLOCK_OSAGE) exh.osage_count++; + } if (exh.osage_count || exh.cloth_count) { exh.osage_names_offset = io_get_position(s); @@ -1427,105 +1383,153 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_align_write(s, 0x10); } - blocks_count = ex->blocks.end - ex->blocks.begin; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: { - obj_skin_block_cloth* cls = &i->cloth; - obj_skin_strings_push_back_check(&strings, string_data(&cls->mesh_name)); - obj_skin_strings_push_back_check(&strings, string_data(&cls->backface_mesh_name)); - for (obj_skin_block_cloth_field_1C* j = cls->field_1C.begin; j != cls->field_1C.end; j++) { - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_0.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_1.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_2.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_3.bone_name)); + obj_skin_block_cloth* cloth = &block->cloth; + obj_skin_strings_push_back_check(&strings, string_data(&cloth->mesh_name)); + obj_skin_strings_push_back_check(&strings, string_data(&cloth->backface_mesh_name)); + for (uint32_t k = 0; k < cloth->count; k++) { + obj_skin_block_cloth_field_1C* sub = &cloth->field_1C[k]; + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_0.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_1.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_2.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_3.bone_name)); } obj_skin_strings_push_back_check(&strings, "CLS"); } break; case OBJ_SKIN_BLOCK_CONSTRAINT: { - obj_skin_block_constraint* cns = &i->constraint; - obj_skin_strings_push_back_check(&strings, string_data(&cns->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&cns->base.name)); - obj_skin_strings_push_back_check(&strings, string_data(&cns->source_node_name)); - switch (cns->type) { + obj_skin_block_constraint* constraint = &block->constraint; + obj_skin_strings_push_back_check(&strings, string_data(&constraint->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, constraint->name_index); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->source_node_name)); + switch (constraint->type) { case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: obj_skin_strings_push_back_check(&strings, "Direction"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->direction.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->direction.up_vector.name)); break; case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: obj_skin_strings_push_back_check(&strings, "Distance"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->distance.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->distance.up_vector.name)); break; case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: obj_skin_strings_push_back_check(&strings, "Orientation"); break; case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: obj_skin_strings_push_back_check(&strings, "Position"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->position.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->position.up_vector.name)); break; } obj_skin_strings_push_back_check(&strings, "CNS"); - obj_skin_strings_push_back_check(&string_set, string_data(&cns->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, constraint->name_index); } break; case OBJ_SKIN_BLOCK_EXPRESSION: { - obj_skin_block_expression* exp = &i->expression; - for (int32_t j = 0; j < exp->expression_count; j++) - obj_skin_strings_push_back_check(&strings, string_data(&exp->expressions[j])); - obj_skin_strings_push_back_check(&strings, string_data(&exp->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&exp->base.name)); + obj_skin_block_expression* expression = &block->expression; + for (int32_t j = 0; j < expression->expressions_count; j++) + obj_skin_strings_push_back_check(&strings, string_data(&expression->expressions[j])); + obj_skin_strings_push_back_check(&strings, string_data(&expression->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, expression->name_index); obj_skin_strings_push_back_check(&strings, "EXP"); - obj_skin_strings_push_back_check(&string_set, string_data(&exp->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, expression->name_index); } break; case OBJ_SKIN_BLOCK_MOTION: { - obj_skin_block_motion* mot = &i->motion; - obj_skin_strings_push_back_check(&strings, string_data(&mot->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&mot->base.name)); - for (obj_skin_motion_node* j = mot->nodes.begin; j != mot->nodes.end; j++) - obj_skin_strings_push_back_check(&strings, string_data(&j->name)); + obj_skin_block_motion* motion = &block->motion; + obj_skin_strings_push_back_check(&strings, string_data(&motion->base.parent_name)); + obj_skin_strings_push_back_check(&strings, string_data(&motion->name)); + for (int32_t j = 0; j < motion->nodes_count; j++) + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, motion->nodes[j].name_index); obj_skin_strings_push_back_check(&strings, "MOT"); - obj_skin_strings_push_back_check(&string_set, string_data(&mot->base.name)); - for (obj_skin_motion_node* j = mot->nodes.begin; j != mot->nodes.end; j++) - obj_skin_strings_push_back_check(&string_set, string_data(&j->name)); + obj_skin_strings_push_back_check(&bone_names, string_data(&motion->name)); + for (int32_t j = 0; j < motion->nodes_count; j++) + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, motion->nodes[j].name_index); } break; case OBJ_SKIN_BLOCK_OSAGE: { - obj_skin_block_osage* osg = &i->osage; - obj_skin_strings_push_back_check(&strings, string_data(&osg->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&osg->base.name)); - obj_skin_strings_push_back_check(&strings, string_data(&osg->external_name)); - for (obj_skin_osage_node* j = osg->nodes.begin; j != osg->nodes.end; j++) { - obj_skin_strings_push_back_check(&strings, string_data(&j->name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sibling_name)); + obj_skin_block_osage* osage = &block->osage; + obj_skin_strings_push_back_check(&strings, string_data(&osage->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage->name_index); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage->external_name_index); + for (int32_t j = 0; j < osage->count; j++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[j]; + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage_node->name_index); + + int32_t name_index = osage->name_index; + obj_skin_osage_sibling_info* osage_sibling_infos = ex->osage_sibling_infos; + for (int32_t k = 0; k < ex->osage_sibling_infos_count; k++) { + if (name_index == osage_sibling_infos->name_index) { + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage_sibling_infos->sibling_name_index); + break; + } + osage_sibling_infos++; + } } obj_skin_strings_push_back_check(&strings, "OSG"); - obj_skin_strings_push_back_check(&string_set, string_data(&osg->external_name)); - for (obj_skin_osage_node* j = osg->nodes.begin; j != osg->nodes.end; j++) { - obj_skin_strings_push_back_check(&string_set, string_data(&j->name)); - obj_skin_strings_push_back_check(&string_set, string_data(&j->sibling_name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage->external_name_index); + for (int32_t j = 0; j < osage->count; j++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[j]; + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage_node->name_index); + + int32_t name_index = osage->name_index; + obj_skin_osage_sibling_info* osage_sibling_infos = ex->osage_sibling_infos; + for (int32_t k = 0; k < ex->osage_sibling_infos_count; k++) { + if (name_index == osage_sibling_infos->name_index) { + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage_sibling_infos->sibling_name_index); + break; + } + osage_sibling_infos++; + } } - obj_skin_osage_node* donor_osage_node = &ex->osage_nodes.begin[osg->start_index]; - for (int32_t j = 0; j < osg->count; j++) { - obj_skin_strings_push_back_check(&string_set, string_data(&donor_osage_node->name)); - obj_skin_strings_push_back_check(&string_set, string_data(&donor_osage_node->sibling_name)); - donor_osage_node++; + obj_skin_osage_node* child_osage_node = &ex->osage_nodes[osage->start_index]; + for (int32_t j = 0; j < osage->count; j++) { + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, child_osage_node->name_index); + + int32_t name_index = child_osage_node->name_index; + obj_skin_osage_sibling_info* osage_sibling_infos = ex->osage_sibling_infos; + for (int32_t k = 0; k < ex->osage_sibling_infos_count; k++) { + if (name_index == osage_sibling_infos->name_index) { + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage_sibling_infos->sibling_name_index); + break; + } + osage_sibling_infos++; + } + child_osage_node++; } - obj_skin_strings_push_back_check(&string_set, string_data(&osg->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage->name_index); } break; } + } - exh.strings_count = (int32_t)(string_set.end - string_set.begin); - exh.strings_offset = io_get_position(s); - for (string* i = string_set.begin; i != string_set.end; i++) + exh.bone_names_count = (int32_t)(bone_names.end - bone_names.begin); + exh.bone_names_offset = io_get_position(s); + for (string* i = bone_names.begin; i != bone_names.end; i++) io_write_int32_t(s, 0); io_align_write(s, 0x10); - if (blocks_count > 0) { + if (ex->blocks_count > 0) { exh.blocks_offset = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { io_write_int32_t(s, 0); io_write_int32_t(s, 0); } @@ -1533,147 +1537,188 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_write_int32_t(s, 0); io_align_write(s, 0x10); - bhs = force_malloc_s(obj_skin_block_header, blocks_count); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_OSAGE: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write(s, 0, 0x28); + bhs = force_malloc_s(obj_skin_block_header, ex->blocks_count); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write(s, 0, 0x28); + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); + } + io_align_write(s, 0x10); + + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_EXPRESSION) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write(s, 0, 0x28); + io_write(s, 0, 0x2C); + } + io_align_write(s, 0x10); + + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write(s, 0, 0x34); + } + io_align_write(s, 0x10); + + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write(s, 0, 0x28); + io_write(s, 0, 0x10); + switch (block->constraint.type) { + case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: + io_write(s, 0, 0x24); + io_write(s, 0, 0x18); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: + io_write(s, 0, 0x24); + io_write(s, 0, 0x04); + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: + io_write(s, 0, 0x0C); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: + io_write(s, 0, 0x24); io_write(s, 0, 0x14); io_write(s, 0, 0x14); break; } - io_align_write(s, 0x10); - - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_EXPRESSION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write(s, 0, 0x28); - io_write(s, 0, 0x2C); - break; - } - io_align_write(s, 0x10); - - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CLOTH: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write(s, 0, 0x34); - break; - } - io_align_write(s, 0x10); - - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CONSTRAINT: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write(s, 0, 0x28); - io_write(s, 0, 0x10); - switch (i->constraint.type) { - case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: - io_write(s, 0, 0x24); - io_write(s, 0, 0x18); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: - io_write(s, 0, 0x24); - io_write(s, 0, 0x04); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: - io_write(s, 0, 0x0C); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: - io_write(s, 0, 0x24); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - break; - } - break; - } + } io_align_write(s, 0x10); int32_t motion_block_count = 0; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_MOTION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write(s, 0, 0x28); - io_write(s, 0, 0x10); - motion_block_count++; - break; - } + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write(s, 0, 0x28); + io_write(s, 0, 0x10); + motion_block_count++; + } io_align_write(s, 0x10); if (exh.osage_count) { osage_block_node = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_OSAGE) - io_write(s, 0, (i->osage.nodes.end - i->osage.nodes.begin) - * (sizeof(uint32_t) + sizeof(float_t) * 4)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) + continue; + + obj_skin_block_osage* osage = &block->osage; + io_write(s, 0, osage->nodes_count * (sizeof(uint32_t) + sizeof(float_t) * 4)); + } io_align_write(s, 0x10); } if (motion_block_count) { motion_block_node_mats = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_MOTION) - io_write(s, 0, (i->motion.nodes.end - i->motion.nodes.begin) * sizeof(mat4)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + obj_skin_block_motion* motion = &block->motion; + io_write(s, 0, motion->nodes_count * sizeof(mat4)); + } io_align_write(s, 0x10); motion_block_node_name_offset = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_MOTION) - io_write(s, 0, (i->motion.nodes.end - i->motion.nodes.begin) * sizeof(uint32_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + obj_skin_block_motion* motion = &block->motion; + io_write(s, 0, motion->nodes_count * sizeof(uint32_t)); + } io_align_write(s, 0x10); } if (exh.cloth_count) { field_18 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - for (int32_t j = 0; j < 32; j++) - if (i->cloth.field_10 & (1 << j)) - io_write(s, 0, sizeof(mat4)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + for (int32_t j = 0; j < 32; j++) + if (cloth->field_10 & (1 << j)) + io_write(s, 0, sizeof(mat4)); + } io_align_write(s, 0x10); field_1C = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, (10 * sizeof(int32_t) + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) - * (i->cloth.field_1C.end - i->cloth.field_1C.begin)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, (10 * sizeof(int32_t) + + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * cloth->count); + } io_align_write(s, 0x10); field_20 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, 10 * (11 * sizeof(int32_t)) - * (i->cloth.field_20.end - i->cloth.field_20.begin)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, 10 * (11 * sizeof(int32_t)) * cloth->count); + } io_align_write(s, 0x10); field_24 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, sizeof(uint16_t) + (i->cloth.field_24.end - - i->cloth.field_24.begin) * sizeof(uint16_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, sizeof(uint16_t) + cloth->field_24_count * sizeof(uint16_t)); + } io_align_write(s, 0x10); field_28 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, sizeof(uint16_t) + (i->cloth.field_28.end - - i->cloth.field_28.begin) * sizeof(uint16_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, sizeof(uint16_t) + cloth->field_28_count * sizeof(uint16_t)); + } io_align_write(s, 0x10); } } } - if (sh.bone_count || sk->ex_data_init) { + if (sk->bones || sk->ex_data_init) { for (string* i = strings.begin; i != &strings.end[-1]; i++) { char* i_str = string_data(i); for (string* j = i + 1; j != strings.end; j++) - if (strcmp(i_str, string_data(j)) > 0) { + if (str_utils_compare(i_str, string_data(j)) > 0) { string temp = *i; *i = *j; *j = temp; @@ -1681,10 +1726,11 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { } } + vector_ssize_t_reserve(&string_offsets, strings.end - strings.begin); + for (string* i = strings.begin; i != strings.end; i++) { - ssize_t off = io_get_position(s); - io_write(s, string_data(i), string_length(i) + 1); - vector_ssize_t_push_back(&string_offsets, &off); + *vector_ssize_t_reserve_back(&string_offsets) = io_get_position(s); + io_write_string_null_terminated(s, i); } } io_align_write(s, 0x10); @@ -1693,38 +1739,20 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { if (sk->ex_data_init) { obj_skin_ex_data* ex = &sk->ex_data; - size_t cls_offset = 0; - size_t cns_offset = 0; - size_t exp_offset = 0; - size_t mot_offset = 0; - size_t osg_offset = 0; - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "CLS")) - cls_offset = string_offsets.begin[i - strings.begin]; + ssize_t cls_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "CLS"); + ssize_t cns_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "CNS"); + ssize_t exp_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "EXP"); + ssize_t mot_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "MOT"); + ssize_t osg_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "OSG"); - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "CNS")) - cns_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "EXP")) - exp_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "MOT")) - mot_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "OSG")) - osg_offset = string_offsets.begin[i - strings.begin]; - - if (blocks_count > 0) { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_CLOTH) + if (ex->blocks_count > 0) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_classic_write_skin_block_cloth(&i->cloth, + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_classic_write_skin_block_cloth(&block->cloth, s, &strings, &string_offsets, &field_18, &field_1C, &field_20, &field_24, &field_28); io_position_pop(s); } @@ -1739,81 +1767,95 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { constraint_type_name_offsets[3] = obj_skin_strings_get_string_offset(&strings, &string_offsets, "Position"); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_CONSTRAINT) + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_classic_write_skin_block_constraint(&i->constraint, - s, &strings, &string_offsets, constraint_type_name_offsets); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_classic_write_skin_block_constraint(&block->constraint, + s, &strings, &string_offsets, bone_names_ptr, constraint_type_name_offsets); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_EXPRESSION) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_EXPRESSION) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_classic_write_skin_block_expression(&i->expression, - s, &strings, &string_offsets); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_classic_write_skin_block_expression(&block->expression, + s, &strings, &string_offsets, bone_names_ptr); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_MOTION) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_classic_write_skin_block_motion(&i->motion, - s, &strings, &string_offsets, &string_set, + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_classic_write_skin_block_motion(&block->motion, + s, &strings, &string_offsets, bone_names_ptr, &motion_block_node_name_offset, &motion_block_node_mats); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_OSAGE) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_classic_write_skin_block_osage(&i->osage, - s, &strings, &string_offsets, &string_set, &osage_block_node); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_classic_write_skin_block_osage(&block->osage, + s, &strings, &string_offsets, &osage_block_node); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_OSAGE) - obj_skin_strings_push_back_check(&osage_names, string_data(&i->osage.external_name)); - else if (i->type == OBJ_SKIN_BLOCK_CLOTH) - obj_skin_strings_push_back_check(&osage_names, string_data(&i->cloth.mesh_name)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type == OBJ_SKIN_BLOCK_CLOTH) { + obj_skin_block_cloth* cloth = &block->cloth; + obj_skin_strings_push_back_check(&osage_names, string_data(&cloth->mesh_name)); + } + else if (block->type == OBJ_SKIN_BLOCK_OSAGE) { + obj_skin_block_osage* osage = &block->osage; + obj_skin_strings_push_back_check_by_index(&osage_names, + bone_names_ptr, osage->external_name_index); + } + } io_position_push(s, exh.blocks_offset, SEEK_SET); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: io_write_int32_t(s, (int32_t)cls_offset); - io_write_int32_t(s, (int32_t)bhs[i - ex->blocks.begin].block_offset); + io_write_int32_t(s, (int32_t)bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_CONSTRAINT: io_write_int32_t(s, (int32_t)cns_offset); - io_write_int32_t(s, (int32_t)bhs[i - ex->blocks.begin].block_offset); + io_write_int32_t(s, (int32_t)bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_EXPRESSION: io_write_int32_t(s, (int32_t)exp_offset); - io_write_int32_t(s, (int32_t)bhs[i - ex->blocks.begin].block_offset); + io_write_int32_t(s, (int32_t)bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_MOTION: io_write_int32_t(s, (int32_t)mot_offset); - io_write_int32_t(s, (int32_t)bhs[i - ex->blocks.begin].block_offset); + io_write_int32_t(s, (int32_t)bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_OSAGE: io_write_int32_t(s, (int32_t)osg_offset); - io_write_int32_t(s, (int32_t)bhs[i - ex->blocks.begin].block_offset); + io_write_int32_t(s, (int32_t)bhs[i].block_offset); break; default: io_write_int32_t(s, 0); io_write_int32_t(s, 0); break; } + } io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_position_pop(s); @@ -1821,11 +1863,11 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { } } - if (sh.bone_count) { + if (sk->bones) { io_position_push(s, sh.bone_names_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, - &string_offsets, string_data(&sk->bones.begin[i].name)); + &string_offsets, string_data(&sk->bones[i].name)); io_write_int32_t(s, (int32_t)str_offset); } io_position_pop(s); @@ -1834,35 +1876,30 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { if (sk->ex_data_init) { obj_skin_ex_data* ex = &sk->ex_data; - if (blocks_count > 0) { - io_position_push(s, exh.strings_offset, SEEK_SET); - for (string* i = string_set.begin; i != string_set.end; i++) { + if (ex->blocks_count > 0) { + io_position_push(s, exh.bone_names_offset, SEEK_SET); + for (string* i = bone_names.begin; i != bone_names.end; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, string_data(i)); io_write_int32_t(s, (int32_t)str_offset); } io_position_pop(s); - exh.osage_nodes_count = (int32_t)(ex->osage_nodes.end - ex->osage_nodes.begin); io_position_push(s, exh.osage_nodes_offset, SEEK_SET); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - uint32_t index = obj_skin_strings_get_string_index(&string_set, string_data(&i->name)); - io_write_uint32_t(s, index); - io_write_float_t(s, i->length); - io_write_uint32_t(s, index & 0x7FFF); + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[i]; + io_write_uint32_t(s, osage_node->name_index); + io_write_float_t(s, osage_node->length); + io_write_uint32_t(s, osage_node->name_index & 0x7FFF); } io_position_pop(s); io_position_push(s, exh.osage_sibling_infos_offset, SEEK_SET); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - if (!string_length(&i->sibling_name)) - continue; - - uint32_t name = obj_skin_strings_get_string_index(&string_set, string_data(&i->name)); - uint32_t sibling_name = obj_skin_strings_get_string_index(&string_set, string_data(&i->sibling_name)); - io_write_uint32_t(s, name); - io_write_uint32_t(s, sibling_name); - io_write_float_t(s, i->sibling_max_distance); + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { + obj_skin_osage_sibling_info* osage_sibling_info = &ex->osage_sibling_infos[i]; + io_write_uint32_t(s, osage_sibling_info->name_index); + io_write_uint32_t(s, osage_sibling_info->sibling_name_index); + io_write_float_t(s, osage_sibling_info->distance); } io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -1880,35 +1917,21 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_position_pop(s); } - for (string* i = osage_names.begin; i != osage_names.end; i++) - string_free(i); - vector_string_free(&osage_names); - } - - for (string* i = strings.begin; i != strings.end; i++) - string_free(i); - vector_string_free(&strings); - - vector_ssize_t_free(&string_offsets); - - for (string* i = string_set.begin; i != string_set.end; i++) - string_free(i); - vector_string_free(&string_set); - - if (sk->ex_data_init) { io_position_push(s, sh.ex_data_offset, SEEK_SET); io_write_int32_t(s, exh.osage_count); - io_write_int32_t(s, exh.osage_nodes_count); + io_write_int32_t(s, ex->osage_nodes_count); io_write(s, 0, 0x04); io_write_int32_t(s, (int32_t)exh.osage_nodes_offset); io_write_int32_t(s, (int32_t)exh.osage_names_offset); io_write_int32_t(s, (int32_t)exh.blocks_offset); - io_write_int32_t(s, exh.strings_count); - io_write_int32_t(s, (int32_t)exh.strings_offset); + io_write_int32_t(s, exh.bone_names_count); + io_write_int32_t(s, (int32_t)exh.bone_names_offset); io_write_int32_t(s, (int32_t)exh.osage_sibling_infos_offset); io_write_int32_t(s, exh.cloth_count); io_write(s, 0, 0x1C); io_position_pop(s); + + vector_string_free(&osage_names, string_free); } io_position_push(s, base_offset, SEEK_SET); @@ -1916,18 +1939,22 @@ static void obj_classic_write_skin(obj* o, stream* s, ssize_t base_offset) { io_write_int32_t(s, (int32_t)sh.bone_matrices_offset); io_write_int32_t(s, (int32_t)sh.bone_names_offset); io_write_int32_t(s, (int32_t)sh.ex_data_offset); - io_write_int32_t(s, sh.bone_count); + io_write_int32_t(s, sk->bones_count); io_write_int32_t(s, (int32_t)sh.bone_parent_ids_offset); io_write(s, 0, 0x0C); io_position_pop(s); + + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + vector_string_free(&bone_names, string_free); } static void obj_classic_read_skin_block_cloth(obj_skin_block_cloth* b, - stream* s, string* str) { + stream* s, char** str) { int32_t mesh_name_offset = io_read_int32_t(s); int32_t backface_mesh_name_offset = io_read_int32_t(s); b->field_08 = io_read_int32_t(s); - int32_t count = io_read_int32_t(s); + b->count = io_read_int32_t(s); b->field_10 = io_read_int32_t(s); b->field_14 = io_read_int32_t(s); int32_t field_18_offset = io_read_int32_t(s); @@ -1964,78 +1991,67 @@ static void obj_classic_read_skin_block_cloth(obj_skin_block_cloth* b, mat.row3.y = io_read_float_t(s); mat.row3.z = io_read_float_t(s); mat.row3.w = io_read_float_t(s); - mat4_transpose(&mat, &b->field_18[i]); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &b->field_18[i]); } io_position_pop(s); } if (field_1C_offset) { io_position_push(s, field_1C_offset, SEEK_SET); - b->field_1C = vector_empty(obj_skin_block_cloth_field_1C); - vector_obj_skin_block_cloth_field_1C_reserve(&b->field_1C, count); - for (int32_t i = 0; i < count; i++) { - obj_skin_block_cloth_field_1C f; - f.field_00 = io_read_float_t(s); - f.field_04 = io_read_float_t(s); - f.field_08 = io_read_float_t(s); - f.field_0C = io_read_float_t(s); - f.field_10 = io_read_float_t(s); - f.field_14 = io_read_float_t(s); - f.field_18 = io_read_float_t(s); - f.field_1C = io_read_uint32_t(s); - f.field_20 = io_read_uint32_t(s); - f.field_24 = io_read_uint32_t(s); - obj_classic_read_skin_block_cloth_field_1C_sub(&f.sub_data_0, s, str); - obj_classic_read_skin_block_cloth_field_1C_sub(&f.sub_data_1, s, str); - obj_classic_read_skin_block_cloth_field_1C_sub(&f.sub_data_2, s, str); - obj_classic_read_skin_block_cloth_field_1C_sub(&f.sub_data_3, s, str); - vector_obj_skin_block_cloth_field_1C_push_back(&b->field_1C, &f); + b->field_1C = force_malloc_s(obj_skin_block_cloth_field_1C, b->count); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_1C* f = &b->field_1C[i]; + f->field_00 = io_read_float_t(s); + f->field_04 = io_read_float_t(s); + f->field_08 = io_read_float_t(s); + f->field_0C = io_read_float_t(s); + f->field_10 = io_read_float_t(s); + f->field_14 = io_read_float_t(s); + f->field_18 = io_read_float_t(s); + f->field_1C = io_read_uint32_t(s); + f->field_20 = io_read_uint32_t(s); + f->field_24 = io_read_uint32_t(s); + obj_classic_read_skin_block_cloth_field_1C_sub(&f->sub_data_0, s, str); + obj_classic_read_skin_block_cloth_field_1C_sub(&f->sub_data_1, s, str); + obj_classic_read_skin_block_cloth_field_1C_sub(&f->sub_data_2, s, str); + obj_classic_read_skin_block_cloth_field_1C_sub(&f->sub_data_3, s, str); } io_position_pop(s); } if (field_20_offset) { io_position_push(s, field_20_offset, SEEK_SET); - b->field_20 = vector_empty(obj_skin_block_cloth_field_20); - vector_obj_skin_block_cloth_field_20_reserve(&b->field_20, count); - for (int32_t i = 0; i < count; i++) { - obj_skin_block_cloth_field_20 f; - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_0, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_1, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_2, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_3, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_4, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_5, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_6, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_7, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_8, s, str); - obj_classic_read_skin_block_cloth_field_20_sub(&f.sub_data_9, s, str); - vector_obj_skin_block_cloth_field_20_push_back(&b->field_20, &f); + b->field_20 = force_malloc_s(obj_skin_block_cloth_field_20, b->count); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_20* f = &b->field_20[i]; + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_0, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_1, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_2, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_3, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_4, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_5, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_6, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_7, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_8, s, str); + obj_classic_read_skin_block_cloth_field_20_sub(&f->sub_data_9, s, str); } io_position_pop(s); } if (field_24_offset) { io_position_push(s, field_24_offset, SEEK_SET); - b->field_24 = vector_empty(uint16_t); - count = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_reserve(&b->field_24, count); - for (int32_t i = 0; i < count; i++) { - uint16_t u = io_read_uint16_t(s); - vector_uint16_t_push_back(&b->field_24, &u); - } + b->field_24_count = io_read_uint16_t_stream_reverse_endianness(s); + b->field_24 = force_malloc_s(uint16_t, b->field_24_count); + io_read(s, b->field_24, b->field_24_count * sizeof(uint16_t)); io_position_pop(s); } if (field_28_offset) { io_position_push(s, field_28_offset, SEEK_SET); - b->field_28 = vector_empty(uint16_t); - count = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_reserve(&b->field_28, count); - for (int32_t i = 0; i < count; i++) { - uint16_t u = io_read_uint16_t(s); - vector_uint16_t_push_back(&b->field_28, &u); - } + b->field_28_count = io_read_uint16_t_stream_reverse_endianness(s); + b->field_28 = force_malloc_s(uint16_t, b->field_28_count); + io_read(s, b->field_28, b->field_28_count * sizeof(uint16_t)); io_position_pop(s); } } @@ -2044,7 +2060,6 @@ static void obj_classic_write_skin_block_cloth(obj_skin_block_cloth* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* field_18_offset, ssize_t* field_1C_offset, ssize_t* field_20_offset, ssize_t* field_24_offset, ssize_t* field_28_offset) { - int32_t count = (int32_t)(b->field_1C.end - b->field_1C.begin); ssize_t mesh_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->mesh_name)); ssize_t backface_mesh_name_offset = obj_skin_strings_get_string_offset(strings, @@ -2053,7 +2068,7 @@ static void obj_classic_write_skin_block_cloth(obj_skin_block_cloth* b, io_write_int32_t(s, (int32_t)mesh_name_offset); io_write_int32_t(s, (int32_t)backface_mesh_name_offset); io_write_int32_t(s, b->field_08); - io_write_int32_t(s, count); + io_write_int32_t(s, b->count); io_write_int32_t(s, b->field_10); io_write_int32_t(s, b->field_14); io_write_int32_t(s, (int32_t)*field_18_offset); @@ -2071,7 +2086,8 @@ static void obj_classic_write_skin_block_cloth(obj_skin_block_cloth* b, continue; mat4 mat; - mat4_transpose(&b->field_18[i], &mat); + mat4u_to_mat4(&b->field_18[i], &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -2093,68 +2109,68 @@ static void obj_classic_write_skin_block_cloth(obj_skin_block_cloth* b, io_position_pop(s); } - if (b->field_1C.end - b->field_1C.begin) { + if (b->field_1C) { io_position_push(s, *field_1C_offset, SEEK_SET); - for (obj_skin_block_cloth_field_1C* i = b->field_1C.begin; i != b->field_1C.end; i++) { - io_write_float_t(s, i->field_00); - io_write_float_t(s, i->field_04); - io_write_float_t(s, i->field_08); - io_write_float_t(s, i->field_0C); - io_write_float_t(s, i->field_10); - io_write_float_t(s, i->field_14); - io_write_float_t(s, i->field_18); - io_write_uint32_t(s, i->field_1C); - io_write_uint32_t(s, i->field_20); - io_write_uint32_t(s, i->field_24); - obj_classic_write_skin_block_cloth_field_1C_sub(&i->sub_data_0, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_1C_sub(&i->sub_data_1, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_1C_sub(&i->sub_data_2, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_1C_sub(&i->sub_data_3, s, strings, string_offsets); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_1C* f = &b->field_1C[i]; + io_write_float_t(s, f->field_00); + io_write_float_t(s, f->field_04); + io_write_float_t(s, f->field_08); + io_write_float_t(s, f->field_0C); + io_write_float_t(s, f->field_10); + io_write_float_t(s, f->field_14); + io_write_float_t(s, f->field_18); + io_write_uint32_t(s, f->field_1C); + io_write_uint32_t(s, f->field_20); + io_write_uint32_t(s, f->field_24); + obj_classic_write_skin_block_cloth_field_1C_sub(&f->sub_data_0, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_1C_sub(&f->sub_data_1, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_1C_sub(&f->sub_data_2, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_1C_sub(&f->sub_data_3, s, strings, string_offsets); } io_position_pop(s); *field_1C_offset += (10 * sizeof(int32_t) - + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * count; + + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * b->count; } - if (b->field_20.end - b->field_20.begin) { + if (b->field_20) { io_position_push(s, *field_20_offset, SEEK_SET); - for (obj_skin_block_cloth_field_20* i = b->field_20.begin; i != b->field_20.end; i++) { - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_0, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_1, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_2, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_3, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_4, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_5, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_6, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_7, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_8, s, strings, string_offsets); - obj_classic_write_skin_block_cloth_field_20_sub(&i->sub_data_9, s, strings, string_offsets); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_20* f = &b->field_20[i]; + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_0, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_1, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_2, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_3, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_4, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_5, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_6, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_7, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_8, s, strings, string_offsets); + obj_classic_write_skin_block_cloth_field_20_sub(&f->sub_data_9, s, strings, string_offsets); } io_position_pop(s); - *field_20_offset += 10 * (11 * sizeof(int32_t)) * count; + *field_20_offset += 10 * (11 * sizeof(int32_t)) * b->count; } - if (b->field_24.end - b->field_24.begin) { + if (b->field_24) { io_position_push(s, *field_24_offset, SEEK_SET); - io_write_uint16_t(s, (uint16_t)(b->field_24.end - b->field_24.begin)); - for (uint16_t* i = b->field_24.begin; i != b->field_24.end; i++) - io_write_uint16_t(s, *i); + io_write_uint16_t(s, (uint16_t)b->field_24_count); + io_write(s, b->field_24, b->field_24_count * sizeof(uint16_t)); io_position_pop(s); - *field_24_offset += sizeof(uint16_t) + (b->field_24.end - b->field_24.begin) * sizeof(uint16_t); + *field_28_offset += sizeof(uint16_t) + b->field_24_count * sizeof(uint16_t); } - if (b->field_28.end - b->field_28.begin) { + if (b->field_28) { io_position_push(s, *field_28_offset, SEEK_SET); - io_write_uint16_t(s, (uint16_t)(b->field_28.end - b->field_28.begin)); - for (uint16_t* i = b->field_28.begin; i != b->field_28.end; i++) - io_write_uint16_t(s, *i); + io_write_uint16_t(s, (uint16_t)b->field_28_count); + io_write(s, b->field_28, b->field_28_count * sizeof(uint16_t)); io_position_pop(s); - *field_28_offset += sizeof(uint16_t) + (b->field_28.end - b->field_28.begin) * sizeof(uint16_t); + *field_28_offset += sizeof(uint16_t) + b->field_28_count * sizeof(uint16_t); } } static void obj_classic_read_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, - stream* s, string* str) { + stream* s, char** str) { int32_t bone_name_offset = io_read_int32_t(s); io_read_string_null_terminated_offset(s, bone_name_offset, &sub->bone_name); sub->weight = io_read_float_t(s); @@ -2173,7 +2189,7 @@ static void obj_classic_write_skin_block_cloth_field_1C_sub(obj_skin_block_cloth } static void obj_classic_read_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, - stream* s, string* str) { + stream* s, char** str) { sub->field_00 = io_read_uint32_t(s); sub->field_04 = io_read_float_t(s); sub->field_08 = io_read_float_t(s); @@ -2203,21 +2219,29 @@ static void obj_classic_write_skin_block_cloth_field_20_sub(obj_skin_block_cloth } static void obj_classic_read_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, string* str) { + stream* s, char** str) { obj_classic_read_skin_block_node(&b->base, s, str); int32_t type_offset = io_read_int32_t(s); char* type = io_read_utf8_string_null_terminated_offset(s, type_offset); - int32_t name = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, name, &b->base.name); + int32_t name_offset = io_read_int32_t(s); + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); + + b->name_index = 0; + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); b->coupling = io_read_int32_t(s); - int32_t source_node_name = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, source_node_name, &b->source_node_name); + int32_t source_node_name_offset = io_read_int32_t(s); + io_read_string_null_terminated_offset(s, source_node_name_offset, &b->source_node_name); - if (!strcmp(type, "Direction")) { + if (!str_utils_compare(type, "Direction")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION; obj_classic_read_skin_block_constraint_up_vector(&b->direction.up_vector, s, str); @@ -2228,7 +2252,7 @@ static void obj_classic_read_skin_block_constraint(obj_skin_block_constraint* b, b->direction.target_offset.y = io_read_float_t(s); b->direction.target_offset.z = io_read_float_t(s); } - else if (!strcmp(type, "Distance")) { + else if (!str_utils_compare(type, "Distance")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE; obj_classic_read_skin_block_constraint_up_vector(&b->distance.up_vector, s, str); @@ -2238,13 +2262,13 @@ static void obj_classic_read_skin_block_constraint(obj_skin_block_constraint* b, obj_classic_read_skin_block_constraint_attach_point(&b->distance.constraining_object, s, str); } - else if (!strcmp(type, "Orientation")) { + else if (!str_utils_compare(type, "Orientation")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION; b->orientation.offset.x = io_read_float_t(s); b->orientation.offset.y = io_read_float_t(s); b->orientation.offset.z = io_read_float_t(s); } - else if (!strcmp(type, "Position")) { + else if (!str_utils_compare(type, "Position")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_POSITION; obj_classic_read_skin_block_constraint_up_vector(&b->position.up_vector, s, str); @@ -2259,7 +2283,7 @@ static void obj_classic_read_skin_block_constraint(obj_skin_block_constraint* b, } static void obj_classic_write_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* offsets) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, ssize_t* offsets) { obj_classic_write_skin_block_node(&b->base, s, strings, string_offsets); ssize_t type_offset = 0; @@ -2279,15 +2303,15 @@ static void obj_classic_write_skin_block_constraint(obj_skin_block_constraint* b } io_write_int32_t(s, (int32_t)type_offset); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_int32_t(s, (int32_t)name); + ssize_t name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + io_write_int32_t(s, (int32_t)name_offset); io_write_int32_t(s, b->coupling); - ssize_t source_node_name = obj_skin_strings_get_string_offset(strings, + ssize_t source_node_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->source_node_name)); - io_write_int32_t(s, (int32_t)source_node_name); + io_write_int32_t(s, (int32_t)source_node_name_offset); switch (b->type) { case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: @@ -2326,7 +2350,7 @@ static void obj_classic_write_skin_block_constraint(obj_skin_block_constraint* b } static void obj_classic_read_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, - stream* s, string* str) { + stream* s, char** str) { ap->affected_by_orientation = io_read_int32_t(s) != 0; ap->affected_by_scaling = io_read_int32_t(s) != 0; ap->offset.x = io_read_float_t(s); @@ -2344,7 +2368,7 @@ static void obj_classic_write_skin_block_constraint_attach_point(obj_skin_block_ } static void obj_classic_read_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, - stream* s, string* str) { + stream* s, char** str) { up->active = io_read_int32_t(s) != 0; up->roll = io_read_float_t(s); up->affected_axis.x = io_read_float_t(s); @@ -2354,8 +2378,8 @@ static void obj_classic_read_skin_block_constraint_up_vector(obj_skin_block_cons up->point_at.y = io_read_float_t(s); up->point_at.z = io_read_float_t(s); - int32_t name = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, name, &up->name); + int32_t name_offset = io_read_int32_t(s); + io_read_string_null_terminated_offset(s, name_offset, &up->name); } static void obj_classic_write_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, @@ -2369,82 +2393,93 @@ static void obj_classic_write_skin_block_constraint_up_vector(obj_skin_block_con io_write_float_t(s, up->point_at.y); io_write_float_t(s, up->point_at.z); - ssize_t name = obj_skin_strings_get_string_offset(strings, + ssize_t name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&up->name)); - io_write_int32_t(s, (int32_t)name); + io_write_int32_t(s, (int32_t)name_offset); } static void obj_classic_read_skin_block_expression(obj_skin_block_expression* b, - stream* s, string* str) { + stream* s, char** str) { obj_classic_read_skin_block_node(&b->base, s, str); - int32_t name = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, name, &b->base.name); + int32_t name_offset = io_read_int32_t(s); + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); - b->expression_count = io_read_int32_t(s); - b->expression_count = min(b->expression_count, 9); - for (int32_t i = 0; i < b->expression_count; i++) { - int32_t expression = io_read_int32_t(s); - if (expression) - io_read_string_null_terminated_offset(s, expression, &b->expressions[i]); + b->name_index = 0; + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); + + b->expressions_count = io_read_int32_t(s); + b->expressions_count = min(b->expressions_count, 9); + for (int32_t i = 0; i < b->expressions_count; i++) { + int32_t expression_offset = io_read_int32_t(s); + if (expression_offset) + io_read_string_null_terminated_offset(s, expression_offset, &b->expressions[i]); } - for (int32_t i = b->expression_count; i < 9; i++) - memset(&b->expressions[i], 0, sizeof(string)); + for (int32_t i = b->expressions_count; i < 9; i++) + b->expressions[i] = string_empty; } static void obj_classic_write_skin_block_expression(obj_skin_block_expression* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names) { obj_classic_write_skin_block_node(&b->base, s, strings, string_offsets); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_int32_t(s, (int32_t)name); + ssize_t name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + io_write_int32_t(s, (int32_t)name_offset); - io_write_int32_t(s, min(b->expression_count, 9)); - for (int32_t i = 0; i < b->expression_count && i < 9; i++) { - ssize_t expression = obj_skin_strings_get_string_offset(strings, + io_write_int32_t(s, min(b->expressions_count, 9)); + for (int32_t i = 0; i < b->expressions_count && i < 9; i++) { + ssize_t expression_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->expressions[i])); - io_write_int32_t(s, (int32_t)expression); + io_write_int32_t(s, (int32_t)expression_offset); } - for (int32_t i = b->expression_count; i < 9; i++) + for (int32_t i = b->expressions_count; i < 9; i++) io_write_int32_t(s, 0); } static void obj_classic_read_skin_block_motion(obj_skin_block_motion* b, - stream* s, string* str) { + stream* s, char** str) { obj_classic_read_skin_block_node(&b->base, s, str); int32_t name_offset = io_read_int32_t(s); - int32_t count = io_read_int32_t(s); + b->nodes_count = io_read_int32_t(s); int32_t bone_names_offset = io_read_int32_t(s); int32_t bone_matrices_offset = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, name_offset, &b->base.name); + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); - obj_skin_motion_node node; - memset(&node, 0, sizeof(obj_skin_motion_node)); + b->name_index = 0; + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); - b->nodes = vector_empty(obj_skin_motion_node); - vector_obj_skin_motion_node_reserve(&b->nodes, count); + b->nodes = 0; + + if (!b->nodes_count) + return; + + b->nodes = force_malloc_s(obj_skin_motion_node, b->nodes_count); if (bone_names_offset) { io_position_push(s, bone_names_offset, SEEK_SET); - for (int32_t i = 0; i < count; i++) { - uint32_t name = io_read_uint32_t(s); - if (name & 0x8000) - string_copy(&str[name & 0x7FFF], &node.name); - else - memset(&node.name, 0, sizeof(string)); - vector_obj_skin_motion_node_push_back(&b->nodes, &node); - } + for (int32_t i = 0; i < b->nodes_count; i++) + b->nodes[i].name_index = io_read_uint32_t(s); io_position_pop(s); } if (bone_matrices_offset) { io_position_push(s, bone_matrices_offset, SEEK_SET); - for (int32_t i = 0; i < count; i++) { + for (int32_t i = 0; i < b->nodes_count; i++) { mat4 mat; mat.row0.x = io_read_float_t(s); mat.row0.y = io_read_float_t(s); @@ -2462,7 +2497,8 @@ static void obj_classic_read_skin_block_motion(obj_skin_block_motion* b, mat.row3.y = io_read_float_t(s); mat.row3.z = io_read_float_t(s); mat.row3.w = io_read_float_t(s); - mat4_transpose(&mat, &b->nodes.begin[i].transformation); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &b->nodes[i].transformation); } io_position_pop(s); } @@ -2470,30 +2506,31 @@ static void obj_classic_read_skin_block_motion(obj_skin_block_motion* b, static void obj_classic_write_skin_block_motion(obj_skin_block_motion* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, - vector_string* string_set, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset) { + char** bone_names, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset) { obj_classic_write_skin_block_node(&b->base, s, strings, string_offsets); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_int32_t(s, (int32_t)name); - io_write_int32_t(s, (int32_t)(b->nodes.end - b->nodes.begin)); + ssize_t name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + io_write_int32_t(s, (int32_t)name_offset); + io_write_int32_t(s, b->nodes_count); io_write_int32_t(s, (int32_t)*bone_names_offset); io_write_int32_t(s, (int32_t)*bone_matrices_offset); obj_skin_motion_node node; memset(&node, 0, sizeof(obj_skin_motion_node)); - if (b->nodes.end - b->nodes.begin) { + if (b->nodes) { io_position_push(s, *bone_names_offset, SEEK_SET); - for (obj_skin_motion_node* i = b->nodes.begin; i != b->nodes.end; i++) - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&i->name))); + for (int32_t i = 0; i < b->nodes_count; i++) + io_write_uint32_t(s, b->nodes[i].name_index); io_position_pop(s); - *bone_names_offset += (b->nodes.end - b->nodes.begin) * sizeof(uint32_t); + *bone_names_offset += b->nodes_count * sizeof(uint32_t); io_position_push(s, *bone_matrices_offset, SEEK_SET); - for (obj_skin_motion_node* i = b->nodes.begin; i != b->nodes.end; i++) { + for (int32_t i = 0; i < b->nodes_count; i++) { mat4 mat; - mat4_transpose(&i->transformation, &mat); + mat4u_to_mat4(&b->nodes[i].transformation, &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -2512,14 +2549,14 @@ static void obj_classic_write_skin_block_motion(obj_skin_block_motion* b, io_write_float_t(s, mat.row3.w); } io_position_pop(s); - *bone_matrices_offset += (b->nodes.end - b->nodes.begin) * sizeof(mat4); + *bone_matrices_offset += b->nodes_count * sizeof(mat4); } } static void obj_classic_read_skin_block_node(obj_skin_block_node* b, - stream* s, string* str) { - int32_t parent_name = io_read_int32_t(s); - io_read_string_null_terminated_offset(s, parent_name, &b->parent_name); + stream* s, char** str) { + int32_t parent_name_offset = io_read_int32_t(s); + io_read_string_null_terminated_offset(s, parent_name_offset, &b->parent_name); b->position.x = io_read_float_t(s); b->position.y = io_read_float_t(s); @@ -2534,9 +2571,9 @@ static void obj_classic_read_skin_block_node(obj_skin_block_node* b, static void obj_classic_write_skin_block_node(obj_skin_block_node* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets) { - ssize_t parent_name = obj_skin_strings_get_string_offset(strings, + ssize_t parent_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->parent_name)); - io_write_int32_t(s, (int32_t)parent_name); + io_write_int32_t(s, (int32_t)parent_name_offset); io_write_float_t(s, b->position.x); io_write_float_t(s, b->position.y); @@ -2550,83 +2587,68 @@ static void obj_classic_write_skin_block_node(obj_skin_block_node* b, } static void obj_classic_read_skin_block_osage(obj_skin_block_osage* b, - stream* s, string* str) { + stream* s, char** str) { obj_classic_read_skin_block_node(&b->base, s, str); b->start_index = io_read_int32_t(s); b->count = io_read_int32_t(s); - uint32_t external_name = io_read_uint32_t(s); - if (external_name & 0x8000) - string_copy(&str[external_name & 0x7FFF], &b->external_name); - else - memset(&b->external_name, 0, sizeof(string)); - - uint32_t name = io_read_uint32_t(s); - if (name & 0x8000) - string_copy(&str[name & 0x7FFF], &b->base.name); - else - memset(&b->base.name, 0, sizeof(string)); + b->external_name_index = io_read_uint32_t(s); + b->name_index = io_read_uint32_t(s); int32_t offset = io_read_int32_t(s); io_read(s, 0, 0x14); - b->nodes = vector_empty(obj_skin_osage_node); - if (offset) { - vector_obj_skin_osage_node_reserve(&b->nodes, b->count); - io_position_push(s, offset, SEEK_SET); - if (io_read_uint32_t(s)) { - io_set_position(s, offset, SEEK_SET); - obj_skin_osage_node osage_node; - memset(&osage_node, 0, sizeof(obj_skin_osage_node)); + b->nodes = 0; - for (int32_t i = 0; i < b->count; i++) { - uint32_t name = io_read_uint32_t(s); - if (name & 0x8000) - string_copy(&str[name & 0x7FFF], &osage_node.name); - else - memset(&osage_node.name, 0, sizeof(string)); + if (!b->nodes_count || !offset) + return; - osage_node.length = io_read_float_t(s); - osage_node.rotation.x = io_read_float_t(s); - osage_node.rotation.y = io_read_float_t(s); - osage_node.rotation.z = io_read_float_t(s); - vector_obj_skin_osage_node_push_back(&b->nodes, &osage_node); - } + b->nodes = force_malloc_s(obj_skin_osage_node, b->nodes_count); + + io_position_push(s, offset, SEEK_SET); + if (io_read_uint32_t(s)) { + io_set_position(s, offset, SEEK_SET); + for (int32_t i = 0; i < b->nodes_count; i++) { + obj_skin_osage_node* node = &b->nodes[i]; + node->name_index = io_read_uint32_t(s); + node->length = io_read_float_t(s); + node->rotation.x = io_read_float_t(s); + node->rotation.y = io_read_float_t(s); + node->rotation.z = io_read_float_t(s); } } io_position_pop(s); } static void obj_classic_write_skin_block_osage(obj_skin_block_osage* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, - vector_string* string_set, ssize_t* nodes_offset) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, ssize_t* nodes_offset) { obj_classic_write_skin_block_node(&b->base, s, strings, string_offsets); io_write_int32_t(s, b->start_index); io_write_int32_t(s, b->count); - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&b->external_name))); - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&b->base.name))); + io_write_uint32_t(s, b->external_name_index); + io_write_uint32_t(s, b->name_index); io_write_int32_t(s, (int32_t)*nodes_offset); io_write(s, 0, 0x14); - if (b->nodes.end - b->nodes.begin) { + if (b->nodes) { io_position_push(s, *nodes_offset, SEEK_SET); - for (obj_skin_osage_node* i = b->nodes.begin; i != b->nodes.end; i++) { - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&i->name))); - io_write_float_t(s, i->length); - io_write_float_t(s, i->rotation.x); - io_write_float_t(s, i->rotation.y); - io_write_float_t(s, i->rotation.z); + for (int32_t i = 0; i < b->nodes_count; i++) { + obj_skin_osage_node* node = &b->nodes[i]; + io_write_uint32_t(s, node->name_index); + io_write_float_t(s, node->length); + io_write_float_t(s, node->rotation.x); + io_write_float_t(s, node->rotation.y); + io_write_float_t(s, node->rotation.z); } io_position_pop(s); - *nodes_offset += (b->nodes.end - b->nodes.begin) * (sizeof(uint32_t) + sizeof(float_t) * 4); + *nodes_offset += b->nodes_count * (sizeof(uint32_t) + sizeof(float_t) * 4); } } -static void obj_classic_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, +static void obj_classic_read_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, ssize_t base_offset, int32_t vertex_count, obj_vertex_attrib_type attrib_type) { - obj_vertex_flags vertex_flags = OBJ_VERTEX_NONE; if (attrib_type & OBJ_VERTEX_ATTRIB_POSITION) vertex_flags |= OBJ_VERTEX_POSITION; @@ -2767,7 +2789,7 @@ static void obj_classic_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, bone_index.z = -1; if (bone_index.w == 0xFF) bone_index.w = -1; - vtx[j].bone_index = bone_index; + vec4i_to_vec4iu(bone_index, vtx[j].bone_index); } break; case OBJ_VERTEX_ATTRIB_UNKNOWN: @@ -2785,7 +2807,7 @@ static void obj_classic_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, mesh->vertex_flags = vertex_flags; } -static void obj_classic_write_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, +static void obj_classic_write_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, ssize_t base_offset, int32_t* vertex_count, obj_vertex_attrib_type* attrib_type, int32_t* vertex_size) { obj_vertex_data* vtx = mesh->vertex; int32_t _vertex_count = mesh->vertex_count; @@ -2915,7 +2937,7 @@ static void obj_classic_write_vertex(obj* o, stream* s, ssize_t* attrib_offsets, attrib_offsets[11] = io_get_position(s) - base_offset; for (int32_t i = 0; i < _vertex_count; i++) { vec4 bone_index; - vec4i_to_vec4(vtx[i].bone_index, bone_index); + vec4i16_to_vec4(vtx[i].bone_index, bone_index); io_write_float_t(s, bone_index.x); io_write_float_t(s, bone_index.y); io_write_float_t(s, bone_index.z); @@ -2995,98 +3017,92 @@ static void obj_modern_read_inner(obj_set* os, stream* s) { } bool is_x = true; - io_set_position(&s_mosd, 0x00C, SEEK_SET); + io_set_position(&s_mosd, 0x0C, SEEK_SET); is_x &= io_read_uint32_t_stream_reverse_endianness(&s_mosd) == 0; - io_set_position(&s_mosd, 0x014, SEEK_SET); + io_set_position(&s_mosd, 0x14, SEEK_SET); is_x &= io_read_uint32_t_stream_reverse_endianness(&s_mosd) == 0; - io_set_position(&s_mosd, 0x01C, SEEK_SET); + io_set_position(&s_mosd, 0x1C, SEEK_SET); is_x &= io_read_uint32_t_stream_reverse_endianness(&s_mosd) == 0; - io_set_position(&s_mosd, 0x024, SEEK_SET); + io_set_position(&s_mosd, 0x24, SEEK_SET); is_x &= io_read_uint32_t_stream_reverse_endianness(&s_mosd) == 0; - io_set_position(&s_mosd, 0x02C, SEEK_SET); + io_set_position(&s_mosd, 0x2C, SEEK_SET); is_x &= io_read_uint32_t_stream_reverse_endianness(&s_mosd) == 0; io_set_position(&s_mosd, 0x04, SEEK_SET); obj_set_header osh; memset(&osh, 0, sizeof(obj_set_header)); if (!is_x) { - osh.objects_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); + os->objects_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); osh.max_object_id = io_read_int32_t_stream_reverse_endianness(&s_mosd); osh.objects_offset = io_read_offset_f2(&s_mosd, st.header.length); osh.object_skins_offset = io_read_offset_f2(&s_mosd, st.header.length); osh.object_names_offset = io_read_offset_f2(&s_mosd, st.header.length); osh.object_ids_offset = io_read_offset_f2(&s_mosd, st.header.length); osh.texture_ids_offset = io_read_offset_f2(&s_mosd, st.header.length); - osh.texture_ids_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); + os->texture_ids_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); } else { - osh.objects_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); + os->objects_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); osh.max_object_id = io_read_int32_t_stream_reverse_endianness(&s_mosd); osh.objects_offset = io_read_offset_x(&s_mosd); osh.object_skins_offset = io_read_offset_x(&s_mosd); osh.object_names_offset = io_read_offset_x(&s_mosd); osh.object_ids_offset = io_read_offset_x(&s_mosd); osh.texture_ids_offset = io_read_offset_x(&s_mosd); - osh.texture_ids_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); + os->texture_ids_count = io_read_int32_t_stream_reverse_endianness(&s_mosd); } - int32_t count = osh.objects_count; - os->vec = vector_empty(obj); - vector_obj_reserve(&os->vec, osh.objects_count); + os->objects = force_malloc_s(obj, os->objects_count); ssize_t* objects_offsets = 0; if (osh.objects_offset) { - objects_offsets = force_malloc_s(ssize_t, count); + objects_offsets = force_malloc_s(ssize_t, os->objects_count); io_set_position(&s_mosd, osh.objects_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) objects_offsets[i] = io_read_offset_f2(&s_mosd, st.header.length); else - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) objects_offsets[i] = io_read_offset_x(&s_mosd); } ssize_t* object_skins_offsets = 0; if (osh.object_skins_offset) { - object_skins_offsets = force_malloc_s(ssize_t, count); + object_skins_offsets = force_malloc_s(ssize_t, os->objects_count); io_set_position(&s_mosd, osh.object_skins_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) object_skins_offsets[i] = io_read_offset_f2(&s_mosd, st.header.length); else - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) object_skins_offsets[i] = io_read_offset_x(&s_mosd); } ssize_t* object_names_offsets = 0; if (osh.object_names_offset) { - object_names_offsets = force_malloc_s(ssize_t, count); + object_names_offsets = force_malloc_s(ssize_t, os->objects_count); io_set_position(&s_mosd, osh.object_names_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) object_names_offsets[i] = io_read_offset_f2(&s_mosd, st.header.length); else - for (int32_t i = 0; i < count; i++) + for (int32_t i = 0; i < os->objects_count; i++) object_names_offsets[i] = io_read_offset_x(&s_mosd); } if (osh.objects_offset) - for (int32_t i = 0; i < count; i++) { - obj o; - memset(&o, 0, sizeof(obj)); - + for (int32_t i = 0; i < os->objects_count; i++) { + obj* obj = &os->objects[i]; if (osh.object_names_offset && object_names_offsets[i]) io_read_string_null_terminated_offset(&s_mosd, - object_names_offsets[i], &o.name); - - vector_obj_push_back(&os->vec, &o); + object_names_offsets[i], &obj->name); } if (osh.object_ids_offset) { io_set_position(&s_mosd, osh.object_ids_offset, SEEK_SET); - for (int32_t i = 0; i < count; i++) - os->vec.begin[i].id = io_read_uint32_t_stream_reverse_endianness(&s_mosd); + for (int32_t i = 0; i < os->objects_count; i++) + os->objects[i].id = io_read_uint32_t_stream_reverse_endianness(&s_mosd); } free(objects_offsets); @@ -3095,13 +3111,9 @@ static void obj_modern_read_inner(obj_set* os, stream* s) { if (osh.texture_ids_offset) { io_set_position(&s_mosd, osh.texture_ids_offset, SEEK_SET); - int32_t count = osh.texture_ids_count; - os->tex_ids = vector_empty(uint32_t); - vector_uint32_t_reserve(&os->tex_ids, count); - for (int32_t i = 0; i < count; i++) { - uint32_t tex_id = io_read_uint32_t_stream_reverse_endianness(&s_mosd); - vector_uint32_t_push_back(&os->tex_ids, &tex_id); - } + os->texture_ids = force_malloc_s(uint32_t, os->texture_ids_count); + for (int32_t i = 0; i < os->texture_ids_count; i++) + os->texture_ids[i] = io_read_uint32_t_stream_reverse_endianness(&s_mosd); } int32_t omdl_index = 0; @@ -3144,15 +3156,15 @@ static void obj_modern_read_inner(obj_set* os, stream* s) { s_ovtx_ptr = &s_ovtx; } - obj* o = &os->vec.begin[omdl_index]; + obj* obj = &os->objects[omdl_index]; stream s_omdl; io_mopen(&s_omdl, i->data, i->length); s_omdl.is_big_endian = i->header.use_big_endian; - obj_modern_read_model(o, &s_omdl, 0, i->header.length, is_x, s_oidx_ptr, s_ovtx_ptr); + obj_modern_read_model(obj, &s_omdl, 0, i->header.length, is_x, s_oidx_ptr, s_ovtx_ptr); io_free(&s_omdl); if (s_oskn_ptr) - obj_modern_read_skin(o, s_oskn_ptr, 0, oskn->header.length, is_x); + obj_modern_read_skin(obj, s_oskn_ptr, 0, oskn->header.length, is_x); if (s_oskn_ptr) io_free(&s_oskn); @@ -3184,11 +3196,9 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { obj_set_header osh; memset(&osh, 0, sizeof(obj_set_header)); - osh.objects_count = (int32_t)(os->vec.end - os->vec.begin); osh.max_object_id = -1; - osh.texture_ids_count = (int32_t)(os->tex_ids.end - os->tex_ids.begin); - int32_t count = osh.objects_count; + int32_t count = os->objects_count; if (!is_x) { ee = (enrs_entry){ 0, 1, 44, 1, vector_empty(enrs_sub_entry) }; @@ -3207,44 +3217,43 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { } if (!is_x) - off += (uint32_t)(count * 4LL); + off += (uint32_t)(count * 4ULL); else - off += (uint32_t)(count * 8LL); + off += (uint32_t)(count * 8ULL); off = align_val(off, 0x10); if (!is_x) - off += (uint32_t)(count * 4LL); + off += (uint32_t)(count * 4ULL); else - off += (uint32_t)(count * 8LL); + off += (uint32_t)(count * 8ULL); off = align_val(off, 0x10); if (!is_x) { ee = (enrs_entry){ off, 1, 4, count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(count * 4LL); + off = (uint32_t)(count * 4ULL); } else { ee = (enrs_entry){ off, 1, 8, count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(count * 8LL); + off = (uint32_t)(count * 8ULL); } off = align_val(off, 0x10); ee = (enrs_entry){ off, 1, 4, count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(count * 4LL); + off = (uint32_t)(count * 4ULL); off = align_val(off, 0x10); - ee = (enrs_entry){ off, 1, 4, osh.texture_ids_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 4, os->texture_ids_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(osh.texture_ids_count * 4LL); + off = (uint32_t)(os->texture_ids_count * 4ULL); off = align_val(off, 0x10); - io_set_position(&s_mosd, 0x00, SEEK_SET); if (!is_x) { io_write_int32_t(&s_mosd, 0); io_write_int32_t(&s_mosd, 0); @@ -3302,19 +3311,18 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { osh.object_ids_offset = io_get_position(&s_mosd); for (int32_t i = 0; i < count; i++) - io_write_uint32_t(&s_mosd, os->vec.begin[i].id); + io_write_uint32_t(&s_mosd, os->objects[i].id); io_align_write(&s_mosd, 0x10); - osh.texture_ids_count = (int32_t)(os->tex_ids.end - os->tex_ids.begin); osh.texture_ids_offset = io_get_position(&s_mosd); - for (int32_t i = 0; i < osh.texture_ids_count; i++) - io_write_uint32_t(&s_mosd, os->tex_ids.begin[i]); + for (int32_t i = 0; i < os->texture_ids_count; i++) + io_write_uint32_t(&s_mosd, os->texture_ids[i]); io_align_write(&s_mosd, 0x10); ssize_t* object_names_offsets = force_malloc_s(ssize_t, count); for (int32_t i = 0; i < count; i++) { object_names_offsets[i] = (int32_t)io_get_position(&s_mosd); - io_write_string_null_terminated(&s_mosd, &os->vec.begin[i].name); + io_write_string_null_terminated(&s_mosd, &os->objects[i].name); } io_align_write(&s_mosd, 0x10); @@ -3331,27 +3339,27 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { io_position_push(&s_mosd, 0x00, SEEK_SET); if (!is_x) { io_write_uint32_t(&s_mosd, 0x5062501); - io_write_int32_t(&s_mosd, osh.objects_count); + io_write_int32_t(&s_mosd, os->objects_count); io_write_int32_t(&s_mosd, -1); io_write_offset_f2(&s_mosd, osh.objects_offset, 0x20); io_write_offset_f2(&s_mosd, osh.object_skins_offset, 0x20); io_write_offset_f2(&s_mosd, osh.object_names_offset, 0x20); io_write_offset_f2(&s_mosd, osh.object_ids_offset, 0x20); io_write_offset_f2(&s_mosd, osh.texture_ids_offset, 0x20); - io_write_int32_t(&s_mosd, osh.texture_ids_count); + io_write_int32_t(&s_mosd, os->texture_ids_count); io_write_int32_t(&s_mosd, 0); io_write_int32_t(&s_mosd, 0); } else { io_write_uint32_t(&s_mosd, 0x5062501); - io_write_int32_t(&s_mosd, osh.objects_count); + io_write_int32_t(&s_mosd, os->objects_count); io_write_int32_t(&s_mosd, -1); io_write_offset_x(&s_mosd, osh.objects_offset); io_write_offset_x(&s_mosd, osh.object_skins_offset); io_write_offset_x(&s_mosd, osh.object_names_offset); io_write_offset_x(&s_mosd, osh.object_ids_offset); io_write_offset_x(&s_mosd, osh.texture_ids_offset); - io_write_int32_t(&s_mosd, osh.texture_ids_count); + io_write_int32_t(&s_mosd, os->texture_ids_count); io_write_int32_t(&s_mosd, 0); io_write_int32_t(&s_mosd, 0); } @@ -3360,46 +3368,41 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { f2_struct st; memset(&st, 0, sizeof(f2_struct)); for (int32_t i = 0; i < count; i++) { - obj* o = &os->vec.begin[i]; + obj* obj = &os->objects[i]; - f2_struct omdl; - memset(&omdl, 0, sizeof(f2_struct)); + f2_struct* omdl = vector_f2_struct_reserve_back(&st.sub_structs); stream s_omdl; io_mopen(&s_omdl, 0, 0); - if (o->skin_init) { - f2_struct oskn; - memset(&oskn, 0, sizeof(f2_struct)); + if (obj->skin_init) { + f2_struct* oskn = vector_f2_struct_reserve_back(&st.sub_structs); stream s_oskn; io_mopen(&s_oskn, 0, 0); - obj_modern_write_skin(o, &s_oskn, 0, is_x, &oskn); + obj_modern_write_skin(obj, &s_oskn, 0, is_x, oskn); io_align_write(&s_oskn, 0x10); - io_mcopy(&s_oskn, &oskn.data, &oskn.length); + io_mcopy(&s_oskn, &oskn->data, &oskn->length); io_free(&s_oskn); - oskn.header.signature = reverse_endianness_uint32_t('OSKN'); - oskn.header.length = 0x20; - oskn.header.use_big_endian = false; - oskn.header.use_section_size = true; - - vector_f2_struct_push_back(&omdl.sub_structs, &oskn); + oskn->header.signature = reverse_endianness_uint32_t('OSKN'); + oskn->header.length = 0x20; + oskn->header.use_big_endian = false; + oskn->header.use_section_size = true; } - obj_modern_write_model(o, &s_omdl, 0, is_x, &omdl); + obj_modern_write_model(obj, &s_omdl, 0, is_x, omdl); io_align_write(&s_omdl, 0x10); - io_mcopy(&s_omdl, &omdl.data, &omdl.length); + io_mcopy(&s_omdl, &omdl->data, &omdl->length); io_free(&s_omdl); - omdl.header.signature = reverse_endianness_uint32_t('OMDL'); - omdl.header.length = 0x20; - omdl.header.use_big_endian = false; - omdl.header.use_section_size = true; - vector_f2_struct_push_back(&st.sub_structs, &omdl); + omdl->header.signature = reverse_endianness_uint32_t('OMDL'); + omdl->header.length = 0x20; + omdl->header.use_big_endian = false; + omdl->header.use_section_size = true; } io_align_write(&s_mosd, 0x10); @@ -3418,33 +3421,32 @@ static void obj_modern_write_inner(obj_set* os, stream* s) { f2_struct_free(&st); } -static void obj_modern_read_index(obj* o, stream* s, - obj_sub_mesh* sub_mesh, int32_t indices_count) { - uint32_t* indices = force_malloc_s(uint32_t, indices_count); +static void obj_modern_read_index(obj* obj, stream* s, obj_sub_mesh* sub_mesh) { + bool tri_strip = sub_mesh->primitive_type == OBJ_PRIMITIVE_TRIANGLE_STRIP; + uint32_t* indices = force_malloc_s(uint32_t, sub_mesh->indices_count); switch (sub_mesh->index_format) { case OBJ_INDEX_U8: - for (int32_t i = 0; i < indices_count; i++) { + for (int32_t i = 0; i < sub_mesh->indices_count; i++) { uint8_t idx = io_read_uint8_t(s); - indices[i] = idx == 0xFF ? 0xFFFFFFFF : idx; + indices[i] = tri_strip && idx == 0xFF ? 0xFFFFFFFF : idx; } break; case OBJ_INDEX_U16: - for (int32_t i = 0; i < indices_count; i++) { + for (int32_t i = 0; i < sub_mesh->indices_count; i++) { uint16_t idx = io_read_uint16_t_stream_reverse_endianness(s); - indices[i] = idx == 0xFFFF ? 0xFFFFFFFF : idx; + indices[i] = tri_strip && idx == 0xFFFF ? 0xFFFFFFFF : idx; } break; case OBJ_INDEX_U32: - for (int32_t i = 0; i < indices_count; i++) + for (int32_t i = 0; i < sub_mesh->indices_count; i++) indices[i] = io_read_uint32_t_stream_reverse_endianness(s); break; } sub_mesh->indices = indices; - sub_mesh->indices_count = indices_count; } -static void obj_modern_write_index(obj* o, stream* s, bool is_x, - obj_sub_mesh* sub_mesh, int32_t* indices_count, f2_struct* oidx) { +static void obj_modern_write_index(obj* obj, stream* s, bool is_x, + obj_sub_mesh* sub_mesh, f2_struct* oidx) { int32_t size = 1; enrs_type type = ENRS_INVALID; switch (sub_mesh->index_format) { @@ -3498,10 +3500,9 @@ static void obj_modern_write_index(obj* o, stream* s, bool is_x, break; } io_align_write(s, 0x04); - *indices_count = _indices_count; } -static void obj_modern_read_model(obj* o, stream* s, ssize_t base_offset, +static void obj_modern_read_model(obj* obj, stream* s, ssize_t base_offset, uint32_t header_length, bool is_x, stream* s_oidx, stream* s_ovtx) { const size_t mesh_size = is_x ? 0x130 : 0xD8; const size_t sub_mesh_size = is_x ? 0x80 : 0x70; @@ -3512,51 +3513,47 @@ static void obj_modern_read_model(obj* o, stream* s, ssize_t base_offset, memset(&oh, 0, sizeof(obj_header)); if (!is_x) { io_read(s, 0, 0x08); - o->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); - oh.meshes_count = io_read_int32_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); + obj->meshes_count = io_read_int32_t_stream_reverse_endianness(s); oh.meshes_offset = io_read_offset_f2(s, header_length); - oh.materials_count = io_read_int32_t_stream_reverse_endianness(s); + obj->materials_count = io_read_int32_t_stream_reverse_endianness(s); oh.materials_offset = io_read_offset_f2(s, header_length); } else { io_read(s, 0, 0x08); - oh.meshes_count = io_read_int32_t_stream_reverse_endianness(s); - oh.materials_count = io_read_int32_t_stream_reverse_endianness(s); - o->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); - o->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); + obj->meshes_count = io_read_int32_t_stream_reverse_endianness(s); + obj->materials_count = io_read_int32_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); + obj->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); oh.meshes_offset = io_read_offset_x(s); oh.materials_offset = io_read_offset_x(s); io_read(s, 0, 0x10); - o->flags = io_read_uint8_t(s); + obj->flags = io_read_uint8_t(s); io_read(s, 0, 0x07); } io_read(s, 0, 0x28); if (oh.meshes_offset > 0) { - o->meshes = vector_empty(obj_mesh); - vector_obj_mesh_reserve(&o->meshes, oh.meshes_count); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh mesh; - memset(&mesh, 0, sizeof(obj_mesh)); + obj->meshes = force_malloc_s(obj_mesh, obj->meshes_count); + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; io_set_position(s, base_offset + oh.meshes_offset + mesh_size * i, SEEK_SET); obj_mesh_header mh; memset(&mh, 0, sizeof(obj_mesh_header)); io_read(s, 0, 0x04); - mesh.bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); - mesh.bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); - mesh.bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); - mesh.bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); - mh.sub_meshes_count = io_read_int32_t_stream_reverse_endianness(s); - mh.sub_meshes_offset = io_read_offset(s, 0, is_x); - if (mh.sub_meshes_offset && !is_x) - mh.sub_meshes_offset -= header_length; + mesh->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); + mesh->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); + mesh->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); + mesh->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); + mesh->sub_meshes_count = io_read_int32_t_stream_reverse_endianness(s); + mh.sub_meshes_offset = io_read_offset(s, header_length, is_x); mh.attrib_type = io_read_uint32_t_stream_reverse_endianness(s); mh.vertex_size = io_read_int32_t_stream_reverse_endianness(s); mh.vertex_count = io_read_int32_t_stream_reverse_endianness(s); @@ -3568,70 +3565,67 @@ static void obj_modern_read_model(obj* o, stream* s, ssize_t base_offset, for (int32_t j = 0; j < 20; j++) mh.attrib_offsets[j] = io_read_offset_x(s); - mesh.flags = io_read_int32_t_stream_reverse_endianness(s); + mesh->flags = io_read_int32_t_stream_reverse_endianness(s); mh.attrib_flags = io_read_uint32_t_stream_reverse_endianness(s); io_read(s, 0, 0x18); - io_read(s, &mesh.name, sizeof(mesh.name)); - mesh.name[sizeof(mesh.name) - 1] = 0; + io_read(s, &mesh->name, sizeof(mesh->name)); + mesh->name[sizeof(mesh->name) - 1] = 0; if (mh.sub_meshes_offset) { - mesh.sub_meshes = vector_empty(obj_sub_mesh); - vector_obj_sub_mesh_reserve(&mesh.sub_meshes, mh.sub_meshes_count); - for (int32_t j = 0; j < mh.sub_meshes_count; j++) { - obj_sub_mesh sub_mesh; - memset(&sub_mesh, 0, sizeof(obj_sub_mesh)); + mesh->sub_meshes = force_malloc_s(obj_sub_mesh, mesh->sub_meshes_count); + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; io_set_position(s, base_offset + mh.sub_meshes_offset + sub_mesh_size * j, SEEK_SET); obj_sub_mesh_header smh; memset(&smh, 0, sizeof(obj_sub_mesh_header)); io_read(s, 0, 0x04); - sub_mesh.bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.material_index = io_read_uint32_t_stream_reverse_endianness(s); - io_read(s, &sub_mesh.texcoord_indices, 0x08); - smh.bone_index_count = io_read_int32_t_stream_reverse_endianness(s); + sub_mesh->bounding_sphere.center.x = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_sphere.center.y = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_sphere.center.z = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_sphere.radius = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->material_index = io_read_uint32_t_stream_reverse_endianness(s); + io_read(s, &sub_mesh->texcoord_indices, 0x08); + sub_mesh->bone_indices_count = io_read_int32_t_stream_reverse_endianness(s); smh.bone_indices_offset = io_read_offset(s, header_length, is_x); - sub_mesh.bones_per_vertex = io_read_uint32_t_stream_reverse_endianness(s); - sub_mesh.primitive_type = io_read_uint32_t_stream_reverse_endianness(s); - sub_mesh.index_format = io_read_uint32_t_stream_reverse_endianness(s); - smh.indices_count = io_read_int32_t_stream_reverse_endianness(s); + sub_mesh->bones_per_vertex = io_read_uint32_t_stream_reverse_endianness(s); + sub_mesh->primitive_type = io_read_uint32_t_stream_reverse_endianness(s); + sub_mesh->index_format = io_read_uint32_t_stream_reverse_endianness(s); + sub_mesh->indices_count = io_read_int32_t_stream_reverse_endianness(s); smh.indices_offset = io_read_offset(s, 0, is_x); - sub_mesh.flags = io_read_uint32_t_stream_reverse_endianness(s); + sub_mesh->flags = io_read_uint32_t_stream_reverse_endianness(s); io_read(s, 0, 0x10); - sub_mesh.bounding_box.center.x = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_box.center.y = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_box.center.z = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_box.size.x = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_box.size.y = io_read_float_t_stream_reverse_endianness(s); - sub_mesh.bounding_box.size.z = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.center.x = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.center.y = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.center.z = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.size.x = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.size.y = io_read_float_t_stream_reverse_endianness(s); + sub_mesh->bounding_box.size.z = io_read_float_t_stream_reverse_endianness(s); io_read(s, 0, 0x04); - sub_mesh.index_offset = io_read_uint32_t_stream_reverse_endianness(s); + sub_mesh->indices_offset = io_read_uint32_t_stream_reverse_endianness(s); if (is_x) io_read(s, 0, 0x04); - if (sub_mesh.bones_per_vertex == 4 && smh.bone_indices_offset) { - uint16_t* bone_index = force_malloc_s(uint16_t, smh.bone_index_count); + if (sub_mesh->bones_per_vertex == 4 && smh.bone_indices_offset) { + sub_mesh->bone_indices = force_malloc_s(uint16_t, sub_mesh->bone_indices_count); io_set_position(s, base_offset + smh.bone_indices_offset, SEEK_SET); - for (int32_t k = 0; k < smh.bone_index_count; k++) - bone_index[k] = io_read_uint16_t_stream_reverse_endianness(s); - sub_mesh.bone_index = bone_index; - sub_mesh.bone_index_count = smh.bone_index_count; + io_read(s, sub_mesh->bone_indices, sub_mesh->bone_indices_count * sizeof(uint16_t)); + if (s->is_big_endian) { + uint16_t* bone_indices = sub_mesh->bone_indices; + for (int32_t k = 0; k < sub_mesh->bone_indices_count; k++) + bone_indices[k] = reverse_endianness_uint16_t(bone_indices[k]); + } } io_set_position(s_oidx, smh.indices_offset, SEEK_SET); - obj_modern_read_index(o, s_oidx, &sub_mesh, smh.indices_count); - - vector_obj_sub_mesh_push_back(&mesh.sub_meshes, &sub_mesh); + obj_modern_read_index(obj, s_oidx, sub_mesh); } } - obj_modern_read_vertex(o, s_ovtx, mh.attrib_offsets, &mesh, + obj_modern_read_vertex(obj, s_ovtx, mh.attrib_offsets, mesh, mh.attrib_flags, mh.vertex_count, mh.vertex_size); - vector_obj_mesh_push_back(&o->meshes, &mesh); } } @@ -3639,27 +3633,21 @@ static void obj_modern_read_model(obj* o, stream* s, ssize_t base_offset, obj_material_texture_enrs_table_init(); io_set_position(s, base_offset + oh.materials_offset, SEEK_SET); - o->materials = vector_empty(obj_material_parent); - vector_obj_material_parent_reserve(&o->materials, oh.materials_count); - for (int32_t i = 0; i < oh.materials_count; i++) { - obj_material_parent m; - io_read(s, &m, sizeof(obj_material_parent)); - if (s->is_big_endian) - enrs_apply(&obj_material_texture_enrs_table, &m); - vector_obj_material_parent_push_back(&o->materials, &m); - } + obj->materials = force_malloc_s(obj_material_data, obj->materials_count); + io_read(s, obj->materials, obj->materials_count * sizeof(obj_material_data)); + if (s->is_big_endian) + for (int32_t i = 0; i < obj->materials_count; i++) + enrs_apply(&obj_material_texture_enrs_table, &obj->materials[i]); } } -static void obj_modern_write_model(obj* o, stream* s, +static void obj_modern_write_model(obj* obj, stream* s, ssize_t base_offset, bool is_x, f2_struct* omdl) { const size_t mesh_size = is_x ? 0x130 : 0xD8; const size_t sub_mesh_size = is_x ? 0x80 : 0x70; - f2_struct oidx; - f2_struct ovtx; - memset(&oidx, 0, sizeof(f2_struct)); - memset(&ovtx, 0, sizeof(f2_struct)); + f2_struct* oidx = vector_f2_struct_reserve_back(&omdl->sub_structs); + f2_struct* ovtx = vector_f2_struct_reserve_back(&omdl->sub_structs); stream s_oidx; stream s_ovtx; @@ -3674,9 +3662,6 @@ static void obj_modern_write_model(obj* o, stream* s, obj_header oh; memset(&oh, 0, sizeof(obj_header)); - oh.meshes_count = (int32_t)(o->meshes.end - o->meshes.begin); - oh.materials_count = (int32_t)(o->materials.end - o->materials.begin); - if (!is_x) { ee = (enrs_entry){ 0, 1, 80, 1, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 10, ENRS_DWORD }); @@ -3692,27 +3677,25 @@ static void obj_modern_write_model(obj* o, stream* s, } if (!is_x) { - ee = (enrs_entry){ off, 1, 216, oh.meshes_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 216, obj->meshes_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 32, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(oh.meshes_count * 216LL); + off = (uint32_t)(obj->meshes_count * 216ULL); } else { - ee = (enrs_entry){ off, 5, 304, oh.meshes_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 5, 304, obj->meshes_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 6, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 20, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(oh.meshes_count * 304LL); + off = (uint32_t)(obj->meshes_count * 304ULL); } uint32_t total_sub_meshes = 0; - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; - total_sub_meshes += (uint32_t)(mesh->sub_meshes.end - mesh->sub_meshes.begin); - } + for (int32_t i = 0; i < obj->meshes_count; i++) + total_sub_meshes += obj->meshes[i].sub_meshes_count; if (!is_x) { ee = (enrs_entry){ off, 17, 112, total_sub_meshes, vector_empty(enrs_sub_entry) }; @@ -3734,7 +3717,7 @@ static void obj_modern_write_model(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(oh.meshes_count * 112LL); + off = (uint32_t)(obj->meshes_count * 112ULL); } else { ee = (enrs_entry){ off, 17, 128, total_sub_meshes, vector_empty(enrs_sub_entry) }; @@ -3756,34 +3739,38 @@ static void obj_modern_write_model(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(oh.meshes_count * 128LL); + off = (uint32_t)(obj->meshes_count * 128ULL); } - int32_t total_bone_index_count = 0; - for (obj_mesh* i = o->meshes.begin; i != o->meshes.end; i++) - for (obj_sub_mesh* j = i->sub_meshes.begin; j != i->sub_meshes.end; j++) - if (j->bones_per_vertex == 4) - total_bone_index_count += j->bone_index_count; + int32_t total_bone_indices_count = 0; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[i]; + if (sub_mesh->bones_per_vertex == 4) + total_bone_indices_count += sub_mesh->bone_indices_count; + } + } - ee = (enrs_entry){ off, 1, 2, total_bone_index_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 2, total_bone_indices_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(2 * (size_t)total_bone_index_count); + off = (uint32_t)(2 * (size_t)total_bone_indices_count); off = align_val(off, is_x ? 0x10 : 0x04); - if (oh.materials_count) { + if (obj->materials_count) { obj_material_texture_enrs_table_init(); enrs_entry* mte = &obj_material_texture_enrs_table.begin[0]; - ee = (enrs_entry){ off, 186, 1200, oh.materials_count, }; + ee = (enrs_entry){ off, 186, 1200, obj->materials_count, }; ee.offset = off; ee.count = mte->count; ee.size = mte->size; - ee.repeat_count = oh.materials_count; + ee.repeat_count = obj->materials_count; ee.sub = vector_empty(enrs_sub_entry); vector_enrs_sub_entry_insert_range(&ee.sub, 0, mte->sub.begin, mte->sub.end); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(oh.materials_count * oh.materials_count); + off = (uint32_t)(ee.size * ee.repeat_count); } if (!is_x) { @@ -3817,13 +3804,13 @@ static void obj_modern_write_model(obj* o, stream* s, } io_align_write(s, 0x10); - if (oh.meshes_count) { + if (obj->meshes_count) { oh.meshes_offset = io_get_position(s) - base_offset; - obj_mesh_header* mhs = force_malloc_s(obj_mesh_header, oh.meshes_count); - obj_sub_mesh_header** smhss = force_malloc_s(obj_sub_mesh_header*, oh.meshes_count); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + obj_mesh_header* mhs = force_malloc_s(obj_mesh_header, obj->meshes_count); + obj_sub_mesh_header** smhss = force_malloc_s(obj_sub_mesh_header*, obj->meshes_count); + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; io_write(s, 0, 0x04); io_write_float_t(s, 0.0f); @@ -3849,15 +3836,14 @@ static void obj_modern_write_model(obj* o, stream* s, io_write(s, 0, sizeof(mesh->name)); } - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; - mh->sub_meshes_count = (int32_t)(mesh->sub_meshes.end - mesh->sub_meshes.begin); mh->attrib_type = OBJ_VERTEX_ATTRIB_MODERN_STORAGE; - if (mh->sub_meshes_count) { + if (mesh->sub_meshes_count) { mh->sub_meshes_offset = io_get_position(s) - base_offset; - for (int32_t j = 0; j < mh->sub_meshes_count; j++) { + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { io_write(s, 0, 0x04); io_write_float_t(s, 0.0f); io_write_float_t(s, 0.0f); @@ -3888,47 +3874,43 @@ static void obj_modern_write_model(obj* o, stream* s, } } - obj_modern_write_vertex(o, &s_ovtx, is_x, mh->attrib_offsets, mesh, - &mh->attrib_flags, &mh->vertex_count, &mh->vertex_size, &ovtx); + obj_modern_write_vertex(obj, &s_ovtx, is_x, mh->attrib_offsets, mesh, + &mh->attrib_flags, &mh->vertex_count, &mh->vertex_size, ovtx); } - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; obj_sub_mesh_header* smhs = 0; - if (mh->sub_meshes_count) { - smhs = force_malloc_s(obj_sub_mesh_header, mh->sub_meshes_count); + if (mesh->sub_meshes_count) { + smhs = force_malloc_s(obj_sub_mesh_header, mesh->sub_meshes_count); smhss[i] = smhs; - for (int32_t j = 0; j < mh->sub_meshes_count; j++) { - obj_sub_mesh* sub_mesh = &mesh->sub_meshes.begin[j]; + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; obj_sub_mesh_header* smh = &smhs[j]; - if (sub_mesh->bones_per_vertex == 4 && sub_mesh->bone_index_count) { + if (sub_mesh->bones_per_vertex == 4 && sub_mesh->bone_indices_count) { smh->bone_indices_offset = io_get_position(s) - base_offset; - - smh->bone_index_count = sub_mesh->bone_index_count; - uint16_t* bone_index = sub_mesh->bone_index; - for (int32_t k = 0; k < smh->bone_index_count; k++) - io_write_uint16_t(s, bone_index[k]); + io_write(s, sub_mesh->bone_indices, sub_mesh->bone_indices_count * sizeof(uint16_t)); } smh->indices_offset = io_get_position(&s_oidx); - obj_modern_write_index(o, &s_oidx, is_x, sub_mesh, &smh->indices_count, &oidx); + obj_modern_write_index(obj, &s_oidx, is_x, sub_mesh, oidx); } } } io_align_write(s, is_x ? 0x10 : 0x04); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; obj_sub_mesh_header* smhs = smhss[i]; - if (mh->sub_meshes_count) { + if (mesh->sub_meshes_count) { io_position_push(s, base_offset + mh->sub_meshes_offset, SEEK_SET); - for (int32_t j = 0; j < mh->sub_meshes_count; j++) { - obj_sub_mesh* sub_mesh = &mesh->sub_meshes.begin[j]; + for (int32_t j = 0; j < mesh->sub_meshes_count; j++) { + obj_sub_mesh* sub_mesh = &mesh->sub_meshes[j]; obj_sub_mesh_header* smh = &smhs[j]; io_write(s, 0, 0x04); @@ -3938,12 +3920,12 @@ static void obj_modern_write_model(obj* o, stream* s, io_write_float_t(s, sub_mesh->bounding_sphere.radius); io_write_uint32_t(s, sub_mesh->material_index); io_write(s, &sub_mesh->texcoord_indices, 0x08); - io_write_int32_t(s, smh->bone_index_count); + io_write_int32_t(s, sub_mesh->bone_indices_count); io_write_offset(s, smh->bone_indices_offset, 0x20, is_x); io_write_uint32_t(s, sub_mesh->bones_per_vertex); io_write_uint32_t(s, sub_mesh->primitive_type); io_write_uint32_t(s, sub_mesh->index_format); - io_write_int32_t(s, smh->indices_count); + io_write_int32_t(s, sub_mesh->indices_count); io_write_offset(s, smh->indices_offset, 0, is_x); io_write_uint32_t(s, sub_mesh->flags); io_write(s, 0, 0x10); @@ -3970,7 +3952,7 @@ static void obj_modern_write_model(obj* o, stream* s, io_write_uint32_t(s, index_max); break; } - io_write_uint32_t(s, sub_mesh->index_offset); + io_write_uint32_t(s, sub_mesh->indices_offset); if (is_x) io_write(s, 0, 0x04); @@ -3981,8 +3963,8 @@ static void obj_modern_write_model(obj* o, stream* s, } io_position_push(s, base_offset + oh.meshes_offset, SEEK_SET); - for (int32_t i = 0; i < oh.meshes_count; i++) { - obj_mesh* mesh = &o->meshes.begin[i]; + for (int32_t i = 0; i < obj->meshes_count; i++) { + obj_mesh* mesh = &obj->meshes[i]; obj_mesh_header* mh = &mhs[i]; io_write(s, 0, 0x04); @@ -3990,7 +3972,7 @@ static void obj_modern_write_model(obj* o, stream* s, io_write_float_t(s, mesh->bounding_sphere.center.y); io_write_float_t(s, mesh->bounding_sphere.center.z); io_write_float_t(s, mesh->bounding_sphere.radius); - io_write_int32_t(s, mh->sub_meshes_count); + io_write_int32_t(s, mesh->sub_meshes_count); if (mh->sub_meshes_offset && !is_x) mh->sub_meshes_offset += 0x20; io_write_offset(s, mh->sub_meshes_offset, 0, is_x); @@ -4016,10 +3998,10 @@ static void obj_modern_write_model(obj* o, stream* s, free(smhss); } - if (oh.materials_count) { + if (obj->materials) { oh.materials_offset = io_get_position(s) - base_offset; - for (int32_t i = 0; i < oh.materials_count; i++) - io_write(s, &o->materials.begin[i], sizeof(obj_material_parent)); + for (int32_t i = 0; i < obj->materials_count; i++) + io_write(s, &obj->materials[i], sizeof(obj_material_data)); } io_align_write(s, 0x10); @@ -4027,28 +4009,28 @@ static void obj_modern_write_model(obj* o, stream* s, if (!is_x) { io_write_uint32_t(s, 0x10000); io_write_uint32_t(s, 0x00); - io_write_float_t(s, o->bounding_sphere.center.x); - io_write_float_t(s, o->bounding_sphere.center.y); - io_write_float_t(s, o->bounding_sphere.center.z); - io_write_float_t(s, o->bounding_sphere.radius); - io_write_int32_t(s, oh.meshes_count); + io_write_float_t(s, obj->bounding_sphere.center.x); + io_write_float_t(s, obj->bounding_sphere.center.y); + io_write_float_t(s, obj->bounding_sphere.center.z); + io_write_float_t(s, obj->bounding_sphere.radius); + io_write_int32_t(s, obj->meshes_count); io_write_offset_f2(s, oh.meshes_offset, 0x20); - io_write_int32_t(s, oh.materials_count); + io_write_int32_t(s, obj->materials_count); io_write_offset_f2(s, oh.materials_offset, 0x20); } else { io_write_uint32_t(s, 0x10000); io_write_uint32_t(s, 0x00); - io_write_int32_t(s, oh.meshes_count); - io_write_int32_t(s, oh.materials_count); - io_write_float_t(s, o->bounding_sphere.center.x); - io_write_float_t(s, o->bounding_sphere.center.y); - io_write_float_t(s, o->bounding_sphere.center.z); - io_write_float_t(s, o->bounding_sphere.radius); + io_write_int32_t(s, obj->meshes_count); + io_write_int32_t(s, obj->materials_count); + io_write_float_t(s, obj->bounding_sphere.center.x); + io_write_float_t(s, obj->bounding_sphere.center.y); + io_write_float_t(s, obj->bounding_sphere.center.z); + io_write_float_t(s, obj->bounding_sphere.radius); io_write_offset_x(s, oh.meshes_offset); io_write_offset_x(s, oh.materials_offset); io_write(s, 0, 0x10); - io_write_uint8_t(s, o->flags); + io_write_uint8_t(s, obj->flags); io_write(s, 0, 0x07); } io_position_pop(s); @@ -4057,30 +4039,28 @@ static void obj_modern_write_model(obj* o, stream* s, omdl->pof = pof; io_align_write(&s_oidx, 0x10); - io_mcopy(&s_oidx, &oidx.data, &oidx.length); + io_mcopy(&s_oidx, &oidx->data, &oidx->length); io_free(&s_oidx); - oidx.header.signature = reverse_endianness_uint32_t('OIDX'); - oidx.header.length = 0x20; - oidx.header.use_big_endian = false; - oidx.header.use_section_size = true; - vector_f2_struct_push_back(&omdl->sub_structs, &oidx); + oidx->header.signature = reverse_endianness_uint32_t('OIDX'); + oidx->header.length = 0x20; + oidx->header.use_big_endian = false; + oidx->header.use_section_size = true; io_align_write(&s_ovtx, 0x10); - io_mcopy(&s_ovtx, &ovtx.data, &ovtx.length); + io_mcopy(&s_ovtx, &ovtx->data, &ovtx->length); io_free(&s_ovtx); - ovtx.header.signature = reverse_endianness_uint32_t('OVTX'); - ovtx.header.length = 0x20; - ovtx.header.use_big_endian = false; - ovtx.header.use_section_size = true; - vector_f2_struct_push_back(&omdl->sub_structs, &ovtx); + ovtx->header.signature = reverse_endianness_uint32_t('OVTX'); + ovtx->header.length = 0x20; + ovtx->header.use_big_endian = false; + ovtx->header.use_section_size = true; } -static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, +static void obj_modern_read_skin(obj* obj, stream* s, ssize_t base_offset, uint32_t header_length, bool is_x) { - obj_skin* sk = &o->skin; - o->skin_init = true; + obj_skin* sk = &obj->skin; + obj->skin_init = true; io_set_position(s, base_offset, SEEK_SET); obj_skin_header sh; @@ -4090,7 +4070,7 @@ static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, sh.bone_matrices_offset = io_read_offset_f2(s, header_length); sh.bone_names_offset = io_read_offset_f2(s, header_length); sh.ex_data_offset = io_read_offset_f2(s, header_length); - sh.bone_count = io_read_int32_t_stream_reverse_endianness(s); + sk->bones_count = io_read_int32_t_stream_reverse_endianness(s); sh.bone_parent_ids_offset = io_read_offset_f2(s, header_length); io_read(s, 0, 0x0C); } @@ -4099,24 +4079,23 @@ static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, sh.bone_matrices_offset = io_read_offset_x(s); sh.bone_names_offset = io_read_offset_x(s); sh.ex_data_offset = io_read_offset_x(s); - sh.bone_count = io_read_int32_t_stream_reverse_endianness(s); + sk->bones_count = io_read_int32_t_stream_reverse_endianness(s); sh.bone_parent_ids_offset = io_read_offset_x(s); io_read(s, 0, 0x18); } if (sh.bone_ids_offset) { - sk->bones = vector_empty(obj_skin_bone); - vector_obj_skin_bone_reserve(&sk->bones, sh.bone_count); + sk->bones = force_malloc_s(obj_skin_bone, sk->bones_count); ssize_t* bone_names_offsets = 0; if (sh.bone_names_offset) { - bone_names_offsets = force_malloc_s(ssize_t, sh.bone_count); + bone_names_offsets = force_malloc_s(ssize_t, sk->bones_count); io_set_position(s, sh.bone_names_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < sh.bone_count; i++) + for (int32_t i = 0; i < sk->bones_count; i++) bone_names_offsets[i] = io_read_offset_f2(s, header_length); else - for (int32_t i = 0; i < sh.bone_count; i++) + for (int32_t i = 0; i < sk->bones_count; i++) bone_names_offsets[i] = io_read_offset_x(s); } @@ -4126,14 +4105,12 @@ static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, memset(&bone, 0, sizeof(obj_skin_bone)); io_set_position(s, sh.bone_ids_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) { - bone.id = io_read_uint32_t_stream_reverse_endianness(s); - vector_obj_skin_bone_push_back(&sk->bones, &bone); - } + for (int32_t i = 0; i < sk->bones_count; i++) + sk->bones[i].id = io_read_uint32_t_stream_reverse_endianness(s); if (sh.bone_matrices_offset) { io_set_position(s, sh.bone_matrices_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { mat4 mat; mat.row0.x = io_read_float_t_stream_reverse_endianness(s); mat.row0.y = io_read_float_t_stream_reverse_endianness(s); @@ -4151,19 +4128,20 @@ static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, mat.row3.y = io_read_float_t_stream_reverse_endianness(s); mat.row3.z = io_read_float_t_stream_reverse_endianness(s); mat.row3.w = io_read_float_t_stream_reverse_endianness(s); - mat4_transpose(&mat, &sk->bones.begin[i].inv_bind_pose_mat); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &sk->bones[i].inv_bind_pose_mat); } } if (sh.bone_names_offset) - for (int32_t i = 0; i < sh.bone_count; i++) + for (int32_t i = 0; i < sk->bones_count; i++) io_read_string_null_terminated_offset(s, - bone_names_offsets[i], &sk->bones.begin[i].name); + bone_names_offsets[i], &sk->bones[i].name); if (sh.bone_parent_ids_offset) { io_set_position(s, sh.bone_parent_ids_offset, SEEK_SET); - for (int32_t i = 0; i < sh.bone_count; i++) - sk->bones.begin[i].parent = io_read_uint32_t_stream_reverse_endianness(s); + for (int32_t i = 0; i < sk->bones_count; i++) + sk->bones[i].parent = io_read_uint32_t_stream_reverse_endianness(s); } } free(bone_names_offsets); @@ -4178,195 +4156,198 @@ static void obj_modern_read_skin(obj* o, stream* s, ssize_t base_offset, memset(&exh, 0, sizeof(obj_skin_ex_data_header)); if (!is_x) { exh.osage_count = io_read_int32_t_stream_reverse_endianness(s); - exh.osage_nodes_count = io_read_int32_t_stream_reverse_endianness(s); + ex->osage_nodes_count = io_read_int32_t_stream_reverse_endianness(s); io_read(s, 0, 0x04); exh.osage_nodes_offset = io_read_offset_f2(s, header_length); exh.osage_names_offset = io_read_offset_f2(s, header_length); exh.blocks_offset = io_read_offset_f2(s, header_length); - exh.strings_count = io_read_int32_t_stream_reverse_endianness(s); - exh.strings_offset = io_read_offset_f2(s, header_length); + exh.bone_names_count = io_read_int32_t_stream_reverse_endianness(s); + exh.bone_names_offset = io_read_offset_f2(s, header_length); exh.osage_sibling_infos_offset = io_read_offset_f2(s, header_length); exh.cloth_count = io_read_int32_t_stream_reverse_endianness(s); io_read(s, 0, 0x1C); } else { exh.osage_count = io_read_int32_t_stream_reverse_endianness(s); - exh.osage_nodes_count = io_read_int32_t_stream_reverse_endianness(s); + ex->osage_nodes_count = io_read_int32_t_stream_reverse_endianness(s); io_read(s, 0, 0x08); exh.osage_nodes_offset = io_read_offset_x(s); exh.osage_names_offset = io_read_offset_x(s); exh.blocks_offset = io_read_offset_x(s); - exh.strings_count = io_read_int32_t_stream_reverse_endianness(s); - exh.strings_offset = io_read_offset_x(s); + exh.bone_names_count = io_read_int32_t_stream_reverse_endianness(s); + exh.bone_names_offset = io_read_offset_x(s); exh.osage_sibling_infos_offset = io_read_offset_x(s); exh.cloth_count = io_read_int32_t_stream_reverse_endianness(s); io_read(s, 0, 0x04); io_read(s, 0, 0x38); } - vector_string string_set = vector_empty(string); - vector_string_reserve(&string_set, exh.strings_count); - if (exh.strings_offset) { - ssize_t* strings_offsets = force_malloc_s(ssize_t, exh.strings_count); - io_set_position(s, exh.strings_offset, SEEK_SET); + if (exh.bone_names_offset) { + vector_string bone_names = vector_empty(string); + vector_string_reserve(&bone_names, exh.bone_names_count); + ssize_t* strings_offsets = force_malloc_s(ssize_t, exh.bone_names_count); + io_set_position(s, exh.bone_names_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < exh.strings_count; i++) + for (int32_t i = 0; i < exh.bone_names_count; i++) strings_offsets[i] = io_read_offset_f2(s, header_length); else - for (int32_t i = 0; i < exh.strings_count; i++) + for (int32_t i = 0; i < exh.bone_names_count; i++) strings_offsets[i] = io_read_offset_x(s); - for (int32_t i = 0; i < exh.strings_count; i++) { - string str; - io_read_string_null_terminated_offset(s, strings_offsets[i], &str); - vector_string_push_back(&string_set, &str); + size_t buf_size = 0; + for (int32_t i = 0; i < exh.bone_names_count; i++) { + string* str = vector_string_reserve_back(&bone_names); + if (strings_offsets[i]) + io_read_string_null_terminated_offset(s, strings_offsets[i], str); + else + *str = string_empty; + buf_size += str->length + 1; } free(strings_offsets); + + ex->bone_names_buf = force_malloc(buf_size); + ex->bone_names = force_malloc_s(char*, buf_size + 1); + ex->bone_names_count = exh.bone_names_count; + + char* bone_names_buf = ex->bone_names_buf; + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < exh.bone_names_count; i++) { + string* str = &bone_names.begin[i]; + *bone_names_ptr++ = bone_names_buf; + memcpy(bone_names_buf, string_data(str), str->length); + bone_names_buf[str->length] = 0; + bone_names_buf += str->length + 1; + } + *bone_names_ptr = 0; + vector_string_free(&bone_names, string_free); + } + else { + ex->bone_names_buf = 0; + ex->bone_names = 0; + ex->bone_names_count = 0; } - ex->osage_nodes = vector_empty(obj_skin_osage_node); - vector_obj_skin_osage_node_reserve(&ex->osage_nodes, exh.osage_nodes_count); + char** bone_names = ex->bone_names; + if (!bone_names) + return; + if (exh.osage_nodes_offset) { - obj_skin_osage_node osage_node; - memset(&osage_node, 0, sizeof(obj_skin_osage_node)); + ex->osage_nodes = force_malloc_s(obj_skin_osage_node, ex->osage_nodes_count); io_set_position(s, exh.osage_nodes_offset, SEEK_SET); - for (int32_t i = 0; i < exh.osage_nodes_count; i++) { - int32_t name = io_read_uint32_t_stream_reverse_endianness(s); - if (name & 0x8000) - string_copy(&string_set.begin[name & 0x7FFF], &osage_node.name); - else - memset(&osage_node.name, 0, sizeof(string)); + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[i]; - osage_node.length = io_read_float_t_stream_reverse_endianness(s); + osage_node->name_index = io_read_uint32_t_stream_reverse_endianness(s); + osage_node->length = io_read_float_t_stream_reverse_endianness(s); io_read(s, 0, 0x04); - vector_obj_skin_osage_node_push_back(&ex->osage_nodes, &osage_node); } } if (exh.blocks_offset) { - int32_t blocks_count = 0; + ex->blocks_count = 0; io_set_position(s, exh.blocks_offset, SEEK_SET); if (!is_x) while (io_read_int32_t(s)) { io_read(s, 0, 0x04); - blocks_count++; + ex->blocks_count++; } else while (io_read_int64_t(s)) { io_read(s, 0, 0x08); - blocks_count++; + ex->blocks_count++; } - obj_skin_block_header* bhs = force_malloc_s(obj_skin_block_header, blocks_count); + obj_skin_block_header* bhs = force_malloc_s(obj_skin_block_header, ex->blocks_count); io_set_position(s, exh.blocks_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < blocks_count; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { bhs[i].block_signature_offset = io_read_offset_f2(s, header_length); bhs[i].block_offset = io_read_offset_f2(s, header_length); } else - for (int32_t i = 0; i < blocks_count; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { bhs[i].block_signature_offset = io_read_offset_x(s); bhs[i].block_offset = io_read_offset_x(s); } - obj_skin_block block; - memset(&block, 0, sizeof(obj_skin_block)); - - ex->blocks = vector_empty(obj_skin_block); - vector_obj_skin_block_reserve(&ex->blocks, blocks_count); - for (int32_t i = 0; i < blocks_count; i++) { - bool valid = false; + ex->blocks = force_malloc_s(obj_skin_osage_node, ex->blocks_count); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; char* block_signature = io_read_utf8_string_null_terminated_offset(s, bhs[i].block_signature_offset); - if (utf8_length(block_signature) == 3) { - valid = true; + if (utf8_length(block_signature) != 3) { + free(block_signature); + continue; + } - uint32_t signature = load_reverse_endianness_uint32_t(block_signature); - switch (signature) { - case 'CLS\0': - block.type = OBJ_SKIN_BLOCK_CLOTH; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_modern_read_skin_block_cloth(&block.cloth, s, - header_length, string_set.begin, is_x); - break; - case 'CNS\0': - block.type = OBJ_SKIN_BLOCK_CONSTRAINT; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_modern_read_skin_block_constraint(&block.constraint, s, - header_length, string_set.begin, is_x); - break; - case 'EXP\0': - block.type = OBJ_SKIN_BLOCK_EXPRESSION; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_modern_read_skin_block_expression(&block.expression, s, - header_length, string_set.begin, is_x); - break; - case 'MOT\0': - block.type = OBJ_SKIN_BLOCK_MOTION; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_modern_read_skin_block_motion(&block.motion, s, - header_length, string_set.begin, is_x); - break; - case 'OSG\0': - block.type = OBJ_SKIN_BLOCK_OSAGE; - io_set_position(s, bhs[i].block_offset, SEEK_SET); - obj_modern_read_skin_block_osage(&block.osage, s, - header_length, string_set.begin, is_x); - break; - default: - valid = false; - break; - } + uint32_t signature = load_reverse_endianness_uint32_t(block_signature); + switch (signature) { + case 'CLS\0': + block->type = OBJ_SKIN_BLOCK_CLOTH; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_modern_read_skin_block_cloth(&block->cloth, s, + header_length, bone_names, is_x); + break; + case 'CNS\0': + block->type = OBJ_SKIN_BLOCK_CONSTRAINT; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_modern_read_skin_block_constraint(&block->constraint, s, + header_length, bone_names, is_x); + break; + case 'EXP\0': + block->type = OBJ_SKIN_BLOCK_EXPRESSION; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_modern_read_skin_block_expression(&block->expression, s, + header_length, bone_names, is_x); + break; + case 'MOT\0': + block->type = OBJ_SKIN_BLOCK_MOTION; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_modern_read_skin_block_motion(&block->motion, s, + header_length, bone_names, is_x); + break; + case 'OSG\0': + block->type = OBJ_SKIN_BLOCK_OSAGE; + io_set_position(s, bhs[i].block_offset, SEEK_SET); + obj_modern_read_skin_block_osage(&block->osage, s, + header_length, bone_names, is_x); + break; + default: + break; } free(block_signature); - - if (valid) - vector_obj_skin_block_push_back(&ex->blocks, &block); } free(bhs); } - io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); - while (true) { - uint32_t bone_name_index = io_read_uint32_t_stream_reverse_endianness(s); - if (!bone_name_index) - break; + if (exh.osage_sibling_infos_offset) { + ex->osage_sibling_infos_count = 0; + io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); + while (io_read_uint32_t(s)) { + io_read(s, 0, 0x08); + ex->osage_sibling_infos_count++; + } - uint32_t sibling_name = io_read_uint32_t_stream_reverse_endianness(s); - float_t sibling_distance = io_read_float_t_stream_reverse_endianness(s); - - if (!(bone_name_index & 0x8000)) - continue; - - char* bone_name = string_data(&string_set.begin[bone_name_index & 0x7FFF]); - - obj_skin_osage_node* osage_node = 0; - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) - if (!strcmp(string_data(&i->name), bone_name)) { - string_free(&i->sibling_name); - if (sibling_name & 0x8000) - string_copy(&string_set.begin[sibling_name & 0x7FFF], &i->sibling_name); - else - memset(&i->sibling_name, 0, sizeof(string)); - - i->sibling_max_distance = sibling_distance; - break; - } + obj_skin_osage_sibling_info* osis = force_malloc_s( + obj_skin_osage_sibling_info, ex->osage_sibling_infos_count); + ex->osage_sibling_infos = osis; + io_set_position(s, exh.blocks_offset, SEEK_SET); + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { + osis[i].name_index = io_read_uint32_t_stream_reverse_endianness(s); + osis[i].sibling_name_index = io_read_uint32_t_stream_reverse_endianness(s); + osis[i].distance = io_read_float_t_stream_reverse_endianness(s); + } + io_set_position(s, exh.osage_sibling_infos_offset, SEEK_SET); } - - for (string* i = string_set.begin; i != string_set.end; i++) - string_free(i); - vector_string_free(&string_set); } } -static void obj_modern_write_skin(obj* o, stream* s, - ssize_t base_offset, bool is_x, f2_struct* oskn) { - obj_skin* sk = &o->skin; +static void obj_modern_write_skin(obj* obj, stream* s, + ssize_t base_offset, bool is_x, f2_struct* oskn) { + obj_skin* sk = &obj->skin; uint32_t off; vector_enrs_entry e = vector_empty(enrs_entry); @@ -4391,52 +4372,51 @@ static void obj_modern_write_skin(obj* o, stream* s, obj_skin_header sh; memset(&sh, 0, sizeof(obj_skin_header)); - sh.bone_count = (int32_t)(sk->bones.end - sk->bones.begin); - if (sh.bone_count) { - if (sh.bone_count % 4) { - ee = (enrs_entry){ off, 1, 4, sh.bone_count, vector_empty(enrs_sub_entry) }; + if (sk->bones_count) { + if (sk->bones_count % 4) { + ee = (enrs_entry){ off, 1, 4, sk->bones_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 4LL); + off = (uint32_t)(sk->bones_count * 4ULL); off = align_val(off, 0x10); - ee = (enrs_entry){ off, 1, 4, sh.bone_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 4, sk->bones_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 4LL); + off = (uint32_t)(sk->bones_count * 4ULL); } else { - ee = (enrs_entry){ off, 1, 4, sh.bone_count * 2, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 4, sk->bones_count * 2, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 2 * 4LL); + off = (uint32_t)(sk->bones_count * 2 * 4ULL); } off = align_val(off, 0x10); if (!is_x) { - ee = (enrs_entry){ off, 1, 4, sh.bone_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 4, sk->bones_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 4LL); + off = (uint32_t)(sk->bones_count * 4ULL); } else { - ee = (enrs_entry){ off, 1, 8, sh.bone_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 8, sk->bones_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 8LL); + off = (uint32_t)(sk->bones_count * 8ULL); } off = align_val(off, 0x10); - ee = (enrs_entry){ off, 1, 64, sh.bone_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 64, sk->bones_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 16, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(sh.bone_count * 64LL); + off = (uint32_t)(sk->bones_count * 64ULL); off = align_val(off, 0x10); } vector_string strings = vector_empty(string); vector_ssize_t string_offsets = vector_empty(ssize_t); - vector_string string_set = vector_empty(string); + vector_string bone_names = vector_empty(string); obj_skin_ex_data_header exh; memset(&exh, 0, sizeof(obj_skin_ex_data_header)); @@ -4449,119 +4429,154 @@ static void obj_modern_write_skin(obj* o, stream* s, ssize_t field_20 = 0; ssize_t field_24 = 0; ssize_t field_28 = 0; - int32_t blocks_count = 0; - int32_t expression_count = 0; + int32_t expressions_count = 0; int32_t motion_count = 0; int32_t motion_nodes_count = 0; if (sk->ex_data_init) { obj_skin_ex_data* ex = &sk->ex_data; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: { - obj_skin_block_cloth* cls = &i->cloth; - obj_skin_strings_push_back_check(&strings, string_data(&cls->mesh_name)); - obj_skin_strings_push_back_check(&strings, string_data(&cls->backface_mesh_name)); - for (obj_skin_block_cloth_field_1C* j = cls->field_1C.begin; j != cls->field_1C.end; j++) { - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_0.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_1.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_2.bone_name)); - obj_skin_strings_push_back_check(&strings, string_data(&j->sub_data_3.bone_name)); + obj_skin_block_cloth* cloth = &block->cloth; + obj_skin_strings_push_back_check(&strings, string_data(&cloth->mesh_name)); + obj_skin_strings_push_back_check(&strings, string_data(&cloth->backface_mesh_name)); + + for (uint32_t k = 0; k < cloth->count; k++) { + obj_skin_block_cloth_field_1C* sub = &cloth->field_1C[k]; + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_0.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_1.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_2.bone_name)); + obj_skin_strings_push_back_check(&strings, string_data(&sub->sub_data_3.bone_name)); } obj_skin_strings_push_back_check(&strings, "CLS"); } break; case OBJ_SKIN_BLOCK_CONSTRAINT: { - obj_skin_block_constraint* cns = &i->constraint; - obj_skin_strings_push_back_check(&strings, string_data(&cns->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&cns->base.name)); - obj_skin_strings_push_back_check(&strings, string_data(&cns->source_node_name)); - switch (cns->type) { + obj_skin_block_constraint* constraint = &block->constraint; + obj_skin_strings_push_back_check(&strings, string_data(&constraint->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, constraint->name_index); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->source_node_name)); + switch (constraint->type) { case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: obj_skin_strings_push_back_check(&strings, "Direction"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->direction.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->direction.up_vector.name)); break; case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: obj_skin_strings_push_back_check(&strings, "Distance"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->distance.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->distance.up_vector.name)); break; case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: obj_skin_strings_push_back_check(&strings, "Orientation"); break; case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: obj_skin_strings_push_back_check(&strings, "Position"); - obj_skin_strings_push_back_check(&strings, string_data(&cns->position.up_vector.name)); + obj_skin_strings_push_back_check(&strings, string_data(&constraint->position.up_vector.name)); break; } obj_skin_strings_push_back_check(&strings, "CNS"); - obj_skin_strings_push_back_check(&string_set, string_data(&cns->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, constraint->name_index); } break; case OBJ_SKIN_BLOCK_EXPRESSION: { - obj_skin_block_expression* exp = &i->expression; - for (int32_t j = 0; j < exp->expression_count; j++) - obj_skin_strings_push_back_check(&strings, string_data(&exp->expressions[j])); - obj_skin_strings_push_back_check(&strings, string_data(&exp->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&exp->base.name)); + obj_skin_block_expression* expression = &block->expression; + for (int32_t j = 0; j < expression->expressions_count; j++) + obj_skin_strings_push_back_check(&strings, string_data(&expression->expressions[j])); + obj_skin_strings_push_back_check(&strings, string_data(&expression->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, expression->name_index); obj_skin_strings_push_back_check(&strings, "EXP"); - obj_skin_strings_push_back_check(&string_set, string_data(&exp->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, expression->name_index); } break; case OBJ_SKIN_BLOCK_MOTION: { - obj_skin_block_motion* mot = &i->motion; - obj_skin_strings_push_back_check(&strings, string_data(&mot->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&mot->base.name)); - for (obj_skin_motion_node* j = mot->nodes.begin; j != mot->nodes.end; j++) - obj_skin_strings_push_back_check(&strings, string_data(&j->name)); + obj_skin_block_motion* motion = &block->motion; + obj_skin_strings_push_back_check(&strings, string_data(&motion->base.parent_name)); + obj_skin_strings_push_back_check(&strings, string_data(&motion->name)); + for (int32_t j = 0; j < motion->nodes_count; j++) + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, motion->nodes[j].name_index); obj_skin_strings_push_back_check(&strings, "MOT"); - if (!is_x) { - obj_skin_strings_push_back_check(&string_set, string_data(&mot->base.name)); - } - for (obj_skin_motion_node* j = mot->nodes.begin; j != mot->nodes.end; j++) - obj_skin_strings_push_back_check(&string_set, string_data(&j->name)); + if (!is_x) + obj_skin_strings_push_back_check(&bone_names, string_data(&motion->name)); + for (int32_t j = 0; j < motion->nodes_count; j++) + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, motion->nodes[j].name_index); } break; case OBJ_SKIN_BLOCK_OSAGE: { - obj_skin_block_osage* osg = &i->osage; - obj_skin_strings_push_back_check(&strings, string_data(&osg->base.parent_name)); - obj_skin_strings_push_back_check(&strings, string_data(&osg->base.name)); - obj_skin_strings_push_back_check(&strings, string_data(&osg->external_name)); - obj_skin_osage_node* osage_node = &ex->osage_nodes.begin[osg->start_index]; - for (int32_t j = 0; j < osg->count; j++) { - obj_skin_strings_push_back_check(&strings, string_data(&osage_node->name)); - obj_skin_strings_push_back_check(&strings, string_data(&osage_node->sibling_name)); + obj_skin_block_osage* osage = &block->osage; + obj_skin_strings_push_back_check(&strings, string_data(&osage->base.parent_name)); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage->name_index); + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage->external_name_index); + obj_skin_osage_node* osage_node = &ex->osage_nodes[osage->start_index]; + for (int32_t j = 0; j < osage->count; j++) { + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage_node->name_index); + + int32_t name_index = osage->name_index; + obj_skin_osage_sibling_info* osage_sibling_infos = ex->osage_sibling_infos; + for (int32_t k = 0; k < ex->osage_sibling_infos_count; k++) { + if (name_index == osage_sibling_infos->name_index) { + obj_skin_strings_push_back_check_by_index(&strings, + bone_names_ptr, osage_sibling_infos->sibling_name_index); + break; + } + osage_sibling_infos++; + } osage_node++; } obj_skin_strings_push_back_check(&strings, "OSG"); - obj_skin_strings_push_back_check(&string_set, string_data(&osg->external_name)); - osage_node = &ex->osage_nodes.begin[osg->start_index]; - for (int32_t j = 0; j < osg->count; j++) { - obj_skin_strings_push_back_check(&string_set, string_data(&osage_node->name)); - obj_skin_strings_push_back_check(&string_set, string_data(&osage_node->sibling_name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage->external_name_index); + osage_node = &ex->osage_nodes[osage->start_index]; + for (int32_t j = 0; j < osage->count; j++) { + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage_node->name_index); + + int32_t name_index = osage->name_index; + obj_skin_osage_sibling_info* osage_sibling_infos = ex->osage_sibling_infos; + for (int32_t k = 0; k < ex->osage_sibling_infos_count; k++) { + if (name_index == osage_sibling_infos->name_index) { + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage_sibling_infos->sibling_name_index); + break; + } + osage_sibling_infos++; + } osage_node++; } - obj_skin_strings_push_back_check(&string_set, string_data(&osg->base.name)); + obj_skin_strings_push_back_check_by_index(&bone_names, + bone_names_ptr, osage->name_index); } break; } - - exh.osage_nodes_count = (int32_t)(ex->osage_nodes.end - ex->osage_nodes.begin); + } exh.cloth_count = 0; exh.osage_count = 0; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type == OBJ_SKIN_BLOCK_CLOTH) exh.cloth_count++; - else if (i->type == OBJ_SKIN_BLOCK_EXPRESSION) - expression_count++; - else if (i->type == OBJ_SKIN_BLOCK_MOTION) { + else if (block->type == OBJ_SKIN_BLOCK_EXPRESSION) + expressions_count++; + else if (block->type == OBJ_SKIN_BLOCK_MOTION) { motion_count++; - motion_nodes_count += (int32_t)(i->motion.nodes.end - i->motion.nodes.begin); + motion_nodes_count += block->motion.nodes_count; } - else if (i->type == OBJ_SKIN_BLOCK_OSAGE) + else if (block->type == OBJ_SKIN_BLOCK_OSAGE) exh.osage_count++; + } - exh.strings_count = (int32_t)(string_set.end - string_set.begin); + exh.bone_names_count = (int32_t)(bone_names.end - bone_names.begin); } if (sk->ex_data_init) { @@ -4585,22 +4600,17 @@ static void obj_modern_write_skin(obj* o, stream* s, } off = align_val(off, 0x10); - if (exh.osage_nodes_count) { - ee = (enrs_entry){ off, 1, 12, exh.osage_nodes_count, vector_empty(enrs_sub_entry) }; + if (ex->osage_nodes_count) { + ee = (enrs_entry){ off, 1, 12, ex->osage_nodes_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.osage_nodes_count * 12LL); + off = (uint32_t)(ex->osage_nodes_count * 12ULL); off = align_val(off, 0x10); - int32_t osage_sibling_infos_count = 1; - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) - if (string_length(&i->sibling_name)) - osage_sibling_infos_count++; - - ee = (enrs_entry){ off, 1, 12, osage_sibling_infos_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 12, ex->osage_sibling_infos_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(osage_sibling_infos_count * 12LL); + off = (uint32_t)(ex->osage_sibling_infos_count * 12ULL); off = align_val(off, 0x10); } @@ -4610,44 +4620,43 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 4, count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(count * 4LL); + off = (uint32_t)(count * 4ULL); } else { ee = (enrs_entry){ off, 1, 8, count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(count * 8LL); + off = (uint32_t)(count * 8ULL); } off = align_val(off, 0x10); } if (!is_x) { - ee = (enrs_entry){ off, 1, 4, exh.strings_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 4, exh.bone_names_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.strings_count * 4LL); + off = (uint32_t)(exh.bone_names_count * 4ULL); } else { - ee = (enrs_entry){ off, 1, 8, exh.strings_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 8, exh.bone_names_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.strings_count * 8LL); + off = (uint32_t)(exh.bone_names_count * 8ULL); } off = align_val(off, 0x10); - blocks_count = (int32_t)(ex->blocks.end - ex->blocks.begin); - if (blocks_count > 0) { + if (ex->blocks_count > 0) { if (!is_x) { - ee = (enrs_entry){ off, 1, 8, blocks_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 8, ex->blocks_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(blocks_count * 8LL); + off = (uint32_t)(ex->blocks_count * 8ULL); } else { - ee = (enrs_entry){ off, 1, 16, blocks_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 16, ex->blocks_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 2, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(blocks_count * 16LL); + off = (uint32_t)(ex->blocks_count * 16ULL); } off = align_val(off, 0x10); @@ -4657,7 +4666,7 @@ static void obj_modern_write_skin(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 14, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.osage_count * 76LL); + off = (uint32_t)(exh.osage_count * 76ULL); } else { ee = (enrs_entry){ off, 4, 104, exh.osage_count, vector_empty(enrs_sub_entry) }; @@ -4666,27 +4675,27 @@ static void obj_modern_write_skin(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 4, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 8, 1, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.osage_count * 104LL); + off = (uint32_t)(exh.osage_count * 104ULL); } off = align_val(off, 0x10); } - if (expression_count) { + if (expressions_count) { if (!is_x) { - ee = (enrs_entry){ off, 1, 84, expression_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 1, 84, expressions_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 19, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(expression_count * 84LL); + off = (uint32_t)(expressions_count * 84ULL); } else { - ee = (enrs_entry){ off, 5, 136, expression_count, vector_empty(enrs_sub_entry) }; + ee = (enrs_entry){ off, 5, 136, expressions_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 9, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 9, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(expression_count * 136LL); + off = (uint32_t)(expressions_count * 136ULL); } off = align_val(off, 0x10); } @@ -4696,7 +4705,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 52, exh.cloth_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 13, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.cloth_count * 52LL); + off = (uint32_t)(exh.cloth_count * 52ULL); } else { ee = (enrs_entry){ off, 4, 88, exh.cloth_count, vector_empty(enrs_sub_entry) }; @@ -4705,18 +4714,19 @@ static void obj_modern_write_skin(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 6, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(exh.cloth_count * 88LL); + off = (uint32_t)(exh.cloth_count * 88ULL); } off = align_val(off, 0x10); } int32_t constraint_count = 0; obj_skin_block_constraint_type cns_type = OBJ_SKIN_BLOCK_CONSTRAINT_NONE; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_CONSTRAINT) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) continue; - if (cns_type == i->constraint.type) { + if (cns_type == block->constraint.type) { constraint_count++; continue; } @@ -4727,7 +4737,7 @@ static void obj_modern_write_skin(obj* o, stream* s, off = ee.size * ee.repeat_count; } - cns_type = i->constraint.type; + cns_type = block->constraint.type; if (!is_x) switch (cns_type) { case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: @@ -4806,7 +4816,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 56, motion_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 14, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(motion_count * 56LL); + off = (uint32_t)(motion_count * 56ULL); } else { ee = (enrs_entry){ off, 5, 80, motion_count, vector_empty(enrs_sub_entry) }; @@ -4816,7 +4826,7 @@ static void obj_modern_write_skin(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 2, ENRS_QWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(motion_count * 80LL); + off = (uint32_t)(motion_count * 80ULL); } off = align_val(off, 0x10); @@ -4824,13 +4834,13 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 64, motion_nodes_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 16, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(motion_nodes_count * 64LL); + off = (uint32_t)(motion_nodes_count * 64ULL); off = align_val(off, 0x10); ee = (enrs_entry){ off, 1, 4, motion_nodes_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(motion_nodes_count * 4LL); + off = (uint32_t)(motion_nodes_count * 4ULL); off = align_val(off, 0x10); } @@ -4840,25 +4850,25 @@ static void obj_modern_write_skin(obj* o, stream* s, int32_t field_20_count = 0; int32_t field_24_count = 0; int32_t field_28_count = 0; - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type == OBJ_SKIN_BLOCK_CLOTH) { for (int32_t j = 0; j < 32; j++) - if (i->cloth.field_10 & (1 << j)) + if (block->cloth.field_10 & (1 << j)) field_18_count++; - field_1C_count += (int32_t)(i->cloth.field_1C.end - i->cloth.field_1C.begin); - field_20_count += (int32_t)(i->cloth.field_20.end - i->cloth.field_20.begin); - field_24_count += (int32_t)(i->cloth.field_24.end - i->cloth.field_24.begin); - field_24_count++; - field_28_count += (int32_t)(i->cloth.field_28.end - i->cloth.field_28.begin); - field_28_count++; + field_1C_count += block->cloth.field_1C ? block->cloth.count : 0; + field_20_count += block->cloth.field_20 ? block->cloth.count : 0; + field_24_count += block->cloth.field_24 ? block->cloth.field_24_count + 1 : 0; + field_28_count += block->cloth.field_28 ? block->cloth.field_28_count + 1 : 0; } + } if (field_18_count) { ee = (enrs_entry){ off, 1, 64, field_18_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 16, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_18_count * 64LL); + off = (uint32_t)(field_18_count * 64ULL); off = align_val(off, 0x10); } @@ -4867,7 +4877,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 104, field_1C_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 26, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_1C_count * 104LL); + off = (uint32_t)(field_1C_count * 104ULL); } else { ee = (enrs_entry){ off, 9, 136, field_1C_count, vector_empty(enrs_sub_entry) }; @@ -4881,7 +4891,7 @@ static void obj_modern_write_skin(obj* o, stream* s, vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 4, 1, ENRS_QWORD }); vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_1C_count * 136LL); + off = (uint32_t)(field_1C_count * 136ULL); } off = align_val(off, 0x10); } @@ -4890,7 +4900,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 440, field_20_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 110, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_20_count * 440LL); + off = (uint32_t)(field_20_count * 440ULL); off = align_val(off, 0x10); } @@ -4898,7 +4908,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 2, field_24_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_24_count * 2LL); + off = (uint32_t)(field_24_count * 2ULL); off = align_val(off, 0x10); } @@ -4906,7 +4916,7 @@ static void obj_modern_write_skin(obj* o, stream* s, ee = (enrs_entry){ off, 1, 2, field_28_count, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 1, ENRS_WORD }); vector_enrs_entry_push_back(&e, &ee); - off = (uint32_t)(field_28_count * 2LL); + off = (uint32_t)(field_28_count * 2ULL); off = align_val(off, 0x10); } } @@ -4933,34 +4943,35 @@ static void obj_modern_write_skin(obj* o, stream* s, } io_align_write(s, 0x10); - if (sh.bone_count) { + if (sk->bones_count) { sh.bone_ids_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) - io_write_int32_t(s, sk->bones.begin[i].id); + for (int32_t i = 0; i < sk->bones_count; i++) + io_write_int32_t(s, sk->bones[i].id); io_align_write(s, 0x10); sh.bone_parent_ids_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) - io_write_int32_t(s, sk->bones.begin[i].parent); + for (int32_t i = 0; i < sk->bones_count; i++) + io_write_int32_t(s, sk->bones[i].parent); io_align_write(s, 0x10); sh.bone_names_offset = io_get_position(s); if (!is_x) - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - obj_skin_strings_push_back_check(&strings, string_data(&sk->bones.begin[i].name)); + obj_skin_strings_push_back_check(&strings, string_data(&sk->bones[i].name)); } else - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { io_write_offset_x_pof_add(s, 0, &pof); - obj_skin_strings_push_back_check(&strings, string_data(&sk->bones.begin[i].name)); + obj_skin_strings_push_back_check(&strings, string_data(&sk->bones[i].name)); } io_align_write(s, 0x10); sh.bone_matrices_offset = io_get_position(s); - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { mat4 mat; - mat4_transpose(&sk->bones.begin[i].inv_bind_pose_mat, &mat); + mat4u_to_mat4(&sk->bones[i].inv_bind_pose_mat, &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -5014,9 +5025,9 @@ static void obj_modern_write_skin(obj* o, stream* s, } io_align_write(s, 0x10); - if (exh.osage_nodes_count) { + if (ex->osage_nodes_count) { exh.osage_nodes_offset = io_get_position(s); - for (int32_t i = 0; i < exh.osage_nodes_count; i++) { + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -5024,10 +5035,7 @@ static void obj_modern_write_skin(obj* o, stream* s, io_align_write(s, 0x10); exh.osage_sibling_infos_offset = io_get_position(s); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - if (!string_length(&i->sibling_name)) - continue; - + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { io_write_int32_t(s, 0); io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -5057,19 +5065,19 @@ static void obj_modern_write_skin(obj* o, stream* s, io_align_write(s, 0x10); } - exh.strings_offset = io_get_position(s); + exh.bone_names_offset = io_get_position(s); if (!is_x) - for (string* i = string_set.begin; i != string_set.end; i++) + for (string* i = bone_names.begin; i != bone_names.end; i++) io_write_offset_f2_pof_add(s, 0, 0x20, &pof); else - for (string* i = string_set.begin; i != string_set.end; i++) + for (string* i = bone_names.begin; i != bone_names.end; i++) io_write_offset_x_pof_add(s, 0, &pof); io_align_write(s, 0x10); - if (blocks_count > 0) { + if (ex->blocks_count > 0) { exh.blocks_offset = io_get_position(s); if (!is_x) { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { io_write_offset_f2_pof_add(s, 0, 0x20, &pof); io_write_offset_f2_pof_add(s, 0, 0x20, &pof); } @@ -5077,7 +5085,7 @@ static void obj_modern_write_skin(obj* o, stream* s, io_write_offset_f2(s, 0, 0x20); } else { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { + for (int32_t i = 0; i < ex->blocks_count; i++) { io_write_offset_x_pof_add(s, 0, &pof); io_write_offset_x_pof_add(s, 0, &pof); } @@ -5086,320 +5094,366 @@ static void obj_modern_write_skin(obj* o, stream* s, } io_align_write(s, 0x10); - bhs = force_malloc_s(obj_skin_block_header, blocks_count); + bhs = force_malloc_s(obj_skin_block_header, ex->blocks_count); if (!is_x) - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_OSAGE: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x24); - io_write(s, 0, 0x24); - break; - } + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x24); + io_write(s, 0, 0x24); + } else - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_OSAGE: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) + continue; + + obj_skin_block_osage* osage = &block->osage; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x28); + if (osage->motion_node_name.length) { + io_write(s, 0, 0x18); io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x28); - if (string_length(&i->osage.motion_node_name)) { - io_write(s, 0, 0x18); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x18); - } - else - io_write(s, 0, 0x38); - break; + io_write(s, 0, 0x18); } + else + io_write(s, 0, 0x38); + } io_align_write(s, 0x10); if (!is_x) - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_EXPRESSION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_EXPRESSION) + continue; + + obj_skin_block_expression* expression = &block->expression; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x24); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x04); + + for (int32_t j = 0; j < expression->expressions_count && j < 9; j++) io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x24); + + for (int32_t j = expression->expressions_count; j < 9; j++) + io_write(s, 0, 0x04); + } + else + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_EXPRESSION) + continue; + obj_skin_block_expression* expression = &block->expression; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x28); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x08); + + for (int32_t j = 0; j < expression->expressions_count && j < 9; j++) + io_write_offset_x_pof_add(s, 0, &pof); + + for (int32_t j = expression->expressions_count; j < 9; j++) + io_write(s, 0, 0x08); + } + io_align_write(s, 0x10); + + if (!is_x) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x10); + + if (cloth->field_10) io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + else io_write(s, 0, 0x04); - for (int32_t j = 0; j < i->expression.expression_count && j < 9; j++) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - - for (int32_t j = i->expression.expression_count; j < 9; j++) - io_write(s, 0, 0x04); - break; + if (cloth->count) { + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); } - else - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_EXPRESSION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x28); - io_write_offset_x_pof_add(s, 0, &pof); + else io_write(s, 0, 0x08); - for (int32_t j = 0; j < i->expression.expression_count && j < 9; j++) - io_write_offset_x_pof_add(s, 0, &pof); + if (cloth->field_24_count) + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + else + io_write(s, 0, 0x04); - for (int32_t j = i->expression.expression_count; j < 9; j++) - io_write(s, 0, 0x08); - break; + if (cloth->field_28_count) + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + else + io_write(s, 0, 0x04); + + io_write(s, 0, 0x08); + } + else + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_x_pof_add(s, 0, &pof); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x10); + + if (cloth->field_10) + io_write_offset_x_pof_add(s, 0, &pof); + else + io_write(s, 0, 0x08); + + if (cloth->count) { + io_write_offset_x_pof_add(s, 0, &pof); + io_write_offset_x_pof_add(s, 0, &pof); } + else + io_write(s, 0, 0x10); + + if (cloth->field_24_count) + io_write_offset_x_pof_add(s, 0, &pof); + else + io_write(s, 0, 0x08); + + if (cloth->field_28_count) + io_write_offset_x_pof_add(s, 0, &pof); + else + io_write(s, 0, 0x08); + + io_write(s, 0, 0x10); + } io_align_write(s, 0x10); if (!is_x) - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CLOTH: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x24); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x04); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + switch (block->constraint.type) { + case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: + io_write(s, 0, 0x20); io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x10); - - if (i->cloth.field_10) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - else - io_write(s, 0, 0x04); - - if (i->cloth.field_1C.end - i->cloth.field_1C.begin) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - else - io_write(s, 0, 0x04); - - if (i->cloth.field_20.end - i->cloth.field_20.begin) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - else - io_write(s, 0, 0x04); - - if (i->cloth.field_24.end - i->cloth.field_24.begin) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - else - io_write(s, 0, 0x04); - - if (i->cloth.field_28.end - i->cloth.field_28.begin) - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - else - io_write(s, 0, 0x04); - - io_write(s, 0, 0x08); + io_write(s, 0, 0x18); break; - } - else - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CLOTH: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_x_pof_add(s, 0, &pof); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x10); - - if (i->cloth.field_10) - io_write_offset_x_pof_add(s, 0, &pof); - else - io_write(s, 0, 0x08); - - if (i->cloth.field_1C.end - i->cloth.field_1C.begin) - io_write_offset_x_pof_add(s, 0, &pof); - else - io_write(s, 0, 0x08); - - if (i->cloth.field_20.end - i->cloth.field_20.begin) - io_write_offset_x_pof_add(s, 0, &pof); - else - io_write(s, 0, 0x08); - - if (i->cloth.field_24.end - i->cloth.field_24.begin) - io_write_offset_x_pof_add(s, 0, &pof); - else - io_write(s, 0, 0x08); - - if (i->cloth.field_28.end - i->cloth.field_28.begin) - io_write_offset_x_pof_add(s, 0, &pof); - else - io_write(s, 0, 0x08); - - io_write(s, 0, 0x10); - break; - } - io_align_write(s, 0x10); - - if (!is_x) - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CONSTRAINT: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x24); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: + io_write(s, 0, 0x20); io_write_offset_f2_pof_add(s, 0, 0x20, &pof); io_write(s, 0, 0x04); + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: + io_write(s, 0, 0x0C); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: + io_write(s, 0, 0x20); io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - switch (i->constraint.type) { - case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: - io_write(s, 0, 0x20); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x18); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: - io_write(s, 0, 0x20); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x04); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: - io_write(s, 0, 0x0C); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: - io_write(s, 0, 0x20); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - break; - } + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); break; } + } else - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_CONSTRAINT: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x28); + io_write_offset_x_pof_add(s, 0, &pof); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x08); + io_write_offset_x_pof_add(s, 0, &pof); + switch (block->constraint.type) { + case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: + io_write(s, 0, 0x20); io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x28); + io_write(s, 0, 0x18); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: + io_write(s, 0, 0x20); io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x04); + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); + io_write(s, 0, 0x04); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: + io_write(s, 0, 0x0C); + io_write(s, 0, 0x04); + break; + case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: + io_write(s, 0, 0x20); io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x08); - io_write_offset_x_pof_add(s, 0, &pof); - switch (i->constraint.type) { - case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: - io_write(s, 0, 0x20); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x18); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE: - io_write(s, 0, 0x20); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x04); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - io_write(s, 0, 0x04); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION: - io_write(s, 0, 0x0C); - io_write(s, 0, 0x04); - break; - case OBJ_SKIN_BLOCK_CONSTRAINT_POSITION: - io_write(s, 0, 0x20); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x14); - io_write(s, 0, 0x14); - break; - } + io_write(s, 0, 0x14); + io_write(s, 0, 0x14); break; } + } io_align_write(s, 0x10); if (!is_x) - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_MOTION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x24); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write(s, 0, 0x04); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - io_write_offset_f2_pof_add(s, 0, 0x20, &pof); - break; - } + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x24); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write(s, 0, 0x04); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + io_write_offset_f2_pof_add(s, 0, 0x20, &pof); + } else - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { - case OBJ_SKIN_BLOCK_MOTION: - bhs[i - ex->blocks.begin].block_offset = io_get_position(s); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x28); - io_write_offset_x_pof_add(s, 0, &pof); - io_write(s, 0, 0x08); - io_write_offset_x_pof_add(s, 0, &pof); - io_write_offset_x_pof_add(s, 0, &pof); - break; - } + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + bhs[i].block_offset = io_get_position(s); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x28); + io_write_offset_x_pof_add(s, 0, &pof); + io_write(s, 0, 0x08); + io_write_offset_x_pof_add(s, 0, &pof); + io_write_offset_x_pof_add(s, 0, &pof); + } io_align_write(s, 0x10); if (motion_count) { motion_block_node_mats = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_MOTION) - io_write(s, 0, (i->motion.nodes.end - i->motion.nodes.begin) * sizeof(mat4)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + obj_skin_block_motion* motion = &block->motion; + io_write(s, 0, motion->nodes_count * sizeof(mat4)); + } io_align_write(s, 0x10); motion_block_node_name_offset = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_MOTION) - io_write(s, 0, (i->motion.nodes.end - i->motion.nodes.begin) * sizeof(uint32_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) + continue; + + obj_skin_block_motion* motion = &block->motion; + io_write(s, 0, motion->nodes_count * sizeof(uint32_t)); + } io_align_write(s, 0x10); } if (exh.cloth_count) { field_18 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - for (int32_t j = 0; j < 32; j++) - if (i->cloth.field_10 & (1 << j)) - io_write(s, 0, sizeof(mat4)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + for (int32_t j = 0; j < 32; j++) + if (cloth->field_10 & (1 << j)) + io_write(s, 0, sizeof(mat4)); + } io_align_write(s, 0x10); field_1C = io_get_position(s); - if (!is_x) { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, (10 * sizeof(int32_t) - + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) - * (i->cloth.field_1C.end - i->cloth.field_1C.begin)); - } - else { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, (10 * sizeof(int32_t) - + 4 * (sizeof(int64_t) + 4 * sizeof(int32_t))) - * (i->cloth.field_1C.end - i->cloth.field_1C.begin)); - } + if (!is_x) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, (10 * sizeof(int32_t) + + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * cloth->count); + } + else + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, (10 * sizeof(int32_t) + 4 * (sizeof(int64_t) + + 4 * sizeof(int32_t))) * cloth->count); + } io_align_write(s, 0x10); field_20 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, 10 * (11 * sizeof(int32_t)) - * (i->cloth.field_20.end - i->cloth.field_20.begin)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, 10 * (11 * sizeof(int32_t)) * cloth->count); + } io_align_write(s, 0x10); field_24 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, sizeof(uint16_t) + (i->cloth.field_24.end - - i->cloth.field_24.begin) * sizeof(uint16_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, sizeof(uint16_t) + cloth->field_24_count * sizeof(uint16_t)); + } io_align_write(s, 0x10); field_28 = io_get_position(s); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_CLOTH) - io_write(s, 0, sizeof(uint16_t) + (i->cloth.field_28.end - - i->cloth.field_28.begin) * sizeof(uint16_t)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) + continue; + + obj_skin_block_cloth* cloth = &block->cloth; + io_write(s, 0, sizeof(uint16_t) + cloth->field_28_count * sizeof(uint16_t)); + } io_align_write(s, 0x10); } } } - if (sh.bone_count || sk->ex_data_init) { + if (sk->bones || sk->ex_data_init) { for (string* i = strings.begin; i != &strings.end[-1]; i++) { char* i_str = string_data(i); for (string* j = i + 1; j != strings.end; j++) - if (strcmp(i_str, string_data(j)) > 0) { + if (str_utils_compare(i_str, string_data(j)) > 0) { string temp = *i; *i = *j; *j = temp; @@ -5407,9 +5461,11 @@ static void obj_modern_write_skin(obj* o, stream* s, } } + vector_ssize_t_reserve(&string_offsets, strings.end - strings.begin); + for (string* i = strings.begin; i != strings.end; i++) { ssize_t off = io_get_position(s); - io_write(s, string_data(i), string_length(i) + 1); + io_write_string_null_terminated(s, i); vector_ssize_t_push_back(&string_offsets, &off); } } @@ -5419,38 +5475,20 @@ static void obj_modern_write_skin(obj* o, stream* s, if (sk->ex_data_init) { obj_skin_ex_data* ex = &sk->ex_data; - size_t cls_offset = 0; - size_t cns_offset = 0; - size_t exp_offset = 0; - size_t mot_offset = 0; - size_t osg_offset = 0; - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "CLS")) - cls_offset = string_offsets.begin[i - strings.begin]; + ssize_t cls_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "CLS"); + ssize_t cns_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "CNS"); + ssize_t exp_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "EXP"); + ssize_t mot_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "MOT"); + ssize_t osg_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, "OSG"); - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "CNS")) - cns_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "EXP")) - exp_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "MOT")) - mot_offset = string_offsets.begin[i - strings.begin]; - - for (string* i = strings.begin; i != strings.end; i++) - if (!strcmp(string_data(i), "OSG")) - osg_offset = string_offsets.begin[i - strings.begin]; - - if (blocks_count > 0) { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_CLOTH) + if (ex->blocks_count > 0) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CLOTH) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_modern_write_skin_block_cloth(&i->cloth, s, &strings, &string_offsets, + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_modern_write_skin_block_cloth(&block->cloth, s, &strings, &string_offsets, is_x, &field_18, &field_1C, &field_20, &field_24, &field_28); io_position_pop(s); } @@ -5465,113 +5503,129 @@ static void obj_modern_write_skin(obj* o, stream* s, constraint_type_name_offsets[3] = obj_skin_strings_get_string_offset(&strings, &string_offsets, "Position"); - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_CONSTRAINT) + char** bone_names_ptr = ex->bone_names; + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_CONSTRAINT) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_modern_write_skin_block_constraint(&i->constraint, - s, &strings, &string_offsets, is_x, constraint_type_name_offsets); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_modern_write_skin_block_constraint(&block->constraint, + s, &strings, &string_offsets, bone_names_ptr, is_x, constraint_type_name_offsets); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_EXPRESSION) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_EXPRESSION) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_modern_write_skin_block_expression(&i->expression, - s, &strings, &string_offsets, is_x); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_modern_write_skin_block_expression(&block->expression, + s, &strings, &string_offsets, bone_names_ptr, is_x); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_MOTION) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_MOTION) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_modern_write_skin_block_motion(&i->motion, - s, &strings, &string_offsets, is_x, &string_set, + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_modern_write_skin_block_motion(&block->motion, + s, &strings, &string_offsets, is_x, bone_names_ptr, &motion_block_node_name_offset, &motion_block_node_mats); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) { - if (i->type != OBJ_SKIN_BLOCK_OSAGE) + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type != OBJ_SKIN_BLOCK_OSAGE) continue; - io_position_push(s, bhs[i - ex->blocks.begin].block_offset, SEEK_SET); - obj_modern_write_skin_block_osage(&i->osage, - s, &strings, &string_offsets, is_x, &string_set); + io_position_push(s, bhs[i].block_offset, SEEK_SET); + obj_modern_write_skin_block_osage(&block->osage, + s, &strings, &string_offsets, is_x); io_position_pop(s); } - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - if (i->type == OBJ_SKIN_BLOCK_OSAGE) - obj_skin_strings_push_back_check(&osage_names, string_data(&i->osage.external_name)); - else if (i->type == OBJ_SKIN_BLOCK_CLOTH) - obj_skin_strings_push_back_check(&osage_names, string_data(&i->cloth.mesh_name)); + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + if (block->type == OBJ_SKIN_BLOCK_CLOTH) { + obj_skin_block_cloth* cloth = &block->cloth; + obj_skin_strings_push_back_check(&osage_names, string_data(&cloth->mesh_name)); + } + else if (block->type == OBJ_SKIN_BLOCK_OSAGE) { + obj_skin_block_osage* osage = &block->osage; + obj_skin_strings_push_back_check_by_index(&osage_names, + bone_names_ptr, osage->external_name_index); + } + } io_position_push(s, exh.blocks_offset, SEEK_SET); if (!is_x) { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: io_write_offset_f2(s, cls_offset, 0x20); - io_write_offset_f2(s, bhs[i - ex->blocks.begin].block_offset, 0x20); + io_write_offset_f2(s, bhs[i].block_offset, 0x20); break; case OBJ_SKIN_BLOCK_CONSTRAINT: io_write_offset_f2(s, cns_offset, 0x20); - io_write_offset_f2(s, bhs[i - ex->blocks.begin].block_offset, 0x20); + io_write_offset_f2(s, bhs[i].block_offset, 0x20); break; case OBJ_SKIN_BLOCK_EXPRESSION: io_write_offset_f2(s, exp_offset, 0x20); - io_write_offset_f2(s, bhs[i - ex->blocks.begin].block_offset, 0x20); + io_write_offset_f2(s, bhs[i].block_offset, 0x20); break; case OBJ_SKIN_BLOCK_MOTION: io_write_offset_f2(s, mot_offset, 0x20); - io_write_offset_f2(s, bhs[i - ex->blocks.begin].block_offset, 0x20); + io_write_offset_f2(s, bhs[i].block_offset, 0x20); break; case OBJ_SKIN_BLOCK_OSAGE: io_write_offset_f2(s, osg_offset, 0x20); - io_write_offset_f2(s, bhs[i - ex->blocks.begin].block_offset, 0x20); + io_write_offset_f2(s, bhs[i].block_offset, 0x20); break; default: io_write_offset_f2(s, 0, 0); io_write_offset_f2(s, 0, 0); break; } + } io_write_offset_f2(s, 0, 0); io_write_offset_f2(s, 0, 0); } else { - for (obj_skin_block* i = ex->blocks.begin; i != ex->blocks.end; i++) - switch (i->type) { + for (int32_t i = 0; i < ex->blocks_count; i++) { + obj_skin_block* block = &ex->blocks[i]; + switch (block->type) { case OBJ_SKIN_BLOCK_CLOTH: io_write_offset_x(s, cls_offset); - io_write_offset_x(s, bhs[i - ex->blocks.begin].block_offset); + io_write_offset_x(s, bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_CONSTRAINT: io_write_offset_x(s, cns_offset); - io_write_offset_x(s, bhs[i - ex->blocks.begin].block_offset); + io_write_offset_x(s, bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_EXPRESSION: io_write_offset_x(s, exp_offset); - io_write_offset_x(s, bhs[i - ex->blocks.begin].block_offset); + io_write_offset_x(s, bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_MOTION: io_write_offset_x(s, mot_offset); - io_write_offset_x(s, bhs[i - ex->blocks.begin].block_offset); + io_write_offset_x(s, bhs[i].block_offset); break; case OBJ_SKIN_BLOCK_OSAGE: io_write_offset_x(s, osg_offset); - io_write_offset_x(s, bhs[i - ex->blocks.begin].block_offset); + io_write_offset_x(s, bhs[i].block_offset); break; default: io_write_offset_x(s, 0); io_write_offset_x(s, 0); break; } + } io_write_offset_x(s, 0); io_write_offset_x(s, 0); } @@ -5580,18 +5634,18 @@ static void obj_modern_write_skin(obj* o, stream* s, } } - if (sh.bone_count) { + if (sk->bones) { io_position_push(s, sh.bone_names_offset, SEEK_SET); if (!is_x) - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, - &string_offsets, string_data(&sk->bones.begin[i].name)); + &string_offsets, string_data(&sk->bones[i].name)); io_write_offset_f2(s, str_offset, 0x20); } else - for (int32_t i = 0; i < sh.bone_count; i++) { + for (int32_t i = 0; i < sk->bones_count; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, - &string_offsets, string_data(&sk->bones.begin[i].name)); + &string_offsets, string_data(&sk->bones[i].name)); io_write_offset_x(s, str_offset); } io_position_pop(s); @@ -5600,42 +5654,37 @@ static void obj_modern_write_skin(obj* o, stream* s, if (sk->ex_data_init) { obj_skin_ex_data* ex = &sk->ex_data; - if (blocks_count > 0) { - io_position_push(s, exh.strings_offset, SEEK_SET); + if (ex->blocks_count > 0) { + io_position_push(s, exh.bone_names_offset, SEEK_SET); if (!is_x) - for (string* i = string_set.begin; i != string_set.end; i++) { + for (string* i = bone_names.begin; i != bone_names.end; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, string_data(i)); io_write_offset_f2(s, str_offset, 0x20); } else - for (string* i = string_set.begin; i != string_set.end; i++) { + for (string* i = bone_names.begin; i != bone_names.end; i++) { size_t str_offset = obj_skin_strings_get_string_offset(&strings, &string_offsets, string_data(i)); io_write_offset_x(s, str_offset); } io_position_pop(s); - exh.osage_nodes_count = (int32_t)(ex->osage_nodes.end - ex->osage_nodes.begin); io_position_push(s, exh.osage_nodes_offset, SEEK_SET); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - uint32_t index = obj_skin_strings_get_string_index(&string_set, string_data(&i->name)); - io_write_uint32_t(s, index); - io_write_float_t(s, i->length); + for (int32_t i = 0; i < ex->osage_nodes_count; i++) { + obj_skin_osage_node* osage_node = &ex->osage_nodes[i]; + io_write_uint32_t(s, osage_node->name_index); + io_write_float_t(s, osage_node->length); io_write_uint32_t(s, 0); } io_position_pop(s); io_position_push(s, exh.osage_sibling_infos_offset, SEEK_SET); - for (obj_skin_osage_node* i = ex->osage_nodes.begin; i != ex->osage_nodes.end; i++) { - if (!string_length(&i->sibling_name)) - continue; - - uint32_t name = obj_skin_strings_get_string_index(&string_set, string_data(&i->name)); - uint32_t sibling_name = obj_skin_strings_get_string_index(&string_set, string_data(&i->sibling_name)); - io_write_uint32_t(s, name); - io_write_uint32_t(s, sibling_name); - io_write_float_t(s, i->sibling_max_distance); + for (int32_t i = 0; i < ex->osage_sibling_infos_count; i++) { + obj_skin_osage_sibling_info* osage_sibling_info = &ex->osage_sibling_infos[i]; + io_write_uint32_t(s, osage_sibling_info->name_index); + io_write_uint32_t(s, osage_sibling_info->sibling_name_index); + io_write_float_t(s, osage_sibling_info->distance); } io_write_int32_t(s, 0); io_write_int32_t(s, 0); @@ -5660,51 +5709,37 @@ static void obj_modern_write_skin(obj* o, stream* s, io_position_pop(s); } - for (string* i = osage_names.begin; i != osage_names.end; i++) - string_free(i); - vector_string_free(&osage_names); - } - - for (string* i = strings.begin; i != strings.end; i++) - string_free(i); - vector_string_free(&strings); - - vector_ssize_t_free(&string_offsets); - - for (string* i = string_set.begin; i != string_set.end; i++) - string_free(i); - vector_string_free(&string_set); - - if (sk->ex_data_init) { io_position_push(s, sh.ex_data_offset, SEEK_SET); if (!is_x) { io_write_int32_t(s, exh.osage_count); - io_write_int32_t(s, exh.osage_nodes_count); + io_write_int32_t(s, ex->osage_nodes_count); io_write(s, 0, 0x04); io_write_offset_f2(s, exh.osage_nodes_offset, 0x20); io_write_offset_f2(s, exh.osage_names_offset, 0x20); io_write_offset_f2(s, exh.blocks_offset, 0x20); - io_write_int32_t(s, exh.strings_count); - io_write_offset_f2(s, exh.strings_offset, 0x20); + io_write_int32_t(s, exh.bone_names_count); + io_write_offset_f2(s, exh.bone_names_offset, 0x20); io_write_offset_f2(s, exh.osage_sibling_infos_offset, 0x20); io_write_int32_t(s, exh.cloth_count); io_write(s, 0, 0x1C); } else { io_write_int32_t(s, exh.osage_count); - io_write_int32_t(s, exh.osage_nodes_count); + io_write_int32_t(s, ex->osage_nodes_count); io_write(s, 0, 0x08); io_write_offset_x(s, exh.osage_nodes_offset); io_write_offset_x(s, exh.osage_names_offset); io_write_offset_x(s, exh.blocks_offset); - io_write_int32_t(s, exh.strings_count); - io_write_offset_x(s, exh.strings_offset); + io_write_int32_t(s, exh.bone_names_count); + io_write_offset_x(s, exh.bone_names_offset); io_write_offset_x(s, exh.osage_sibling_infos_offset); io_write_int32_t(s, exh.cloth_count); io_write(s, 0, 0x04); io_write(s, 0, 0x38); } io_position_pop(s); + + vector_string_free(&osage_names, string_free); } io_position_push(s, base_offset, SEEK_SET); @@ -5713,7 +5748,7 @@ static void obj_modern_write_skin(obj* o, stream* s, io_write_offset_f2(s, sh.bone_matrices_offset, 0x20); io_write_offset_f2(s, sh.bone_names_offset, 0x20); io_write_offset_f2(s, sh.ex_data_offset, 0x20); - io_write_int32_t(s, sh.bone_count); + io_write_int32_t(s, sk->bones_count); io_write_offset_f2(s, sh.bone_parent_ids_offset, 0x20); io_write(s, 0, 0x0C); } @@ -5722,18 +5757,22 @@ static void obj_modern_write_skin(obj* o, stream* s, io_write_offset_x(s, sh.bone_matrices_offset); io_write_offset_x(s, sh.bone_names_offset); io_write_offset_x(s, sh.ex_data_offset); - io_write_int32_t(s, sh.bone_count); + io_write_int32_t(s, sk->bones_count); io_write_offset_x(s, sh.bone_parent_ids_offset); io_write(s, 0, 0x18); } io_position_pop(s); + vector_string_free(&strings, string_free); + vector_ssize_t_free(&string_offsets, 0); + vector_string_free(&bone_names, string_free); + oskn->enrs = e; oskn->pof = pof; } static void obj_modern_read_skin_block_cloth(obj_skin_block_cloth* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { ssize_t mesh_name_offset = io_read_offset(s, header_length, is_x); io_read_string_null_terminated_offset(s, mesh_name_offset, &b->mesh_name); @@ -5741,16 +5780,16 @@ static void obj_modern_read_skin_block_cloth(obj_skin_block_cloth* b, io_read_string_null_terminated_offset(s, backface_mesh_name_offset, &b->backface_mesh_name); b->field_08 = io_read_int32_t_stream_reverse_endianness(s); - int32_t count = io_read_int32_t_stream_reverse_endianness(s); + b->count = io_read_int32_t_stream_reverse_endianness(s); b->field_10 = io_read_int32_t_stream_reverse_endianness(s); b->field_14 = io_read_int32_t_stream_reverse_endianness(s); ssize_t field_18_offset = io_read_offset(s, header_length, is_x); ssize_t field_1C_offset = io_read_offset(s, header_length, is_x); - b->field_1C = vector_empty(obj_skin_block_cloth_field_1C); - b->field_20 = vector_empty(obj_skin_block_cloth_field_20); - b->field_24 = vector_empty(uint16_t); - b->field_28 = vector_empty(uint16_t); + b->field_1C = 0; + b->field_20 = 0; + b->field_24 = 0; + b->field_28 = 0; ssize_t field_20_offset = io_read_offset(s, header_length, is_x); ssize_t field_24_offset = io_read_offset(s, header_length, is_x); ssize_t field_28_offset = io_read_offset(s, header_length, is_x); @@ -5780,73 +5819,76 @@ static void obj_modern_read_skin_block_cloth(obj_skin_block_cloth* b, mat.row3.y = io_read_float_t_stream_reverse_endianness(s); mat.row3.z = io_read_float_t_stream_reverse_endianness(s); mat.row3.w = io_read_float_t_stream_reverse_endianness(s); - mat4_transpose(&mat, &b->field_18[i]); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &b->field_18[i]); } io_position_pop(s); } if (field_1C_offset) { io_position_push(s, field_1C_offset, SEEK_SET); - vector_obj_skin_block_cloth_field_1C_reserve(&b->field_1C, count); - for (int32_t i = 0; i < count; i++) { - obj_skin_block_cloth_field_1C f; - f.field_00 = io_read_float_t_stream_reverse_endianness(s); - f.field_04 = io_read_float_t_stream_reverse_endianness(s); - f.field_08 = io_read_float_t_stream_reverse_endianness(s); - f.field_0C = io_read_float_t_stream_reverse_endianness(s); - f.field_10 = io_read_float_t_stream_reverse_endianness(s); - f.field_14 = io_read_float_t_stream_reverse_endianness(s); - f.field_18 = io_read_float_t_stream_reverse_endianness(s); - f.field_1C = io_read_uint32_t_stream_reverse_endianness(s); - f.field_20 = io_read_uint32_t_stream_reverse_endianness(s); - f.field_24 = io_read_uint32_t_stream_reverse_endianness(s); - obj_modern_read_skin_block_cloth_field_1C_sub(&f.sub_data_0, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_1C_sub(&f.sub_data_1, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_1C_sub(&f.sub_data_2, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_1C_sub(&f.sub_data_3, s, header_length, str, is_x); - vector_obj_skin_block_cloth_field_1C_push_back(&b->field_1C, &f); + b->field_1C = force_malloc_s(obj_skin_block_cloth_field_1C, b->count); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_1C* f = &b->field_1C[i]; + f->field_00 = io_read_float_t_stream_reverse_endianness(s); + f->field_04 = io_read_float_t_stream_reverse_endianness(s); + f->field_08 = io_read_float_t_stream_reverse_endianness(s); + f->field_0C = io_read_float_t_stream_reverse_endianness(s); + f->field_10 = io_read_float_t_stream_reverse_endianness(s); + f->field_14 = io_read_float_t_stream_reverse_endianness(s); + f->field_18 = io_read_float_t_stream_reverse_endianness(s); + f->field_1C = io_read_uint32_t_stream_reverse_endianness(s); + f->field_20 = io_read_uint32_t_stream_reverse_endianness(s); + f->field_24 = io_read_uint32_t_stream_reverse_endianness(s); + obj_modern_read_skin_block_cloth_field_1C_sub(&f->sub_data_0, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_1C_sub(&f->sub_data_1, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_1C_sub(&f->sub_data_2, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_1C_sub(&f->sub_data_3, s, header_length, str, is_x); } io_position_pop(s); } if (field_20_offset) { io_position_push(s, field_20_offset, SEEK_SET); - vector_obj_skin_block_cloth_field_20_reserve(&b->field_20, count); - for (int32_t i = 0; i < count; i++) { - obj_skin_block_cloth_field_20 f; - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_0, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_1, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_2, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_3, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_4, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_5, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_6, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_7, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_8, s, header_length, str, is_x); - obj_modern_read_skin_block_cloth_field_20_sub(&f.sub_data_9, s, header_length, str, is_x); - vector_obj_skin_block_cloth_field_20_push_back(&b->field_20, &f); + b->field_20 = force_malloc_s(obj_skin_block_cloth_field_1C, b->count); + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_20* f = &b->field_20[i]; + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_0, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_1, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_2, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_3, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_4, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_5, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_6, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_7, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_8, s, header_length, str, is_x); + obj_modern_read_skin_block_cloth_field_20_sub(&f->sub_data_9, s, header_length, str, is_x); } io_position_pop(s); } if (field_24_offset) { io_position_push(s, field_24_offset, SEEK_SET); - count = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_reserve(&b->field_24, count); - for (int32_t i = 0; i < count; i++) { - uint16_t u = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_push_back(&b->field_24, &u); + b->field_24_count = io_read_uint16_t_stream_reverse_endianness(s); + b->field_24 = force_malloc_s(uint16_t, b->field_24_count); + io_read(s, b->field_24, b->field_24_count * sizeof(uint16_t)); + if (s->is_big_endian) { + uint16_t* field_24 = b->field_24; + for (int32_t i = 0; i < b->field_24_count; i++) + field_24[i] = reverse_endianness_uint16_t(field_24[i]); } io_position_pop(s); } if (field_28_offset) { io_position_push(s, field_28_offset, SEEK_SET); - count = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_reserve(&b->field_28, count); - for (int32_t i = 0; i < count; i++) { - uint16_t u = io_read_uint16_t_stream_reverse_endianness(s); - vector_uint16_t_push_back(&b->field_28, &u); + b->field_28_count = io_read_uint16_t_stream_reverse_endianness(s); + b->field_28 = force_malloc_s(uint16_t, b->field_28_count); + io_read(s, b->field_28, b->field_28_count * sizeof(uint16_t)); + if (s->is_big_endian) { + uint16_t* field_28 = b->field_28; + for (int32_t i = 0; i < b->field_28_count; i++) + field_28[i] = reverse_endianness_uint16_t(field_28[i]); } io_position_pop(s); } @@ -5857,7 +5899,6 @@ static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, ssize_t* field_18_offset, ssize_t* field_1C_offset, ssize_t* field_20_offset, ssize_t* field_24_offset, ssize_t* field_28_offset) { - int32_t count = (int32_t)(b->field_1C.end - b->field_1C.begin); ssize_t mesh_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->mesh_name)); ssize_t backface_mesh_name_offset = obj_skin_strings_get_string_offset(strings, @@ -5867,14 +5908,14 @@ static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, io_write_offset_f2(s, mesh_name_offset, 0x20); io_write_offset_f2(s, backface_mesh_name_offset, 0x20); io_write_int32_t(s, b->field_08); - io_write_int32_t(s, count); + io_write_int32_t(s, b->count); io_write_int32_t(s, b->field_10); io_write_int32_t(s, b->field_14); io_write_offset_f2(s, b->field_10 ? *field_18_offset : 0, 0x20); - io_write_offset_f2(s, b->field_1C.end - b->field_1C.begin ? *field_1C_offset : 0, 0x20); - io_write_offset_f2(s, b->field_20.end - b->field_20.begin ? *field_20_offset : 0, 0x20); - io_write_offset_f2(s, b->field_24.end - b->field_24.begin ? *field_24_offset : 0, 0x20); - io_write_offset_f2(s, b->field_28.end - b->field_28.begin ? *field_28_offset : 0, 0x20); + io_write_offset_f2(s, b->field_1C ? *field_1C_offset : 0, 0x20); + io_write_offset_f2(s, b->field_20 ? *field_20_offset : 0, 0x20); + io_write_offset_f2(s, b->field_24 ? *field_24_offset : 0, 0x20); + io_write_offset_f2(s, b->field_28 ? *field_28_offset : 0, 0x20); io_write_uint32_t(s, b->field_2C); io_write_uint32_t(s, b->field_30); } @@ -5882,14 +5923,14 @@ static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, io_write_offset_x(s, mesh_name_offset); io_write_offset_x(s, backface_mesh_name_offset); io_write_int32_t(s, b->field_08); - io_write_int32_t(s, count); + io_write_int32_t(s, b->count); io_write_int32_t(s, b->field_10); io_write_int32_t(s, b->field_14); io_write_offset_x(s, b->field_10 ? *field_18_offset : 0); - io_write_offset_x(s, b->field_1C.end - b->field_1C.begin ? *field_1C_offset : 0); - io_write_offset_x(s, b->field_20.end - b->field_20.begin ? *field_20_offset : 0); - io_write_offset_x(s, b->field_24.end - b->field_24.begin ? *field_24_offset : 0); - io_write_offset_x(s, b->field_28.end - b->field_28.begin ? *field_28_offset : 0); + io_write_offset_x(s, b->field_1C ? *field_1C_offset : 0); + io_write_offset_x(s, b->field_20 ? *field_20_offset : 0); + io_write_offset_x(s, b->field_24 ? *field_24_offset : 0); + io_write_offset_x(s, b->field_28 ? *field_28_offset : 0); io_write_uint32_t(s, b->field_2C); io_write_uint32_t(s, b->field_30); } @@ -5901,7 +5942,8 @@ static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, continue; mat4 mat; - mat4_transpose(&b->field_18[i], &mat); + mat4u_to_mat4(&b->field_18[i], &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -5923,86 +5965,86 @@ static void obj_modern_write_skin_block_cloth(obj_skin_block_cloth* b, io_position_pop(s); } - if (b->field_1C.end - b->field_1C.begin) { + if (b->field_1C) { io_position_push(s, *field_1C_offset, SEEK_SET); - for (obj_skin_block_cloth_field_1C* i = b->field_1C.begin; i != b->field_1C.end; i++) { - io_write_float_t(s, i->field_00); - io_write_float_t(s, i->field_04); - io_write_float_t(s, i->field_08); - io_write_float_t(s, i->field_0C); - io_write_float_t(s, i->field_10); - io_write_float_t(s, i->field_14); - io_write_float_t(s, i->field_18); - io_write_uint32_t(s, i->field_1C); - io_write_uint32_t(s, i->field_20); - io_write_uint32_t(s, i->field_24); - obj_modern_write_skin_block_cloth_field_1C_sub(&i->sub_data_0, + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_1C* f = &b->field_1C[i]; + io_write_float_t(s, f->field_00); + io_write_float_t(s, f->field_04); + io_write_float_t(s, f->field_08); + io_write_float_t(s, f->field_0C); + io_write_float_t(s, f->field_10); + io_write_float_t(s, f->field_14); + io_write_float_t(s, f->field_18); + io_write_uint32_t(s, f->field_1C); + io_write_uint32_t(s, f->field_20); + io_write_uint32_t(s, f->field_24); + obj_modern_write_skin_block_cloth_field_1C_sub(&f->sub_data_0, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_1C_sub(&i->sub_data_1, + obj_modern_write_skin_block_cloth_field_1C_sub(&f->sub_data_1, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_1C_sub(&i->sub_data_2, + obj_modern_write_skin_block_cloth_field_1C_sub(&f->sub_data_2, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_1C_sub(&i->sub_data_3, + obj_modern_write_skin_block_cloth_field_1C_sub(&f->sub_data_3, s, strings, string_offsets, is_x); } io_position_pop(s); if (!is_x) *field_1C_offset += (10 * sizeof(int32_t) - + 4 * (sizeof(int64_t) + 4 * sizeof(int32_t))) * count; + + 4 * (sizeof(int64_t) + 4 * sizeof(int32_t))) * b->count; else *field_1C_offset += (10 * sizeof(int32_t) - + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * count; + + 4 * (sizeof(int32_t) + 3 * sizeof(int32_t))) * b->count; } - if (b->field_20.end - b->field_20.begin) { + if (b->field_20) { io_position_push(s, *field_20_offset, SEEK_SET); - for (obj_skin_block_cloth_field_20* i = b->field_20.begin; i != b->field_20.end; i++) { - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_0, + for (uint32_t i = 0; i < b->count; i++) { + obj_skin_block_cloth_field_20* f = &b->field_20[i]; + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_0, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_1, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_1, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_2, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_2, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_3, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_3, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_4, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_4, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_5, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_5, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_6, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_6, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_7, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_7, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_8, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_8, s, strings, string_offsets, is_x); - obj_modern_write_skin_block_cloth_field_20_sub(&i->sub_data_9, + obj_modern_write_skin_block_cloth_field_20_sub(&f->sub_data_9, s, strings, string_offsets, is_x); } io_position_pop(s); - *field_20_offset += 10 * (11 * sizeof(int32_t)) * count; + *field_20_offset += 10 * (11 * sizeof(int32_t)) * b->count; } - if (b->field_24.end - b->field_24.begin) { + if (b->field_24) { io_position_push(s, *field_24_offset, SEEK_SET); - io_write_uint16_t(s, (uint16_t)(b->field_24.end - b->field_24.begin)); - for (uint16_t* i = b->field_24.begin; i != b->field_24.end; i++) - io_write_uint16_t(s, *i); + io_write_uint16_t(s, (uint16_t)b->field_24_count); + io_write(s, b->field_24, b->field_24_count * sizeof(uint16_t)); io_position_pop(s); - *field_24_offset += sizeof(uint16_t) + (b->field_24.end - b->field_24.begin) * sizeof(uint16_t); + *field_28_offset += sizeof(uint16_t) + b->field_24_count * sizeof(uint16_t); } - if (b->field_28.end - b->field_28.begin) { + if (b->field_28) { io_position_push(s, *field_28_offset, SEEK_SET); - io_write_uint16_t(s, (uint16_t)(b->field_28.end - b->field_28.begin)); - for (uint16_t* i = b->field_28.begin; i != b->field_28.end; i++) - io_write_uint16_t(s, *i); + io_write_uint16_t(s, (uint16_t)b->field_28_count); + io_write(s, b->field_28, b->field_28_count * sizeof(uint16_t)); io_position_pop(s); - *field_28_offset += sizeof(uint16_t) + (b->field_28.end - b->field_28.begin) * sizeof(uint16_t); + *field_28_offset += sizeof(uint16_t) + b->field_28_count * sizeof(uint16_t); } } static void obj_modern_read_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_field_1C_sub* sub, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { ssize_t bone_name_offset = io_read_offset(s, header_length, is_x); io_read_string_null_terminated_offset(s, bone_name_offset, &sub->bone_name); sub->weight = io_read_float_t_stream_reverse_endianness(s); @@ -6025,7 +6067,7 @@ static void obj_modern_write_skin_block_cloth_field_1C_sub(obj_skin_block_cloth_ } static void obj_modern_read_skin_block_cloth_field_20_sub(obj_skin_block_cloth_field_20_sub* sub, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { sub->field_00 = io_read_uint32_t_stream_reverse_endianness(s); sub->field_04 = io_read_float_t_stream_reverse_endianness(s); sub->field_08 = io_read_float_t_stream_reverse_endianness(s); @@ -6055,21 +6097,29 @@ static void obj_modern_write_skin_block_cloth_field_20_sub(obj_skin_block_cloth_ } static void obj_modern_read_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { obj_modern_read_skin_block_node(&b->base, s, header_length, str, is_x); ssize_t type_offset = io_read_offset(s, header_length, is_x); char* type = io_read_utf8_string_null_terminated_offset(s, type_offset); - ssize_t name = io_read_offset(s, header_length, is_x); - io_read_string_null_terminated_offset(s, name, &b->base.name); + ssize_t name_offset = io_read_offset(s, header_length, is_x); + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); + + b->name_index = 0; + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); b->coupling = io_read_int32_t_stream_reverse_endianness(s); - ssize_t source_node_name = io_read_offset(s, header_length, is_x); - io_read_string_null_terminated_offset(s, source_node_name, &b->source_node_name); + ssize_t source_node_name_offset = io_read_offset(s, header_length, is_x); + io_read_string_null_terminated_offset(s, source_node_name_offset, &b->source_node_name); - if (!strcmp(type, "Direction")) { + if (!str_utils_compare(type, "Direction")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION; obj_modern_read_skin_block_constraint_up_vector(&b->direction.up_vector, s, header_length, str, is_x); @@ -6080,7 +6130,7 @@ static void obj_modern_read_skin_block_constraint(obj_skin_block_constraint* b, b->direction.target_offset.y = io_read_float_t_stream_reverse_endianness(s); b->direction.target_offset.z = io_read_float_t_stream_reverse_endianness(s); } - else if (!strcmp(type, "Distance")) { + else if (!str_utils_compare(type, "Distance")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE; obj_modern_read_skin_block_constraint_up_vector(&b->distance.up_vector, s, header_length, str, is_x); @@ -6090,13 +6140,13 @@ static void obj_modern_read_skin_block_constraint(obj_skin_block_constraint* b, obj_modern_read_skin_block_constraint_attach_point(&b->distance.constraining_object, s, header_length, str, is_x); } - else if (!strcmp(type, "Orientation")) { + else if (!str_utils_compare(type, "Orientation")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION; b->orientation.offset.x = io_read_float_t_stream_reverse_endianness(s); b->orientation.offset.y = io_read_float_t_stream_reverse_endianness(s); b->orientation.offset.z = io_read_float_t_stream_reverse_endianness(s); } - else if (!strcmp(type, "Position")) { + else if (!str_utils_compare(type, "Position")) { b->type = OBJ_SKIN_BLOCK_CONSTRAINT_POSITION; obj_modern_read_skin_block_constraint_up_vector(&b->position.up_vector, s, header_length, str, is_x); @@ -6111,7 +6161,8 @@ static void obj_modern_read_skin_block_constraint(obj_skin_block_constraint* b, } static void obj_modern_write_skin_block_constraint(obj_skin_block_constraint* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, ssize_t* offsets) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, + bool is_x, ssize_t* offsets) { obj_modern_write_skin_block_node(&b->base, s, strings, string_offsets, is_x); ssize_t type_offset = 0; @@ -6131,15 +6182,15 @@ static void obj_modern_write_skin_block_constraint(obj_skin_block_constraint* b, } io_write_offset(s, type_offset, 0x20, is_x); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_offset(s, name, 0x20, is_x); + ssize_t name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + io_write_offset(s, name_offset, 0x20, is_x); io_write_int32_t(s, b->coupling); - ssize_t source_node_name = obj_skin_strings_get_string_offset(strings, + ssize_t source_node_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->source_node_name)); - io_write_offset(s, source_node_name, 0x20, is_x); + io_write_offset(s, source_node_name_offset, 0x20, is_x); switch (b->type) { case OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION: @@ -6178,7 +6229,7 @@ static void obj_modern_write_skin_block_constraint(obj_skin_block_constraint* b, } static void obj_modern_read_skin_block_constraint_attach_point(obj_skin_block_constraint_attach_point* ap, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { ap->affected_by_orientation = io_read_int32_t_stream_reverse_endianness(s) != 0; ap->affected_by_scaling = io_read_int32_t_stream_reverse_endianness(s) != 0; ap->offset.x = io_read_float_t_stream_reverse_endianness(s); @@ -6196,7 +6247,7 @@ static void obj_modern_write_skin_block_constraint_attach_point(obj_skin_block_c } static void obj_modern_read_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { up->active = io_read_int32_t_stream_reverse_endianness(s) != 0; up->roll = io_read_float_t_stream_reverse_endianness(s); up->affected_axis.x = io_read_float_t_stream_reverse_endianness(s); @@ -6206,8 +6257,8 @@ static void obj_modern_read_skin_block_constraint_up_vector(obj_skin_block_const up->point_at.y = io_read_float_t_stream_reverse_endianness(s); up->point_at.z = io_read_float_t_stream_reverse_endianness(s); - ssize_t name = io_read_offset(s, header_length, is_x); - io_read_string_null_terminated_offset(s, name, &up->name); + ssize_t name_offset = io_read_offset(s, header_length, is_x); + io_read_string_null_terminated_offset(s, name_offset, &up->name); } static void obj_modern_write_skin_block_constraint_up_vector(obj_skin_block_constraint_up_vector* up, @@ -6221,100 +6272,115 @@ static void obj_modern_write_skin_block_constraint_up_vector(obj_skin_block_cons io_write_float_t(s, up->point_at.y); io_write_float_t(s, up->point_at.z); - ssize_t name = obj_skin_strings_get_string_offset(strings, + ssize_t name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&up->name)); - io_write_offset(s, name, 0x20, is_x); + io_write_offset(s, name_offset, 0x20, is_x); } static void obj_modern_read_skin_block_expression(obj_skin_block_expression* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { obj_modern_read_skin_block_node(&b->base, s, header_length, str, is_x); - ssize_t name = io_read_offset(s, header_length, is_x); - io_read_string_null_terminated_offset(s, name, &b->base.name); + ssize_t name_offset = io_read_offset(s, header_length, is_x); + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); - b->expression_count = io_read_int32_t_stream_reverse_endianness(s); - b->expression_count = min(b->expression_count, 10); + b->name_index = 0; + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); + + b->expressions_count = io_read_int32_t_stream_reverse_endianness(s); + b->expressions_count = min(b->expressions_count, 9); if (!is_x) - for (int32_t i = 0; i < b->expression_count; i++) { - ssize_t expression = io_read_offset_f2(s, header_length); - if (expression) - io_read_string_null_terminated_offset(s, expression, &b->expressions[i]); + for (int32_t i = 0; i < b->expressions_count; i++) { + ssize_t expression_offset = io_read_offset_f2(s, header_length); + if (expression_offset) + io_read_string_null_terminated_offset(s, expression_offset, &b->expressions[i]); } else - for (int32_t i = 0; i < b->expression_count; i++) { - ssize_t expression = io_read_offset_x(s); - if (expression) - io_read_string_null_terminated_offset(s, expression, &b->expressions[i]); + for (int32_t i = 0; i < b->expressions_count; i++) { + ssize_t expression_offset = io_read_offset_x(s); + if (expression_offset) + io_read_string_null_terminated_offset(s, expression_offset, &b->expressions[i]); } - for (int32_t i = b->expression_count; i < 9; i++) - memset(&b->expressions[i], 0, sizeof(string)); + for (int32_t i = b->expressions_count; i < 9; i++) + b->expressions[i] = string_empty; } static void obj_modern_write_skin_block_expression(obj_skin_block_expression* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, char** bone_names, bool is_x) { obj_modern_write_skin_block_node(&b->base, s, strings, string_offsets, is_x); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_offset(s, name, 0x20, is_x); + ssize_t name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + io_write_offset(s, name_offset, 0x20, is_x); - io_write_int32_t(s, min(b->expression_count, 9)); + io_write_int32_t(s, min(b->expressions_count, 9)); if (!is_x) { - for (int32_t i = 0; i < b->expression_count && i < 9; i++) { - ssize_t expression = obj_skin_strings_get_string_offset(strings, + for (int32_t i = 0; i < b->expressions_count && i < 9; i++) { + ssize_t expression_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->expressions[i])); - io_write_offset_f2(s, (int32_t)expression, 0x20); + io_write_offset_f2(s, (int32_t)expression_offset, 0x20); } - for (int32_t i = b->expression_count; i < 9; i++) + for (int32_t i = b->expressions_count; i < 9; i++) io_write_offset_f2(s, 0, 0x20); } else { - for (int32_t i = 0; i < b->expression_count && i < 9; i++) { - ssize_t expression = obj_skin_strings_get_string_offset(strings, + for (int32_t i = 0; i < b->expressions_count && i < 9; i++) { + ssize_t expression_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->expressions[i])); - io_write_offset_x(s, expression); + io_write_offset_x(s, expression_offset); } - for (int32_t i = b->expression_count; i < 9; i++) + for (int32_t i = b->expressions_count; i < 9; i++) io_write_offset_x(s, 0); } } static void obj_modern_read_skin_block_motion(obj_skin_block_motion* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { obj_modern_read_skin_block_node(&b->base, s, header_length, str, is_x); ssize_t name_offset = io_read_offset(s, header_length, is_x); - int32_t count = io_read_int32_t_stream_reverse_endianness(s); + b->nodes_count = io_read_int32_t_stream_reverse_endianness(s); ssize_t bone_names_offset = io_read_offset(s, header_length, is_x); ssize_t bone_matrices_offset = io_read_offset(s, header_length, is_x); - io_read_string_null_terminated_offset(s, name_offset, &b->base.name); + if (!is_x) { + b->name_index = 0; + char* name = io_read_utf8_string_null_terminated_offset(s, name_offset); + for (char** i = str; *i; i++) + if (!str_utils_compare(name, *i)) { + b->name_index = 0x8000 | (int32_t)(i - str); + break; + } + free(name); + } + else + io_read_string_null_terminated_offset(s, name_offset, &b->name); + b->nodes = 0; + + if (!b->nodes_count) + return; + + b->nodes = force_malloc_s(obj_skin_motion_node, b->nodes_count); - b->nodes = vector_empty(obj_skin_motion_node); - vector_obj_skin_motion_node_reserve(&b->nodes, count); if (bone_names_offset) { - obj_skin_motion_node node; - memset(&node, 0, sizeof(obj_skin_motion_node)); io_position_push(s, bone_names_offset, SEEK_SET); - for (int32_t i = 0; i < count; i++) { - uint32_t name = io_read_uint32_t_stream_reverse_endianness(s); - if (name & 0x8000) - string_copy(&str[name & 0x7FFF], &node.name); - else - memset(&node.name, 0, sizeof(string)); - vector_obj_skin_motion_node_push_back(&b->nodes, &node); - } + for (int32_t i = 0; i < b->nodes_count; i++) + b->nodes[i].name_index = io_read_uint32_t_stream_reverse_endianness(s); io_position_pop(s); } if (bone_matrices_offset) { io_position_push(s, bone_matrices_offset, SEEK_SET); - for (int32_t i = 0; i < count; i++) { + for (int32_t i = 0; i < b->nodes_count; i++) { mat4 mat; mat.row0.x = io_read_float_t_stream_reverse_endianness(s); mat.row0.y = io_read_float_t_stream_reverse_endianness(s); @@ -6332,7 +6398,8 @@ static void obj_modern_read_skin_block_motion(obj_skin_block_motion* b, mat.row3.y = io_read_float_t_stream_reverse_endianness(s); mat.row3.z = io_read_float_t_stream_reverse_endianness(s); mat.row3.w = io_read_float_t_stream_reverse_endianness(s); - mat4_transpose(&mat, &b->nodes.begin[i].transformation); + mat4_transpose(&mat, &mat); + mat4_to_mat4u(&mat, &b->nodes[i].transformation); } io_position_pop(s); } @@ -6340,30 +6407,33 @@ static void obj_modern_read_skin_block_motion(obj_skin_block_motion* b, static void obj_modern_write_skin_block_motion(obj_skin_block_motion* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, - vector_string* string_set, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset) { + char** bone_names, ssize_t* bone_names_offset, ssize_t* bone_matrices_offset) { obj_modern_write_skin_block_node(&b->base, s, strings, string_offsets, is_x); - ssize_t name = obj_skin_strings_get_string_offset(strings, - string_offsets, string_data(&b->base.name)); - io_write_offset(s, name, 0x20, is_x); - io_write_int32_t(s, (int32_t)(b->nodes.end - b->nodes.begin)); - io_write_offset(s, b->nodes.end - b->nodes.begin ? *bone_names_offset : 0, 0x20, is_x); - io_write_offset(s, b->nodes.end - b->nodes.begin ? *bone_matrices_offset : 0, 0x20, is_x); + ssize_t name_offset; + if (!is_x) + name_offset = obj_skin_strings_get_string_offset_by_index(strings, + string_offsets, bone_names, b->name_index); + else + name_offset = obj_skin_strings_get_string_offset(strings, + string_offsets, string_data(&b->name)); + io_write_offset(s, name_offset, 0x20, is_x); + io_write_int32_t(s, b->nodes_count); + io_write_offset(s, b->nodes ? *bone_names_offset : 0, 0x20, is_x); + io_write_offset(s, b->nodes ? *bone_matrices_offset : 0, 0x20, is_x); - obj_skin_motion_node node; - memset(&node, 0, sizeof(obj_skin_motion_node)); - - if (b->nodes.end - b->nodes.begin) { + if (b->nodes) { io_position_push(s, *bone_names_offset, SEEK_SET); - for (obj_skin_motion_node* i = b->nodes.begin; i != b->nodes.end; i++) - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&i->name))); + for (int32_t i = 0; i < b->nodes_count; i++) + io_write_uint32_t(s, b->nodes[i].name_index); io_position_pop(s); - *bone_names_offset += (b->nodes.end - b->nodes.begin) * sizeof(uint32_t); + *bone_names_offset += b->nodes_count * sizeof(uint32_t); io_position_push(s, *bone_matrices_offset, SEEK_SET); - for (obj_skin_motion_node* i = b->nodes.begin; i != b->nodes.end; i++) { + for (int32_t i = 0; i < b->nodes_count; i++) { mat4 mat; - mat4_transpose(&i->transformation, &mat); + mat4u_to_mat4(&b->nodes[i].transformation, &mat); + mat4_transpose(&mat, &mat); io_write_float_t(s, mat.row0.x); io_write_float_t(s, mat.row0.y); io_write_float_t(s, mat.row0.z); @@ -6382,12 +6452,12 @@ static void obj_modern_write_skin_block_motion(obj_skin_block_motion* b, io_write_float_t(s, mat.row3.w); } io_position_pop(s); - *bone_matrices_offset += (b->nodes.end - b->nodes.begin) * sizeof(mat4); + *bone_matrices_offset += b->nodes_count * sizeof(mat4); } } static void obj_modern_read_skin_block_node(obj_skin_block_node* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { ssize_t parent_name = io_read_offset(s, header_length, is_x); io_read_string_null_terminated_offset(s, parent_name, &b->parent_name); @@ -6406,9 +6476,9 @@ static void obj_modern_read_skin_block_node(obj_skin_block_node* b, static void obj_modern_write_skin_block_node(obj_skin_block_node* b, stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x) { - ssize_t parent_name = obj_skin_strings_get_string_offset(strings, + ssize_t parent_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->parent_name)); - io_write_offset(s, parent_name, 0x20, is_x); + io_write_offset(s, parent_name_offset, 0x20, is_x); io_write_float_t(s, b->position.x); io_write_float_t(s, b->position.y); @@ -6424,56 +6494,48 @@ static void obj_modern_write_skin_block_node(obj_skin_block_node* b, } static void obj_modern_read_skin_block_osage(obj_skin_block_osage* b, - stream* s, uint32_t header_length, string* str, bool is_x) { + stream* s, uint32_t header_length, char** str, bool is_x) { obj_modern_read_skin_block_node(&b->base, s, header_length, str, is_x); b->start_index = io_read_int32_t_stream_reverse_endianness(s); b->count = io_read_int32_t_stream_reverse_endianness(s); - uint32_t external_name = io_read_uint32_t_stream_reverse_endianness(s); - if (external_name & 0x8000) - string_copy(&str[external_name & 0x7FFF], &b->external_name); - else - memset(&b->external_name, 0, sizeof(string)); - - uint32_t name = io_read_uint32_t_stream_reverse_endianness(s); - if (name & 0x8000) - string_copy(&str[name & 0x7FFF], &b->base.name); - else - memset(&b->base.name, 0, sizeof(string)); + b->external_name_index = io_read_uint32_t_stream_reverse_endianness(s); + b->name_index = io_read_uint32_t_stream_reverse_endianness(s); if (!is_x) io_read(s, 0, 0x14); else { io_read(s, 0, 0x08); - ssize_t motion_node_name = io_read_offset_x(s); - io_read_string_null_terminated_offset(s, motion_node_name, &b->motion_node_name); + ssize_t motion_node_name_offset = io_read_offset_x(s); + io_read_string_null_terminated_offset(s, motion_node_name_offset, &b->motion_node_name); io_read(s, 0, 0x18); } - b->nodes = vector_empty(obj_skin_osage_node); + + b->nodes = 0; + b->nodes_count = 0; } static void obj_modern_write_skin_block_osage(obj_skin_block_osage* b, - stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x, - vector_string* string_set) { + stream* s, vector_string* strings, vector_ssize_t* string_offsets, bool is_x) { obj_modern_write_skin_block_node(&b->base, s, strings, string_offsets, is_x); io_write_int32_t(s, b->start_index); io_write_int32_t(s, b->count); - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&b->external_name))); - io_write_uint32_t(s, obj_skin_strings_get_string_index(string_set, string_data(&b->base.name))); + io_write_uint32_t(s, b->external_name_index); + io_write_uint32_t(s, b->name_index); if (!is_x) io_write(s, 0, 0x14); else { io_write(s, 0, 0x08); - ssize_t motion_node_name = obj_skin_strings_get_string_offset(strings, + ssize_t motion_node_name_offset = obj_skin_strings_get_string_offset(strings, string_offsets, string_data(&b->motion_node_name)); - io_write_offset_x(s, motion_node_name); - io_write(s, 0, 0x18); + io_write_offset_x(s, motion_node_name_offset); + io_write(s, 0, 0x18); } } -static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, +static void obj_modern_read_vertex(obj* obj, stream* s, ssize_t* attrib_offsets, obj_mesh* mesh, const uint32_t attrib_flags, int32_t vertex_count, int32_t vertex_size) { obj_vertex_flags vertex_flags = OBJ_VERTEX_POSITION | OBJ_VERTEX_NORMAL @@ -6482,10 +6544,11 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o | OBJ_VERTEX_TEXCOORD1 | OBJ_VERTEX_COLOR0; - if (attrib_flags & 0x08) + if (attrib_flags == 0x06) + vertex_flags |= OBJ_VERTEX_TEXCOORD2; + else if (attrib_flags == 0x0A) vertex_flags |= OBJ_VERTEX_TEXCOORD2 | OBJ_VERTEX_TEXCOORD3; - - if (attrib_flags & 0x04) + else if (attrib_flags == 0x04) vertex_flags |= OBJ_VERTEX_BONE_DATA; ssize_t vtx_offset = attrib_offsets[13]; @@ -6513,7 +6576,8 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o tangent.y = (float_t)io_read_int16_t_stream_reverse_endianness(s); tangent.z = (float_t)io_read_int16_t_stream_reverse_endianness(s); tangent.w = (float_t)io_read_int16_t_stream_reverse_endianness(s); - vec4_div_min_max_scalar(tangent, -32768.0f, 32767.0f, vtx[i].tangent); + vec4_div_min_max_scalar(tangent, -32768.0f, 32767.0f, tangent); + vec4_to_vec4u(tangent, vtx[i].tangent); vec2h texcoord0; texcoord0.x = io_read_half_t_stream_reverse_endianness(s); @@ -6525,7 +6589,13 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o texcoord1.y = io_read_half_t_stream_reverse_endianness(s); vec2h_to_vec2(texcoord1, vtx[i].texcoord1); - if (attrib_flags & 0x08) { + if (attrib_flags == 0x06) { + vec2h texcoord2; + texcoord2.x = io_read_half_t_stream_reverse_endianness(s); + texcoord2.y = io_read_half_t_stream_reverse_endianness(s); + vec2h_to_vec2(texcoord2, vtx[i].texcoord2); + } + else if (attrib_flags == 0x0A) { vec2h texcoord2; texcoord2.x = io_read_half_t_stream_reverse_endianness(s); texcoord2.y = io_read_half_t_stream_reverse_endianness(s); @@ -6544,19 +6614,20 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o color.w = io_read_half_t_stream_reverse_endianness(s); vec4h_to_vec4(color, vtx[i].color0); - if (attrib_flags & 0x04) { + if (attrib_flags == 0x04) { vec4 bone_weight; bone_weight.x = (float_t)io_read_int16_t_stream_reverse_endianness(s); bone_weight.y = (float_t)io_read_int16_t_stream_reverse_endianness(s); bone_weight.z = (float_t)io_read_int16_t_stream_reverse_endianness(s); bone_weight.w = (float_t)io_read_int16_t_stream_reverse_endianness(s); - vec4_div_min_max_scalar(bone_weight, -32768.0f, 32767.0f, vtx[i].bone_weight); + vec4_div_min_max_scalar(bone_weight, -32768.0f, 32767.0f, bone_weight); + vec4_to_vec4u(bone_weight, vtx[i].bone_weight); vec4i bone_index; - bone_index.x = io_read_uint8_t(s); - bone_index.y = io_read_uint8_t(s); - bone_index.z = io_read_uint8_t(s); - bone_index.w = io_read_uint8_t(s); + bone_index.x = (int32_t)io_read_uint8_t(s); + bone_index.y = (int32_t)io_read_uint8_t(s); + bone_index.z = (int32_t)io_read_uint8_t(s); + bone_index.w = (int32_t)io_read_uint8_t(s); if (bone_index.x == 0xFF) bone_index.x = -1; if (bone_index.y == 0xFF) @@ -6565,7 +6636,7 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o bone_index.z = -1; if (bone_index.w == 0xFF) bone_index.w = -1; - vtx[i].bone_index = bone_index; + vec4i_to_vec4iu(bone_index, vtx[i].bone_index); } if (memcmp(&vtx[i].tangent, &vec4_null, sizeof(vec4))) @@ -6580,7 +6651,7 @@ static void obj_modern_read_vertex(obj* o, stream* s, ssize_t* attrib_offsets, o mesh->vertex_flags = vertex_flags; } -static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, +static void obj_modern_write_vertex(obj* obj, stream* s, bool is_x, ssize_t* attrib_offsets, obj_mesh* mesh, uint32_t* attrib_flags, int32_t* vertex_count, int32_t* vertex_size, f2_struct* ovtx) { @@ -6588,22 +6659,25 @@ static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, int32_t _vertex_count = mesh->vertex_count; obj_vertex_flags vertex_flags = mesh->vertex_flags; - uint32_t _attrib_flags = 0; + uint32_t _attrib_flags = 0x02; int32_t _vertex_size = 0x2C; int32_t enrs_se3_rc = 12; - if (vertex_flags & OBJ_VERTEX_TEXCOORD2 | vertex_flags & OBJ_VERTEX_TEXCOORD3) { - _attrib_flags |= 0x08; - _vertex_size += 0x08; - enrs_se3_rc += 4; - } - if (vertex_flags & OBJ_VERTEX_BONE_DATA) { - _attrib_flags |= 0x04; + _attrib_flags = 0x04; _vertex_size += 0x0C; enrs_se3_rc += 4; } - else - _attrib_flags |= 0x02; + else if ((vertex_flags & (OBJ_VERTEX_TEXCOORD2 & OBJ_VERTEX_TEXCOORD3)) + == (OBJ_VERTEX_TEXCOORD2 | OBJ_VERTEX_TEXCOORD3)) { + _attrib_flags = 0x0A; + _vertex_size += 0x08; + enrs_se3_rc += 4; + } + else if (vertex_flags & OBJ_VERTEX_TEXCOORD2) { + _attrib_flags = 0x06; + _vertex_size += 0x04; + enrs_se3_rc += 2; + } uint32_t off = 0; vector_enrs_entry* e = &ovtx->enrs; @@ -6641,7 +6715,8 @@ static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, io_write(s, 0, 0x02); vec4 tangent; - vec4_mult_min_max_scalar(vtx[i].tangent, -32768.0f, 32767.0f, tangent); + vec4u_to_vec4(vtx[i].tangent, tangent); + vec4_mult_min_max_scalar(tangent, -32768.0f, 32767.0f, tangent); io_write_int16_t(s, (int16_t)roundf(tangent.x)); io_write_int16_t(s, (int16_t)roundf(tangent.y)); io_write_int16_t(s, (int16_t)roundf(tangent.z)); @@ -6678,7 +6753,8 @@ static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, if (_attrib_flags & 0x04) { vec4 bone_weight; - vec4_mult_min_max_scalar(vtx[i].bone_weight, -32768.0f, 32767.0f, bone_weight); + vec4u_to_vec4(vtx[i].bone_weight, bone_weight); + vec4_mult_min_max_scalar(bone_weight, -32768.0f, 32767.0f, bone_weight); io_write_int16_t(s, (int16_t)bone_weight.x); io_write_int16_t(s, (int16_t)bone_weight.y); io_write_int16_t(s, (int16_t)bone_weight.z); @@ -6698,43 +6774,60 @@ static void obj_modern_write_vertex(obj* o, stream* s, bool is_x, *vertex_size = _vertex_size; } -inline static uint32_t obj_skin_strings_get_string_index(vector_string* vec, char* str) { - if (!str) - return 0; +inline static void obj_skin_block_node_free(obj_skin_block_node* b) { + string_free(&b->parent_name); +} - ssize_t str_index = 0; +inline static uint32_t obj_skin_strings_get_string_index(vector_string* vec, char* str) { + size_t len = utf8_length(str); for (string* i = vec->begin; i != vec->end; i++) - if (!strcmp(str, string_data(i))) - str_index = i - vec->begin; - return (uint32_t)(0x8000 | str_index); + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return (uint32_t)(0x8000 | i - vec->begin); + return 0x8000; } inline static ssize_t obj_skin_strings_get_string_offset(vector_string* vec, vector_ssize_t* vec_off, char* str) { - if (!str) + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return vec_off->begin[i - vec->begin]; + return 0; +} + +inline static ssize_t obj_skin_strings_get_string_offset_by_index(vector_string* vec, + vector_ssize_t* vec_off, char** strings, uint32_t index) { + if (!(index & 0x8000)) return 0; - ssize_t str_offset = 0; + char* str = strings[index]; + size_t len = utf8_length(str); for (string* i = vec->begin; i != vec->end; i++) - if (!strcmp(str, string_data(i))) - str_offset = vec_off->begin[i - vec->begin]; - return str_offset; + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return vec_off->begin[i - vec->begin]; + return 0; } inline static void obj_skin_strings_push_back_check(vector_string* vec, char* str) { - if (!str) + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return; + + string* s = vector_string_reserve_back(vec); + string_init_length(s, str, len); +} + +inline static void obj_skin_strings_push_back_check_by_index(vector_string* vec, char** strings, uint32_t index) { + if (!(index & 0x8000)) return; - bool found = false; - for (string* k = vec->begin; k != vec->end; k++) - if (!strcmp(string_data(k), str)) { - found = true; - break; - } + char* str = strings[index & 0x7FFF]; + size_t len = utf8_length(str); + for (string* i = vec->begin; i != vec->end; i++) + if (!memcmp(str, string_data(i), min(len, i->length) + 1)) + return; - if (!found) { - string _s; - string_init(&_s, str); - vector_string_push_back(vec, &_s); - } + string* s = vector_string_reserve_back(vec); + string_init_length(s, str, len); } diff --git a/src/KKdLib/obj.h b/src/KKdLib/obj.h index ee9468cc..41a4313b 100644 --- a/src/KKdLib/obj.h +++ b/src/KKdLib/obj.h @@ -6,32 +6,10 @@ #pragma once #include "default.h" -#include "string.h" #include "kf.h" +#include "mat.h" +#include "string.h" #include "vec.h" -#include "vector.h" - -typedef enum obj_skin_block_constraint_type { - OBJ_SKIN_BLOCK_CONSTRAINT_NONE = 0, - OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION, - OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE, - OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION, - OBJ_SKIN_BLOCK_CONSTRAINT_POSITION, -} obj_skin_block_constraint_type; - -typedef enum obj_skin_block_constraint_coupling { - OBJ_SKIN_BLOCK_CONSTRAINT_COUPLING_RIGID = 0x01, - OBJ_SKIN_BLOCK_CONSTRAINT_COUPLING_SOFT = 0x03, -} obj_skin_block_constraint_coupling; - -typedef enum obj_skin_block_type { - OBJ_SKIN_BLOCK_NONE = 0, - OBJ_SKIN_BLOCK_CLOTH, - OBJ_SKIN_BLOCK_CONSTRAINT, - OBJ_SKIN_BLOCK_EXPRESSION, - OBJ_SKIN_BLOCK_MOTION, - OBJ_SKIN_BLOCK_OSAGE, -} obj_skin_block_type; typedef enum obj_index_format { OBJ_INDEX_U8 = 0x00, @@ -39,48 +17,6 @@ typedef enum obj_index_format { OBJ_INDEX_U32 = 0x02, } obj_index_format; -typedef enum obj_mesh_flags { - OBJ_MESH_FACE_CAMERA_POSITION = 0x02, - OBJ_MESH_TRANSLUCENT_NO_SHADOW = 0x04, - OBJ_MESH_FACE_CAMERA_VIEW = 0x08, -} obj_mesh_flags; - -typedef enum obj_primitive_type { - OBJ_PRIMITIVE_POINTS = 0x00, - OBJ_PRIMITIVE_LINES = 0x01, - OBJ_PRIMITIVE_LINE_STRIP = 0x02, - OBJ_PRIMITIVE_LINE_LOOP = 0x03, - OBJ_PRIMITIVE_TRIANGLES = 0x04, - OBJ_PRIMITIVE_TRIANGLE_STRIP = 0x05, - OBJ_PRIMITIVE_TRIANGLE_FAN = 0x06, - OBJ_PRIMITIVE_QUADS = 0x07, - OBJ_PRIMITIVE_QUAD_STRIP = 0x08, - OBJ_PRIMITIVE_POLYGON = 0x09, -} obj_primitive_type; - -typedef enum obj_sub_mesh_flags { - OBJ_SUB_MESH_NONE = 0x01, - OBJ_SUB_MESH_RECIEVE_SHADOW = 0x01, - OBJ_SUB_MESH_CAST_SHADOW = 0x02, - OBJ_SUB_MESH_TRANSPARENT = 0x04, -} obj_sub_mesh_flags; - -typedef enum obj_vertex_flags { - OBJ_VERTEX_NONE = 0x000, - OBJ_VERTEX_POSITION = 0x001, - OBJ_VERTEX_NORMAL = 0x002, - OBJ_VERTEX_TANGENT = 0x004, - OBJ_VERTEX_BINORMAL = 0x008, - OBJ_VERTEX_TEXCOORD0 = 0x010, - OBJ_VERTEX_TEXCOORD1 = 0x020, - OBJ_VERTEX_TEXCOORD2 = 0x040, - OBJ_VERTEX_TEXCOORD3 = 0x080, - OBJ_VERTEX_COLOR0 = 0x100, - OBJ_VERTEX_COLOR1 = 0x200, - OBJ_VERTEX_BONE_DATA = 0x400, - OBJ_VERTEX_UNKNOWN = 0x800, -} obj_vertex_flags; - typedef enum obj_material_aniso_direction { OBJ_MATERIAL_ANISO_DIRECTION_NORMAL = 0, OBJ_MATERIAL_ANISO_DIRECTION_U = 1, @@ -99,6 +35,7 @@ typedef enum obj_material_blend_factor { OBJ_MATERIAL_BLEND_INVERSE_DST_ALPHA = 7, OBJ_MATERIAL_BLEND_DST_COLOR = 8, OBJ_MATERIAL_BLEND_INVERSE_DST_COLOR = 9, + OBJ_MATERIAL_BLEND_ALPHA_SATURATE = 10, } obj_material_blend_factor; typedef enum obj_material_bump_map_type { @@ -128,8 +65,8 @@ typedef enum obj_material_flags { OBJ_MATERIAL_COLOR_L3 = 0x0800, OBJ_MATERIAL_COLOR_L3_ALPHA = 0x1000, OBJ_MATERIAL_TRANSLUCENCY = 0x2000, - OBJ_MATERIAL_FLAG14 = 0x4000, - OBJ_MATERIAL_OVERRIDEIBL = 0x8000, + OBJ_MATERIAL_FLAG_14 = 0x4000, + OBJ_MATERIAL_OVERRIDE_IBL = 0x8000, } obj_material_flags; typedef enum obj_material_specular_quality { @@ -137,12 +74,102 @@ typedef enum obj_material_specular_quality { OBJ_MATERIAL_SPECULAR_QUALITY_HIGH = 1, } obj_material_specular_quality; +typedef enum obj_material_texture_type { + OBJ_MATERIAL_TEXTURE_NONE = 0x00, + OBJ_MATERIAL_TEXTURE_COLOR = 0x01, + OBJ_MATERIAL_TEXTURE_NORMAL = 0x02, + OBJ_MATERIAL_TEXTURE_SPECULAR = 0x03, + OBJ_MATERIAL_TEXTURE_HEIGHT = 0x04, + OBJ_MATERIAL_TEXTURE_REFLECTION = 0x05, + OBJ_MATERIAL_TEXTURE_TRANSLUCENCY = 0x06, + OBJ_MATERIAL_TEXTURE_TRANSPARENCY = 0x07, + OBJ_MATERIAL_TEXTURE_ENVIRONMENT_SPHERE = 0x08, + OBJ_MATERIAL_TEXTURE_ENVIRONMENT_CUBE = 0x09, +} obj_material_texture_type; + +typedef enum obj_material_texture_coordinate_translation_type { + OBJ_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_NONE = 0x00, + OBJ_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_UV = 0x01, + OBJ_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_SPHERE = 0x02, + OBJ_MATERIAL_TEXTURE_COORDINATE_TRANSLATION_CUBE = 0x03 +} obj_material_texture_coordinate_translation_type; + typedef enum obj_material_vertex_translation_type { OBJ_MATERIAL_VERTEX_TRANSLATION_DEFAULT = 0, OBJ_MATERIAL_VERTEX_TRANSLATION_ENVELOPE = 1, OBJ_MATERIAL_VERTEX_TRANSLATION_MORPHING = 2, } obj_material_vertex_translation_type; +typedef enum obj_mesh_flags { + OBJ_MESH_FLAG_1 = 0x01, + OBJ_MESH_BILLBOARD_Y_AXIS = 0x02, + OBJ_MESH_TRANSLUCENT_NO_SHADOW = 0x04, + OBJ_MESH_BILLBOARD = 0x08, +} obj_mesh_flags; + +typedef enum obj_primitive_type { + OBJ_PRIMITIVE_POINTS = 0x00, + OBJ_PRIMITIVE_LINES = 0x01, + OBJ_PRIMITIVE_LINE_STRIP = 0x02, + OBJ_PRIMITIVE_LINE_LOOP = 0x03, + OBJ_PRIMITIVE_TRIANGLES = 0x04, + OBJ_PRIMITIVE_TRIANGLE_STRIP = 0x05, + OBJ_PRIMITIVE_TRIANGLE_FAN = 0x06, + OBJ_PRIMITIVE_QUADS = 0x07, + OBJ_PRIMITIVE_QUAD_STRIP = 0x08, + OBJ_PRIMITIVE_POLYGON = 0x09, +} obj_primitive_type; + +typedef enum obj_skin_block_constraint_type { + OBJ_SKIN_BLOCK_CONSTRAINT_NONE = 0, + OBJ_SKIN_BLOCK_CONSTRAINT_DIRECTION, + OBJ_SKIN_BLOCK_CONSTRAINT_DISTANCE, + OBJ_SKIN_BLOCK_CONSTRAINT_ORIENTATION, + OBJ_SKIN_BLOCK_CONSTRAINT_POSITION, +} obj_skin_block_constraint_type; + +typedef enum obj_skin_block_constraint_coupling { + OBJ_SKIN_BLOCK_CONSTRAINT_COUPLING_RIGID = 0x01, + OBJ_SKIN_BLOCK_CONSTRAINT_COUPLING_SOFT = 0x03, +} obj_skin_block_constraint_coupling; + +typedef enum obj_skin_block_type { + OBJ_SKIN_BLOCK_NONE = 0, + OBJ_SKIN_BLOCK_CLOTH, + OBJ_SKIN_BLOCK_CONSTRAINT, + OBJ_SKIN_BLOCK_EXPRESSION, + OBJ_SKIN_BLOCK_ITEM, + OBJ_SKIN_BLOCK_MOTION, + OBJ_SKIN_BLOCK_OSAGE, +} obj_skin_block_type; + +typedef enum obj_sub_mesh_flags { + OBJ_SUB_MESH_RECIEVE_SHADOW = 0x01, + OBJ_SUB_MESH_CAST_SHADOW = 0x02, + OBJ_SUB_MESH_TRANSPARENT = 0x04, + OBJ_SUB_MESH_FLAG_8 = 0x08, + OBJ_SUB_MESH_FLAG_10 = 0x10, + OBJ_SUB_MESH_FLAG_20 = 0x20, + OBJ_SUB_MESH_FLAG_40 = 0x40, + OBJ_SUB_MESH_FLAG_80 = 0x80, +} obj_sub_mesh_flags; + +typedef enum obj_vertex_flags { + OBJ_VERTEX_NONE = 0x000, + OBJ_VERTEX_POSITION = 0x001, + OBJ_VERTEX_NORMAL = 0x002, + OBJ_VERTEX_TANGENT = 0x004, + OBJ_VERTEX_BINORMAL = 0x008, + OBJ_VERTEX_TEXCOORD0 = 0x010, + OBJ_VERTEX_TEXCOORD1 = 0x020, + OBJ_VERTEX_TEXCOORD2 = 0x040, + OBJ_VERTEX_TEXCOORD3 = 0x080, + OBJ_VERTEX_COLOR0 = 0x100, + OBJ_VERTEX_COLOR1 = 0x200, + OBJ_VERTEX_BONE_DATA = 0x400, + OBJ_VERTEX_UNKNOWN = 0x800, +} obj_vertex_flags; + typedef struct obj_bounding_box { vec3 center; vec3 size; @@ -153,26 +180,89 @@ typedef struct obj_bounding_sphere { float_t radius; } obj_bounding_sphere; +typedef struct objt_material_blend_flags { + uint32_t alpha_texture : 1; + uint32_t alpha_material : 1; + uint32_t punch_through : 1; + uint32_t double_sided : 1; + uint32_t normal_direction_light : 1; + obj_material_blend_factor src_blend_factor : 4; + obj_material_blend_factor dst_blend_factor : 4; + uint32_t blend_operation : 3; + uint32_t z_bias : 4; + uint32_t no_fog : 1; + uint32_t flag_21 : 6; + uint32_t flag_27 : 1; + uint32_t flag_28 : 1; + uint32_t flag_29 : 2; + uint32_t flag_31 : 1; +} obj_material_blend_flags; + +typedef struct obj_material_shader_flags { + obj_material_vertex_translation_type vertex_translation_type : 2; + obj_material_color_source_type color_source_type : 2; + uint32_t lambert_shading : 1; + uint32_t phong_shading : 1; + uint32_t per_pixel_shading : 1; + uint32_t double_shading : 1; + obj_material_bump_map_type bump_map_type : 2; + uint32_t fresnel : 4; + uint32_t line_light : 4; + uint32_t recieve_shadow : 1; + uint32_t cast_shadow : 1; + obj_material_specular_quality specular_quality : 1; + obj_material_aniso_direction aniso_direction : 2; +} obj_material_shader_flags; + +typedef struct obj_material_texture_flags { + obj_material_texture_type type : 4; + uint32_t tex_coord_index : 4; + obj_material_texture_coordinate_translation_type tex_coord_trans_type : 4; +} obj_material_texture_flags; + +typedef struct obj_material_texture_sampler_flags { + uint32_t repeat_u : 1; + uint32_t repeat_v : 1; + uint32_t mirror_u : 1; + uint32_t mirror_v : 1; + uint32_t ignore_alpha : 1; + uint32_t blend : 5; + uint32_t alpha_blend : 5; + uint32_t border : 1; + uint32_t clamp_to_edge : 1; + uint32_t filter : 3; + uint32_t mip_map : 2; + uint32_t mip_map_bias : 7; + uint32_t flag_29 : 1; + uint32_t anisotropic_filter : 2; +} obj_material_texture_sampler_flags; + +typedef struct obj_material_texture_texture_flags { + obj_material_texture_type type : 4; + uint32_t tex_coord_index : 4; + obj_material_texture_coordinate_translation_type tex_coord_trans_type : 3; +} obj_material_texture_texture_flags; + typedef struct obj_material_texture { - uint32_t sampler_flags; + obj_material_texture_sampler_flags sampler_flags; uint32_t texture_id; - uint32_t texture_flags; + obj_material_texture_texture_flags texture_flags; char shader_name[8]; float_t weight; - float_t tex_coord_mat[16]; + mat4u tex_coord_mat; int32_t reserved[8]; } obj_material_texture; typedef struct obj_material { obj_material_flags flags; char shader_name[8]; - uint32_t shader_flags; + obj_material_shader_flags shader_flags; obj_material_texture textures[8]; - uint32_t blend_flags; - float_t diffuse[4]; - float_t ambient[4]; - float_t specular[4]; - float_t emission[4]; + obj_material_blend_flags blend_flags; + vec4u diffuse; + vec4u ambient; + vec4u specular; + vec4u emission; float_t shininess; float_t intensity; obj_bounding_sphere reserved_sphere; @@ -181,64 +271,47 @@ typedef struct obj_material { int32_t reserved[15]; } obj_material; -typedef struct obj_material_parent { +typedef struct obj_material_data { uint32_t textures_count; - obj_material data; -} obj_material_parent; - -vector(obj_material_parent) + obj_material material; +} obj_material_data; typedef struct obj_sub_mesh { obj_bounding_sphere bounding_sphere; uint32_t material_index; uint8_t texcoord_indices[8]; - uint16_t* bone_index; - int32_t bone_index_count; + uint16_t* bone_indices; + int32_t bone_indices_count; uint32_t bones_per_vertex; obj_primitive_type primitive_type; obj_index_format index_format; uint32_t* indices; int32_t indices_count; obj_sub_mesh_flags flags; - uint32_t index_offset; + uint32_t indices_offset; obj_bounding_box bounding_box; } obj_sub_mesh; -vector(obj_sub_mesh) - -typedef struct obj_vertex_data { // Optimized to memory +typedef struct obj_vertex_data { vec3 position; vec3 normal; - vec3 binormal; - vec3 dummy; - vec2 texcoord0; - vec2 texcoord1; - vec2 texcoord2; - vec2 texcoord3; - vec4 tangent; - vec4 color0; - vec4 color1; - vec4 bone_weight; - vec4i bone_index; - vec4 unknown; - /*vec3 position; - vec3 normal; - vec4 tangent; + vec4u tangent; vec3 binormal; vec2 texcoord0; vec2 texcoord1; vec2 texcoord2; vec2 texcoord3; - vec4 color0; - vec4 color1; - vec4 bone_weight; - vec4i bone_index; - vec4 unknown;*/ + vec4u color0; + vec4u color1; + vec4u bone_weight; + vec4iu bone_index; + vec4u unknown; } obj_vertex_data; typedef struct obj_mesh { obj_bounding_sphere bounding_sphere; - vector_obj_sub_mesh sub_meshes; + obj_sub_mesh* sub_meshes; + int32_t sub_meshes_count; obj_vertex_data* vertex; int32_t vertex_count; obj_vertex_flags vertex_flags; @@ -246,8 +319,6 @@ typedef struct obj_mesh { char name[0x40]; } obj_mesh; -vector(obj_mesh) - typedef struct obj_skin_block_cloth_field_1C_sub { string bone_name; float_t weight; @@ -299,28 +370,27 @@ typedef struct obj_skin_block_cloth_field_20 { obj_skin_block_cloth_field_20_sub sub_data_9; } obj_skin_block_cloth_field_20; -vector(obj_skin_block_cloth_field_1C) -vector(obj_skin_block_cloth_field_20) - typedef struct obj_skin_block_node { string parent_name; vec3 position; vec3 rotation; vec3 scale; - string name; } obj_skin_block_node; typedef struct obj_skin_block_cloth { string mesh_name; string backface_mesh_name; uint32_t field_08; + uint32_t count; uint32_t field_10; uint32_t field_14; - mat4 field_18[32]; - vector_obj_skin_block_cloth_field_1C field_1C; - vector_obj_skin_block_cloth_field_20 field_20; - vector_uint16_t field_24; - vector_uint16_t field_28; + mat4u field_18[32]; + obj_skin_block_cloth_field_1C* field_1C; + obj_skin_block_cloth_field_20* field_20; + uint16_t* field_24; + int32_t field_24_count; + uint16_t* field_28; + int32_t field_28_count; uint32_t field_2C; uint32_t field_30; } obj_skin_block_cloth; @@ -364,8 +434,9 @@ typedef struct obj_skin_block_constraint_position { typedef struct obj_skin_block_constraint { obj_skin_block_node base; - obj_skin_block_constraint_coupling coupling; + uint32_t name_index; string source_node_name; + obj_skin_block_constraint_coupling coupling; obj_skin_block_constraint_type type; union { obj_skin_block_constraint_direction direction; @@ -377,38 +448,40 @@ typedef struct obj_skin_block_constraint { typedef struct obj_skin_block_expression { obj_skin_block_node base; - int32_t expression_count; + uint32_t name_index; + int32_t expressions_count; string expressions[9]; } obj_skin_block_expression; typedef struct obj_skin_motion_node { - string name; - mat4 transformation; + uint32_t name_index; + mat4u transformation; } obj_skin_motion_node; -vector(obj_skin_motion_node) - typedef struct obj_skin_block_motion { obj_skin_block_node base; - vector_obj_skin_motion_node nodes; + union { + string name; + uint32_t name_index; + }; + obj_skin_motion_node* nodes; + int32_t nodes_count; } obj_skin_block_motion; typedef struct obj_skin_osage_node { - string name; + uint32_t name_index; float_t length; vec3 rotation; - string sibling_name; - float_t sibling_max_distance; } obj_skin_osage_node; -vector(obj_skin_osage_node) - typedef struct obj_skin_block_osage { obj_skin_block_node base; int32_t start_index; int32_t count; - vector_obj_skin_osage_node nodes; - string external_name; + obj_skin_osage_node* nodes; + int32_t nodes_count; + uint32_t external_name_index; + uint32_t name_index; string motion_node_name; } obj_skin_block_osage; @@ -423,32 +496,44 @@ typedef struct obj_skin_block { }; } obj_skin_block; -vector(obj_skin_block) +typedef struct obj_skin_osage_sibling_info { + uint32_t name_index; + uint32_t sibling_name_index; + float_t distance; +} obj_skin_osage_sibling_info; typedef struct obj_skin_ex_data { - vector_obj_skin_osage_node osage_nodes; - vector_obj_skin_block blocks; + obj_skin_osage_node* osage_nodes; + int32_t osage_nodes_count; + obj_skin_block* blocks; + int32_t blocks_count; + char* bone_names_buf; + char** bone_names; + int32_t bone_names_count; + obj_skin_osage_sibling_info* osage_sibling_infos; + int32_t osage_sibling_infos_count; } obj_skin_ex_data; typedef struct obj_skin_bone { uint32_t id; - mat4 inv_bind_pose_mat; - string name; uint32_t parent; + mat4u inv_bind_pose_mat; + string name; } obj_skin_bone; -vector(obj_skin_bone) - typedef struct obj_skin { - vector_obj_skin_bone bones; + obj_skin_bone* bones; + int32_t bones_count; obj_skin_ex_data ex_data; bool ex_data_init; } obj_skin; typedef struct obj { obj_bounding_sphere bounding_sphere; - vector_obj_mesh meshes; - vector_obj_material_parent materials; + obj_mesh* meshes; + int32_t meshes_count; + obj_material_data* materials; + int32_t materials_count; uint8_t flags; obj_skin skin; bool skin_init; @@ -456,14 +541,15 @@ typedef struct obj { uint32_t id; } obj; -vector(obj) - typedef struct obj_set { bool ready; bool modern; bool is_x; - vector_obj vec; - vector_uint32_t tex_ids; + + obj* objects; + int32_t objects_count; + uint32_t* texture_ids; + int32_t texture_ids_count; } obj_set; extern void obj_init(obj_set* os); diff --git a/src/KKdLib/pv_db.h b/src/KKdLib/pv_db.h index a26a0802..07e45616 100644 --- a/src/KKdLib/pv_db.h +++ b/src/KKdLib/pv_db.h @@ -6,200 +6,201 @@ #pragma once #include "default.h" +#include "string.h" #include "vector.h" -typedef enum chara { - CHARA_MIK = 0, - CHARA_RIN = 1, - CHARA_LEN = 2, - CHARA_LUK = 3, - CHARA_NER = 4, - CHARA_HAK = 5, - CHARA_KAI = 6, - CHARA_MEI = 7, - CHARA_SAK = 8, - CHARA_TET = 9, -} chara; +typedef enum pv_db_chara { + PV_DB_CHARA_MIK = 0, + PV_DB_CHARA_RIN = 1, + PV_DB_CHARA_LEN = 2, + PV_DB_CHARA_LUK = 3, + PV_DB_CHARA_NER = 4, + PV_DB_CHARA_HAK = 5, + PV_DB_CHARA_KAI = 6, + PV_DB_CHARA_MEI = 7, + PV_DB_CHARA_SAK = 8, + PV_DB_CHARA_TET = 9, +} pv_db_chara; -typedef enum chreff_type { - CHARA_EFFECT_AUTH3D = 0, - CHARA_EFFECT_AUTH3D_OBJ = 1, -} chreff_type; +typedef enum pv_db_chreff_type { + PV_DB_CHARA_EFFECT_AUTH3D = 0, + PV_DB_CHARA_EFFECT_AUTH3D_OBJ = 1, +} pv_db_chreff_type; -typedef enum db_format { - DB_NONE, - DB_AC101, - DB_AC110, - DB_AC120, - DB_AC130, - DB_AC200, - DB_AC210, - DB_AC211, - DB_AC220, - DB_AC221, - DB_AC301, - DB_AC310, - DB_AC320, - DB_AC401, - DB_AC402, - DB_AC410, - DB_AC500, - DB_AC510, - DB_AC511, - DB_AC520, - DB_AC521, - DB_AC600, - DB_AFT101, - DB_AFT110, - DB_AFT120, - DB_AFT200, - DB_AFT210, - DB_AFT220, - DB_AFT300, - DB_AFT310, - DB_AFT400, - DB_AFT410, - DB_AFT500, - DB_AFT501, - DB_AFT510, - DB_AFT600, - DB_AFT601, - DB_AFT610, - DB_AFT620, - DB_AFT621, - DB_AFT622, - DB_AFT701, - DB_AFT710, - DB_FT, -} db_format; +typedef enum pv_db_format { + PV_DB_NONE, + PV_DB_AC101, + PV_DB_AC110, + PV_DB_AC120, + PV_DB_AC130, + PV_DB_AC200, + PV_DB_AC210, + PV_DB_AC211, + PV_DB_AC220, + PV_DB_AC221, + PV_DB_AC301, + PV_DB_AC310, + PV_DB_AC320, + PV_DB_AC401, + PV_DB_AC402, + PV_DB_AC410, + PV_DB_AC500, + PV_DB_AC510, + PV_DB_AC511, + PV_DB_AC520, + PV_DB_AC521, + PV_DB_AC600, + PV_DB_AFT101, + PV_DB_AFT110, + PV_DB_AFT120, + PV_DB_AFT200, + PV_DB_AFT210, + PV_DB_AFT220, + PV_DB_AFT300, + PV_DB_AFT310, + PV_DB_AFT400, + PV_DB_AFT410, + PV_DB_AFT500, + PV_DB_AFT501, + PV_DB_AFT510, + PV_DB_AFT600, + PV_DB_AFT601, + PV_DB_AFT610, + PV_DB_AFT620, + PV_DB_AFT621, + PV_DB_AFT622, + PV_DB_AFT701, + PV_DB_AFT710, + PV_DB_FT, +} pv_db_format; -typedef enum duet_type { - DUET_USER_SETTING = 0, - DUET_FIXED_SIZE = 1, - DUET_FIXED_SUB = 2, - DUET_FIXED_ALL = 3, - DUET_PSEUDO_DEFAULT = 4, - DUET_PSEUDO_SAME = 5, - DUET_PSEUDO_SWIM = 6, - DUET_PSEUDO_SWIM_S = 7, -} duet_type; +typedef enum pv_db_duet_type { + PV_DB_DUET_USER_SETTING = 0, + PV_DB_DUET_FIXED_SIZE = 1, + PV_DB_DUET_FIXED_SUB = 2, + PV_DB_DUET_FIXED_ALL = 3, + PV_DB_DUET_PSEUDO_DEFAULT = 4, + PV_DB_DUET_PSEUDO_SAME = 5, + PV_DB_DUET_PSEUDO_SWIM = 6, + PV_DB_DUET_PSEUDO_SWIM_S = 7, +} pv_db_duet_type; -typedef enum eyes_base_adjust_type { - EYES_BASE_ADJUST_DIRECTION = 0, - EYES_BASE_ADJUST_CLEARANCE = 1, - EYES_BASE_ADJUST_OFF = 2, -} eyes_base_adjust_type; +typedef enum pv_db_eyes_base_adjust_type { + PV_DB_EYES_BASE_ADJUST_DIRECTION = 0, + PV_DB_EYES_BASE_ADJUST_CLEARANCE = 1, + PV_DB_EYES_BASE_ADJUST_OFF = 2, +} pv_db_eyes_base_adjust_type; -typedef enum frame_texture_type { - FRAME_TEXTURE_PRE_PP = 0, - FRAME_TEXTURE_POST_PP = 1, - FRAME_TEXTURE_FB = 2, -} frame_texture_type; +typedef enum pv_db_frame_texture_type { + PV_DB_FRAME_TEXTURE_PRE_PP = 0, + PV_DB_FRAME_TEXTURE_POST_PP = 1, + PV_DB_FRAME_TEXTURE_FB = 2, +} pv_db_frame_texture_type; -typedef enum movie_surface { - MOVIE_SURFACE_BACK = 0, - MOVIE_SURFACE_FRONT = 1, -} movie_surface; +typedef enum pv_db_movie_surface { + PV_DB_MOVIE_SURFACE_BACK = 0, + PV_DB_MOVIE_SURFACE_FRONT = 1, +} pv_db_movie_surface; -typedef enum performer_size { - PERFORMER_SIZE_NORMAL = 0, - PERFORMER_SIZE_PLAY_CHARA = 1, - PERFORMER_SIZE_PV_CHARA = 2, - PERFORMER_SIZE_SHORT = 3, - PERFORMER_SIZE_TALL = 4, -} performer_size; +typedef enum pv_db_performer_size { + PV_DB_PERFORMER_SIZE_NORMAL = 0, + PV_DB_PERFORMER_SIZE_PLAY_CHARA = 1, + PV_DB_PERFORMER_SIZE_PV_CHARA = 2, + PV_DB_PERFORMER_SIZE_SHORT = 3, + PV_DB_PERFORMER_SIZE_TALL = 4, +} pv_db_performer_size; -typedef enum performer_type { - PERFORMER_VOCAL = 0, - PERFORMER_PSEUDO_DEFAULT = 1, - PERFORMER_PSEUDO_SAME = 2, - PERFORMER_PSEUDO_SWIM = 3, - PERFORMER_PSEUDO_SWIM_S = 4, - PERFORMER_PSEUDO_MYCHARA = 5, - PERFORMER_GUEST = 6, -} performer_type; +typedef enum pv_db_performer_type { + PV_DB_PERFORMER_VOCAL = 0, + PV_DB_PERFORMER_PSEUDO_DEFAULT = 1, + PV_DB_PERFORMER_PSEUDO_SAME = 2, + PV_DB_PERFORMER_PSEUDO_SWIM = 3, + PV_DB_PERFORMER_PSEUDO_SWIM_S = 4, + PV_DB_PERFORMER_PSEUDO_MYCHARA = 5, + PV_DB_PERFORMER_GUEST = 6, +} pv_db_performer_type; -typedef enum pv_level { - PV_LV_00_0 = 0, - PV_LV_00_5 = 1, - PV_LV_01_0 = 2, - PV_LV_01_5 = 3, - PV_LV_02_0 = 4, - PV_LV_02_5 = 5, - PV_LV_03_0 = 6, - PV_LV_03_5 = 7, - PV_LV_04_0 = 8, - PV_LV_04_5 = 9, - PV_LV_05_0 = 10, - PV_LV_05_5 = 11, - PV_LV_06_0 = 12, - PV_LV_06_5 = 13, - PV_LV_07_0 = 14, - PV_LV_07_5 = 15, - PV_LV_08_0 = 16, - PV_LV_08_5 = 17, - PV_LV_09_0 = 18, - PV_LV_09_5 = 19, - PV_LV_10_0 = 20, -} pv_level; +typedef enum pv_db_pv_level { + PV_DB_PV_LV_00_0 = 0, + PV_DB_PV_LV_00_5 = 1, + PV_DB_PV_LV_01_0 = 2, + PV_DB_PV_LV_01_5 = 3, + PV_DB_PV_LV_02_0 = 4, + PV_DB_PV_LV_02_5 = 5, + PV_DB_PV_LV_03_0 = 6, + PV_DB_PV_LV_03_5 = 7, + PV_DB_PV_LV_04_0 = 8, + PV_DB_PV_LV_04_5 = 9, + PV_DB_PV_LV_05_0 = 10, + PV_DB_PV_LV_05_5 = 11, + PV_DB_PV_LV_06_0 = 12, + PV_DB_PV_LV_06_5 = 13, + PV_DB_PV_LV_07_0 = 14, + PV_DB_PV_LV_07_5 = 15, + PV_DB_PV_LV_08_0 = 16, + PV_DB_PV_LV_08_5 = 17, + PV_DB_PV_LV_09_0 = 18, + PV_DB_PV_LV_09_5 = 19, + PV_DB_PV_LV_10_0 = 20, +} pv_db_pv_level; -typedef struct another_song_aft310 { +typedef struct pv_db_another_song_aft310 { string name; string song_file_name; -} another_song_aft310; +} pv_db_another_song_aft310; -typedef struct another_song_aft500 { +typedef struct pv_db_another_song_aft500 { string name; string name_en; // FT/M39 string song_file_name; string vocal_chara_num; // FT/M39 string vocal_disp_name; // FT/M39 string vocal_disp_name_en; // FT/M39 -} another_song_aft500; +} pv_db_another_song_aft500; -typedef struct auth_replace_by_module { +typedef struct pv_db_auth_replace_by_module { null_int32_t id; null_int32_t module_id; string name; string org_name; -} auth_replace_by_module; +} pv_db_auth_replace_by_module; -null(chara) +null(pv_db_chara) -typedef struct chrcam { - null_chara chara; +typedef struct pv_db_chrcam { + null_pv_db_chara chara; null_int32_t id; string name; string org_name; -} chrcam; +} pv_db_chrcam; -null(chreff_type) +null(pv_db_chreff_type) -typedef struct chreff_data { - null_chreff_type type; +typedef struct pv_db_chreff_data { + null_pv_db_chreff_type type; string Name; -} chreff_data; +} pv_db_chreff_data; -vector(chreff_data) +vector(pv_db_chreff_data) -typedef struct chreff { - vector_chreff_data data; +typedef struct pv_db_chreff { + vector_pv_db_chreff_data data; null_int32_t id; string name; -} chreff; +} pv_db_chreff; -typedef struct chrmot { - null_chara chara; +typedef struct pv_db_chrmot { + null_pv_db_chara chara; null_int32_t id; string name; string org_name; -} chrmot; +} pv_db_chrmot; -typedef struct disp2d_ac200 { +typedef struct pv_db_disp2d_ac200 { string set_name; null_int32_t target_shadow_type; null_int32_t title_end_2d_field; @@ -208,9 +209,9 @@ typedef struct disp2d_ac200 { null_int32_t title_start_2d_field; null_int32_t title_start_2d_low_field; // not AC200 null_int32_t title_start_3d_field; -} disp2d_ac200; +} pv_db_disp2d_ac200; -typedef struct disp2d_aft210 { +typedef struct pv_db_disp2d_aft210 { string set_name; null_int32_t target_shadow_type; null_int32_t title_2d_layer; @@ -220,60 +221,60 @@ typedef struct disp2d_aft210 { null_int32_t title_start_2d_field; null_int32_t title_start_2d_low_field; null_int32_t title_start_3d_field; -} disp2d_aft210; +} pv_db_disp2d_aft210; -null(duet_type) +null(pv_db_duet_type) -typedef struct duet { - null_duet_type type; +typedef struct pv_db_duet { + null_pv_db_duet_type type; null_int32_t num; -} duet; +} pv_db_duet; -typedef struct eyes_rot_rate { - null_chara chr; +typedef struct pv_db_eyes_rot_rate { + null_pv_db_chara chr; null_float_t xn_rate; null_float_t xp_rate; -} eyes_rot_rate; +} pv_db_eyes_rot_rate; -typedef struct ex_auth { +typedef struct pv_db_ex_auth { string name; string org_name; -} ex_auth; +} pv_db_ex_auth; -typedef struct ex_song_ac101 { - null_chara chara; +typedef struct pv_db_ex_song_ac101 { + null_pv_db_chara chara; string file; string name; -} ex_song_ac101; +} pv_db_ex_song_ac101; -typedef struct ex_song_aft101 { - null_chara chara; - null_chara chara2P; // not AFT101 - null_chara chara3P; // not AFT101 - null_chara chara4P; // not AFT101 +typedef struct pv_db_ex_song_aft101 { + null_pv_db_chara chara; + null_pv_db_chara chara2P; // not AFT101 + null_pv_db_chara chara3P; // not AFT101 + null_pv_db_chara chara4P; // not AFT101 string file; string name; -} ex_song_aft101; +} pv_db_ex_song_aft101; -vector(ex_auth) +vector(pv_db_ex_auth) -typedef struct ex_song_aft300 { - vector_ex_auth ex_auth; // AFT621/AFT622/AFT701/FT/M39 +typedef struct pv_db_ex_song_aft300 { + vector_pv_db_ex_auth ex_auth; // AFT621/AFT622/AFT701/FT/M39 - null_chara chara; - null_chara chara2P; - null_chara chara3P; - null_chara chara4P; - null_chara chara5P; // not AFT300/AFT310/AFT400 - null_chara chara6P; // not AFT300/AFT310/AFT400 + null_pv_db_chara chara; + null_pv_db_chara chara2P; + null_pv_db_chara chara3P; + null_pv_db_chara chara4P; + null_pv_db_chara chara5P; // not AFT300/AFT310/AFT400 + null_pv_db_chara chara6P; // not AFT300/AFT310/AFT400 string file; string name; -} ex_song_aft300; +} pv_db_ex_song_aft300; -typedef struct field_ac101 { +typedef struct pv_db_field_ac101 { string aet_back; string aet_front; string aet_id_back; @@ -281,9 +282,9 @@ typedef struct field_ac101 { string auth_3d; string spr_set_back; string stage; -} field_ac101; +} pv_db_field_ac101; -typedef struct field_ac200 { +typedef struct pv_db_field_ac200 { vector_string auth_3d_list; // not AC200/AC210/AC211 vector_int32_t auth_3d_frame_list; // AC520/AC521/AC600 vector_string ex_auth_3d_list; // AC510/AC511/AC520/AC521/AC600 @@ -300,9 +301,9 @@ typedef struct field_ac200 { string spr_set_back; string stage; null_int32_t stage_flag; // AC520/AC521/AC600 -} field_ac200; +} pv_db_field_ac200; -typedef struct field_ac500 { +typedef struct pv_db_field_ac500 { vector_string auth_3d_list; string aet_back; @@ -317,9 +318,9 @@ typedef struct field_ac500 { string spr_set_back; string stage; null_int32_t stage_flag; // AC520/AC521/AC600 -} field_ac500; +} pv_db_field_ac500; -typedef struct field_aft101 { +typedef struct pv_db_field_aft101 { vector_string auth_3d_list; vector_int32_t auth_3d_frame_list; vector_string ex_auth_3d_list; @@ -340,9 +341,9 @@ typedef struct field_aft101 { string spr_set_back; string stage; null_int32_t stage_flag; -} field_aft101; +} pv_db_field_aft101; -typedef struct field_aft210 { +typedef struct pv_db_field_aft210 { vector_int32_t aet_back_frame_list; vector_string aet_back_list; vector_int32_t aet_front_frame_list; @@ -379,9 +380,9 @@ typedef struct field_aft210 { string spr_set_back; string stage; null_int32_t stage_flag; -} field_aft210; +} pv_db_field_aft210; -typedef struct field_aft500 { +typedef struct pv_db_field_aft500 { vector_int32_t aet_back_frame_list; vector_string aet_back_list; vector_int32_t aet_front_frame_list; @@ -425,9 +426,9 @@ typedef struct field_aft500 { string spr_set_back; string stage; null_int32_t stage_flag; -} field_aft500; +} pv_db_field_aft500; -typedef struct mdata_ac110 { +typedef struct pv_db_mdata_ac110 { string directory; null_int32_t flag; string gam_aet; @@ -436,26 +437,26 @@ typedef struct mdata_ac110 { string sel_spr; string sel_spr_cmn; string target_shadow_type; -} mdata_ac110; +} pv_db_mdata_ac110; -typedef struct mdata_ac200 { +typedef struct pv_db_mdata_ac200 { string directory; null_int32_t flag; -} mdata_ac200; +} pv_db_mdata_ac200; -typedef struct osage_init { +typedef struct pv_db_osage_init { null_int32_t frame; string motion; string stage; -} osage_init; +} pv_db_osage_init; -null(performer_size) -null(performer_type) +null(pv_db_performer_size) +null(pv_db_performer_type) -typedef struct performer_aft101 { - null_chara chara; - null_performer_size size; - null_performer_type type; +typedef struct pv_db_performer_aft101 { + null_pv_db_chara chara; + null_pv_db_performer_size size; + null_pv_db_performer_type type; null_int32_t costume; null_int32_t exclude; @@ -465,12 +466,12 @@ typedef struct performer_aft101 { null_int32_t item_neck; null_int32_t item_zujo; null_int32_t pv_costume; -} performer_aft101; +} pv_db_performer_aft101; -typedef struct performer_aft500 { - null_chara chara; - null_performer_size size; - null_performer_type type; +typedef struct pv_db_performer_aft500 { + null_pv_db_chara chara; + null_pv_db_performer_size size; + null_pv_db_performer_type type; null_int32_t costume; null_int32_t exclude; @@ -482,34 +483,34 @@ typedef struct performer_aft500 { null_int32_t item_zujo; null_int32_t pv_costume; null_int32_t pseudo_same_id; -} performer_aft500; +} pv_db_performer_aft500; -typedef struct pv_expression { +typedef struct pv_db_pv_expression { string file_name; -} pv_expression; +} pv_db_pv_expression; -typedef struct sabi { +typedef struct pv_db_sabi { null_float_t play_time; null_float_t start_time; -} sabi; +} pv_db_sabi; -typedef struct sel_2d { +typedef struct pv_db_sel_2d { string bg; string jk; string logo; string plate; -} sel_2d; +} pv_db_sel_2d; -typedef struct song_info_ac101 { +typedef struct pv_db_song_info_ac101 { string arranger; string guitar_player; // AC130 string lyrics; string manipulator; string music; string pv_editor; -} song_info_ac101; +} pv_db_song_info_ac101; -typedef struct song_info_ac200 { +typedef struct pv_db_song_info_ac200 { string arranger; string guitar_player; string lyrics; @@ -524,57 +525,57 @@ typedef struct song_info_ac200 { string ex_info2val; string ex_info3key; string ex_info3val; -} song_info_ac200; +} pv_db_song_info_ac200; -typedef struct stage_param_ac200 { +typedef struct pv_db_stage_param_ac200 { string collision_file; string stage; string wind_file; -} stage_param_ac200; +} pv_db_stage_param_ac200; -typedef struct stage_param_aft210 { +typedef struct pv_db_stage_param_aft210 { string collision_file; null_int32_t mhd_id; string stage; string wind_file; -} stage_param_aft210; +} pv_db_stage_param_aft210; -typedef struct title_image_ac101 { +typedef struct pv_db_title_image_ac101 { vector_string file; // AC101 vector_string file_name; // AC101 string aet_name; null_float_t time; -} title_image_ac101; +} pv_db_title_image_ac101; -typedef struct title_image_ac200 { +typedef struct pv_db_title_image_ac200 { string aet_name; null_float_t end_time; null_float_t time; -} title_image_ac200; +} pv_db_title_image_ac200; -vector(field_ac101) +vector(pv_db_field_ac101) -typedef struct diff_ac101 { - vector_field_ac101 field; +typedef struct pv_db_diff_ac101 { + vector_pv_db_field_ac101 field; vector_string motion; - sel_2d sel_2d; // AC101 - song_info_ac101 song_info; - title_image_ac101 title_image; + pv_db_sel_2d sel_2d; // AC101 + pv_db_song_info_ac101 song_info; + pv_db_title_image_ac101 title_image; null_int32_t level; string movie_file_name; string script_file_name; string se_name; null_int32_t version; -} diff_ac101; +} pv_db_diff_ac101; -vector(field_ac200) +vector(pv_db_field_ac200) -typedef struct diff_ac200 { - vector_field_ac200 field; +typedef struct pv_db_diff_ac200 { + vector_pv_db_field_ac200 field; vector_string edit_effect; vector_string hand_item; @@ -582,8 +583,8 @@ typedef struct diff_ac200 { vector_string motion2P; vector_string pv_item; // not AC200/AC210/AC211 - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; null_float_t edit_chara_scale; null_int32_t level; @@ -591,14 +592,14 @@ typedef struct diff_ac200 { string script_file_name; string se_name; null_int32_t version; -} diff_ac200; +} pv_db_diff_ac200; -null(movie_surface) +null(pv_db_movie_surface) -vector(field_aft101) +vector(pv_db_field_aft101) -typedef struct diff_aft101 { - vector_field_aft101 field; +typedef struct pv_db_diff_aft101 { + vector_pv_db_field_aft101 field; vector_string edit_effect; vector_string hand_item; @@ -608,10 +609,10 @@ typedef struct diff_aft101 { vector_string motion4P; vector_string pv_item; - pv_level level; - null_movie_surface movie_surface; - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_pv_level level; + null_pv_db_movie_surface movie_surface; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; string chainslide_failure_name; string chainslide_first_name; @@ -628,20 +629,20 @@ typedef struct diff_aft101 { string slide_name; string slidertouch_name; null_int32_t version; -} diff_aft101; +} pv_db_diff_aft101; -typedef struct diff_attr { +typedef struct pv_db_diff_attr { null_int32_t extra; null_int32_t original; null_int32_t slide; -} diff_attr; +} pv_db_diff_attr; -vector(field_aft210) -vector(performer_aft101) +vector(pv_db_field_aft210) +vector(pv_db_performer_aft101) -typedef struct diff_aft300 { - vector_field_aft210 field; - vector_performer_aft101 performer; +typedef struct pv_db_diff_aft300 { + vector_pv_db_field_aft210 field; + vector_pv_db_performer_aft101 performer; vector_string edit_effect; vector_string edit_effect_low_field; @@ -656,11 +657,11 @@ typedef struct diff_aft300 { vector_string movie_list; vector_string pv_item; - diff_attr attribute; - pv_level level; - null_movie_surface movie_surface; - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_diff_attr attribute; + pv_db_pv_level level; + null_pv_db_movie_surface movie_surface; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; string chainslide_failure_name; string chainslide_first_name; @@ -682,21 +683,21 @@ typedef struct diff_aft300 { string slidertouch_name; null_float_t sudden_timing; null_int32_t version; -} diff_aft300; +} pv_db_diff_aft300; -vector(diff_aft300) +vector(pv_db_diff_aft300) -typedef struct difficulty_aft300 { - vector_diff_aft300 diff[5]; - diff_attr attribute; -} difficulty_aft300; +typedef struct pv_db_difficulty_aft300 { + vector_pv_db_diff_aft300 diff[5]; + pv_db_diff_attr attribute; +} pv_db_difficulty_aft300; -vector(field_aft500) -vector(performer_aft500) +vector(pv_db_field_aft500) +vector(pv_db_performer_aft500) -typedef struct diff_aft500 { - vector_field_aft500 field; - vector_performer_aft500 performer; +typedef struct pv_db_diff_aft500 { + vector_pv_db_field_aft500 field; + vector_pv_db_performer_aft500 performer; vector_string edit_effect; vector_string edit_effect_low_field; @@ -711,12 +712,12 @@ typedef struct diff_aft500 { vector_string movie_list; vector_string pv_item; - diff_attr attribute; - pv_level level; - null_movie_surface movie_surface; - song_info_ac200 song_info_en; // FT/M39 - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_diff_attr attribute; + pv_db_pv_level level; + null_pv_db_movie_surface movie_surface; + pv_db_song_info_ac200 song_info_en; // FT/M39 + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; string chainslide_failure_name; string chainslide_first_name; @@ -738,33 +739,33 @@ typedef struct diff_aft500 { string slidertouch_name; null_float_t sudden_timing; null_int32_t version; -} diff_aft500; +} pv_db_diff_aft500; -vector(diff_aft500) +vector(pv_db_diff_aft500) -typedef struct difficulty_aft500 { - vector_diff_aft500 diff[5]; - diff_attr attribute; -} difficulty_aft500; +typedef struct pv_db_difficulty_aft500 { + vector_pv_db_diff_aft500 diff[5]; + pv_db_diff_attr attribute; +} pv_db_difficulty_aft500; -vector(ex_song_ac101) -vector(osage_init) +vector(pv_db_ex_song_ac101) +vector(pv_db_osage_init) -typedef struct pv_ac101 { - vector_ex_song_ac101 ex_song; - vector_field_ac200 field; - vector_osage_init osage_init; // AC120/AC130 +typedef struct pv_db_pv_ac101 { + vector_pv_db_ex_song_ac101 ex_song; + vector_pv_db_field_ac200 field; + vector_pv_db_osage_init osage_init; // AC120/AC130 vector_string lyric; vector_string motion; - diff_ac101 difficulty[5]; - mdata_ac110 mdata; // AC110/AC120/AC130 - sabi sabi; - sel_2d sel_2d; // AC101 - song_info_ac200 song_info; - title_image_ac200 title_image; - null_chara unlock; + pv_db_diff_ac101 difficulty[5]; + pv_db_mdata_ac110 mdata; // AC110/AC120/AC130 + pv_db_sabi sabi; + pv_db_sel_2d sel_2d; // AC101 + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; + null_pv_db_chara unlock; null_int32_t bpm; null_int32_t date; @@ -775,15 +776,15 @@ typedef struct pv_ac101 { string song_file_name; string song_name; string song_name_reading; -} pv_ac101; +} pv_db_pv_ac101; -vector(stage_param_ac200) +vector(pv_db_stage_param_ac200) -typedef struct pv_ac200 { - vector_ex_song_ac101 ex_song; - vector_field_ac200 field; - vector_osage_init osage_init; - vector_stage_param_ac200 stage_param; +typedef struct pv_db_pv_ac200 { + vector_pv_db_ex_song_ac101 ex_song; + vector_pv_db_field_ac200 field; + vector_pv_db_osage_init osage_init; + vector_pv_db_stage_param_ac200 stage_param; vector_string edit_effect; vector_string hand_item; @@ -792,15 +793,15 @@ typedef struct pv_ac200 { vector_string motion2P; vector_string pv_item; // not AC200/AC210/AC211 - diff_ac200 difficulty[5]; - disp2d_ac200 disp2d; - duet duet; - mdata_ac200 mdata; - sabi sabi; - song_info_ac200 song_info; - title_image_ac200 title_image; - null_chara unlock1P; - null_chara unlock2P; + pv_db_diff_ac200 difficulty[5]; + pv_db_disp2d_ac200 disp2d; + pv_db_duet duet; + pv_db_mdata_ac200 mdata; + pv_db_sabi sabi; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; + null_pv_db_chara unlock1p; + null_pv_db_chara unlock2p; null_int32_t bpm; null_int32_t date; @@ -813,42 +814,42 @@ typedef struct pv_ac200 { string song_name; string song_name_reading; null_bool use_osage_play_data; // not AC200 -} pv_ac200; +} pv_db_pv_ac200; -null(eyes_base_adjust_type) +null(pv_db_eyes_base_adjust_type) -vector(chreff) -vector(ex_song_aft101) -vector(eyes_rot_rate) +vector(pv_db_chreff) +vector(pv_db_ex_song_aft101) +vector(pv_db_eyes_rot_rate) -typedef struct pv_aft101 { - vector_chreff chreff; - vector_ex_song_aft101 ex_song; - vector_eyes_rot_rate eyes_rot_rate; // AFT200 - vector_field_aft101 field; - vector_osage_init osage_init; - vector_performer_aft101 performer; - vector_stage_param_ac200 stage_param; +typedef struct pv_db_pv_aft101 { + vector_pv_db_chreff chreff; + vector_pv_db_ex_song_aft101 ex_song; + vector_pv_db_eyes_rot_rate eyes_rot_rate; // AFT200 + vector_pv_db_field_aft101 field; + vector_pv_db_osage_init osage_init; + vector_pv_db_performer_aft101 performer; + vector_pv_db_stage_param_ac200 stage_param; vector_string edit_effect; vector_string effect_se_name_list; vector_string hand_item; vector_string lyric; vector_string motion; - vector_string motion2P; - vector_string motion3P; - vector_string motion4P; + vector_string motion2p; + vector_string motion3p; + vector_string motion4p; vector_string pv_item; - diff_aft101 difficulty[5]; - disp2d_ac200 disp2d; - null_eyes_base_adjust_type eyes_base_adjust_type; // AFT200 - mdata_ac200 mdata; - null_movie_surface movie_surface; - pv_expression pv_expression; - sabi sabi; - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_diff_aft101 difficulty[5]; + pv_db_disp2d_ac200 disp2d; + null_pv_db_eyes_base_adjust_type eyes_base_adjust_type; // AFT200 + pv_db_mdata_ac200 mdata; + null_pv_db_movie_surface movie_surface; + pv_db_pv_expression pv_expression; + pv_db_sabi sabi; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; null_int32_t bpm; string chainslide_failure_name; @@ -872,38 +873,38 @@ typedef struct pv_aft101 { string song_name; string song_name_reading; null_bool use_osage_play_data; -} pv_aft101; +} pv_db_pv_aft101; -vector(stage_param_aft210) +vector(pv_db_stage_param_aft210) -typedef struct pv_aft210 { - vector_chreff chreff; - vector_ex_song_aft101 ex_song; - vector_eyes_rot_rate eyes_rot_rate; - vector_field_aft210 field; - vector_osage_init osage_init; - vector_performer_aft101 performer; - vector_stage_param_aft210 stage_param; +typedef struct pv_db_pv_aft210 { + vector_pv_db_chreff chreff; + vector_pv_db_ex_song_aft101 ex_song; + vector_pv_db_eyes_rot_rate eyes_rot_rate; + vector_pv_db_field_aft210 field; + vector_pv_db_osage_init osage_init; + vector_pv_db_performer_aft101 performer; + vector_pv_db_stage_param_aft210 stage_param; vector_string edit_effect; vector_string effect_se_name_list; vector_string hand_item; vector_string lyric; vector_string motion; - vector_string motion2P; - vector_string motion3P; - vector_string motion4P; + vector_string motion2p; + vector_string motion3p; + vector_string motion4p; vector_string pv_item; - diff_aft101 difficulty[5]; - disp2d_aft210 disp2d; - null_eyes_base_adjust_type eyes_base_adjust_type; - mdata_ac200 mdata; - null_movie_surface movie_surface; - pv_expression pv_expression; - sabi sabi; - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_diff_aft101 difficulty[5]; + pv_db_disp2d_aft210 disp2d; + null_pv_db_eyes_base_adjust_type eyes_base_adjust_type; + pv_db_mdata_ac200 mdata; + null_pv_db_movie_surface movie_surface; + pv_db_pv_expression pv_expression; + pv_db_sabi sabi; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; null_int32_t bpm; string chainslide_failure_name; @@ -927,22 +928,22 @@ typedef struct pv_aft210 { string song_name; string song_name_reading; null_bool use_osage_play_data; -} pv_aft210; +} pv_db_pv_aft210; -vector(another_song_aft310) -vector(chrcam) -vector(ex_song_aft300) +vector(pv_db_another_song_aft310) +vector(pv_db_chrcam) +vector(pv_db_ex_song_aft300) -typedef struct pv_aft300 { - vector_another_song_aft310 another_song; // not AFT300 - vector_chrcam chrcam; // not AFT300 - vector_chreff chreff; - vector_ex_song_aft300 ex_song; - vector_eyes_rot_rate eyes_rot_rate; - vector_field_aft210 field; - vector_osage_init osage_init; - vector_performer_aft101 performer; - vector_stage_param_aft210 stage_param; +typedef struct pv_db_pv_aft300 { + vector_pv_db_another_song_aft310 another_song; // not AFT300 + vector_pv_db_chrcam chrcam; // not AFT300 + vector_pv_db_chreff chreff; + vector_pv_db_ex_song_aft300 ex_song; + vector_pv_db_eyes_rot_rate eyes_rot_rate; + vector_pv_db_field_aft210 field; + vector_pv_db_osage_init osage_init; + vector_pv_db_performer_aft101 performer; + vector_pv_db_stage_param_aft210 stage_param; vector_string edit_effect; vector_string edit_effect_low_field; // not AFT300 @@ -950,22 +951,22 @@ typedef struct pv_aft300 { vector_string hand_item; vector_string lyric; vector_string motion; - vector_string motion2P; - vector_string motion3P; - vector_string motion4P; - vector_string motion5P; // AFT410 - vector_string motion6P; // AFT410 + vector_string motion2p; + vector_string motion3p; + vector_string motion4p; + vector_string motion5p; // AFT410 + vector_string motion6p; // AFT410 vector_string pv_item; - difficulty_aft300 difficulty; - disp2d_aft210 disp2d; - null_eyes_base_adjust_type eyes_base_adjust_type; - mdata_ac200 mdata; - null_movie_surface movie_surface; - pv_expression pv_expression; - sabi sabi; - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_difficulty_aft300 difficulty; + pv_db_disp2d_aft210 disp2d; + null_pv_db_eyes_base_adjust_type eyes_base_adjust_type; + pv_db_mdata_ac200 mdata; + null_pv_db_movie_surface movie_surface; + pv_db_pv_expression pv_expression; + pv_db_sabi sabi; + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; null_int32_t bpm; string chainslide_failure_name; @@ -993,26 +994,26 @@ typedef struct pv_aft300 { string song_name_reading; null_float_t sudden_timing; null_bool use_osage_play_data; -} pv_aft300; +} pv_db_pv_aft300; -null(frame_texture_type) +null(pv_db_frame_texture_type) -vector(another_song_aft500) -vector(auth_replace_by_module) -vector(chrmot) +vector(pv_db_another_song_aft500) +vector(pv_db_auth_replace_by_module) +vector(pv_db_chrmot) -typedef struct pv_aft500 { - vector_another_song_aft500 another_song; - vector_auth_replace_by_module auth_replace_by_module; // AFT600/AFT601/AFT610/AFT620/AFT621/AFT622/AFT701/FT/M39 - vector_chrcam chrcam; - vector_chreff chreff; - vector_chrmot chrmot; // AFT620/AFT621/AFT622/AFT701/FT/M39 - vector_ex_song_aft300 ex_song; - vector_eyes_rot_rate eyes_rot_rate; - vector_field_aft500 field; - vector_osage_init osage_init; - vector_performer_aft500 performer; - vector_stage_param_aft210 stage_param; +typedef struct pv_db_pv_aft500 { + vector_pv_db_another_song_aft500 another_song; + vector_pv_db_auth_replace_by_module auth_replace_by_module; // AFT600/AFT601/AFT610/AFT620/AFT621/AFT622/AFT701/FT/M39 + vector_pv_db_chrcam chrcam; + vector_pv_db_chreff chreff; + vector_pv_db_chrmot chrmot; // AFT620/AFT621/AFT622/AFT701/FT/M39 + vector_pv_db_ex_song_aft300 ex_song; + vector_pv_db_eyes_rot_rate eyes_rot_rate; + vector_pv_db_field_aft500 field; + vector_pv_db_osage_init osage_init; + vector_pv_db_performer_aft500 performer; + vector_pv_db_stage_param_aft210 stage_param; vector_string edit_effect; vector_string edit_effect_low_field; @@ -1029,22 +1030,22 @@ typedef struct pv_aft500 { vector_string movie_list; vector_string pv_item; - difficulty_aft300 difficulty; - disp2d_aft210 disp2d; - null_eyes_base_adjust_type eyes_base_adjust_type; - null_frame_texture_type frame_texture_a_type; - null_frame_texture_type frame_texture_b_type; - null_frame_texture_type frame_texture_c_type; - null_frame_texture_type frame_texture_d_type; - null_frame_texture_type frame_texture_e_type; - null_frame_texture_type frame_texture_type; - mdata_ac200 mdata; - null_movie_surface movie_surface; - pv_expression pv_expression; - sabi sabi; - song_info_ac200 song_info_en; // FT/M39 - song_info_ac200 song_info; - title_image_ac200 title_image; + pv_db_difficulty_aft300 difficulty; + pv_db_disp2d_aft210 disp2d; + null_pv_db_eyes_base_adjust_type eyes_base_adjust_type; + null_pv_db_frame_texture_type frame_texture_a_type; + null_pv_db_frame_texture_type frame_texture_b_type; + null_pv_db_frame_texture_type frame_texture_c_type; + null_pv_db_frame_texture_type frame_texture_d_type; + null_pv_db_frame_texture_type frame_texture_e_type; + null_pv_db_frame_texture_type frame_texture_type; + pv_db_mdata_ac200 mdata; + null_pv_db_movie_surface movie_surface; + pv_db_pv_expression pv_expression; + pv_db_sabi sabi; + pv_db_song_info_ac200 song_info_en; // FT/M39 + pv_db_song_info_ac200 song_info; + pv_db_title_image_ac200 title_image; null_int32_t bpm; string chainslide_failure_name; @@ -1084,4 +1085,4 @@ typedef struct pv_aft500 { string song_name_reading_en; // FT/M39 null_float_t sudden_timing; null_bool use_osage_play_data; -} pv_aft500; +} pv_db_pv_aft500; diff --git a/src/KKdLib/quat.c b/src/KKdLib/quat.c index ae251d68..e531ab36 100644 --- a/src/KKdLib/quat.c +++ b/src/KKdLib/quat.c @@ -4,17 +4,36 @@ */ #include "quat.h" +#include +#include -void quat_mult(quat* x, quat* y, quat* z) { - quat xt; - quat yt; +inline void quat_mult(quat* x, quat* y, quat* z) { + __m128 xt; + __m128 yt; quat zt; - xt = *x; - yt = *y; - zt.x = xt.x * yt.w + xt.y * yt.z - xt.z * yt.y + xt.w * yt.x; - zt.y = -xt.x * yt.z + xt.y * yt.w + xt.z * yt.x + xt.w * yt.y; - zt.z = xt.x * yt.y - xt.y * yt.x + xt.z * yt.w + xt.w * yt.z; - zt.w = -xt.x * yt.x - xt.y * yt.y - xt.z * yt.z + xt.w * yt.w; + __m128 zt0; + __m128 zt1; + __m128 zt2; + __m128 zt3; + + xt = x->data; + yt = y->data; + zt0 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x1B)); + zt1 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x4E)); + zt2 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0xB1)); + zt3 = _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0xE4)); + zt0 = _mm_xor_ps(zt0, (__m128) { .m128_f32 = { 0.0f, 0.0f, -0.0f, 0.0f } }); + zt1 = _mm_xor_ps(zt1, (__m128) { .m128_f32 = { -0.0f, 0.0f, 0.0f, 0.0f } }); + zt2 = _mm_xor_ps(zt2, (__m128) { .m128_f32 = { 0.0f, -0.0f, 0.0f, 0.0f } }); + zt3 = _mm_xor_ps(zt3, (__m128) { .m128_f32 = { -0.0f, -0.0f, -0.0f, 0.0f } }); + zt0 = _mm_hadd_ps(zt0, zt0); + zt1 = _mm_hadd_ps(zt1, zt1); + zt2 = _mm_hadd_ps(zt2, zt2); + zt3 = _mm_hadd_ps(zt3, zt3); + zt.x = _mm_cvtss_f32(_mm_hadd_ps(zt0, zt0)); + zt.y = _mm_cvtss_f32(_mm_hadd_ps(zt1, zt1)); + zt.z = _mm_cvtss_f32(_mm_hadd_ps(zt2, zt2)); + zt.w = _mm_cvtss_f32(_mm_hadd_ps(zt3, zt3)); *z = zt; } diff --git a/src/KKdLib/sort.c b/src/KKdLib/sort.c index 6913695e..3b802748 100644 --- a/src/KKdLib/sort.c +++ b/src/KKdLib/sort.c @@ -7,38 +7,280 @@ #include "sort.h" -#define RADIX 8 +#define RADIX_BASE 8 +#define RADIX (1 << RADIX_BASE) -inline int32_t digit(int32_t n, size_t k, size_t m) { - return (int32_t)(((ssize_t)n >> (RADIX * k) & (m - 1))); +void radix_sort_int8_t(int8_t* arr, size_t n) { + if (n <= 1) + return; + + uint8_t* a = (uint8_t*)arr; + for (size_t i = 0; i < n; i++) + if (a[i] & 0x80) + a[i] |= 0x80; + else + a[i] = (uint8_t)(-(int8_t)a[i]); + radix_sort_uint8_t(a, n); + for (size_t i = 0; i < n; i++) + if (a[i] & 0x80) + a[i] &= ~0x80; + else + a[i] = (uint8_t)(-(int8_t)a[i]); } -void radix_sort(int32_t* array, size_t length) { - const size_t k = (32 + RADIX - 1) / RADIX; - const size_t m = (size_t)1 << RADIX; - const size_t s = sizeof(int32_t); - int32_t* l = array; - int32_t* r = l + length; - int32_t* b = force_malloc_s(s, length); - int32_t* c = force_malloc_s(s, m); - int32_t t; - for (size_t i = 0; i < k; i++) { - memset(c, 0, m * s); +void radix_sort_uint8_t(uint8_t* arr, size_t n) { + if (n <= 1) + return; - for (int32_t* j = l; j < r; j++) - c[digit(*j, i, m)]++; + uint8_t* o = force_malloc_s(uint8_t, n); + size_t* c = force_malloc_s(size_t, RADIX); + uint8_t* org_arr = arr; - t = c[0]; - for (size_t j = 1; j < m; j++) - t = c[j] += t; + for (size_t shift = 0, s = 0; shift < sizeof(uint8_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); - for (int32_t* j = r - 1; j >= l; j--) - b[--c[digit(*j, i, m)]] = *j; + for (size_t i = 0; i < n; i++) + c[(arr[i] >> s) & (RADIX - 1)]++; - size_t cur = 0; - for (int32_t* j = l; j < r; j++) - *j = b[cur++]; + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) + o[--c[(arr[i] >> s) & (RADIX - 1)]] = arr[i]; + + uint8_t* t = arr; + arr = o; + o = t; } - free(b); + + if (org_arr == o) { + uint8_t* t = arr; + arr = o; + o = t; + + memmove(arr, o, sizeof(uint8_t) * n); + } + + free(o); + free(c); +} + +void radix_sort_int16_t(int16_t* arr, size_t n) { + if (n <= 1) + return; + + uint16_t* a = (uint16_t*)arr; + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000) + a[i] |= 0x8000; + else + a[i] = (uint16_t)(-(int16_t)a[i]); + radix_sort_uint16_t(a, n); + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000) + a[i] &= ~0x8000; + else + a[i] = (uint16_t)(-(int16_t)a[i]); +} + +void radix_sort_uint16_t(uint16_t* arr, size_t n) { + if (n <= 1) + return; + + uint16_t* o = force_malloc_s(uint16_t, n); + size_t* c = force_malloc_s(size_t, RADIX); + uint16_t* org_arr = arr; + + for (size_t shift = 0, s = 0; shift < sizeof(uint16_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < n; i++) + c[(arr[i] >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) + o[--c[(arr[i] >> s) & (RADIX - 1)]] = arr[i]; + + uint16_t* t = arr; + arr = o; + o = t; + } + + if (org_arr == o) { + uint16_t* t = arr; + arr = o; + o = t; + + memmove(arr, o, sizeof(uint16_t) * n); + } + + free(o); + free(c); +} + +void radix_sort_int32_t(int32_t* arr, size_t n) { + if (n <= 1) + return; + + uint32_t* a = (uint32_t*)arr; + for (size_t i = 0; i < n; i++) + if (a[i] & 0x80000000) + a[i] |= 0x80000000; + else + a[i] = (uint32_t)(-(int32_t)a[i]); + radix_sort_uint32_t(a, n); + for (size_t i = 0; i < n; i++) + if (a[i] & 0x80000000) + a[i] &= ~0x80000000; + else + a[i] = (uint32_t)(-(int32_t)a[i]); +} + +void radix_sort_uint32_t(uint32_t* arr, size_t n) { + if (n <= 1) + return; + + uint32_t* o = force_malloc_s(uint32_t, n); + size_t* c = force_malloc_s(size_t, RADIX); + uint32_t* org_arr = arr; + + for (size_t shift = 0, s = 0; shift < sizeof(uint32_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < n; i++) + c[(arr[i] >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) + o[--c[(arr[i] >> s) & (RADIX - 1)]] = arr[i]; + + uint32_t* t = arr; + arr = o; + o = t; + } + + if (org_arr == o) { + uint32_t* t = arr; + arr = o; + o = t; + + memmove(arr, o, sizeof(uint32_t) * n); + } + + free(o); + free(c); +} + +void radix_sort_int64_t(int64_t* arr, size_t n) { + if (n <= 1) + return; + + uint64_t* a = (uint64_t*)arr; + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000000000000000) + a[i] |= 0x8000000000000000; + else + a[i] = (uint64_t)(-(int64_t)a[i]); + radix_sort_uint64_t(a, n); + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000000000000000) + a[i] &= ~0x8000000000000000; + else + a[i] = (uint64_t)(-(int64_t)a[i]); +} + +void radix_sort_uint64_t(uint64_t* arr, size_t n) { + if (n <= 1) + return; + + uint64_t* o = force_malloc_s(uint64_t, n); + size_t* c = force_malloc_s(size_t, RADIX); + uint64_t* org_arr = arr; + + for (size_t shift = 0, s = 0; shift < sizeof(uint64_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < n; i++) + c[(arr[i] >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) + o[--c[(arr[i] >> s) & (RADIX - 1)]] = arr[i]; + + uint64_t* t = arr; + arr = o; + o = t; + } + + if (org_arr == o) { + uint64_t* t = arr; + arr = o; + o = t; + + memmove(arr, o, sizeof(uint64_t) * n); + } + + free(o); + free(c); +} + +void radix_sort_ssize_t(ssize_t* arr, size_t n) { + if (n <= 1) + return; + + size_t* a = (size_t*)arr; + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000000000000000) + a[i] |= 0x8000000000000000; + else + a[i] = (size_t)(-(ssize_t)a[i]); + radix_sort_size_t(a, n); + for (size_t i = 0; i < n; i++) + if (a[i] & 0x8000000000000000) + a[i] &= ~0x8000000000000000; + else + a[i] = (size_t)(-(ssize_t)a[i]); +} + +void radix_sort_size_t(size_t* arr, size_t n) { + if (n <= 1) + return; + + size_t* o = force_malloc_s(size_t, n); + size_t* c = force_malloc_s(size_t, RADIX); + size_t* org_arr = arr; + + for (size_t shift = 0, s = 0; shift < sizeof(size_t) * 8 / RADIX_BASE; shift++, s += RADIX_BASE) { + memset(c, 0, sizeof(size_t) * RADIX); + + for (size_t i = 0; i < n; i++) + c[(arr[i] >> s) & (RADIX - 1)]++; + + for (size_t i = 1; i < RADIX; i++) + c[i] += c[i - 1]; + + for (ssize_t i = n - 1; i >= 0; i--) + o[--c[(arr[i] >> s) & (RADIX - 1)]] = arr[i]; + + size_t* t = arr; + arr = o; + o = t; + } + + if (org_arr == o) { + size_t* t = arr; + arr = o; + o = t; + + memmove(arr, o, sizeof(size_t) * n); + } + + free(o); free(c); } diff --git a/src/KKdLib/sort.h b/src/KKdLib/sort.h index 9bad483c..a2111101 100644 --- a/src/KKdLib/sort.h +++ b/src/KKdLib/sort.h @@ -8,5 +8,15 @@ #pragma once #include "default.h" +#include "string.h" -extern void radix_sort(int32_t* array, size_t length); +extern void radix_sort_int8_t(int8_t* arr, size_t n); +extern void radix_sort_uint8_t(uint8_t* arr, size_t n); +extern void radix_sort_int16_t(int16_t* arr, size_t n); +extern void radix_sort_uint16_t(uint16_t* arr, size_t n); +extern void radix_sort_int32_t(int32_t* arr, size_t n); +extern void radix_sort_uint32_t(uint32_t* arr, size_t n); +extern void radix_sort_int64_t(int64_t* arr, size_t n); +extern void radix_sort_uint64_t(uint64_t* arr, size_t n); +extern void radix_sort_ssize_t(ssize_t* arr, size_t n); +extern void radix_sort_size_t(size_t* arr, size_t n); diff --git a/src/KKdLib/sound_diva.c b/src/KKdLib/sound/diva.c similarity index 98% rename from src/KKdLib/sound_diva.c rename to src/KKdLib/sound/diva.c index 5f3ad73a..0b1cdd0a 100644 --- a/src/KKdLib/sound_diva.c +++ b/src/KKdLib/sound/diva.c @@ -3,10 +3,10 @@ GitHub/GitLab: korenkonder */ -#include "sound_diva.h" -#include "sound_wav.h" -#include "io_stream.h" -#include "str_utils.h" +#include "diva.h" +#include "wav.h" +#include "../io/stream.h" +#include "../str_utils.h" static const int8_t ima_index_table[] = { -1, -1, -1, -1, 2, 4, 6, 8, diff --git a/src/KKdLib/sound_diva.h b/src/KKdLib/sound/diva.h similarity index 95% rename from src/KKdLib/sound_diva.h rename to src/KKdLib/sound/diva.h index f61e3eff..57154c3e 100644 --- a/src/KKdLib/sound_diva.h +++ b/src/KKdLib/sound/diva.h @@ -5,7 +5,7 @@ #pragma once -#include "default.h" +#include "../default.h" typedef struct diva { size_t size; diff --git a/src/KKdLib/sound_vag.c b/src/KKdLib/sound/vag.c similarity index 98% rename from src/KKdLib/sound_vag.c rename to src/KKdLib/sound/vag.c index 6587eae3..109dbb70 100644 --- a/src/KKdLib/sound_vag.c +++ b/src/KKdLib/sound/vag.c @@ -3,11 +3,11 @@ GitHub/GitLab: korenkonder */ -#include "sound_vag.h" -#include "sound_wav.h" -#include "io_path.h" -#include "io_stream.h" -#include "str_utils.h" +#include "vag.h" +#include "wav.h" +#include "../io/path.h" +#include "../io/stream.h" +#include "../str_utils.h" static const int8_t shift_factor_table[] = { 0, 1, 2, 3, 4, 5, 6, 7, -8, -7, -6, -5, -4, -3, -2, -1 @@ -266,7 +266,7 @@ void vag_wwrite(vag* v, wchar_t* path, vag_option option) { size_t c, i, i1, i2; int32_t ch = v->channels; - int32_t* samp = force_malloc_s(int32_t, hevag ? v->channels * 8LL : 4LL); + int32_t* samp = force_malloc_s(int32_t, hevag ? v->channels * 8ULL : 4ULL); if (hevag && coef_index_count > 29) { uint8_t flag, sample; int32_t temp_data[BLOCK_SIZE]; @@ -428,7 +428,7 @@ static void vag_read_wav(vag* v, wchar_t* path, float_t** data, size_t* samples, } if (!count) { - vector_bool_free(&loop); + vector_bool_free(&loop, 0); free(temp_path); return; } @@ -456,7 +456,7 @@ static void vag_read_wav(vag* v, wchar_t* path, float_t** data, size_t* samples, free(wav_samples); free(wav_data); - vector_bool_free(&loop); + vector_bool_free(&loop, 0); free(temp_path); return; } @@ -530,7 +530,7 @@ static void vag_read_wav(vag* v, wchar_t* path, float_t** data, size_t* samples, free(wav_samples); free(wav_data); - vector_bool_free(&loop); + vector_bool_free(&loop, 0); free(temp_path); } @@ -638,7 +638,7 @@ static void calculate_4_bits_vag(int32_t* data, int8_t* four_bit, int32_t* coef_ *coef_index = c_f; calculate_4_bits_vag_inner(data, four_bit, c_f, shift_factor, v, tv, v, tv); - *shift_factor = (int32_t)(20LL - *shift_factor); + *shift_factor = (int32_t)(20ULL - *shift_factor); } static void calculate_4_bits_vag_inner(int32_t* data, int8_t* four_bit, int32_t coef_index, @@ -680,8 +680,8 @@ static void calculate_4_bits_vag_inner(int32_t* data, int8_t* four_bit, int32_t if ((shift_max & (m + (shift_max >> 4))) == shift_max) break; - t_s_f = (int32_t)(8LL + s_f); - s_f = (int32_t)(12LL - s_f); + t_s_f = (int32_t)(8ULL + s_f); + s_f = (int32_t)(12ULL - s_f); int32_t ts1 = tv[0]; int32_t ts2 = tv[1]; @@ -753,7 +753,7 @@ static void calculate_4_bits_hevag(int32_t* data, int8_t* four_bit, int32_t* coe *coef_index = c_f; calculate_4_bits_hevag_inner(data, four_bit, c_f, shift_factor, v, tv, v, tv); - *shift_factor = (int32_t)(20LL - *shift_factor); + *shift_factor = (int32_t)(20ULL - *shift_factor); } static void calculate_4_bits_hevag_inner(int32_t* data, int8_t* four_bit, int32_t coef_index, @@ -803,8 +803,8 @@ static void calculate_4_bits_hevag_inner(int32_t* data, int8_t* four_bit, int32_ if ((shift_max & (m + (shift_max >> 4))) == shift_max) break; - t_s_f = (int32_t)(8LL + s_f); - s_f = (int32_t)(12LL - s_f); + t_s_f = (int32_t)(8ULL + s_f); + s_f = (int32_t)(12ULL - s_f); int32_t ts1 = tv[0]; int32_t ts2 = tv[1]; diff --git a/src/KKdLib/sound_vag.h b/src/KKdLib/sound/vag.h similarity index 96% rename from src/KKdLib/sound_vag.h rename to src/KKdLib/sound/vag.h index b54e3c30..82ebd5cc 100644 --- a/src/KKdLib/sound_vag.h +++ b/src/KKdLib/sound/vag.h @@ -5,7 +5,7 @@ #pragma once -#include "default.h" +#include "../default.h" typedef enum vag_option { VAG_OPTION_VAG, diff --git a/src/KKdLib/sound_wav.c b/src/KKdLib/sound/wav.c similarity index 99% rename from src/KKdLib/sound_wav.c rename to src/KKdLib/sound/wav.c index a6b74acb..a7420eaf 100644 --- a/src/KKdLib/sound_wav.c +++ b/src/KKdLib/sound/wav.c @@ -3,8 +3,8 @@ GitHub/GitLab: korenkonder */ -#include "sound_wav.h" -#include "io_stream.h" +#include "wav.h" +#include "../io/stream.h" wav* wav_init() { wav* w = force_malloc(sizeof(wav)); diff --git a/src/KKdLib/sound_wav.h b/src/KKdLib/sound/wav.h similarity index 96% rename from src/KKdLib/sound_wav.h rename to src/KKdLib/sound/wav.h index a36decc4..aa97ffed 100644 --- a/src/KKdLib/sound_wav.h +++ b/src/KKdLib/sound/wav.h @@ -5,7 +5,7 @@ #pragma once -#include "default.h" +#include "../default.h" typedef struct wav { int32_t size; diff --git a/src/KKdLib/str_utils.c b/src/KKdLib/str_utils.c index 2e59e000..d03a771a 100644 --- a/src/KKdLib/str_utils.c +++ b/src/KKdLib/str_utils.c @@ -41,6 +41,65 @@ bool str_utils_wcheck_ends_with(wchar_t* str, wchar_t* mask) { return false; } +char* str_utils_get_next_int32_t(char* str, int32_t* value, char separator) { + string s; + str = str_utils_get_next_string(str, &s, separator); + sscanf_s(string_data(&s), "%d", value); + string_free(&s); + return str; +} + +wchar_t* str_utils_wget_next_int32_t(wchar_t* str, int32_t* value, wchar_t separator) { + wstring s; + str = str_utils_wget_next_string(str, &s, separator); + swscanf_s(wstring_data(&s), L"%d", value); + wstring_free(&s); + return str; +} + +char* str_utils_get_next_float_t(char* str, float_t* value, char separator) { + string s; + str = str_utils_get_next_string(str, &s, separator); + sscanf_s(string_data(&s), "%f", value); + string_free(&s); + return str; +} + +wchar_t* str_utils_wget_next_float_t(wchar_t* str, float_t* value, wchar_t separator) { + wstring s; + str = str_utils_wget_next_string(str, &s, separator); + swscanf_s(wstring_data(&s), L"%f", value); + wstring_free(&s); + return str; +} + +char* str_utils_get_next_string(char* str, string* value, char separator) { + if (!str) + return 0; + + string_init(value, 0); + while (*str) { + char c = *str++; + if (c == separator) + break; + + string_add_char(value, c); + } + return *str ? str : 0; +} + +wchar_t* str_utils_wget_next_string(wchar_t* str, wstring* value, wchar_t separator) { + wstring_init(value, 0); + while (*str) { + wchar_t c = *str++; + if (c == separator) + break; + + wstring_add_char(value, c); + } + return str; +} + char* str_utils_split_get_right(char* str, char split) { if (!str) return 0; @@ -360,3 +419,250 @@ wchar_t* str_utils_wcopy(wchar_t* str) { memcpy(p, str, sizeof(wchar_t) * len); return p; } + +inline int32_t str_utils_compare(char* str0, char* str1) { + int32_t diff = 0;; + char c0; + char c1; + do + { + c0 = *str0++; + c1 = *str1++; + if (!c0 || !c1) + return c0 - c1; + } while (c0 == c1); + return c0 - c1; +} + +inline int32_t str_utils_wcompare(wchar_t* str0, wchar_t* str1) { + int32_t diff = 0;; + wchar_t c0; + wchar_t c1; + do + { + c0 = *str0++; + c1 = *str1++; + if (!c0 || !c1) + return c0 - c1; + } while (c0 == c1); + return c0 - c1; +} + +inline int32_t str_utils_compare_length(char* str0, size_t str0_len, char* str1, size_t str1_len) { + if (!str0_len) + return -*str1; + else if (!str1_len) + return *str0; + + int32_t diff = 0;; + char c0; + char c1; + do + { + c0 = *str0++; + c1 = *str1++; + if (!c0 || !c1) + return c0 - c1; + } while (c0 == c1 && --str0_len && --str1_len); + return c0 - c1; +} + +inline int32_t str_utils_wcompare_length(wchar_t* str0, size_t str0_len, wchar_t* str1, size_t str1_len) { + if (!str0_len) + return -*str1; + else if (!str1_len) + return *str0; + + int32_t diff = 0;; + wchar_t c0; + wchar_t c1; + do + { + c0 = *str0++; + c1 = *str1++; + if (!c0 || !c1) + return c0 - c1; + } while (c0 == c1 && --str0_len && --str1_len); + return c0 - c1; +} + +size_t str_utils_get_substring_offset(char* str0, size_t str0_len, + size_t str0_off, char* str1, size_t str1_len) { + if (!str1_len && str0_off <= str0_len) + return str0_off; + + if (str0_off < str0_len && str1_len <= str0_len - str0_off) { + size_t len = str0_len - str1_len - str0_off + 1; + char* str = &str0[str0_off]; + for (; len; ) { + char* s = memchr(str, *str1, len); + if (!s) + break; + + if (!str1_len || !memcmp(s, str1, str1_len)) + return s - str0; + + len += str - (s + 1); + str = s + 1; + } + } + return -1; +} + +size_t str_utils_wget_substring_offset(wchar_t* str0, size_t str0_len, + size_t str0_off, wchar_t* str1, size_t str1_len) { + if (!str1_len && str0_off <= str0_len) + return str0_off; + + if (str0_off < str0_len && str1_len <= str0_len - str0_off) { + size_t len = str0_len - str1_len - str0_off + 1; + wchar_t* str = &str0[str0_off]; + for (; len; ) { + wchar_t* s = wmemchr(str, *str1, len); + if (!s) + break; + + if (!str1_len || !memcmp(s, str1, sizeof(wchar_t) * str1_len)) + return s - str0; + + len += str - (s + 1); + str = s + 1; + } + } + return -1; +} + +bool str_utils_text_file_parse(void* data, size_t length, + char** buf, char*** lines, size_t* count) { + if (!data || !length || !buf || !lines || !count) + return false; + + char* d = data; + bool del = false; + size_t c; + *buf = 0; + *lines = 0; + *count = 0; + if ((uint8_t)d[0] == 0x00) + return false; + else if (d[0] == 0xFF) { + if (length == 1 || (uint8_t)d[1] != 0xFE || length == 2) + return false; + + wchar_t* w_d = (wchar_t*)data + 1; + d = utf16_to_utf8(w_d); + length = utf8_length(d); + del = true; + goto decode_utf8_ansi; + } + else if ((uint8_t)d[0] == 0xFE) { + if (length == 1 || (uint8_t)d[1] != 0xFF || length == 2) + return false; + + length /= 2; + wchar_t* w_d = (wchar_t*)data + 1; + w_d = str_utils_wcopy(w_d); + for (size_t i = 0; i < length; i++) + w_d[i] = (wchar_t)reverse_endianness_uint16_t((uint16_t)w_d[i]); + d = utf16_to_utf8(w_d); + length = utf8_length(d); + del = true; + free(w_d); + goto decode_utf8_ansi; + } + else if ((uint8_t)d[0] == 0xEF) { + if (length == 1 || (uint8_t)d[1] != 0xBB || length == 2 || (uint8_t)d[2] != 0xBF || length == 3) + return false; + + d += 3; + length -= 3; + goto decode_utf8_ansi; + } + else { + decode_utf8_ansi: + c = 1; + bool lf; + char ch; + char* t; + lf = false; + t = d; + ch = 0; + + size_t buf_len = length; + for (size_t i = 0, l = 0; i < length; i++) { + ch = *t++; + if (ch == '\r') { + if (i + 1 < length && *t == '\n') { + i++; + t++; + buf_len--; + } + lf = true; + } + else if (ch == '\n') + lf = true; + + if (lf) { + if (!l && c > 1) + buf_len--; + c++; + l = 0; + lf = false; + } + else + l++; + } + + if (ch != '\r' && ch != '\n') + buf_len++; + + lf = false; + t = d; + char* temp_buf = force_malloc(buf_len); + char** temp_lines = force_malloc_s(char*, c); + + char* b = temp_buf; + for (size_t i = 0, j = 0, l = 0; j < c; i++) { + ch = *t++; + if (ch == '\r') { + if (i + 1 < length && *t == '\n') { + i++; + t++; + } + lf = true; + } + else if (ch == '\n') + lf = true; + + if (i >= length || lf) { + temp_lines[j] = b; + if (l) { + memcpy(b, d + i - l, l); + b[l] = 0; + b += l + 1; + } + else if (j) + temp_lines[j]--; + else + *b++ = 0; + j++; + + if (!lf) + break; + + l = 0; + lf = false; + } + else + l++; + } + + *buf = temp_buf; + *lines = temp_lines; + *count = c; + } + + if (del) + free(d); + return true; +} diff --git a/src/KKdLib/str_utils.h b/src/KKdLib/str_utils.h index c986f131..3400bf9e 100644 --- a/src/KKdLib/str_utils.h +++ b/src/KKdLib/str_utils.h @@ -6,10 +6,17 @@ #pragma once #include "default.h" +#include "string.h" extern bool str_utils_check_ends_with(char* str, char* mask); extern bool str_utils_wcheck_ends_with(wchar_t* str, wchar_t* mask); extern char* str_utils_split_get_right(char* str, char split); +extern char* str_utils_get_next_int32_t(char* str, int32_t* value, char separator); +extern wchar_t* str_utils_wget_next_int32_t(wchar_t* str, int32_t* value, wchar_t separator); +extern char* str_utils_get_next_float_t(char* str, float_t* value, char separator); +extern wchar_t* str_utils_wget_next_float_t(wchar_t* str, float_t* value, wchar_t separator); +extern char* str_utils_get_next_string(char* str, string* value, char separator); +extern wchar_t* str_utils_wget_next_string(wchar_t* str, wstring* value, wchar_t separator); extern wchar_t* str_utils_wsplit_get_right(wchar_t* str, wchar_t split); extern char* str_utils_split_get_left(char* str, char split); extern wchar_t* str_utils_wsplit_get_left(wchar_t* str, wchar_t split); @@ -33,3 +40,13 @@ extern char* str_utils_add(char* str0, char* str1); extern wchar_t* str_utils_wadd(wchar_t* str0, wchar_t* str1); extern char* str_utils_copy(char* str); extern wchar_t* str_utils_wcopy(wchar_t* str); +extern int32_t str_utils_compare(char* str0, char* str1); +extern int32_t str_utils_wcompare(wchar_t* str0, wchar_t* str1); +extern int32_t str_utils_compare_length(char* str0, size_t str0_len, char* str1, size_t str1_len); +extern int32_t str_utils_wcompare_length(wchar_t* str0, size_t str0_len, wchar_t* str1, size_t str1_len); +extern size_t str_utils_get_substring_offset(char* str0, size_t str0_len, + size_t str0_off, char* str1, size_t str1_len); +extern size_t str_utils_wget_substring_offset(wchar_t* str0, size_t str0_len, + size_t str0_off, wchar_t* str1, size_t str1_len); +extern bool str_utils_text_file_parse(void* data, size_t length, + char** buf, char*** lines, size_t* count); diff --git a/src/KKdLib/string.c b/src/KKdLib/string.c index 02f3febb..f5a0b407 100644 --- a/src/KKdLib/string.c +++ b/src/KKdLib/string.c @@ -6,83 +6,181 @@ #include "string.h" #include "str_utils.h" -inline void string_init(string* s, char* str) { - if (!str) { - s->data[0] = 0; - s->length = 0; - return; - } +string string_empty = { + .data = "", + .length = 0, + .capacity = STRING_NULL_LENGTH, +}; - s->length = utf8_length(str); - if (s->length > STRING_LENGTH - 1) { - s->ptr = force_malloc(s->length + 1); - memcpy(s->ptr, str, s->length + 1); - } - else - memcpy(s->data, str, s->length + 1); +wstring wstring_empty = { + .data = L"", + .length = 0, + .capacity = WSTRING_NULL_LENGTH, +}; + +vector_func(string) +vector_func(wstring) +vector_ptr_func(string) +vector_ptr_func(wstring) + +static void string_reserve(string* s, size_t size); +static void wstring_reserve(wstring* s, size_t size); + +inline void string_init(string* s, char* str) { + *s = string_empty; + if (!str) + return; + + size_t length = utf8_length(str); + string_reserve(s, length); + memmove(string_data(s), str, length); + s->length = length; + string_data(s)[s->length] = 0; +} + +inline void string_init_length(string* s, char* str, size_t length) { + *s = string_empty; + if (!str && !length) + return; + + string_reserve(s, length); + memmove(string_data(s), str, length); + s->length = length; + string_data(s)[s->length] = 0; } inline char* string_data(string* s) { - return s->length ? s->length > STRING_LENGTH - 1 ? s->ptr : s->data : 0; + return s->capacity > STRING_NULL_LENGTH ? s->ptr : s->data; } inline void string_add(string* s, char* str) { - char* t = str_utils_add(string_data(s), str); - string_free(s); - string_init(s, t); - free(t); + if (!s || !str) + return; + + size_t length = utf8_length(str); + if (!length) + return; + + string_reserve(s, length); + memmove(string_data(s) + s->length, str, length); + s->length += length; + string_data(s)[s->length] = 0; +} + +inline void string_add_length(string* s, char* str, size_t length) { + if (!s || !str || !length) + return; + + string_reserve(s, length); + memmove(string_data(s) + s->length, str, length); + s->length += length; + string_data(s)[s->length] = 0; +} + +inline void string_add_char(string* s, char c) { + if (!s || !c) + return; + + string_reserve(s, 1); + string_data(s)[s->length++] = c; + string_data(s)[s->length] = 0; } inline void string_copy(string* src, string* dst) { - string_init(dst, string_data(src)); + string_init_length(dst, string_data(src), src->length); } inline void string_copy_wstring(wstring* src, string* dst) { - char* temp = utf16_to_utf8(wstring_access(src)); + char* temp = utf16_to_utf8(wstring_data(src)); string_init(dst, temp); free(temp); } -inline size_t string_length(string* s) { - return s->length; +inline void string_replace(string* src, string* dst) { + string_free(dst); + string_copy(src, dst); +} + +inline void string_replace_wstring(wstring* src, string* dst) { + string_free(dst); + string_copy_wstring(src, dst); +} + +inline bool string_compare(string* str0, string* str1) { + if (str0->length != str1->length) + return false; + return !memcmp(string_data(str0), string_data(str1), + str0->length) ? true : false; } inline void string_free(string* s) { - if (s->length > STRING_LENGTH - 1) + if (s->capacity > STRING_NULL_LENGTH) free(s->ptr); - s->data[0] = 0; - s->length = 0; + *s = string_empty; } -inline wchar_t* wstring_access(wstring* s) { - return s->length ? s->length > WSTRING_LENGTH - 1 ? s->ptr : s->data : 0; +inline wchar_t* wstring_data(wstring* s) { + return s->capacity > WSTRING_NULL_LENGTH ? s->ptr : s->data; } inline void wstring_init(wstring* s, wchar_t* str) { - if (!str) { - s->data[0] = 0; - s->length = 0; + *s = wstring_empty; + if (!str) return; - } - s->length = utf16_length(str); - if (s->length > WSTRING_LENGTH - 1) { - s->ptr = force_malloc_s(wchar_t, s->length + 1); - memcpy(s->ptr, str, sizeof(wchar_t) * (s->length + 1)); - } - else - memcpy(s->data, str, sizeof(wchar_t) * (s->length + 1)); + size_t length = utf16_length(str); + wstring_reserve(s, length); + memmove(wstring_data(s), str, sizeof(wchar_t) * length); + s->length = length; + wstring_data(s)[s->length] = 0; +} + +inline void wstring_init_length(wstring* s, wchar_t* str, size_t length) { + *s = wstring_empty; + if (!str || !length) + return; + + wstring_reserve(s, length); + memmove(wstring_data(s), str, sizeof(wchar_t) * length); + s->length = length; + wstring_data(s)[s->length] = 0; } inline void wstring_add(wstring* s, wchar_t* str) { - wchar_t* t = str_utils_wadd(wstring_access(s), str); - wstring_free(s); - wstring_init(s, t); - free(t); + if (!s || !str) + return; + + size_t length = utf16_length(str); + if (!length) + return; + + wstring_reserve(s, length); + memmove(wstring_data(s) + s->length, str, sizeof(wchar_t) * length); + s->length += length; + wstring_data(s)[s->length] = 0; +} + +inline void wstring_add_length(wstring* s, wchar_t* str, size_t length) { + if (!s || !str || !length) + return; + + wstring_reserve(s, length); + memmove(wstring_data(s) + s->length, str, sizeof(wchar_t) * length); + s->length += length; + wstring_data(s)[s->length] = 0; +} + +inline void wstring_add_char(wstring* s, wchar_t c) { + if (!s || !c) + return; + + wstring_reserve(s, 1); + wstring_data(s)[s->length++] = c; + wstring_data(s)[s->length] = 0; } inline void wstring_copy(wstring* src, wstring* dst) { - wstring_init(dst, wstring_access(src)); + wstring_init_length(dst, wstring_data(src), src->length); } inline void wstring_copy_string(string* src, wstring* dst) { @@ -91,13 +189,87 @@ inline void wstring_copy_string(string* src, wstring* dst) { free(temp); } -inline size_t wstring_length(wstring* s) { - return s->length; +inline void wstring_replace(wstring* src, wstring* dst) { + wstring_free(dst); + wstring_copy(src, dst); +} + +inline void wstring_replace_string(string* src, wstring* dst) { + wstring_free(dst); + wstring_copy_string(src, dst); +} + +inline bool wstring_compare(wstring* str0, wstring* str1) { + if (str0->length != str1->length) + return false; + return !memcmp(wstring_data(str0), wstring_data(str1), + sizeof(wchar_t) * str0->length) ? true : false; } inline void wstring_free(wstring* s) { - if (s->length > WSTRING_LENGTH - 1) + if (s->capacity > WSTRING_NULL_LENGTH) free(s->ptr); - s->data[0] = 0; - s->length = 0; + *s = wstring_empty; +} + +static void string_reserve(string* s, size_t size) { + if (s->capacity - s->length >= size) + return; + + size_t capacity = s->capacity; + if ((size_t)(INT64_MAX / sizeof(char) - (capacity >> 1)) >= capacity) + capacity = (capacity >> 1) + capacity; + else + capacity = 0; + capacity = max(capacity, s->length + size); + capacity |= STRING_NULL_LENGTH; + + char* src = string_data(s); + char* dst; + if (capacity > STRING_NULL_LENGTH) + dst = force_malloc(capacity + 1); + else + dst = s->data; + + if (dst != src) + memmove(dst, src, s->length + 1); + + if (capacity > STRING_NULL_LENGTH) + s->ptr = dst; + + if (s->capacity > STRING_NULL_LENGTH) + free(src); + + s->capacity = capacity; +} + +static void wstring_reserve(wstring* s, size_t size) { + if (s->capacity - s->length >= size) + return; + + size_t capacity = s->capacity; + if ((size_t)(INT64_MAX / sizeof(char) - (capacity >> 1)) >= capacity) + capacity = (capacity >> 1) + capacity; + else + capacity = 0; + capacity = max(capacity, s->length + size); + capacity |= WSTRING_NULL_LENGTH; + + wchar_t* src = wstring_data(s); + wchar_t* dst; + if (capacity > STRING_NULL_LENGTH) + dst = force_malloc_s(wchar_t, capacity + 1); + else + dst = s->data; + + if (dst != src) + memmove(dst, src, sizeof(wchar_t) * (s->length + 1)); + + if (capacity > STRING_NULL_LENGTH) + s->ptr = dst; + + if (s->capacity > STRING_NULL_LENGTH) + free(src); + + s->capacity = capacity; } diff --git a/src/KKdLib/string.h b/src/KKdLib/string.h index 40df5803..014dbac0 100644 --- a/src/KKdLib/string.h +++ b/src/KKdLib/string.h @@ -6,16 +6,20 @@ #pragma once #include "default.h" +#include "vector.h" -#define STRING_LENGTH 24 -#define WSTRING_LENGTH 12 +#define STRING_LENGTH (32 - sizeof(size_t) * 2) +#define STRING_NULL_LENGTH (STRING_LENGTH - 1) +#define WSTRING_LENGTH ((32 - sizeof(size_t) * 2) / sizeof(wchar_t)) +#define WSTRING_NULL_LENGTH (WSTRING_LENGTH - 1) typedef struct string { union { char data[STRING_LENGTH]; char* ptr; }; - uint64_t length; + size_t length; + size_t capacity; } string; typedef struct wstring { @@ -23,20 +27,39 @@ typedef struct wstring { wchar_t data[WSTRING_LENGTH]; wchar_t* ptr; }; - uint64_t length; + size_t length; + size_t capacity; } wstring; +extern string string_empty; +extern wstring wstring_empty; + +vector(string) +vector(wstring) +vector_ptr(string) +vector_ptr(wstring) + extern void string_init(string* s, char* str); +extern void string_init_length(string* s, char* str, size_t length); extern char* string_data(string* s); extern void string_add(string* s, char* str); +extern void string_add_length(string* s, char* str, size_t length); +extern void string_add_char(string* s, char c); extern void string_copy(string* src, string* dst); extern void string_copy_wstring(wstring* src, string* dst); -extern size_t string_length(string* s); +extern void string_replace(string* src, string* dst); +extern void string_replace_wstring(wstring* src, string* dst); +extern bool string_compare(string* str0, string* str1); extern void string_free(string* s); extern void wstring_init(wstring* s, wchar_t* str); -extern wchar_t* wstring_access(wstring* s); +extern void wstring_init_length(wstring* s, wchar_t* str, size_t length); +extern wchar_t* wstring_data(wstring* s); extern void wstring_add(wstring* s, wchar_t* str); +extern void wstring_add_length(wstring* s, wchar_t* str, size_t length); +extern void wstring_add_char(wstring* s, wchar_t c); extern void wstring_copy(wstring* src, wstring* dst); extern void wstring_copy_string(string* src, wstring* dst); -extern size_t wstring_length(wstring* s); +extern void wstring_replace(wstring* src, wstring* dst); +extern void wstring_replace_string(string* src, wstring* dst); +extern bool wstring_compare(wstring* str0, wstring* str1); extern void wstring_free(wstring* s); diff --git a/src/KKdLib/txp.c b/src/KKdLib/txp.c index 724bca84..e267dd91 100644 --- a/src/KKdLib/txp.c +++ b/src/KKdLib/txp.c @@ -4,11 +4,16 @@ */ #include "txp.h" -#include "io_stream.h" +#include "f2/struct.h" +#include "io/stream.h" vector_func(txp_mipmap) vector_func(txp) +void txp_init(txp* t) { + memset(t, 0, sizeof(txp)); +} + void txp_copy(txp* src, txp* dst) { memset(dst, 0, sizeof(txp)); dst->has_cube_map = src->has_cube_map; @@ -88,33 +93,37 @@ void txp_free(txp* t) { for (txp_mipmap* i = t->data.begin; i != t->data.end; i++) free(i->data); - vector_txp_mipmap_free(&t->data); + vector_txp_mipmap_free(&t->data, 0); } -bool tex_set_pack_file(vector_txp* t, void** data, size_t* length, bool use_big_endian) { +void txp_set_init(txp_set* ts) { + *ts = vector_empty(txp); +} + +bool txp_set_pack_file(txp_set* ts, void** data, size_t* length, bool big_endian) { size_t l; txp* tex; txp_mipmap* tex_mipmap; - if (!t || !data) + if (!ts || !data) return false; *data = 0; *length = 0; - size_t count = t->end - t->begin; + size_t count = ts->end - ts->begin; if (count < 1) return false; size_t* txp4_offset = force_malloc_s(size_t, count); size_t** txp2_offset = force_malloc_s(size_t*, count); - tex = t->begin; + tex = ts->begin; for (size_t i = 0; i < count; i++, tex++) txp2_offset[i] = force_malloc_s(size_t, (size_t)tex->mipmaps_count * tex->array_size); l = 12 + count * 4; - tex = t->begin; + tex = ts->begin; for (size_t i = 0; i < count; i++, tex++) { txp4_offset[i] = l; l += 12 + (size_t)tex->array_size * tex->mipmaps_count * 4; @@ -131,14 +140,14 @@ bool tex_set_pack_file(vector_txp* t, void** data, size_t* length, bool use_big_ stream s; io_mopen(&s, 0, l); - s.is_big_endian = use_big_endian; + s.is_big_endian = big_endian; io_write_uint32_t_stream_reverse_endianness(&s, 0x03505854); io_write_uint32_t_stream_reverse_endianness(&s, (uint32_t)count); io_write_uint32_t_stream_reverse_endianness(&s, (uint8_t)count | 0x01010100); for (size_t i = 0; i < count; i++) io_write_uint32_t_stream_reverse_endianness(&s, (uint32_t)txp4_offset[i]); - tex = t->begin; + tex = ts->begin; for (size_t i = 0; i < count; i++, tex++) { io_set_position(&s, txp4_offset[i], SEEK_SET); io_write_uint32_t_stream_reverse_endianness(&s, tex->array_size > 1 ? 0x05505854 : 0x04505854); @@ -177,18 +186,39 @@ bool tex_set_pack_file(vector_txp* t, void** data, size_t* length, bool use_big_ return true; } -bool tex_set_produce_enrs(vector_txp* t, vector_enrs_entry* enrs) { +bool txp_set_pack_file_modern(txp_set* ts, void** data, size_t* length, bool big_endian) { + f2_struct st; + memset(&st, 0, sizeof(f2_struct)); + + if (!txp_set_pack_file(ts, &st.data, &st.length, big_endian)) { + *data = 0; + *length = 0; + return false; + } + + txp_set_produce_enrs(ts, &st.enrs); + + st.header.signature = reverse_endianness_uint32_t('MTXD'); + st.header.length = 0x20; + st.header.use_big_endian = big_endian; + st.header.use_section_size = true; + f2_struct_mwrite(&st, data, length, true, false); + f2_struct_free(&st); + return true; +} + +bool txp_set_produce_enrs(txp_set* ts, vector_enrs_entry* enrs) { size_t l; txp* tex; txp_mipmap* tex_mipmap; - if (!t || !enrs) + if (!ts || !enrs) return false; *enrs = vector_empty(enrs_entry); l = 0; - size_t count = t->end - t->begin; + size_t count = ts->end - ts->begin; if (count < 1) return false; @@ -204,9 +234,9 @@ bool tex_set_produce_enrs(vector_txp* t, vector_enrs_entry* enrs) { ee = (enrs_entry){ o, 1, (uint32_t)(count * 4), 1, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, (uint32_t)count, ENRS_DWORD }); vector_enrs_entry_push_back(&e, &ee); - l += (size_t)(o = (uint32_t)(count * 4LL)); + l += (size_t)(o = (uint32_t)(count * 4ULL)); - tex = t->begin; + tex = ts->begin; for (size_t i = 0; i < count; i++, tex++) { ee = (enrs_entry){ o, 1, 12, 1, vector_empty(enrs_sub_entry) }; vector_enrs_sub_entry_push_back(&ee.sub, &(enrs_sub_entry){ 0, 3, ENRS_DWORD }); @@ -233,21 +263,21 @@ bool tex_set_produce_enrs(vector_txp* t, vector_enrs_entry* enrs) { return true; } -bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian) { +bool txp_set_unpack_file(txp_set* ts, void* data, bool big_endian) { uint32_t sign; uint32_t tex_count; - txp tex; - txp_mipmap tex_mipmap; + txp* tex; + txp_mipmap* tex_mipmap; size_t set_d; size_t d; size_t mipmap_d; uint32_t sub_tex_count; uint32_t info; - if (!t || !data) + if (!ts || !data) return false; - if (use_big_endian) + if (big_endian) sign = load_reverse_endianness_uint32_t((void*)data); else sign = *(uint32_t*)data; @@ -255,17 +285,16 @@ bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian) { if (sign != 0x03505854) return false; - tex_set_free(t); set_d = (size_t)data; - if (use_big_endian) + if (big_endian) tex_count = load_reverse_endianness_uint32_t((void*)(set_d + 4)); else tex_count = *(uint32_t*)(set_d + 4); - *t = vector_empty(txp); - vector_txp_reserve(t, tex_count); + *ts = vector_empty(txp); + vector_txp_reserve(ts, tex_count); for (size_t i = 0; i < tex_count; i++) { - if (use_big_endian) { + if (big_endian) { d = set_d + (size_t)load_reverse_endianness_uint32_t((uint32_t*)(set_d + 12) + i); sign = load_reverse_endianness_uint32_t((void*)d); } @@ -277,7 +306,7 @@ bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian) { if (sign != 0x04505854 && sign != 0x05505854) continue; - if (use_big_endian) { + if (big_endian) { sub_tex_count = load_reverse_endianness_uint32_t((void*)(d + 4)); info = load_reverse_endianness_uint32_t((void*)(d + 8)); } @@ -286,20 +315,20 @@ bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian) { info = *(uint32_t*)(d + 8); } - memset(&tex, 0, sizeof(txp)); - tex.has_cube_map = sign == 0x05505854; - tex.mipmaps_count = info & 0xFF; - tex.array_size = (info >> 8) & 0xFF; + tex = vector_txp_reserve_back(ts); + tex->has_cube_map = sign == 0x05505854; + tex->mipmaps_count = info & 0xFF; + tex->array_size = (info >> 8) & 0xFF; - if (tex.array_size == 1 && tex.mipmaps_count != sub_tex_count) - tex.mipmaps_count = sub_tex_count & 0xFF; + if (tex->array_size == 1 && tex->mipmaps_count != sub_tex_count) + tex->mipmaps_count = sub_tex_count & 0xFF; - uint32_t mipmaps_count = tex.mipmaps_count; - tex.data = vector_empty(txp_mipmap); - vector_txp_mipmap_reserve(&tex.data, (size_t)tex.array_size * tex.mipmaps_count); - for (size_t j = 0; j < tex.array_size; j++) - for (size_t k = 0; k < tex.mipmaps_count; k++) { - if (use_big_endian) { + uint32_t mipmaps_count = tex->mipmaps_count; + tex->data = vector_empty(txp_mipmap); + vector_txp_mipmap_reserve(&tex->data, (size_t)tex->array_size * tex->mipmaps_count); + for (size_t j = 0; j < tex->array_size; j++) + for (size_t k = 0; k < tex->mipmaps_count; k++) { + if (big_endian) { mipmap_d = d + (size_t)load_reverse_endianness_uint32_t((uint32_t*)(d + 12) + j * mipmaps_count + k); sign = load_reverse_endianness_uint32_t((void*)mipmap_d); } @@ -308,42 +337,50 @@ bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian) { sign = *(uint32_t*)mipmap_d; } - memset(&tex_mipmap, 0, sizeof(txp_mipmap)); + tex_mipmap = vector_txp_mipmap_reserve_back(&tex->data); - if (use_big_endian) { - tex_mipmap.width = load_reverse_endianness_uint32_t((void*)(mipmap_d + 4)); - tex_mipmap.height = load_reverse_endianness_uint32_t((void*)(mipmap_d + 8)); - tex_mipmap.format = load_reverse_endianness_uint32_t((void*)(mipmap_d + 12)); - tex_mipmap.size = load_reverse_endianness_uint32_t((void*)(mipmap_d + 20)); + if (big_endian) { + tex_mipmap->width = load_reverse_endianness_uint32_t((void*)(mipmap_d + 4)); + tex_mipmap->height = load_reverse_endianness_uint32_t((void*)(mipmap_d + 8)); + tex_mipmap->format = load_reverse_endianness_uint32_t((void*)(mipmap_d + 12)); + tex_mipmap->size = load_reverse_endianness_uint32_t((void*)(mipmap_d + 20)); } else { - tex_mipmap.width = *(uint32_t*)(mipmap_d + 4); - tex_mipmap.height = *(uint32_t*)(mipmap_d + 8); - tex_mipmap.format = *(uint32_t*)(mipmap_d + 12); - tex_mipmap.size = *(uint32_t*)(mipmap_d + 20); + tex_mipmap->width = *(uint32_t*)(mipmap_d + 4); + tex_mipmap->height = *(uint32_t*)(mipmap_d + 8); + tex_mipmap->format = *(uint32_t*)(mipmap_d + 12); + tex_mipmap->size = *(uint32_t*)(mipmap_d + 20); } - ssize_t size = txp_get_size(tex_mipmap.format, tex_mipmap.width, tex_mipmap.height); - tex_mipmap.data = force_malloc(max(size, tex_mipmap.size)); - memcpy(tex_mipmap.data, (void*)(mipmap_d + 24), tex_mipmap.size); - size -= tex_mipmap.size; + ssize_t size = txp_get_size(tex_mipmap->format, tex_mipmap->width, tex_mipmap->height); + tex_mipmap->data = force_malloc(max(size, tex_mipmap->size)); + memcpy(tex_mipmap->data, (void*)(mipmap_d + 24), tex_mipmap->size); + size -= tex_mipmap->size; if (size > 0) - memset((void*)((size_t)tex_mipmap.data + tex_mipmap.size), 0, size); - vector_txp_mipmap_push_back(&tex.data, &tex_mipmap); + memset((void*)((size_t)tex_mipmap->data + tex_mipmap->size), 0, size); } - vector_txp_push_back(t, &tex); } return true; } -void tex_set_free(vector_txp* t) { +bool txp_set_unpack_file_modern(txp_set* ts, void* data, size_t length) { + bool ret = false; + f2_struct st; + f2_struct_mread(&st, data, length); + if (st.header.signature == reverse_endianness_uint32_t('MTXD')) + ret = txp_set_unpack_file(ts, st.data, st.header.use_big_endian); + f2_struct_free(&st); + return ret; +} + +void txp_set_free(txp_set* t) { if (!t) return; for (txp* i = t->begin; i != t->end; i++) { for (txp_mipmap* j = i->data.begin; j != i->data.end; j++) free(j->data); - vector_txp_mipmap_free(&i->data); + vector_txp_mipmap_free(&i->data, 0); } - vector_txp_free(t); + vector_txp_free(t, 0); } diff --git a/src/KKdLib/txp.h b/src/KKdLib/txp.h index 06b8b56d..99b41356 100644 --- a/src/KKdLib/txp.h +++ b/src/KKdLib/txp.h @@ -6,7 +6,7 @@ #pragma once #include "default.h" -#include "f2_enrs.h" +#include "f2/enrs.h" #include "vector.h" typedef enum txp_format { @@ -45,10 +45,16 @@ typedef struct txp { vector(txp) +typedef vector_txp txp_set; + +extern void txp_init(txp* t); extern void txp_copy(txp* src, txp* dst); extern uint32_t txp_get_size(txp_format format, uint32_t width, uint32_t height); extern void txp_free(txp* t); -extern bool tex_set_pack_file(vector_txp* t, void** data, size_t* length, bool use_big_endian); -extern bool tex_set_produce_enrs(vector_txp* t, vector_enrs_entry* enrs); -extern bool tex_set_unpack_file(vector_txp* t, void* data, bool use_big_endian); -extern void tex_set_free(vector_txp* t); +extern void txp_set_init(txp_set* ts); +extern bool txp_set_pack_file(txp_set* ts, void** data, size_t* length, bool big_endian); +extern bool txp_set_pack_file_modern(txp_set* ts, void** data, size_t* length, bool big_endian); +extern bool txp_set_produce_enrs(txp_set* ts, vector_enrs_entry* enrs); +extern bool txp_set_unpack_file(txp_set* ts, void* data, bool big_endian); +extern bool txp_set_unpack_file_modern(txp_set* ts, void* data, size_t length); +extern void txp_set_free(txp_set* ts); diff --git a/src/KKdLib/types.h b/src/KKdLib/types.h index 62e56f71..95e1429a 100644 --- a/src/KKdLib/types.h +++ b/src/KKdLib/types.h @@ -8,6 +8,7 @@ #include #include #include +#include #define FASTCALL __fastcall #define ALIGN(n) __declspec(align(n)) diff --git a/src/KKdLib/vec.c b/src/KKdLib/vec.c index ddd3fc09..8952151b 100644 --- a/src/KKdLib/vec.c +++ b/src/KKdLib/vec.c @@ -9,6 +9,9 @@ const __m128 vec2_negate = { .m128_f32 = { -0.0, -0.0, 0.0, 0.0 } }; const __m128 vec3_negate = { .m128_f32 = { -0.0, -0.0, -0.0, 0.0 } }; const __m128 vec4_negate = { .m128_f32 = { -0.0, -0.0, -0.0, -0.0 } }; +const __m128 vec4_mask_vec2 = { .m128_u32 = { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 } }; +const __m128 vec4_mask_vec3 = { .m128_u32 = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 } }; + const __m128d vec2d_negate = { -0.0, -0.0 }; const vec2 vec2_identity = { 1.0f, 1.0f }; @@ -26,3 +29,24 @@ const vec4i vec4i_null = { 0, 0, 0, 0 }; const vec2d vec2d_identity = { 1.0f, 1.0f }; const vec2d vec2d_null = { 0.0f, 0.0f }; + +const vec4u vec4u_identity = { 1.0f, 1.0f, 1.0f, 1.0f }; + +const vec4u vec4u_null = { 0.0f, 0.0f, 0.0f, 0.0f }; + +const vec4iu vec4iu_null = { 0, 0, 0, 0 }; + +vector_func(vec2) +vector_func(vec2i) +vector_func(vec3) +vector_func(vec3i) +vector_func(vec4) +vector_func(vec4i) +vector_ptr_func(vec2) +vector_ptr_func(vec2i) +vector_ptr_func(vec3) +vector_ptr_func(vec3i) +vector_ptr_func(vec4) +vector_ptr_func(vec4i) + +// Crutch for vector_func definition diff --git a/src/KKdLib/vec.h b/src/KKdLib/vec.h index 7b7acd02..a259bd2b 100644 --- a/src/KKdLib/vec.h +++ b/src/KKdLib/vec.h @@ -7,6 +7,7 @@ #include "default.h" #include "half_t.h" +#include "vector.h" #include #include @@ -150,10 +151,27 @@ typedef struct vec2d { __m128d data; } vec2d; +typedef struct vec4u { + float_t x; + float_t y; + float_t z; + float_t w; +} vec4u; + +typedef struct vec4iu { + int32_t x; + int32_t y; + int32_t z; + int32_t w; +} vec4iu; + extern const __m128 vec2_negate; extern const __m128 vec3_negate; extern const __m128 vec4_negate; +extern const __m128 vec4_mask_vec2; +extern const __m128 vec4_mask_vec3; + extern const __m128 vec4_negate; extern const vec2 vec2_identity; @@ -172,6 +190,25 @@ extern const vec2d vec2d_identity; extern const vec2d vec2d_null; +extern const vec4u vec4u_identity; + +extern const vec4u vec4u_null; + +extern const vec4iu vec4iu_null; + +vector(vec2) +vector(vec2i) +vector(vec3) +vector(vec3i) +vector(vec4) +vector(vec4i) +vector_ptr(vec2) +vector_ptr(vec2i) +vector_ptr(vec3) +vector_ptr(vec3i) +vector_ptr(vec4) +vector_ptr(vec4i) + #define vec2i8_to_vec2(src, dst) \ (dst).x = (float_t)(src).x; \ (dst).y = (float_t)(src).y; @@ -442,6 +479,30 @@ extern const vec2d vec2d_null; (dst).z = (uint16_t)(src).z; \ (dst).w = (uint16_t)(src).w; +#define vec4_to_vec4u(src, dst) \ +(dst).x = (src).x; \ +(dst).y = (src).y; \ +(dst).z = (src).z; \ +(dst).w = (src).w; + +#define vec4u_to_vec4(src, dst) \ +(dst).x = (src).x; \ +(dst).y = (src).y; \ +(dst).z = (src).z; \ +(dst).w = (src).w; + +#define vec4i_to_vec4iu(src, dst) \ +(dst).x = (src).x; \ +(dst).y = (src).y; \ +(dst).z = (src).z; \ +(dst).w = (src).w; + +#define vec4iu_to_vec4i(src, dst) \ +(dst).x = (src).x; \ +(dst).y = (src).y; \ +(dst).z = (src).z; \ +(dst).w = (src).w; + #define vec2_add(x, y, z) \ { \ __m128 xt; \ @@ -1187,9 +1248,10 @@ extern const vec2d vec2d_null; *(vec3*)&xt = (x); \ *(vec3*)&yt = (y); \ zt = _mm_sub_ps( \ - _mm_mul_ps(_mm_shuffle_ps(xt, xt, 0x09), _mm_shuffle_ps(yt, yt, 0x12)), \ - _mm_mul_ps(_mm_shuffle_ps(xt, xt, 0x12), _mm_shuffle_ps(yt, yt, 0x09)) \ + _mm_mul_ps(xt, _mm_shuffle_ps(yt, yt, 0x09)), \ + _mm_mul_ps(yt, _mm_shuffle_ps(xt, xt, 0x09)) \ ); \ + zt = _mm_shuffle_ps(zt, zt, 0x09); \ (z) = *(vec3*)&zt; \ } diff --git a/src/KKdLib/vector.c b/src/KKdLib/vector.c index 9a1c446b..198fa48d 100644 --- a/src/KKdLib/vector.c +++ b/src/KKdLib/vector.c @@ -18,19 +18,8 @@ vector_func(int64_t) vector_func(uint64_t) vector_func(size_t) vector_func(ssize_t) -vector_func(half_t) vector_func(float_t) vector_func(double_t) -vector_func(string) -vector_func(wstring) -vector_func(vec2) -vector_func(vec2i) -vector_func(vec3) -vector_func(vec3i) -vector_func(vec4) -vector_func(vec4i) -vector_func(mat3) -vector_func(mat4) vector_ptr_func(char) vector_ptr_func(wchar_t) vector_ptr_func(bool) @@ -44,17 +33,6 @@ vector_ptr_func(int64_t) vector_ptr_func(uint64_t) vector_ptr_func(size_t) vector_ptr_func(ssize_t) -vector_ptr_func(half_t) vector_ptr_func(float_t) vector_ptr_func(double_t) vector_ptr_func(void) -vector_ptr_func(string) -vector_ptr_func(wstring) -vector_ptr_func(vec2) -vector_ptr_func(vec2i) -vector_ptr_func(vec3) -vector_ptr_func(vec3i) -vector_ptr_func(vec4) -vector_ptr_func(vec4i) -vector_ptr_func(mat3) -vector_ptr_func(mat4) diff --git a/src/KKdLib/vector.h b/src/KKdLib/vector.h index 82edb27b..f5180bda 100644 --- a/src/KKdLib/vector.h +++ b/src/KKdLib/vector.h @@ -6,10 +6,6 @@ #pragma once #include "default.h" -#include "half_t.h" -#include "mat.h" -#include "string.h" -#include "vec.h" #define vector_dispose_func(t) void(* dispose_func)(t* data) #define vector_empty(t) (vector_##t){ 0, 0, 0 } @@ -24,14 +20,17 @@ typedef struct vector_##t { \ \ extern void vector_##t##_reserve(vector_##t* vec, ssize_t size); \ extern void vector_##t##_push_back(vector_##t* vec, t* val); \ -extern void vector_##t##_pop_back(vector_##t* vec); \ +extern t* vector_##t##_reserve_back(vector_##t* vec); \ +extern void vector_##t##_pop_back(vector_##t* vec, vector_dispose_func(t)); \ extern void vector_##t##_insert(vector_##t* vec, ssize_t position, t* val); \ extern void vector_##t##_insert_range(vector_##t* vec, ssize_t position, t* first, t* last); \ -extern void vector_##t##_erase(vector_##t* vec, ssize_t position); \ -extern void vector_##t##_erase_range(vector_##t* vec, ssize_t first, ssize_t last); \ +extern void vector_##t##_erase(vector_##t* vec, \ + ssize_t position, vector_dispose_func(t)); \ +extern void vector_##t##_erase_range(vector_##t* vec, \ + ssize_t first, ssize_t last, vector_dispose_func(t)); \ extern void vector_##t##_swap(vector_##t* vec1, vector_##t* vec2); \ -extern void vector_##t##_clear(vector_##t* vec); \ -extern void vector_##t##_free(vector_##t* vec); +extern void vector_##t##_clear(vector_##t* vec, vector_dispose_func(t)); \ +extern void vector_##t##_free(vector_##t* vec, vector_dispose_func(t)); #define vector_ptr(t) \ typedef struct vector_ptr_##t { \ @@ -40,9 +39,9 @@ typedef struct vector_ptr_##t { \ t** capacity_end; \ } vector_ptr_##t; \ \ -\ extern void vector_ptr_##t##_reserve(vector_ptr_##t* vec, ssize_t size); \ extern void vector_ptr_##t##_push_back(vector_ptr_##t* vec, t** val); \ +extern t** vector_ptr_##t##_reserve_back(vector_ptr_##t* vec); \ extern void vector_ptr_##t##_pop_back(vector_ptr_##t* vec, vector_dispose_func(t)); \ extern void vector_ptr_##t##_insert(vector_ptr_##t* vec, ssize_t position, t** val); \ extern void vector_ptr_##t##_insert_range(vector_ptr_##t* vec, ssize_t position, t** first, t** last); \ @@ -54,7 +53,33 @@ extern void vector_ptr_##t##_swap(vector_ptr_##t* vec1, vector_ptr_##t* vec2); \ extern void vector_ptr_##t##_clear(vector_ptr_##t* vec, vector_dispose_func(t)); \ extern void vector_ptr_##t##_free(vector_ptr_##t* vec, vector_dispose_func(t)); -#define vector_func(t) \ +#define vector_func(t)\ +void vector_##t##_reserve(vector_##t* vec, ssize_t size) { \ + if (vec->capacity_end - vec->end >= size) \ + return; \ +\ + ssize_t capacity = vec->capacity_end - vec->begin; \ + if ((ssize_t)(INT64_MAX / sizeof(t) - (capacity >> 1)) >= capacity) \ + capacity = (capacity >> 1) + capacity; \ + else \ + capacity = 0; \ + capacity = max(capacity, vec->end - vec->begin + size); \ +\ + t* temp = 0; \ + if (capacity) \ + temp = force_malloc_s(t, capacity); \ +\ + if (!temp) \ + return; \ +\ + memmove(temp, vec->begin, sizeof(t) * (vec->end - vec->begin)); \ + ssize_t length = vec->end - vec->begin; \ + free(vec->begin); \ + vec->capacity_end = &temp[capacity]; \ + vec->end = &temp[length]; \ + vec->begin = temp; \ +} \ +\ void vector_##t##_push_back(vector_##t* vec, t* val) { \ if (!vec || !val) \ return; \ @@ -66,12 +91,27 @@ void vector_##t##_push_back(vector_##t* vec, t* val) { \ vec->end++; \ } \ \ -void vector_##t##_pop_back(vector_##t* vec) { \ +t* vector_##t##_reserve_back(vector_##t* vec) { \ + if (!vec) \ + return 0; \ +\ + if (vec->capacity_end - vec->end < 1) \ + vector_##t##_reserve(vec, vec->end - vec->capacity_end + 1); \ +\ + t* val = vec->end++; \ + memset(val, 0, sizeof(t)); \ + return val; \ +} \ +\ +void vector_##t##_pop_back(vector_##t* vec, vector_dispose_func(t)) { \ if (!vec) \ return; \ \ - if (vec->end - vec->begin > 0) \ + if (vec->end - vec->begin > 0) { \ + if (dispose_func) \ + dispose_func(&vec->end[1]); \ vec->end--; \ + } \ } \ \ void vector_##t##_insert(vector_##t* vec, ssize_t position, t* val) { \ @@ -108,17 +148,22 @@ void vector_##t##_insert_range(vector_##t* vec, ssize_t position, t* first, t* l vec->end += s; \ } \ \ -void vector_##t##_erase(vector_##t* vec, ssize_t position) { \ +void vector_##t##_erase(vector_##t* vec, \ + ssize_t position, vector_dispose_func(t)) { \ if (!vec || vec->end - vec->begin <= position) \ return; \ \ t* t0 = vec->begin + position; \ t* t1 = vec->begin + position + 1; \ + if (dispose_func) \ + dispose_func(t0); \ +\ memmove(t0, t1, sizeof(t) * (vec->end - t1)); \ vec->end--; \ } \ \ -void vector_##t##_erase_range(vector_##t* vec, ssize_t first, ssize_t last) { \ +void vector_##t##_erase_range(vector_##t* vec, \ + ssize_t first, ssize_t last, vector_dispose_func(t)) { \ if (!vec || !last || last - first < 1) \ return; \ \ @@ -128,6 +173,10 @@ void vector_##t##_erase_range(vector_##t* vec, ssize_t first, ssize_t last) { \ \ t* t0 = vec->begin + s; \ t* t1 = vec->begin + s + 1; \ + if (dispose_func) \ + for (ssize_t i = 0; i < s; i++) \ + dispose_func(&t0[i]); \ +\ memmove(t0, t1, sizeof(t) * (vec->end - t1)); \ vec->end -= s; \ } \ @@ -141,52 +190,57 @@ void vector_##t##_swap(vector_##t* vec1, vector_##t* vec2) { \ *vec2 = vec; \ } \ \ -void vector_##t##_clear(vector_##t* vec) { \ +void vector_##t##_clear(vector_##t* vec, vector_dispose_func(t)) { \ + if (!vec) \ + return; \ +\ + if (dispose_func) \ + for (t* i = vec->begin; i != vec->end; i++) \ + dispose_func(i); \ vec->end = vec->begin; \ } \ \ -void vector_##t##_free(vector_##t* vec) { \ +void vector_##t##_free(vector_##t* vec, vector_dispose_func(t)) { \ + if (!vec) \ + return; \ +\ + if (dispose_func) \ + for (t* i = vec->begin; i != vec->end; i++) \ + dispose_func(i); \ +\ free(vec->begin); \ vec->begin = 0; \ vec->end = 0; \ vec->capacity_end = 0; \ -} \ -\ -void vector_##t##_reserve(vector_##t* vec, ssize_t size) { \ +} + +#define vector_ptr_func(t)\ +void vector_ptr_##t##_reserve(vector_ptr_##t* vec, ssize_t size) { \ if (vec->capacity_end - vec->end >= size) \ return; \ \ - ssize_t count = vec->end - vec->begin + size; \ ssize_t capacity = vec->capacity_end - vec->begin; \ - if ((ssize_t)(INT64_MAX / sizeof(t) - (capacity >> 1)) >= capacity) { \ - ssize_t _count = (capacity >> 1) + capacity; \ - if (_count < count) \ - _count = vec->end - vec->begin + size; \ - count = _count; \ - } \ - else { \ - ssize_t _count = 0; \ - if (count) \ - _count = vec->end - vec->begin + size; \ - count = _count; \ - } \ + if ((ssize_t)(INT64_MAX / sizeof(t*) - (capacity >> 1)) >= capacity) \ + capacity = (capacity >> 1) + capacity; \ + else \ + capacity = 0; \ + capacity = max(capacity, vec->end - vec->begin + size); \ \ - t* temp = 0; \ - if (count) \ - temp = force_malloc_s(t, count); \ + t** temp = 0; \ + if (capacity) \ + temp = force_malloc_s(t*, capacity); \ \ if (!temp) \ return; \ \ - memmove(temp, vec->begin, sizeof(t) * (vec->end - vec->begin)); \ + memmove(temp, vec->begin, sizeof(t*) * (vec->end - vec->begin)); \ ssize_t length = vec->end - vec->begin; \ free(vec->begin); \ - vec->capacity_end = &temp[count]; \ + vec->capacity_end = &temp[capacity]; \ vec->end = &temp[length]; \ vec->begin = temp; \ -} - -#define vector_ptr_func(t) \ +} \ +\ void vector_ptr_##t##_push_back(vector_ptr_##t* vec, t** val) { \ if (!vec || !val) \ return; \ @@ -197,6 +251,18 @@ void vector_ptr_##t##_push_back(vector_ptr_##t* vec, t** val) { \ *vec->end++ = *val; \ } \ \ +t** vector_ptr_##t##_reserve_back(vector_ptr_##t* vec) { \ + if (!vec) \ + return 0; \ +\ + if (vec->capacity_end - vec->end < 1) \ + vector_ptr_##t##_reserve(vec, vec->end - vec->capacity_end + 1); \ +\ + t** val = vec->end++; \ + memset(val, 0, sizeof(t*)); \ + return val; \ +} \ +\ void vector_ptr_##t##_pop_back(vector_ptr_##t* vec, vector_dispose_func(t)) { \ if (!vec) \ return; \ @@ -272,12 +338,13 @@ void vector_ptr_##t##_erase_range(vector_ptr_##t* vec, \ \ t** t0 = vec->begin + first; \ t** t1 = vec->begin + first + s; \ - if (dispose_func) \ + if (dispose_func) { \ for (ssize_t i = 0; i < s; i++) \ if (t0[i]) { \ dispose_func(t0[i]); \ t0[i] = 0; \ } \ + } \ else \ for (ssize_t i = 0; i < s; i++) \ free(t0[i]); \ @@ -299,12 +366,13 @@ void vector_ptr_##t##_clear(vector_ptr_##t* vec, vector_dispose_func(t)) { \ if (!vec) \ return; \ \ - if (dispose_func) \ + if (dispose_func) { \ for (t** i = vec->begin; i != vec->end; i++) \ if (*i) { \ dispose_func(*i); \ *i = 0; \ } \ + } \ else \ for (t** i = vec->begin; i != vec->end; i++) \ free(*i); \ @@ -315,12 +383,13 @@ void vector_ptr_##t##_free(vector_ptr_##t* vec, vector_dispose_func(t)) { \ if (!vec) \ return; \ \ - if (dispose_func) \ + if (dispose_func) { \ for (t** i = vec->begin; i != vec->end; i++) \ if (*i) { \ dispose_func(*i); \ *i = 0; \ } \ + } \ else \ for (t** i = vec->begin; i != vec->end; i++) \ free(*i); \ @@ -329,40 +398,6 @@ void vector_ptr_##t##_free(vector_ptr_##t* vec, vector_dispose_func(t)) { \ vec->begin = 0; \ vec->end = 0; \ vec->capacity_end = 0; \ -} \ -\ -void vector_ptr_##t##_reserve(vector_ptr_##t* vec, ssize_t size) { \ - if (vec->capacity_end - vec->end >= size) \ - return; \ -\ - ssize_t count = vec->end - vec->begin + size; \ - ssize_t capacity = vec->capacity_end - vec->begin; \ - if ((ssize_t)(INT64_MAX / sizeof(t*) - (capacity >> 1)) >= capacity) { \ - ssize_t _count = (capacity >> 1) + capacity; \ - if (_count < count) \ - _count = vec->end - vec->begin + size; \ - count = _count; \ - } \ - else { \ - ssize_t _count = 0; \ - if (count) \ - _count = vec->end - vec->begin + size; \ - count = _count; \ - } \ -\ - t** temp = 0; \ - if (count) \ - temp = force_malloc_s(t*, count); \ -\ - if (!temp) \ - return; \ -\ - memmove(temp, vec->begin, sizeof(t*) * (vec->end - vec->begin)); \ - ssize_t length = vec->end - vec->begin; \ - free(vec->begin); \ - vec->capacity_end = &temp[count]; \ - vec->end = &temp[length]; \ - vec->begin = temp; \ } vector(char) @@ -378,19 +413,8 @@ vector(int64_t) vector(uint64_t) vector(size_t) vector(ssize_t) -vector(half_t) vector(float_t) vector(double_t) -vector(string) -vector(wstring) -vector(vec2) -vector(vec2i) -vector(vec3) -vector(vec3i) -vector(vec4) -vector(vec4i) -vector(mat3) -vector(mat4) vector_ptr(char) vector_ptr(wchar_t) vector_ptr(bool) @@ -404,17 +428,6 @@ vector_ptr(int64_t) vector_ptr(uint64_t) vector_ptr(size_t) vector_ptr(ssize_t) -vector_ptr(half_t) vector_ptr(float_t) vector_ptr(double_t) -vector_ptr(void) -vector_ptr(string) -vector_ptr(wstring) -vector_ptr(vec2) -vector_ptr(vec2i) -vector_ptr(vec3) -vector_ptr(vec3i) -vector_ptr(vec4) -vector_ptr(vec4i) -vector_ptr(mat3) -vector_ptr(mat4) +vector_ptr(void) \ No newline at end of file diff --git a/thirdparty.txt b/thirdparty.txt index 9b311a19..2980f69b 100644 --- a/thirdparty.txt +++ b/thirdparty.txt @@ -201,347 +201,3 @@ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIO CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- - -libx264 - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License.