mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-23 04:19:50 +00:00
1a10e45682
Renamed all instances of skelatool -> skeletool. This is more consistent than the mixed usage previously, which consequently makes adding the external project in CMake easier.
217 lines
6.7 KiB
C++
217 lines
6.7 KiB
C++
|
|
#include <assimp/mesh.h>
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <assimp/postprocess.h>
|
|
|
|
#ifndef WIN32
|
|
#include <execinfo.h>
|
|
#endif
|
|
|
|
#include "src/SceneWriter.h"
|
|
#include "src/CommandLineParser.h"
|
|
#include "src/materials/MaterialParser.h"
|
|
#include "src/SceneLoader.h"
|
|
#include "src/FileUtils.h"
|
|
|
|
#include "src/definition_generator/MeshDefinitionGenerator.h"
|
|
#include "src/definition_generator/CollisionGenerator.h"
|
|
#include "src/definition_generator/MaterialGenerator.h"
|
|
#include "src/materials/MaterialState.h"
|
|
#include "src/materials/MaterialTranslator.h"
|
|
#include "src/StringUtils.h"
|
|
#include "src/lua_generator/LuaGenerator.h"
|
|
|
|
void handler(int sig) {
|
|
// print out all the frames to stderr
|
|
fprintf(stderr, "Error: signal %d:\n", sig);
|
|
|
|
#ifndef WIN32
|
|
// TODO: proper backtraces on Windows
|
|
void *array[10];
|
|
size_t size = backtrace(array, 10);
|
|
backtrace_symbols_fd(array, size, STDERR_FILENO);
|
|
#endif
|
|
|
|
exit(1);
|
|
}
|
|
|
|
|
|
bool parseMaterials(const std::string& filename, DisplayListSettings& output) {
|
|
std::fstream file(filename, std::ios::in);
|
|
|
|
struct ParseResult parseResult(DirectoryName(filename));
|
|
parseResult.mForcePallete = output.mForcePallete;
|
|
parseResult.mTargetCIBuffer = output.mTargetCIBuffer;
|
|
parseMaterialFile(file, parseResult);
|
|
output.mMaterials.insert(parseResult.mMaterialFile.mMaterials.begin(), parseResult.mMaterialFile.mMaterials.end());
|
|
|
|
for (auto err : parseResult.mErrors) {
|
|
std::cerr << "Error parsing file " << filename << std::endl;
|
|
std::cerr << err.mMessage << std::endl;
|
|
}
|
|
|
|
return parseResult.mErrors.size() == 0;
|
|
}
|
|
|
|
bool getVectorByName(const aiScene* scene, const std::string name, aiVector3D& result) {
|
|
int axis;
|
|
if (!scene->mMetaData->Get(name, axis)) {
|
|
return false;
|
|
}
|
|
|
|
switch (axis) {
|
|
case 0: result = aiVector3D(1.0f, 0.0f, 0.0f); break;
|
|
case 1: result = aiVector3D(0.0f, 1.0f, 0.0f); break;
|
|
case 2: result = aiVector3D(0.0f, 0.0f, 1.0f); break;
|
|
default: return false;
|
|
}
|
|
|
|
int upSign;
|
|
if (scene->mMetaData->Get(name + "Sign", upSign)) {
|
|
if (upSign < 0) {
|
|
result = -result;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
float angleBetween(const aiVector3D& a, const aiVector3D& b) {
|
|
return acos(a * b / (a - b).SquareLength());
|
|
}
|
|
|
|
aiQuaternion getUpRotation(const aiVector3D& euler) {
|
|
return aiQuaternion(euler.y * M_PI / 180.0f, euler.z * M_PI / 180.0f, euler.x * M_PI / 180.0f);
|
|
}
|
|
|
|
/**
|
|
* F3DEX2 - 32 vertices in buffer
|
|
* F3D - 16 vetcies in buffer
|
|
*/
|
|
|
|
int main(int argc, char *argv[]) {
|
|
signal(SIGSEGV, handler);
|
|
CommandLineArguments args;
|
|
|
|
if (!parseCommandLineArguments(argc, argv, args)) {
|
|
return 1;
|
|
}
|
|
|
|
DisplayListSettings settings = DisplayListSettings();
|
|
|
|
settings.mFixedPointScale = args.mFixedPointScale;
|
|
settings.mModelScale = args.mModelScale;
|
|
settings.mRotateModel = getUpRotation(args.mEulerAngles);
|
|
settings.mPrefix = args.mPrefix;
|
|
settings.mExportAnimation = args.mExportAnimation;
|
|
settings.mExportGeometry = args.mExportGeometry;
|
|
settings.mBonesAsVertexGroups = args.mBonesAsVertexGroups;
|
|
settings.mForcePallete = args.mForcePallete;
|
|
settings.mTargetCIBuffer = args.mTargetCIBuffer;
|
|
settings.mTicksPerSecond = args.mFPS;
|
|
settings.mSortDirection = args.mSortDirection;
|
|
|
|
bool hasError = false;
|
|
|
|
for (auto materialFile = args.mMaterialFiles.begin(); materialFile != args.mMaterialFiles.end(); ++materialFile) {
|
|
if (EndsWith(*materialFile, ".yaml") || EndsWith(*materialFile, ".yml") || EndsWith(*materialFile, ".json")) {
|
|
if (!parseMaterials(*materialFile, settings)) {
|
|
hasError = true;
|
|
}
|
|
} else {
|
|
aiScene* materialScene = loadScene(*materialFile, true, settings.mVertexCacheSize, 0);
|
|
|
|
if (!materialScene) {
|
|
hasError = true;
|
|
}
|
|
|
|
fillMissingMaterials(gTextureCache, materialScene, settings);
|
|
}
|
|
}
|
|
|
|
if (hasError) {
|
|
return 1;
|
|
}
|
|
|
|
auto defaultMaterial = settings.mMaterials.find(args.mDefaultMaterial);
|
|
|
|
if (defaultMaterial != settings.mMaterials.end()) {
|
|
settings.mDefaultMaterialState = defaultMaterial->second->mState;
|
|
settings.mDefaultMaterialName = args.mDefaultMaterial;
|
|
settings.mForceMaterialName = args.mForceMaterialName;
|
|
}
|
|
|
|
const aiScene* scene = NULL;
|
|
|
|
unsigned int additionalPFlags = 0;
|
|
|
|
if (settings.NeedsTangents()) {
|
|
additionalPFlags |= aiProcess_CalcTangentSpace;
|
|
}
|
|
|
|
if (args.mInputFile.length()) {
|
|
std::cout << "Generating from mesh " << args.mInputFile << std::endl;
|
|
scene = loadScene(args.mInputFile, args.mOutputType == FileOutputType::Mesh && !args.mProcessAsModel, settings.mVertexCacheSize, additionalPFlags);
|
|
|
|
if (!scene) {
|
|
return 1;
|
|
}
|
|
|
|
fillMissingMaterials(gTextureCache, scene, settings);
|
|
}
|
|
|
|
std::cout << "Saving to " << args.mOutputFile << std::endl;
|
|
CFileDefinition fileDef(settings.mPrefix, settings.mFixedPointScale, settings.mModelScale, settings.mRotateModel);
|
|
|
|
switch (args.mOutputType)
|
|
{
|
|
case FileOutputType::Mesh:
|
|
{
|
|
MeshDefinitionGenerator meshGenerator(settings);
|
|
std::cout << "Generating mesh definitions" << std::endl;
|
|
meshGenerator.TraverseScene(scene);
|
|
meshGenerator.PopulateBones(scene, fileDef);
|
|
meshGenerator.GenerateDefinitions(scene, fileDef);
|
|
break;
|
|
}
|
|
case FileOutputType::Materials:
|
|
{
|
|
std::cout << "Saving materials to " << args.mOutputFile << std::endl;
|
|
|
|
MaterialGenerator materialGenerator(settings);
|
|
|
|
materialGenerator.TraverseScene(scene);
|
|
materialGenerator.GenerateDefinitions(scene, fileDef);
|
|
break;
|
|
}
|
|
case FileOutputType::CollisionMesh:
|
|
{
|
|
NodeGroups nodesByGroup(scene);
|
|
std::cout << "Generating collider definitions" << std::endl;
|
|
auto collisionOutput = generateCollision(scene, fileDef, settings, nodesByGroup);
|
|
generateMeshCollider(fileDef, *collisionOutput);
|
|
break;
|
|
}
|
|
case FileOutputType::Script:
|
|
{
|
|
NodeGroups nodesByGroup(scene);
|
|
|
|
for (auto script : args.mScriptFiles) {
|
|
std::cout << "Generating definitions from script " << script << std::endl;
|
|
generateFromLuaScript(args.mInputFile, script, scene, fileDef, nodesByGroup, settings);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::cout << "Writing output" << std::endl;
|
|
fileDef.GenerateAll(args.mOutputFile);
|
|
|
|
return 0;
|
|
} |