fixed floors sample

This commit is contained in:
Sandro Sobczyński
2020-11-03 16:44:39 +01:00
parent 5aa2a9bdb5
commit b75b2d6e4f
30 changed files with 331 additions and 224 deletions
+48 -31
View File
@@ -7,10 +7,10 @@
<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 />
@@ -25,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)
@@ -34,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">
<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/ps2-tyra/tyra/tree/master/src/samples/floors)
* [Ari (WIP)](https://github.com/ps2-tyra/tyra/tree/master/src/samples/ari)
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 :/
### Contributors wanted
#### I will be grateful for any help, Discord: Sandro#3402
**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:
### 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, 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
* 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
### 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
### 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
@@ -78,7 +84,8 @@ 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.
To get a local copy up and running follow these simple steps.
YouTube tutorials soon!
### Prerequisites
@@ -116,9 +123,9 @@ See the [open issues](https://github.com/ps2-tyra/tyra/issues) for a list of pro
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
@@ -130,6 +137,16 @@ Distributed under the Apache License 2.0 License. See `LICENSE` for more informa
Sandro Sobczyński - sandro.sobczynski@gmail.com
[![LinkedIn][linkedin-shield]][linkedin-url]
## Thanks
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
+8 -5
View File
@@ -79,11 +79,14 @@ public:
*/
MeshMaterial *getMaterialById(const u32 &t_id) const { return frames[0].getMaterialById(t_id); }
/** Returns bounding box vertex at given index with added mesh position.
* @param o_result Result
* @param offset 0-7. Because, bounding box have 8 corners
/**
* Returns bounding vertex of current frame.
* @param i 0-7. Because, bounding box have 8 corners
*/
void getCurrentBoundingBoxVertex(Vector3 &o_result, const u32 &t_index);
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
@@ -171,7 +174,7 @@ public:
*/
const u8 &isStayAnimationSet() const { return animState.isStayFrameSet; };
/** Check if mesh is visible in view frustum */
/** True when mesh is in view frustum */
u8 isInFrustum(Plane *t_frustumPlanes);
/**
+9 -3
View File
@@ -75,11 +75,17 @@ public:
/** 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 &getBoundingBox(const u8 &i) { return boundingBox[i]; };
Vector3 &getBoundingBoxVertex(const u8 &i) { return boundingBox[i]; };
// ----
// Setters
@@ -126,11 +132,11 @@ public:
void allocateMaterials(const u32 &t_val);
/**
* Calculates bounding box (AABB).
* 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 calculateBoundingBox();
void calculateBoundingBoxes();
private:
Vector3 boundingBox[8];
+26 -1
View File
@@ -12,6 +12,8 @@
#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.
@@ -58,6 +60,18 @@ public:
/** 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
// ----
@@ -93,10 +107,21 @@ public:
/** 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;
u8 _isNameSet, _areFacesAllocated, _isBoundingBoxCalculated;
char *name;
};
+2 -2
View File
@@ -33,7 +33,7 @@ public:
~GifSender();
void initPacket(u8 context);
void addObjects(RenderData *t_renderData, Mesh **t_objects3D, u32 t_amount, LightBulb *t_bulbs, u16 t_bulbsCount, texbuffer_t *textureBuffer);
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);
@@ -54,7 +54,7 @@ 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 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);
};
@@ -80,13 +80,16 @@ public:
// ----
/** 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);
+2 -2
View File
@@ -29,14 +29,14 @@ public:
// TODO refactor
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_coordinates, prim_t *t_prim, texbuffer_t *textureBuffer);
VU1 vu1; // TODO
MATRIX localWorld, localScreen;
VECTOR position, rotation;
u32 vertCount;
VU1 vu1;
};
#endif
+1 -1
View File
@@ -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
{
+1 -1
View File
@@ -47,7 +47,7 @@ void DffLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
fread(&data, sizeof(u8), fileSize, file);
fclose(file);
serialize(o_result, t_invertT, data, t_scale);
o_result->calculateBoundingBox();
o_result->calculateBoundingBoxes();
PRINT_LOG("Dff file loaded!");
}
+1 -1
View File
@@ -147,6 +147,6 @@ MeshFrame *MD2Loader::load(u32 &o_framesCount, char *t_subpath, char *t_nameWith
delete[] finalPath;
o_framesCount = framesCount;
for (u32 i = 0; i < framesCount; i++)
resultFrames[i].calculateBoundingBox();
resultFrames[i].calculateBoundingBoxes();
return resultFrames;
}
+1 -1
View File
@@ -96,7 +96,7 @@ void ObjLoader::load(MeshFrame *o_result, char *t_filename, float t_scale, u8 t_
else
break;
}
o_result->calculateBoundingBox();
o_result->calculateBoundingBoxes();
fclose(file);
}
+6 -13
View File
@@ -238,19 +238,11 @@ u32 Mesh::getDrawData(u32 t_materialIndex, VECTOR *o_vertices, VECTOR *o_normals
return addedFaces;
}
void Mesh::getCurrentBoundingBoxVertex(Vector3 &o_result, const u32 &t_index)
{
o_result.set(
frames[animState.currentFrame].getBoundingBox(t_index).x + position.x,
frames[animState.currentFrame].getBoundingBox(t_index).y + position.y,
frames[animState.currentFrame].getBoundingBox(t_index).z + position.z);
}
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;
@@ -260,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++)
{
getCurrentBoundingBoxVertex(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
@@ -288,7 +283,6 @@ void Mesh::setDefaultColor()
/** Sets texture level of details settings and CLUT settings */
void Mesh::setDefaultLODAndClut()
{
PRINT_LOG("Setting LOD, CLUT");
lod.calculation = LOD_USE_K;
lod.max_level = 0;
lod.mag_filter = LOD_MAG_NEAREST;
@@ -301,5 +295,4 @@ void Mesh::setDefaultLODAndClut()
clut.psm = 0;
clut.load_method = CLUT_NO_LOAD;
clut.address = 0;
PRINT_LOG("LOD, CLUT set!");
}
+3 -1
View File
@@ -91,13 +91,15 @@ void MeshFrame::allocateMaterials(const u32 &t_val)
_areMaterialsAllocated = true;
}
void MeshFrame::calculateBoundingBox()
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;
+67
View File
@@ -23,6 +23,7 @@ MeshMaterial::MeshMaterial()
facesCount = 0;
_isNameSet = false;
_areFacesAllocated = false;
_isBoundingBoxCalculated = false;
}
MeshMaterial::~MeshMaterial()
@@ -65,3 +66,69 @@ void MeshMaterial::setName(char *t_val)
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;
}
+16 -34
View File
@@ -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, texbuffer_t *textureBuffer)
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]->lod);
q = draw_texturebuffer(q, 0, textureBuffer, &t_objects3D[0]->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);
addCurrentCalcs(vertexCount);
delete[] xyz;
delete[] rgbaq;
delete[] st;
}
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(); // TODO err
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, *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);
@@ -215,9 +202,9 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
for (u32 i = 0; i < vertexCount; i++)
{
// Apply the light value to the colour.
colors[i][0] = (t_mesh.color.r * lights[i][0]);
colors[i][1] = (t_mesh.color.g * lights[i][1]);
colors[i][2] = (t_mesh.color.b * lights[i][2]);
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);
}
@@ -238,12 +225,7 @@ u32 GifSender::calc3DObject(Matrix t_perspective, Mesh &t_mesh, RenderData *t_re
convertCalcs(vertexCount, vertices, colors, coordinates, t_mesh.color);
delete[] vertices;
delete[] normals;
delete[] colors;
delete[] coordinates;
return vertexCount;
}
void GifSender::convertCalcs(u32 t_vertexCount, VECTOR *t_vertices, VECTOR *t_colors, VECTOR *t_sts, color_t &t_color)
+26 -16
View File
@@ -163,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, &textureBuffer);
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();
changeTexture(t_mesh, 0);
gifSender->initPacket(context);
// TODO
gifSender->addObjects(&renderData, &t_mesh, 1, t_bulbs, t_bulbsCount, &textureBuffer);
gifSender->sendPacket();
draw_wait_finish();
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);
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();
delete[] vertices;
delete[] normals;
delete[] coordinates;
}
}
/** PATH3 Many */
@@ -195,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);
}
@@ -205,7 +213,7 @@ 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
vifSender->sendMatrices(renderData, t_mesh->position, t_mesh->rotation);
if (!t_mesh->isDataLoaded())
PRINT_ERR("Can't draw, because no mesh data was loaded!");
@@ -213,6 +221,8 @@ void Renderer::draw(Mesh *t_mesh, LightBulb *t_bulbs, u16 t_bulbsCount)
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->getMaterial(i).getFacesCount();
VECTOR *vertices = new VECTOR[vertCount];
VECTOR *normals = new VECTOR[vertCount];
+43 -40
View File
@@ -37,19 +37,17 @@ VifSender::~VifSender() {}
// Methods
// ----
void VifSender::sendMatrices(const RenderData &t_renderData, const Vector3 &t_position, const Vector3 &t_rotation)
{
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_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)
{
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);
create_local_world(localWorld, position, rotation);
create_local_screen(localScreen, localWorld, t_renderData->worldView->data, t_perspective.data);
// TODO Send it once man xd
vu1.sendSingleRefList(0, &localScreen, 4);
// we have to split 3D object into small parts, because of small memory of VU1
for (u32 i = 0; i < vertCount2;)
{
@@ -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
+1 -1
View File
@@ -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;
+7 -2
View File
@@ -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
+2 -11
View File
@@ -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"
@@ -84,17 +75,17 @@ void Ari::onInit()
island->loadDff("sunnyisl/", "sunnyisl", 0.1F, false);
island->rotation.x = -1.6F;
island->position.set(0.0F, 10.0F, 20.0F);
island->shouldBeFrustumCulled = false;
island->shouldBeBackfaceCulled = true;
island->shouldBeFrustumCulled = false;
islandAddons = new Mesh();
islandAddons->loadDff("sunnyisl/", "sunnyisl3", 0.1F, false);
islandAddons->rotation.x = -1.6F;
islandAddons->position.set(0.0F, 10.0F, 20.0F);
islandAddons->shouldBeFrustumCulled = false;
skybox = new Mesh();
skybox->loadObj("skybox/", "skybox", 100.0F, false);
skybox->shouldBeFrustumCulled = false;
waterFloors = new Mesh *[WATER_TILES_COUNT];
spirals = new Point[WATER_TILES_COUNT];
+4 -4
View File
@@ -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 \
+2 -2
View File
@@ -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
+6
View File
@@ -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()
+2
View File
@@ -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();
+3 -3
View File
@@ -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;
+1 -2
View File
@@ -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);
};
+36 -33
View File
@@ -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,37 +105,41 @@ void Player::onBeforePlayerFloorMove(Floor *floor, float &newY)
this->mesh.position.y -= -newY * 1.05F;
}
/** Calculates minimum and maximum X, Y, Z of this 3D objects vertices + current position */
// void Mesh::getMinMax(Vector3 *t_min, Vector3 *t_max)
// {
// Vector3 calc = Vector3();
// u8 isInitialized = 0;
// for (u32 i = 0; i < 8; i++)
// {
// getFarthestVertex(&calc, i);
// if (isInitialized == 0)
// {
// isInitialized = 1;
// t_min->set(calc);
// t_max->set(calc);
// }
/** 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->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->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_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)
@@ -150,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)
{
+1 -2
View File
@@ -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);
};