Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fe12962b8 | |||
| e359bcbe2b | |||
| 13f4b5e626 | |||
| 2ae1ccd761 | |||
| d7013f302b | |||
| b3fe92c996 | |||
| 822663f95e | |||
| 3f9bb33177 | |||
| fa173f1e87 | |||
| f08da7b358 | |||
| 945b9c462b | |||
| c9535412a7 | |||
| 2c41930cb2 | |||
| 2a4e2a2109 | |||
| 286b9e43a7 | |||
| f62eaff37b | |||
| 48fa642cef | |||
| cad720a399 | |||
| cf3f5b3443 | |||
| 48a0eec86b | |||
| 6a9f3c6683 | |||
| 325fea1a8b | |||
| ce00f58b89 | |||
| 5d4d2b0f06 | |||
| ca25a6de03 |
+2
-2
@@ -60,12 +60,12 @@
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Send to PS2",
|
||||
"command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
|
||||
"command": "docker exec -t tyra-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || $true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Open PS2 output logger",
|
||||
"command": "docker stop ps2-logs || true && docker run -t --rm --name=ps2-logs -p ${input:local2Ip}:18194:18194/udp h4570/tyra sh -c 'ps2client -h ${input:ps2Ip} listen'",
|
||||
"command": "docker stop ps2-logs || $true && docker run -t --rm --name=ps2-logs -p ${input:local2Ip}:18194:18194/udp h4570/tyra sh -c 'ps2client -h ${input:ps2Ip} listen'",
|
||||
"runOptions": {
|
||||
"instanceLimit": 1
|
||||
},
|
||||
|
||||
Vendored
+2
-1
@@ -3,6 +3,7 @@
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"ryzngard.vscode-header-source",
|
||||
"maziac.asm-code-lens",
|
||||
"dmnsgn.vscode-wavefront"
|
||||
"dmnsgn.vscode-wavefront",
|
||||
"spmeesseman.vscode-taskexplorer"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
[](https://www.codacy.com/gh/h4570/tyra/dashboard?utm_source=github.com&utm_medium=referral&utm_content=h4570/tyra&utm_campaign=Badge_Grade)
|
||||
[![Contributors][contributors-shield]][contributors-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
[](https://discord.gg/NhhTmg3Gm5)
|
||||
@@ -34,12 +35,11 @@
|
||||
* [Features](#features)
|
||||
* [Branches](#branches)
|
||||
* [Contributing](#contributing)
|
||||
* [Games](#games)
|
||||
* [License](#license)
|
||||
* [Built With](#built-with)
|
||||
* [Acronyms](#acronyms)
|
||||
* [Thanks](#thanks)
|
||||
|
||||
<br />
|
||||
* [Credits](#credits)
|
||||
|
||||
## About the Project
|
||||
<p align="center">
|
||||
@@ -51,24 +51,25 @@
|
||||
### Description
|
||||
Tyra is a project that allows you to easily create games for the PlayStation 2 console.
|
||||
When I tried to make a game for PS2 a few years ago, I realized how many things had to be done to tame this exotic console architecture.
|
||||
Decision was simple - I need to create an engine which will handle 3D file loading, 2D/3D rendering, animation, audio, handling between PS2 CPUs, synchronization and it should be simple as possible - so people with no experience can create a simple game in a few hours.
|
||||
Decision was simple - I need to create an engine which will handle 3D file loading, 2D/3D rendering, animation, audio, handling between PS2 CPUs, synchronization.. It should be simple as possible - so people with no experience can create a simple game in a few hours.
|
||||
**And that's what Tyra is all about.**
|
||||
|
||||
### Tutorials
|
||||
* Setup environment - [Text tutorial](https://github.com/h4570/tyra/tree/master/docs/install) or [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH)
|
||||
* Cook game assets - [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH)
|
||||
* Create game from template - [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH)
|
||||
* 01 - Setup environment - [Text tutorial](https://github.com/h4570/tyra/tree/master/docs/install) or [Video](https://www.youtube.com/watch?v=9IXOU1SPdzc)
|
||||
* 02 - Cooking game assets - [Video](https://www.youtube.com/watch?v=LjO71ovPFJs)
|
||||
* 03 - Create a game repository - [Video](https://www.youtube.com/watch?v=DKfIKar3GUM)
|
||||
* 04 - Run game from USB in PS2 - [Video](https://www.youtube.com/watch?v=ZX8fTQqiNho)
|
||||
---
|
||||
* 01 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/01-hello), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Hello world
|
||||
* 02 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/02-sprite), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 2D rendering
|
||||
* 03 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/03-minecraft), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 3D minecraft blocks
|
||||
* 04 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/04-de_dust2), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - `de_dust2.obj` rendering
|
||||
* 05 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/05-animation), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - 3D animation
|
||||
* 06 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/06-audio), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Background music and sound effects
|
||||
* 07 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/07-lighting), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Static lightmap and dynamic directional lights
|
||||
* 08 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/08-skybox-debug), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Skybox and debug rendering
|
||||
* 09 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/09-manual-mode), [Video (soon)](https://www.youtube.com/playlist?list=PLdQVLBcXRRWvtMi-OqccDWLTEFEisD5RH) - Manual rendering (a'la OpenGL)
|
||||
|
||||
* 01 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/01-hello) - Hello world
|
||||
* 02 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/02-sprite) - 2D rendering
|
||||
* 03 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/03-minecraft) - 3D minecraft blocks
|
||||
* 04 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/04-de_dust2) - `de_dust2.obj` rendering
|
||||
* 05 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/05-animation) - 3D animation
|
||||
* 06 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/06-audio) - Background music and sound effects
|
||||
* 07 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/07-lighting) - Static lightmap and dynamic directional lights
|
||||
* 08 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/08-skybox-debug) - Skybox and debug rendering
|
||||
* 09 - [Code](https://github.com/h4570/tyra/tree/master/tutorials/09-manual-mode) - Manual rendering (a'la OpenGL)
|
||||
* Demo game - [Code](https://github.com/h4570/tyra/tree/master/demo)
|
||||
---
|
||||
|
||||
### Features
|
||||
@@ -85,10 +86,12 @@ Decision was simple - I need to create an engine which will handle 3D file loadi
|
||||
* Precise - culling only visible parts of mesh
|
||||
* Clipping:
|
||||
* Standard "fake", but fast PS2 clipping done in `VU1`
|
||||
* Software triangle done in `EE Core`
|
||||
* Software clipping done in `EE Core`
|
||||
* Optimized math functions via `VU0` coprocessor
|
||||
* Background music and sound effects support
|
||||
* Pad support
|
||||
* USB support
|
||||
* Memory card support
|
||||
* `.wav` Audio file support
|
||||
* `.obj` 3D file support
|
||||
* `.md2` 3D file support
|
||||
@@ -100,8 +103,6 @@ Decision was simple - I need to create an engine which will handle 3D file loadi
|
||||
|
||||
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
|
||||
|
||||
<br />
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||
@@ -112,22 +113,23 @@ Contributions are what make the open source community such an amazing place to b
|
||||
4. Push to the Branch (`git push origin feature/amazing-feature`)
|
||||
5. Open a Pull Request
|
||||
|
||||
<br />
|
||||
## Games
|
||||
|
||||
List of games developed with Tyra.
|
||||
If you created one, please contact me - I will add it to the list :)
|
||||
|
||||
* [Tyracraft](https://github.com/Wellinator/tyracraft)
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the Apache License 2.0 License. See `LICENSE` for more information.
|
||||
|
||||
<br />
|
||||
|
||||
## Built With
|
||||
|
||||
* [PS2DEV](https://github.com/ps2dev/ps2dev)
|
||||
* [VCLPP](https://github.com/glampert/vclpp)
|
||||
* Sony VCL
|
||||
|
||||
<br />
|
||||
|
||||
## Acronyms
|
||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
||||
* EE Core - main PS2 CPU (c++ done here)
|
||||
@@ -136,14 +138,13 @@ Distributed under the Apache License 2.0 License. See `LICENSE` for more informa
|
||||
* VU1 - programmable (ASM) vector processor, which is similar to vertex shader. Accessed via DMA.
|
||||
* IOP - I/O processor which enables access to peripheral devices, such the game controller
|
||||
|
||||
<br />
|
||||
|
||||
## Credits
|
||||
|
||||
Without these guys, Tyra would not happen:
|
||||
* Dr Henry Fortuna - for code sources, PS2 academy tutorials
|
||||
* Rick Gaiser, fjtrujy - for maintaining PS2DEV
|
||||
* Wellington Carvalho - for testing, contributing to Tyra and sharing cool ideas!
|
||||
* Leonardo Ono - for software renderer example (with clipping!)
|
||||
* Lukasz D.K. - for huge archive of PS2 stuff
|
||||
* Guilherme Lampert - for code sources
|
||||
* Jesper Svennevid, Daniel Collin - for openvcl's code samples
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
------------ Tyra's v2.0 roadmap to publish on GitHub ------------
|
||||
- [General] Readme Credits: clipping, obj loader
|
||||
- [Video] How to setup environment
|
||||
- [Video] How to work with Tyra
|
||||
- [Video] How to create own game
|
||||
- [Video] How to cook assets (audio, textures, obj)
|
||||
- [Video] Tutorial videos
|
||||
- [Video] How to run game from USB
|
||||
|
||||
------------ Github issues for Tyra v2 ------------
|
||||
- [Demo] BBox constructors
|
||||
- [General] Add cpp lint checker in GitHub / static code analysis
|
||||
- [General] Smart pointers and std::array instead of raw pointers
|
||||
- [General] Control generated id to avoid duplication. Maybe Just increment from 0? Add interface IIdentificable?
|
||||
- [renderer] fog
|
||||
- [General] CI in Github via docker image
|
||||
- [MD2] Refactor
|
||||
- [2D] Add zbuffer support (z-index)
|
||||
- [3DUtility] Add zbuffer support (z-index), cupMesh->translation.translateZ(10.0F) - wylaczyc zeby widziec problem
|
||||
- [2D] Fixed font support
|
||||
- [File] Async file loading
|
||||
- [tyrdat] Custom 3D data file with precalculated bboxes with support of async loading
|
||||
- [Renderer] Interlacing, and then 640x448 resolution
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
namespace Demo {
|
||||
|
||||
const bool IS_REAL_PS2 = false;
|
||||
const bool IS_REAL_PS2_VIA_USB = false;
|
||||
|
||||
} // namespace Demo
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
int main() {
|
||||
Tyra::EngineOptions options;
|
||||
|
||||
if (Demo::IS_REAL_PS2) {
|
||||
if (Demo::IS_REAL_PS2_VIA_USB) {
|
||||
options.writeLogsToFile = true;
|
||||
options.loadUsbDriver = true;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"),
|
||||
objOptions);
|
||||
data->normalsEnabled = false;
|
||||
data->loadNormals = false;
|
||||
motherMesh = new DynamicMesh(data.get());
|
||||
|
||||
bodyTexture = textureRepo->add(
|
||||
@@ -45,7 +45,7 @@ EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
|
||||
auto* death = engine->audio.adpcm.load(
|
||||
FileUtils::fromCwd("game/models/zombie/death.adpcm"));
|
||||
|
||||
const int enemyCount = IS_REAL_PS2 ? 8 : 12;
|
||||
const int enemyCount = IS_REAL_PS2_VIA_USB ? 8 : 12;
|
||||
for (int i = 0; i < enemyCount; i++) {
|
||||
EnemyInfo info;
|
||||
info.adpcmChannel = 9 + i;
|
||||
|
||||
@@ -45,7 +45,7 @@ void GameState::onStart() {
|
||||
|
||||
engine->audio.song.setVolume(85);
|
||||
|
||||
if (IS_REAL_PS2) engine->renderer.setFrameLimit(false);
|
||||
if (IS_REAL_PS2_VIA_USB) engine->renderer.setFrameLimit(false);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ Weapon::Weapon(Engine* engine) {
|
||||
auto* repo = &engine->renderer.core.texture.repository;
|
||||
auto data =
|
||||
loader.load(FileUtils::fromCwd("game/models/ak47/ak47.obj"), objOptions);
|
||||
data->normalsEnabled = false;
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
mesh->translation.translateX(2.85F);
|
||||
|
||||
@@ -25,7 +25,7 @@ Skybox::Skybox(TextureRepository* repo) {
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/skybox/skybox.obj"),
|
||||
objOptions);
|
||||
data->normalsEnabled = false;
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/skybox/"), "png");
|
||||
|
||||
@@ -29,7 +29,7 @@ Terrain::Terrain(TextureRepository* repo)
|
||||
|
||||
auto data = loader.load(FileUtils::fromCwd("game/models/terrain/terrain.obj"),
|
||||
objOptions);
|
||||
data->normalsEnabled = false;
|
||||
data->loadNormals = false;
|
||||
mesh = new StaticMesh(data.get());
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/terrain/"), "png");
|
||||
|
||||
@@ -32,6 +32,11 @@ class FileUtils {
|
||||
static std::string fromCwd(const std::string& relativePath);
|
||||
static std::string fromCwd(const char* relativePath);
|
||||
|
||||
static std::string getFilenameFromPath(const std::string& path);
|
||||
static std::string getPathFromFilename(const std::string& path);
|
||||
static std::string getFilenameWithoutExtension(const std::string& filename);
|
||||
static std::string getExtensionOfFilename(const std::string& filename);
|
||||
|
||||
const char* getElfName() const { return elfName; };
|
||||
const char* getElfPath() const { return elfPath; };
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class MeshBuilderData {
|
||||
|
||||
std::vector<MeshBuilderMaterialData*> materials;
|
||||
|
||||
bool textureCoordsEnabled, normalsEnabled, lightMapEnabled;
|
||||
bool loadNormals, loadLightmap;
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include "./mesh_builder_material_frame_data.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
|
||||
@@ -25,6 +26,7 @@ class MeshBuilderMaterialData {
|
||||
|
||||
std::vector<MeshBuilderMaterialFrameData*> frames;
|
||||
std::string name;
|
||||
std::optional<std::string> texturePath;
|
||||
Color ambient;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../loader.hpp"
|
||||
#include "../builder/mesh_builder_data.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@@ -23,7 +22,7 @@ struct MD2LoaderOptions {
|
||||
};
|
||||
|
||||
/** Class responsible for loading & parsing Quake's II ".md2" 3D files */
|
||||
class MD2Loader : public Loader {
|
||||
class MD2Loader {
|
||||
public:
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../loader.hpp"
|
||||
#include "../builder/mesh_builder_data.hpp"
|
||||
#include <string>
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "loaders/3d/obj_loader/tiny_obj_loader.hpp"
|
||||
#include <memory.h>
|
||||
#include <optional>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -36,7 +36,7 @@ struct MaterialVertexCount {
|
||||
};
|
||||
|
||||
/** Class responsible for loading & parsing obj files */
|
||||
class ObjLoader : public Loader {
|
||||
class ObjLoader {
|
||||
public:
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath);
|
||||
static std::unique_ptr<MeshBuilderData> load(const char* fullpath,
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
class Loader {
|
||||
protected:
|
||||
static std::string getFilenameFromPath(const std::string& path);
|
||||
static std::string getPathFromFilename(const std::string& path);
|
||||
static std::string getFilenameWithoutExtension(const std::string& filename);
|
||||
static std::string getExtensionOfFilename(const std::string& filename);
|
||||
};
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -10,13 +10,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "loaders/loader.hpp"
|
||||
#include "loaders/texture/builder/texture_builder_data.hpp"
|
||||
#include "renderer/core/texture/models/texture_bpp.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Tyra {
|
||||
class TextureLoader : public Loader {
|
||||
class TextureLoader {
|
||||
public:
|
||||
/**
|
||||
* @brief Loads texture data from file.
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "debug/debug.hpp"
|
||||
#include "./mesh_material_frame.hpp"
|
||||
#include "loaders/3d/builder/mesh_builder_data.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -23,11 +24,9 @@ class MeshMaterial {
|
||||
~MeshMaterial();
|
||||
|
||||
bool isMother, lightmapFlag;
|
||||
|
||||
u32 id;
|
||||
|
||||
std::string name;
|
||||
|
||||
std::optional<std::string> textureName;
|
||||
Color ambient;
|
||||
|
||||
std::vector<MeshMaterialFrame*> frames;
|
||||
|
||||
@@ -44,8 +44,7 @@ class DynPipRenderer {
|
||||
void uploadPrograms();
|
||||
void setDoubleBuffer();
|
||||
|
||||
void addBufferDataToPacket(DynPipVU1Program* program, DynPipBag** bags,
|
||||
const u32& count);
|
||||
void addBufferDataToPacket(DynPipBag** bags, const u32& count);
|
||||
void sendPacket();
|
||||
|
||||
prim_t* prim;
|
||||
|
||||
@@ -59,7 +59,7 @@ class DynamicPipeline : public Renderer3DPipeline {
|
||||
|
||||
void setBuffer(DynPipBag* buffers, DynPipBag* buffer, u16* bufferIndex);
|
||||
|
||||
void sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex);
|
||||
void sendRestOfBuffers(DynPipBag* buffers, const u16& bufferIndex);
|
||||
|
||||
void addVertices(const MeshMaterialFrame* materialFrameFrom,
|
||||
const MeshMaterialFrame* materialFrameTo, DynPipBag* bag,
|
||||
|
||||
@@ -22,7 +22,7 @@ class RendererSettings {
|
||||
height(448.0F),
|
||||
interlacedHeightF(height / 2),
|
||||
near(0.1F),
|
||||
far(8192.0F),
|
||||
far(51200.0F),
|
||||
projectionScale(4096.0F),
|
||||
aspectRatio(width / height),
|
||||
interlacedHeightUI(static_cast<unsigned int>(interlacedHeightF)) {}
|
||||
|
||||
@@ -64,4 +64,32 @@ std::string FileUtils::fromCwd(const char* file) {
|
||||
auto cwd = getCwd();
|
||||
return cwd + file;
|
||||
}
|
||||
|
||||
std::string FileUtils::getFilenameFromPath(const std::string& path) {
|
||||
std::string filename = path.substr(path.find_last_of("/\\") + 1);
|
||||
if (filename.size() == path.size()) {
|
||||
filename = path.substr(path.find_last_of(":\\") + 1);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string FileUtils::getPathFromFilename(const std::string& path) {
|
||||
std::string basepath = path.substr(0, path.find_last_of("/\\"));
|
||||
if (basepath.size() == path.size()) {
|
||||
basepath = path.substr(0, path.find_last_of(":\\"));
|
||||
}
|
||||
return basepath;
|
||||
}
|
||||
|
||||
std::string FileUtils::getFilenameWithoutExtension(
|
||||
const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(0, lastindex);
|
||||
}
|
||||
|
||||
std::string FileUtils::getExtensionOfFilename(const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(lastindex + 1);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
namespace Tyra {
|
||||
|
||||
MeshBuilderData::MeshBuilderData() {
|
||||
textureCoordsEnabled = false;
|
||||
normalsEnabled = false;
|
||||
lightMapEnabled = false;
|
||||
loadNormals = false;
|
||||
loadLightmap = false;
|
||||
}
|
||||
|
||||
MeshBuilderData::~MeshBuilderData() {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <string>
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/md2_loader/anorms.hpp"
|
||||
#include "loaders/loader.hpp"
|
||||
#include "file/file_utils.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -88,7 +88,7 @@ std::unique_ptr<MeshBuilderData> MD2Loader::load(const char* fullpath,
|
||||
std::string path = fullpath;
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto filename = getFilenameFromPath(path);
|
||||
auto filename = FileUtils::getFilenameFromPath(path);
|
||||
|
||||
FILE* file = fopen(fullpath, "rb");
|
||||
TYRA_ASSERT(file != nullptr, "Failed to load: ", filename);
|
||||
@@ -122,12 +122,13 @@ std::unique_ptr<MeshBuilderData> MD2Loader::load(const char* fullpath,
|
||||
auto result = std::make_unique<MeshBuilderData>();
|
||||
|
||||
auto* material = new MeshBuilderMaterialData();
|
||||
material->name = getFilenameWithoutExtension(filename);
|
||||
material->name = FileUtils::getFilenameWithoutExtension(filename);
|
||||
material->texturePath = material->name;
|
||||
material->texturePath.value().append(".png");
|
||||
|
||||
result->materials.push_back(material);
|
||||
result->normalsEnabled = true;
|
||||
result->textureCoordsEnabled = true;
|
||||
result->lightMapEnabled = false;
|
||||
result->loadNormals = true;
|
||||
result->loadLightmap = false;
|
||||
|
||||
Vec4** tempVertices = new Vec4*[framesCount];
|
||||
Vec4** tempNormals = new Vec4*[framesCount];
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "math/vec2.hpp"
|
||||
#include "math/vec4.hpp"
|
||||
#include "renderer/models/color.hpp"
|
||||
#include "debug/debug.hpp"
|
||||
#include "loaders/3d/obj_loader/obj_loader.hpp"
|
||||
#include "file/file_utils.hpp"
|
||||
|
||||
#define TINYOBJLOADER_USE_MAPBOX_EARCUT
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
@@ -40,12 +40,12 @@ std::unique_ptr<MeshBuilderData> ObjLoader::load(
|
||||
std::unique_ptr<MeshBuilderData> ObjLoader::load(
|
||||
const char* fullpath, const ObjLoaderOptions& options) {
|
||||
std::string path = fullpath;
|
||||
std::string basePath = getPathFromFilename(path);
|
||||
std::string basePath = FileUtils::getPathFromFilename(path);
|
||||
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto rawFilename = getFilenameWithoutExtension(path);
|
||||
auto extension = getExtensionOfFilename(path);
|
||||
auto rawFilename = FileUtils::getFilenameWithoutExtension(path);
|
||||
auto extension = FileUtils::getExtensionOfFilename(path);
|
||||
auto result = std::make_unique<MeshBuilderData>();
|
||||
|
||||
tinyobj::ObjReaderConfig readerConfig;
|
||||
@@ -131,9 +131,7 @@ void ObjLoader::addOutputMaterialsAndFrames(
|
||||
const std::vector<tinyobj::shape_t>& shapes,
|
||||
const std::vector<tinyobj::material_t>& materials, const u16& framesCount,
|
||||
std::vector<MaterialVertexCount>& materialVertexCounts) {
|
||||
if (attrib.texcoords.size()) output->textureCoordsEnabled = true;
|
||||
|
||||
if (attrib.normals.size()) output->normalsEnabled = true;
|
||||
if (attrib.normals.size()) output->loadNormals = true;
|
||||
|
||||
TYRA_ASSERT(materials.size() > 0,
|
||||
"No material data found! Please add .mtl "
|
||||
@@ -145,6 +143,10 @@ void ObjLoader::addOutputMaterialsAndFrames(
|
||||
|
||||
material->name = materials[i].name;
|
||||
|
||||
if (!materials[i].diffuse_texname.empty()) {
|
||||
material->texturePath = materials[i].diffuse_texname;
|
||||
}
|
||||
|
||||
material->ambient.set(materials[i].diffuse[0] * 128.0F,
|
||||
materials[i].diffuse[1] * 128.0F,
|
||||
materials[i].diffuse[2] * 128.0F, 128.0F);
|
||||
@@ -157,10 +159,11 @@ void ObjLoader::addOutputMaterialsAndFrames(
|
||||
frame->count = counter.count;
|
||||
frame->vertices = new Vec4[counter.count];
|
||||
|
||||
if (output->textureCoordsEnabled)
|
||||
if (material->texturePath.has_value()) {
|
||||
frame->textureCoords = new Vec4[counter.count];
|
||||
}
|
||||
|
||||
if (output->normalsEnabled) frame->normals = new Vec4[counter.count];
|
||||
if (output->loadNormals) frame->normals = new Vec4[counter.count];
|
||||
|
||||
material->frames.push_back(frame);
|
||||
}
|
||||
@@ -186,6 +189,8 @@ void ObjLoader::importFrame(MeshBuilderData* output,
|
||||
materialInsertControls.push_back(control);
|
||||
}
|
||||
|
||||
std::vector<u32> materialIdsWithTextureWarning;
|
||||
|
||||
// Loop over shapes
|
||||
for (size_t s = 0; s < shapes.size(); s++) {
|
||||
const auto& mesh = shapes[s].mesh;
|
||||
@@ -197,7 +202,8 @@ void ObjLoader::importFrame(MeshBuilderData* output,
|
||||
auto& materialInsertControl = materialInsertControls[materialId];
|
||||
size_t vertCountPerFace = size_t(mesh.num_face_vertices[f]);
|
||||
|
||||
auto* outFrame = output->materials[materialId]->frames[frameIndex];
|
||||
auto* outMaterial = output->materials[materialId];
|
||||
auto* outFrame = outMaterial->frames[frameIndex];
|
||||
|
||||
TYRA_ASSERT(count == 1 || vertCountPerFace == 3,
|
||||
"Please triangulate obj files if you are animating!",
|
||||
@@ -232,6 +238,7 @@ void ObjLoader::importFrame(MeshBuilderData* output,
|
||||
// Check if `texcoord_index` is zero or positive. negative =
|
||||
// notexcoord data
|
||||
if (idx.texcoord_index >= 0) {
|
||||
if (outMaterial->texturePath.has_value()) {
|
||||
tinyobj::real_t tx =
|
||||
attrib.texcoords[2 * size_t(idx.texcoord_index) + 0];
|
||||
tinyobj::real_t ty =
|
||||
@@ -240,6 +247,23 @@ void ObjLoader::importFrame(MeshBuilderData* output,
|
||||
auto finalY = invertY ? 1.0F - ty : ty;
|
||||
outFrame->textureCoords[materialInsertControl.inserted].set(
|
||||
tx, finalY, 1.0F, 0.0F);
|
||||
} else {
|
||||
auto warningWasNotPrinted =
|
||||
std::find(materialIdsWithTextureWarning.begin(),
|
||||
materialIdsWithTextureWarning.end(),
|
||||
materialId) == materialIdsWithTextureWarning.end();
|
||||
|
||||
if (frameIndex == 0 && warningWasNotPrinted) {
|
||||
materialIdsWithTextureWarning.push_back(materialId);
|
||||
|
||||
TYRA_WARN(
|
||||
"Material \"", outMaterial->name,
|
||||
"\" has texture coordinates, but texture path was not found "
|
||||
"in .mtl file! ",
|
||||
"Please consider adding texture path to map_Kd field in .mtl "
|
||||
"file!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
materialInsertControl.inserted++;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "loaders/loader.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
std::string Loader::getFilenameFromPath(const std::string& path) {
|
||||
std::string filename = path.substr(path.find_last_of("/\\") + 1);
|
||||
if (filename.size() == path.size()) {
|
||||
filename = path.substr(path.find_last_of(":\\") + 1);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
std::string Loader::getPathFromFilename(const std::string& path) {
|
||||
std::string basepath = path.substr(0, path.find_last_of("/\\"));
|
||||
if (basepath.size() == path.size()) {
|
||||
basepath = path.substr(0, path.find_last_of(":\\"));
|
||||
}
|
||||
return basepath;
|
||||
}
|
||||
|
||||
std::string Loader::getFilenameWithoutExtension(const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(0, lastindex);
|
||||
}
|
||||
|
||||
std::string Loader::getExtensionOfFilename(const std::string& filename) {
|
||||
auto lastindex = filename.find_last_of(".");
|
||||
return filename.substr(lastindex + 1);
|
||||
}
|
||||
|
||||
} // namespace Tyra
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <draw_buffers.h>
|
||||
#include "loaders/texture/png_loader.hpp"
|
||||
#include "file/file_utils.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -32,7 +33,7 @@ TextureBuilderData* PngLoader::load(const char* fullPath) {
|
||||
std::string path = fullPath;
|
||||
TYRA_ASSERT(!path.empty(), "Provided path is empty!");
|
||||
|
||||
auto filename = getFilenameFromPath(path);
|
||||
auto filename = FileUtils::getFilenameFromPath(path);
|
||||
|
||||
FILE* file = fopen(fullPath, "rb");
|
||||
TYRA_ASSERT(file != nullptr, "Failed to load ", fullPath);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include "renderer/3d/mesh/mesh_material.hpp"
|
||||
#include "file/file_utils.hpp"
|
||||
|
||||
namespace Tyra {
|
||||
|
||||
@@ -29,7 +30,7 @@ MeshMaterial::MeshMaterial(const MeshBuilderData& data,
|
||||
|
||||
id = rand() % 1000000;
|
||||
|
||||
if (data.lightMapEnabled) {
|
||||
if (data.loadLightmap) {
|
||||
lightmapFlag = true;
|
||||
TYRA_ASSERT(material->frames[0]->colors != nullptr,
|
||||
"Colors faces are required");
|
||||
@@ -38,8 +39,15 @@ MeshMaterial::MeshMaterial(const MeshBuilderData& data,
|
||||
}
|
||||
|
||||
ambient.set(material->ambient);
|
||||
|
||||
name = material->name;
|
||||
|
||||
if (material->texturePath.has_value()) {
|
||||
auto textureFilename =
|
||||
FileUtils::getFilenameFromPath(material->texturePath.value());
|
||||
|
||||
textureName = FileUtils::getFilenameWithoutExtension(textureFilename);
|
||||
}
|
||||
|
||||
TYRA_ASSERT(name.length() > 0, "MeshMaterial name cannot be empty");
|
||||
|
||||
u32 lastVertexCount = 0;
|
||||
@@ -71,7 +79,7 @@ MeshMaterial::MeshMaterial(const MeshMaterial& mesh) {
|
||||
|
||||
lightmapFlag = mesh.lightmapFlag;
|
||||
name = mesh.name;
|
||||
|
||||
textureName = mesh.textureName;
|
||||
ambient.set(128.0F, 128.0F, 128.0F, 128.0F);
|
||||
|
||||
for (u32 i = 0; i < mesh.frames.size(); i++) {
|
||||
@@ -112,9 +120,14 @@ std::string MeshMaterial::getPrint(const char* name) const {
|
||||
res << std::endl;
|
||||
res << std::fixed << std::setprecision(2);
|
||||
res << "Id: " << id << ", " << std::endl;
|
||||
res << "Name: " << name << ", " << std::endl;
|
||||
res << "Name: " << this->name << ", " << std::endl;
|
||||
|
||||
if (textureName.has_value()) {
|
||||
res << "Texture path: " << textureName.value() << ", " << std::endl;
|
||||
}
|
||||
|
||||
res << "Frames count: " << frames.size() << ", " << std::endl;
|
||||
res << "Single color?: " << static_cast<u32>(lightmapFlag) << std::endl;
|
||||
res << "Lightmap?: " << static_cast<u32>(lightmapFlag) << std::endl;
|
||||
res << ")";
|
||||
|
||||
return res.str();
|
||||
|
||||
@@ -36,11 +36,12 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
|
||||
TYRA_ASSERT(frame->count > 0, "Vertex count must be greater than 0",
|
||||
"Material name: ", material->name);
|
||||
TYRA_ASSERT(frame->vertices != nullptr, "Vertex array can't be null");
|
||||
TYRA_ASSERT(!data.normalsEnabled || frame->normals != nullptr,
|
||||
TYRA_ASSERT(!data.loadNormals || frame->normals != nullptr,
|
||||
"Normal array can't be null");
|
||||
TYRA_ASSERT(!data.textureCoordsEnabled || frame->textureCoords != nullptr,
|
||||
TYRA_ASSERT(
|
||||
!material->texturePath.has_value() || frame->textureCoords != nullptr,
|
||||
"Texture coordinate array can't be null");
|
||||
TYRA_ASSERT(!data.lightMapEnabled || frame->colors != nullptr,
|
||||
TYRA_ASSERT(!data.loadLightmap || frame->colors != nullptr,
|
||||
"Color array can't be null");
|
||||
|
||||
bbox = new BBox(frame->vertices, frame->count);
|
||||
@@ -48,7 +49,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
|
||||
count = frame->count;
|
||||
vertices = frame->vertices;
|
||||
|
||||
if (data.normalsEnabled) {
|
||||
if (data.loadNormals) {
|
||||
normals = frame->normals;
|
||||
} else {
|
||||
if (frame->normals != nullptr) delete[] frame->normals;
|
||||
@@ -56,7 +57,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
|
||||
normals = nullptr;
|
||||
}
|
||||
|
||||
if (data.textureCoordsEnabled) {
|
||||
if (material->texturePath.has_value()) {
|
||||
textureCoords = frame->textureCoords;
|
||||
} else {
|
||||
if (frame->textureCoords != nullptr) delete[] frame->textureCoords;
|
||||
@@ -64,7 +65,7 @@ MeshMaterialFrame::MeshMaterialFrame(const MeshBuilderData& data,
|
||||
textureCoords = nullptr;
|
||||
}
|
||||
|
||||
if (data.lightMapEnabled) {
|
||||
if (data.loadLightmap) {
|
||||
colors = frame->colors;
|
||||
} else {
|
||||
if (frame->colors != nullptr) delete[] frame->colors;
|
||||
|
||||
@@ -160,19 +160,19 @@ void DynPipRenderer::sendObjectData(
|
||||
void DynPipRenderer::render(DynPipBag** bags, const u32& count) {
|
||||
if (count <= 0) return;
|
||||
|
||||
auto* program = programsRepo->getProgramByBag(bags[0]);
|
||||
addBufferDataToPacket(program, bags, count);
|
||||
addBufferDataToPacket(bags, count);
|
||||
sendPacket();
|
||||
}
|
||||
|
||||
void DynPipRenderer::addBufferDataToPacket(DynPipVU1Program* program,
|
||||
DynPipBag** bags, const u32& count) {
|
||||
void DynPipRenderer::addBufferDataToPacket(DynPipBag** bags, const u32& count) {
|
||||
currentPacket = packets[context];
|
||||
packet2_reset(currentPacket, false);
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
if (bags[i]->count <= 0) continue;
|
||||
|
||||
auto* program = programsRepo->getProgramByBag(bags[i]);
|
||||
|
||||
program->addBufferDataToPacket(currentPacket, bags[i], prim);
|
||||
|
||||
if (lastProgramName != program->getName()) {
|
||||
|
||||
@@ -35,6 +35,11 @@ void DynamicPipeline::onUse() {
|
||||
|
||||
buffers = new DynPipBag[buffersCount];
|
||||
|
||||
for (u32 i = 0; i < buffersCount; i++) {
|
||||
buffers[i].texture = nullptr;
|
||||
buffers[i].lighting = nullptr;
|
||||
}
|
||||
|
||||
auto packetSize =
|
||||
buffersCount * 5.1F; // 5.1 = packet2_get_qw_count / buffersCount
|
||||
|
||||
@@ -96,11 +101,12 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
|
||||
|
||||
for (u32 i = 0; i < mesh->materials.size(); i++) {
|
||||
auto* material = mesh->materials[i];
|
||||
|
||||
auto* frameFrom = material->frames[mesh->animation.getState().currentFrame];
|
||||
auto* frameTo = material->frames[mesh->animation.getState().nextFrame];
|
||||
|
||||
auto partSize = core.getMaxVertCountByParams(
|
||||
options && options->lighting, material->frames[0]->textureCoords);
|
||||
options && options->lighting, material->textureName.has_value());
|
||||
|
||||
u32 partsCount = ceil(frameFrom->count / static_cast<float>(partSize));
|
||||
|
||||
@@ -109,13 +115,17 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
|
||||
setBuffersColorBag(buffers, colorBag);
|
||||
u8 isPartInitialized = false;
|
||||
|
||||
auto* texture =
|
||||
Texture* texture = nullptr;
|
||||
|
||||
if (material->textureName.has_value()) {
|
||||
texture =
|
||||
rendererCore->texture.repository.getByMeshMaterialId(material->id);
|
||||
|
||||
TYRA_ASSERT(texture, "Texture for material: ", material->name,
|
||||
"Id: ", material->id,
|
||||
"Was not found in texture repository! Did you forget to add "
|
||||
"texture or disable texture coords loading in mesh?");
|
||||
}
|
||||
|
||||
for (u32 k = 0; k < partsCount; k++) {
|
||||
auto& buffer = buffers[bufferIndex];
|
||||
@@ -127,6 +137,7 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
|
||||
u32 startIndex = k * partSize;
|
||||
|
||||
addVertices(frameFrom, frameTo, &buffer, startIndex);
|
||||
|
||||
buffer.texture = getTextureBag(texture, frameFrom, frameTo, startIndex);
|
||||
buffer.lighting = getLightingBag(frameFrom, frameTo, &model, options,
|
||||
dirLights, startIndex);
|
||||
@@ -139,11 +150,13 @@ void DynamicPipeline::render(const DynamicMesh* mesh,
|
||||
setBuffer(buffers, &buffer, &bufferIndex);
|
||||
}
|
||||
|
||||
sendRestOfBuffers(buffers, bufferIndex);
|
||||
bufferIndex = 0;
|
||||
core.begin(infoBag);
|
||||
|
||||
delete colorBag;
|
||||
}
|
||||
|
||||
sendRestOfBuffers(buffers, &bufferIndex);
|
||||
|
||||
if (dirLights) {
|
||||
delete dirLights;
|
||||
}
|
||||
@@ -177,11 +190,12 @@ void DynamicPipeline::setBuffer(DynPipBag* buffers, DynPipBag* buffer,
|
||||
*bufferIndex += 1;
|
||||
}
|
||||
|
||||
void DynamicPipeline::sendRestOfBuffers(DynPipBag* buffers, u16* bufferIndex) {
|
||||
auto isEndOf1stDBuffer = *bufferIndex <= halfBuffersCount - 1;
|
||||
void DynamicPipeline::sendRestOfBuffers(DynPipBag* buffers,
|
||||
const u16& bufferIndex) {
|
||||
auto isEndOf1stDBuffer = bufferIndex <= halfBuffersCount - 1;
|
||||
|
||||
u32 offset = isEndOf1stDBuffer ? 0 : halfBuffersCount;
|
||||
u32 size = *bufferIndex - offset;
|
||||
u32 size = bufferIndex - offset;
|
||||
|
||||
if (size <= 0) return;
|
||||
|
||||
@@ -258,7 +272,7 @@ DynPipColorBag* DynamicPipeline::getColorBag(
|
||||
DynPipTextureBag* DynamicPipeline::getTextureBag(
|
||||
Texture* texture, const MeshMaterialFrame* materialFrameFrom,
|
||||
const MeshMaterialFrame* materialFrameTo, const u32& startIndex) {
|
||||
if (!materialFrameFrom->textureCoords) return nullptr;
|
||||
if (!materialFrameFrom->textureCoords || texture == nullptr) return nullptr;
|
||||
|
||||
auto* result = new DynPipTextureBag();
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ void StaticPipeline::render(const StaticMesh* mesh,
|
||||
!(options->frustumCulling != PipelineFrustumCulling_Precise &&
|
||||
infoBag->fullClipChecks == true),
|
||||
"Full clip checks are only supported with frustum culling == Precise!");
|
||||
|
||||
TYRA_ASSERT(options->transformationType == TyraMVP ||
|
||||
(!options->fullClipChecks &&
|
||||
options->frustumCulling == PipelineFrustumCulling_None),
|
||||
@@ -146,7 +147,8 @@ StaPipColorBag* StaticPipeline::getColorBag(
|
||||
|
||||
StaPipTextureBag* StaticPipeline::getTextureBag(
|
||||
const MeshMaterial* material, const MeshMaterialFrame* materialFrame) {
|
||||
if (!materialFrame->textureCoords) return nullptr;
|
||||
if (!materialFrame->textureCoords || !material->textureName.has_value())
|
||||
return nullptr;
|
||||
|
||||
auto* result = new StaPipTextureBag();
|
||||
|
||||
|
||||
@@ -116,8 +116,12 @@ void TextureRepository::addByMesh(const Mesh* mesh, const char* directory,
|
||||
if (dirFixed.back() != '/' && dirFixed.back() != ':') dirFixed += "/";
|
||||
|
||||
for (u32 i = 0; i < mesh->materials.size(); i++) {
|
||||
if (!mesh->materials[i]->textureName.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string fullPath =
|
||||
dirFixed + mesh->materials[i]->name + "." + extension;
|
||||
dirFixed + mesh->materials[i]->textureName.value() + "." + extension;
|
||||
|
||||
auto* data = loader.load(fullPath.c_str());
|
||||
Texture* texture = new Texture(data);
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "Send to PS2",
|
||||
"command": "docker exec -t tyra-game-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
|
||||
"command": "docker exec -t tyra-game-compiler sh -c 'cd ${config:buildDirectory}/bin && killall -v ps2client || $true && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} reset && ps2client -h ${input:ps2Ip} execee host:$(find . -maxdepth 1 -type f -name \"*.elf\")'"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
|
||||
Vendored
+3
-1
@@ -2,6 +2,8 @@
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools-extension-pack",
|
||||
"ryzngard.vscode-header-source",
|
||||
"maziac.asm-code-lens"
|
||||
"maziac.asm-code-lens",
|
||||
"dmnsgn.vscode-wavefront",
|
||||
"spmeesseman.vscode-taskexplorer"
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <engine.hpp>
|
||||
#include <game.hpp>
|
||||
#include <tyra>
|
||||
|
||||
namespace Racer {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "engine.hpp"
|
||||
#include <tyra>
|
||||
#include "racer_game.hpp"
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -37,9 +37,8 @@ void Tutorial04::loop() {
|
||||
/**
|
||||
* Render de_dust2.
|
||||
*
|
||||
* As you see there are clipping issues (visual glitches).
|
||||
* If you want to know how to fix it, please
|
||||
* watch video tutorial.
|
||||
* If you see clipping issues (visual glitches),
|
||||
* You can check how to fix them in #02 YT tutorial.
|
||||
*/
|
||||
stapip.render(mesh.get(), renderOptions);
|
||||
}
|
||||
@@ -52,7 +51,7 @@ void Tutorial04::loadMesh() {
|
||||
|
||||
/**
|
||||
* Load mesh data
|
||||
* Texture names are the material names "usemtl <material name>"
|
||||
* Texture file names are loaded from .mtl file (map_Kd field).
|
||||
*/
|
||||
auto data =
|
||||
ObjLoader::load(FileUtils::fromCwd("de_dust2/de_dust2.obj"), options);
|
||||
@@ -68,8 +67,9 @@ void Tutorial04::loadMesh() {
|
||||
renderOptions.frustumCulling = Tyra::PipelineFrustumCulling_None;
|
||||
|
||||
/**
|
||||
* Function which load all textures into texture repository,
|
||||
* based on material names.
|
||||
* Function which load all textures into texture repository.
|
||||
* It will automatically extract filename from path (map_Kd) and add
|
||||
* proper extension.
|
||||
*/
|
||||
engine->renderer.getTextureRepository().addByMesh(
|
||||
mesh.get(), FileUtils::fromCwd("de_dust2/"), "png");
|
||||
|
||||
@@ -21,6 +21,8 @@ Tutorial05::~Tutorial05() {
|
||||
}
|
||||
|
||||
void Tutorial05::init() {
|
||||
engine->renderer.setClearScreenColor(Color(32.0F, 32.0F, 32.0F));
|
||||
|
||||
dynpip.setRenderer(&engine->renderer.core);
|
||||
|
||||
cameraPosition = Vec4(0.0F, 0.0F, -10.0F);
|
||||
@@ -55,7 +57,7 @@ void Tutorial05::loadZombieMesh() {
|
||||
/** Starting file suffix index. It means that 1 will start from _000001.obj */
|
||||
options.animation.startingIndex = 1;
|
||||
|
||||
/** If you want to know how to cook this file, please watch tutorial video */
|
||||
/** If you want to know how to cook this file, please watch #02 YT tutorial */
|
||||
auto data = ObjLoader::load(FileUtils::fromCwd("zombie/zombie.obj"), options);
|
||||
|
||||
zombieMesh = std::make_unique<DynamicMesh>(data.get());
|
||||
|
||||
@@ -76,12 +76,9 @@ void Tutorial07::loadMeshWithLightmap() {
|
||||
auto data = ObjLoader::load(FileUtils::fromCwd("cup.obj"), options);
|
||||
|
||||
/**
|
||||
* We don't want to load texture coordinates,
|
||||
* because this obj file has no texture.
|
||||
*
|
||||
* Anyways you can use texture as well.
|
||||
* This model has no texture (it was exported without UV data),
|
||||
* but you can use lighting with textures as well.
|
||||
*/
|
||||
data->textureCoordsEnabled = false;
|
||||
|
||||
/** Lets add lightmap manually */
|
||||
setLightmap(data.get());
|
||||
@@ -120,7 +117,7 @@ void Tutorial07::setDirectionalLightsOptions() {
|
||||
|
||||
void Tutorial07::setLightmap(MeshBuilderData* data) {
|
||||
/** Information for mesh, that data has lightmap */
|
||||
data->lightMapEnabled = true;
|
||||
data->loadLightmap = true;
|
||||
|
||||
/** This object file has only 1 material */
|
||||
auto* material = data->materials[0];
|
||||
|
||||
@@ -92,7 +92,6 @@ void Tutorial08::loadCupMesh() {
|
||||
options.scale = 3.0F;
|
||||
|
||||
auto data = ObjLoader::load(FileUtils::fromCwd("cup/cup.obj"), options);
|
||||
data->textureCoordsEnabled = false;
|
||||
|
||||
cupMesh = std::make_unique<StaticMesh>(data.get());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user