Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b75b2d6e4f | |||
| 5aa2a9bdb5 | |||
| 06a440243a | |||
| 138ab762ba | |||
| 200fa3e4d5 | |||
| ef7bd425db | |||
| d4be8e94e7 | |||
| f9dc79caf1 | |||
| 885e8b4f2b | |||
| 3cfe7ba8f1 | |||
| ebf2a9ac24 | |||
| 24016ffa7e | |||
| aa97e471ed | |||
| 99d4c3633b | |||
| 8501a85f49 | |||
| ab69ba28e3 | |||
| 5320d7f84d | |||
| 9e00ef3634 | |||
| abda2fe3fa | |||
| 18e00f8e17 | |||
| bde819903b | |||
| ec6555aca3 | |||
| 034ea34931 | |||
| 887fcc1ba6 |
+6
-6
@@ -1,11 +1,11 @@
|
||||
.vscode/
|
||||
|
||||
*.bmp
|
||||
*.obj
|
||||
*.wav
|
||||
*.md2
|
||||
*.dff
|
||||
*.irx
|
||||
*.[Bb][Mm][Pp]
|
||||
*.[Oo][Bb][Jj]
|
||||
*.[Ww][Aa][Vv]
|
||||
*.[Dd][Ff][Ff]
|
||||
*.[Ii][Rr][Xx]
|
||||
*.[Mm][Dd]2
|
||||
|
||||
# ---
|
||||
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
[![Contributors][contributors-shield]][contributors-url]
|
||||
[![MIT License][license-shield]][license-url]
|
||||
[![LinkedIn][linkedin-shield]][linkedin-url]
|
||||
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://github.com/h4570/tyra">
|
||||
<a href="https://github.com/ps2-tyra/tyra">
|
||||
<img src="http://allvectorlogo.com/img/2016/05/ps2-logo.png" alt="Logo" width="230" height="125">
|
||||
</a>
|
||||
|
||||
<h3 align="center">Tyra (Work in progress)</h3>
|
||||
<h3 align="center">Tyra alpha 1.1.0</h3>
|
||||
|
||||
<p align="center">
|
||||
Tiny game engine for PS2 (PlayStation 2™) homebrew, written in C++98
|
||||
First open source renderer and game engine for PS2 (PlayStation 2™).
|
||||
<br />
|
||||
<a href="https://www.youtube.com/"><strong>View Demo (soon) »</strong></a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="https://github.com/h4570/tyra/issues">Report Bug</a>
|
||||
<a href="https://github.com/ps2-tyra/tyra/issues">Report Bug</a>
|
||||
·
|
||||
<a href="https://github.com/h4570/tyra/issues">Request Feature</a>
|
||||
<a href="https://github.com/ps2-tyra/tyra/issues">Request Feature</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
@@ -26,7 +25,9 @@
|
||||
|
||||
* [About the Project](#about-the-project)
|
||||
* [Samples](#samples)
|
||||
* [Features](#features)
|
||||
* [About project](#about-project)
|
||||
* [Acronyms](#acronyms)
|
||||
* [Tyra features](#tyra-features)
|
||||
* [Built With](#built-with)
|
||||
* [Getting Started](#getting-started)
|
||||
* [Prerequisites](#prerequisites)
|
||||
@@ -35,43 +36,47 @@
|
||||
* [Contributing](#contributing)
|
||||
* [License](#license)
|
||||
* [Contact](#contact)
|
||||
* [Thanks](#thanks)
|
||||
|
||||
## About The Project
|
||||
|
||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/tyra.gif" alt="sample" width="600" height="auto">
|
||||
|
||||
This repository contains a early version of game engine with simple demos for PS2 (PlayStation 2™) that I've developed using the freely available PS2DEV, unofficial SDK.
|
||||
Developing for PS2 was and is a big challenge for me, it's pretty low-level and hard (for me :D). The architecture is completely different from an Intel x86 and there are lots of extra things that you need to take into account. There are some samples available to teach on, but overall community died several years ago :/
|
||||
|
||||
**Why PS2 game dev is so different?** Creating games for PS2 is completly different from dragging colored buttons from side to side through an application with nice GUI (ex. Unity).
|
||||
Coding something for PS2 requires from you doing everything from scratch, even data transfer management through (/co)processors like:
|
||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
||||
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper, geometry transformations are not done by it. Has only 2MB~ memory for textures, but very high transfer rate, so you can switch them in the blink
|
||||
* VU0 - vector processor accessed by inline assembly code injected into C program
|
||||
* VU1 - vector processor (similar vertex shader) accessed via DMAC
|
||||
* IOP - I/O processor which enables access to peripheral devices, such the game controller
|
||||
<img src="http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/tyra.gif" alt="sample" width="600" height="auto">
|
||||
|
||||
### Samples
|
||||
* [Floors](https://github.com/h4570/tyra/tree/master/src/samples/floors)
|
||||
* [Ari (WIP)](https://github.com/h4570/tyra/tree/master/src/samples/ari)
|
||||
* [Floors](https://github.com/ps2-tyra/tyra/tree/master/src/samples/floors)
|
||||
* [Ari (WIP)](https://github.com/ps2-tyra/tyra/tree/master/src/samples/ari)
|
||||
|
||||
### Features
|
||||
* VU1 (PATH 1 rendering) with double buffering
|
||||
* GIF (PATH 3 rendering) with double buffering
|
||||
* Optimized calculations using VU0
|
||||
* Frustum culling
|
||||
* Backface culling
|
||||
* Perspective projection (like OpenGL's)
|
||||
* Audio support
|
||||
* Animation support
|
||||
* Third person view "lookAt" camera (like OpenGL's)
|
||||
* Dualshock 2 pad support
|
||||
* RGB 888 24bit texture support (with .bmp loader)
|
||||
* 3D files loaders: ".obj", ".dff" (renderware) and ".md2"
|
||||
* Multi threading management
|
||||
* 3D object management
|
||||
### Contributors wanted
|
||||
#### I will be grateful for any help, Discord: Sandro#3402
|
||||
|
||||
### About project
|
||||
Goal of Tyra project is to provide simple API for PS2 (PlayStation 2™) game creation. So you can just run PS2 emulator, grab your .obj file, and put it into live in a seconds. Project is on early stage, so a lot of stuff is changing from release to release.
|
||||
|
||||
YouTube tutorials soon!
|
||||
|
||||
**Why PS2 game dev is so different?** Raw PS2 development can be a big challenge. PS2 it's pretty low-level and there are a lot of stuff that you must do from scratch.
|
||||
Tyra takes care for you, and rendering, coprocessors communication and many more low-level stuff is already done.
|
||||
|
||||
### Acronyms
|
||||
* EE (Emotion Engine) - whole set of processors and subsystems that make up the PlayStation 2
|
||||
* GS (Graphic synthesizer) - configurable rasterizer and texture mapper. Has only 2MB~ memory for textures, but for the opposite have very high transfer rate, so you can switch textures in the blink
|
||||
* VU0 - programmable (ASM) vector processor that is accessed by inline assembly code injected into C program.
|
||||
* 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
|
||||
|
||||
### Tyra features
|
||||
* VU1 rendering (PATH 1), double-buffered
|
||||
* GIF rendering (PATH 3), double-buffered
|
||||
* Frustum culling, backface culling
|
||||
* OpenGL adaptions: Perspective projection, lookAt camera
|
||||
* Texture support (.bmp loader)
|
||||
* Mesh loaders: ".obj", ".dff" (RenderWare, GTA:SA) and ".md2" (Quake II)
|
||||
* Threading support
|
||||
* Lighting support (now PATH3 only)
|
||||
* Other: collision, gravity etc.
|
||||
* Animation support
|
||||
* Audio support
|
||||
* Pad support
|
||||
* TODO: physics, ADPCM and many more!
|
||||
|
||||
### Built With
|
||||
|
||||
@@ -80,6 +85,7 @@ Coding something for PS2 requires from you doing everything from scratch, even d
|
||||
## Getting Started
|
||||
|
||||
To get a local copy up and running follow these simple steps.
|
||||
YouTube tutorials soon!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -92,7 +98,7 @@ This is an example of how to list things you need to use the software and how to
|
||||
|
||||
1. Clone the repo
|
||||
```sh
|
||||
git clone https://github.com/h4570/tyra.git
|
||||
git clone https://github.com/ps2-tyra/tyra.git
|
||||
```
|
||||
2. Get into src folder and compile it!
|
||||
```sh
|
||||
@@ -106,30 +112,20 @@ make
|
||||
|
||||
## Roadmap
|
||||
|
||||
Here is a list of the things I'm working on:
|
||||
### Roadmap moved to github kanban:
|
||||
[https://github.com/ps2-tyra/tyra/projects/1](https://github.com/ps2-tyra/tyra/projects/1)
|
||||
|
||||
* Fix PATH3 and PATH1 triangle clipping
|
||||
* Add skybox with 6 textures to ari sample
|
||||
* Ariana textures
|
||||
* Bugfix: Player speed on different zoom
|
||||
* Implement player rotation
|
||||
* Bugfix: Backface culling bug on rotation
|
||||
* Bugfix: Remove camera rotation reset flickering
|
||||
* Bugfix: 2x Audio tick overflow
|
||||
* Audio - change listeners logic
|
||||
* Sound effects
|
||||
* Code documentation
|
||||
|
||||
See the [open issues](https://github.com/h4570/tyra/issues) for a list of proposed features (and known issues).
|
||||
See the [open issues](https://github.com/ps2-tyra/tyra/issues) for a list of proposed features (and known issues).
|
||||
|
||||
## 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**.
|
||||
|
||||
1. Fork the Project
|
||||
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
||||
2. Create your Feature Branch (`git checkout -b feature/amazing-feature`)
|
||||
3. Commit your Changes (`git commit -m 'Add some amazing-feature'`)
|
||||
4. Push to the Branch (`git push origin feature/amazing-feature`)
|
||||
5. Open a Pull Request
|
||||
|
||||
## License
|
||||
@@ -138,13 +134,24 @@ Distributed under the Apache License 2.0 License. See `LICENSE` for more informa
|
||||
|
||||
## Contact
|
||||
|
||||
Sandro Sobczyński - hastoklai@gmail.com
|
||||
Sandro Sobczyński - sandro.sobczynski@gmail.com
|
||||
[![LinkedIn][linkedin-shield]][linkedin-url]
|
||||
|
||||
Project Link: [https://github.com/h4570/tyra](https://github.com/h4570/tyra)
|
||||
## Thanks
|
||||
|
||||
[contributors-shield]: https://img.shields.io/github/contributors/h4570/tyra.svg?style=flat-square
|
||||
[contributors-url]: https://github.com/h4570/tyra/graphs/contributors
|
||||
Without these guys, everything would be harder:
|
||||
* Dr Henry Fortuna - Abertay University (code sources)
|
||||
* Lukasz D.K. (huge archive of PS2 stuff)
|
||||
* Guilherme Lampert - PlayStation London (code sources)
|
||||
* Jesper Svennevid, Daniel Collin - Microcode (openvcl, code samples)
|
||||
* Whole PS2SDK/PS2Scene team
|
||||
* And so many other guys. Thanks!
|
||||
|
||||
Project Link: [https://github.com/ps2-tyra/tyra](https://github.com/ps2-tyra/tyra)
|
||||
|
||||
[contributors-shield]: https://img.shields.io/github/contributors/ps2-tyra/tyra.svg?style=flat-square
|
||||
[contributors-url]: https://github.com/ps2-tyra/tyra/graphs/contributors
|
||||
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat-square&logo=linkedin&colorB=555
|
||||
[linkedin-url]: https://linkedin.com/in/sandro-sobczyński-28820b15a/
|
||||
[license-shield]: https://img.shields.io/github/license/h4570/tyra.svg?style=flat-square
|
||||
[license-url]: https://github.com/h4570/tyra/blob/master/LICENSE
|
||||
[license-shield]: https://img.shields.io/github/license/ps2-tyra/tyra.svg?style=flat-square
|
||||
[license-url]: https://github.com/ps2-tyra/tyra/blob/master/LICENSE
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <tamtypes.h>
|
||||
#include "../models/texture.hpp"
|
||||
#include "../models/mesh_texture.hpp"
|
||||
|
||||
/** Class responsible for loading images in bmp format */
|
||||
class BmpLoader
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
BmpLoader();
|
||||
~BmpLoader();
|
||||
|
||||
void load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
|
||||
void load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef _TYRA_DFF_LOADER_
|
||||
#define _TYRA_DFF_LOADER_
|
||||
|
||||
#include "../models/dff_model.hpp"
|
||||
#include "../models/mesh_frame.hpp"
|
||||
#include "./dff_structure.hpp"
|
||||
|
||||
/** Class responsible for loading&parsing .obj 3D files */
|
||||
@@ -22,30 +22,27 @@ public:
|
||||
DffLoader();
|
||||
~DffLoader();
|
||||
|
||||
void load(RwClump &o_clump, char *t_fileName, float t_scale);
|
||||
void serialize(RwClump &t_clump, u8 *t_data, float t_scale);
|
||||
|
||||
static u8 readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
static u16 readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
static u32 readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
static float readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
static u8 *readData(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize);
|
||||
static char *readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize = 0);
|
||||
|
||||
void readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||
void serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale);
|
||||
|
||||
private:
|
||||
// ---
|
||||
void readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readGeometryExtension(RwGeometryExtension &t_ge, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readGeometryData(RwGeometryData &t_gd, u8 *t_buffer, u32 &t_ptrPos, float t_scale);
|
||||
void readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readGeometryData(MeshFrame *o_frame, u8 t_invertT, u8 *t_buffer, u32 &t_ptrPos, float t_scale);
|
||||
void readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readTextureData(RwTextureData &t_td, u8 *t_buffer, u32 &t_ptrPos);
|
||||
void readStringData(RwString &t_s, u8 *bt_uffer, u32 &t_ptrPos);
|
||||
void readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos);
|
||||
// ---
|
||||
u8 readByteFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
u16 readWordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
u32 readDwordFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
float readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos);
|
||||
char *readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize = 0);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
class RwFrameListChunk
|
||||
{
|
||||
public:
|
||||
~RwFrameListChunk() { delete[] rotationalMatrix; }
|
||||
~RwFrameListChunk() {}
|
||||
float *rotationalMatrix; // [ROT_MAT_DIM]
|
||||
float coordinatesOffsetX;
|
||||
float coordinatesOffsetY;
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
class RwFrameListData : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwFrameListData() { delete frameInformation; }
|
||||
~RwFrameListData() {}
|
||||
static const u32 ROT_MAT_DIM = 9;
|
||||
u32 frameCount;
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
class RwFrame : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwFrame() { delete[] frameName; }
|
||||
~RwFrame() {}
|
||||
u8 *frameName; // [sectionSize] - should be interpreted as string
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ class RwFrameList : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
RwFrameListData data;
|
||||
~RwFrameList() { delete[] extensions; }
|
||||
~RwFrameList() {}
|
||||
RwFrameListExtension *extensions;
|
||||
};
|
||||
// ---
|
||||
@@ -89,50 +89,65 @@ public:
|
||||
u32 morphTargetCount;
|
||||
};
|
||||
|
||||
class RwGeometryDataLightingHeader
|
||||
struct RwGeometryDataLightingHeader
|
||||
{ // IF versionNumber = 4099 - according to not complete documentation
|
||||
public:
|
||||
float ambient;
|
||||
float diffuse;
|
||||
float specular;
|
||||
};
|
||||
|
||||
class RwGeometryDataColorInformationChunk
|
||||
struct RwGeometryDataColorInformationChunk
|
||||
{ // if rwOBJECT_VERTEX_PREILIT in flags
|
||||
public:
|
||||
|
||||
u8 red;
|
||||
u8 green;
|
||||
u8 blue;
|
||||
u8 alpha;
|
||||
};
|
||||
|
||||
class RwGeometryDataTextureMappingInformationChunk
|
||||
struct RwGeometryDataTextureMappingInformationChunk
|
||||
{ // if rwOBJECT_VERTEX_TEXTURED in flags
|
||||
public:
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
class RwGeometryDataFaceInformation
|
||||
struct RwGeometryDataFaceInformation
|
||||
{
|
||||
public:
|
||||
u16 vertex2; // this
|
||||
u16 vertex1; // is
|
||||
u16 flags; // weird
|
||||
u16 vertex3; // order
|
||||
};
|
||||
|
||||
class RwGeometryDataNonameInfo
|
||||
{
|
||||
public:
|
||||
float boundingSphereX;
|
||||
float boundingSphereY;
|
||||
float boundingSphereZ;
|
||||
float boundingSphereR;
|
||||
u32 hasPosition;
|
||||
u32 hasNormals;
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Section: Geometry
|
||||
class RwGeometryData : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwGeometryData()
|
||||
{
|
||||
delete colorInformation;
|
||||
delete textureMappingInformation;
|
||||
delete faceInformation;
|
||||
delete vertexInformation;
|
||||
delete normalInformation;
|
||||
// if (dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
|
||||
// delete[] normalInformation;
|
||||
// delete[] vertexInformation;
|
||||
// free(vertexInformation);
|
||||
// delete[] faceInformation;
|
||||
// if (dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
|
||||
// delete[] colorInformation;
|
||||
// if (dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||
// delete[] textureMappingInformation;
|
||||
}
|
||||
RwGeometryDataHeader dataHeader;
|
||||
|
||||
@@ -144,16 +159,7 @@ public:
|
||||
|
||||
RwGeometryDataFaceInformation *faceInformation; // [triangleCount]
|
||||
|
||||
class RwGeometryDataNonameInfo
|
||||
{
|
||||
public:
|
||||
float boundingSphereX;
|
||||
float boundingSphereY;
|
||||
float boundingSphereZ;
|
||||
float boundingSphereR;
|
||||
u32 hasPosition;
|
||||
u32 hasNormals;
|
||||
} nonameInfo;
|
||||
RwGeometryDataNonameInfo nonameInfo;
|
||||
|
||||
Vector3 *vertexInformation; // [vertexCount]
|
||||
|
||||
@@ -211,7 +217,7 @@ class RwMaterialExtension : public RwSectionHeader
|
||||
class RwMaterial : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwMaterial() { delete[] textures; }
|
||||
~RwMaterial() {}
|
||||
RwMaterialData data;
|
||||
RwTexture *textures;
|
||||
RwMaterialExtension extension;
|
||||
@@ -220,7 +226,7 @@ public:
|
||||
class RwMaterialListData : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwMaterialListData() { delete[] arrayOfUnks; }
|
||||
~RwMaterialListData() {}
|
||||
u32 materialCount;
|
||||
u32 *arrayOfUnks; // Filled with '-1's, [materialCount] - it wasn't mentioned in docs.
|
||||
};
|
||||
@@ -228,7 +234,7 @@ public:
|
||||
class RwMaterialList : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwMaterialList() { delete[] materials; }
|
||||
~RwMaterialList() {}
|
||||
RwMaterialListData data;
|
||||
RwMaterial *materials;
|
||||
};
|
||||
@@ -242,24 +248,26 @@ public:
|
||||
class RwGeometryListInfoChunk
|
||||
{
|
||||
public:
|
||||
~RwGeometryListInfoChunk() { delete vertexInformation; }
|
||||
~RwGeometryListInfoChunk() {}
|
||||
u32 faceIndex;
|
||||
u32 materialIndex;
|
||||
|
||||
RwGeometryListVertexInfoChunk *vertexInformation; // [faceIndex]
|
||||
};
|
||||
|
||||
class RwMaterialSplit
|
||||
class RwMaterialSplitHeader
|
||||
{
|
||||
public:
|
||||
~RwMaterialSplit() { delete splitInformation; }
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
u32 triangleStrip;
|
||||
u32 splitCount;
|
||||
u32 faceCount;
|
||||
} header;
|
||||
};
|
||||
|
||||
class RwMaterialSplit
|
||||
{
|
||||
public:
|
||||
~RwMaterialSplit() {}
|
||||
RwMaterialSplitHeader header;
|
||||
|
||||
RwGeometryListInfoChunk *splitInformation; // [splitCount]
|
||||
};
|
||||
@@ -289,7 +297,7 @@ public:
|
||||
class RwGeometryList : public RwSectionHeader
|
||||
{
|
||||
public:
|
||||
~RwGeometryList() { delete[] geometries; }
|
||||
~RwGeometryList() {}
|
||||
RwGeometryListData data;
|
||||
RwGeometry *geometries;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef _TYRA_MD2_LOADER_
|
||||
#define _TYRA_MD2_LOADER_
|
||||
|
||||
#include "../models/md2_model.hpp"
|
||||
#include "../models/mesh_frame.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
// magic number "IDP2" or 844121161
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
MD2Loader();
|
||||
~MD2Loader();
|
||||
|
||||
void load(MD2Model *o_result, char *t_fileName, float t_scale);
|
||||
MeshFrame *load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#ifndef _TYRA_OBJ_LOADER_
|
||||
#define _TYRA_OBJ_LOADER_
|
||||
|
||||
#include "../models/obj_model.hpp"
|
||||
#include "../models/mesh_frame.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
/** Class responsible for loading&parsing .obj 3D files */
|
||||
@@ -22,10 +22,14 @@ public:
|
||||
ObjLoader();
|
||||
~ObjLoader();
|
||||
|
||||
void load(ObjModel *o_result, char *t_fileName, float t_scale);
|
||||
/** Parse .obj file, allocate output data and store it. Multitexture support
|
||||
* Notice: At this moment textures names are MATERIAL names from .obj file!
|
||||
* Notice 2: Faces MUST be triangulated (check out blender export settings).
|
||||
*/
|
||||
void load(MeshFrame *o_result, char *t_fileName, float t_scale, u8 t_invertT);
|
||||
|
||||
private:
|
||||
void setObjDataQuantities(FILE *t_file, ObjModel *t_result);
|
||||
void allocateObjMemory(FILE *t_file, MeshFrame *t_result);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_ANIM_STATE_
|
||||
#define _TYRA_ANIM_STATE_
|
||||
|
||||
#include <tamtypes.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 startFrame;
|
||||
u32 endFrame;
|
||||
u32 stayFrame;
|
||||
u8 isStayFrameSet;
|
||||
float speed;
|
||||
float interpolation;
|
||||
u32 animType;
|
||||
u32 currentFrame;
|
||||
u32 nextFrame;
|
||||
} AnimState;
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_DFF_MODEL_
|
||||
#define _TYRA_DFF_MODEL_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <math3d.h>
|
||||
#include "../loaders/dff_structure.hpp"
|
||||
#include "./math/vector3.hpp"
|
||||
|
||||
/** Class which have common types for all 3D objects */
|
||||
class DffModel
|
||||
{
|
||||
|
||||
public:
|
||||
DffModel();
|
||||
~DffModel();
|
||||
|
||||
u32 getDrawData(u32 splitIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
||||
RwClump clump;
|
||||
|
||||
private:
|
||||
void fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u8 geometry, u32 t_getI, u32 t_setI);
|
||||
u8 isMemoryAllocated;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -26,11 +26,13 @@ public:
|
||||
float xy[2] __attribute__((__aligned__(16)));
|
||||
};
|
||||
|
||||
Point(float x, float y);
|
||||
Point(const float &t_x, const float &t_y);
|
||||
Point(const Point &v);
|
||||
Point();
|
||||
~Point();
|
||||
|
||||
void set(float x, float y);
|
||||
void set(const float &t_x, const float &t_y);
|
||||
void set(const Point &v);
|
||||
void print();
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
float xyz[3] __attribute__((__aligned__(16)));
|
||||
};
|
||||
|
||||
Vector3(float x, float y, float z);
|
||||
Vector3(float t_x, float t_y, float t_z);
|
||||
Vector3(const Vector3 &v);
|
||||
Vector3();
|
||||
~Vector3();
|
||||
@@ -48,10 +48,10 @@ public:
|
||||
u8 isOnSquare(Vector3 &t_min, Vector3 &t_max);
|
||||
float length();
|
||||
void normalize();
|
||||
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float t_interp);
|
||||
void setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale);
|
||||
float innerProduct(Vector3 &v);
|
||||
void set(Vector3 &v);
|
||||
void set(float x, float y, float z);
|
||||
void set(const Vector3 &v);
|
||||
void set(const float &x, const float &y, const float &z);
|
||||
void copy(Vector3 &v);
|
||||
float distanceTo(Vector3 &v);
|
||||
void print();
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_MD2_MODEL_
|
||||
#define _TYRA_MD2_MODEL_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <math3d.h>
|
||||
#include "math/vector3.hpp"
|
||||
#include "math/point.hpp"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 startFrame;
|
||||
u32 endFrame;
|
||||
float speed;
|
||||
float interpolation;
|
||||
u32 animType;
|
||||
u32 currentFrame;
|
||||
u32 nextFrame;
|
||||
} MD2AnimState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 verticeIndexes[3];
|
||||
u16 coordIndexes[3];
|
||||
} MD2Triangle;
|
||||
|
||||
/** Class which have common types for all 3D objects */
|
||||
class MD2Model
|
||||
{
|
||||
|
||||
public:
|
||||
u32 verticesPerFrameCount, framesCount, coordinatesCount, trianglesCount;
|
||||
Vector3 *vertices __attribute__((aligned(16)));
|
||||
Point *coordinates;
|
||||
u32 *normalIndexes;
|
||||
MD2Triangle *triangles;
|
||||
MD2AnimState animState;
|
||||
/** File name without extension */
|
||||
char *filename;
|
||||
MD2Model(char *t_md2File);
|
||||
~MD2Model();
|
||||
u32 getCurrentFrameData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
||||
void allocateMemory();
|
||||
|
||||
private:
|
||||
Vector3 calcVector;
|
||||
Vector3 calc3Vectors[3];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,61 +8,195 @@
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_OBJECT3D_
|
||||
#define _TYRA_OBJECT3D_
|
||||
#ifndef _TYRA_MESH_
|
||||
#define _TYRA_MESH_
|
||||
|
||||
#include "math/vector3.hpp"
|
||||
#include "math/plane.hpp"
|
||||
#include "mesh_spec.hpp"
|
||||
#include "obj_model.hpp"
|
||||
#include "dff_model.hpp"
|
||||
#include "md2_model.hpp"
|
||||
#include "./mesh_texture.hpp"
|
||||
#include "./mesh_frame.hpp"
|
||||
#include <tamtypes.h>
|
||||
#include <draw_types.h>
|
||||
#include <draw_buffers.h>
|
||||
#include <draw_sampling.h>
|
||||
#include "./anim_state.hpp"
|
||||
|
||||
/** Class which have common types for all 3D objects */
|
||||
class Mesh
|
||||
{
|
||||
|
||||
public:
|
||||
Vector3 position, rotation;
|
||||
u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled;
|
||||
|
||||
MeshSpec *spec;
|
||||
MD2Model *md2;
|
||||
ObjModel *obj;
|
||||
DffModel *dff;
|
||||
float scale;
|
||||
color_t color;
|
||||
Vector3 boxVertices[8];
|
||||
|
||||
Mesh();
|
||||
~Mesh();
|
||||
|
||||
void loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale);
|
||||
void setObj(Vector3 &t_initPos, ObjModel *t_objModel, MeshSpec *t_spec);
|
||||
void loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale);
|
||||
void setDff(Vector3 &t_initPos, DffModel *t_dffModel, MeshSpec *t_spec);
|
||||
void loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale);
|
||||
void getMinMax(Vector3 *t_min, Vector3 *t_max);
|
||||
void playAnimation(u32 t_startFrame, u32 t_endFrame);
|
||||
u32 getVertexCount();
|
||||
void setAnimSpeed(float t_value);
|
||||
u32 getDrawData(u32 splitIndex, VECTOR *t_vertices, VECTOR *t_normals, VECTOR *t_coordinates, VECTOR *t_colors, Vector3 &t_cameraPos);
|
||||
Vector3 position, rotation;
|
||||
float scale;
|
||||
u8 shouldBeLighted, shouldBeBackfaceCulled, shouldBeFrustumCulled;
|
||||
color_t color;
|
||||
clutbuffer_t clut;
|
||||
lod_t lod;
|
||||
|
||||
// ----
|
||||
// Getters
|
||||
// ----
|
||||
|
||||
/** Auto generated unique Id. */
|
||||
const u32 &getId() const { return id; };
|
||||
|
||||
/** Array of materials. Size of getMaterialsCount() */
|
||||
MeshMaterial *getMaterials() const { return frames[0].getMaterials(); };
|
||||
|
||||
const u32 &getMaterialsCount() const { return frames[0].getMaterialsCount(); };
|
||||
|
||||
/** Returns material, which is a mesh "subgroup". */
|
||||
MeshMaterial &getMaterial(const u32 &i) const { return frames[0].getMaterial(i); };
|
||||
|
||||
/** Auto count of frames. Static object (not animated) will have only 1 frame. */
|
||||
const u32 &getFramesCount() const { return framesCount; };
|
||||
|
||||
/** Count of vertices. */
|
||||
u32 getVertexCount() { return frames[0].getVertexCount(); };
|
||||
|
||||
/** Returns single frame. */
|
||||
MeshFrame &getFrame(const u32 &i) const { return frames[i]; };
|
||||
|
||||
/** Array of frames. Size of getFramesCount() */
|
||||
MeshFrame *getFrames() const { return frames; };
|
||||
|
||||
const u32 &getCurrentAnimationFrame() const { return animState.currentFrame; };
|
||||
|
||||
const u32 &getNextAnimationFrame() const { return animState.nextFrame; };
|
||||
|
||||
const u32 &getStartAnimationFrame() const { return animState.startFrame; };
|
||||
|
||||
const u32 &getEndAnimationFrame() const { return animState.endFrame; };
|
||||
|
||||
const u32 &getStayAnimationFrame() const { return animState.stayFrame; };
|
||||
|
||||
/**
|
||||
* Returns material, which is a mesh "subgroup".
|
||||
* NULL if not found.
|
||||
*/
|
||||
MeshMaterial *getMaterialById(const u32 &t_id) const { return frames[0].getMaterialById(t_id); }
|
||||
|
||||
/**
|
||||
* Returns bounding vertex of current frame.
|
||||
* @param i 0-7. Because, bounding box have 8 corners
|
||||
*/
|
||||
Vector3 &getCurrentBoundingBoxVertex(const u8 &i) { return frames[animState.currentFrame].getBoundingBoxVertex(i); };
|
||||
|
||||
/** Returns bounding box of current frame. Size: 8 */
|
||||
Vector3 *getCurrentBoundingBox() const { return frames[animState.currentFrame].getBoundingBox(); };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Load mesh data from .obj files. Animation not supported.
|
||||
* Be aware that texture names will be grabbed from material name.
|
||||
* So no .mtl file is needed. Please check if material names in .obj file
|
||||
* are equal to texture file names.
|
||||
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||
* @param t_objFile File name without extension. Example "sand"
|
||||
* @param t_scale Scale. For 1:1, type 1.0F
|
||||
* @param t_framesCount Amount of frames.
|
||||
* Example: 2.
|
||||
* Searched files: sand_000001.obj, sand_000002.obj
|
||||
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||
*/
|
||||
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT);
|
||||
|
||||
/**
|
||||
* Load mesh data from .obj file. Animation supported.
|
||||
* Be aware that texture names will be grabbed from material name.
|
||||
* So no .mtl file is needed. Please check if material names in .obj file
|
||||
* are equal to texture file names.
|
||||
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||
* @param t_objFile File name without extension. Example "sand"
|
||||
* @param t_scale Scale. For 1:1, type 1.0F
|
||||
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||
*/
|
||||
void loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT);
|
||||
|
||||
/**
|
||||
* Load mesh data from RenderWare .dff file. Animation not supported
|
||||
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||
* @param t_objFile File name without extension. Example "sand"
|
||||
* @param t_scale Scale. For 1:1, type 1.0F
|
||||
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||
*/
|
||||
void loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT);
|
||||
|
||||
/**
|
||||
* Load mesh data from Quake II .md2 file. Animation supported.
|
||||
* @param t_subfolder Relative path. Example "meshes/blocks"
|
||||
* @param t_objFile File name without extension. Example "sand"
|
||||
* @param t_scale Scale. For 1:1, type 1.0F
|
||||
* @param t_invertT Sometimes textures are in UV format, in this case, invertT should be set to true.
|
||||
* Converts Y coordinate texture from Y to 1.0F - Y
|
||||
*/
|
||||
void loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT);
|
||||
|
||||
/** Copy by reference mesh data from other mesh */
|
||||
void loadFrom(const Mesh &t_mesh);
|
||||
|
||||
/** Check if are there any frames */
|
||||
u8 isDataLoaded() const { return framesCount > 0; };
|
||||
|
||||
/** Loop in one frame */
|
||||
void playAnimation(const u32 &t_frame) { playAnimation(t_frame, t_frame); }
|
||||
|
||||
/** Play animation in loop from startFrame to endFrame */
|
||||
void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame);
|
||||
|
||||
/** Play animation from startFrame to endFrame and after loop in stayFrame */
|
||||
void playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame);
|
||||
|
||||
void setAnimSpeed(const float &t_value) { animState.speed = t_value; }
|
||||
|
||||
/**
|
||||
* Check if this class loaded mesh data first.
|
||||
* Meshes which use loadFrom() method have false there.
|
||||
*/
|
||||
const u8 &isMother() const { return _isMother; };
|
||||
|
||||
/**
|
||||
* Check if this class loaded mesh data first.
|
||||
* Meshes which use loadFrom() method have false there.
|
||||
*/
|
||||
const u8 &isStayAnimationSet() const { return animState.isStayFrameSet; };
|
||||
|
||||
/** True when mesh is in view frustum */
|
||||
u8 isInFrustum(Plane *t_frustumPlanes);
|
||||
|
||||
u8 isMd2Loaded, isObjLoaded, isDffLoaded, isSpecInitialized;
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by renderer.
|
||||
*/
|
||||
void animate();
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by renderer.
|
||||
*/
|
||||
u32 getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos);
|
||||
|
||||
private:
|
||||
void setDefaultWrapSettings(texwrap_t &t_wrapSettings);
|
||||
u32 verticesCount;
|
||||
Vector3 *vertices;
|
||||
void loadTextures(char *t_subfolder, char *t_extension);
|
||||
void computeBoundingBox();
|
||||
void setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef);
|
||||
void createSpecIfNotCreated();
|
||||
AnimState animState;
|
||||
MeshFrame *frames;
|
||||
u32 id, framesCount;
|
||||
u8 _isMother;
|
||||
Vector3 calc3Vectors[3];
|
||||
void setDefaultColor();
|
||||
void getFarthestVertex(Vector3 *o_result, int t_offset);
|
||||
void setDefaultLODAndClut();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_MESH_FRAME_
|
||||
#define _TYRA_MESH_FRAME_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <tamtypes.h>
|
||||
#include "math/point.hpp"
|
||||
#include "math/vector3.hpp"
|
||||
#include "./mesh_material.hpp"
|
||||
|
||||
/**
|
||||
* Class which contains core mesh data
|
||||
* which are needed for drawing.
|
||||
* Static object (not animated), will have
|
||||
* only one instance of this class.
|
||||
*/
|
||||
class MeshFrame
|
||||
{
|
||||
|
||||
public:
|
||||
MeshFrame();
|
||||
~MeshFrame();
|
||||
|
||||
// ----
|
||||
// Getters
|
||||
// ----
|
||||
|
||||
const u32 &getVertexCount() const { return vertexCount; };
|
||||
const u32 &getSTsCount() const { return stsCount; };
|
||||
const u32 &getNormalsCount() const { return normalsCount; };
|
||||
const u32 &getMaterialsCount() const { return materialsCount; };
|
||||
|
||||
/** Returns vertex. 3 vertices = 1 triangle. */
|
||||
Vector3 &getVertex(const u32 &i) const { return vertices[i]; };
|
||||
|
||||
/** Returns texture coordinate. */
|
||||
Point &getST(const u32 &i) const { return sts[i]; };
|
||||
|
||||
/** Returns normal vector. Used for lighting. */
|
||||
Vector3 &getNormal(const u32 &i) const { return normals[i]; };
|
||||
|
||||
/** Returns material, which is a mesh "subgroup". */
|
||||
MeshMaterial &getMaterial(const u32 &i) const { return materials[i]; };
|
||||
|
||||
/**
|
||||
* Returns material, which is a mesh "subgroup".
|
||||
* NULL if not found.
|
||||
*/
|
||||
MeshMaterial *getMaterialById(const u32 &t_id) const
|
||||
{
|
||||
for (u32 i = 0; i < materialsCount; i++)
|
||||
if (materials[i].getId() == t_id)
|
||||
return &materials[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Array of vertices. Size of getVertexCount() */
|
||||
Vector3 *getVertices() const { return vertices; };
|
||||
|
||||
/** Array of vertices. Size of getSTsCount() */
|
||||
Point *getSTs() const { return sts; };
|
||||
|
||||
/** Array of vertices. Size of getNormalsCount() */
|
||||
Vector3 *getNormals() const { return normals; };
|
||||
|
||||
/** Array of materials. Size of getMaterialsCount() */
|
||||
MeshMaterial *getMaterials() const { return materials; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB).
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 *getBoundingBox() { return boundingBox; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB) vertex.
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setVertex(const u32 &t_index, const Vector3 &t_val) { vertices[t_index].set(t_val); }
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setNormal(const u32 &t_index, const Vector3 &t_val) { normals[t_index].set(t_val); }
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setST(const u32 &t_index, const Point &t_val) { sts[t_index].set(t_val); }
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
|
||||
const u8 &areSTsAllocated() const { return _areSTsAllocated; };
|
||||
const u8 &areVerticesAllocated() const { return _areVerticesAllocated; };
|
||||
const u8 &areNormalsAllocated() const { return _areNormalsAllocated; };
|
||||
const u8 &areMaterialsAllocated() const { return _areMaterialsAllocated; };
|
||||
const u8 &isBoundingBoxCalculated() const { return _isBoundingBoxCalculated; };
|
||||
|
||||
/** Set STs count and allocate memory. */
|
||||
void allocateSTs(const u32 &t_val);
|
||||
|
||||
/** Set vertex count and allocate memory. */
|
||||
void allocateVertices(const u32 &t_val);
|
||||
|
||||
/** Set normals count and allocate memory. */
|
||||
void allocateNormals(const u32 &t_val);
|
||||
|
||||
/** Set materials count and allocate memory. */
|
||||
void allocateMaterials(const u32 &t_val);
|
||||
|
||||
/**
|
||||
* Calculates bounding box (AABB) for frame and for materiaals.
|
||||
* Should be called by data loader,
|
||||
* so there is no need to run it again.
|
||||
*/
|
||||
void calculateBoundingBoxes();
|
||||
|
||||
private:
|
||||
Vector3 boundingBox[8];
|
||||
u8 _areSTsAllocated,
|
||||
_areVerticesAllocated,
|
||||
_areNormalsAllocated,
|
||||
_areMaterialsAllocated,
|
||||
_isBoundingBoxCalculated;
|
||||
u32 vertexCount, stsCount, normalsCount, materialsCount;
|
||||
MeshMaterial *materials;
|
||||
Point *sts __attribute__((aligned(16)));
|
||||
Vector3
|
||||
*vertices __attribute__((aligned(16))),
|
||||
*normals __attribute__((aligned(16)));
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_MESH_MATERIAL_
|
||||
#define _TYRA_MESH_MATERIAL_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include "./math/vector3.hpp"
|
||||
#include "./math/plane.hpp"
|
||||
|
||||
/** Class which contains draw instructions for part mesh of mesh.
|
||||
* Mesh can have many materials.
|
||||
* For example, car mesh can have three materials:
|
||||
* body, tires and windows.
|
||||
*/
|
||||
class MeshMaterial
|
||||
{
|
||||
|
||||
public:
|
||||
MeshMaterial();
|
||||
~MeshMaterial();
|
||||
|
||||
// ----
|
||||
// Getters
|
||||
// ----
|
||||
|
||||
/** Material name. */
|
||||
char *getName() const { return name; };
|
||||
|
||||
/**
|
||||
* Auto generated unique Id.
|
||||
* Core role of this variable is to select correct texture to draw
|
||||
*/
|
||||
const u32 &getId() const { return id; };
|
||||
|
||||
const u32 &getFacesCount() const { return facesCount; };
|
||||
|
||||
/** Indexes of vertices. Each 3 faces will give you vertices of next triangle. */
|
||||
u32 &getVertexFace(const u32 &i) const { return vertexFaces[i]; };
|
||||
|
||||
/** Indexes of texture coords. Each 3 faces will give you texture coords of next triangle. */
|
||||
u32 &getSTFace(const u32 &i) const { return stFaces[i]; };
|
||||
|
||||
/** Indexes of normal vectors used for lighting. Each 3 faces will give you normal vectors of next triangle. */
|
||||
u32 &getNormalFace(const u32 &i) const { return normalFaces[i]; };
|
||||
|
||||
/** Array of vertex faces. Size of getFacesCount() */
|
||||
u32 *getVertexFaces() const { return vertexFaces; };
|
||||
|
||||
/** Array of texture coords faces. Size of getFacesCount() */
|
||||
u32 *getSTFaces() const { return stFaces; };
|
||||
|
||||
/** Array of normal vector faces. Size of getFacesCount() */
|
||||
u32 *getNormalFaces() const { return normalFaces; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB).
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 *getBoundingBox() { return boundingBox; };
|
||||
|
||||
/**
|
||||
* Returns bounding box (AABB) vertex.
|
||||
* Total length: 8
|
||||
*/
|
||||
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setVertexFace(const u32 &t_index, const u32 &t_val) { vertexFaces[t_index] = t_val; }
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setSTFace(const u32 &t_index, const u32 &t_val) { stFaces[t_index] = t_val; }
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setNormalFace(const u32 &t_index, const u32 &t_val) { normalFaces[t_index] = t_val; }
|
||||
|
||||
/** Set material name. */
|
||||
void setName(char *t_val);
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
|
||||
const u8 &isNameSet() const { return _isNameSet; };
|
||||
const u8 &areFacesAllocated() const { return _areFacesAllocated; };
|
||||
|
||||
/** Set faces count and allocate memory. */
|
||||
void allocateFaces(const u32 &t_val);
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Calculates bounding box (AABB).
|
||||
* Called automatically in mesh frame class on data loading.
|
||||
*/
|
||||
void calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount);
|
||||
|
||||
/** True when mesh is in view frustum */
|
||||
u8 isInFrustum(Plane *t_frustumPlanes, const Vector3 &position);
|
||||
|
||||
private:
|
||||
Vector3 boundingBox[8];
|
||||
u32 facesCount, id;
|
||||
u32 *vertexFaces, *stFaces, *normalFaces;
|
||||
u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated;
|
||||
char *name;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_OBJECT3D_SPEC_
|
||||
#define _TYRA_OBJECT3D_SPEC_
|
||||
|
||||
#include "math/vector3.hpp"
|
||||
#include "./texture.hpp"
|
||||
#include <tamtypes.h>
|
||||
#include <draw_buffers.h>
|
||||
#include <draw_sampling.h>
|
||||
|
||||
/** Class which contain 3D object specification */
|
||||
class MeshSpec
|
||||
{
|
||||
|
||||
public:
|
||||
texbuffer_t textureBuffer;
|
||||
clutbuffer_t clut;
|
||||
lod_t lod;
|
||||
|
||||
MeshSpec();
|
||||
~MeshSpec();
|
||||
void allocateTextureBuffer(u16 t_width, u16 t_height);
|
||||
void deallocateTextureBuffer();
|
||||
void allocateMemory();
|
||||
void setupLodAndClut();
|
||||
Texture *textures;
|
||||
|
||||
private:
|
||||
u8 isTextureVRAMAllocated;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_MESH_TEXTURE_
|
||||
#define _TYRA_MESH_TEXTURE_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <draw_sampling.h>
|
||||
#include "./texture_wrap_settings.hpp"
|
||||
#include "./texture_link.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Class which contains texture data.
|
||||
* Textures are paired with meshes via addUsage(),
|
||||
* removeUsage() functions which use meshId and materialId.
|
||||
*/
|
||||
class MeshTexture
|
||||
{
|
||||
|
||||
public:
|
||||
MeshTexture();
|
||||
~MeshTexture();
|
||||
|
||||
// ----
|
||||
// Getters
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Auto generated unique Id.
|
||||
* Core role of this variable is to dont send
|
||||
* again texture in renderer, when last sent texture id
|
||||
* by renderer will be equal to this id.
|
||||
*/
|
||||
const u32 &getId() const { return id; };
|
||||
|
||||
const u8 &getWidth() const { return width; };
|
||||
|
||||
const u8 &getHeight() const { return height; };
|
||||
|
||||
u32 getTextureLinksCount() const { return static_cast<u32>(texLinks.size()); };
|
||||
|
||||
texwrap_t *getWrapSettings() { return &wrapSettings; };
|
||||
|
||||
/**
|
||||
* Returns always width * width * 3.
|
||||
* 3 because of RGB
|
||||
*/
|
||||
u32 getDataSize() const { return width * height * 3; };
|
||||
|
||||
/**
|
||||
* Texture data, used by renderer.
|
||||
* Array of size getDataSize().
|
||||
*/
|
||||
unsigned char *getData() const { return data; };
|
||||
|
||||
/**
|
||||
* Get texture name.
|
||||
* For "textures/abc.bmp" result will be: "abc"
|
||||
*/
|
||||
char *getName() const { return name; };
|
||||
|
||||
/** Array of texture links. Size of getTextureLinksCount() */
|
||||
const std::vector<TextureLink> &getTextureLinks() const { return texLinks; };
|
||||
|
||||
/**
|
||||
* Returns index of link.
|
||||
* -1 if not found.
|
||||
*/
|
||||
const s32 getIndexOfLink(const u32 &t_meshId, const u32 &t_materialId) const
|
||||
{
|
||||
for (u32 i = 0; i < texLinks.size(); i++)
|
||||
if (texLinks[i].materialId == t_materialId && texLinks[i].meshId == t_meshId)
|
||||
return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
/**
|
||||
* Set texture size and allocate texture data
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setSize(const u8 &t_width, const u8 &t_height);
|
||||
|
||||
/**
|
||||
* Do not call this method unless you know what you do.
|
||||
* Should be called by data loader.
|
||||
*/
|
||||
void setHeight(const u8 &t_val) { height = t_val; }
|
||||
|
||||
/**
|
||||
* Set texture name.
|
||||
* Should be the file name without extension
|
||||
*/
|
||||
void setData(const u32 &t_index, const unsigned char &t_val) { data[t_index] = t_val; }
|
||||
|
||||
/**
|
||||
* Set texture name.
|
||||
* Should be the file name without extension
|
||||
*/
|
||||
void setName(char *t_val);
|
||||
|
||||
/** Set texture wrapping */
|
||||
void setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical);
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
|
||||
/** Assign texture to mesh and mesh material */
|
||||
void addLink(const u32 &t_meshId, const u32 &t_materialId);
|
||||
|
||||
const u8 &isNameSet() const { return _isNameSet; };
|
||||
|
||||
const u8 &isSizeSet() const { return _isSizeSet; };
|
||||
|
||||
const u8 isLinkedWith(const u32 &t_meshId, const u32 &t_materialId) const
|
||||
{
|
||||
s32 index = getIndexOfLink(t_meshId, t_materialId);
|
||||
if (index != -1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
|
||||
void removeLink(const u32 &t_index) { texLinks.erase(texLinks.begin() + t_index); }
|
||||
|
||||
void removeLink(const u32 &t_meshId, const u32 &t_materialId)
|
||||
{
|
||||
s32 index = getIndexOfLink(t_meshId, t_materialId);
|
||||
if (index != -1)
|
||||
removeLink(index);
|
||||
else
|
||||
PRINT_ERR("Cant remove link, because it was not found!");
|
||||
}
|
||||
|
||||
private:
|
||||
void setDefaultWrapSettings();
|
||||
texwrap_t wrapSettings;
|
||||
char *name;
|
||||
std::vector<TextureLink> texLinks;
|
||||
u32 id;
|
||||
u8 width, height, _isNameSet, _isSizeSet;
|
||||
unsigned char *data;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_OBJ_MODEL_
|
||||
#define _TYRA_OBJ_MODEL_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <math3d.h>
|
||||
#include "math/vector3.hpp"
|
||||
|
||||
/** Class which have common types for all 3D objects */
|
||||
class ObjModel
|
||||
{
|
||||
|
||||
public:
|
||||
u32 verticesCount, coordinatesCount, normalsCount, facesCount;
|
||||
Vector3 *vertices __attribute__((aligned(16))),
|
||||
*coordinates __attribute__((aligned(16))),
|
||||
*normals __attribute__((aligned(16)));
|
||||
u32 *verticeFaces, *coordinateFaces, *normalFaces;
|
||||
|
||||
/** File name without extension */
|
||||
char *filename;
|
||||
|
||||
ObjModel(char *t_objFile);
|
||||
~ObjModel();
|
||||
u32 getDrawData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled);
|
||||
void allocateMemory();
|
||||
|
||||
private:
|
||||
void fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u32 t_getI, u32 t_setI);
|
||||
u8 isMemoryAllocated;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -8,19 +8,14 @@
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_TEXTURE_
|
||||
#define _TYRA_TEXTURE_
|
||||
#ifndef _TYRA_TEXTURE_USAGE_
|
||||
#define _TYRA_TEXTURE_USAGE_
|
||||
|
||||
#include <tamtypes.h>
|
||||
#include <draw_sampling.h>
|
||||
|
||||
struct Texture
|
||||
struct TextureLink
|
||||
{
|
||||
u32 id;
|
||||
unsigned char *data;
|
||||
texwrap_t wrapSettings;
|
||||
char *name;
|
||||
u8 width, height;
|
||||
u32 meshId, materialId;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_TEXTURE_WRAP_SETTINGS_
|
||||
#define _TYRA_TEXTURE_WRAP_SETTINGS_
|
||||
|
||||
enum WrapSettings
|
||||
{
|
||||
Repeat = 0,
|
||||
Clamp = 1,
|
||||
RegionClamp = 2,
|
||||
RegionRepeat = 3
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "../models/screen_settings.hpp"
|
||||
#include "../models/light_bulb.hpp"
|
||||
#include "../models/render_data.hpp"
|
||||
#include "../models/mesh_texture.hpp"
|
||||
|
||||
/** Class responsible for sending data packets via GIF (PATH3) */
|
||||
class GifSender
|
||||
@@ -32,11 +33,11 @@ public:
|
||||
~GifSender();
|
||||
|
||||
void initPacket(u8 context);
|
||||
void addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
void addObject(RenderData *t_renderData, Mesh *t_objects3D, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
|
||||
void addClear(zbuffer_t *t_zBuffer);
|
||||
void sendPacket();
|
||||
void sendClear(zbuffer_t *t_zBuffer);
|
||||
static void sendTexture(Texture &texture, texbuffer_t *t_texBuffer);
|
||||
static void sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer);
|
||||
|
||||
private:
|
||||
xyz_t *xyz;
|
||||
@@ -53,8 +54,8 @@ private:
|
||||
float halfScreenW, halfScreenH;
|
||||
MATRIX localWorld, localScreen, localLight;
|
||||
|
||||
u32 calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
void convertCalcs(u32 t_vertCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, u8 t_alpha);
|
||||
void calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
void convertCalcs(u32 t_vertCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color);
|
||||
void addCurrentCalcs(u32 &t_vertexCount);
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "../models/math/plane.hpp"
|
||||
#include "../models/screen_settings.hpp"
|
||||
#include "../models/render_data.hpp"
|
||||
#include "./texture_repository.hpp"
|
||||
|
||||
/** Class responsible for intializing draw env, textures and buffers */
|
||||
class Renderer
|
||||
@@ -55,15 +56,21 @@ public:
|
||||
|
||||
void endFrame(float fps);
|
||||
|
||||
TextureRepository *getTextureRepository() { return &textureRepo; };
|
||||
|
||||
private:
|
||||
void changeTexture(Mesh *t_mesh, u8 t_textureIndex);
|
||||
void changeTexture(Mesh *t_mesh, u32 t_materialId);
|
||||
u32 lastTextureId;
|
||||
texbuffer_t textureBuffer;
|
||||
u8 isTextureVRAMAllocated;
|
||||
void allocateTextureBuffer(u16 t_width, u16 t_height);
|
||||
void deallocateTextureBuffer();
|
||||
void flipBuffers();
|
||||
void beginFrameIfNeeded();
|
||||
u8 isFrameEmpty;
|
||||
Matrix perspective;
|
||||
RenderData renderData;
|
||||
|
||||
u32 lastTextureId;
|
||||
TextureRepository textureRepo;
|
||||
GifSender *gifSender;
|
||||
VifSender *vifSender;
|
||||
packet_t *flipPacket;
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TYRA_TEXTURE_REPOSITORY_
|
||||
#define _TYRA_TEXTURE_REPOSITORY_
|
||||
|
||||
#include <vector>
|
||||
#include <tamtypes.h>
|
||||
#include <draw_buffers.h>
|
||||
#include "../models/mesh.hpp"
|
||||
#include "../models/mesh_frame.hpp"
|
||||
#include "../loaders/bmp_loader.hpp"
|
||||
|
||||
/** Class responsible for intializing draw env, textures and buffers */
|
||||
class TextureRepository
|
||||
{
|
||||
|
||||
public:
|
||||
TextureRepository();
|
||||
~TextureRepository();
|
||||
|
||||
// ----
|
||||
// Getters
|
||||
// ----
|
||||
|
||||
/** Returns all repository textures. */
|
||||
std::vector<MeshTexture *> *getAll() { return &textures; }
|
||||
|
||||
u32 getTexturesCount() const { return static_cast<u32>(textures.size()); };
|
||||
|
||||
/**
|
||||
* Returns single texture.
|
||||
* NULL if not found.
|
||||
*/
|
||||
MeshTexture *getByMesh(const u32 &t_meshId, const u32 &t_materialId)
|
||||
{
|
||||
for (u32 i = 0; i < textures.size(); i++)
|
||||
if (textures[i]->isLinkedWith(t_meshId, t_materialId))
|
||||
return textures[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns single texture.
|
||||
* NULL if not found.
|
||||
*/
|
||||
MeshTexture *getByTextureId(const u32 &t_id) const
|
||||
{
|
||||
for (u32 i = 0; i < textures.size(); i++)
|
||||
if (t_id == textures[i]->getId())
|
||||
return textures[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns index of link.
|
||||
* -1 if not found.
|
||||
*/
|
||||
const s32 getIndexOf(const u32 &t_texId) const
|
||||
{
|
||||
for (u32 i = 0; i < textures.size(); i++)
|
||||
if (textures[i]->getId() == t_texId)
|
||||
return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// ----
|
||||
// Setters
|
||||
// ----
|
||||
|
||||
// ----
|
||||
// Other
|
||||
// ----
|
||||
|
||||
/** Add unlinked texture.
|
||||
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only!
|
||||
* @param t_subfolder Relative path. Ex.: "textures/"
|
||||
* @param t_name Filename without extension. Ex.: "water"
|
||||
*
|
||||
*/
|
||||
MeshTexture *add(char *t_subfolder, char *t_name);
|
||||
|
||||
/**
|
||||
* Add linked textures in given subpath for mesh material names.
|
||||
* NOTICE: BMP (RGB 888 24bit, without color information) is suppored only!
|
||||
* @param t_path Relative path where textures should be searched
|
||||
*/
|
||||
void addByMesh(char *t_path, Mesh &mesh);
|
||||
|
||||
/**
|
||||
* Remove texture from repository.
|
||||
* Texture is NOT destructed.
|
||||
*/
|
||||
void removeByIndex(const u32 &t_index) { textures.erase(textures.begin() + t_index); }
|
||||
|
||||
/**
|
||||
* Remove texture from repository.
|
||||
* Texture is NOT destructed.
|
||||
*/
|
||||
const void removeById(const u32 &t_texId)
|
||||
{
|
||||
s32 index = getIndexOf(t_texId);
|
||||
if (index != -1)
|
||||
removeByIndex(index);
|
||||
else
|
||||
PRINT_ERR("Cant remove texture, because it was not found!");
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<MeshTexture *> textures;
|
||||
BmpLoader loader;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -28,15 +28,15 @@ public:
|
||||
~VifSender();
|
||||
|
||||
// TODO refactor
|
||||
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, VECTOR *colors, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount);
|
||||
void drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
|
||||
void sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation);
|
||||
|
||||
private:
|
||||
void drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_coordinates, prim_t *t_prim);
|
||||
|
||||
void drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer);
|
||||
VU1 vu1; // TODO
|
||||
MATRIX localWorld, localScreen;
|
||||
VECTOR position, rotation;
|
||||
u32 vertCount;
|
||||
VU1 vu1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,22 @@
|
||||
#include <math3d.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class Debug
|
||||
{
|
||||
public:
|
||||
static void errTrap(char *t_text, char *t_file)
|
||||
{
|
||||
printf("\n");
|
||||
printf("====================================\n");
|
||||
printf("| ERROR: %s\n", t_text);
|
||||
printf("| File : %s\n", t_file);
|
||||
printf("====================================\n\n");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
#define PRINT_LOG(TEXT) printf("LOG: " TEXT " (" __FILE__ ")\n")
|
||||
#define PRINT_ERR(TEXT) printf("---\n--- ---\n--- --- --- ERR: " TEXT " (" __FILE__ ")\n--- ---\n---\n")
|
||||
#define PRINT_ERR(TEXT) Debug::errTrap(TEXT, __FILE__)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
class Vector3; // Forward definition
|
||||
|
||||
void manyVec3ToNative(VECTOR *t_result, Vector3 *t_vec, int t_amount, float t_fourthVal);
|
||||
void vec3ToNative(VECTOR t_result, Vector3 &t_vec, float t_fourthVal);
|
||||
void vec3ToNative(VECTOR t_result, const Vector3 &t_vec, float t_fourthVal);
|
||||
|
||||
class Math
|
||||
{
|
||||
|
||||
@@ -17,6 +17,8 @@ class String
|
||||
{
|
||||
|
||||
public:
|
||||
static char *createU32ToString(u32 a);
|
||||
static char *createWithLeadingZeros(char *a);
|
||||
static char *createCopy(char *source);
|
||||
static u32 getLength(char *a);
|
||||
static char *createConcatenated(char *a, char *b);
|
||||
|
||||
@@ -30,27 +30,28 @@ BmpLoader::~BmpLoader() {}
|
||||
* @param t_name Without extension. Example "skyfall2"
|
||||
* @param t_extension With dot and extension. Example ".BMP"
|
||||
*/
|
||||
void BmpLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
||||
void BmpLoader::load(MeshTexture &o_texture, char *t_subfolder, char *t_name, char *t_extension)
|
||||
{
|
||||
char *t_path_part = String::createConcatenated(t_subfolder, t_name);
|
||||
char *t_path = String::createConcatenated(t_path_part, t_extension);
|
||||
delete[] t_path_part;
|
||||
|
||||
FILE *file = fopen(t_path, "rb");
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
PRINT_ERR("Failed to load .bmp file!");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char header[54];
|
||||
fread(header, sizeof(unsigned char), 54, file);
|
||||
|
||||
u32 width = *(u32 *)&header[18];
|
||||
u32 height = *(u32 *)&header[22];
|
||||
o_texture.id = rand() % 100000;
|
||||
o_texture.width = width;
|
||||
o_texture.height = height;
|
||||
o_texture.data = new unsigned char[width * height * 3];
|
||||
o_texture.setSize(width, height);
|
||||
printf("BMPLoader - width: %d | height: %d\n", width, height);
|
||||
if (width > 128 || height > 128)
|
||||
PRINT_ERR("Given texture is big for PS2. Please strict to 128x128 max");
|
||||
|
||||
u64 rowPadded = (width * 3 + 3) & (~3);
|
||||
|
||||
@@ -68,12 +69,13 @@ void BmpLoader::load(Texture &o_texture, char *t_subfolder, char *t_name, char *
|
||||
data[j] = data[j + 2];
|
||||
data[j + 2] = tmp;
|
||||
|
||||
o_texture.data[x] = data[j];
|
||||
o_texture.data[x + 1] = data[j + 1];
|
||||
o_texture.data[x + 2] = data[j + 2];
|
||||
o_texture.setData(x, data[j]);
|
||||
o_texture.setData(x + 1, data[j + 1]);
|
||||
o_texture.setData(x + 2, data[j + 2]);
|
||||
x += 3;
|
||||
}
|
||||
}
|
||||
delete[] t_path;
|
||||
delete[] data;
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
+203
-159
@@ -34,7 +34,7 @@ DffLoader::~DffLoader() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void DffLoader::load(RwClump &o_clump, char *t_filename, float t_scale)
|
||||
void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||
{
|
||||
PRINT_LOG("Loading dff file");
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
@@ -42,87 +42,128 @@ void DffLoader::load(RwClump &o_clump, char *t_filename, float t_scale)
|
||||
PRINT_ERR("Failed to load .obj file!");
|
||||
fseek(file, 0L, SEEK_END);
|
||||
long fileSize = ftell(file);
|
||||
u8 *data = new u8[fileSize];
|
||||
u8 data[fileSize];
|
||||
rewind(file);
|
||||
fread(data, sizeof(u8), fileSize, file);
|
||||
fread(&data, sizeof(u8), fileSize, file);
|
||||
fclose(file);
|
||||
serialize(o_clump, data, t_scale);
|
||||
delete[] data;
|
||||
serialize(o_result, t_invertT, data, t_scale);
|
||||
o_result->calculateBoundingBoxes();
|
||||
PRINT_LOG("Dff file loaded!");
|
||||
}
|
||||
|
||||
void DffLoader::serialize(RwClump &t_clump, u8 *t_data, float t_scale)
|
||||
void DffLoader::serialize(MeshFrame *o_result, u8 t_invertT, u8 *t_data, float t_scale)
|
||||
{
|
||||
u32 ptrPos = 0;
|
||||
readSectionHeader(t_clump, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.data, t_data, ptrPos);
|
||||
readClumpData(t_clump.data, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.frameList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.frameList.data, t_data, ptrPos);
|
||||
readFrameListData(t_clump.frameList.data, t_data, ptrPos);
|
||||
|
||||
t_clump.frameList.extensions = new RwFrameListExtension[t_clump.frameList.data.frameCount];
|
||||
for (u32 i = 0; i < t_clump.frameList.data.frameCount; i++)
|
||||
{
|
||||
readSectionHeader(t_clump.frameList.extensions[i], t_data, ptrPos);
|
||||
ptrPos += t_clump.frameList.extensions[i].sectionSize;
|
||||
}
|
||||
// readSectionHeader(t_clump, t_data, ptrPos);
|
||||
// readSectionHeader(t_clump.data, t_data, ptrPos);
|
||||
// readClumpData(t_clump.data, t_data, ptrPos);
|
||||
for (u8 i = 0; i < 3 * 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
readSectionHeader(t_clump.geometryList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
|
||||
readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
|
||||
// readSectionHeader(t_clump.frameList, t_data, ptrPos);
|
||||
// readSectionHeader(t_clump.frameList.data, t_data, ptrPos);
|
||||
// readFrameListData(t_clump.frameList.data, t_data, ptrPos);
|
||||
// t_clump.frameList.extensions = new RwFrameListExtension[t_clump.frameList.data.frameCount];
|
||||
// for (u32 i = 0; i < t_clump.frameList.data.frameCount; i++)
|
||||
// {
|
||||
// readSectionHeader(t_clump.frameList.extensions[i], t_data, ptrPos);
|
||||
// ptrPos += t_clump.frameList.extensions[i].sectionSize;
|
||||
// }
|
||||
RwSectionHeader header1 = RwSectionHeader();
|
||||
readSectionHeader(header1, t_data, ptrPos);
|
||||
ptrPos += header1.sectionSize;
|
||||
|
||||
t_clump.geometryList.geometries = new RwGeometry[t_clump.geometryList.data.geometryCount];
|
||||
printf("Geometries:%d\n", t_clump.geometryList.data.geometryCount);
|
||||
for (u32 i = 0; i < t_clump.geometryList.data.geometryCount; i++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].data, t_data, ptrPos);
|
||||
readGeometryData(t_clump.geometryList.geometries[i].data, t_data, ptrPos, t_scale);
|
||||
// readSectionHeader(t_clump.geometryList, t_data, ptrPos);
|
||||
// readSectionHeader(t_clump.geometryList.data, t_data, ptrPos);
|
||||
for (u8 i = 0; i < 2 * 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
||||
readMaterialListData(t_clump.geometryList.geometries[i].materialList.data, t_data, ptrPos);
|
||||
// readGeometryListData(t_clump.geometryList.data, t_data, ptrPos);
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
u32 materialCount = t_clump.geometryList.geometries[i].materialList.data.materialCount;
|
||||
printf("Materials:%d\n", materialCount);
|
||||
// readSectionHeader(geometry, t_data, ptrPos);
|
||||
// readSectionHeader(geometry.data, t_data, ptrPos);
|
||||
for (size_t i = 0; i < 2 * 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
t_clump.geometryList.geometries[i].materialList.materials = new RwMaterial[materialCount];
|
||||
readGeometryData(o_result, t_invertT, t_data, ptrPos, t_scale);
|
||||
|
||||
// readSectionHeader(geometry.materialList, t_data, ptrPos);
|
||||
// readSectionHeader(geometry.materialList.data, t_data, ptrPos);
|
||||
for (size_t i = 0; i < 2 * 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
RwMaterialListData materialListData = RwMaterialListData();
|
||||
readMaterialListData(materialListData, t_data, ptrPos);
|
||||
u32 materialCount = materialListData.materialCount;
|
||||
|
||||
char **materialNames = new char *[materialCount];
|
||||
for (u32 j = 0; j < materialCount; j++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
||||
readMaterialData(t_clump.geometryList.geometries[i].materialList.materials[j].data, t_data, ptrPos);
|
||||
// readSectionHeader(geometry.materialList.materials[j], t_data, ptrPos);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
u32 textureCount = t_clump.geometryList.geometries[i].materialList.materials[j].data.textureCount;
|
||||
t_clump.geometryList.geometries[i].materialList.materials[j].textures = new RwTexture[textureCount];
|
||||
for (u32 k = 0; k < textureCount; k++)
|
||||
{
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k], t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
readTextureData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureName, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
readStringData(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
// RwMaterialData materialData = RwMaterialData();
|
||||
// readSectionHeader(materialData, t_data, ptrPos);
|
||||
// readMaterialData(materialData, t_data, ptrPos);
|
||||
RwSectionHeader header1 = RwSectionHeader();
|
||||
readSectionHeader(header1, t_data, ptrPos);
|
||||
ptrPos += header1.sectionSize;
|
||||
|
||||
// for (u32 k = 0; k < textureCount; k++)
|
||||
// {
|
||||
|
||||
// readSectionHeader(geometry.materialList.materials[j].textures[k], t_data, ptrPos);
|
||||
// readSectionHeader(geometry.materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
for (size_t i = 0; i < 2 * 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
// readTextureData(geometry.materialList.materials[j].textures[k].data, t_data, ptrPos);
|
||||
ptrPos += sizeof(u32);
|
||||
|
||||
RwSectionHeader header1b = RwSectionHeader();
|
||||
readSectionHeader(header1b, t_data, ptrPos);
|
||||
materialNames[j] = readString(t_data, ptrPos, header1b.sectionSize);
|
||||
|
||||
// readSectionHeader(geometry.materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
// readStringData(geometry.materialList.materials[j].textures[k].textureAlphaName, t_data, ptrPos);
|
||||
RwSectionHeader header2 = RwSectionHeader();
|
||||
readSectionHeader(header2, t_data, ptrPos);
|
||||
ptrPos += header2.sectionSize;
|
||||
|
||||
// The content of extension is Sky Mipmap Val
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].textures[k].extension.sectionSize;
|
||||
}
|
||||
// Probably always void extension
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].materialList.materials[j].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].materialList.materials[j].extension.sectionSize;
|
||||
}
|
||||
// For Bin Mesh aka Material split
|
||||
readSectionHeader(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
||||
readGeometryExtension(t_clump.geometryList.geometries[i].extension, t_data, ptrPos);
|
||||
ptrPos += t_clump.geometryList.geometries[i].extension.sectionSize;
|
||||
}
|
||||
// readSectionHeader(geometry.materialList.materials[j].textures[k].extension, t_data, ptrPos);
|
||||
RwSectionHeader header3 = RwSectionHeader();
|
||||
readSectionHeader(header3, t_data, ptrPos);
|
||||
ptrPos += header3.sectionSize;
|
||||
// }
|
||||
|
||||
readSectionHeader(t_clump.atomic, t_data, ptrPos);
|
||||
readSectionHeader(t_clump.atomic.data, t_data, ptrPos);
|
||||
ptrPos += t_clump.atomic.data.sectionSize;
|
||||
// Probably always void extension
|
||||
// readSectionHeader(geometry.materialList.materials[j].extension, t_data, ptrPos);
|
||||
RwSectionHeader header4 = RwSectionHeader();
|
||||
readSectionHeader(header4, t_data, ptrPos);
|
||||
ptrPos += header4.sectionSize;
|
||||
}
|
||||
// delete[] materialNames; // TODO
|
||||
|
||||
// For Bin Mesh aka Material split
|
||||
// readSectionHeader(geometry.extension, t_data, ptrPos);
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
ptrPos += sizeof(u32);
|
||||
readGeometryExtension(o_result, materialNames, t_data, ptrPos);
|
||||
|
||||
for (size_t i = 0; i < materialCount; i++)
|
||||
delete[] materialNames[i];
|
||||
|
||||
delete materialNames;
|
||||
|
||||
// ptrPos += geometry.extension.sectionSize;
|
||||
|
||||
// readSectionHeader(t_clump.atomic, t_data, ptrPos);
|
||||
// readSectionHeader(t_clump.atomic.data, t_data, ptrPos);
|
||||
// ptrPos += t_clump.atomic.data.sectionSize;
|
||||
}
|
||||
|
||||
void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_ptrPos)
|
||||
@@ -136,139 +177,151 @@ void DffLoader::readSectionHeader(RwSectionHeader &t_sh, u8 *t_buffer, u32 &t_pt
|
||||
|
||||
void DffLoader::readFrameListData(RwFrameListData &t_frd, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
printf("Frame count:%d\n", t_frd.frameCount);
|
||||
t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
|
||||
// t_frd.frameCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// printf("Frame count:%d\n", t_frd.frameCount);
|
||||
// t_frd.frameInformation = new RwFrameListChunk[t_frd.frameCount];
|
||||
|
||||
for (u32 i = 0; i < t_frd.frameCount; i++)
|
||||
{
|
||||
t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
|
||||
for (u32 j = 0; j < t_frd.ROT_MAT_DIM; j++)
|
||||
t_frd.frameInformation[i].rotationalMatrix[j] = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// for (u32 i = 0; i < t_frd.frameCount; i++)
|
||||
// {
|
||||
// t_frd.frameInformation[i].rotationalMatrix = new float[t_frd.ROT_MAT_DIM];
|
||||
// for (u32 j = 0; j < t_frd.ROT_MAT_DIM; j++)
|
||||
// t_frd.frameInformation[i].rotationalMatrix[j] = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_frd.frameInformation[i].coordinatesOffsetX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].coordinatesOffsetY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].coordinatesOffsetZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i]
|
||||
.parentFrame = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_frd.frameInformation[i].unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
// t_frd.frameInformation[i].coordinatesOffsetX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_frd.frameInformation[i].coordinatesOffsetY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_frd.frameInformation[i].coordinatesOffsetZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_frd.frameInformation[i]
|
||||
// .parentFrame = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_frd.frameInformation[i].unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// }
|
||||
}
|
||||
|
||||
void DffLoader::readClumpData(RwClumpData &t_cd, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_cd.objectCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_cd.unk1 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_cd.unk2 = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_cd.objectCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_cd.unk1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_cd.unk2 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryListData(RwGeometryListData &t_gld, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_gld.geometryCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gld.geometryCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryExtension(RwGeometryExtension &t_ge, u8 *t_buffer, u32 &t_ptrPos)
|
||||
void DffLoader::readGeometryExtension(MeshFrame *o_frame, char **materialNames, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
for (u8 i = 0; i < 3; i++)
|
||||
t_ptrPos += sizeof(u32);
|
||||
|
||||
t_ge.materialSplit.header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
RwMaterialSplitHeader header = RwMaterialSplitHeader();
|
||||
header.triangleStrip = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.splitCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.faceCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_ge.materialSplit.splitInformation = new RwGeometryListInfoChunk[t_ge.materialSplit.header.splitCount];
|
||||
for (u32 i = 0; i < t_ge.materialSplit.header.splitCount; i++)
|
||||
o_frame->allocateMaterials(header.splitCount);
|
||||
for (u32 i = 0; i < header.splitCount; i++)
|
||||
{
|
||||
t_ge.materialSplit.splitInformation[i].faceIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_ge.materialSplit.splitInformation[i].materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_ge.materialSplit.splitInformation[i].vertexInformation = new RwGeometryListVertexInfoChunk[t_ge.materialSplit.splitInformation[i].faceIndex];
|
||||
for (u32 j = 0; j < t_ge.materialSplit.splitInformation[i].faceIndex; j++)
|
||||
t_ge.materialSplit.splitInformation[i].vertexInformation[j].vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
u32 facesCount = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
u32 materialIndex = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
o_frame->getMaterial(i).allocateFaces(facesCount);
|
||||
o_frame->getMaterial(i).setName(materialNames[materialIndex]);
|
||||
for (u32 j = 0; j < facesCount; j++)
|
||||
{
|
||||
u32 vertex1 = readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
o_frame->getMaterial(i).setVertexFace(j, vertex1);
|
||||
o_frame->getMaterial(i).setNormalFace(j, vertex1);
|
||||
o_frame->getMaterial(i).setSTFace(j, vertex1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readGeometryData(RwGeometryData &t_gd, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
|
||||
void DffLoader::readGeometryData(MeshFrame *o_frame, u8 t_invertT, u8 *t_buffer, u32 &t_ptrPos, float t_scale)
|
||||
{
|
||||
t_gd.dataHeader.flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.unk1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.triangleCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.vertexCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.dataHeader.morphTargetCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
Vector3 tempVec = Vector3();
|
||||
Point tempPoint = Point();
|
||||
|
||||
RwGeometryDataHeader header;
|
||||
header.flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.unk1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.triangleCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.vertexCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
header.morphTargetCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
if (false)
|
||||
{ // version equals 4099 according to old documentation, disabled as for now
|
||||
t_gd.lightingHeader.ambient = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.lightingHeader.diffuse = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.lightingHeader.specular = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
readDwordFromArrayLE(t_buffer, t_ptrPos); // ambient
|
||||
readDwordFromArrayLE(t_buffer, t_ptrPos); // diffuse
|
||||
readDwordFromArrayLE(t_buffer, t_ptrPos); // specular
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_PRELIT)
|
||||
if (header.flags & rwOBJECT_VERTEX_PRELIT)
|
||||
for (u32 i = 0; i < header.vertexCount; i++)
|
||||
{
|
||||
t_gd.colorInformation = new RwGeometryDataColorInformationChunk[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
readByteFromArrayLE(t_buffer, t_ptrPos); // r
|
||||
readByteFromArrayLE(t_buffer, t_ptrPos); // g
|
||||
readByteFromArrayLE(t_buffer, t_ptrPos); // b
|
||||
readByteFromArrayLE(t_buffer, t_ptrPos); // a
|
||||
}
|
||||
|
||||
if (header.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||
{
|
||||
t_gd.colorInformation[i].red = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].green = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].blue = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.colorInformation[i].alpha = readByteFromArrayLE(t_buffer, t_ptrPos);
|
||||
o_frame->allocateSTs(header.vertexCount);
|
||||
for (u32 i = 0; i < header.vertexCount; i++)
|
||||
{
|
||||
float u = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
float v = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
tempPoint.set(u, v);
|
||||
if (t_invertT)
|
||||
tempPoint.y = 1.0F - tempPoint.y;
|
||||
o_frame->setST(i, tempPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_TEXTURED)
|
||||
for (u32 i = 0; i < header.triangleCount; i++)
|
||||
{
|
||||
t_gd.textureMappingInformation = new RwGeometryDataTextureMappingInformationChunk[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.textureMappingInformation[i].u = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.textureMappingInformation[i].v = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
readWordFromArrayLE(t_buffer, t_ptrPos); // vert2
|
||||
readWordFromArrayLE(t_buffer, t_ptrPos); // vert1
|
||||
readWordFromArrayLE(t_buffer, t_ptrPos); // flags
|
||||
readWordFromArrayLE(t_buffer, t_ptrPos); // vert3
|
||||
}
|
||||
|
||||
t_gd.faceInformation = new RwGeometryDataFaceInformation[t_gd.dataHeader.triangleCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.triangleCount; i++)
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
t_ptrPos += sizeof(u32);
|
||||
// t_gd.nonameInfo.boundingSphereX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gd.nonameInfo.boundingSphereY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gd.nonameInfo.boundingSphereZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gd.nonameInfo.boundingSphereR = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gd.nonameInfo.hasPosition = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_gd.nonameInfo.hasNormals = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
o_frame->allocateVertices(header.vertexCount);
|
||||
for (u32 i = 0; i < header.vertexCount; i++)
|
||||
{
|
||||
t_gd.faceInformation[i].vertex2 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].vertex1 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].flags = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.faceInformation[i].vertex3 = readWordFromArrayLE(t_buffer, t_ptrPos);
|
||||
float x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
float y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
float z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
tempVec.set(x, y, z);
|
||||
o_frame->setVertex(i, tempVec);
|
||||
}
|
||||
|
||||
t_gd.nonameInfo.boundingSphereX = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereY = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereZ = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.boundingSphereR = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.hasPosition = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.nonameInfo.hasNormals = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
|
||||
t_gd.vertexInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
o_frame->allocateNormals(header.vertexCount);
|
||||
for (u32 i = 0; i < header.vertexCount; i++)
|
||||
{
|
||||
t_gd.vertexInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
t_gd.vertexInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
t_gd.vertexInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos) * t_scale;
|
||||
}
|
||||
|
||||
if (t_gd.dataHeader.flags & rwOBJECT_VERTEX_NORMALS)
|
||||
{
|
||||
t_gd.normalInformation = new Vector3[t_gd.dataHeader.vertexCount];
|
||||
for (u32 i = 0; i < t_gd.dataHeader.vertexCount; i++)
|
||||
{
|
||||
t_gd.normalInformation[i].x = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.normalInformation[i].y = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_gd.normalInformation[i].z = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
float x = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
float y = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
float z = readFloatFromArrayLE(t_buffer, t_ptrPos);
|
||||
tempVec.set(x, y, z);
|
||||
o_frame->setNormal(i, tempVec);
|
||||
}
|
||||
}
|
||||
|
||||
void DffLoader::readMaterialListData(RwMaterialListData &t_mld, u8 *t_buffer, u32 &t_ptrPos)
|
||||
{
|
||||
t_mld.materialCount = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
t_mld.arrayOfUnks = new u32[t_mld.materialCount];
|
||||
// t_mld.arrayOfUnks = new u32[t_mld.materialCount];
|
||||
for (u32 i = 0; i < t_mld.materialCount; i++)
|
||||
{
|
||||
t_mld.arrayOfUnks[i] = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
// t_mld.arrayOfUnks[i] = DffLoader::readDwordFromArrayLE(t_buffer, t_ptrPos);
|
||||
}
|
||||
|
||||
void DffLoader::readMaterialData(RwMaterialData &t_md, u8 *t_buffer, u32 &t_ptrPos)
|
||||
@@ -325,15 +378,6 @@ float DffLoader::readFloatFromArrayLE(u8 *t_buffer, u32 &t_ptrPos)
|
||||
return res;
|
||||
}
|
||||
|
||||
u8 *DffLoader::readData(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
||||
{
|
||||
u8 *arr = new u8[t_dataSize];
|
||||
for (u32 i = 0; i < t_dataSize; ++i)
|
||||
arr[i] = t_buffer[i + t_ptrPos];
|
||||
t_ptrPos += t_dataSize;
|
||||
return arr;
|
||||
}
|
||||
|
||||
char *DffLoader::readString(u8 *t_buffer, u32 &t_ptrPos, u32 t_dataSize)
|
||||
{
|
||||
u32 strLength = String::getLength((char *)&t_buffer[t_ptrPos]);
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
|
||||
#include "../include/loaders/md2_loader.hpp"
|
||||
|
||||
#include "../include/utils/string.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/loaders/anorms.hpp"
|
||||
#include "../include/models/math/vector3.hpp"
|
||||
#include "../include/models/math/point.hpp"
|
||||
#include <string.h>
|
||||
#include <iosfwd>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
@@ -28,101 +29,124 @@ MD2Loader::~MD2Loader() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Load, parse .obj file and load data into given MeshSpec */
|
||||
void MD2Loader::load(MD2Model *o_result, char *t_filename, float t_scale)
|
||||
int MEM_fread(char *buf, size_t size, size_t n, const FILE *f)
|
||||
{
|
||||
memcpy(buf, f, size * n);
|
||||
f += size * n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandro: Possible PS2SDK bug here?
|
||||
* When I wanted to fopen() -> fread() -> allocate frames memory (vertices etc) -> fclose() = I had in about 10x errors in console
|
||||
* When I did fopen() -> fread() -> fclose() -> allocate frames memory = I had no errors 🤨
|
||||
* It looks like memory allocation during fopen()-fread()-fclose() is broken.
|
||||
*/
|
||||
MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWithoutExtension, float t_scale, u8 t_invertT)
|
||||
{
|
||||
PRINT_LOG("Loading new MD2 file");
|
||||
md2_t header; // md2 header
|
||||
char *buffer; // buffer storing frame data
|
||||
char *part1 = String::createConcatenated(t_subpath, t_nameWithoutExtension);
|
||||
char *finalPath = String::createConcatenated(part1, ".md2"); // "folder/object.md2"
|
||||
delete[] part1;
|
||||
md2_t header;
|
||||
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
FILE *file = fopen(finalPath, "rb");
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
PRINT_ERR("Failed to load .md2 file!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fread((char *)&header, sizeof(md2_t), 1, file);
|
||||
|
||||
if ((header.ident != MD2_IDENT) && (header.version != MD2_VERSION))
|
||||
{
|
||||
PRINT_ERR("This MD2 file was not in correct format!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
o_result->framesCount = header.num_frames;
|
||||
o_result->verticesPerFrameCount = header.num_xyz;
|
||||
o_result->coordinatesCount = header.num_st;
|
||||
o_result->trianglesCount = header.num_tris;
|
||||
u32 framesCount = header.num_frames;
|
||||
u32 vertexCount = header.num_xyz;
|
||||
u32 stsCount = header.num_st;
|
||||
u32 trianglesCount = header.num_tris;
|
||||
|
||||
printf("MD2 - Frames: %d\n", header.num_frames);
|
||||
printf("MD2 - Vert: %d\n", header.num_xyz);
|
||||
printf("MD2 - Tris: %d\n", header.num_tris);
|
||||
printf("MD2 - STs: %d\n", header.num_st);
|
||||
printf("MD2 - Skin W:%d H: %d\n", header.skinwidth, header.skinheight);
|
||||
|
||||
o_result->allocateMemory();
|
||||
|
||||
buffer = new char[o_result->framesCount * header.framesize];
|
||||
char framesBuffer[framesCount * header.framesize];
|
||||
fseek(file, header.ofs_frames, SEEK_SET);
|
||||
fread((char *)buffer, o_result->framesCount * header.framesize, 1, file);
|
||||
fread(&framesBuffer, framesCount * header.framesize, 1, file);
|
||||
|
||||
frame_t *frame; // temporary vars
|
||||
Vector3 *ptrVerts;
|
||||
u32 *ptrNormals;
|
||||
// vertex array initialization
|
||||
for (u32 j = 0; j < o_result->framesCount; j++)
|
||||
{
|
||||
frame = (frame_t *)&buffer[header.framesize * j];
|
||||
ptrVerts = &o_result->vertices[o_result->verticesPerFrameCount * j];
|
||||
ptrNormals = &o_result->normalIndexes[o_result->verticesPerFrameCount * j];
|
||||
|
||||
for (u32 i = 0; i < o_result->verticesPerFrameCount; i++)
|
||||
{
|
||||
ptrVerts[i].x = ((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale;
|
||||
ptrVerts[i].y = ((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale;
|
||||
ptrVerts[i].z = ((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale;
|
||||
|
||||
ptrNormals[i] = frame->verts[i].lightnormalindex;
|
||||
}
|
||||
if (j == o_result->framesCount - 1)
|
||||
printf("Last frame, last vert: X:%f Y:%f Z:%f\n",
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].x,
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].y,
|
||||
ptrVerts[o_result->verticesPerFrameCount - 1].z);
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
buffer = new char[o_result->coordinatesCount * sizeof(texCoord_t)];
|
||||
char stsBuffer[stsCount * sizeof(texCoord_t)];
|
||||
fseek(file, header.ofs_st, SEEK_SET);
|
||||
fread((char *)buffer, o_result->coordinatesCount * sizeof(texCoord_t), 1, file);
|
||||
fread(&stsBuffer, stsCount * sizeof(texCoord_t), 1, file);
|
||||
|
||||
texCoord_t *texCoord;
|
||||
for (u32 i = 0; i < o_result->coordinatesCount; i++)
|
||||
{
|
||||
texCoord = (texCoord_t *)&buffer[sizeof(texCoord_t) * i];
|
||||
o_result->coordinates[i].x = (float)texCoord->s / header.skinwidth;
|
||||
o_result->coordinates[i].y = (float)texCoord->t / header.skinheight;
|
||||
}
|
||||
delete[] buffer;
|
||||
|
||||
printf("Last tex coord(%d): S:%f T:%f\n",
|
||||
o_result->coordinatesCount,
|
||||
o_result->coordinates[o_result->coordinatesCount - 1].x,
|
||||
o_result->coordinates[o_result->coordinatesCount - 1].y);
|
||||
|
||||
buffer = new char[o_result->trianglesCount * sizeof(triangle_t)];
|
||||
char trianglesBuffer[trianglesCount * sizeof(triangle_t)];
|
||||
fseek(file, header.ofs_tris, SEEK_SET);
|
||||
fread((char *)buffer, o_result->trianglesCount * sizeof(triangle_t), 1, file);
|
||||
|
||||
triangle_t *triangle; // temporary var
|
||||
// vertex array initialization
|
||||
for (u32 i = 0; i < o_result->trianglesCount; i++)
|
||||
{
|
||||
triangle = (triangle_t *)&buffer[sizeof(triangle_t) * i];
|
||||
for (u8 j = 0; j < 3; j++)
|
||||
{
|
||||
o_result->triangles[i].verticeIndexes[j] = triangle->index_xyz[j];
|
||||
o_result->triangles[i].coordIndexes[j] = triangle->index_st[j];
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
fread(&trianglesBuffer, trianglesCount * sizeof(triangle_t), 1, file);
|
||||
|
||||
fclose(file);
|
||||
|
||||
MeshFrame *resultFrames = new MeshFrame[26];
|
||||
|
||||
frame_t *frame;
|
||||
Vector3 tempVec = Vector3();
|
||||
for (u32 j = 0; j < framesCount; j++)
|
||||
{
|
||||
resultFrames[j].allocateVertices(vertexCount);
|
||||
resultFrames[j].allocateNormals(vertexCount); // can be optimized
|
||||
resultFrames[j].allocateSTs(stsCount);
|
||||
resultFrames[j].allocateMaterials(1);
|
||||
resultFrames[j].getMaterial(0).allocateFaces(trianglesCount * 3);
|
||||
resultFrames[j].getMaterial(0).setName(t_nameWithoutExtension);
|
||||
frame = (frame_t *)&framesBuffer[header.framesize * j];
|
||||
for (u32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
tempVec.set(
|
||||
((frame->verts[i].v[0] * frame->scale[0]) + frame->translate[0]) * t_scale,
|
||||
((frame->verts[i].v[1] * frame->scale[1]) + frame->translate[1]) * t_scale,
|
||||
((frame->verts[i].v[2] * frame->scale[2]) + frame->translate[2]) * t_scale);
|
||||
resultFrames[j].setVertex(i, tempVec);
|
||||
|
||||
tempVec.set(
|
||||
ANORMS[frame->verts[i].lightnormalindex][0],
|
||||
ANORMS[frame->verts[i].lightnormalindex][1],
|
||||
ANORMS[frame->verts[i].lightnormalindex][2]);
|
||||
resultFrames[j].setNormal(i, tempVec);
|
||||
}
|
||||
}
|
||||
|
||||
Point tempPoint = Point();
|
||||
texCoord_t *texCoord;
|
||||
for (u32 i = 0; i < stsCount; i++)
|
||||
{
|
||||
texCoord = (texCoord_t *)&stsBuffer[sizeof(texCoord_t) * i];
|
||||
tempPoint.set(
|
||||
(float)texCoord->s / header.skinwidth,
|
||||
(float)texCoord->t / header.skinheight);
|
||||
if (t_invertT)
|
||||
tempPoint.y = 1.0F - tempPoint.y;
|
||||
for (u32 j = 0; j < framesCount; j++)
|
||||
resultFrames[j].setST(i, tempPoint);
|
||||
}
|
||||
|
||||
triangle_t *triangle;
|
||||
for (u32 i = 0; i < trianglesCount; i++)
|
||||
{
|
||||
triangle = (triangle_t *)&trianglesBuffer[sizeof(triangle_t) * i];
|
||||
for (u8 j = 0; j < 3; j++)
|
||||
{
|
||||
for (u32 x = 0; x < framesCount; x++)
|
||||
{
|
||||
resultFrames[x].getMaterial(0).setVertexFace((i * 3) + j, triangle->index_xyz[j]);
|
||||
resultFrames[x].getMaterial(0).setSTFace((i * 3) + j, triangle->index_st[j]);
|
||||
resultFrames[x].getMaterial(0).setNormalFace((i * 3) + j, triangle->index_xyz[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRINT_LOG("MD2 file loaded!");
|
||||
delete[] finalPath;
|
||||
o_framesCount = framesCount;
|
||||
for (u32 i = 0; i < framesCount; i++)
|
||||
resultFrames[i].calculateBoundingBoxes();
|
||||
return resultFrames;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../include/loaders/obj_loader.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <string.h>
|
||||
|
||||
// ----
|
||||
@@ -25,15 +26,15 @@ ObjLoader::~ObjLoader() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Load, parse .obj file and load data into given MeshSpec */
|
||||
void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
||||
void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_invertT)
|
||||
{
|
||||
FILE *file = fopen(t_filename, "rb");
|
||||
if (file == NULL)
|
||||
PRINT_ERR("Failed to load .obj file!");
|
||||
setObjDataQuantities(file, o_result);
|
||||
o_result->allocateMemory();
|
||||
u32 verticesI = 0, cordsI = 0, normalsI = 0, i = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
|
||||
allocateObjMemory(file, o_result);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
u32 verticesI = 0, cordsI = 0, normalsI = 0, faceI = 0, vertexIndex[3], coordIndex[3], normalIndex[3];
|
||||
s16 materialsI = -1;
|
||||
while (1)
|
||||
{
|
||||
char lineHeader[128]; // read the first word of the line
|
||||
@@ -44,19 +45,28 @@ void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
o_result->vertices[verticesI++] = vector * t_scale;
|
||||
o_result->setVertex(verticesI++, vector * t_scale);
|
||||
}
|
||||
else if (strcmp(lineHeader, "vt") == 0)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f\n", &vector.x, &vector.y);
|
||||
o_result->coordinates[cordsI++] = vector;
|
||||
Point point = Point();
|
||||
fscanf(file, "%f %f\n", &point.x, &point.y);
|
||||
if (t_invertT)
|
||||
point.y = 1.0F - point.y;
|
||||
o_result->setST(cordsI++, point);
|
||||
}
|
||||
else if (strcmp(lineHeader, "vn") == 0)
|
||||
{
|
||||
Vector3 vector = Vector3();
|
||||
fscanf(file, "%f %f %f\n", &vector.x, &vector.y, &vector.z);
|
||||
o_result->normals[normalsI++] = vector;
|
||||
o_result->setNormal(normalsI++, vector);
|
||||
}
|
||||
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||
{
|
||||
char temp[30];
|
||||
fscanf(file, "%s\n", temp);
|
||||
o_result->getMaterial(++materialsI).setName(temp);
|
||||
faceI = 0;
|
||||
}
|
||||
else if (strcmp(lineHeader, "f") == 0)
|
||||
{
|
||||
@@ -68,36 +78,36 @@ void ObjLoader::load(ObjModel *o_result, char *t_filename, float t_scale)
|
||||
PRINT_ERR(".obj can't be read by this simple parser. Try exporting with other options");
|
||||
else
|
||||
{
|
||||
o_result->verticeFaces[i] = vertexIndex[0] - 1;
|
||||
o_result->verticeFaces[i + 1] = vertexIndex[1] - 1;
|
||||
o_result->verticeFaces[i + 2] = vertexIndex[2] - 1;
|
||||
o_result->getMaterial(materialsI).setVertexFace(faceI, vertexIndex[0] - 1);
|
||||
o_result->getMaterial(materialsI).setVertexFace(faceI + 1, vertexIndex[1] - 1);
|
||||
o_result->getMaterial(materialsI).setVertexFace(faceI + 2, vertexIndex[2] - 1);
|
||||
|
||||
o_result->coordinateFaces[i] = coordIndex[0] - 1;
|
||||
o_result->coordinateFaces[i + 1] = coordIndex[1] - 1;
|
||||
o_result->coordinateFaces[i + 2] = coordIndex[2] - 1;
|
||||
o_result->getMaterial(materialsI).setSTFace(faceI, coordIndex[0] - 1);
|
||||
o_result->getMaterial(materialsI).setSTFace(faceI + 1, coordIndex[1] - 1);
|
||||
o_result->getMaterial(materialsI).setSTFace(faceI + 2, coordIndex[2] - 1);
|
||||
|
||||
o_result->normalFaces[i] = normalIndex[0] - 1;
|
||||
o_result->normalFaces[i + 1] = normalIndex[1] - 1;
|
||||
o_result->normalFaces[i + 2] = normalIndex[2] - 1;
|
||||
i += 3;
|
||||
o_result->getMaterial(materialsI).setNormalFace(faceI, normalIndex[0] - 1);
|
||||
o_result->getMaterial(materialsI).setNormalFace(faceI + 1, normalIndex[1] - 1);
|
||||
o_result->getMaterial(materialsI).setNormalFace(faceI + 2, normalIndex[2] - 1);
|
||||
faceI += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
o_result->calculateBoundingBoxes();
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file
|
||||
* When done, file read offset is resetted to the begginning of file
|
||||
*/
|
||||
void ObjLoader::setObjDataQuantities(FILE *t_file, ObjModel *o_result)
|
||||
/** Calculate how many vertices(v), coordinates(vt), normals(vn) and faces(f) have .obj file */
|
||||
void ObjLoader::allocateObjMemory(FILE *t_file, MeshFrame *o_result)
|
||||
{
|
||||
o_result->verticesCount = 0;
|
||||
o_result->coordinatesCount = 0;
|
||||
o_result->normalsCount = 0;
|
||||
o_result->facesCount = 0;
|
||||
u32 vertexCount = 0;
|
||||
u32 stsCount = 0;
|
||||
u32 normalsCount = 0;
|
||||
u32 materialsCount = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
char lineHeader[128];
|
||||
@@ -105,16 +115,47 @@ void ObjLoader::setObjDataQuantities(FILE *t_file, ObjModel *o_result)
|
||||
if (res != EOF)
|
||||
{
|
||||
if (strcmp(lineHeader, "v") == 0)
|
||||
o_result->verticesCount += 1;
|
||||
vertexCount += 1;
|
||||
else if (strcmp(lineHeader, "vt") == 0)
|
||||
o_result->coordinatesCount += 1;
|
||||
stsCount += 1;
|
||||
else if (strcmp(lineHeader, "vn") == 0)
|
||||
o_result->normalsCount += 1;
|
||||
else if (strcmp(lineHeader, "f") == 0)
|
||||
o_result->facesCount += 3;
|
||||
normalsCount += 1;
|
||||
else if (strcmp(lineHeader, "usemtl") == 0)
|
||||
materialsCount += 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
o_result->allocateVertices(vertexCount);
|
||||
o_result->allocateNormals(normalsCount);
|
||||
o_result->allocateSTs(stsCount);
|
||||
o_result->allocateMaterials(materialsCount);
|
||||
|
||||
s16 currentMatI = -1;
|
||||
|
||||
fseek(t_file, 0, SEEK_SET);
|
||||
u32 facesCounter = 0;
|
||||
while (1)
|
||||
{
|
||||
char lineHeader[128];
|
||||
int res = fscanf(t_file, "%s", lineHeader);
|
||||
if (res != EOF)
|
||||
{
|
||||
if (strcmp(lineHeader, "usemtl") == 0)
|
||||
{
|
||||
if (currentMatI >= 0) // Skip -1
|
||||
o_result->getMaterial(currentMatI).allocateFaces(facesCounter);
|
||||
currentMatI++;
|
||||
}
|
||||
else if (strcmp(lineHeader, "f") == 0)
|
||||
facesCounter += 3;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
o_result->getMaterial(currentMatI).allocateFaces(facesCounter); // Allocate last one
|
||||
|
||||
// o_result->isMemoryAllocated = true;
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/dff_model.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
DffModel::DffModel() {}
|
||||
|
||||
DffModel::~DffModel() {}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 DffModel::getDrawData(u32 splitIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 result = 0;
|
||||
for (u32 i = 0; i < clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].faceIndex; i++)
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, 0,
|
||||
clump.geometryList.geometries[0].extension.materialSplit.splitInformation[splitIndex].vertexInformation[i].vertex1,
|
||||
result++);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DffModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u8 geometry, u32 t_getI, u32 t_setI)
|
||||
{
|
||||
o_vertices[t_setI][0] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].x;
|
||||
o_vertices[t_setI][1] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].y;
|
||||
o_vertices[t_setI][2] = clump.geometryList.geometries[geometry].data.vertexInformation[t_getI].z;
|
||||
o_vertices[t_setI][3] = 1.0F;
|
||||
|
||||
o_normals[t_setI][0] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].x;
|
||||
o_normals[t_setI][1] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].y;
|
||||
o_normals[t_setI][2] = clump.geometryList.geometries[geometry].data.normalInformation[t_getI].z;
|
||||
o_normals[t_setI][3] = 1.0F;
|
||||
|
||||
o_coordinates[t_setI][0] = clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].u;
|
||||
o_coordinates[t_setI][1] = 1.0F - clump.geometryList.geometries[geometry].data.textureMappingInformation[t_getI].v;
|
||||
o_coordinates[t_setI][2] = 1.0F;
|
||||
o_coordinates[t_setI][3] = 1.0F;
|
||||
|
||||
o_colors[t_setI][0] = 1.0F;
|
||||
o_colors[t_setI][1] = 1.0F;
|
||||
o_colors[t_setI][2] = 1.0F;
|
||||
o_colors[t_setI][3] = 1.0F;
|
||||
}
|
||||
@@ -17,10 +17,17 @@
|
||||
// ----
|
||||
|
||||
/** Create by specifying values */
|
||||
Point::Point(float x, float y)
|
||||
Point::Point(const float &t_x, const float &t_y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
}
|
||||
|
||||
/** Create with other point values */
|
||||
Point::Point(const Point &v)
|
||||
{
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
}
|
||||
|
||||
/** Create empty point */
|
||||
@@ -36,10 +43,16 @@ Point::~Point() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Point::set(float x, float y)
|
||||
void Point::set(const float &t_x, const float &t_y)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
}
|
||||
|
||||
void Point::set(const Point &v)
|
||||
{
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
}
|
||||
|
||||
void Point::print()
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
// ----
|
||||
|
||||
/** Create by specifying 3 points */
|
||||
Vector3::Vector3(float x, float y, float z)
|
||||
Vector3::Vector3(float t_x, float t_y, float t_z)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
x = t_x;
|
||||
y = t_y;
|
||||
z = t_z;
|
||||
}
|
||||
|
||||
/** Create with another vector values */
|
||||
@@ -33,7 +33,7 @@ Vector3::Vector3(const Vector3 &another)
|
||||
z = another.z;
|
||||
}
|
||||
|
||||
void Vector3::setByLerp(const Vector3 &v1, const Vector3 &v2, const float t_interp)
|
||||
void Vector3::setByLerp(const Vector3 &v1, const Vector3 &v2, const float &t_interp, const float &t_scale)
|
||||
{
|
||||
asm volatile(
|
||||
"lqc2 vf4, 0x0(%1) \n\t" // vf4 = v1
|
||||
@@ -47,6 +47,9 @@ void Vector3::setByLerp(const Vector3 &v1, const Vector3 &v2, const float t_inte
|
||||
:
|
||||
: "r"(&this->xyz), "r"(&v1.xyz), "r"(&v2.xyz), "f"(t_interp)
|
||||
: "$8");
|
||||
x *= t_scale;
|
||||
y *= t_scale;
|
||||
z *= t_scale;
|
||||
}
|
||||
|
||||
/** Create empty vector */
|
||||
@@ -245,14 +248,14 @@ float Vector3::innerProduct(Vector3 &v)
|
||||
// return (x * v.x + y * v.y + z * v.z);
|
||||
}
|
||||
|
||||
void Vector3::set(float x, float y, float z)
|
||||
void Vector3::set(const float &x, const float &y, const float &z)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
void Vector3::set(Vector3 &v)
|
||||
void Vector3::set(const Vector3 &v)
|
||||
{
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/md2_model.hpp"
|
||||
|
||||
#include "../include/utils/anorms.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MD2Model::MD2Model(char *t_md2File)
|
||||
{
|
||||
filename = String::createWithoutExtension(t_md2File);
|
||||
|
||||
verticesPerFrameCount = 0;
|
||||
coordinatesCount = 0;
|
||||
trianglesCount = 0;
|
||||
framesCount = 0;
|
||||
|
||||
animState.startFrame = 0;
|
||||
animState.endFrame = 0;
|
||||
animState.interpolation = 0.0F;
|
||||
animState.animType = 0;
|
||||
animState.currentFrame = 0;
|
||||
animState.nextFrame = 0;
|
||||
animState.speed = 0.1F;
|
||||
|
||||
vertices = 0;
|
||||
coordinates = 0;
|
||||
normalIndexes = 0;
|
||||
triangles = 0;
|
||||
}
|
||||
|
||||
MD2Model::~MD2Model()
|
||||
{
|
||||
delete[] vertices;
|
||||
delete[] normalIndexes;
|
||||
delete[] coordinates;
|
||||
delete[] triangles;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 MD2Model::getCurrentFrameData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 i = 0;
|
||||
animState.interpolation += animState.speed;
|
||||
if (animState.interpolation >= 1.0F)
|
||||
{
|
||||
animState.interpolation = 0.0F;
|
||||
animState.currentFrame = animState.nextFrame;
|
||||
if (++animState.nextFrame > animState.endFrame)
|
||||
animState.nextFrame = animState.startFrame;
|
||||
}
|
||||
for (u32 iTri = 0; iTri < trianglesCount; iTri++)
|
||||
{
|
||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
||||
{
|
||||
const u32 CURR_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.currentFrame);
|
||||
|
||||
if (animState.startFrame == animState.endFrame)
|
||||
{
|
||||
calc3Vectors[iVert].x = vertices[CURR_VERTICE].x * t_scale;
|
||||
calc3Vectors[iVert].y = vertices[CURR_VERTICE].y * t_scale;
|
||||
calc3Vectors[iVert].z = vertices[CURR_VERTICE].z * t_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
const u32 NEXT_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.nextFrame);
|
||||
calcVector.setByLerp(vertices[CURR_VERTICE], vertices[NEXT_VERTICE], animState.interpolation);
|
||||
calc3Vectors[iVert].x = calcVector.x * t_scale;
|
||||
calc3Vectors[iVert].y = calcVector.y * t_scale;
|
||||
calc3Vectors[iVert].z = calcVector.z * t_scale;
|
||||
}
|
||||
}
|
||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[2], &calc3Vectors[1], &calc3Vectors[0]) == 0)
|
||||
for (u32 iVert = 0; iVert < 3; iVert++)
|
||||
{
|
||||
const u32 CURR_VERTICE =
|
||||
triangles[iTri].verticeIndexes[iVert] +
|
||||
(verticesPerFrameCount * animState.currentFrame);
|
||||
|
||||
const u32 CURR_COORD = triangles[iTri].coordIndexes[iVert];
|
||||
|
||||
o_vertices[i][0] = calc3Vectors[iVert].x;
|
||||
o_vertices[i][1] = calc3Vectors[iVert].y;
|
||||
o_vertices[i][2] = calc3Vectors[iVert].z;
|
||||
o_vertices[i][3] = 1.0F;
|
||||
|
||||
o_normals[i][0] = ANORMS[normalIndexes[CURR_VERTICE]][0];
|
||||
o_normals[i][1] = ANORMS[normalIndexes[CURR_VERTICE]][1];
|
||||
o_normals[i][2] = ANORMS[normalIndexes[CURR_VERTICE]][2];
|
||||
o_normals[i][3] = 1.0F;
|
||||
|
||||
o_coordinates[i][0] = coordinates[CURR_COORD].x;
|
||||
o_coordinates[i][1] = 1.0F - coordinates[CURR_COORD].y;
|
||||
o_coordinates[i][2] = 1.0F;
|
||||
o_coordinates[i][3] = 1.0F;
|
||||
|
||||
o_colors[i][0] = 1.0F;
|
||||
o_colors[i][1] = 1.0F;
|
||||
o_colors[i][2] = 1.0F;
|
||||
o_colors[i][3] = 1.0F;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void MD2Model::allocateMemory()
|
||||
{
|
||||
vertices = new Vector3[verticesPerFrameCount * framesCount];
|
||||
normalIndexes = new u32[verticesPerFrameCount * framesCount];
|
||||
coordinates = new Point[coordinatesCount];
|
||||
triangles = new MD2Triangle[trianglesCount];
|
||||
}
|
||||
+196
-237
@@ -9,13 +9,14 @@
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh.hpp"
|
||||
|
||||
#include "../include/loaders/obj_loader.hpp"
|
||||
#include "../include/loaders/md2_loader.hpp"
|
||||
#include "../include/loaders/dff_loader.hpp"
|
||||
#include "../include/loaders/bmp_loader.hpp"
|
||||
#include "../include/models/mesh_texture.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
@@ -23,262 +24,225 @@
|
||||
|
||||
Mesh::Mesh()
|
||||
{
|
||||
id = rand() % 1000000;
|
||||
shouldBeFrustumCulled = true;
|
||||
shouldBeBackfaceCulled = false;
|
||||
shouldBeLighted = false;
|
||||
isMd2Loaded = false;
|
||||
isObjLoaded = false;
|
||||
isDffLoaded = false;
|
||||
isSpecInitialized = false;
|
||||
_isMother = false;
|
||||
scale = 1.0F;
|
||||
framesCount = 0;
|
||||
animState.startFrame = 0;
|
||||
animState.endFrame = 0;
|
||||
animState.interpolation = 0.0F;
|
||||
animState.animType = 0;
|
||||
animState.currentFrame = 0;
|
||||
animState.stayFrame = 0;
|
||||
animState.isStayFrameSet = false;
|
||||
animState.nextFrame = 0;
|
||||
animState.speed = 0.1F;
|
||||
setDefaultColor();
|
||||
setDefaultLODAndClut();
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
delete md2;
|
||||
if (isObjLoaded)
|
||||
delete obj;
|
||||
if (isDffLoaded)
|
||||
delete dff;
|
||||
if (_isMother)
|
||||
delete[] frames;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, Vector3 &t_initPos, float t_scale)
|
||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u8 &t_invertT)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
DffLoader loader = DffLoader();
|
||||
dff = new DffModel();
|
||||
char *dffPath = String::createConcatenated(t_subfolder, t_dffFile);
|
||||
loader.load(dff->clump, dffPath, t_scale);
|
||||
delete[] dffPath;
|
||||
position = t_initPos;
|
||||
setVerticesReference(
|
||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
||||
setDefaultColor();
|
||||
isDffLoaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
}
|
||||
|
||||
void Mesh::setDff(Vector3 &t_initPos, DffModel *t_dffModel, MeshSpec *t_spec)
|
||||
{
|
||||
position = t_initPos;
|
||||
spec = t_spec;
|
||||
isSpecInitialized = 1;
|
||||
dff = t_dffModel;
|
||||
setVerticesReference(
|
||||
dff->clump.geometryList.geometries[0].data.dataHeader.vertexCount,
|
||||
dff->clump.geometryList.geometries[0].data.vertexInformation);
|
||||
setDefaultColor();
|
||||
isDffLoaded = true;
|
||||
}
|
||||
|
||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, Vector3 &t_initPos, float t_scale)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
ObjLoader loader = ObjLoader();
|
||||
obj = new ObjModel(t_objFile);
|
||||
char *objPath = String::createConcatenated(t_subfolder, t_objFile);
|
||||
loader.load(obj, objPath, t_scale);
|
||||
delete[] objPath;
|
||||
position = t_initPos;
|
||||
setVerticesReference(obj->facesCount, obj->vertices);
|
||||
setDefaultColor();
|
||||
isObjLoaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
framesCount = 1;
|
||||
frames = new MeshFrame[framesCount];
|
||||
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
|
||||
char *finalPath = String::createConcatenated(part1, ".obj"); // "folder/object.obj"
|
||||
loader.load(&frames[0], finalPath, t_scale, t_invertT);
|
||||
delete[] part1;
|
||||
delete[] finalPath;
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
void Mesh::setObj(Vector3 &t_initPos, ObjModel *t_objModel, MeshSpec *t_spec)
|
||||
void Mesh::loadObj(char *t_subfolder, char *t_objFile, const float &t_scale, const u32 &t_framesCount, const u8 &t_invertT)
|
||||
{
|
||||
position = t_initPos;
|
||||
spec = t_spec;
|
||||
isSpecInitialized = true;
|
||||
obj = t_objModel;
|
||||
setVerticesReference(obj->facesCount, obj->vertices);
|
||||
setDefaultColor();
|
||||
isObjLoaded = true;
|
||||
}
|
||||
|
||||
void Mesh::createSpecIfNotCreated()
|
||||
{
|
||||
if (!isSpecInitialized)
|
||||
{
|
||||
isSpecInitialized = true;
|
||||
spec = new MeshSpec();
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::setAnimSpeed(float t_value)
|
||||
{
|
||||
if (isMd2Loaded == 1)
|
||||
md2->animState.speed = t_value;
|
||||
else
|
||||
PRINT_ERR("Animation speed set is not possible, because no md2 3D model was loaded!");
|
||||
}
|
||||
|
||||
void Mesh::setVerticesReference(u32 t_verticesCount, Vector3 *t_verticesRef)
|
||||
{
|
||||
verticesCount = t_verticesCount;
|
||||
vertices = t_verticesRef;
|
||||
computeBoundingBox();
|
||||
}
|
||||
|
||||
u32 Mesh::getVertexCount()
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
return md2->trianglesCount * 3;
|
||||
else if (isObjLoaded)
|
||||
return obj->facesCount;
|
||||
else if (isDffLoaded)
|
||||
return dff->clump.geometryList.geometries[0].data.dataHeader.triangleCount * 3;
|
||||
if (t_framesCount == 0)
|
||||
PRINT_ERR("Frames count cannot be 0!");
|
||||
else if (t_framesCount == 1)
|
||||
loadObj(t_subfolder, t_objFile, t_scale, t_invertT);
|
||||
else
|
||||
{
|
||||
PRINT_ERR("Can't get vertex count, because no 3D model was loaded!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::setDefaultWrapSettings(texwrap_t &t_wrapSettings)
|
||||
{
|
||||
t_wrapSettings.horizontal = WRAP_REPEAT;
|
||||
t_wrapSettings.vertical = WRAP_REPEAT;
|
||||
t_wrapSettings.maxu = 0;
|
||||
t_wrapSettings.maxv = 0;
|
||||
t_wrapSettings.minu = 0;
|
||||
t_wrapSettings.minv = 0;
|
||||
}
|
||||
|
||||
void Mesh::loadTextures(char *t_subfolder, char *t_extension)
|
||||
{
|
||||
BmpLoader bmpLoader = BmpLoader();
|
||||
if (isMd2Loaded || isObjLoaded)
|
||||
ObjLoader loader = ObjLoader();
|
||||
framesCount = t_framesCount;
|
||||
frames = new MeshFrame[framesCount];
|
||||
char *part1 = String::createConcatenated(t_subfolder, t_objFile); // "folder/object"
|
||||
char *part2 = String::createConcatenated(part1, "_"); // "folder/object_"
|
||||
for (u32 i = 0; i < framesCount; i++)
|
||||
{
|
||||
spec->textures = new Texture[1];
|
||||
if (isMd2Loaded)
|
||||
bmpLoader.load(spec->textures[0], t_subfolder, md2->filename, t_extension);
|
||||
if (isObjLoaded)
|
||||
bmpLoader.load(spec->textures[0], t_subfolder, obj->filename, t_extension);
|
||||
setDefaultWrapSettings(spec->textures[0].wrapSettings);
|
||||
char *part3 = String::createU32ToString(i + 1); // 0 -> "1"
|
||||
char *part4 = String::createWithLeadingZeros(part3); // "000001"
|
||||
char *part5 = String::createConcatenated(part2, part4); // "folder/object_000001"
|
||||
char *finalPath = String::createConcatenated(part5, ".obj"); // "folder/object_000001.obj"
|
||||
loader.load(&frames[i], finalPath, t_scale, t_invertT);
|
||||
delete[] part3;
|
||||
delete[] part4;
|
||||
delete[] part5;
|
||||
delete[] finalPath;
|
||||
}
|
||||
else if (isDffLoaded)
|
||||
{
|
||||
spec->textures = new Texture[dff->clump.geometryList.geometries[0].materialList.data.materialCount];
|
||||
for (u8 i = 0; i < dff->clump.geometryList.geometries[0].materialList.data.materialCount; i++)
|
||||
for (u8 j = 0; j < dff->clump.geometryList.geometries[0].materialList.materials[i].data.textureCount; j++)
|
||||
{
|
||||
bmpLoader.load(spec->textures[i], t_subfolder, dff->clump.geometryList.geometries[0].materialList.materials[i].textures[j].textureName.text, t_extension);
|
||||
setDefaultWrapSettings(spec->textures[i].wrapSettings);
|
||||
delete[] part2;
|
||||
delete[] part1;
|
||||
_isMother = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
PRINT_ERR("Can't load textures, because no 3D model was loaded!");
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
u32 Mesh::getDrawData(u32 splitIndex, VECTOR *t_vertices, VECTOR *t_normals, VECTOR *t_coordinates, VECTOR *t_colors, Vector3 &t_cameraPos)
|
||||
void Mesh::loadDff(char *t_subfolder, char *t_dffFile, const float &t_scale, const u8 &t_invertT)
|
||||
{
|
||||
if (isMd2Loaded)
|
||||
return md2->getCurrentFrameData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
else if (isObjLoaded)
|
||||
return obj->getDrawData(t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
else if (isDffLoaded)
|
||||
return dff->getDrawData(splitIndex, t_vertices, t_normals, t_coordinates, t_colors, t_cameraPos, scale, shouldBeBackfaceCulled);
|
||||
PRINT_ERR("Can't get draw data, because no 3D model was loaded!");
|
||||
return 0;
|
||||
DffLoader loader = DffLoader();
|
||||
char *part1 = String::createConcatenated(t_subfolder, t_dffFile);
|
||||
char *dffPath = String::createConcatenated(part1, ".dff");
|
||||
framesCount = 1;
|
||||
frames = new MeshFrame[1];
|
||||
loader.load(frames, dffPath, t_scale, t_invertT);
|
||||
delete[] part1;
|
||||
delete[] dffPath;
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
/** Set object position and specification */
|
||||
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, Vector3 &t_initPos, float t_scale)
|
||||
void Mesh::loadMD2(char *t_subfolder, char *t_md2File, const float &t_scale, const u8 &t_invertT)
|
||||
{
|
||||
createSpecIfNotCreated();
|
||||
md2 = new MD2Model(t_md2File);
|
||||
MD2Loader loader = MD2Loader();
|
||||
position = t_initPos;
|
||||
char *md2Path = String::createConcatenated(t_subfolder, t_md2File);
|
||||
loader.load(md2, md2Path, t_scale);
|
||||
delete[] md2Path;
|
||||
setVerticesReference(md2->verticesPerFrameCount * md2->framesCount, md2->vertices);
|
||||
setDefaultColor();
|
||||
isMd2Loaded = true;
|
||||
loadTextures(t_subfolder, ".bmp");
|
||||
spec->allocateTextureBuffer(spec->textures[0].width, spec->textures[0].height); // wtf?
|
||||
frames = loader.load(framesCount, t_subfolder, t_md2File, t_scale, t_invertT);
|
||||
_isMother = true;
|
||||
}
|
||||
|
||||
/** Set's default object color + no transparency */
|
||||
void Mesh::setDefaultColor()
|
||||
void Mesh::loadFrom(const Mesh &t_mesh)
|
||||
{
|
||||
color.r = 0x80;
|
||||
color.g = 0x80;
|
||||
color.b = 0x80;
|
||||
color.a = 0x80;
|
||||
color.q = 1.0F;
|
||||
frames = t_mesh.frames;
|
||||
framesCount = t_mesh.framesCount;
|
||||
}
|
||||
|
||||
/** Calculates minimum and maximum X, Y, Z of this 3D objects vertices + current position */
|
||||
void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max)
|
||||
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame)
|
||||
{
|
||||
Vector3 calc = Vector3();
|
||||
u8 isInitialized = 0;
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
if (framesCount > 1)
|
||||
{
|
||||
getFarthestVertex(&calc, i);
|
||||
if (isInitialized == 0)
|
||||
{
|
||||
isInitialized = 1;
|
||||
t_min->set(calc);
|
||||
t_max->set(calc);
|
||||
}
|
||||
|
||||
if (t_min->x > calc.x)
|
||||
t_min->x = calc.x;
|
||||
if (calc.x > t_max->x)
|
||||
t_max->x = calc.x;
|
||||
|
||||
if (t_min->y > calc.y)
|
||||
t_min->y = calc.y;
|
||||
if (calc.y > t_max->y)
|
||||
t_max->y = calc.y;
|
||||
|
||||
if (t_min->z > calc.z)
|
||||
t_min->z = calc.z;
|
||||
if (calc.z > t_max->z)
|
||||
t_max->z = calc.z;
|
||||
if (t_endFrame >= framesCount)
|
||||
PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||
animState.startFrame = t_startFrame;
|
||||
animState.endFrame = t_endFrame;
|
||||
if (animState.currentFrame == t_startFrame)
|
||||
animState.nextFrame = t_endFrame;
|
||||
else
|
||||
animState.nextFrame = t_startFrame;
|
||||
}
|
||||
else if (framesCount == 0)
|
||||
PRINT_ERR("Cant play animation, because no mesh data was loaded!");
|
||||
else if (framesCount == 1)
|
||||
PRINT_ERR("Cant play animation, because this mesh have only one frame.");
|
||||
}
|
||||
|
||||
void Mesh::playAnimation(u32 t_startFrame, u32 t_endFrame)
|
||||
void Mesh::playAnimation(const u32 &t_startFrame, const u32 &t_endFrame, const u32 &t_stayFrame)
|
||||
{
|
||||
if (isMd2Loaded == 1)
|
||||
if (framesCount > 1)
|
||||
{
|
||||
md2->animState.startFrame = t_startFrame;
|
||||
md2->animState.endFrame = t_endFrame;
|
||||
if (t_endFrame >= framesCount)
|
||||
PRINT_ERR("End frame value is too high. Valid range: (0, getFramesCount()-1)");
|
||||
animState.startFrame = t_startFrame;
|
||||
animState.endFrame = t_endFrame;
|
||||
animState.isStayFrameSet = true;
|
||||
animState.stayFrame = t_stayFrame;
|
||||
animState.nextFrame = t_startFrame;
|
||||
}
|
||||
else if (framesCount == 0)
|
||||
PRINT_ERR("Cant play animation, because no mesh data was loaded!");
|
||||
else if (framesCount == 1)
|
||||
PRINT_ERR("Cant play animation, because this mesh have only one frame.");
|
||||
}
|
||||
|
||||
void Mesh::animate()
|
||||
{
|
||||
animState.interpolation += animState.speed;
|
||||
if (animState.interpolation >= 1.0F)
|
||||
{
|
||||
animState.interpolation = 0.0F;
|
||||
animState.currentFrame = animState.nextFrame;
|
||||
if (++animState.nextFrame > animState.endFrame)
|
||||
{
|
||||
if (animState.isStayFrameSet)
|
||||
{
|
||||
animState.isStayFrameSet = false;
|
||||
animState.nextFrame = animState.stayFrame;
|
||||
animState.startFrame = animState.stayFrame;
|
||||
animState.endFrame = animState.stayFrame;
|
||||
}
|
||||
else
|
||||
PRINT_ERR("Animation is only supported in MD2 format!");
|
||||
animState.nextFrame = animState.startFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns next farthest vertex of 3D object
|
||||
* @param offset Max 8 (because, box have 8 corners)
|
||||
*/
|
||||
void Mesh::getFarthestVertex(Vector3 *o_result, int t_offset)
|
||||
u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, Vector3 &t_cameraPos)
|
||||
{
|
||||
o_result->x = boxVertices[t_offset].x + position.x;
|
||||
o_result->y = boxVertices[t_offset].y + position.y;
|
||||
o_result->z = boxVertices[t_offset].z + position.z;
|
||||
u32 addedFaces = 0;
|
||||
#define CURR_FRAME frames[animState.currentFrame]
|
||||
#define NEXT_FRAME frames[animState.nextFrame]
|
||||
MeshMaterial *material = &CURR_FRAME.getMaterial(t_materialIndex); // cache
|
||||
Vector3 *verts = CURR_FRAME.getVertices(); // cache
|
||||
Vector3 *nextVerts = NEXT_FRAME.getVertices(); // cache
|
||||
Point *sts = CURR_FRAME.getSTs(); // cache
|
||||
Vector3 *normals = CURR_FRAME.getNormals(); // cache
|
||||
#define CURR_VERT verts[material->getVertexFace(matI + vertI)]
|
||||
#define CURR_ST sts[material->getSTFace(matI + vertI)]
|
||||
#define CURR_NORMAL normals[material->getNormalFace(matI + vertI)]
|
||||
#define NEXT_VERT nextVerts[material->getVertexFace(matI + vertI)]
|
||||
|
||||
for (u32 matI = 0; matI < material->getFacesCount(); matI += 3)
|
||||
{
|
||||
for (u32 vertI = 0; vertI < 3; vertI++)
|
||||
if (animState.currentFrame != animState.nextFrame)
|
||||
calc3Vectors[vertI].setByLerp(CURR_VERT, NEXT_VERT, animState.interpolation, scale);
|
||||
|
||||
if (!shouldBeBackfaceCulled ||
|
||||
Vector3::shouldBeBackfaceCulled(&t_cameraPos, &calc3Vectors[0], &calc3Vectors[1], &calc3Vectors[2]))
|
||||
|
||||
for (u32 vertI = 0; vertI < 3; vertI++)
|
||||
{
|
||||
|
||||
if (animState.currentFrame == animState.nextFrame)
|
||||
{
|
||||
o_vertices[addedFaces][0] = CURR_VERT.x;
|
||||
o_vertices[addedFaces][1] = CURR_VERT.y;
|
||||
o_vertices[addedFaces][2] = CURR_VERT.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
o_vertices[addedFaces][0] = calc3Vectors[vertI].x;
|
||||
o_vertices[addedFaces][1] = calc3Vectors[vertI].y;
|
||||
o_vertices[addedFaces][2] = calc3Vectors[vertI].z;
|
||||
}
|
||||
o_vertices[addedFaces][3] = 1.0F;
|
||||
|
||||
o_normals[addedFaces][0] = CURR_NORMAL.x;
|
||||
o_normals[addedFaces][1] = CURR_NORMAL.y;
|
||||
o_normals[addedFaces][2] = CURR_NORMAL.z;
|
||||
o_normals[addedFaces][3] = 1.0F;
|
||||
|
||||
o_coordinates[addedFaces][0] = CURR_ST.x;
|
||||
o_coordinates[addedFaces][1] = CURR_ST.y;
|
||||
o_coordinates[addedFaces][2] = 1.0F;
|
||||
o_coordinates[addedFaces++][3] = 1.0F;
|
||||
}
|
||||
}
|
||||
return addedFaces;
|
||||
}
|
||||
|
||||
/** Check if box is visible in view frustum */
|
||||
u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||
{
|
||||
Vector3 boxCalcTemp;
|
||||
int boxResult = 1, boxIn = 0, boxOut = 0;
|
||||
|
||||
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||
Vector3 *currentBoundingBox = getCurrentBoundingBox();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
boxOut = 0;
|
||||
@@ -288,7 +252,10 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||
// both inside and out of the frustum
|
||||
for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||
{
|
||||
getFarthestVertex(&boxCalcTemp, y);
|
||||
boxCalcTemp.set(
|
||||
currentBoundingBox[y].x + position.x,
|
||||
currentBoundingBox[y].y + position.y,
|
||||
currentBoundingBox[y].z + position.z);
|
||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||
boxOut++;
|
||||
else
|
||||
@@ -303,37 +270,29 @@ u8 Mesh::isInFrustum(Plane *t_frustumPlanes)
|
||||
return boxResult;
|
||||
}
|
||||
|
||||
/** Compute 8 farthest corners for intersection check */
|
||||
void Mesh::computeBoundingBox()
|
||||
/** Set's default object color + no transparency */
|
||||
void Mesh::setDefaultColor()
|
||||
{
|
||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||
lowX = hiX = vertices[0].x;
|
||||
lowY = hiY = vertices[0].y;
|
||||
lowZ = hiZ = vertices[0].z;
|
||||
for (u32 i = 0; i < verticesCount; i++)
|
||||
{
|
||||
if (lowX > vertices[i].x)
|
||||
lowX = vertices[i].x;
|
||||
if (hiX < vertices[i].x)
|
||||
hiX = vertices[i].x;
|
||||
|
||||
if (lowY > vertices[i].y)
|
||||
lowY = vertices[i].y;
|
||||
if (hiY < vertices[i].y)
|
||||
hiY = vertices[i].y;
|
||||
|
||||
if (lowZ > vertices[i].z)
|
||||
lowZ = vertices[i].z;
|
||||
if (hiZ < vertices[i].z)
|
||||
hiZ = vertices[i].z;
|
||||
}
|
||||
boxVertices[0].set(lowX, lowY, lowZ);
|
||||
boxVertices[1].set(lowX, lowY, hiZ);
|
||||
boxVertices[2].set(lowX, hiY, lowZ);
|
||||
boxVertices[3].set(lowX, hiY, hiZ);
|
||||
|
||||
boxVertices[4].set(hiX, lowY, lowZ);
|
||||
boxVertices[5].set(hiX, lowY, hiZ);
|
||||
boxVertices[6].set(hiX, hiY, lowZ);
|
||||
boxVertices[7].set(hiX, hiY, hiZ);
|
||||
color.r = 0x80;
|
||||
color.g = 0x80;
|
||||
color.b = 0x80;
|
||||
color.a = 0x80;
|
||||
color.q = 1.0F;
|
||||
}
|
||||
|
||||
/** Sets texture level of details settings and CLUT settings */
|
||||
void Mesh::setDefaultLODAndClut()
|
||||
{
|
||||
lod.calculation = LOD_USE_K;
|
||||
lod.max_level = 0;
|
||||
lod.mag_filter = LOD_MAG_NEAREST;
|
||||
lod.min_filter = LOD_MIN_NEAREST;
|
||||
lod.l = 0;
|
||||
lod.k = 0.0F;
|
||||
|
||||
clut.storage_mode = CLUT_STORAGE_MODE1;
|
||||
clut.start = 0;
|
||||
clut.psm = 0;
|
||||
clut.load_method = CLUT_NO_LOAD;
|
||||
clut.address = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_frame.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MeshFrame::MeshFrame()
|
||||
{
|
||||
vertexCount = 0;
|
||||
stsCount = 0;
|
||||
normalsCount = 0;
|
||||
materialsCount = 0;
|
||||
_areSTsAllocated = false;
|
||||
_areVerticesAllocated = false;
|
||||
_areNormalsAllocated = false;
|
||||
_areMaterialsAllocated = false;
|
||||
}
|
||||
|
||||
MeshFrame::~MeshFrame()
|
||||
{
|
||||
if (_areSTsAllocated)
|
||||
delete[] sts;
|
||||
if (_areVerticesAllocated)
|
||||
delete[] vertices;
|
||||
if (_areNormalsAllocated)
|
||||
delete[] normals;
|
||||
if (_areMaterialsAllocated)
|
||||
delete[] materials;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void MeshFrame::allocateSTs(const u32 &t_val)
|
||||
{
|
||||
if (_areSTsAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't allocate STs, because were already set!");
|
||||
return;
|
||||
}
|
||||
stsCount = t_val;
|
||||
sts = new Point[t_val];
|
||||
_areSTsAllocated = true;
|
||||
}
|
||||
|
||||
void MeshFrame::allocateVertices(const u32 &t_val)
|
||||
{
|
||||
if (_areVerticesAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't allocate vertices, because were already set!");
|
||||
return;
|
||||
}
|
||||
vertexCount = t_val;
|
||||
vertices = new Vector3[t_val];
|
||||
_areVerticesAllocated = true;
|
||||
}
|
||||
|
||||
void MeshFrame::allocateNormals(const u32 &t_val)
|
||||
{
|
||||
if (_areNormalsAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't allocate normals, because were already set!");
|
||||
return;
|
||||
}
|
||||
normalsCount = t_val;
|
||||
normals = new Vector3[t_val];
|
||||
_areNormalsAllocated = true;
|
||||
}
|
||||
|
||||
void MeshFrame::allocateMaterials(const u32 &t_val)
|
||||
{
|
||||
if (_areMaterialsAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't allocate materials, because were already set!");
|
||||
return;
|
||||
}
|
||||
materialsCount = t_val;
|
||||
materials = new MeshMaterial[t_val];
|
||||
_areMaterialsAllocated = true;
|
||||
}
|
||||
|
||||
void MeshFrame::calculateBoundingBoxes()
|
||||
{
|
||||
if (!_areVerticesAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't calculate bounding box, because vertices were not allocated!");
|
||||
return;
|
||||
}
|
||||
for (u32 i = 0; i < materialsCount; i++)
|
||||
materials->calculateBoundingBox(vertices, vertexCount);
|
||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||
lowX = hiX = vertices[0].x;
|
||||
lowY = hiY = vertices[0].y;
|
||||
lowZ = hiZ = vertices[0].z;
|
||||
for (u32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
if (lowX > vertices[i].x)
|
||||
lowX = vertices[i].x;
|
||||
if (hiX < vertices[i].x)
|
||||
hiX = vertices[i].x;
|
||||
|
||||
if (lowY > vertices[i].y)
|
||||
lowY = vertices[i].y;
|
||||
if (hiY < vertices[i].y)
|
||||
hiY = vertices[i].y;
|
||||
|
||||
if (lowZ > vertices[i].z)
|
||||
lowZ = vertices[i].z;
|
||||
if (hiZ < vertices[i].z)
|
||||
hiZ = vertices[i].z;
|
||||
}
|
||||
boundingBox[0].set(lowX, lowY, lowZ);
|
||||
boundingBox[1].set(lowX, lowY, hiZ);
|
||||
boundingBox[2].set(lowX, hiY, lowZ);
|
||||
boundingBox[3].set(lowX, hiY, hiZ);
|
||||
|
||||
boundingBox[4].set(hiX, lowY, lowZ);
|
||||
boundingBox[5].set(hiX, lowY, hiZ);
|
||||
boundingBox[6].set(hiX, hiY, lowZ);
|
||||
boundingBox[7].set(hiX, hiY, hiZ);
|
||||
_isBoundingBoxCalculated = true;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_material.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MeshMaterial::MeshMaterial()
|
||||
{
|
||||
id = rand() % 1000000;
|
||||
facesCount = 0;
|
||||
_isNameSet = false;
|
||||
_areFacesAllocated = false;
|
||||
_isBoundingBoxCalculated = false;
|
||||
}
|
||||
|
||||
MeshMaterial::~MeshMaterial()
|
||||
{
|
||||
if (_areFacesAllocated)
|
||||
{
|
||||
delete[] vertexFaces;
|
||||
delete[] stFaces;
|
||||
delete[] normalFaces;
|
||||
}
|
||||
if (_isNameSet)
|
||||
delete[] name;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void MeshMaterial::allocateFaces(const u32 &t_val)
|
||||
{
|
||||
if (_areFacesAllocated)
|
||||
{
|
||||
PRINT_ERR("Can't allocate faces, because were already set!");
|
||||
return;
|
||||
}
|
||||
facesCount = t_val;
|
||||
stFaces = new u32[t_val];
|
||||
normalFaces = new u32[t_val];
|
||||
vertexFaces = new u32[t_val];
|
||||
_areFacesAllocated = true;
|
||||
}
|
||||
|
||||
void MeshMaterial::setName(char *t_val)
|
||||
{
|
||||
if (_isNameSet)
|
||||
{
|
||||
PRINT_ERR("Can't set name, because was already set!");
|
||||
return;
|
||||
}
|
||||
name = String::createCopy(t_val);
|
||||
_isNameSet = true;
|
||||
}
|
||||
|
||||
u8 MeshMaterial::isInFrustum(Plane *t_frustumPlanes, const Vector3 &position)
|
||||
{
|
||||
Vector3 boxCalcTemp;
|
||||
u8 boxResult = 1, boxIn = 0, boxOut = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
boxOut = 0;
|
||||
boxIn = 0;
|
||||
// for each corner of the box do ...
|
||||
// get out of the cycle as soon as a box as corners
|
||||
// both inside and out of the frustum
|
||||
for (int y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++)
|
||||
{
|
||||
boxCalcTemp.set(
|
||||
boundingBox[y].x + position.x,
|
||||
boundingBox[y].y + position.y,
|
||||
boundingBox[y].z + position.z);
|
||||
if (t_frustumPlanes[i].distanceTo(boxCalcTemp) < 0)
|
||||
boxOut++;
|
||||
else
|
||||
boxIn++;
|
||||
}
|
||||
//if all corners are out
|
||||
if (boxIn == 0)
|
||||
return 0;
|
||||
else if (boxOut)
|
||||
boxResult = 1;
|
||||
}
|
||||
return boxResult;
|
||||
}
|
||||
|
||||
void MeshMaterial::calculateBoundingBox(Vector3 *t_vertices, u32 t_vertCount)
|
||||
{
|
||||
float lowX, lowY, lowZ, hiX, hiY, hiZ;
|
||||
lowX = hiX = t_vertices[vertexFaces[0]].x;
|
||||
lowY = hiY = t_vertices[vertexFaces[0]].y;
|
||||
lowZ = hiZ = t_vertices[vertexFaces[0]].z;
|
||||
for (u32 i = 0; i < facesCount; i++)
|
||||
{
|
||||
if (lowX > t_vertices[vertexFaces[i]].x)
|
||||
lowX = t_vertices[vertexFaces[i]].x;
|
||||
if (hiX < t_vertices[vertexFaces[i]].x)
|
||||
hiX = t_vertices[vertexFaces[i]].x;
|
||||
|
||||
if (lowY > t_vertices[vertexFaces[i]].y)
|
||||
lowY = t_vertices[vertexFaces[i]].y;
|
||||
if (hiY < t_vertices[vertexFaces[i]].y)
|
||||
hiY = t_vertices[vertexFaces[i]].y;
|
||||
|
||||
if (lowZ > t_vertices[vertexFaces[i]].z)
|
||||
lowZ = t_vertices[vertexFaces[i]].z;
|
||||
if (hiZ < t_vertices[vertexFaces[i]].z)
|
||||
hiZ = t_vertices[vertexFaces[i]].z;
|
||||
}
|
||||
boundingBox[0].set(lowX, lowY, lowZ);
|
||||
boundingBox[1].set(lowX, lowY, hiZ);
|
||||
boundingBox[2].set(lowX, hiY, lowZ);
|
||||
boundingBox[3].set(lowX, hiY, hiZ);
|
||||
|
||||
boundingBox[4].set(hiX, lowY, lowZ);
|
||||
boundingBox[5].set(hiX, lowY, hiZ);
|
||||
boundingBox[6].set(hiX, hiY, lowZ);
|
||||
boundingBox[7].set(hiX, hiY, hiZ);
|
||||
_isBoundingBoxCalculated = true;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_spec.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/math.hpp"
|
||||
#include <graph_vram.h>
|
||||
#include <gs_psm.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MeshSpec::MeshSpec()
|
||||
{
|
||||
PRINT_LOG("Creating object 3D spec");
|
||||
this->setupLodAndClut();
|
||||
PRINT_LOG("Object 3D spec created!");
|
||||
}
|
||||
|
||||
/** Release memory if object was initialized */
|
||||
MeshSpec::~MeshSpec()
|
||||
{
|
||||
if (this->isTextureVRAMAllocated == true)
|
||||
graph_vram_free(this->textureBuffer.address);
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void MeshSpec::allocateTextureBuffer(u16 t_width, u16 t_height)
|
||||
{
|
||||
this->textureBuffer.width = t_width;
|
||||
this->textureBuffer.psm = GS_PSM_24;
|
||||
this->textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK);
|
||||
if (this->textureBuffer.address <= 1)
|
||||
PRINT_ERR("Texture buffer allocation error. No memory!");
|
||||
this->textureBuffer.info.width = draw_log2(t_width);
|
||||
this->textureBuffer.info.height = draw_log2(t_height);
|
||||
this->textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
|
||||
this->textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
||||
this->isTextureVRAMAllocated = true;
|
||||
}
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void MeshSpec::deallocateTextureBuffer()
|
||||
{
|
||||
if (this->isTextureVRAMAllocated)
|
||||
{
|
||||
graph_vram_free(textureBuffer.address);
|
||||
this->isTextureVRAMAllocated = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets texture level of details settings and CLUT settings */
|
||||
void MeshSpec::setupLodAndClut()
|
||||
{
|
||||
PRINT_LOG("Setting LOD, CLUT");
|
||||
this->lod.calculation = LOD_USE_K;
|
||||
this->lod.max_level = 0;
|
||||
this->lod.mag_filter = LOD_MAG_NEAREST;
|
||||
this->lod.min_filter = LOD_MIN_NEAREST;
|
||||
this->lod.l = 0;
|
||||
this->lod.k = 0.0F;
|
||||
|
||||
this->clut.storage_mode = CLUT_STORAGE_MODE1;
|
||||
this->clut.start = 0;
|
||||
this->clut.psm = 0;
|
||||
this->clut.load_method = CLUT_NO_LOAD;
|
||||
this->clut.address = 0;
|
||||
PRINT_LOG("LOD, CLUT set!");
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/mesh_texture.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
#include <cstdlib>
|
||||
#include <draw_sampling.h>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
MeshTexture::MeshTexture()
|
||||
{
|
||||
id = rand() % 1000000;
|
||||
_isSizeSet = false;
|
||||
_isNameSet = false;
|
||||
setDefaultWrapSettings();
|
||||
}
|
||||
|
||||
MeshTexture::~MeshTexture()
|
||||
{
|
||||
if (getTextureLinksCount() > 0)
|
||||
texLinks.clear();
|
||||
if (_isNameSet)
|
||||
delete[] name;
|
||||
if (_isSizeSet)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void MeshTexture::setSize(const u8 &t_width, const u8 &t_height)
|
||||
{
|
||||
if (_isSizeSet)
|
||||
{
|
||||
PRINT_ERR("Can't set size, because was already set!");
|
||||
return;
|
||||
}
|
||||
width = t_width;
|
||||
height = t_height;
|
||||
data = new unsigned char[getDataSize()];
|
||||
_isSizeSet = true;
|
||||
}
|
||||
|
||||
void MeshTexture::setName(char *t_val)
|
||||
{
|
||||
if (_isNameSet)
|
||||
{
|
||||
PRINT_ERR("Can't set name, because was already set!");
|
||||
return;
|
||||
}
|
||||
name = String::createCopy(t_val);
|
||||
_isNameSet = true;
|
||||
}
|
||||
|
||||
void MeshTexture::setDefaultWrapSettings()
|
||||
{
|
||||
wrapSettings.horizontal = WRAP_REPEAT;
|
||||
wrapSettings.vertical = WRAP_REPEAT;
|
||||
wrapSettings.maxu = 0;
|
||||
wrapSettings.maxv = 0;
|
||||
wrapSettings.minu = 0;
|
||||
wrapSettings.minv = 0;
|
||||
}
|
||||
|
||||
void MeshTexture::setWrapSettings(const WrapSettings t_horizontal, const WrapSettings t_vertical)
|
||||
{
|
||||
wrapSettings.horizontal = t_horizontal;
|
||||
wrapSettings.vertical = t_vertical;
|
||||
}
|
||||
|
||||
void MeshTexture::addLink(const u32 &t_meshId, const u32 &t_materialId)
|
||||
{
|
||||
TextureLink link;
|
||||
link.materialId = t_materialId;
|
||||
link.meshId = t_meshId;
|
||||
texLinks.push_back(link);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/models/obj_model.hpp"
|
||||
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include "../include/utils/string.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
ObjModel::ObjModel(char *t_objFile)
|
||||
{
|
||||
filename = String::createWithoutExtension(t_objFile);
|
||||
}
|
||||
|
||||
ObjModel::~ObjModel()
|
||||
{
|
||||
if (isMemoryAllocated == true)
|
||||
{
|
||||
delete[] vertices;
|
||||
delete[] coordinates;
|
||||
delete[] normals;
|
||||
|
||||
delete[] verticeFaces;
|
||||
delete[] coordinateFaces;
|
||||
delete[] normalFaces;
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
u32 ObjModel::getDrawData(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, Vector3 &t_cameraPos, float t_scale, u8 t_shouldBeBackfaceCulled)
|
||||
{
|
||||
u32 addedFaces = 0;
|
||||
for (u32 i = 0; i < facesCount; i += 3)
|
||||
if (!t_shouldBeBackfaceCulled || Vector3::shouldBeBackfaceCulled(
|
||||
&t_cameraPos,
|
||||
&vertices[verticeFaces[i]],
|
||||
&vertices[verticeFaces[i + 1]],
|
||||
&vertices[verticeFaces[i + 2]]) == 0)
|
||||
{
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i, addedFaces++);
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 1, addedFaces++);
|
||||
fillNextFace(o_vertices, o_normals, o_coordinates, o_colors, i + 2, addedFaces++);
|
||||
}
|
||||
|
||||
return addedFaces;
|
||||
}
|
||||
|
||||
/** Allocate memory for vertices,coords etc.
|
||||
* Called by ObjLoader
|
||||
*/
|
||||
void ObjModel::allocateMemory()
|
||||
{
|
||||
PRINT_LOG("Allocating 3D object specification memory");
|
||||
vertices = new Vector3[verticesCount];
|
||||
coordinates = new Vector3[coordinatesCount];
|
||||
normals = new Vector3[normalsCount];
|
||||
|
||||
verticeFaces = new u32[facesCount];
|
||||
coordinateFaces = new u32[facesCount];
|
||||
normalFaces = new u32[facesCount];
|
||||
isMemoryAllocated = true;
|
||||
PRINT_LOG("3D object specification memory allocated!");
|
||||
}
|
||||
|
||||
void ObjModel::fillNextFace(VECTOR *o_vertices, VECTOR *o_normals, VECTOR *o_coordinates, VECTOR *o_colors, u32 t_getI, u32 t_setI)
|
||||
{
|
||||
o_vertices[t_setI][0] = vertices[verticeFaces[t_getI]].x;
|
||||
o_vertices[t_setI][1] = vertices[verticeFaces[t_getI]].y;
|
||||
o_vertices[t_setI][2] = vertices[verticeFaces[t_getI]].z;
|
||||
o_vertices[t_setI][3] = 1.0F;
|
||||
|
||||
o_normals[t_setI][0] = normals[normalFaces[t_getI]].x;
|
||||
o_normals[t_setI][1] = normals[normalFaces[t_getI]].y;
|
||||
o_normals[t_setI][2] = normals[normalFaces[t_getI]].z;
|
||||
o_normals[t_setI][3] = 1.0F;
|
||||
|
||||
o_coordinates[t_setI][0] = coordinates[coordinateFaces[t_getI]].x;
|
||||
o_coordinates[t_setI][1] = coordinates[coordinateFaces[t_getI]].y;
|
||||
o_coordinates[t_setI][2] = 1.0F;
|
||||
o_coordinates[t_setI][3] = 1.0F;
|
||||
|
||||
o_colors[t_setI][0] = 1.0F;
|
||||
o_colors[t_setI][1] = 1.0F;
|
||||
o_colors[t_setI][2] = 1.0F;
|
||||
o_colors[t_setI][3] = 1.0F;
|
||||
}
|
||||
@@ -51,15 +51,15 @@ GifSender::~GifSender()
|
||||
#include <gs_gp.h>
|
||||
|
||||
/** Send texture via GIF */
|
||||
void GifSender::sendTexture(Texture &texture, texbuffer_t *t_texBuffer)
|
||||
void GifSender::sendTexture(MeshTexture &texture, texbuffer_t *t_texBuffer)
|
||||
{
|
||||
const u16 packetSize = 40;
|
||||
packet_t *packet = packet_init(packetSize, PACKET_NORMAL);
|
||||
qword_t *q = packet->data;
|
||||
q = draw_texture_transfer(q, texture.data, texture.width, texture.height, GS_PSM_24, t_texBuffer->address, t_texBuffer->width);
|
||||
q = draw_texture_transfer(q, texture.getData(), texture.getWidth(), texture.getHeight(), GS_PSM_24, t_texBuffer->address, t_texBuffer->width);
|
||||
DMATAG_CNT(q, 2, 0, 0, 0);
|
||||
q++;
|
||||
q = draw_texture_wrapping(q, 0, &texture.wrapSettings);
|
||||
q = draw_texture_wrapping(q, 0, texture.getWrapSettings());
|
||||
q = draw_texture_flush(q);
|
||||
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
|
||||
dma_wait_fast();
|
||||
@@ -129,7 +129,7 @@ void GifSender::addClear(zbuffer_t *t_zBuffer)
|
||||
* @param objects3D Array of 3D objects pointers
|
||||
* @param amount Amount of 3D objects
|
||||
*/
|
||||
void GifSender::addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
void GifSender::addObject(RenderData *t_renderData, Mesh *t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
|
||||
{
|
||||
if (!isAnyObjectAdded)
|
||||
{
|
||||
@@ -140,19 +140,18 @@ void GifSender::addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_a
|
||||
tempDMATag = q;
|
||||
q++;
|
||||
|
||||
q = draw_texture_sampling(q, 0, &t_objects3D[0]->spec->lod);
|
||||
q = draw_texturebuffer(q, 0, &t_objects3D[0]->spec->textureBuffer, &t_objects3D[0]->spec->clut);
|
||||
dw = (u64 *)draw_prim_start(q, 0, t_renderData->prim, &t_objects3D[0]->color);
|
||||
q = draw_texture_sampling(q, 0, &t_mesh->lod);
|
||||
q = draw_texturebuffer(q, 0, textureBuffer, &t_mesh->clut);
|
||||
dw = (u64 *)draw_prim_start(q, 0, t_renderData->prim, &t_mesh->color);
|
||||
|
||||
for (u32 i = 0; i < t_amount; i++)
|
||||
if (t_objects3D[i]->shouldBeFrustumCulled == 0 || t_objects3D[i]->isInFrustum(t_renderData->frustumPlanes))
|
||||
{
|
||||
u32 vertexCount = calc3DObject(*t_renderData->perspective, *t_objects3D[i], t_renderData, t_bulbs, t_bulbsCount);
|
||||
xyz = new xyz_t[vertexCount];
|
||||
rgbaq = new color_t[vertexCount];
|
||||
st = new texel_t[vertexCount];
|
||||
calc3DObject(*t_renderData->perspective, *t_mesh, vertexCount, vertices, normals, coordinates, t_renderData, t_bulbs, t_bulbsCount);
|
||||
addCurrentCalcs(vertexCount);
|
||||
delete[] xyz;
|
||||
delete[] rgbaq;
|
||||
delete[] st;
|
||||
}
|
||||
|
||||
if ((u32)dw % 16) // if we are in the middle of qw, switch packet
|
||||
*dw++ = 0;
|
||||
@@ -167,22 +166,10 @@ void GifSender::addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_a
|
||||
* @param worldView Matrix
|
||||
* @param perspective Matrix with .setPerpsective() used [clone of gluPerspective]
|
||||
* @param mesh 3D object
|
||||
* @returns Vertex count
|
||||
*/
|
||||
u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
void GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, u32 vertexCount, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, RenderData *t_renderData, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
u32 vertexCount = t_mesh.getVertexCount();
|
||||
|
||||
VECTOR *vertices = new VECTOR[vertexCount];
|
||||
VECTOR *normals = new VECTOR[vertexCount];
|
||||
VECTOR *coordinates = new VECTOR[vertexCount];
|
||||
VECTOR *colors = new VECTOR[vertexCount];
|
||||
vertexCount = t_mesh.getDrawData(0, vertices, normals, coordinates, colors, *t_renderData->cameraPosition);
|
||||
|
||||
xyz = new xyz_t[vertexCount];
|
||||
rgbaq = new color_t[vertexCount];
|
||||
st = new texel_t[vertexCount];
|
||||
|
||||
VECTOR position, rotation;
|
||||
|
||||
vec3ToNative(position, t_mesh.position, 1.0F);
|
||||
@@ -195,7 +182,7 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
|
||||
if (SHOULD_BE_LIGHTED)
|
||||
create_local_light(localLight, rotation);
|
||||
|
||||
// I cant put perspective from renderData here. PS2SDK bug?
|
||||
// I cant put perspective from renderData here. ee-gcc bug?
|
||||
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data);
|
||||
|
||||
if (SHOULD_BE_LIGHTED)
|
||||
@@ -212,27 +199,36 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
|
||||
|
||||
calculate_lights(lights, vertexCount, normals, lightDirections, lightColors, lightTypes, lightsCount);
|
||||
|
||||
calculate_colours(colors, vertexCount, colors, lights);
|
||||
for (u32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Apply the light value to the colour.
|
||||
colors[i][0] = (t_mesh.color.r * lights[i][0] / 128.0F);
|
||||
colors[i][1] = (t_mesh.color.g * lights[i][1] / 128.0F);
|
||||
colors[i][2] = (t_mesh.color.b * lights[i][2] / 128.0F);
|
||||
vector_clamp(colors[i], colors[i], 0.00f, 1.99f);
|
||||
}
|
||||
|
||||
delete[] lightDirections;
|
||||
delete[] lightColors;
|
||||
delete[] lightTypes;
|
||||
delete[] lights;
|
||||
}
|
||||
else
|
||||
for (u32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
colors[i][0] = t_mesh.color.r / 128.0F;
|
||||
colors[i][1] = t_mesh.color.g / 128.0F;
|
||||
colors[i][2] = t_mesh.color.b / 128.0F;
|
||||
}
|
||||
|
||||
calculate_vertices(vertices, vertexCount, vertices, localScreen);
|
||||
|
||||
convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color.a);
|
||||
convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color);
|
||||
|
||||
delete[] vertices;
|
||||
delete[] normals;
|
||||
delete[] coordinates;
|
||||
delete[] colors;
|
||||
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, u8 t_alpha)
|
||||
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color)
|
||||
{
|
||||
// TODO get this via screensettings
|
||||
const s32 centerX = ftoi4(2048);
|
||||
@@ -254,7 +250,7 @@ void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_co
|
||||
rgbaq[i].r = (u8)(t_colors[i][0] * 128.0F);
|
||||
rgbaq[i].g = (u8)(t_colors[i][1] * 128.0F);
|
||||
rgbaq[i].b = (u8)(t_colors[i][2] * 128.0F);
|
||||
rgbaq[i].a = t_alpha;
|
||||
rgbaq[i].a = t_color.a;
|
||||
rgbaq[i].q = q;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,9 @@ Renderer::Renderer(u32 t_packetSize, ScreenSettings *t_screen)
|
||||
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0); // Initialize DMA to enable data transfer
|
||||
dma_channel_fast_waits(DMA_CHANNEL_GIF);
|
||||
context = 0;
|
||||
lastTextureId = 0;
|
||||
isTextureVRAMAllocated = false;
|
||||
isFrameEmpty = false;
|
||||
lastTextureId = 0;
|
||||
flipPacket = packet_init(3, PACKET_UCAB); // Uncached accelerated
|
||||
allocateBuffers(t_screen->width, t_screen->height);
|
||||
initDrawingEnv(t_screen->width, t_screen->height);
|
||||
@@ -55,6 +56,49 @@ Renderer::~Renderer() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void Renderer::allocateTextureBuffer(u16 t_width, u16 t_height)
|
||||
{
|
||||
textureBuffer.width = t_width;
|
||||
textureBuffer.psm = GS_PSM_24;
|
||||
textureBuffer.address = graph_vram_allocate(t_width, t_height, GS_PSM_24, GRAPH_ALIGN_BLOCK);
|
||||
if (textureBuffer.address <= 1)
|
||||
PRINT_ERR("Texture buffer allocation error. No memory!");
|
||||
textureBuffer.info.width = draw_log2(t_width);
|
||||
textureBuffer.info.height = draw_log2(t_height);
|
||||
textureBuffer.info.components = TEXTURE_COMPONENTS_RGB;
|
||||
textureBuffer.info.function = TEXTURE_FUNCTION_MODULATE;
|
||||
isTextureVRAMAllocated = true;
|
||||
}
|
||||
|
||||
/** Configure and allocate vRAM for texture buffer */
|
||||
void Renderer::deallocateTextureBuffer()
|
||||
{
|
||||
if (isTextureVRAMAllocated)
|
||||
{
|
||||
graph_vram_free(textureBuffer.address);
|
||||
isTextureVRAMAllocated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::changeTexture(Mesh *t_mesh, u32 t_materialId)
|
||||
{
|
||||
|
||||
MeshTexture *tex = textureRepo.getByMesh(t_mesh->getId(), t_materialId);
|
||||
if (tex != NULL)
|
||||
{
|
||||
if (tex->getId() != lastTextureId)
|
||||
{
|
||||
lastTextureId = tex->getId();
|
||||
deallocateTextureBuffer();
|
||||
allocateTextureBuffer(tex->getWidth(), tex->getHeight());
|
||||
GifSender::sendTexture(*tex, &textureBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
PRINT_ERR("Texture was not found in texture repository!");
|
||||
}
|
||||
|
||||
/** Initializes drawing environment (1st app packet) */
|
||||
void Renderer::initDrawingEnv(float t_screenW, float t_screenH)
|
||||
{
|
||||
@@ -88,17 +132,6 @@ void Renderer::setPrim()
|
||||
PRINT_LOG("Prim set!");
|
||||
}
|
||||
|
||||
void Renderer::changeTexture(Mesh *t_mesh, u8 t_textureIndex)
|
||||
{
|
||||
if (t_mesh->spec->textures[t_textureIndex].id != lastTextureId)
|
||||
{
|
||||
lastTextureId = t_mesh->spec->textures[t_textureIndex].id;
|
||||
t_mesh->spec->deallocateTextureBuffer();
|
||||
t_mesh->spec->allocateTextureBuffer(t_mesh->spec->textures[t_textureIndex].width, t_mesh->spec->textures[t_textureIndex].height);
|
||||
GifSender::sendTexture(t_mesh->spec->textures[t_textureIndex], &t_mesh->spec->textureBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/** Defines and allocates framebuffers and zbuffer */
|
||||
void Renderer::allocateBuffers(float t_screenW, float t_screenH)
|
||||
{
|
||||
@@ -130,25 +163,35 @@ void Renderer::allocateBuffers(float t_screenW, float t_screenH)
|
||||
/** PATH3 Many + lighting */
|
||||
void Renderer::drawByPath3(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
gifSender->initPacket(context);
|
||||
// TODO
|
||||
changeTexture(t_meshes[0], 0);
|
||||
gifSender->addObjects(&renderData, t_meshes, t_amount, t_bulbs, t_bulbsCount);
|
||||
gifSender->sendPacket();
|
||||
draw_wait_finish();
|
||||
for (u16 i = 0; i < t_amount; i++)
|
||||
drawByPath3(t_meshes[i], t_bulbs, t_bulbsCount);
|
||||
}
|
||||
|
||||
/** PATH3 Single + lighting */
|
||||
void Renderer::drawByPath3(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
if (!t_mesh->isDataLoaded())
|
||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||
if (t_mesh->getCurrentAnimationFrame() != t_mesh->getNextAnimationFrame())
|
||||
t_mesh->animate();
|
||||
for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++)
|
||||
{
|
||||
if (t_mesh->shouldBeFrustumCulled && !t_mesh->getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh->position))
|
||||
return;
|
||||
changeTexture(t_mesh, t_mesh->getMaterial(i).getId());
|
||||
gifSender->initPacket(context);
|
||||
// TODO
|
||||
changeTexture(t_mesh, 0);
|
||||
gifSender->addObjects(&renderData, &t_mesh, 1, t_bulbs, t_bulbsCount);
|
||||
u32 vertCount = t_mesh->getMaterial(i).getFacesCount();
|
||||
VECTOR *vertices = new VECTOR[vertCount];
|
||||
VECTOR *normals = new VECTOR[vertCount];
|
||||
VECTOR *coordinates = new VECTOR[vertCount];
|
||||
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
|
||||
gifSender->addObject(&renderData, t_mesh, vertCount, vertices, normals, coordinates, t_bulbs, t_bulbsCount, &textureBuffer);
|
||||
gifSender->sendPacket();
|
||||
draw_wait_finish();
|
||||
delete[] vertices;
|
||||
delete[] normals;
|
||||
delete[] coordinates;
|
||||
}
|
||||
}
|
||||
|
||||
/** PATH3 Many */
|
||||
@@ -162,8 +205,6 @@ void Renderer::drawByPath3(Mesh *t_mesh) { drawByPath3(t_mesh, NULL, 0); }
|
||||
/** PATH1 Many + lighting */
|
||||
void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
// TODO
|
||||
beginFrameIfNeeded();
|
||||
for (u16 i = 0; i < t_amount; i++)
|
||||
draw(t_meshes[i], t_bulbs, t_bulbsCount);
|
||||
}
|
||||
@@ -172,32 +213,27 @@ void Renderer::draw(Mesh **t_meshes, u16 t_amount, LightBulb *t_bulbs, u16 t_bul
|
||||
void Renderer::draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
{
|
||||
beginFrameIfNeeded();
|
||||
// TODO VU1 send single list here
|
||||
if (!t_mesh->isObjLoaded && !t_mesh->isDffLoaded && !t_mesh->isMd2Loaded)
|
||||
vifSender->sendMatrices(renderData, t_mesh->position, t_mesh->rotation);
|
||||
if (!t_mesh->isDataLoaded())
|
||||
PRINT_ERR("Can't draw, because no mesh data was loaded!");
|
||||
|
||||
if (t_mesh->getCurrentAnimationFrame() != t_mesh->getNextAnimationFrame())
|
||||
t_mesh->animate();
|
||||
for (u32 i = 0; i < t_mesh->getMaterialsCount(); i++)
|
||||
{
|
||||
if (t_mesh->shouldBeFrustumCulled && !t_mesh->getMaterial(i).isInFrustum(renderData.frustumPlanes, t_mesh->position))
|
||||
return;
|
||||
u32 vertCount = t_mesh->getVertexCount();
|
||||
u32 vertCount = t_mesh->getMaterial(i).getFacesCount();
|
||||
VECTOR *vertices = new VECTOR[vertCount];
|
||||
VECTOR *normals = new VECTOR[vertCount];
|
||||
VECTOR *coordinates = new VECTOR[vertCount];
|
||||
VECTOR *colors = new VECTOR[vertCount];
|
||||
if (t_mesh->isObjLoaded || t_mesh->isMd2Loaded)
|
||||
{
|
||||
changeTexture(t_mesh, 0);
|
||||
vertCount = t_mesh->getDrawData(0, vertices, normals, coordinates, colors, *renderData.cameraPosition);
|
||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, colors, t_mesh, t_bulbs, t_bulbsCount);
|
||||
}
|
||||
else if (t_mesh->isDffLoaded)
|
||||
for (u32 i = 0; i < t_mesh->dff->clump.geometryList.geometries[0].extension.materialSplit.header.splitCount; i++)
|
||||
{
|
||||
const u32 currentTexI = t_mesh->dff->clump.geometryList.geometries[0].extension.materialSplit.splitInformation[i].materialIndex;
|
||||
changeTexture(t_mesh, currentTexI);
|
||||
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, colors, *renderData.cameraPosition);
|
||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, colors, t_mesh, t_bulbs, t_bulbsCount);
|
||||
}
|
||||
changeTexture(t_mesh, t_mesh->getMaterial(i).getId());
|
||||
vertCount = t_mesh->getDrawData(i, vertices, normals, coordinates, *renderData.cameraPosition);
|
||||
vifSender->drawMesh(&renderData, perspective, vertCount, vertices, normals, coordinates, t_mesh, t_bulbs, t_bulbsCount, &textureBuffer);
|
||||
delete[] vertices;
|
||||
delete[] normals;
|
||||
delete[] coordinates;
|
||||
delete[] colors;
|
||||
}
|
||||
}
|
||||
|
||||
/** PATH1 Many */
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
# ______ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2020, tyra - https://github.com/h4570/tyra
|
||||
# Licenced under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "../include/modules/texture_repository.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
// ----
|
||||
|
||||
TextureRepository::TextureRepository()
|
||||
{
|
||||
PRINT_LOG("Initializing texture repository");
|
||||
PRINT_LOG("Texture repository initialized!");
|
||||
}
|
||||
|
||||
TextureRepository::~TextureRepository()
|
||||
{
|
||||
if (getTexturesCount() > 0)
|
||||
{
|
||||
for (u32 i = 0; i < getTexturesCount(); i++)
|
||||
delete textures[i];
|
||||
textures.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
MeshTexture *TextureRepository::add(char *t_subfolder, char *t_name)
|
||||
{
|
||||
MeshTexture *texture = new MeshTexture();
|
||||
loader.load(*texture, t_subfolder, t_name, ".bmp");
|
||||
texture->setName(t_name);
|
||||
textures.push_back(texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void TextureRepository::addByMesh(char *t_path, Mesh &mesh)
|
||||
{
|
||||
for (u32 i = 0; i < mesh.getMaterialsCount(); i++)
|
||||
{
|
||||
MeshTexture *texture = new MeshTexture();
|
||||
loader.load(*texture, t_path, mesh.getMaterial(i).getName(), ".bmp");
|
||||
texture->setName(mesh.getMaterial(i).getName());
|
||||
texture->addLink(mesh.getId(), mesh.getMaterial(i).getId());
|
||||
textures.push_back(texture);
|
||||
}
|
||||
}
|
||||
@@ -37,19 +37,17 @@ VifSender::~VifSender() {}
|
||||
// Methods
|
||||
// ----
|
||||
|
||||
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, VECTOR *colors, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
|
||||
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
|
||||
{
|
||||
if (t_mesh->shouldBeFrustumCulled == 1 && !t_mesh->isInFrustum(t_renderData->frustumPlanes))
|
||||
return;
|
||||
|
||||
vec3ToNative(position, t_mesh->position, 1.0F);
|
||||
vec3ToNative(rotation, t_mesh->rotation, 1.0F);
|
||||
vec3ToNative(position, t_position, 1.0F);
|
||||
vec3ToNative(rotation, t_rotation, 1.0F);
|
||||
create_local_world(localWorld, position, rotation);
|
||||
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data);
|
||||
|
||||
// TODO Send it once man xd
|
||||
create_local_screen(localScreen, localWorld, t_renderData.worldView->data, t_renderData.perspective->data);
|
||||
vu1.sendSingleRefList(0, &localScreen, 4);
|
||||
}
|
||||
|
||||
void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 vertCount2, VECTOR *vertices, VECTOR *normals, VECTOR *coordinates, Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer)
|
||||
{
|
||||
// we have to split 3D object into small parts, because of small memory of VU1
|
||||
for (u32 i = 0; i < vertCount2;)
|
||||
{
|
||||
@@ -60,7 +58,7 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
||||
i -= 3;
|
||||
|
||||
const u32 endI = i + (VU1_PACKAGE_VERTS_PER_BUFF - 1) > vertCount2 ? vertCount2 : i + (VU1_PACKAGE_VERTS_PER_BUFF - 1);
|
||||
drawVertices(t_mesh, i, endI, vertices, colors, coordinates, t_renderData->prim);
|
||||
drawVertices(t_mesh, i, endI, vertices, coordinates, t_renderData->prim, textureBuffer);
|
||||
if (endI == vertCount2) // if there are no more vertices to draw, break
|
||||
{
|
||||
i = vertCount2;
|
||||
@@ -74,7 +72,7 @@ void VifSender::drawMesh(RenderData *t_renderData, Matrix t_perspective, u32 ver
|
||||
}
|
||||
|
||||
/** Draw using PATH1 */
|
||||
void VifSender::drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_coordinates, prim_t *t_prim)
|
||||
void VifSender::drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_vertices, VECTOR *t_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer)
|
||||
{
|
||||
const u32 vertCount = t_end - t_start;
|
||||
vu1.addListBeginning();
|
||||
@@ -89,29 +87,29 @@ void VifSender::drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_ver
|
||||
|
||||
vu1.add128( // tex -> lod
|
||||
GS_SET_TEX1(
|
||||
t_mesh->spec->lod.calculation,
|
||||
t_mesh->spec->lod.max_level,
|
||||
t_mesh->spec->lod.mag_filter,
|
||||
t_mesh->spec->lod.min_filter,
|
||||
t_mesh->spec->lod.mipmap_select,
|
||||
t_mesh->spec->lod.l,
|
||||
(int)(t_mesh->spec->lod.k * 16.0F)),
|
||||
t_mesh->lod.calculation,
|
||||
t_mesh->lod.max_level,
|
||||
t_mesh->lod.mag_filter,
|
||||
t_mesh->lod.min_filter,
|
||||
t_mesh->lod.mipmap_select,
|
||||
t_mesh->lod.l,
|
||||
(int)(t_mesh->lod.k * 16.0F)),
|
||||
GS_REG_TEX1);
|
||||
|
||||
vu1.add128( // tex -> buff + clut
|
||||
GS_SET_TEX0(
|
||||
t_mesh->spec->textureBuffer.address >> 6,
|
||||
t_mesh->spec->textureBuffer.width >> 6,
|
||||
t_mesh->spec->textureBuffer.psm,
|
||||
t_mesh->spec->textureBuffer.info.width,
|
||||
t_mesh->spec->textureBuffer.info.height,
|
||||
t_mesh->spec->textureBuffer.info.components,
|
||||
t_mesh->spec->textureBuffer.info.function,
|
||||
t_mesh->spec->clut.address >> 6,
|
||||
t_mesh->spec->clut.psm,
|
||||
t_mesh->spec->clut.storage_mode,
|
||||
t_mesh->spec->clut.start,
|
||||
t_mesh->spec->clut.load_method),
|
||||
textureBuffer->address >> 6,
|
||||
textureBuffer->width >> 6,
|
||||
textureBuffer->psm,
|
||||
textureBuffer->info.width,
|
||||
textureBuffer->info.height,
|
||||
textureBuffer->info.components,
|
||||
textureBuffer->info.function,
|
||||
t_mesh->clut.address >> 6,
|
||||
t_mesh->clut.psm,
|
||||
t_mesh->clut.storage_mode,
|
||||
t_mesh->clut.start,
|
||||
t_mesh->clut.load_method),
|
||||
GS_REG_TEX0);
|
||||
|
||||
vu1.add128(
|
||||
@@ -138,38 +136,43 @@ void VifSender::drawVertices(Mesh *t_mesh, u32 t_start, u32 t_end, VECTOR *t_ver
|
||||
|
||||
//// Clipping tests start
|
||||
|
||||
// const float minZ = 1;
|
||||
// const float maxZ = 65535;
|
||||
// const int iGuardDimXY = 2048;
|
||||
// // const float minZ = 1;
|
||||
// // const float maxZ = 65535;
|
||||
// // const int iGuardDimXY = 2048;
|
||||
|
||||
// vu1.addFloat(1.0F); // TODO clipping maybe there is problem?
|
||||
// vu1.addFloat(1.0F);
|
||||
// vu1.addFloat(1.0F);
|
||||
// vu1.addFloat(1.0F);
|
||||
// float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f);
|
||||
// packet += Math::Max( xClip, 1.0f );
|
||||
// float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f);
|
||||
// packet += Math::Max( yClip, 1.0f );
|
||||
// float depthClip = 2048.0f / depthClipToGs;
|
||||
// // FIXME: maybe these 2048's should be 2047.5s...
|
||||
// depthClip *= 1.003f; // round up a bit for fp error (????)
|
||||
// packet += depthClip;
|
||||
// // enable/disable clipping
|
||||
// packet += (drawContext.GetDoClipping()) ? 1 : 0;
|
||||
// // vu1.addFloat(1.0F); // f_TODO clipping maybe there is problem?
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // float xClip = (float)2048.0f/(drawContext.GetFBWidth() * 0.5f * 2.0f);
|
||||
// // packet += Math::Max( xClip, 1.0f );
|
||||
// // float yClip = (float)2048.0f/(drawContext.GetFBHeight() * 0.5f * 2.0f);
|
||||
// // packet += Math::Max( yClip, 1.0f );
|
||||
// // float depthClip = 2048.0f / depthClipToGs;
|
||||
// // // F_FIXME: maybe these 2048's should be 2047.5s...
|
||||
// // depthClip *= 1.003f; // round up a bit for fp error (????)
|
||||
// // packet += depthClip;
|
||||
// // // enable/disable clipping
|
||||
// // packet += (drawContext.GetDoClipping()) ? 1 : 0;
|
||||
|
||||
// u32 depthBits = 24; // or 28(fog) or 16
|
||||
// float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f;
|
||||
// vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f));
|
||||
// vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f));
|
||||
// vu1.addFloat((2048.0f / depthClipToGs) * 1.003F);
|
||||
// // vu1.addFloat(2048.0F); // scale
|
||||
// // vu1.addFloat(2048.0F); // scale
|
||||
// // vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
|
||||
// vu1.addFloat(0.0F);
|
||||
// // vu1.addFloat(0.5f * iGuardDimXY);
|
||||
// // vu1.addFloat(-0.5f * iGuardDimXY);
|
||||
// // vu1.addFloat(1.0F);
|
||||
// // vu1.addFloat(500.0F); // far
|
||||
|
||||
u32 depthBits = 24; // or 28(fog) or 16
|
||||
float depthClipToGs = (float)((1 << depthBits) - 1) / 2.0f;
|
||||
vu1.addFloat(2048.0f / (640.0F * 0.5f * 2.0f));
|
||||
vu1.addFloat(2048.0f / (480.0F * 0.5f * 2.0f));
|
||||
vu1.addFloat((2048.0f / depthClipToGs) * 1.003F);
|
||||
// vu1.addFloat(2048.0F); // scale
|
||||
// vu1.addFloat(2048.0F); // scale
|
||||
// vu1.addFloat(((float)0xFFFFFF) / 32.0F); // scale
|
||||
vu1.addFloat(0.0F);
|
||||
// vu1.addFloat(0.5f * iGuardDimXY);
|
||||
// vu1.addFloat(-0.5f * iGuardDimXY);
|
||||
// vu1.addFloat(1.0F);
|
||||
// vu1.addFloat(500.0F); // far
|
||||
vu1.addFloat(0.0F);
|
||||
vu1.addFloat(0.0F);
|
||||
vu1.addFloat(0.0F);
|
||||
|
||||
//// Clipping tests end
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ float Math::sqrt(float x)
|
||||
float Math::invSqrt(float x) { return 1.0F / sqrt(x); }
|
||||
|
||||
/** Converts Vector3 to PS2SDK's Vector4 */
|
||||
void vec3ToNative(VECTOR o_result, Vector3 &t_vec, float t_fourthVal)
|
||||
void vec3ToNative(VECTOR o_result, const Vector3 &t_vec, float t_fourthVal)
|
||||
{
|
||||
o_result[0] = t_vec.x;
|
||||
o_result[1] = t_vec.y;
|
||||
|
||||
@@ -9,8 +9,31 @@
|
||||
*/
|
||||
|
||||
#include "../include/utils/string.hpp"
|
||||
#include "../include/utils/debug.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
char *String::createU32ToString(u32 a)
|
||||
{
|
||||
char *result = new char[(((sizeof a) * CHAR_BIT) + 2) / 3 + 2];
|
||||
sprintf(result, "%d", a);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Converts "123" to "000123". 6 digits length */
|
||||
char *String::createWithLeadingZeros(char *a)
|
||||
{
|
||||
const u8 digitsAmount = 6;
|
||||
char *part = createConcatenated("00000000", a);
|
||||
u16 partLength = getLength(part);
|
||||
u16 insert = 0;
|
||||
char *result = new char[digitsAmount + 1];
|
||||
for (u16 i = partLength - digitsAmount; i < partLength; i++)
|
||||
result[insert++] = part[i];
|
||||
delete[] part;
|
||||
result[digitsAmount] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
char *String::createWithoutExtension(char *source)
|
||||
{
|
||||
u32 length = 0;
|
||||
@@ -34,6 +57,7 @@ char *String::createCopy(char *source)
|
||||
return res;
|
||||
}
|
||||
|
||||
// For test\0 will return 4
|
||||
u32 String::getLength(char *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
|
||||
@@ -5,17 +5,17 @@ EE_OBJS = \
|
||||
../../engine/models/math/plane.o \
|
||||
../../engine/models/math/point.o \
|
||||
../../engine/models/math/vector3.o \
|
||||
../../engine/models/dff_model.o \
|
||||
../../engine/models/md2_model.o \
|
||||
../../engine/models/mesh_frame.o \
|
||||
../../engine/models/mesh_material.o \
|
||||
../../engine/models/mesh.o \
|
||||
../../engine/models/mesh_spec.o \
|
||||
../../engine/models/obj_model.o \
|
||||
../../engine/models/mesh_texture.o \
|
||||
../../engine/modules/audio.o \
|
||||
../../engine/modules/camera_base.o \
|
||||
../../engine/modules/gif_sender.o \
|
||||
../../engine/modules/light.o \
|
||||
../../engine/modules/pad.o \
|
||||
../../engine/modules/renderer.o \
|
||||
../../engine/modules/texture_repository.o \
|
||||
../../engine/modules/timer.o \
|
||||
../../engine/modules/vif_sender.o \
|
||||
../../engine/modules/vu1.o \
|
||||
@@ -50,7 +50,7 @@ all: $(EE_BIN)
|
||||
$(EE_DVP) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(EE_BIN) $(EE_OBJS)
|
||||
rm -f $(EE_OBJS)
|
||||
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
|
||||
### Description
|
||||
|
||||
* .obj (skybox, water)
|
||||
* .dff (island)
|
||||
* .md2 (ari)
|
||||
* mesh cloning (water)
|
||||
|
||||
Testing demo. In future there will be Ariana Grande demo.
|
||||
|
||||
### Assets
|
||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/ari/assets.zip)
|
||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/assets.zip)
|
||||
|
||||
### Screenshot
|
||||
|
||||
[![Ari screenshot][ari-screenshot]](#)
|
||||
|
||||
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/ari/ari.gif
|
||||
[ari-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/ari/ari.gif
|
||||
|
||||
+26
-27
@@ -8,15 +8,6 @@
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
// SANDRO TODO
|
||||
// Ogarnac czemu tekstura sie zle wczytuje
|
||||
// Ogarnac wiele tekstur do skyboxa (wczytywane z .mtl i .obj)
|
||||
// texture loading for obj and md2
|
||||
// animation for dff
|
||||
// TODO obj destructor
|
||||
// TODO md2 destructor
|
||||
// TODO dff destructor
|
||||
|
||||
#include "ari.hpp"
|
||||
|
||||
#include "utils/math.hpp"
|
||||
@@ -35,7 +26,7 @@ Ari::~Ari() {}
|
||||
|
||||
// TEST START
|
||||
const u8 WATER_TILES_COUNT = 64;
|
||||
Mesh *island, *islandAddons, *skybox;
|
||||
Mesh *island, *islandAddons, *skybox, *test;
|
||||
Mesh **waterFloors;
|
||||
Point *spirals;
|
||||
|
||||
@@ -65,6 +56,9 @@ void calcSpiral(int X, int Y)
|
||||
}
|
||||
// TEST END
|
||||
|
||||
// TODO 1 - const & in parameters
|
||||
// TODO 2 - Destructor mesh
|
||||
|
||||
void Ari::onInit()
|
||||
{
|
||||
player = new Player();
|
||||
@@ -75,29 +69,30 @@ void Ari::onInit()
|
||||
engine.audio.loadSong("MOV-CIRC.WAV");
|
||||
engine.audio.play();
|
||||
|
||||
Vector3 islandPos = Vector3(0.0F, 10.0F, 0.0F);
|
||||
texRepo = engine.renderer->getTextureRepository();
|
||||
|
||||
island = new Mesh();
|
||||
island->loadDff("sunnyisl/", "sunnyisl", 0.1F, false);
|
||||
island->rotation.x = -1.6F;
|
||||
island->loadDff("sunnyisl/", "sunnyisl.dff", islandPos, 0.1F);
|
||||
island->shouldBeFrustumCulled = false;
|
||||
island->position.set(0.0F, 10.0F, 20.0F);
|
||||
island->shouldBeBackfaceCulled = true;
|
||||
island->shouldBeFrustumCulled = false;
|
||||
|
||||
islandAddons = new Mesh();
|
||||
islandAddons->loadDff("sunnyisl/", "sunnyisl3", 0.1F, false);
|
||||
islandAddons->rotation.x = -1.6F;
|
||||
islandAddons->loadDff("sunnyisl/", "sunnyisl3.dff", islandPos, 0.1F);
|
||||
islandAddons->shouldBeFrustumCulled = false;
|
||||
islandAddons->position.set(0.0F, 10.0F, 20.0F);
|
||||
|
||||
skybox = new Mesh();
|
||||
Vector3 skyboxPos = Vector3(0.0F, 0.0F, 0.0F);
|
||||
skybox->loadObj("skybox/", "skybox.obj", skyboxPos, 100.0F);
|
||||
skybox->shouldBeFrustumCulled = true;
|
||||
skybox->loadObj("skybox/", "skybox", 100.0F, false);
|
||||
skybox->shouldBeFrustumCulled = false;
|
||||
|
||||
waterFloors = new Mesh *[WATER_TILES_COUNT];
|
||||
spirals = new Point[WATER_TILES_COUNT];
|
||||
Vector3 initPos = Vector3(0.0F, 8.0F, 0.0F);
|
||||
waterFloors[0] = new Mesh();
|
||||
waterFloors[0]->loadObj("water/", "water.obj", initPos, 5.0F);
|
||||
waterFloors[0]->shouldBeFrustumCulled = true;
|
||||
waterFloors[0]->loadObj("water/", "water", 5.0F, false);
|
||||
waterFloors[0]->position.set(0.0F, 8.0F, 0.0F);
|
||||
texRepo->addByMesh("water/", *waterFloors[0]);
|
||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
spirals[i].x = 1.0F;
|
||||
@@ -108,13 +103,17 @@ void Ari::onInit()
|
||||
for (u8 i = 1; i < WATER_TILES_COUNT; i++)
|
||||
{
|
||||
waterFloors[i] = new Mesh();
|
||||
Vector3 nextPos = Vector3(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
|
||||
waterFloors[i]->setObj(nextPos, waterFloors[0]->obj, waterFloors[0]->spec);
|
||||
waterFloors[i]->shouldBeFrustumCulled = true;
|
||||
waterFloors[i]->loadFrom(*waterFloors[0]);
|
||||
waterFloors[i]->position.set(10.0F * spirals[i].x, 8.0F, 10.0F * spirals[i].y);
|
||||
texRepo->getByMesh(waterFloors[0]->getId(), waterFloors[0]->getMaterial(0).getId())
|
||||
->addLink(waterFloors[i]->getId(), waterFloors[i]->getMaterial(0).getId());
|
||||
}
|
||||
}
|
||||
|
||||
u32 currentTexI = 0;
|
||||
texRepo->addByMesh("sunnyisl/", *island);
|
||||
texRepo->addByMesh("sunnyisl/", *islandAddons);
|
||||
texRepo->addByMesh("skybox/", *skybox);
|
||||
texRepo->addByMesh("ari/", player->mesh);
|
||||
}
|
||||
|
||||
void Ari::initBulb()
|
||||
{
|
||||
@@ -132,5 +131,5 @@ void Ari::onUpdate()
|
||||
engine.renderer->draw(islandAddons);
|
||||
engine.renderer->draw(&player->mesh);
|
||||
for (u8 i = 0; i < WATER_TILES_COUNT; i++)
|
||||
engine.renderer->draw(waterFloors[i]); // TODO
|
||||
engine.renderer->draw(waterFloors[i]);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <engine.hpp>
|
||||
#include "objects/player.hpp"
|
||||
#include <models/light_bulb.hpp>
|
||||
#include <modules/texture_repository.hpp>
|
||||
#include "./camera.hpp"
|
||||
|
||||
class Ari : public Game
|
||||
@@ -35,6 +36,7 @@ private:
|
||||
LightBulb bulb;
|
||||
Player *player;
|
||||
Camera *camera;
|
||||
TextureRepository *texRepo;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,11 +25,11 @@ Player::Player()
|
||||
PRINT_LOG("Creating player object");
|
||||
this->gravity = 0.1F;
|
||||
this->lift = -1.0F;
|
||||
Vector3 initPos = Vector3(0.0F, 8.0F, 0.0F);
|
||||
this->mesh.loadMD2("ari/", "ari.md2", initPos, 0.0001F);
|
||||
this->mesh.loadMD2("ari/", "ari", 0.0001F, true);
|
||||
this->mesh.position.set(0.0F, 10.0F, 0.0F);
|
||||
this->mesh.shouldBeBackfaceCulled = true;
|
||||
this->mesh.shouldBeFrustumCulled = false;
|
||||
// this->mesh.shouldBeLighted = true;
|
||||
this->mesh.shouldBeLighted = true;
|
||||
this->mesh.setAnimSpeed(0.05F);
|
||||
this->mesh.playAnimation(0, 1);
|
||||
PRINT_LOG("Player object created!");
|
||||
@@ -37,7 +37,6 @@ Player::Player()
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
delete[] this->spec;
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "../camera.hpp"
|
||||
#include <modules/pad.hpp>
|
||||
#include <models/mesh_spec.hpp>
|
||||
#include <tamtypes.h>
|
||||
|
||||
/** Player 3D object class */
|
||||
@@ -24,7 +23,6 @@ public:
|
||||
float gravity, velocity, lift;
|
||||
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
|
||||
Mesh mesh;
|
||||
MeshSpec *spec;
|
||||
Player();
|
||||
~Player();
|
||||
|
||||
@@ -32,4 +30,36 @@ private:
|
||||
Vector3 playerNextPosition;
|
||||
};
|
||||
|
||||
// TODO Rysowanie idzie wg tekstur
|
||||
|
||||
// 2 Graczy, 1 mesh 2 tekstury
|
||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
||||
// var addedTextures = texturesRepo.addByMaterialNames("textures/dirt/", sharedFrames);
|
||||
// var addedTexture = texturesRepo.add("textures/blocks/sand.bmp");
|
||||
// dirt = new Mesh(sharedFrames);
|
||||
// sand = new Mesh(sharedFrames);
|
||||
// addedTextures[0].addUsage(dirt.Id, sharedFrames.getMaterialId(0));
|
||||
// addedTexture.addUsage(sand.Id, sand.getMaterialId(0));
|
||||
|
||||
// 1 gracz, 2 dynamic tekstury
|
||||
// sharedFrames = objLoader.load("meshes/", "block", 1.0F);
|
||||
// var addedTexture1 = texturesRepo.add("textures/blocks/sand.bmp");
|
||||
// var addedTexture2 = texturesRepo.add("textures/blocks/sand_damaged.bmp");
|
||||
// sand = new Mesh(sharedFrames);
|
||||
// addedTexture1.removeUsage(sand.Id, sand.getMaterialId(0));
|
||||
// draw()
|
||||
// addedTexture2.addUsage(sand.Id, sand.getMaterialId(0));
|
||||
|
||||
// 2 różne obj, te same tekstury
|
||||
// frames1 = objLoader.load("meshes/", "island", 1.0F);
|
||||
// frames2 = objLoader.load("meshes/", "islandAddons", 1.0F);
|
||||
// island = new Mesh(frames1);
|
||||
// islandAddons = new Mesh(frames2);
|
||||
// var addedTextures1 = texturesRepo.addByMaterialNames("textures/island/",frames1);
|
||||
// var addedTextures2 = texturesRepo.addByMaterialNames("textures/island/",frames2);
|
||||
// texturesRepo.remove(addedTextures2[0]); // duplicate
|
||||
// addedTextures1[0].addUsage(islandAddons.Id, islandAddons.getMaterialId(0));
|
||||
|
||||
// Mesh -> position, rotation, color, scale, shouldBeLighted, clut, lod
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,17 +5,17 @@ EE_OBJS = \
|
||||
../../engine/models/math/plane.o \
|
||||
../../engine/models/math/point.o \
|
||||
../../engine/models/math/vector3.o \
|
||||
../../engine/models/dff_model.o \
|
||||
../../engine/models/md2_model.o \
|
||||
../../engine/models/mesh_frame.o \
|
||||
../../engine/models/mesh_material.o \
|
||||
../../engine/models/mesh.o \
|
||||
../../engine/models/mesh_spec.o \
|
||||
../../engine/models/obj_model.o \
|
||||
../../engine/models/mesh_texture.o \
|
||||
../../engine/modules/audio.o \
|
||||
../../engine/modules/camera_base.o \
|
||||
../../engine/modules/gif_sender.o \
|
||||
../../engine/modules/light.o \
|
||||
../../engine/modules/pad.o \
|
||||
../../engine/modules/renderer.o \
|
||||
../../engine/modules/texture_repository.o \
|
||||
../../engine/modules/timer.o \
|
||||
../../engine/modules/vif_sender.o \
|
||||
../../engine/modules/vu1.o \
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
Simple demo which shows lighting using PATH3, and player movement and animation.
|
||||
|
||||
### Assets
|
||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/floors/assets.zip)
|
||||
[Download](http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/assets.zip)
|
||||
|
||||
### Screenshot
|
||||
|
||||
[![Floors screenshot][floors-screenshot]](#)
|
||||
|
||||
[floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.0.0/samples/floors/floors.gif
|
||||
[floors-screenshot]: http://apgcglz.cluster028.hosting.ovh.net/tyra/1.1.0/samples/floors/floors.gif
|
||||
|
||||
@@ -33,6 +33,12 @@ void Floors::onInit()
|
||||
engine.audio.addListener(&lightManager);
|
||||
engine.audio.loadSong("NF-CHILL.WAV");
|
||||
engine.audio.play();
|
||||
texRepo = engine.renderer->getTextureRepository();
|
||||
texRepo->addByMesh("warrior/", player->mesh);
|
||||
texRepo->addByMesh("floor/", *floorManager->meshes[0]);
|
||||
for (size_t i = 1; i < floorManager->floorAmount; i++)
|
||||
texRepo->getByMesh(floorManager->meshes[0]->getId(), floorManager->meshes[0]->getMaterial(0).getId())
|
||||
->addLink(floorManager->meshes[i]->getId(), floorManager->meshes[i]->getMaterial(0).getId());
|
||||
}
|
||||
|
||||
void Floors::onUpdate()
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <engine.hpp>
|
||||
#include "managers/floor_manager.hpp"
|
||||
#include "managers/light_manager.hpp"
|
||||
#include "modules/texture_repository.hpp"
|
||||
#include "objects/player.hpp"
|
||||
#include "./camera.hpp"
|
||||
|
||||
@@ -32,6 +33,7 @@ public:
|
||||
Engine engine;
|
||||
|
||||
private:
|
||||
TextureRepository *texRepo;
|
||||
LightManager lightManager;
|
||||
FloorManager *floorManager;
|
||||
Player *player;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#include <utils/math.hpp>
|
||||
#include <utils/debug.hpp>
|
||||
#include <loaders/obj_loader.hpp>
|
||||
|
||||
// ----
|
||||
// Constructors/Destructors
|
||||
@@ -34,8 +33,6 @@ FloorManager::FloorManager(int t_floorAmount)
|
||||
FloorManager::~FloorManager()
|
||||
{
|
||||
delete[] spirals;
|
||||
delete[] spec;
|
||||
delete[] obj;
|
||||
delete[] meshes;
|
||||
}
|
||||
|
||||
@@ -83,15 +80,13 @@ void FloorManager::initFloors()
|
||||
PRINT_LOG("Initializing floors");
|
||||
meshes = new Mesh *[floorAmount];
|
||||
|
||||
Vector3 initPos = Vector3(0.0F, 0.0F, 0.0F);
|
||||
meshes[0] = new Mesh();
|
||||
meshes[0]->loadObj("floor/", "floor.obj", initPos, 2.0F);
|
||||
meshes[0]->loadObj("floor/", "floor", 2.0F, false);
|
||||
meshes[0]->shouldBeFrustumCulled = true;
|
||||
obj = meshes[0]->obj;
|
||||
spec = meshes[0]->spec;
|
||||
meshes[0]->shouldBeLighted = true;
|
||||
for (u8 i = 0; i < floorAmount; i++)
|
||||
{
|
||||
floors[i].init(obj, spec, spirals[i], i);
|
||||
floors[i].init(meshes[0], spirals[i], i);
|
||||
meshes[i] = &floors[i].mesh;
|
||||
}
|
||||
PRINT_LOG("Floors initialized!");
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
class Player; // Forward definition
|
||||
|
||||
#include <models/math/point.hpp>
|
||||
#include <models/obj_model.hpp>
|
||||
#include <models/mesh_spec.hpp>
|
||||
#include <modules/camera_base.hpp>
|
||||
#include <models/audio_listener.hpp>
|
||||
|
||||
@@ -33,12 +31,10 @@ public:
|
||||
void update(Player &t_player);
|
||||
Mesh **meshes;
|
||||
void onAudioTick();
|
||||
MeshSpec *spec;
|
||||
|
||||
private:
|
||||
u8 audioOffset, audioMode;
|
||||
u32 audioTick;
|
||||
ObjModel *obj;
|
||||
Point *spirals;
|
||||
void calcSpiral(int X, int Y);
|
||||
void initFloors();
|
||||
|
||||
@@ -36,10 +36,10 @@ Floor::~Floor() {}
|
||||
* @param spiral Spiral position
|
||||
* @param initOffset Number of floor (index)
|
||||
*/
|
||||
void Floor::init(ObjModel *obj, MeshSpec *spec, Point &spiral, u8 &initOffset)
|
||||
void Floor::init(Mesh *mother, Point &spiral, u8 &initOffset)
|
||||
{
|
||||
Vector3 initPos = Vector3(0.00F, -10.00F, 0.00F);
|
||||
this->mesh.setObj(initPos, obj, spec);
|
||||
this->mesh.position.set(0.00F, -10.00F, 0.00F);
|
||||
this->mesh.loadFrom(*mother);
|
||||
this->initOffset = initOffset;
|
||||
this->animTimer = rand() % FLOOR_ANIMATION_LENGTH;
|
||||
this->mesh.shouldBeLighted = true;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
class Player; // Forward definition
|
||||
|
||||
#include <models/mesh.hpp>
|
||||
#include <models/obj_model.hpp>
|
||||
#include <models/math/point.hpp>
|
||||
#include <tamtypes.h>
|
||||
|
||||
@@ -30,7 +29,7 @@ public:
|
||||
Floor();
|
||||
~Floor();
|
||||
|
||||
void init(ObjModel *obj, MeshSpec *spec, Point &spiral, u8 &initOffset);
|
||||
void init(Mesh *mother, Point &spiral, u8 &initOffset);
|
||||
void animate(Player &player);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ Player::Player()
|
||||
this->gravity = 0.1F;
|
||||
this->lift = -1.0F;
|
||||
|
||||
Vector3 initPos = Vector3(0.00F, 20.00F, 0.00F);
|
||||
this->mesh.loadMD2("warrior/", "warrior.md2", initPos, 0.2F);
|
||||
this->mesh.loadMD2("warrior/", "warrior", 0.2F, true);
|
||||
this->mesh.position.set(0.00F, 20.00F, 0.00F);
|
||||
this->mesh.rotation.x = -1.6F;
|
||||
this->mesh.shouldBeBackfaceCulled = false;
|
||||
this->mesh.shouldBeFrustumCulled = false;
|
||||
@@ -39,7 +39,6 @@ Player::Player()
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
delete[] this->spec;
|
||||
}
|
||||
|
||||
// ----
|
||||
@@ -83,7 +82,7 @@ void Player::updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager
|
||||
Vector3 max = Vector3();
|
||||
for (int i = 0; i < floorManager.floorAmount; i++)
|
||||
{
|
||||
floorManager.floors[i].mesh.getMinMax(&min, &max);
|
||||
getMinMax(&floorManager.floors[i].mesh, &min, &max);
|
||||
this->isCollideFloor = this->playerNextPosition.collidesSquare(min, max);
|
||||
if (this->isCollideFloor == 1)
|
||||
break;
|
||||
@@ -106,6 +105,42 @@ void Player::onBeforePlayerFloorMove(Floor *floor, float &newY)
|
||||
this->mesh.position.y -= -newY * 1.05F;
|
||||
}
|
||||
|
||||
/** Calculates minimum and maximum X, Y, Z of mesh vertices + current position */
|
||||
void Player::getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max)
|
||||
{
|
||||
Vector3 calc = Vector3();
|
||||
u8 isInitialized = 0;
|
||||
Vector3 *boundingBox = t_mesh->getCurrentBoundingBox();
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
{
|
||||
calc.set(
|
||||
boundingBox[i].x + t_mesh->position.x,
|
||||
boundingBox[i].y + t_mesh->position.y,
|
||||
boundingBox[i].z + t_mesh->position.z);
|
||||
if (isInitialized == 0)
|
||||
{
|
||||
isInitialized = 1;
|
||||
t_min->set(calc);
|
||||
t_max->set(calc);
|
||||
}
|
||||
|
||||
if (t_min->x > calc.x)
|
||||
t_min->x = calc.x;
|
||||
if (calc.x > t_max->x)
|
||||
t_max->x = calc.x;
|
||||
|
||||
if (t_min->y > calc.y)
|
||||
t_min->y = calc.y;
|
||||
if (calc.y > t_max->y)
|
||||
t_max->y = calc.y;
|
||||
|
||||
if (t_min->z > calc.z)
|
||||
t_min->z = calc.z;
|
||||
if (calc.z > t_max->z)
|
||||
t_max->z = calc.z;
|
||||
}
|
||||
}
|
||||
|
||||
/** Update player position by gravity and update index of current floor */
|
||||
void Player::updateGravity(Pad &pad, FloorManager &floorManager)
|
||||
{
|
||||
@@ -118,7 +153,7 @@ void Player::updateGravity(Pad &pad, FloorManager &floorManager)
|
||||
this->isOnFloor = 0;
|
||||
for (int i = 0; i < floorManager.floorAmount; i++)
|
||||
{
|
||||
floorManager.floors[i].mesh.getMinMax(&min, &max);
|
||||
getMinMax(&floorManager.floors[i].mesh, &min, &max);
|
||||
this->isOnFloor = this->mesh.position.isOnSquare(min, max);
|
||||
if (this->isOnFloor == 1)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "../managers/floor_manager.hpp"
|
||||
#include "../camera.hpp"
|
||||
#include <modules/pad.hpp>
|
||||
#include <models/mesh_spec.hpp>
|
||||
#include <tamtypes.h>
|
||||
|
||||
/** Player 3D object class */
|
||||
@@ -25,7 +24,6 @@ public:
|
||||
float gravity, velocity, lift;
|
||||
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
|
||||
Mesh mesh;
|
||||
MeshSpec *spec;
|
||||
Player();
|
||||
~Player();
|
||||
|
||||
@@ -34,6 +32,7 @@ public:
|
||||
|
||||
private:
|
||||
Vector3 playerNextPosition;
|
||||
void getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max);
|
||||
void updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager);
|
||||
void updateGravity(Pad &pad, FloorManager &floorManager);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user