<commit_before>/* OpenHoW
 * Copyright (C) 2017-2020 <NAME> <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <PL/platform_filesystem.h>
#include <PL/platform_mesh.h>
#include <PL/platform_model.h>

#include "engine.h"
#include "model.h"
#include "loaders/loaders.h"

#include "graphics/display.h"
#include "graphics/shaders.h"
#include "graphics/texture_atlas.h"
#include "graphics/mesh.h"

using namespace openhow;

const char *Model_GetAnimationDescription( unsigned int i ) {
	static const char *animationNames[] = {
		"Run cycle (normal)",
		"Run cycle (wounded)",
		"Run cycle (more wounded)",
		"Walk cycle (backwards)",
		"Turning on Spot",
		"Swimming",
		"Swimming like Rick",
		"Getting into Vehicles",
		"Jumping - Start",
		"Jumping - Middle",
		"Jumping - End",
		"Scramble",
		"Getting out Handgun",
		"Getting out Rifle",
		"Getting out Machine gun",
		"Getting out Heavy weapon",
		"Getting out Punch",
		"Getting out Grenade",
		"Getting out Sword / Knife",
		"Using Grenade",
		"Using Punch",
		"Sword / Knife",
		"Bayonet",
		"Aiming Handgun",
		"Aiming Rifle",
		"Aiming Machine gun",
		"Aiming Heavy weapon",
		"Standing around cycle 1",
		"Standing around cycle 2",
		"Very Wounded",
		"Lord Flash-Heart Pose",
		"Looking around",
		"Looking gormless",
		"Cowering",
		"Brushoff 1",
		"Brushoff 2",
		"Brushoff 3",
		"Sneeze",
		"Flying through air/falling",
		"Bouncing on B-Hind",
		"Getting to feet",
		"Celebration #1",
		"Celebration #2",
		"Celebration #3",
		"Salute",
		"Look back",
		"Thinking",
		"Dying #1",
		"Dying #2",
		"Dying #3",
		"Drowning",
		"Idle Cold",
		"Idle Hot",
		"Lay Mine",
		"Heal",
		"Pick pocket",
		"Air strike",
		"<NAME>",
		"Parachuting",
	};

	if ( i >= plArrayElements( animationNames ) ) {
		return nullptr;
	}

	return animationNames[ i ];
}

PLModel *Model_LoadVtxFile( const char *path ) {
	VtxHandle *vtx = Vtx_LoadFile( path );
	if ( vtx == nullptr ) {
		LogWarn( "Failed to load Vtx, \"%s\"!\n", path );
		return nullptr;
	}

	/* now we load in all the faces */
	char fac_path[PL_SYSTEM_MAX_PATH];
	strncpy( fac_path, path, strlen( path ) - 3 );
	fac_path[ strlen( path ) - 3 ] = '\0';
	strcat( fac_path, "fac" );
	FacHandle *fac = Fac_LoadFile( fac_path );
	if ( fac == nullptr ) {
		Vtx_DestroyHandle( vtx );
		LogWarn( "Failed to load Fac, \"%s\"!\n", path );
		return nullptr;
	}

	const char *filename = plGetFileName( path );
	// skydome is a special case, since we don't care about textures...
	if ( pl_strcasecmp( filename, "skydome.vtx" ) == 0 || pl_strcasecmp( filename, "skydomeu.vtx" ) == 0 ) {
		PLMesh *mesh = plCreateMesh( PL_MESH_TRIANGLES, PL_DRAW_STATIC, fac->num_triangles, vtx->num_vertices );
		if ( mesh == nullptr ) {
			Vtx_DestroyHandle( vtx );
			Fac_DestroyHandle( fac );
			LogWarn( "Failed to create mesh (%s)!\n", plGetError() );
			return nullptr;
		}

		for ( unsigned int j = 0; j < vtx->num_vertices; ++j ) {
			plSetMeshVertexPosition( mesh, j, vtx->vertices[ j ].position * -1 * .5f );
		}

		unsigned int cur_index = 0;
		for ( unsigned int j = 0; j < fac->num_triangles; ++j ) {
			plSetMeshTrianglePosition( mesh, &cur_index,
									   fac->triangles[ j ].vertex_indices[ 0 ],
									   fac->triangles[ j ].vertex_indices[ 1 ],
									   fac->triangles[ j ].vertex_indices[ 2 ]
			);
		}

		Vtx_DestroyHandle( vtx );
		Fac_DestroyHandle( fac );

		mesh->texture = Engine::Resource()->GetFallbackTexture();

		PLModel *model = plCreateBasicStaticModel( mesh );
		if ( model == nullptr ) {
			LogWarn( "Failed to create model (%s)!\n", plGetError() );
			return nullptr;
		}

		return model;
	}

	TextureAtlas atlas( 128, 8 );
	if ( fac->texture_table_size > 0 ) {
		for ( unsigned int i = 0; i < fac->texture_table_size; ++i ) {
			if ( fac->texture_table[ i ].name[ 0 ] == '\0' ) {
				LogWarn( "Invalid texture name in table, skipping (%d)!\n", i );
				continue;
			}

			std::string str = path;
			size_t pos = str.find_last_of( '/' );
			std::string texture_path = str.erase( pos ) + "/";
			if ( !atlas.AddImage( texture_path + fac->texture_table[ i ].name + ".png", true ) ) {
				LogWarn( "Failed to add texture \"%s\" to atlas!\n", fac->texture_table[ i ].name );
			}
		}
		atlas.Finalize();
	} else {
		LogWarn( "No texture table for \"%s\"!\n", path );
	}

	PLMesh *mesh = plCreateMesh( PL_MESH_TRIANGLES, PL_DRAW_DYNAMIC, fac->num_triangles, fac->num_triangles * 3 );
	if ( mesh == nullptr ) {
		Vtx_DestroyHandle( vtx );
		Fac_DestroyHandle( fac );
		LogWarn( "Failed to create mesh (%s)!\n", plGetError() );
		return nullptr;
	}

	for ( unsigned int j = 0; j < vtx->num_vertices; ++j ) {
		vtx->vertices[ j ].position *= .5f;

		// Flip
		vtx->vertices[ j ].position.y *= -1;
		vtx->vertices[ j ].position.x *= -1;
	}

	// automatically returns default if failed
	mesh->texture = atlas.GetTexture();

	unsigned int cur_index = 0;
	for ( unsigned int j = 0, next_vtx_i = 0; j < fac->num_triangles; ++j ) {
		for ( unsigned int tri_vtx_i = 0; tri_vtx_i < 3; ++tri_vtx_i, ++next_vtx_i ) {
			unsigned int tri_vtx = fac->triangles[ j ].vertex_indices[ tri_vtx_i ];

			plSetMeshVertexColour( mesh, next_vtx_i, PL_COLOUR_WHITE );
			plSetMeshVertexPosition( mesh, next_vtx_i, vtx->vertices[ tri_vtx ].position );

#if 0 // todo: only necessary for pigs?
			mesh->vertices[next_vtx_i].bone_index = vtx->vertices[tri_vtx].bone_index;
			mesh->vertices[next_vtx_i].bone_weight = 1.f;
#endif
		}<commit_msg>remove flip for model (which fixes a lot of crap)<commit_after>/* OpenHoW
 * Copyright (C) 2017-2020 <NAME> <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <PL/platform_filesystem.h>
#include <PL/platform_mesh.h>
#include <PL/platform_model.h>

#include "engine.h"
#include "model.h"
#include "loaders/loaders.h"

#include "graphics/display.h"
#include "graphics/shaders.h"
#include "graphics/texture_atlas.h"
#include "graphics/mesh.h"

using namespace openhow;

const char *Model_GetAnimationDescription( unsigned int i ) {
	static const char *animationNames[] = {
		"Run cycle (normal)",
		"Run cycle (wounded)",
		"Run cycle (more wounded)",
		"Walk cycle (backwards)",
		"Turning on Spot",
		"Swimming",
		"Swimming like Rick",
		"Getting into Vehicles",
		"Jumping - Start",
		"Jumping - Middle",
		"Jumping - End",
		"Scramble",
		"Getting out Handgun",
		"Getting out Rifle",
		"Getting out Machine gun",
		"Getting out Heavy weapon",
		"Getting out Punch",
		"Getting out Grenade",
		"Getting out Sword / Knife",
		"Using Grenade",
		"Using Punch",
		"Sword / Knife",
		"Bayonet",
		"Aiming Handgun",
		"Aiming Rifle",
		"Aiming Machine gun",
		"Aiming Heavy weapon",
		"Standing around cycle 1",
		"Standing around cycle 2",
		"Very Wounded",
		"Lord Flash-Heart Pose",
		"Looking around",
		"Looking gormless",
		"Cowering",
		"Brushoff 1",
		"Brushoff 2",
		"Brushoff 3",
		"Sneeze",
		"Flying through air/falling",
		"Bouncing on B-Hind",
		"Getting to feet",
		"Celebration #1",
		"Celebration #2",
		"Celebration #3",
		"Salute",
		"Look back",
		"Thinking",
		"Dying #1",
		"Dying #2",
		"Dying #3",
		"Drowning",
		"Idle Cold",
		"Idle Hot",
		"Lay Mine",
		"Heal",
		"Pick pocket",
		"Air strike",
		"<NAME>",
		"Parachuting",
	};

	if ( i >= plArrayElements( animationNames ) ) {
		return nullptr;
	}

	return animationNames[ i ];
}

PLModel *Model_LoadVtxFile( const char *path ) {
	VtxHandle *vtx = Vtx_LoadFile( path );
	if ( vtx == nullptr ) {
		LogWarn( "Failed to load Vtx, \"%s\"!\n", path );
		return nullptr;
	}

	/* now we load in all the faces */
	char fac_path[PL_SYSTEM_MAX_PATH];
	strncpy( fac_path, path, strlen( path ) - 3 );
	fac_path[ strlen( path ) - 3 ] = '\0';
	strcat( fac_path, "fac" );
	FacHandle *fac = Fac_LoadFile( fac_path );
	if ( fac == nullptr ) {
		Vtx_DestroyHandle( vtx );
		LogWarn( "Failed to load Fac, \"%s\"!\n", path );
		return nullptr;
	}

	const char *filename = plGetFileName( path );
	// skydome is a special case, since we don't care about textures...
	if ( pl_strcasecmp( filename, "skydome.vtx" ) == 0 || pl_strcasecmp( filename, "skydomeu.vtx" ) == 0 ) {
		PLMesh *mesh = plCreateMesh( PL_MESH_TRIANGLES, PL_DRAW_STATIC, fac->num_triangles, vtx->num_vertices );
		if ( mesh == nullptr ) {
			Vtx_DestroyHandle( vtx );
			Fac_DestroyHandle( fac );
			LogWarn( "Failed to create mesh (%s)!\n", plGetError() );
			return nullptr;
		}

		for ( unsigned int j = 0; j < vtx->num_vertices; ++j ) {
			plSetMeshVertexPosition( mesh, j, vtx->vertices[ j ].position * -1 * .5f );
		}

		unsigned int cur_index = 0;
		for ( unsigned int j = 0; j < fac->num_triangles; ++j ) {
			plSetMeshTrianglePosition( mesh, &cur_index,
									   fac->triangles[ j ].vertex_indices[ 0 ],
									   fac->triangles[ j ].vertex_indices[ 1 ],
									   fac->triangles[ j ].vertex_indices[ 2 ]
			);
		}

		Vtx_DestroyHandle( vtx );
		Fac_DestroyHandle( fac );

		mesh->texture = Engine::Resource()->GetFallbackTexture();

		PLModel *model = plCreateBasicStaticModel( mesh );
		if ( model == nullptr ) {
			LogWarn( "Failed to create model (%s)!\n", plGetError() );
			return nullptr;
		}

		return model;
	}

	TextureAtlas atlas( 128, 8 );
	if ( fac->texture_table_size > 0 ) {
		for ( unsigned int i = 0; i < fac->texture_table_size; ++i ) {
			if ( fac->texture_table[ i ].name[ 0 ] == '\0' ) {
				LogWarn( "Invalid texture name in table, skipping (%d)!\n", i );
				continue;
			}

			std::string str = path;
			size_t pos = str.find_last_of( '/' );
			std::string texture_path = str.erase( pos ) + "/";
			if ( !atlas.AddImage( texture_path + fac->texture_table[ i ].name + ".png", true ) ) {
				LogWarn( "Failed to add texture \"%s\" to atlas!\n", fac->texture_table[ i ].name );
			}
		}
		atlas.Finalize();
	} else {
		LogWarn( "No texture table for \"%s\"!\n", path );
	}

	PLMesh *mesh = plCreateMesh( PL_MESH_TRIANGLES, PL_DRAW_DYNAMIC, fac->num_triangles, fac->num_triangles * 3 );
	if ( mesh == nullptr ) {
		Vtx_DestroyHandle( vtx );
		Fac_DestroyHandle( fac );
		LogWarn( "Failed to create mesh (%s)!\n", plGetError() );
		return nullptr;
	}

	for ( unsigned int j = 0; j < vtx->num_vertices; ++j ) {
		vtx->vertices[ j ].position *= .5f;
	}

	// automatically returns default if failed
	mesh->texture = atlas.GetTexture();

	unsigned int cur_index = 0;
	for ( unsigned int j = 0, next_vtx_i = 0; j < fac->num_triangles; ++j ) {
		for ( unsigned int tri_vtx_i = 0; tri_vtx_i < 3; ++tri_vtx_i, ++next_vtx_i ) {
			unsigned int tri_vtx = fac->triangles[ j ].vertex_indices[ tri_vtx_i ];

			plSetMeshVertexColour( mesh, next_vtx_i, PL_COLOUR_WHITE );
			plSetMeshVertexPosition( mesh, next_vtx_i, vtx->vertices[ tri_vtx ].position );

#if 0 // todo: only necessary for pigs?
			mesh->vertices[next_vtx_i].bone_index = vtx->vertices[tri_vtx].bone_index;
			mesh->vertices[next_vtx_i].bone_weight = 1.f;
#endif
		}
{'fraction_non_alphanumeric': 0.14827729348277294, 'fraction_numerical': 0.008634288086342881, 'mean_word_length': 3.537099811676083, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1417804', 'n_tokens_mistral': 4858, 'n_tokens_neox': 4342, 'n_words': 1266}