Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
7114278842 | |||
1dbe69cd8b | |||
1dbe9df091 | |||
88c90b39bb | |||
023c63617d | |||
9e551619a1 | |||
1deb5eae2c | |||
ec82ff4158 | |||
3307cfaab7 | |||
3614742343 | |||
c0b26e7b42 | |||
7ba1037230 | |||
d40a9f921c |
1
.gitignore
vendored
1
.gitignore
vendored
@ -75,3 +75,4 @@ install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
CMakeUserPresets.json
|
||||
|
@ -1,14 +1,14 @@
|
||||
# CMakeLists.txt
|
||||
|
||||
####################################################
|
||||
# Written by JackCarterSmith, 2022
|
||||
# Written by JackCarterSmith, 2023
|
||||
# This code is released under the RSE license.
|
||||
####################################################
|
||||
|
||||
|
||||
# CMake requirement and general configuration
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
cmake_policy(VERSION 3.12)
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
cmake_policy(VERSION 3.15)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
|
||||
if(DEFINED ENV{MS_COMPATIBLE})
|
||||
set(CMAKE_GNUtoMS ON) # Enable compatibility level to exported libraries
|
||||
@ -20,11 +20,10 @@ if(DEFINED ENV{CI}) # Jenkins CI integration mode
|
||||
project(rse-model VERSION $ENV{CI_VERSION}.$ENV{CI_BUILD_NUMBER} DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
|
||||
set(RSE_MODEL_NAME $ENV{CI_OUTPUT_NAME})
|
||||
else() # Standalone project mode, should not be used for release.
|
||||
project(rse-model VERSION 2.2.0 DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
|
||||
project(rse-model VERSION 2.4.0 DESCRIPTION "RogueSquadron Extractor - Model" LANGUAGES C)
|
||||
set(RSE_MODEL_NAME RSEModel)
|
||||
endif()
|
||||
set(RSP_MODEL_LIB_NAME RSPModel${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
|
||||
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
|
||||
@ -82,7 +81,7 @@ endif()
|
||||
|
||||
|
||||
# Install dependancies
|
||||
install(FILES ${PROJECT_BINARY_DIR}/bin/glew32.dll
|
||||
install(FILES ${PROJECT_BINARY_DIR}/bin/glew32.dll ${PROJECT_BINARY_DIR}/bin/vulkan-1.dll
|
||||
DESTINATION ${INSTALL_BIN_DIR})
|
||||
|
||||
# Install library includes
|
||||
|
15
Jenkinsfile
vendored
15
Jenkinsfile
vendored
@ -5,14 +5,13 @@ pipeline {
|
||||
}
|
||||
environment {
|
||||
CI_OUTPUT_NAME = "RSEModel"
|
||||
CI_VERSION = "2.2.0"
|
||||
CI_VERSION = "2.3.1"
|
||||
CI_BUILD_NUMBER = "$BUILD_NUMBER"
|
||||
}
|
||||
stages {
|
||||
stage('Prepare') {
|
||||
steps {
|
||||
cleanWs()
|
||||
rtConanClient(id: "conan", userHome: "/home/jackcartersmith")
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
@ -22,20 +21,16 @@ pipeline {
|
||||
dir("linux") {
|
||||
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Model'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Model.git']]])
|
||||
sh 'git submodule update --init --recursive'
|
||||
dir("build") {
|
||||
rtConanRun(clientId: "conan", command: "install .. --build=missing")
|
||||
}
|
||||
cmakeBuild buildDir: 'build', installation: 'latest', steps: [[args: 'all']]
|
||||
sh 'conan install . -of build -s build_type=Release -o "&:tools=True" -pr:b=default -pr:h=default --build=missing'
|
||||
cmakeBuild buildDir: 'build', cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DRSPMODEL_SHARED=ON -DRSPMODEL_STATIC=OFF -DBUILD_TOOLS=ON -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release', installation: 'latest', steps: [[args: 'all']]
|
||||
}
|
||||
},
|
||||
windows: {
|
||||
dir("windows") {
|
||||
checkout([$class: 'GitSCM', branches: [[name: '**']], browser: [$class: 'GiteaBrowser', repoUrl: 'https://git.jcsmith.fr/JCS-Prod/RSE-Model'], extensions: [], userRemoteConfigs: [[credentialsId: 'jenkins-ssh', url: 'ssh://git@git.jcsmith.fr:2322/JCS-Prod/RSE-Model.git']]])
|
||||
sh 'git submodule update --init --recursive'
|
||||
dir("build") {
|
||||
rtConanRun(clientId: "conan", command: "install .. -pr:b=default -pr:h=windows --build=missing")
|
||||
}
|
||||
cmakeBuild buildDir: 'build', cmakeArgs: '-DGNU_HOST=x86_64-w64-mingw32 -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw_cross_toolchain.cmake', installation: 'latest', steps: [[args: 'all']]
|
||||
sh 'conan install . -of build -s build_type=Release -o "&:tools=True" -pr:b=default -pr:h=windows --build=missing'
|
||||
cmakeBuild buildDir: 'build', cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DRSPMODEL_SHARED=ON -DRSPMODEL_STATIC=OFF -DBUILD_TOOLS=ON -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres', installation: 'latest', steps: [[args: 'all']]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
207
LICENSE-vulkan
Normal file
207
LICENSE-vulkan
Normal file
@ -0,0 +1,207 @@
|
||||
The majority of files in this project use the Apache 2.0 License.
|
||||
There are a few exceptions and their license can be found in the source.
|
||||
Any license deviations from Apache 2.0 are "more permissive" licenses.
|
||||
|
||||
===========================================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
23
README.md
23
README.md
@ -22,13 +22,14 @@ This module can do:
|
||||
|
||||
- Add textures to models.
|
||||
- Discover all unknowns fields, animations, bones mesh, etc.
|
||||
- Full Conan build pipeline
|
||||
|
||||
### Using
|
||||
|
||||
`RSEModel [options] <hob files...>` or you can simply drag&drop HOB files on it.
|
||||
|
||||
A futur main program can extract all HOB files directly from DAT file.
|
||||
Due to issue with copyrights, I can't provide samples... You need to extract HOB files yourself.
|
||||
Due to issues with copyrights, I can't provide samples and my DAT file parser is unfinished... You need to extract HOB files yourself.
|
||||
|
||||
<img src="https://repo.jcsmith.fr/pictures/rse-model.gif" width="620" height="400" />
|
||||
|
||||
@ -45,22 +46,12 @@ Due to issue with copyrights, I can't provide samples... You need to extract HOB
|
||||
|
||||
### Compiling
|
||||
|
||||
You can compile on both Windows (MinGW) or native Linux system thanks to CMake.
|
||||
|
||||
To compile, just clone (**don't forget git submodules**) and launch cmake:
|
||||
I've a preference for compiling libraries by hand, mainly for backward compatibility, but I recommend using Conan packages manager (https://conan.io) for simplicity. (**Don't forget git submodules**)
|
||||
|
||||
```shell
|
||||
cmake .
|
||||
make
|
||||
make install
|
||||
conan install . -of build -b missing -s build_type=Release -o tools=True -pr:b=default -pr:h=default
|
||||
cmake --preset conan-release -G "Unix Makefiles"
|
||||
cmake --build --preset conan-release
|
||||
```
|
||||
|
||||
We can also use cross-compilation (after installing `mingw64` and `cmake` packages on your distrib):
|
||||
|
||||
```shell
|
||||
mkdir build && cd build
|
||||
cmake -DGNU_HOST=x86_64-w64-mingw32 \
|
||||
-DCMAKE_TOOLCHAIN_FILE=../mingw_cross_toolchain.cmake \
|
||||
..
|
||||
cmake --build .
|
||||
```
|
||||
On Windows environment, you can use MinGW `-G "MinGW Makefiles"` or Ninja `-G "Ninja"` as CMake generator.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CMakeLists.txt
|
||||
|
||||
####################################################
|
||||
# Written by JackCarterSmith, 2022
|
||||
# Written by JackCarterSmith, 2023
|
||||
# This code is released under the RSE license.
|
||||
####################################################
|
||||
|
||||
@ -14,6 +14,10 @@ if(BUILD_TOOLS)
|
||||
# Import needed packages and references their include path
|
||||
find_package(GLEW REQUIRED)
|
||||
include_directories(${GLEW_INCLUDE_DIR})
|
||||
#find_package(Vulkan REQUIRED)
|
||||
#include_directories(${Vulkan_INCLUDE_DIR})
|
||||
#find_package(vulkan-memory-allocator REQUIRED)
|
||||
#include_directories(${vulkan-memory-allocator_INCLUDE_DIR})
|
||||
|
||||
|
||||
# Define src/headers files
|
||||
@ -42,9 +46,13 @@ if(BUILD_TOOLS)
|
||||
endif()
|
||||
|
||||
# Link externals libraries to the linker
|
||||
if(RSPMODEL_SHARED)
|
||||
target_link_libraries(rse-model PRIVATE rsp-model-lib ${GLEW_LIBRARIES} ${AUX_LIBS})
|
||||
elseif(RSPMODEL_STATIC)
|
||||
target_link_libraries(rse-model PRIVATE rsp-model-libstatic ${GLEW_LIBRARIES} ${AUX_LIBS})
|
||||
if (TARGET GLEW::GLEW)
|
||||
if(RSPMODEL_SHARED)
|
||||
#target_link_libraries(rse-model PRIVATE rsp-model-lib ${GLEW_LIBRARIES} ${Vulkan_LIBRARIES} ${AUX_LIBS})
|
||||
target_link_libraries(rse-model PRIVATE rsp-model-lib GLEW::GLEW ${AUX_LIBS})
|
||||
elseif(RSPMODEL_STATIC)
|
||||
#target_link_libraries(rse-model PRIVATE rsp-model-libstatic ${GLEW_LIBRARIES} ${Vulkan_LIBRARIES} ${AUX_LIBS})
|
||||
target_link_libraries(rse-model PRIVATE rsp-model-libstatic GLEW::GLEW ${AUX_LIBS})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
@ -99,11 +99,12 @@ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS
|
||||
if (RSPModel_processHOBFile(hobStruct, args_value[file_index], libParams) != RSPLIB_SUCCESS) {
|
||||
printf("[ERR] Failed to parse datas from %s\n", args_value[file_index]);
|
||||
RSPModel_freeHOB(hobStruct);
|
||||
free(hobStruct);
|
||||
return RSPLIB_ERROR_PROCESS;
|
||||
}
|
||||
|
||||
// If Texture module loaded, process HMT file for mtl naming (doesn't extract texture!)
|
||||
if (p_opts->texture_module) {
|
||||
if (p_opts->texture_module && p_opts->export_mtl) {
|
||||
if (strlen(args_value[file_index]) >= MAX_STR_VAR) return RSPLIB_ERROR_GENERIC;
|
||||
|
||||
strncpy(hmt_filename, args_value[file_index], strlen(args_value[file_index]) - 3);
|
||||
@ -132,10 +133,11 @@ static unsigned int mainProcess(int args_cnt, char* args_value[], T_PROG_OPTIONS
|
||||
}
|
||||
}
|
||||
|
||||
RSPTexture_freeHMT(hmtStruct);
|
||||
if (p_opts->texture_module) RSPTexture_freeHMT(hmtStruct);
|
||||
}
|
||||
|
||||
RSPModel_freeHOB(hobStruct);
|
||||
free(hobStruct);
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
# CMakeLists.txt
|
||||
|
||||
####################################################
|
||||
# Written by JackCarterSmith, 2022
|
||||
# Written by JackCarterSmith, 2023
|
||||
# This code is released under the RSE license.
|
||||
####################################################
|
||||
|
||||
@ -31,8 +31,8 @@ endif()
|
||||
# Declare the shared library instance
|
||||
if(RSPMODEL_SHARED)
|
||||
add_library(rsp-model-lib SHARED ${RSP_MOD_SOURCES})
|
||||
set_property(TARGET rsp-model-lib PROPERTY C_STANDARD 90)
|
||||
set_target_properties(rsp-model-lib PROPERTIES VERSION 2.1.0)
|
||||
set_property(TARGET rsp-model-lib PROPERTY C_STANDARD 11)
|
||||
set_target_properties(rsp-model-lib PROPERTIES VERSION 2.3.0)
|
||||
|
||||
target_include_directories(rsp-model-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
@ -53,7 +53,7 @@ endif()
|
||||
# Declare the static library instance
|
||||
if(RSPMODEL_STATIC)
|
||||
add_library(rsp-model-libstatic STATIC ${RSP_MOD_SOURCES})
|
||||
set_property(TARGET rsp-model-libstatic PROPERTY C_STANDARD 90)
|
||||
set_property(TARGET rsp-model-libstatic PROPERTY C_STANDARD 11)
|
||||
|
||||
target_include_directories(rsp-model-libstatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file RSPModel.h
|
||||
* @date 11/08/2022
|
||||
* @date 18/01/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Rogue Squadron Parser model library, used to decode decode datas
|
||||
@ -48,6 +48,7 @@ extern "C" {
|
||||
// Library's functions declaration
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Get the current library version.
|
||||
* @return Char array of the version, escape char included.
|
||||
@ -88,6 +89,36 @@ RSPMODEL_EXTERN unsigned short RSPModel_processHOBFileMemory(
|
||||
const RSPMODEL_PARAMETERS params
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Clean HOB object and it's childrens from memory.
|
||||
* @param[in] hobStruct Pointer to data to be cleaned up.
|
||||
*/
|
||||
RSPMODEL_EXTERN void RSPModel_freeHOB( T_RSPMODEL_HOB* hobStruct );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Get number of model objects inside specified memFilePtr without
|
||||
* fully parsing it.
|
||||
*
|
||||
* @param[in] filePath Path to the HOB file in system.
|
||||
*
|
||||
* @return Number of model objects.
|
||||
*/
|
||||
RSPMODEL_EXTERN unsigned int RSPModel_getHOBFileObjCount( const char* const filePath );
|
||||
|
||||
/**
|
||||
* @brief Get number of model objects inside specified memFilePtr without
|
||||
* fully parsing it.
|
||||
*
|
||||
* @param[in] memFilePtr Pointer to the beginning of the file in memory.
|
||||
*
|
||||
* @return Number of model objects.
|
||||
*/
|
||||
RSPMODEL_EXTERN unsigned int RSPModel_getHOBFileMemObjCount( const void* const memFilePtr );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/**
|
||||
* @brief Convert HOB's object datas to GL compatible format.
|
||||
* @note Only available if GL module as specified at compilation.
|
||||
@ -114,12 +145,6 @@ RSPMODEL_EXTERN unsigned short RSPModel_objectToD3D(
|
||||
const T_RSPMODEL_OBJECT* objStruct, void* D3DObj
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Clean HOB object and it's childrens from memory.
|
||||
* @param[in] hobStruct Pointer to data to be cleaned up.
|
||||
*/
|
||||
RSPMODEL_EXTERN void RSPModel_freeHOB( T_RSPMODEL_HOB* hobStruct );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file RSPModel_datatypes.h
|
||||
* @date 11/08/2022
|
||||
* @date 21/02/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief RSP Model workflow structures definitions
|
||||
@ -39,40 +39,31 @@ typedef char* MEMFILE;
|
||||
#define MEMFILE_DEF
|
||||
#endif
|
||||
|
||||
#ifndef T_RGBA_DEF
|
||||
typedef unsigned int T_RGBA;
|
||||
#define T_RGBA_DEF
|
||||
#endif
|
||||
typedef unsigned int T_RSPMODEL_RGBA;
|
||||
|
||||
#ifndef T_VECTOR3_DEF
|
||||
typedef struct vector3 { float x,y,z; } T_VECTOR3;
|
||||
#define T_VECTOR3_DEF
|
||||
#endif
|
||||
typedef struct rspmodel_vector3 { float x,y,z; } T_RSPMODEL_VECTOR3;
|
||||
typedef struct rspmodel_vertex { short x,y,z,w; } T_RSPMODEL_VERTEX;
|
||||
|
||||
#ifndef T_VERTEX_DEF
|
||||
typedef struct vertex { short x,y,z,w; } T_VERTEX;
|
||||
#define T_VERTEX_DEF
|
||||
#endif
|
||||
typedef struct rspmodel_texcoord { short u,v; } T_RSPMODEL_TEXCOORD;
|
||||
|
||||
#ifndef T_TEXCOORD_DEF
|
||||
typedef struct tex_coord { short u,v; } T_TEXCOORD;
|
||||
#define T_TEXCOORD_DEF
|
||||
#endif
|
||||
typedef struct rspmodel_bbox { T_RSPMODEL_VECTOR3 start,end; } T_RSPMODEL_BBOX;
|
||||
|
||||
typedef struct face_flags {
|
||||
unsigned int fUnknown0:1;
|
||||
unsigned int fUnknown1:1;
|
||||
unsigned int fUnused0:1; //TODO: Parse all HOB to find anyone with this field different of 0
|
||||
unsigned int fUnused1:1; //TODO: Parse all HOB to find anyone with this field different of 0
|
||||
|
||||
unsigned int fHasTexture:1;
|
||||
unsigned int fIsQuad:1;
|
||||
unsigned int fSeparateColorVertex:1;
|
||||
unsigned int fHasColor:1;
|
||||
unsigned int fHasExtraBytesBeforeColor:1;
|
||||
unsigned int fUnknown7:1;
|
||||
unsigned int fNoCulled:1; // Face with this flag always be rendered without culling, usefull to render "flat" object
|
||||
|
||||
unsigned int fUnknown8:1;
|
||||
unsigned int fUnknown9:1;
|
||||
unsigned int fUnknown10:1;
|
||||
|
||||
unsigned int reserved:21;
|
||||
unsigned int fReserved:21;
|
||||
} FACE_FLAGS;
|
||||
|
||||
typedef struct hob_face {
|
||||
@ -86,11 +77,12 @@ typedef struct hob_face {
|
||||
unsigned char bsize;
|
||||
unsigned short mt_index; // Material/texture index, if texture it's correspond to texture_index, otherwise it's mat_'X'
|
||||
unsigned short indices[4];
|
||||
T_RGBA vertex_colors[4]; //TODO: convert in R:8_G:8_B:8_A:8 format? Caution with BE/LE conversion
|
||||
T_TEXCOORD tex_coords[4];
|
||||
T_RSPMODEL_RGBA vertex_colors[4]; //TODO: convert in R:8_G:8_B:8_A:8 format? Caution with BE/LE conversion
|
||||
T_RSPMODEL_TEXCOORD tex_coords[4];
|
||||
} T_RSPMODEL_FACE;
|
||||
|
||||
typedef struct rspmodel_obj_parts {
|
||||
unsigned int meshdef0_offset;
|
||||
unsigned int meshdef1_offset;
|
||||
|
||||
unsigned int face_block_end_offset;
|
||||
@ -98,20 +90,31 @@ typedef struct rspmodel_obj_parts {
|
||||
unsigned int vertex_block_offset;
|
||||
|
||||
unsigned int id;
|
||||
T_VECTOR3 transform;
|
||||
T_RSPMODEL_VECTOR3 offset_transform;
|
||||
T_RSPMODEL_VECTOR3 scale_transform;
|
||||
T_RSPMODEL_VECTOR3 rotate_transform;
|
||||
T_RSPMODEL_VECTOR3 translate_transform;
|
||||
|
||||
unsigned int face_count;
|
||||
T_RSPMODEL_FACE* faces;
|
||||
|
||||
unsigned int vertex_count;
|
||||
T_VERTEX* vertices;
|
||||
T_RSPMODEL_VERTEX* vertices;
|
||||
} T_RSPMODEL_OBJ_PARTS;
|
||||
|
||||
typedef struct rspmodel_object {
|
||||
char name[16];
|
||||
unsigned int face_group_offset;
|
||||
unsigned int object_part_header_offset;
|
||||
unsigned int face_group_header_offset;
|
||||
unsigned int object_parts_header_offset;
|
||||
unsigned int object_parts_header_offset2;
|
||||
unsigned int object_parts_header2_offset;
|
||||
unsigned int object_parts_header2_offset2;
|
||||
|
||||
unsigned int object_subparts_names_offset;
|
||||
unsigned int effects_offset;
|
||||
unsigned int properties_offset2;
|
||||
|
||||
T_RSPMODEL_BBOX bounding_box;
|
||||
|
||||
unsigned int object_part_count;
|
||||
unsigned int face_group_count;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file RSPModel.c
|
||||
* @date 11/08/2022
|
||||
* @date 18/01/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief HOB model parser and export to Waveform OBJ format.
|
||||
@ -27,38 +27,27 @@ inline char* RSPModel_getVersion( void ) {
|
||||
|
||||
unsigned short RSPModel_processHOBFile( T_RSPMODEL_HOB* hob, const char* const filePath,
|
||||
const RSPMODEL_PARAMETERS params ) {
|
||||
unsigned short result = RSPLIB_SUCCESS;
|
||||
MEMFILE pMemFile = NULL;
|
||||
|
||||
if ( hob == NULL || filePath == NULL ) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
RSP_ModelLib_ParseHOBFile(filePath, hob, ¶ms);
|
||||
RSP_ModelLib_LoadHOBFile(&pMemFile, filePath, ¶ms);
|
||||
result = RSP_ModelLib_ProcessHOBMemFile(hob, pMemFile, ¶ms);
|
||||
RSP_ModelLib_FreeHOBFile(&pMemFile);
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned short RSPModel_processHOBFileMemory( T_RSPMODEL_HOB* hob, const void* const memFilePtr,
|
||||
const long memFileSize, const RSPMODEL_PARAMETERS params ) {
|
||||
unsigned short result = RSPLIB_SUCCESS;
|
||||
|
||||
if ( hob == NULL || memFilePtr == NULL ) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
RSP_ModelLib_ParseHOBMemFile((MEMFILE)memFilePtr, hob, ¶ms);
|
||||
result = RSP_ModelLib_ProcessHOBMemFile(hob, (MEMFILE)memFilePtr, ¶ms);
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned short RSPModel_objectToGL( const T_RSPMODEL_OBJECT* objStruct, void* glObj ) {
|
||||
#ifndef GL_SUPPORT
|
||||
return RSPLIB_ERROR_MOD_DISABLED;
|
||||
#endif
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned short RSPModel_objectToD3D( const T_RSPMODEL_OBJECT* objStruct, void* D3DObj ) {
|
||||
#ifndef D3D_SUPPORT
|
||||
return RSPLIB_ERROR_MOD_DISABLED;
|
||||
#endif
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
void RSPModel_freeHOB( T_RSPMODEL_HOB* hobStruct ) {
|
||||
@ -82,6 +71,41 @@ void RSPModel_freeHOB( T_RSPMODEL_HOB* hobStruct ) {
|
||||
}
|
||||
free(hobStruct->objects);
|
||||
}
|
||||
|
||||
free(hobStruct);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
unsigned int RSPModel_getHOBFileObjCount( const char* const filePath ) {
|
||||
unsigned int result = 0;
|
||||
MEMFILE pMemFile = NULL;
|
||||
|
||||
if (filePath != NULL) {
|
||||
RSP_ModelLib_LoadHOBFile(&pMemFile, filePath, 0);
|
||||
result = RSP_ModelLib_getObjectsCount(pMemFile);
|
||||
RSP_ModelLib_FreeHOBFile(&pMemFile);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int RSPModel_getHOBFileMemObjCount( const void* const memFilePtr ) {
|
||||
return RSP_ModelLib_getObjectsCount((MEMFILE)memFilePtr);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
unsigned short RSPModel_objectToGL( const T_RSPMODEL_OBJECT* objStruct, void* glObj ) {
|
||||
#ifndef GL_SUPPORT
|
||||
return RSPLIB_ERROR_MOD_DISABLED;
|
||||
#endif
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
unsigned short RSPModel_objectToD3D( const T_RSPMODEL_OBJECT* objStruct, void* D3DObj ) {
|
||||
#ifndef D3D_SUPPORT
|
||||
return RSPLIB_ERROR_MOD_DISABLED;
|
||||
#endif
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file hob_parser.c
|
||||
* @date 18/08/2022
|
||||
* @date 21/02/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Process HOB file structure and extract its datas.
|
||||
@ -12,8 +12,8 @@
|
||||
#include <string.h>
|
||||
#include "RSPModel_errordefs.h"
|
||||
#include "RSPModel_datatypes.h"
|
||||
#include "hob_struct.h"
|
||||
#include "hob_parser.h"
|
||||
#include "hob_struct.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -21,8 +21,15 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static unsigned short ExtractObjects(T_RSPMODEL_HOB*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ExtractObjParts(T_RSPMODEL_OBJECT*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
|
||||
static unsigned short ParseObjectHeader(T_RSPMODEL_OBJECT*, const MEMFILE, const unsigned char, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectPartsHeaders(T_RSPMODEL_OBJECT*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectPartHeader(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const int, const unsigned char, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectMeshDef(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectFaceblockHeader(T_RSPMODEL_OBJ_PARTS*, const MEMFILE, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectFace(T_RSPMODEL_FACE*, const MEMFILE, unsigned int* const, const unsigned int, const RSPMODEL_PARAMETERS*);
|
||||
static unsigned short ParseObjectFaceVertices(T_RSPMODEL_VERTEX*, const MEMFILE, const unsigned int, const unsigned int, const RSPMODEL_PARAMETERS*);
|
||||
|
||||
static unsigned short ExtractObjpart_Face_Colors(T_RSPMODEL_FACE*, const char*);
|
||||
static unsigned short ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE*, const char*);
|
||||
|
||||
@ -31,7 +38,7 @@ static unsigned short ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE*, const char*);
|
||||
// Public functions definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned short RSP_ModelLib_ParseHOBMemFile(const MEMFILE pMemFile, T_RSPMODEL_HOB* hobStruct, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned short RSP_ModelLib_ProcessHOBMemFile(T_RSPMODEL_HOB* hobStruct, const MEMFILE pMemFile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned char err = RSPLIB_SUCCESS;
|
||||
|
||||
if (hobStruct != NULL && pMemFile != NULL) {
|
||||
@ -42,13 +49,12 @@ unsigned short RSP_ModelLib_ParseHOBMemFile(const MEMFILE pMemFile, T_RSPMODEL_H
|
||||
return err;
|
||||
}
|
||||
|
||||
unsigned short RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* hobStruct, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned short RSP_ModelLib_LoadHOBFile(MEMFILE* newMemFile, const char* fileName, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned char err = RSPLIB_SUCCESS;
|
||||
long fileSize;
|
||||
FILE* fStream = NULL;
|
||||
MEMFILE memFile = NULL;
|
||||
|
||||
if (hobStruct != NULL && fileName != NULL) {
|
||||
if (newMemFile != NULL && fileName != NULL) {
|
||||
// Open file
|
||||
fStream = fopen(fileName, "rb");
|
||||
|
||||
@ -59,17 +65,11 @@ unsigned short RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* h
|
||||
fseek(fStream, 0, SEEK_SET);
|
||||
if (pParams->verbose_mode) printf("[DBG] > Input file size: %ld bytes\n", fileSize);
|
||||
|
||||
memFile = malloc(fileSize + 1);
|
||||
if (memFile != NULL) {
|
||||
*newMemFile = malloc(fileSize + 1);
|
||||
if (*newMemFile != NULL) {
|
||||
// Copy file in RAM
|
||||
fread(memFile, fileSize, 1, fStream);
|
||||
fread(*newMemFile, fileSize, 1, fStream);
|
||||
fclose(fStream);
|
||||
|
||||
// Do the magic!
|
||||
err = ExtractObjects(hobStruct, memFile, pParams);
|
||||
|
||||
free(memFile);
|
||||
|
||||
} else {
|
||||
fclose(fStream);
|
||||
err = RSPLIB_ERROR_MEMORY;
|
||||
@ -84,6 +84,16 @@ unsigned short RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* h
|
||||
return err;
|
||||
}
|
||||
|
||||
unsigned short RSP_ModelLib_FreeHOBFile(const MEMFILE* memFile) {
|
||||
unsigned char err = RSPLIB_SUCCESS;
|
||||
|
||||
if (memFile != NULL && *memFile != NULL) {
|
||||
free(*memFile);
|
||||
} else err = RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private functions definition
|
||||
@ -99,15 +109,16 @@ unsigned short RSP_ModelLib_ParseHOBFile(const char* fileName, T_RSPMODEL_HOB* h
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ExtractObjects(T_RSPMODEL_HOB* pHobStruct, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned int i;
|
||||
unsigned int i, j, k;
|
||||
unsigned int faceExtraOffset = 0;
|
||||
|
||||
if (pHobStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
// Retrieve object count from the header
|
||||
pHobStruct->obj_count = ((T_HOBFILE_HEADER *)pMemfile)->obj_count;
|
||||
printf("[INFO] - Object(s) quantity: %d\n", pHobStruct->obj_count);
|
||||
pHobStruct->obj_count = RSP_ModelLib_getObjectsCount(pMemfile);
|
||||
if (pParams->verbose_mode) printf("[INFO] - Object(s) quantity: %d\n", pHobStruct->obj_count);
|
||||
if (pHobStruct->obj_count <= 0) {
|
||||
printf("[INFO] Can't process empty file!\n");
|
||||
if (pParams->verbose_mode) printf("[INFO] Can't process empty file!\n");
|
||||
return RSPLIB_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
@ -116,273 +127,450 @@ static unsigned short ExtractObjects(T_RSPMODEL_HOB* pHobStruct, const MEMFILE p
|
||||
if (pHobStruct->objects == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
|
||||
for ( i = 0; i < pHobStruct->obj_count; i++ ) {
|
||||
if (pParams->debug_mode) printf("\n-=====================-Begin of Object part-======================-\n");
|
||||
if (pParams->debug_mode) printf("\n-=======================- Begin of Object -=======================-\n");
|
||||
|
||||
// Get object name
|
||||
memcpy(pHobStruct->objects[i].name, ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER)
|
||||
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_name, 16);
|
||||
// Parse object headers
|
||||
ParseObjectHeader(&pHobStruct->objects[i], pMemfile, i, pParams);
|
||||
|
||||
if (pParams->verbose_mode) printf("\n");
|
||||
printf("[INFO] - Process %s object...\n", pHobStruct->objects[i].name);
|
||||
// Extract object parts
|
||||
ParseObjectPartsHeaders(&pHobStruct->objects[i], pMemfile, pParams);
|
||||
|
||||
pHobStruct->objects[i].object_parts = calloc(pHobStruct->objects[i].object_part_count, sizeof(T_RSPMODEL_OBJ_PARTS));
|
||||
if (pHobStruct->objects[i].object_parts == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
|
||||
// Get offsets
|
||||
pHobStruct->objects[i].face_group_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER)
|
||||
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Face group offset: 0x%X\n", pHobStruct->objects[i].face_group_offset);
|
||||
pHobStruct->objects[i].object_part_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER)
|
||||
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->object_parts_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Face group header/object parts offset: 0x%X\n", pHobStruct->objects[i].object_part_header_offset);
|
||||
pHobStruct->objects[i].face_group_header_offset = ((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER)
|
||||
+ sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->facegroup_header_2_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Face group header2 offset: 0x%X\n", pHobStruct->objects[i].face_group_header_offset);
|
||||
for ( j = 0; j < pHobStruct->objects[i].object_part_count; j++ ) {
|
||||
if (pParams->debug_mode) printf("\n-~~~~~~~~~~~~~~~~~~~~~- Begin of obj. part -~~~~~~~~~~~~~~~~~~~~~~-\n");
|
||||
|
||||
if (pParams->god_mode) {
|
||||
printf("[DBG] > Face group unknown1: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset1);
|
||||
printf("[DBG] > Face group unknown2: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset2);
|
||||
printf("[DBG] > Face group unknown3: %d\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknownOffset3);
|
||||
printf("[DBG] > Face group unknown4: %.8f\n",((T_HOBFILE_OBJ_DESCRIPTOR *)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_DESCRIPTOR) * i))->unknown4);
|
||||
// Parse object parts headers
|
||||
ParseObjectPartHeader(&pHobStruct->objects[i].object_parts[j], pMemfile, pHobStruct->objects[i].object_parts_header_offset, j, pParams);
|
||||
|
||||
// Parse object meshdef
|
||||
ParseObjectMeshDef(&pHobStruct->objects[i].object_parts[j], pMemfile, pParams);
|
||||
|
||||
if (pHobStruct->objects[i].object_parts[j].meshdef1_offset) {
|
||||
if (pParams->debug_mode) printf("\n------------------------- Begin of Mesh -------------------------\n");
|
||||
|
||||
// Extract object faces header datas
|
||||
ParseObjectFaceblockHeader(&pHobStruct->objects[i].object_parts[j], pMemfile, pParams);
|
||||
|
||||
pHobStruct->objects[i].object_parts[j].faces = calloc(pHobStruct->objects[i].object_parts[j].face_count, sizeof(T_RSPMODEL_FACE));
|
||||
if (pHobStruct->objects[i].object_parts[j].faces == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
|
||||
faceExtraOffset = pHobStruct->objects[i].object_parts[j].face_block_offset + sizeof(T_HOBFILE_FACEBLOCK);
|
||||
for ( k = 0; k < pHobStruct->objects[i].object_parts[j].face_count; k++ ) {
|
||||
if (pParams->debug_mode) printf("\n-......................- Begin of Face -.....................-\n");
|
||||
|
||||
ParseObjectFace(&pHobStruct->objects[i].object_parts[j].faces[k], pMemfile, &faceExtraOffset, k, pParams);
|
||||
|
||||
if (pParams->debug_mode) printf("\n-.......................- End of Face -......................-\n");
|
||||
}
|
||||
|
||||
// Get vertex datas
|
||||
pHobStruct->objects[i].object_parts[j].vertices = calloc(pHobStruct->objects[i].object_parts[j].vertex_count, sizeof(T_RSPMODEL_VERTEX));
|
||||
if (pHobStruct->objects[i].object_parts[j].vertices == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
|
||||
for ( k = 0; k < pHobStruct->objects[i].object_parts[j].vertex_count; k++ ) {
|
||||
ParseObjectFaceVertices(&pHobStruct->objects[i].object_parts[j].vertices[k], pMemfile,
|
||||
pHobStruct->objects[i].object_parts[j].vertex_block_offset + sizeof(T_RSPMODEL_VERTEX) * k, k, pParams);
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) printf("\n------------------------- End of Mesh ---------------------------\n");
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) printf("\n-~~~~~~~~~~~~~~~~~~~~~~- End of obj. part -~~~~~~~~~~~~~~~~~~~~~~~-\n");
|
||||
}
|
||||
|
||||
// Get count and offsets from the facegroup header
|
||||
pHobStruct->objects[i].object_part_count = ((T_HOBFILE_FACEGROUP_HEADER *)(pMemfile
|
||||
+ pHobStruct->objects[i].object_part_header_offset))->object_part_count;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Object parts count: %d\n", pHobStruct->objects[i].object_part_count);
|
||||
pHobStruct->objects[i].face_group_count = ((T_HOBFILE_FACEGROUP_HEADER *)(pMemfile
|
||||
+ pHobStruct->objects[i].object_part_header_offset))->facegroup_count;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Face groups count: %d\n", pHobStruct->objects[i].face_group_count);
|
||||
//TODO: Caution with obj/facegrp count difference. What is facegroup count???
|
||||
/*
|
||||
* Seem "object" are independant structure like xwing, turret, etc.
|
||||
* Facegroup is more like part of previous object, like wing-left, turret-barrel, etc.
|
||||
*/
|
||||
if (pHobStruct->objects[i].object_part_count != pHobStruct->objects[i].face_group_count && (pParams->verbose_mode))
|
||||
printf("[DBG] > Object parts / facegroup count are different!\n");
|
||||
|
||||
// Get facegroup datas
|
||||
ExtractObjParts(&pHobStruct->objects[i], pMemfile, pParams);
|
||||
if (pParams->debug_mode) printf("\n-=======================- End of Object -=========================-\n");
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Count object's sub-part and extract datas from them.
|
||||
* @brief Parse datas from object's header
|
||||
*
|
||||
* @param[in|out] pObject Take object structure to get the T_RSPMODEL_OBJ_PARTS buffer and object datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
* @param[in|out] pObjStruct Take object structure and fill it with header datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] objIndex Object index for correct offset align.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ExtractObjParts(T_RSPMODEL_OBJECT* pObject, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned int i, subpart_offset = 0;
|
||||
static unsigned short ParseObjectHeader(T_RSPMODEL_OBJECT* pObjStruct, const MEMFILE pMemfile, const unsigned char objIndex, const RSPMODEL_PARAMETERS* pParams) {
|
||||
if (pObjStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
if (pObject == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_OBJ_HEADER* const hobObjHeader =
|
||||
((T_HOBFILE_OBJ_HEADER*)(pMemfile + sizeof(T_HOBFILE_HEADER) + sizeof(T_HOBFILE_OBJ_HEADER) * objIndex));
|
||||
|
||||
pObject->object_parts = calloc(pObject->object_part_count, sizeof(T_RSPMODEL_OBJ_PARTS));
|
||||
if (pObject->object_parts == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
// Get object name
|
||||
memcpy(pObjStruct->name, hobObjHeader->object_name, 16);
|
||||
if (pParams->verbose_mode) printf("\n[INFO] - Process %s object...\n", pObjStruct->name);
|
||||
|
||||
for ( i = 0; i < pObject->object_part_count; i++ ) {
|
||||
if (pParams->debug_mode) printf("\n-----------------------Begin of Mesh part-------------------------\n");
|
||||
subpart_offset = ((T_HOBFILE_FACEGROUP_OFFSET *)(pMemfile + pObject->object_part_header_offset
|
||||
+ sizeof(T_HOBFILE_FACEGROUP_HEADER) + sizeof(T_HOBFILE_FACEGROUP_OFFSET) * i))->facegroup_offset;
|
||||
if (pParams->verbose_mode) printf("\n[DBG] > Face group meshdef0 offset: 0x%X\n", subpart_offset);
|
||||
|
||||
// Get meshdef0 datas
|
||||
if (pParams->god_mode) printf("[DBG] > meshdef0 offset1: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset1);
|
||||
if (pParams->god_mode) printf("[DBG] > meshdef0 offset2: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->offset2);
|
||||
if (pParams->verbose_mode) printf("[DBG] > Prev meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->prev_meshdef0_offset);
|
||||
if (pParams->verbose_mode) printf("[DBG] > Next meshdef0 offset: 0x%X\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->next_meshdef0_offset);
|
||||
|
||||
if (pParams->god_mode) printf("[DBG] > meshdef0 unknown3: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown3);
|
||||
if (pParams->god_mode) printf("[DBG] > meshdef0 unknown4: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown4);
|
||||
if (pParams->god_mode) printf("[DBG] > meshdef0 unknown5: %.8f\n",((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->unknown5);
|
||||
|
||||
// Get meshdef1 (mesh descriptor) offset
|
||||
pObject->object_parts[i].meshdef1_offset = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->meshdef1_offset_plus_4;
|
||||
if (pParams->verbose_mode) printf("\n[DBG] > Face group meshdef1 offset: 0x%X\n", pObject->object_parts[i].meshdef1_offset);
|
||||
|
||||
if( ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->reserved1 != 0 ||
|
||||
((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->reserved2 != 0 ) {
|
||||
if (pParams->god_mode) printf("[DBG] > Face group meshdef0: no 0!\n");
|
||||
}
|
||||
|
||||
if (pObject->object_parts[i].meshdef1_offset > 0) {
|
||||
// Read meshdef1 datas
|
||||
pObject->object_parts[i].face_block_end_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile
|
||||
+ pObject->object_parts[i].meshdef1_offset - 4))->facedef_end_offset;
|
||||
pObject->object_parts[i].vertex_count = ((T_HOBFILE_MESHDEF1 *)(pMemfile
|
||||
+ pObject->object_parts[i].meshdef1_offset - 4))->vertex_count;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Vertex count: %d\n", pObject->object_parts[i].vertex_count);
|
||||
pObject->object_parts[i].face_block_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile
|
||||
+ pObject->object_parts[i].meshdef1_offset - 4))->faceblock_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Faces offset: 0x%X\n", pObject->object_parts[i].face_block_offset);
|
||||
pObject->object_parts[i].vertex_block_offset = ((T_HOBFILE_MESHDEF1 *)(pMemfile
|
||||
+ pObject->object_parts[i].meshdef1_offset - 4))->vertexblocks_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Vertex offset: 0x%X\n\n", pObject->object_parts[i].vertex_block_offset);
|
||||
|
||||
// Get faces datas
|
||||
ExtractObjParts_faces(&pObject->object_parts[i], pMemfile, pParams);
|
||||
}
|
||||
|
||||
// Get object part ID, used by animation? bones?
|
||||
pObject->object_parts[i].id = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->object_id;
|
||||
if (pParams->verbose_mode) printf("\n[DBG] > Facegroup/object ID: %d\n", pObject->object_parts[i].id);
|
||||
|
||||
// Get the transform matrix, used by at-st and at-at (at this time)
|
||||
pObject->object_parts[i].transform.x = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_x;
|
||||
pObject->object_parts[i].transform.y = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_y;
|
||||
pObject->object_parts[i].transform.z = ((T_HOBFILE_MESHDEF0 *)(pMemfile + subpart_offset))->transform_z;
|
||||
if (pParams->god_mode) printf("\n[DBG] > Facegroup/object transform matrix: [%.8f %.8f %.8f]\n",
|
||||
pObject->object_parts[i].transform.x,
|
||||
pObject->object_parts[i].transform.y,
|
||||
pObject->object_parts[i].transform.z
|
||||
);
|
||||
|
||||
if (pParams->debug_mode) printf("\n-----------------------End of Mesh part---------------------------\n");
|
||||
// Get offsets
|
||||
pObjStruct->face_group_offset = hobObjHeader->facegroup_start_offset;
|
||||
pObjStruct->object_parts_header_offset = hobObjHeader->object_parts_offset;
|
||||
pObjStruct->object_parts_header_offset2 = hobObjHeader->object_parts_offset2;
|
||||
pObjStruct->object_parts_header2_offset = hobObjHeader->object_parts2_offset;
|
||||
pObjStruct->object_parts_header2_offset2 = hobObjHeader->object_parts2_offset2;
|
||||
pObjStruct->object_subparts_names_offset = hobObjHeader->subparts_namelist_offset;
|
||||
pObjStruct->effects_offset = hobObjHeader->effects_offset;
|
||||
pObjStruct->properties_offset2 = hobObjHeader->properties_offset;
|
||||
if (pParams->verbose_mode) {
|
||||
printf("[DBG] > Face group start offset: 0x%X\n", pObjStruct->face_group_offset);
|
||||
printf("[DBG] > Object parts 1st header offset (main): 0x%X\n", pObjStruct->object_parts_header_offset);
|
||||
printf("[DBG] > Object parts 1st header offset (aux): 0x%X\n", pObjStruct->object_parts_header_offset2);
|
||||
printf("[DBG] > Object parts 2nd header offset (main): 0x%X\n", pObjStruct->object_parts_header2_offset);
|
||||
printf("[DBG] > Object parts 2nd header offset (aux): 0x%X\n", pObjStruct->object_parts_header2_offset2);
|
||||
printf("[DBG] > Object subparts names offset: 0x%X\n", pObjStruct->object_subparts_names_offset);
|
||||
printf("[DBG] > Object effects offset: 0x%X\n", pObjStruct->effects_offset);
|
||||
printf("[DBG] > Object properties offset: 0x%X\n", pObjStruct->properties_offset2);
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) printf("\n-=====================-End of Object part-========================-\n");
|
||||
// Get bounding box
|
||||
pObjStruct->bounding_box.start.x = hobObjHeader->bbox_start_x;
|
||||
pObjStruct->bounding_box.start.y = hobObjHeader->bbox_start_y;
|
||||
pObjStruct->bounding_box.start.z = hobObjHeader->bbox_start_z;
|
||||
pObjStruct->bounding_box.end.x = hobObjHeader->bbox_end_x;
|
||||
pObjStruct->bounding_box.end.y = hobObjHeader->bbox_end_y;
|
||||
pObjStruct->bounding_box.end.z = hobObjHeader->bbox_end_z;
|
||||
if (pParams->verbose_mode) {
|
||||
printf("[DBG] > Bounding box start: (%.8f, %.8f, %.8f)\n",
|
||||
pObjStruct->bounding_box.start.x,
|
||||
pObjStruct->bounding_box.start.y,
|
||||
pObjStruct->bounding_box.start.z
|
||||
);
|
||||
printf("[DBG] > Bounding box end: (%.8f, %.8f, %.8f)\n",
|
||||
pObjStruct->bounding_box.end.x,
|
||||
pObjStruct->bounding_box.end.y,
|
||||
pObjStruct->bounding_box.end.z
|
||||
);
|
||||
}
|
||||
|
||||
if (pParams->god_mode) {
|
||||
printf("[DBG] > Object header unknown4: %.8f\n", hobObjHeader->unknown4);
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract datas from faces from object sub-part.
|
||||
* @brief Parse datas from object parts's headers
|
||||
*
|
||||
* @param[in|out] pObjPart Take object sub-part structure to get the T_RSPMODEL_FACE buffer and object sub-part datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
* "objects" are individual, independent from each others, element of the game world.
|
||||
* "object parts" are a group of mesh isolated by their animation attribute (and probably others physics attributes...)
|
||||
* "facegroup" are like object parts but isolated by their rendering properties like associated texture, lighting properties, etc.
|
||||
*
|
||||
* @param[in|out] pObjStruct Take object structure and fill it with header datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ExtractObjParts_faces(T_RSPMODEL_OBJ_PARTS* pObjPart, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned int i, facesExtraOffset = 0;
|
||||
static unsigned short ParseObjectPartsHeaders(T_RSPMODEL_OBJECT* pObjStruct, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned int i;
|
||||
char tmpStr[9] = {0};
|
||||
if (pObjStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
if (pObjPart == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
if( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->reserved1 != 0 ||
|
||||
((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->reserved2 != 0 ) {
|
||||
if (pParams->god_mode) printf("[DBG] > Face block: uncommon zero header!\n");
|
||||
}
|
||||
if ( ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->facesOffset !=
|
||||
pObjPart->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)) {
|
||||
if (pParams->god_mode) printf("[DBG] > Face block: uncommon face data offset position!\n");
|
||||
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_OBJPARTS_HEADER* const hobObjPartsHeader1 = ((T_HOBFILE_OBJPARTS_HEADER*)(pMemfile + pObjStruct->object_parts_header_offset));
|
||||
const T_HOBFILE_OBJPARTS_NAMEID* const hobObjPartsNames = ((T_HOBFILE_OBJPARTS_NAMEID*)(pMemfile + pObjStruct->object_subparts_names_offset));
|
||||
|
||||
// Get count and offsets from the facegroup header
|
||||
pObjStruct->object_part_count = hobObjPartsHeader1->object_part_count;
|
||||
pObjStruct->face_group_count = hobObjPartsHeader1->facegroup_count;
|
||||
if (pParams->verbose_mode) {
|
||||
printf("\n");
|
||||
printf("[DBG] > Object parts count: %d\n", pObjStruct->object_part_count);
|
||||
printf("[DBG] > Face groups count: %d\n", pObjStruct->face_group_count);
|
||||
}
|
||||
|
||||
pObjPart->face_count = ((T_HOBFILE_FACEBLOCK *)(pMemfile + pObjPart->face_block_offset))->faceCounts;
|
||||
pObjPart->faces = calloc(pObjPart->face_count, sizeof(T_RSPMODEL_FACE));
|
||||
for ( i = 0; i < pObjPart->face_count; i++ ) {
|
||||
if (pParams->debug_mode) printf("\n----------------------Begin of Face part----------------------\n");
|
||||
//TODO: others T_HOBFILE_FACEGROUP_XXXXXXX parsing
|
||||
|
||||
// Get flags
|
||||
pObjPart->faces[i].flags = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->flags;
|
||||
// Get names from object parts and ID association
|
||||
printf("\n");
|
||||
for (i = 0; i < (pObjStruct->object_part_count - 1); i++) { // object_part_count minus 1 because the first one (id=0) is always the root part
|
||||
memcpy(tmpStr, hobObjPartsNames[i].name, 8);
|
||||
if (pParams->verbose_mode)
|
||||
printf("[DBG] > Object parts ID/name found: %d/%s\n", hobObjPartsNames[i].id, tmpStr);
|
||||
|
||||
// Get unknown bytes
|
||||
pObjPart->faces[i].b1 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b1;
|
||||
pObjPart->faces[i].b2 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b2;
|
||||
pObjPart->faces[i].b3 = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->b3;
|
||||
|
||||
pObjPart->faces[i].bsize = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->faceBlockIntSize * 4; // Multiply by 4 to get the bytes exact number
|
||||
if (((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK)
|
||||
+ sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->headerSeparator != 0) {
|
||||
if (pParams->god_mode) printf("[DBG] > Face header: uncommon separator!\n");
|
||||
}
|
||||
|
||||
// Get materials index
|
||||
pObjPart->faces[i].mt_index = ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->materialIndex;
|
||||
|
||||
// Get vertex indices
|
||||
memcpy(pObjPart->faces[i].indices, ((T_HOBFILE_FACES_HEADER *)(pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) * i + facesExtraOffset))->vertexIndices,
|
||||
sizeof(unsigned short) * 4);
|
||||
|
||||
// Recalculate the dynamic extra bytes offset size - if present
|
||||
if (pObjPart->faces[i].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8;
|
||||
|
||||
// Get vertex color - if present
|
||||
if (pObjPart->faces[i].flags_bits.fHasColor) {
|
||||
facesExtraOffset += ExtractObjpart_Face_Colors(&pObjPart->faces[i], pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * i
|
||||
+ facesExtraOffset);
|
||||
}
|
||||
|
||||
// Get UV map - if present
|
||||
if (pObjPart->faces[i].flags_bits.fHasTexture) {
|
||||
facesExtraOffset += ExtractObjpart_Face_UVMaps(&pObjPart->faces[i], pMemfile + pObjPart->face_block_offset
|
||||
+ sizeof(T_HOBFILE_FACEBLOCK) + sizeof(T_HOBFILE_FACES_HEADER) + sizeof(T_HOBFILE_FACES_HEADER) * i
|
||||
+ facesExtraOffset);
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) {
|
||||
printf("[DBG] > Face %d details: flags:0x%X b1:%d b2:%d b3%d bsize:%d\n", i, pObjPart->faces[i].flags,
|
||||
pObjPart->faces[i].b1, pObjPart->faces[i].b2, pObjPart->faces[i].b3, pObjPart->faces[i].bsize);
|
||||
printf("[DBG] - Type is Quad: %d\n", pObjPart->faces[i].flags_bits.fIsQuad);
|
||||
printf("[DBG] - Have color: %d\n", pObjPart->faces[i].flags_bits.fHasColor);
|
||||
printf("[DBG] - Have texture: %d\n", pObjPart->faces[i].flags_bits.fHasTexture);
|
||||
printf("[DBG] - Material/texture index: %d\n", pObjPart->faces[i].mt_index);
|
||||
printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", pObjPart->faces[i].indices[0], pObjPart->faces[i].indices[1],
|
||||
pObjPart->faces[i].indices[2], pObjPart->faces[i].indices[3]);
|
||||
printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", pObjPart->faces[i].vertex_colors[0],
|
||||
pObjPart->faces[i].vertex_colors[1], pObjPart->faces[i].vertex_colors[2], pObjPart->faces[i].vertex_colors[3]);
|
||||
printf("[DBG] - Vertex UV coord (divided by 4096):\n");
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[0].u,
|
||||
pObjPart->faces[i].tex_coords[0].u,
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[0].v,
|
||||
pObjPart->faces[i].tex_coords[0].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[1].u,
|
||||
pObjPart->faces[i].tex_coords[1].u,
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[1].v,
|
||||
pObjPart->faces[i].tex_coords[1].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[2].u,
|
||||
pObjPart->faces[i].tex_coords[2].u,
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[2].v,
|
||||
pObjPart->faces[i].tex_coords[2].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[3].u,
|
||||
pObjPart->faces[i].tex_coords[3].u,
|
||||
((double) 1/4096) * pObjPart->faces[i].tex_coords[3].v,
|
||||
pObjPart->faces[i].tex_coords[3].v
|
||||
);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (pParams->debug_mode) printf("\n-----------------------End of Face part-----------------------\n");
|
||||
if (pParams->god_mode && hobObjPartsNames[i].unknown0)
|
||||
printf("[DBG] > Object parts ID unknown0 unexpected: 0x%X\n", hobObjPartsNames[i].unknown0);
|
||||
}
|
||||
|
||||
// Get vertex datas
|
||||
pObjPart->vertices = calloc(pObjPart->vertex_count, sizeof(T_VERTEX));
|
||||
if (pObjPart->vertices == NULL) return RSPLIB_ERROR_MEMORY;
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
for ( i = 0; i < pObjPart->vertex_count; i++ ) {
|
||||
pObjPart->vertices[i].x =
|
||||
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->x;
|
||||
/**
|
||||
* @brief Parse datas from the specific object header.
|
||||
*
|
||||
* @param[in|out] pObjPartStruct Take object part structure and fill it with header datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] objPartIndex Object part index for correct offset align.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ParseObjectPartHeader(T_RSPMODEL_OBJ_PARTS* pObjPartStruct, const MEMFILE pMemfile,
|
||||
const int objPartHdrOffset, const unsigned char objPartIndex, const RSPMODEL_PARAMETERS* pParams) {
|
||||
|
||||
pObjPart->vertices[i].y =
|
||||
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->y;
|
||||
if (pObjPartStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
pObjPart->vertices[i].z =
|
||||
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->z;
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_OBJPART_HEADER* const hobObjPartHeader = ((T_HOBFILE_OBJPART_HEADER *)(pMemfile + objPartHdrOffset
|
||||
+ sizeof(T_HOBFILE_OBJPARTS_HEADER) + sizeof(T_HOBFILE_OBJPART_HEADER) * objPartIndex));
|
||||
|
||||
pObjPart->vertices[i].w =
|
||||
((T_HOBFILE_VERTEX *)(pMemfile + pObjPart->vertex_block_offset + sizeof(T_VERTEX) * i))->w; // Always 0???
|
||||
// Get object part datas offset
|
||||
pObjPartStruct->meshdef0_offset = hobObjPartHeader->facegroup_offset;
|
||||
if (pParams->verbose_mode) printf("[DBG] > Obj. part %d facegroup (meshdef0) array offset: 0x%X\n", objPartIndex, pObjPartStruct->meshdef0_offset);
|
||||
if (pParams->god_mode) printf("[DBG] > Obj. part unknown0: 0x%X\n", hobObjPartHeader->unknown0);
|
||||
|
||||
if (pParams->debug_mode) printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", i,
|
||||
pObjPart->vertices[i].x, pObjPart->vertices[i].y, pObjPart->vertices[i].z
|
||||
);
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse datas from object mesh definition.
|
||||
*
|
||||
* MeshDef (or Facegroup) is a compact structure containing the global geometry informations of a specific mesh.
|
||||
* It's split in 2 parts: meshdef0 and meshdef1, meshdef1 offset is indicated in meshdef0 struct.
|
||||
*
|
||||
* @param[in|out] pObjPartStruct Take object part structure and fill it with header datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ParseObjectMeshDef(T_RSPMODEL_OBJ_PARTS* pObjPartStruct, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
if (pObjPartStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_MESHDEF0* const hobObjMeshDef0 = ((T_HOBFILE_MESHDEF0*)(pMemfile + pObjPartStruct->meshdef0_offset));
|
||||
|
||||
// Get meshdef0 datas
|
||||
//pObjPartStruct->id = hobObjMeshDef0->object_id; // Get object part ID, used by animation? bones?
|
||||
pObjPartStruct->offset_transform.x = hobObjMeshDef0->offsett_x; // used by complex/animated objects like at-st, at-at, xwing, etc.
|
||||
pObjPartStruct->offset_transform.y = hobObjMeshDef0->offsett_y;
|
||||
pObjPartStruct->offset_transform.z = hobObjMeshDef0->offsett_z;
|
||||
pObjPartStruct->scale_transform.x = hobObjMeshDef0->scalet_x; // used by complex/animated objects like at-st, at-at, xwing, etc.
|
||||
pObjPartStruct->scale_transform.y = hobObjMeshDef0->scalet_y;
|
||||
pObjPartStruct->scale_transform.z = hobObjMeshDef0->scalet_z;
|
||||
pObjPartStruct->rotate_transform.x = hobObjMeshDef0->rott_x; // used by complex/animated objects like at-st, at-at, xwing, etc.
|
||||
pObjPartStruct->rotate_transform.y = hobObjMeshDef0->rott_y;
|
||||
pObjPartStruct->rotate_transform.z = hobObjMeshDef0->rott_z;
|
||||
pObjPartStruct->translate_transform.x = hobObjMeshDef0->transt_x; // used by complex/animated objects like at-st, at-at, xwing, etc.
|
||||
pObjPartStruct->translate_transform.y = hobObjMeshDef0->transt_y;
|
||||
pObjPartStruct->translate_transform.z = hobObjMeshDef0->transt_z;
|
||||
if (pParams->verbose_mode) {
|
||||
printf("[DBG] > Parent meshdef0 offset: 0x%X\n", hobObjMeshDef0->parent_meshdef0_offset);
|
||||
printf("[DBG] > Children meshdef0 offset: 0x%X\n", hobObjMeshDef0->children_meshdef0_offset);
|
||||
printf("[DBG] > Have offset transform: %d\n", (hobObjMeshDef0->vecsFlags & 0x1)?1:0);
|
||||
printf("[DBG] > Have scaling? vector: %d\n", (hobObjMeshDef0->vecsFlags & 0x2)?1:0);
|
||||
printf("[DBG] > Have translation? vector: %d\n", (hobObjMeshDef0->vecsFlags & 0x4)?1:0);
|
||||
printf("[DBG] > Have offset? vector: %d\n", (hobObjMeshDef0->vecsFlags & 0x8)?1:0);
|
||||
printf("[DBG] > ObjPart offset transform: [%.8f %.8f %.8f]\n",
|
||||
pObjPartStruct->offset_transform.x,
|
||||
pObjPartStruct->offset_transform.y,
|
||||
pObjPartStruct->offset_transform.z
|
||||
);
|
||||
printf("[DBG] > ObjPart scale transform: [%.8f %.8f %.8f]\n",
|
||||
pObjPartStruct->scale_transform.x,
|
||||
pObjPartStruct->scale_transform.y,
|
||||
pObjPartStruct->scale_transform.z
|
||||
);
|
||||
printf("[DBG] > ObjPart rotate transform: [%.8f %.8f %.8f]\n",
|
||||
pObjPartStruct->rotate_transform.x,
|
||||
pObjPartStruct->rotate_transform.y,
|
||||
pObjPartStruct->rotate_transform.z
|
||||
);
|
||||
printf("[DBG] > ObjPart translate transform: [%.8f %.8f %.8f]\n",
|
||||
pObjPartStruct->translate_transform.x,
|
||||
pObjPartStruct->translate_transform.y,
|
||||
pObjPartStruct->translate_transform.z
|
||||
);
|
||||
}
|
||||
if (pParams->god_mode) {
|
||||
printf("[DBG] > meshdef0 offset1: 0x%X\n", hobObjMeshDef0->offset1);
|
||||
printf("[DBG] > meshdef0 offset2: 0x%X\n", hobObjMeshDef0->offset2);
|
||||
|
||||
printf("[DBG] > meshdef0 unknown3: %.8f\n", hobObjMeshDef0->unknown3);
|
||||
printf("[DBG] > meshdef0 unknown4: %.8f\n", hobObjMeshDef0->unknown4);
|
||||
printf("[DBG] > meshdef0 unknown5: %.8f\n", hobObjMeshDef0->unknown5);
|
||||
|
||||
printf("[DBG] > meshdef0 unknown16: %.8f\n", hobObjMeshDef0->unknown16);
|
||||
}
|
||||
|
||||
// Get meshdef1 (mesh descriptor) offset
|
||||
pObjPartStruct->meshdef1_offset = hobObjMeshDef0->meshdef1_offset_plus_4;
|
||||
if (pObjPartStruct->meshdef1_offset > 0) {
|
||||
const T_HOBFILE_MESHDEF1* const hobObjMeshDef1 = ((T_HOBFILE_MESHDEF1*)(pMemfile + pObjPartStruct->meshdef1_offset - 4));
|
||||
|
||||
// Read meshdef1 datas
|
||||
pObjPartStruct->face_block_end_offset = hobObjMeshDef1->facedef_end_offset;
|
||||
pObjPartStruct->vertex_count = hobObjMeshDef1->vertex_count;
|
||||
pObjPartStruct->face_block_offset = hobObjMeshDef1->faceblock_offset;
|
||||
pObjPartStruct->vertex_block_offset = hobObjMeshDef1->vertexblocks_offset;
|
||||
if (pParams->verbose_mode) {
|
||||
printf("\n[DBG] > Facegroup vertices descriptor (meshdef1) offset: 0x%X\n", pObjPartStruct->meshdef1_offset);
|
||||
printf("[DBG] > Vertex count: %d\n", pObjPartStruct->vertex_count);
|
||||
printf("[DBG] > Faces offset: 0x%X\n", pObjPartStruct->face_block_offset);
|
||||
printf("[DBG] > Vertex offset: 0x%X\n", pObjPartStruct->vertex_block_offset);
|
||||
}
|
||||
} else {
|
||||
if (pParams->verbose_mode) printf("\n[DBG] > No vertices datas (meshdef1 = 0x0).\n");
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse datas from object faceblock header.
|
||||
*
|
||||
* Faceblock is group of faces elements with header.
|
||||
* Meshdef have one associated faceblock.
|
||||
*
|
||||
* @param[in|out] pObjPartStruct Take object part structure and fill it with header datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ParseObjectFaceblockHeader(T_RSPMODEL_OBJ_PARTS* pObjPartStruct, const MEMFILE pMemfile, const RSPMODEL_PARAMETERS* pParams) {
|
||||
if (pObjPartStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_FACEBLOCK* const hobObjFaceblock = ((T_HOBFILE_FACEBLOCK*)(pMemfile + pObjPartStruct->face_block_offset));
|
||||
|
||||
// Get faces count
|
||||
pObjPartStruct->face_count = hobObjFaceblock->faceCounts;
|
||||
if (pParams->debug_mode) printf("[DBG] > Faces count: %d\n", pObjPartStruct->face_count);
|
||||
|
||||
if (pParams->god_mode) {
|
||||
if( hobObjFaceblock->reserved1 != 0 || hobObjFaceblock->reserved2 != 0 ) {
|
||||
printf("[DBG] > Faceblock: uncommon zero header! (0x%X) (0x%X)\n", hobObjFaceblock->reserved1, hobObjFaceblock->reserved2);
|
||||
}
|
||||
if ( hobObjFaceblock->facesOffset != pObjPartStruct->face_block_offset + sizeof(T_HOBFILE_FACEBLOCK) ) {
|
||||
printf("[DBG] > Faceblock: uncommon face data offset position!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse datas from object face.
|
||||
*
|
||||
* @param[in|out] pFaceStruct Take face structure and fill it with face datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in|out] facesExtraOffset Face correction offset to correctly align with datas
|
||||
* @param[in] faceNbr Face number (for debug print only)
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ParseObjectFace(T_RSPMODEL_FACE* pFaceStruct, const MEMFILE pMemfile,
|
||||
unsigned int* const facesExtraOffset, const unsigned int faceNbr, const RSPMODEL_PARAMETERS* pParams) {
|
||||
unsigned int localOffset;
|
||||
|
||||
if (pFaceStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_FACES_HEADER* const hobObjFace = ((T_HOBFILE_FACES_HEADER*)(pMemfile + *facesExtraOffset));
|
||||
|
||||
// Get flags
|
||||
pFaceStruct->flags = hobObjFace->flags;
|
||||
|
||||
// Get unknown bytes
|
||||
pFaceStruct->b1 = hobObjFace->b1;
|
||||
pFaceStruct->b2 = hobObjFace->b2;
|
||||
pFaceStruct->b3 = hobObjFace->b3;
|
||||
pFaceStruct->bsize = hobObjFace->faceBlockIntSize * 4; // Multiply by 4 to get the bytes exact number
|
||||
|
||||
if (hobObjFace->headerSeparator != 0) {
|
||||
if (pParams->god_mode) printf("[DBG] > Face header: uncommon separator! (0x%X)\n", hobObjFace->headerSeparator);
|
||||
}
|
||||
|
||||
// Get materials index
|
||||
pFaceStruct->mt_index = hobObjFace->materialIndex;
|
||||
|
||||
// Get vertex indices
|
||||
memcpy(pFaceStruct->indices, hobObjFace->vertexIndices, sizeof(unsigned short) * 4);
|
||||
|
||||
// Recalculate the dynamic extra bytes offset size - if present
|
||||
//if (pObjPart->faces[i].flags_bits.fHasExtraBytesBeforeColor) facesExtraOffset += 8;
|
||||
localOffset = pFaceStruct->flags_bits.fHasExtraBytesBeforeColor ? 8 : 0;
|
||||
|
||||
// Get vertex color - if present
|
||||
if (pFaceStruct->flags_bits.fHasColor) {
|
||||
localOffset += ExtractObjpart_Face_Colors(pFaceStruct, pMemfile + *facesExtraOffset + sizeof(T_HOBFILE_FACES_HEADER) + localOffset);
|
||||
}
|
||||
|
||||
// Get UV map - if present
|
||||
if (pFaceStruct->flags_bits.fHasTexture) {
|
||||
localOffset += ExtractObjpart_Face_UVMaps(pFaceStruct, pMemfile + *facesExtraOffset + sizeof(T_HOBFILE_FACES_HEADER) + localOffset);
|
||||
}
|
||||
|
||||
// Recalculate the extra bytes offset (it's assume the faces are parsed in order)
|
||||
*facesExtraOffset += pFaceStruct->bsize;
|
||||
|
||||
if (pParams->debug_mode) {
|
||||
printf("[DBG] > Face %d details: flags:0x%X b1:0x%X b2:0x%X b3:0x%X bsize:%d\n", faceNbr,
|
||||
pFaceStruct->flags, pFaceStruct->b1, pFaceStruct->b2, pFaceStruct->b3, pFaceStruct->bsize);
|
||||
printf("[DBG] - Type is Quad: %d\n", pFaceStruct->flags_bits.fIsQuad);
|
||||
printf("[DBG] - Have color: %d\n", pFaceStruct->flags_bits.fHasColor);
|
||||
printf("[DBG] - Have texture: %d\n", pFaceStruct->flags_bits.fHasTexture);
|
||||
printf("[DBG] - Material/texture index: %d\n", pFaceStruct->mt_index);
|
||||
printf("[DBG] - Vertex indices: %d, %d, %d, %d\n", pFaceStruct->indices[0], pFaceStruct->indices[1], pFaceStruct->indices[2], pFaceStruct->indices[3]);
|
||||
printf("[DBG] - Vertex colors: 0x%X, 0x%X, 0x%X, 0x%X\n", pFaceStruct->vertex_colors[0], pFaceStruct->vertex_colors[1], pFaceStruct->vertex_colors[2], pFaceStruct->vertex_colors[3]);
|
||||
printf("[DBG] - Vertex UV coord (divided by 4096):\n");
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[0].u, pFaceStruct->tex_coords[0].u,
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[0].v, pFaceStruct->tex_coords[0].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[1].u, pFaceStruct->tex_coords[1].u,
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[1].v, pFaceStruct->tex_coords[1].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[2].u, pFaceStruct->tex_coords[2].u,
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[2].v, pFaceStruct->tex_coords[2].v
|
||||
);
|
||||
printf("[DBG] > %.8f(%d), %.8f(%d)\n",
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[3].u, pFaceStruct->tex_coords[3].u,
|
||||
((double) 1/4096) * pFaceStruct->tex_coords[3].v, pFaceStruct->tex_coords[3].v
|
||||
);
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse datas from object face.
|
||||
*
|
||||
* @param[in|out] pVertexStruct Take vertex structure and fill it with vertices datas.
|
||||
* @param[in] pMemfile Pointer to an in-memory file location.
|
||||
* @param[in] verticesOffset Vertices area offset to correctly align with datas
|
||||
* @param[in] vertexNbr Vertex number (for debug print only)
|
||||
* @param[in] pParams Program option, used to tune parser features.
|
||||
*
|
||||
* @return Error code, RSPLIB_SUCCESS when no error.
|
||||
*/
|
||||
static unsigned short ParseObjectFaceVertices(T_RSPMODEL_VERTEX* pVertexStruct, const MEMFILE pMemfile,
|
||||
const unsigned int verticesOffset, const unsigned int vertexNbr, const RSPMODEL_PARAMETERS* pParams) {
|
||||
|
||||
if (pVertexStruct == NULL || pMemfile == NULL) return RSPLIB_ERROR_ARGS_NULL;
|
||||
|
||||
// Create struct casting for clean code reading
|
||||
const T_HOBFILE_VERTEX* const hobObjVertex = ((T_HOBFILE_VERTEX*)(pMemfile + verticesOffset));
|
||||
|
||||
pVertexStruct->x = hobObjVertex->x;
|
||||
pVertexStruct->y = hobObjVertex->y;
|
||||
pVertexStruct->z = hobObjVertex->z;
|
||||
pVertexStruct->w = hobObjVertex->w; // Always 0???
|
||||
|
||||
if (pParams->debug_mode) {
|
||||
printf("[DBG] > Found vertex %d: (%d, %d, %d)\n", vertexNbr, pVertexStruct->x, pVertexStruct->y, pVertexStruct->z);
|
||||
}
|
||||
|
||||
return RSPLIB_SUCCESS;
|
||||
@ -408,7 +596,7 @@ static unsigned short ExtractObjpart_Face_Colors(T_RSPMODEL_FACE* pFace, const c
|
||||
pFace->vertex_colors[3] = ((T_HOBFILE_FACES_VERTEX_COLOR *)(pFaceMemFileOffset))->v4_rgba;
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR);
|
||||
} else {
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR) - sizeof(T_RGBA);
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_COLOR) - sizeof(T_RSPMODEL_RGBA);
|
||||
}
|
||||
} else {
|
||||
pFace->vertex_colors[0] = ((T_HOBFILE_FACES_COLOR *)(pFaceMemFileOffset))->rgba;
|
||||
@ -440,7 +628,7 @@ static unsigned short ExtractObjpart_Face_UVMaps(T_RSPMODEL_FACE* pFace, const c
|
||||
pFace->tex_coords[3] = ((T_HOBFILE_FACES_VERTEX_TEXTURE *)(pFaceMemFileOffset))->v4_texcoord;
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE);
|
||||
} else {
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE) - sizeof(T_TEXCOORD);
|
||||
dynOffset += sizeof(T_HOBFILE_FACES_VERTEX_TEXTURE) - sizeof(T_RSPMODEL_TEXCOORD);
|
||||
}
|
||||
|
||||
return dynOffset;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file hob_parser.h
|
||||
* @date 18/08/2022
|
||||
* @date 21/02/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Process HOB file structure and extract its datas.
|
||||
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "RSPModel_datatypes.h"
|
||||
#include "hob_struct.h"
|
||||
|
||||
|
||||
#ifndef RSPMODELLIB_HOB_PARSER_H_
|
||||
@ -19,33 +20,45 @@
|
||||
* HOB file and store them in T_RSPMODEL_HOB structure.
|
||||
* @note Unmanaged mode
|
||||
*
|
||||
* @param[in] pMemFile Pointer to an in-memory HOB file location.
|
||||
* @param[out] hobStruct Allocated empty T_RSPMODEL_HOB structure instance to
|
||||
* be filled with HOB datas.
|
||||
* @param[in] pMemFile Pointer to an in-memory HOB file location.
|
||||
* @param[in] pParams Parser options. See RSPMODEL_PARAMETERS.
|
||||
*
|
||||
* @return Processing error code, RSPLIB_SUCCESS if no error.
|
||||
*/
|
||||
unsigned short RSP_ModelLib_ParseHOBMemFile(const MEMFILE pMemFile,
|
||||
T_RSPMODEL_HOB* hobStruct, const RSPMODEL_PARAMETERS* pParams);
|
||||
unsigned short RSP_ModelLib_ProcessHOBMemFile(T_RSPMODEL_HOB* hobStruct,
|
||||
const MEMFILE pMemFile, const RSPMODEL_PARAMETERS* pParams);
|
||||
|
||||
/**
|
||||
* @brief Process HOB file in file system.
|
||||
* @details HOB file is dumped in memory before parsing in order to enhance
|
||||
* performance during parser operation and in optic to protect data
|
||||
* stored in the original file (read-only).
|
||||
* Parser will extract objects count and information stored in HOB file
|
||||
* and store them in T_RSPMODEL_HOB structure.
|
||||
* @note Managed mode
|
||||
* @brief Load file in memory and store it access in pointer.
|
||||
*
|
||||
* @param[in] fileName String value of file name/path.
|
||||
* @param[out] hobStruct Allocated empty T_RSPMODEL_HOB structure instance to
|
||||
* be filled with HOB datas.
|
||||
* @param[out newMemFile Newly created HOB file pointer, NULL if failure.
|
||||
* @param[in] fileName File path in the filesystem.
|
||||
* @param[in] pParams Parser options. See RSPMODEL_PARAMETERS.
|
||||
*
|
||||
* @return Processing error code, RSPLIB_SUCCESS if no error.
|
||||
*/
|
||||
unsigned short RSP_ModelLib_ParseHOBFile(const char* fileName,
|
||||
T_RSPMODEL_HOB* hobStruct, const RSPMODEL_PARAMETERS* pParams);
|
||||
unsigned short RSP_ModelLib_LoadHOBFile(MEMFILE* newMemFile, const char* fileName, const RSPMODEL_PARAMETERS* pParams);
|
||||
|
||||
/**
|
||||
* @brief Clean memory of file created with RSP_ModelLib_LoadHOBFile().
|
||||
*
|
||||
* @param[in] memFile Pointer to an in-memory HOB file location.
|
||||
*
|
||||
* @return Processing error code, RSPLIB_SUCCESS if no error.
|
||||
*/
|
||||
unsigned short RSP_ModelLib_FreeHOBFile(const MEMFILE* memFile);
|
||||
|
||||
/**
|
||||
* @brief Return number of model objects inside specified pMemfile.
|
||||
*
|
||||
* @param[in] pMemfile Pointer to an in-memory HOB file location.
|
||||
*
|
||||
* @return Number of model objects
|
||||
*/
|
||||
static inline unsigned int RSP_ModelLib_getObjectsCount(const MEMFILE pMemfile) {
|
||||
return ((T_HOBFILE_HEADER*)pMemfile)->obj_count;
|
||||
}
|
||||
|
||||
#endif /* RSPMODELLIB_HOB_PARSER_H_ */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file hob_struct.h
|
||||
* @date 26/07/2022
|
||||
* @date 18/09/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief HOB file mapping definition.
|
||||
@ -36,108 +36,158 @@
|
||||
/*
|
||||
* - Global HOB file structure-
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
* | T_HOBFILE_HEADER | obj_count * T_HOBFILE_OBJ_DESCRIPTOR | obj_count * T_HOBFILE_FACEGROUP_HEADER |
|
||||
* | T_HOBFILE_HEADER | obj_count * T_HOBFILE_OBJ_DESCRIPTOR | obj_count * T_HOBFILE_FACEGROUP_HEADER | -->
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure -
|
||||
* +----------------------------+------------------------------------------------+
|
||||
* | T_HOBFILE_FACEGROUP_HEADER | object_part_count * T_HOBFILE_FACEGROUP_OFFSET |
|
||||
* +----------------------------+------------------------------------------------+
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
* --> | T_HOBFILE_FACEGROUP_HEADER_1 | object_part_count * T_HOBFILE_FACEGROUP_OFFSET_1 |
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure 2 -
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
* | T_HOBFILE_FACEGROUP_HEADER_2 | ( object_part_count + facegroup_count ) * T_HOBFILE_FACEGROUP_OFFSET_2 | ( object_part_count - 1 ) * T_HOBFILE_FACEGROUP_NAMEID | + padding
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
*/
|
||||
typedef struct PACK hobfile_header {
|
||||
unsigned int obj_count;
|
||||
unsigned int vertices_offset;
|
||||
} T_HOBFILE_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_obj_descriptor {
|
||||
unsigned char object_name[16];
|
||||
unsigned int facegroup_offset;
|
||||
unsigned int object_parts_offset;
|
||||
unsigned int facegroup_header_2_offset;
|
||||
typedef struct PACK hobfile_obj_header {
|
||||
unsigned char object_name[16]; // Name of the object
|
||||
|
||||
unsigned int reserved1; // 12B of zeros
|
||||
unsigned int reserved2;
|
||||
unsigned int reserved3;
|
||||
unsigned int facegroup_start_offset; // First facegroup datas offset. Look in T_HOBFILE_FACEGROUP_HEADER for all offsets of facegroups of the current object.
|
||||
unsigned int object_parts_offset; // Object parts descriptor offset
|
||||
unsigned int object_parts_offset2; // Facegroup descriptor offset (subpart of Object parts descriptor)
|
||||
|
||||
unsigned int unknownOffset1;
|
||||
unsigned int unknownOffset2;
|
||||
unsigned int unknownOffset3;
|
||||
float unknown4;
|
||||
unsigned int object_parts2_offset; // Optional offset - seem present in tieinter_HOB - point just after the 0xFFFFFFFF of the first one
|
||||
unsigned int object_parts2_offset2; // Optional offset - seem present in tieinter_HOB
|
||||
unsigned int reserved1; // Always zeros ?
|
||||
|
||||
unsigned int reserved4; // 12B of zeros
|
||||
unsigned int subparts_namelist_offset; // Point to an array of string value (8 chars) + ID (2 chars - 1 to obj_parts-1). Seem like name of articulation points (some have name like "node_86").
|
||||
unsigned int effects_offset; // Empty in gun_turret and no datas after, xwing have 0x5006, present in koelsch. worddevastator can have more answers...
|
||||
unsigned int properties_offset; // Offset to different string (a_b/zf/zt/zb/etc.) Animation datas ? Empty with 6x float in train_hob, a_b object is canon beams in gun_turret
|
||||
|
||||
float unknown4; // 1.0F/1.125F - Look forward angle correction?
|
||||
|
||||
unsigned int reserved4; // 12B of zeros
|
||||
unsigned int reserved5;
|
||||
unsigned int reserved6;
|
||||
|
||||
float reserved7;
|
||||
float reserved8;
|
||||
float reserved9;
|
||||
float reserved10;
|
||||
float reserved11;
|
||||
unsigned int end_mask; // Always equal to 0xFFFFFFFF
|
||||
float reserved12;
|
||||
float reserved13;
|
||||
float reserved14;
|
||||
float reserved15;
|
||||
float reserved16;
|
||||
float reserved17;
|
||||
} T_HOBFILE_OBJ_DESCRIPTOR;
|
||||
float unknown5; // Something related to culling camera frustum (when reduced value, the gun_turret didn't render before getting out of camera view)
|
||||
float unknown6; // Something related to collision detection (bigger float >100.0f)
|
||||
|
||||
typedef struct PACK hobfile_facegroup_header {
|
||||
float reserved7; // Something related to collision detection Translation matrix? Center of object?
|
||||
float reserved8; // Something related to collision detection Translation matrix? Center of object?
|
||||
float reserved9; // Something related to collision detection Translation matrix? Center of object?
|
||||
|
||||
unsigned int footer_offset; //To redefine, seem to be a copy of following bounding box? Maybe there are 2 box: render and collision?
|
||||
|
||||
float bbox_start_x; // Bounding box start vector
|
||||
float bbox_start_y;
|
||||
float bbox_start_z;
|
||||
|
||||
float bbox_end_x; // Bounding box start vector
|
||||
float bbox_end_y;
|
||||
float bbox_end_z;
|
||||
} T_HOBFILE_OBJ_HEADER;
|
||||
|
||||
|
||||
/*
|
||||
* T_HOBFILE_OBJPARTS_HEADER
|
||||
* |
|
||||
* \
|
||||
* |T_HOBFILE_OBJPART_HEADER
|
||||
* \
|
||||
* T_HOBFILE_OBJPART_HEADER
|
||||
* |
|
||||
* \
|
||||
* |T_HOBFILE_FACEGROUP_HEADER
|
||||
* \
|
||||
* T_HOBFILE_FACEGROUP_HEADER
|
||||
*/
|
||||
typedef struct PACK hobfile_objparts_header {
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count; //aka. meshdef count
|
||||
} T_HOBFILE_OBJPARTS_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_objpart_header {
|
||||
unsigned int unknown0; // It is flags?
|
||||
unsigned int facegroup_offset;
|
||||
} T_HOBFILE_OBJPART_HEADER;
|
||||
|
||||
/* TODO: Not sure these exist
|
||||
typedef struct PACK hobfile_facegroup_header_2 { //TODO: This is part of a bigger one
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count;
|
||||
} T_HOBFILE_FACEGROUP_HEADER;
|
||||
} T_HOBFILE_FACEGROUP_HEADER_2;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_offset {
|
||||
unsigned int unknown1;
|
||||
unsigned int facegroup_offset;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET;
|
||||
typedef struct PACK hobfile_facegroup_offset_2 { //TODO: This is part of a bigger one
|
||||
unsigned int unknownOffset0;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET_2;
|
||||
*/
|
||||
|
||||
typedef struct PACK hobfile_objparts_nameid {
|
||||
unsigned char name[8];
|
||||
unsigned char unknown0; // Always zeros ?
|
||||
unsigned char id;
|
||||
} T_HOBFILE_OBJPARTS_NAMEID;
|
||||
|
||||
/* TODO:
|
||||
typedef struct PACK hobfile_effects {
|
||||
unsigned char something0;
|
||||
unsigned short something1;
|
||||
} T_HOBFILE_EFFECTS;
|
||||
*/
|
||||
|
||||
typedef struct PACK hobfile_meshdef0 {
|
||||
unsigned int offset1;
|
||||
unsigned int offset2;
|
||||
unsigned int prev_meshdef0_offset;
|
||||
unsigned int next_meshdef0_offset;
|
||||
unsigned int offset1; // Brothers meshdef?
|
||||
unsigned int offset2; // Brothers meshdef?
|
||||
unsigned int parent_meshdef0_offset;
|
||||
unsigned int children_meshdef0_offset;
|
||||
unsigned int meshdef1_offset_plus_4;
|
||||
|
||||
unsigned int reserved1; // 8B of zeros
|
||||
unsigned int reserved2;
|
||||
|
||||
float unknown3;
|
||||
float unknown3; // Always 1.0f?
|
||||
|
||||
unsigned int reserved3; // 12B of zeros
|
||||
unsigned int reserved4;
|
||||
unsigned int reserved5;
|
||||
|
||||
float unknown4;
|
||||
float unknown4; // Always 1.0f?
|
||||
|
||||
unsigned int reserved6; // 12B of zeros
|
||||
unsigned int reserved7;
|
||||
unsigned int reserved8;
|
||||
|
||||
float unknown5;
|
||||
float unknown5; // Always 1.0f?
|
||||
|
||||
unsigned int reserved9; // 12B of zeros
|
||||
unsigned int reserved10;
|
||||
unsigned int reserved11;
|
||||
|
||||
unsigned int object_id;
|
||||
unsigned int vecsFlags; // Enabled local transforms (bit0=offset #1; bit1=scale #2; bit2=rotation #3; bit3=translation;)
|
||||
|
||||
float unknown12; // Can be a vector???
|
||||
float unknown13;
|
||||
float unknown14;
|
||||
float offsett_x; // Offset transform (aka. reverse translation)
|
||||
float offsett_y;
|
||||
float offsett_z;
|
||||
|
||||
float unknown15; // Can be a vector???
|
||||
float unknown16;
|
||||
float unknown17;
|
||||
float scalet_x; // Local transform - Scale
|
||||
float scalet_y;
|
||||
float scalet_z;
|
||||
|
||||
float unknown18; // Can be a matrix???
|
||||
float unknown19;
|
||||
float unknown20;
|
||||
float unknown21;
|
||||
float rott_x; // Local transform - Rotation
|
||||
float rott_y;
|
||||
float rott_z;
|
||||
|
||||
float transform_x;
|
||||
float transform_y;
|
||||
float transform_z;
|
||||
float unknown16; // Always 0?
|
||||
|
||||
float transt_x; // Local transform - Translation
|
||||
float transt_y;
|
||||
float transt_z;
|
||||
} T_HOBFILE_MESHDEF0;
|
||||
|
||||
typedef struct PACK hobfile_meshdef1 {
|
||||
@ -180,31 +230,31 @@ typedef struct PACK hobfile_faceblock {
|
||||
|
||||
typedef struct PACK hobfile_faces_header {
|
||||
unsigned int flags;
|
||||
unsigned char b1; // 74 = transparent / 75 = opaque
|
||||
unsigned char b2;
|
||||
unsigned char b3;
|
||||
unsigned char b1; // Seem to alter texture mapping on face, 49 -> quad face, 48 -> tri face, 47 -> N/A
|
||||
unsigned char b2; // 61 -> texture right rotation, 71 -> little red overlay, 81 -> bigger red overlay, x1 -> don't do anything
|
||||
unsigned char b3; // Seem to alter rendering matrix or maybe vertices position relative to
|
||||
unsigned char faceBlockIntSize; // Bytes size divided by 4, count as number of UInt32 type.
|
||||
unsigned short headerSeparator;
|
||||
unsigned short headerSeparator; // If header it's uncommon, it's probably because you made a wrong parsing
|
||||
unsigned short materialIndex;
|
||||
unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape.
|
||||
} T_HOBFILE_FACES_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_color {
|
||||
T_RGBA v1_rgba;
|
||||
T_RGBA v2_rgba;
|
||||
T_RGBA v3_rgba;
|
||||
T_RGBA v4_rgba; // Used with quad type face
|
||||
T_RSPMODEL_RGBA v1_rgba;
|
||||
T_RSPMODEL_RGBA v2_rgba;
|
||||
T_RSPMODEL_RGBA v3_rgba;
|
||||
T_RSPMODEL_RGBA v4_rgba; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_color {
|
||||
T_RGBA rgba;
|
||||
T_RSPMODEL_RGBA rgba;
|
||||
} T_HOBFILE_FACES_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_texture {
|
||||
T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range
|
||||
T_TEXCOORD v2_texcoord;
|
||||
T_TEXCOORD v3_texcoord;
|
||||
T_TEXCOORD v4_texcoord; // Used with quad type face
|
||||
T_RSPMODEL_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range
|
||||
T_RSPMODEL_TEXCOORD v2_texcoord;
|
||||
T_RSPMODEL_TEXCOORD v3_texcoord;
|
||||
T_RSPMODEL_TEXCOORD v4_texcoord; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_TEXTURE;
|
||||
|
||||
typedef struct PACK hobfile_vertex {
|
||||
|
@ -1,246 +0,0 @@
|
||||
/**
|
||||
* @file hob_struct.h
|
||||
* @date 26/07/2022
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief HOB file mapping definition.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RSPMODELLIB_HOB_STRUCT_H_
|
||||
#define RSPMODELLIB_HOB_STRUCT_H_
|
||||
|
||||
|
||||
/*
|
||||
* long = 64bits???
|
||||
* int = 32bits
|
||||
* short = 16bits
|
||||
* car = 8bits
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define PACK
|
||||
#elif defined(__GNUC__)
|
||||
#define PACK __attribute__((packed))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Declaration of Memory Mapped Structure
|
||||
// Caution: the place of variable is important for correct mapping!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* - Global HOB file structure-
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
* | T_HOBFILE_HEADER | obj_count * T_HOBFILE_OBJ_DESCRIPTOR | obj_count * T_HOBFILE_FACEGROUP_HEADER | -->
|
||||
* +------------------+--------------------------------------+----------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure -
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
* --> | T_HOBFILE_FACEGROUP_HEADER_1 | object_part_count * T_HOBFILE_FACEGROUP_OFFSET_1 |
|
||||
* +------------------------------+--------------------------------------------------+
|
||||
*
|
||||
* - Facegroup sub-structure 2 -
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
* | T_HOBFILE_FACEGROUP_HEADER_2 | ( object_part_count + facegroup_count ) * T_HOBFILE_FACEGROUP_OFFSET_2 | ( object_part_count - 1 ) * T_HOBFILE_FACEGROUP_NAMEID | + padding
|
||||
* +------------------------------+------------------------------------------------------------------------+--------------------------------------------------------+
|
||||
*/
|
||||
typedef struct PACK hobfile_header {
|
||||
unsigned int obj_count;
|
||||
unsigned int vertices_offset;
|
||||
} T_HOBFILE_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_obj_header {
|
||||
unsigned char object_name[16]; // Name of the object
|
||||
|
||||
unsigned int facegroup_start_offset; // First facegroup datas offset. Look in T_HOBFILE_FACEGROUP_HEADER for all offsets of facegroups of the current object.
|
||||
unsigned int object_parts_offset; // Object parts descriptor offset
|
||||
unsigned int object_parts_offset2; // Facegroup descriptor offset (subpart of Object parts descriptor)
|
||||
|
||||
unsigned int opt_offset1; // Optional offset - empty on last obj_header - point to after end mask ffffff of current bloc
|
||||
unsigned int opt_offset2; // Optional offset - empty on last obj_header - point to after the previous opt_offset1
|
||||
unsigned int reserved1; // Always zeros ?
|
||||
|
||||
unsigned int subparts_namelist_offset; // Point to an array of string value (8 chars) + ID (2 chars - 1 to obj_parts-1). Seem like name of articulation points (some have name like "node_86").
|
||||
unsigned int effects_offset; // Empty in gun_turret and no datas after, xwing have 0x5006. worddevastator should have the answer...
|
||||
unsigned int properties_offset; // Offset to different string (a_b/zf/zt/zb/etc.) Animation datas ? Empty with 6x float in train_hob
|
||||
|
||||
float unknown4; // Probably scale: 1.0F/1.125F
|
||||
|
||||
unsigned int reserved4; // 12B of zeros
|
||||
unsigned int reserved5;
|
||||
unsigned int reserved6;
|
||||
|
||||
float unknown5; //Scale? ~20.0F
|
||||
float unknown6; //Scale? ~77-418.0F
|
||||
|
||||
float reserved7; //Translation matrix? Center of object?
|
||||
float reserved8;
|
||||
float reserved9;
|
||||
|
||||
unsigned int footer_offset; //To redefine, seem to be a copy of following bounding box? Maybe there are 2 box: render and collision?
|
||||
|
||||
float bbox_start_x; // Bounding box start vector
|
||||
float bbox_start_y;
|
||||
float bbox_start_z;
|
||||
|
||||
float bbox_end_x; // Bounding box start vector
|
||||
float bbox_end_y;
|
||||
float bbox_end_z;
|
||||
} T_HOBFILE_OBJ_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_header_1 {
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count;
|
||||
} T_HOBFILE_FACEGROUP_HEADER_1;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_offset_1 {
|
||||
unsigned int unknown0; // Flags?
|
||||
unsigned int facegroup_offset;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET_1;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_header_2 {
|
||||
unsigned short object_part_count;
|
||||
unsigned short facegroup_count;
|
||||
} T_HOBFILE_FACEGROUP_HEADER_2;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_offset_2 {
|
||||
unsigned int unknownOffset0;
|
||||
} T_HOBFILE_FACEGROUP_OFFSET_2;
|
||||
|
||||
typedef struct PACK hobfile_facegroup_nameid {
|
||||
unsigned char name[8];
|
||||
unsigned short id;
|
||||
} T_HOBFILE_FACEGROUP_NAMEID;
|
||||
|
||||
typedef struct PACK hobfile_meshdef0 {
|
||||
unsigned int offset1;
|
||||
unsigned int offset2;
|
||||
unsigned int prev_meshdef0_offset;
|
||||
unsigned int next_meshdef0_offset;
|
||||
unsigned int meshdef1_offset_plus_4;
|
||||
|
||||
unsigned int reserved1; // 8B of zeros
|
||||
unsigned int reserved2;
|
||||
|
||||
float unknown3;
|
||||
|
||||
unsigned int reserved3; // 12B of zeros
|
||||
unsigned int reserved4;
|
||||
unsigned int reserved5;
|
||||
|
||||
float unknown4;
|
||||
|
||||
unsigned int reserved6; // 12B of zeros
|
||||
unsigned int reserved7;
|
||||
unsigned int reserved8;
|
||||
|
||||
float unknown5;
|
||||
|
||||
unsigned int reserved9; // 12B of zeros
|
||||
unsigned int reserved10;
|
||||
unsigned int reserved11;
|
||||
|
||||
unsigned int object_id;
|
||||
|
||||
float unknown12; // Can be a vector???
|
||||
float unknown13;
|
||||
float unknown14;
|
||||
|
||||
float unknown15; // Can be a vector???
|
||||
float unknown16;
|
||||
float unknown17;
|
||||
|
||||
float unknown18; // Can be a matrix???
|
||||
float unknown19;
|
||||
float unknown20;
|
||||
float unknown21;
|
||||
|
||||
float transform_x;
|
||||
float transform_y;
|
||||
float transform_z;
|
||||
} T_HOBFILE_MESHDEF0;
|
||||
|
||||
typedef struct PACK hobfile_meshdef1 {
|
||||
unsigned int facedef_end_offset;
|
||||
|
||||
unsigned int reserved1; // 20B of zeros
|
||||
unsigned int reserved2;
|
||||
unsigned int reserved3;
|
||||
unsigned int reserved4;
|
||||
unsigned int reserved5;
|
||||
|
||||
unsigned int vertex_count;
|
||||
unsigned int unknown1;
|
||||
unsigned int reserved6;
|
||||
unsigned int faceblock_offset;
|
||||
unsigned int vertexblocks_offset;
|
||||
|
||||
unsigned int reserved7; // 52B of zeros
|
||||
unsigned int reserved8;
|
||||
unsigned int reserved9;
|
||||
unsigned int reserved10;
|
||||
unsigned int reserved11;
|
||||
unsigned int reserved12;
|
||||
unsigned int reserved13;
|
||||
unsigned int reserved14;
|
||||
unsigned int reserved15;
|
||||
unsigned int reserved16;
|
||||
unsigned int reserved17;
|
||||
unsigned int reserved18;
|
||||
unsigned int reserved19;
|
||||
} T_HOBFILE_MESHDEF1;
|
||||
|
||||
typedef struct PACK hobfile_faceblock {
|
||||
unsigned int reserved1; // 8B of zeros
|
||||
unsigned int reserved2;
|
||||
|
||||
unsigned int facesOffset;
|
||||
unsigned int faceCounts;
|
||||
} T_HOBFILE_FACEBLOCK;
|
||||
|
||||
typedef struct PACK hobfile_faces_header {
|
||||
unsigned int flags;
|
||||
unsigned char b1; // 74 = transparent / 75 = opaque
|
||||
unsigned char b2;
|
||||
unsigned char b3;
|
||||
unsigned char faceBlockIntSize; // Bytes size divided by 4, count as number of UInt32 type.
|
||||
unsigned short headerSeparator;
|
||||
unsigned short materialIndex;
|
||||
unsigned short vertexIndices[4]; // Relative to facegroup, the last value is equal to 0 when it's triangle shape.
|
||||
} T_HOBFILE_FACES_HEADER;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_color {
|
||||
T_RGBA v1_rgba;
|
||||
T_RGBA v2_rgba;
|
||||
T_RGBA v3_rgba;
|
||||
T_RGBA v4_rgba; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_color {
|
||||
T_RGBA rgba;
|
||||
} T_HOBFILE_FACES_COLOR;
|
||||
|
||||
typedef struct PACK hobfile_faces_extra_vertex_texture {
|
||||
T_TEXCOORD v1_texcoord; // Should be divided (no shifting) by 4096 to get 0...1 range
|
||||
T_TEXCOORD v2_texcoord;
|
||||
T_TEXCOORD v3_texcoord;
|
||||
T_TEXCOORD v4_texcoord; // Used with quad type face
|
||||
} T_HOBFILE_FACES_VERTEX_TEXTURE;
|
||||
|
||||
typedef struct PACK hobfile_vertex {
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
short w;
|
||||
} T_HOBFILE_VERTEX;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif /* RSPMODELLIB_HOB_STRUCT_H_ */
|
21
RSPModelLib/src/mesh_builder.h
Normal file
21
RSPModelLib/src/mesh_builder.h
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @file mesh_builder.h
|
||||
* @date 18/01/2023
|
||||
* @author JackCarterSmith
|
||||
* @copyright GPL-v3.0
|
||||
* @brief Mesh constructor of HOB objects.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "RSPModel_datatypes.h"
|
||||
|
||||
#ifndef MESH_BUILDER_H_
|
||||
#define MESH_BUILDER_H_
|
||||
|
||||
unsigned short RSP_ModelLib_HOBObjectToGL( const T_RSPMODEL_OBJECT* objStruct );
|
||||
/*
|
||||
unsigned short RSP_ModelLib_HOBObjectToGL( const T_RSPMODEL_OBJECT* objStruct, void* glObj );
|
||||
unsigned short RSP_ModelLib_HOBObjectToD3D( const T_RSPMODEL_OBJECT* objStruct, void* D3DObj );
|
||||
*/
|
||||
|
||||
#endif /* MESH_BUILDER_H_ */
|
132
conanfile.py
Normal file
132
conanfile.py
Normal file
@ -0,0 +1,132 @@
|
||||
import os
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake
|
||||
from conan.tools.files import copy
|
||||
from conan.tools.scm import Git, Version
|
||||
|
||||
required_conan_version = ">=2.3"
|
||||
|
||||
class rse_model(ConanFile):
|
||||
name = "rspmodellib"
|
||||
package_type = "library"
|
||||
version = "2.3.1"
|
||||
revision_mode = "scm"
|
||||
license = "GPL-3.0"
|
||||
author = "JackCarterSmith <jackcartersmith@jcsmith.fr>"
|
||||
url = "https://git.jcsmith.fr/JCS-Prod/RSE-Model"
|
||||
description = "Rogue Squadron 3D (PC) game models files (HOB) extractor"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "CMakeDeps"
|
||||
options = {
|
||||
"shared": [True, False],
|
||||
"tools": [True, False],
|
||||
"fPIC": [True, False]
|
||||
}
|
||||
|
||||
default_options = {
|
||||
"shared": True,
|
||||
"tools": False,
|
||||
"fPIC": True
|
||||
}
|
||||
|
||||
@property
|
||||
def _is_msvc(self):
|
||||
return str(self.settings.compiler) in ["Visual Studio", "msvc"]
|
||||
|
||||
#def validate(self):
|
||||
# if self.settings.os == "Macos":
|
||||
# raise ConanInvalidConfiguration("MacOS not supported")
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == "Windows":
|
||||
del self.options.fPIC
|
||||
|
||||
def configure(self):
|
||||
self.options["glew"].shared = True
|
||||
#self.options["vulkan-loader"].shared = True
|
||||
if self.options.shared:
|
||||
self.options.rm_safe("fPIC")
|
||||
|
||||
def requirements(self):
|
||||
if self.options.tools:
|
||||
#self.requires("opengl/system")
|
||||
#self.requires("glu/system")
|
||||
self.requires("glew/2.2.0")
|
||||
#self.requires("vulkan-headers/1.3.236.0")
|
||||
#self.requires("vulkan-memory-allocator/3.0.1")
|
||||
#self.requires("vulkan-loader/1.3.236.0")
|
||||
|
||||
def source(self):
|
||||
git = Git(self)
|
||||
cargs = ['--single-branch', '--recursive', '--depth', '1', '--branch', 'v' + self.version]
|
||||
git.clone(url="https://git.jcsmith.fr/JCS-Prod/RSE-Model.git", target=".", args=cargs)
|
||||
|
||||
# def _patch(self):
|
||||
# replace_in_file(self, os.path.join(self.source_folder, "RSPModelLib", "CMakeLists.txt"),
|
||||
# 'set_target_properties(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}_static")',
|
||||
# 'set_target_properties(rsp-texture-libstatic PROPERTIES OUTPUT_NAME "${RSP_TEXTURE_LIB_NAME}")')
|
||||
|
||||
def export_sources(self):
|
||||
copy(self, "CMakeLists.txt", self.recipe_folder, self.export_sources_folder)
|
||||
|
||||
# def layout(self):
|
||||
# cmake_layout(self, src_folder='.', build_folder='build')
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.cache_variables["RSPMODEL_SHARED"] = self.options.shared
|
||||
tc.cache_variables["RSPMODEL_STATIC"] = not self.options.shared
|
||||
tc.cache_variables["BUILD_TOOLS"] = self.options.tools
|
||||
#tc.cache_variables["BUILD_DEBUG"] = self.settings.build_type == "Debug"
|
||||
tc.generate()
|
||||
|
||||
#cmdeps = CMakeDeps(self)
|
||||
#cmpdeps.set_property("glew", "cmake_find_mode", "both")
|
||||
#if self.options.shared:
|
||||
#cmdeps.configuration = "ReleaseShared"
|
||||
#cmdeps.generate()
|
||||
|
||||
for dep in self.dependencies.values():
|
||||
if len(dep.cpp_info.bindirs) > 0:
|
||||
if self.settings.os == "Windows":
|
||||
if self._is_msvc:
|
||||
copy(self, "*.dll", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin", str(self.settings.build_type)))
|
||||
else:
|
||||
copy(self, "*.dll", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin"))
|
||||
else:
|
||||
copy(self, "*.so", dep.cpp_info.bindirs[0], os.path.join(self.build_folder, "bin"))
|
||||
|
||||
def build(self):
|
||||
cmbuilder = CMake(self)
|
||||
#self._patch()
|
||||
cmbuilder.configure()
|
||||
cmbuilder.build()
|
||||
|
||||
def package(self):
|
||||
copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses"))
|
||||
copy(self, pattern="*.h", src=os.path.join(self.source_folder, "include"), dst=os.path.join(self.package_folder, "include"))
|
||||
copy(self, pattern="*.a", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||
copy(self, pattern="*.so", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||
copy(self, pattern="*.lib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False)
|
||||
copy(self, pattern="*.dll", src=self.build_folder, dst=os.path.join(self.package_folder, "bin"), keep_path=False)
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.set_property("cmake_file_name", "RSEModel")
|
||||
self.cpp_info.set_property("cmake_target_name", "RSEModel")
|
||||
self.cpp_info.set_property("cmake_module_target_name", "RSEModel::RSEModel")
|
||||
self.cpp_info.set_property("cmake_find_mode", "both")
|
||||
|
||||
self.cpp_info.names["cmake_find_package"] = "RSEModel"
|
||||
self.cpp_info.names["cmake_find_package_multi"] = "RSEModel"
|
||||
|
||||
self.cpp_info.includedirs = ["include"]
|
||||
|
||||
prefix = "lib" if self._is_msvc else ""
|
||||
#suffix = "d" if self.settings.build_type == "Debug" else ""
|
||||
suffix = ""
|
||||
major_min_version = f"{Version(self.version).major}{Version(self.version).minor}"
|
||||
|
||||
self.cpp_info.libs = ["{}RSEModel{}{}".format(prefix, major_min_version, suffix)]
|
||||
if self.settings.os in ["Linux", "Android", "FreeBSD", "SunOS", "AIX"]:
|
||||
self.cpp_info.system_libs.append("m")
|
||||
self.cpp_info.system_libs.append("dl")
|
@ -1,12 +0,0 @@
|
||||
[requires]
|
||||
glew/2.2.0
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
cmake_find_package
|
||||
|
||||
[options]
|
||||
glew:shared=True
|
||||
|
||||
[imports]
|
||||
bin, *.dll -> ./bin
|
@ -38,7 +38,7 @@ PROJECT_NAME = RSE-Model
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2.1.0
|
||||
PROJECT_NUMBER = 2.3.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
Loading…
x
Reference in New Issue
Block a user