├── P3DBenchmark
├── P3DBenchmark.sav
├── source
│ ├── recip.cpp
│ ├── fixeddiv.s
│ └── main.iwram.cpp
├── P3DBenchmark.elf
├── P3DBenchmark.gba
├── Performance.xlsx
├── include
│ └── model.h
├── P3DBenchmark.pro
└── Makefile
├── Potato3dGBAExample
├── source
│ ├── bspmodel.cpp
│ ├── object3d.cpp
│ ├── recip.cpp
│ ├── render.iwram.cpp
│ ├── model.h
│ ├── fixeddiv.s
│ └── main.cpp
├── test.bmp
├── Potato3dGBAExample.elf
├── Potato3dGBAExample.gba
├── include
│ └── model.h
├── Potato3dGBAExample.pro
└── Makefile
├── P3DFps.xlsx
├── Potato3dExample2
├── source
│ ├── recip.redir.cpp
│ ├── bspmodel.redir.iwram.cpp
│ ├── worldmodel.cpp
│ ├── main.cpp
│ ├── model.cpp
│ ├── setup.cpp
│ ├── fixeddiv.iwram.s
│ ├── collision.cpp
│ ├── camera.cpp
│ ├── videosystem.cpp
│ └── mainloop.iwram.cpp
├── include
│ ├── model.h
│ ├── setup.h
│ ├── common.h
│ ├── collision.h
│ ├── worldmodel.h
│ ├── camera.h
│ ├── mainloop.h
│ └── videosystem.h
├── P3DExample2.pro
└── Makefile
├── Potato3dExample
├── CodeProphet.lib
├── main.cpp
├── mainwindow.h
├── mainwindow2.h
├── Potato3dExample.pro
├── mainwindow.cpp
└── mainwindow2.cpp
├── potato3d.h
├── Config.h
├── P3DObj2Bsp
├── resources.qrc
├── bspmodelexport.h
├── Config.h
├── P3DObj2Bsp.pro
├── .gitignore
├── objloader.h
├── main.cpp
├── bspbuilder.h
└── bspmodelexport.cpp
├── 3dmaths
├── recip.h
├── f3dmath.h
├── divide.h
├── plane.h
├── v2.h
├── v4.h
├── aabb.h
├── v3.h
├── utils.h
└── fp.h
├── README.md
├── ConfigInternal.h
├── ConfigUser.h
├── TextureCache.h
├── object3d.h
├── BspModelDefs.h
├── Pixel.h
├── Qt Debug Helper
└── personaltypes.py
├── .gitignore
├── bspmodel.cpp
├── bspmodel.h
├── RenderTarget.h
├── RenderCommon.h
├── PixelShaderGBA8.h
├── PixelShaderDefault.h
├── object3d.cpp
└── RenderDevice.h
/P3DBenchmark/P3DBenchmark.sav:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/P3DBenchmark/source/recip.cpp:
--------------------------------------------------------------------------------
1 | #include "../../3dmaths/recip.cpp"
2 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/bspmodel.cpp:
--------------------------------------------------------------------------------
1 | #include "../../bspmodel.cpp"
2 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/object3d.cpp:
--------------------------------------------------------------------------------
1 | #include "../../object3d.cpp"
2 |
--------------------------------------------------------------------------------
/P3DFps.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/P3DFps.xlsx
--------------------------------------------------------------------------------
/Potato3dExample2/source/recip.redir.cpp:
--------------------------------------------------------------------------------
1 | #include "../../3dmaths/recip.cpp"
2 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/recip.cpp:
--------------------------------------------------------------------------------
1 | #include "../../3dmaths/recip.cpp"
2 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/bspmodel.redir.iwram.cpp:
--------------------------------------------------------------------------------
1 | //#include "common.h"
2 | #include "../../bspmodel.cpp"
3 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/test.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/Potato3dGBAExample/test.bmp
--------------------------------------------------------------------------------
/P3DBenchmark/P3DBenchmark.elf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/P3DBenchmark/P3DBenchmark.elf
--------------------------------------------------------------------------------
/P3DBenchmark/P3DBenchmark.gba:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/P3DBenchmark/P3DBenchmark.gba
--------------------------------------------------------------------------------
/P3DBenchmark/Performance.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/P3DBenchmark/Performance.xlsx
--------------------------------------------------------------------------------
/Potato3dExample/CodeProphet.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/Potato3dExample/CodeProphet.lib
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/render.iwram.cpp:
--------------------------------------------------------------------------------
1 | #include "../../RenderTarget.cpp"
2 | #include "../../RenderDevice.cpp"
3 |
--------------------------------------------------------------------------------
/potato3d.h:
--------------------------------------------------------------------------------
1 | #ifndef POTATO3D
2 | #define POTATO3D
3 |
4 | #include "Config.h"
5 | #include "object3d.h"
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/Potato3dGBAExample.elf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/Potato3dGBAExample/Potato3dGBAExample.elf
--------------------------------------------------------------------------------
/Potato3dGBAExample/Potato3dGBAExample.gba:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/doomhack/Potato3d/HEAD/Potato3dGBAExample/Potato3dGBAExample.gba
--------------------------------------------------------------------------------
/Config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_H
2 | #define CONFIG_H
3 |
4 | #include "ConfigUser.h"
5 | #include "ConfigInternal.h"
6 |
7 | #endif // CONFIG_H
8 |
--------------------------------------------------------------------------------
/P3DObj2Bsp/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | nQuantCpp.exe
4 |
5 |
6 |
--------------------------------------------------------------------------------
/P3DBenchmark/include/model.h:
--------------------------------------------------------------------------------
1 | #ifndef MODEL_H
2 | #define MODEL_H
3 |
4 | const extern unsigned char modeldata[];
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/model.h:
--------------------------------------------------------------------------------
1 | #ifndef MODEL_H
2 | #define MODEL_H
3 |
4 | const extern unsigned char modeldata[];
5 |
6 | #endif // MODEL_H
7 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/include/model.h:
--------------------------------------------------------------------------------
1 | #ifndef MODEL_H
2 | #define MODEL_H
3 |
4 | const extern unsigned char modeldata[];
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/model.h:
--------------------------------------------------------------------------------
1 | #ifndef MODEL_H
2 | #define MODEL_H
3 |
4 | const extern unsigned char modeldata[];
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/setup.h:
--------------------------------------------------------------------------------
1 | #ifndef SETUP_H
2 | #define SETUP_H
3 |
4 | class Setup
5 | {
6 | public:
7 | Setup();
8 |
9 | void DoSetup();
10 | };
11 |
12 | #endif // SETUP_H
13 |
--------------------------------------------------------------------------------
/3dmaths/recip.h:
--------------------------------------------------------------------------------
1 | #ifndef RECIP_H
2 | #define RECIP_H
3 |
4 | namespace P3D
5 | {
6 | extern const int reciprocalTable[];
7 | extern const unsigned char shiftTable[];
8 | };
9 |
10 | #endif // RECIP_H
11 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/worldmodel.cpp:
--------------------------------------------------------------------------------
1 | #include "../include/worldmodel.h"
2 |
3 | WorldModel::WorldModel()
4 | {
5 |
6 | }
7 |
8 | const P3D::BspModel* WorldModel::GetModel() const
9 | {
10 | return model;
11 | }
12 |
--------------------------------------------------------------------------------
/Potato3dExample/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow2.h"
2 | #include "mainwindow.h"
3 |
4 |
5 | #include
6 |
7 | int main(int argc, char *argv[])
8 | {
9 | QApplication a(argc, argv);
10 | MainWindow w;
11 | w.show();
12 | return a.exec();
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/main.cpp:
--------------------------------------------------------------------------------
1 | #include "../include/mainloop.h"
2 | #include "../include/setup.h"
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | Setup setup;
7 | MainLoop* loop = new MainLoop;
8 |
9 | setup.DoSetup();
10 | loop->Run();
11 |
12 | return 0;
13 | }
14 |
--------------------------------------------------------------------------------
/3dmaths/f3dmath.h:
--------------------------------------------------------------------------------
1 | #ifndef P3DMATH_H
2 | #define P3DMATH_H
3 |
4 | #include
5 |
6 |
7 | #include "fp.h"
8 | #include "v4.h"
9 | #include "v3.h"
10 | #include "v2.h"
11 | #include "m4.h"
12 | #include "plane.h"
13 | #include "aabb.h"
14 | #include "utils.h"
15 |
16 |
17 | #endif // P3DMATH_H
18 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/common.h:
--------------------------------------------------------------------------------
1 | #ifndef COMMON_H
2 | #define COMMON_H
3 |
4 | #include
5 | #ifdef __arm__
6 | #define GBA
7 | #endif
8 |
9 | typedef enum Keys : unsigned int
10 | {
11 | KeyLeft = 1,
12 | KeyRight = 2,
13 | KeyUp = 4,
14 | KeyDown = 8
15 | } Keys;
16 |
17 |
18 | #endif // COMMON_H
19 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/model.cpp:
--------------------------------------------------------------------------------
1 | //#include "C:/Users/Zak/Downloads/GE_Temple/temple.cpp"
2 | //#include "C:/Users/Zak/Downloads/Dam/dam.cpp"
3 | //#include "C:/Users/Zak/Documents/GitProjects/Potato3d/Potato3dExample/models/Streets/Streets.cpp"
4 | #include "C:/Users/Zak/Downloads/Villa/villa.cpp"
5 | //#include "C:/Users/Zak/Downloads/DDHQ2/ddhq2.cpp"
6 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/collision.h:
--------------------------------------------------------------------------------
1 | #ifndef COLLISION_H
2 | #define COLLISION_H
3 |
4 | #include "../include/common.h"
5 | #include "../../Config.h"
6 | #include "../../3dmaths/f3dmath.h"
7 | #include "../../bspmodel.h"
8 |
9 | class Collision
10 | {
11 | public:
12 | Collision();
13 | bool CheckCollision(const P3D::BspModelTriangle* tri, const P3D::V3& point, const P3D::fp radius, P3D::V3& resolutionVector);
14 | };
15 |
16 | #endif // COLLISION_H
17 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/worldmodel.h:
--------------------------------------------------------------------------------
1 | #ifndef WORLDMODEL_H
2 | #define WORLDMODEL_H
3 |
4 | #include "../include/common.h"
5 | #include "../../Config.h"
6 | #include "../../3dmaths/f3dmath.h"
7 | #include "../../bspmodel.h"
8 | #include "model.h"
9 |
10 |
11 | class WorldModel
12 | {
13 | public:
14 | explicit WorldModel();
15 |
16 | const P3D::BspModel* GetModel() const;
17 | private:
18 | const P3D::BspModel* model = (P3D::BspModel*)&modeldata;
19 | };
20 |
21 | #endif // WORLDMODEL_H
22 |
--------------------------------------------------------------------------------
/P3DBenchmark/P3DBenchmark.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | CONFIG += console c++20
3 | CONFIG -= app_bundle
4 | CONFIG += force_debug_info
5 | QT += core gui
6 |
7 |
8 |
9 | INCLUDEPATH += "include"
10 |
11 | INCLUDEPATH += "C:\devkitPro\libgba\include"
12 |
13 | SOURCES += \
14 | source/main.iwram.cpp \
15 | source/recip.cpp
16 |
17 |
18 |
19 | #QMAKE_CXXFLAGS += /GL
20 | #QMAKE_CFLAGS += /GL
21 |
22 | #QMAKE_LFLAGS += /LTCG
23 |
24 | DISTFILES += \
25 | Makefile
26 |
27 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/setup.cpp:
--------------------------------------------------------------------------------
1 | #include "../include/common.h"
2 | #include "../include/setup.h"
3 |
4 |
5 | #ifdef GBA
6 | #include
7 | #include
8 | #include
9 |
10 | #define REG_WAITCNT *((vu16 *)(0x4000204))
11 | #endif
12 |
13 | Setup::Setup()
14 | {
15 |
16 | }
17 |
18 | void Setup::DoSetup()
19 | {
20 | #ifdef GBA
21 | irqInit();
22 |
23 | //Set gamepak wait states and prefetch.
24 | REG_WAITCNT = 0x46DA;
25 |
26 | SetMode(MODE_4 | BG2_ENABLE | BIT(5));
27 | #else
28 |
29 | #endif
30 | }
31 |
--------------------------------------------------------------------------------
/P3DObj2Bsp/bspmodelexport.h:
--------------------------------------------------------------------------------
1 | #ifndef BSPMODELEXPORT_H
2 | #define BSPMODELEXPORT_H
3 |
4 | #include
5 | #include
6 |
7 | #include "bspbuilder.h"
8 | #include "config.h"
9 | #include "../BspModelDefs.h"
10 |
11 |
12 | namespace Obj2Bsp
13 | {
14 | class BspModelExport
15 | {
16 | public:
17 | BspModelExport();
18 |
19 | QByteArray ExportBSPModel(Obj2Bsp::BspNode* root, Model3d* model);
20 |
21 | private:
22 | void TraverseNodesRecursive(BspNode* n, QList& nodeList);
23 |
24 | };
25 |
26 | }
27 |
28 | #endif // BSPMODELEXPORT_H
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Potato3d
2 |
3 | A simple, fast 3d renderer for stuff with slow processors.
4 |
5 |
6 | Still very much a work in progress.
7 |
8 |
9 | Currently uses BSP to sort and cull polygons.
10 |
11 | Very little division in the hot path. I've been able to use a reciprocal table to get rid of most division.
12 |
13 | All math execept for one time set-up stuff is fixed point. Can also use float or doubles by just changing a #define.
14 |
15 |
16 | Renders textures perspective-correctish. Perspective correct tex corodinates are computed every 16px and linear interpolated from there.
17 |
18 |
19 | Rendering is front-to-back with no Z-buffer and zero overdraw. But the span buffering is still a performance hog.
20 |
21 |
--------------------------------------------------------------------------------
/P3DObj2Bsp/Config.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIG_H
2 | #define CONFIG_H
3 |
4 | #include
5 | #include
6 |
7 | #include "../3dmaths/f3dmath.h"
8 |
9 | namespace Obj2Bsp
10 | {
11 | inline constexpr int TEX_SIZE = 64;
12 | inline constexpr int TEX_MAX_TILE = 8;
13 |
14 | inline constexpr QImage::Format textureFormat = QImage::Format_Indexed8;
15 |
16 |
17 | inline constexpr int LIGHT_LEVELS = 8;
18 | inline constexpr int FOG_LEVELS = 16;
19 |
20 | inline constexpr int FOG_COLOR = 0x799ED7;
21 |
22 | inline constexpr const char QUANT_ALGO[] = "PNN"; //PNN, DIV, NEU, WU
23 | }
24 |
25 | namespace P3D
26 | {
27 | typedef quint8 pixel;
28 |
29 | //typedef double fp;
30 | typedef P3D::FP16 fp;
31 | }
32 |
33 | #endif // CONFIG_H
34 |
--------------------------------------------------------------------------------
/P3DObj2Bsp/P3DObj2Bsp.pro:
--------------------------------------------------------------------------------
1 | QT = core gui
2 |
3 | CONFIG += c++20 cmdline
4 |
5 | # You can make your code fail to compile if it uses deprecated APIs.
6 | # In order to do so, uncomment the following line.
7 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
8 |
9 | SOURCES += \
10 | bspbuilder.cpp \
11 | bspmodelexport.cpp \
12 | main.cpp \
13 | objloader.cpp
14 |
15 | # Default rules for deployment.
16 | qnx: target.path = /tmp/$${TARGET}/bin
17 | else: unix:!android: target.path = /opt/$${TARGET}/bin
18 | !isEmpty(target.path): INSTALLS += target
19 |
20 | HEADERS += \
21 | ../BspModelDefs.h \
22 | bspbuilder.h \
23 | bspmodelexport.h \
24 | config.h \
25 | objloader.h
26 |
27 | RESOURCES += \
28 | resources.qrc
29 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/fixeddiv.iwram.s:
--------------------------------------------------------------------------------
1 | .arm
2 | .align 2
3 |
4 | .global udiv64_arm
5 | .type udiv64_arm, %function
6 |
7 | udiv64_arm:
8 |
9 | /*
10 | Tweaked version of 64/32 division found in
11 | section 7.3.1.3 of
12 | ARM System Developer’s Guide
13 | Designing and Optimizing System Software
14 |
15 | ISBN: 1-55860-874-5
16 |
17 | r0 = numerator high, return quotient
18 | r1 = numerator low
19 | r2 = denominator
20 | r3 = scratch
21 | */
22 |
23 | cmp r0, r2
24 | bcs .overflow_32
25 | rsb r2, r2, #0
26 | adds r3, r1, r1
27 | adcs r1, r2, r0, LSL#1
28 | subcc r1, r1, r2
29 |
30 | .rept 31
31 | adcs r3, r3, r3
32 | adcs r1, r2, r1, LSL#1
33 | subcc r1,r1, r2
34 | .endr
35 |
36 | adcs r0, r3, r3
37 | bx lr
38 |
39 | .overflow_32:
40 | mov r0, #-1
41 | bx lr
42 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/camera.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMERA_H
2 | #define CAMERA_H
3 |
4 | #include "../include/common.h"
5 | #include "../../Config.h"
6 | #include "../../3dmaths/f3dmath.h"
7 |
8 | class Camera
9 | {
10 | public:
11 | Camera();
12 |
13 | const P3D::V3& GetPosition() const;
14 | const P3D::V3 GetEyePosition() const;
15 | const P3D::V3& GetAngle() const;
16 | void MovePosition(const P3D::V3& delta);
17 | void SetPosition(const P3D::V3& pos);
18 |
19 | void HandleInput(unsigned int keyState, P3D::fp gravity_velocity);
20 |
21 | private:
22 | P3D::V3 position = P3D::V3(0,50,0);
23 | P3D::V3 angle = P3D::V3(0,0,0);
24 | const P3D::V3 eyeOffset = P3D::V3(0,100,0);
25 | };
26 |
27 | #endif // CAMERA_H
28 |
--------------------------------------------------------------------------------
/P3DBenchmark/source/fixeddiv.s:
--------------------------------------------------------------------------------
1 | .section .iwram
2 | .arm
3 | .align
4 |
5 | .global udiv64_arm
6 |
7 | udiv64_arm:
8 |
9 | /*
10 | Tweaked version of 64/32 division found in
11 | section 7.3.1.3 of
12 | ARM System Developer’s Guide
13 | Designing and Optimizing System Software
14 |
15 | ISBN: 1-55860-874-5
16 |
17 | r0 = numerator high, return quotient
18 | r1 = numerator low
19 | r2 = denominator
20 | r3 = scratch
21 | */
22 |
23 | cmp r0, r2
24 | bcs .overflow_32
25 | rsb r2, r2, #0
26 | adds r3, r1, r1
27 | adcs r1, r2, r0, LSL#1
28 | subcc r1, r1, r2
29 |
30 | .rept 31
31 | adcs r3, r3, r3
32 | adcs r1, r2, r1, LSL#1
33 | subcc r1,r1, r2
34 | .endr
35 |
36 | adcs r0, r3, r3
37 | bx lr
38 |
39 | .overflow_32:
40 | mov r0, #-1
41 | bx lr
42 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/source/fixeddiv.s:
--------------------------------------------------------------------------------
1 | .section .iwram
2 | .arm
3 | .align
4 |
5 | .global udiv64_arm
6 |
7 | udiv64_arm:
8 |
9 | /*
10 | Tweaked version of 64/32 division found in
11 | section 7.3.1.3 of
12 | ARM System Developer’s Guide
13 | Designing and Optimizing System Software
14 |
15 | ISBN: 1-55860-874-5
16 |
17 | r0 = numerator high, return quotient
18 | r1 = numerator low
19 | r2 = denominator
20 | r3 = scratch
21 | */
22 |
23 | cmp r0, r2
24 | bcs .overflow_32
25 | rsb r2, r2, #0
26 | adds r3, r1, r1
27 | adcs r1, r2, r0, LSL#1
28 | subcc r1, r1, r2
29 |
30 | .rept 31
31 | adcs r3, r3, r3
32 | adcs r1, r2, r1, LSL#1
33 | subcc r1,r1, r2
34 | .endr
35 |
36 | adcs r0, r3, r3
37 | bx lr
38 |
39 | .overflow_32:
40 | mov r0, #-1
41 | bx lr
42 |
--------------------------------------------------------------------------------
/3dmaths/divide.h:
--------------------------------------------------------------------------------
1 | #ifndef DIVIDE_H
2 | #define DIVIDE_H
3 |
4 | #ifdef __arm__
5 | extern "C" constexpr unsigned int udiv64_arm (unsigned int a, unsigned int b, unsigned int c);
6 | #endif
7 |
8 | template
9 | constexpr inline T FixedDiv(const T a, const T b, int fracbits)
10 | {
11 | return (a * (1 << fracbits)) / b;
12 | }
13 |
14 | template<>
15 | constexpr inline int FixedDiv(int a, int b, int fracbits)
16 | {
17 | #ifndef __arm__
18 | long long int tmp = ((long long int)a << fracbits) / b;
19 |
20 | return (int)tmp;
21 | #else
22 |
23 | int sign = (a^b) < 0; /* different signs */
24 |
25 | a = a<0 ? -a:a;
26 | b = b<0 ? -b:b;
27 |
28 | unsigned int l = (a << fracbits);
29 | unsigned int h = (a >> fracbits);
30 |
31 | int q = udiv64_arm (h,l,b);
32 | if (sign)
33 | q = -q;
34 |
35 | return q;
36 | #endif
37 |
38 | }
39 |
40 | #endif // DIVIDE_H
41 |
--------------------------------------------------------------------------------
/Potato3dGBAExample/Potato3dGBAExample.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | CONFIG += console c++14
3 | CONFIG -= app_bundle
4 | CONFIG -= qt
5 |
6 |
7 | INCLUDEPATH += "include"
8 |
9 | INCLUDEPATH += "C:\devkitPro\libgba\include"
10 |
11 | SOURCES += \
12 | source/bspmodel.cpp \
13 | source/main.cpp \
14 | source/model.cpp \
15 | source/object3d.cpp \
16 | source/recip.cpp \
17 | source/render.iwram.cpp
18 |
19 |
20 | HEADERS += \
21 | ../3dmaths/divide.h \
22 | ../3dmaths/f3dmath.h \
23 | ../3dmaths/fp.h \
24 | ../3dmaths/m4.h \
25 | ../3dmaths/utils.h \
26 | ../3dmaths/v2.h \
27 | ../3dmaths/v3.h \
28 | ../3dmaths/v4.h \
29 | ../common.h \
30 | ../object3d.h \
31 | ../potato3d.h \
32 | ../render.h \
33 | ../rtypes.h \
34 | include/common.h \
35 | include/model.h
36 |
37 | DISTFILES += \
38 | Makefile \
39 | source/fixeddiv.s
40 |
41 |
42 |
--------------------------------------------------------------------------------
/ConfigInternal.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIGINTERNAL_H
2 | #define CONFIGINTERNAL_H
3 |
4 | namespace P3D
5 | {
6 | inline constexpr int constexpr_log2(int v) { return v ? 1 + constexpr_log2(v >> 1) : -1; }
7 |
8 | inline constexpr int TEX_SHIFT = constexpr_log2(TEX_SIZE);
9 |
10 | inline constexpr int TEX_MASK = (TEX_SIZE-1);
11 |
12 | inline constexpr int TEX_SIZE_PIXELS = (TEX_SIZE * TEX_SIZE);
13 |
14 | inline constexpr int TEX_SIZE_BYTES = (TEX_SIZE_PIXELS * sizeof(pixel));
15 |
16 |
17 | inline constexpr int SUBDIVIDE_SPAN_SHIFT = constexpr_log2(SUBDIVIDE_SPAN_LEN);
18 |
19 | inline constexpr int FOG_SHIFT = constexpr_log2(FOG_LEVELS);
20 | inline constexpr int LIGHT_SHIFT = constexpr_log2(LIGHT_LEVELS);
21 | inline constexpr fp FOG_MAX = fp(1) - std::numeric_limits().epsilon();
22 | inline constexpr fp LIGHT_MAX = fp(1) - std::numeric_limits().epsilon();
23 |
24 | }
25 |
26 | #endif // CONFIGINTERNAL_H
27 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/collision.cpp:
--------------------------------------------------------------------------------
1 | #include "../include/collision.h"
2 |
3 | Collision::Collision()
4 | {
5 |
6 | }
7 |
8 | bool Collision::CheckCollision(const P3D::BspModelTriangle* tri, const P3D::V3& point, const P3D::fp radius, P3D::V3& resolutionVector)
9 | {
10 | P3D::fp distance = tri->normal_plane.DistanceToPoint(point);
11 |
12 | //No collision
13 | if(distance < 0 || distance >= radius)
14 | return false;
15 |
16 | P3D::fp margin = -P3D::fp(P3D::pASR(radius, 4));
17 |
18 | if(tri->edge_plane_0_1.DistanceToPoint(point) < margin)
19 | return false;
20 |
21 | if(tri->edge_plane_1_2.DistanceToPoint(point) < margin)
22 | return false;
23 |
24 | if(tri->edge_plane_2_0.DistanceToPoint(point) < margin)
25 | return false;
26 |
27 | //Move in direction of normal.
28 | P3D::fp penetrationDepth = radius - distance;
29 |
30 | resolutionVector = tri->normal_plane.Normal() * (penetrationDepth + P3D::fp(0.05));
31 |
32 | return true;
33 | }
34 |
--------------------------------------------------------------------------------
/P3DObj2Bsp/.gitignore:
--------------------------------------------------------------------------------
1 | # This file is used to ignore files which are generated
2 | # ----------------------------------------------------------------------------
3 |
4 | *~
5 | *.autosave
6 | *.a
7 | *.core
8 | *.moc
9 | *.o
10 | *.obj
11 | *.orig
12 | *.rej
13 | *.so
14 | *.so.*
15 | *_pch.h.cpp
16 | *_resource.rc
17 | *.qm
18 | .#*
19 | *.*#
20 | core
21 | !core/
22 | tags
23 | .DS_Store
24 | .directory
25 | *.debug
26 | Makefile*
27 | *.prl
28 | *.app
29 | moc_*.cpp
30 | ui_*.h
31 | qrc_*.cpp
32 | Thumbs.db
33 | *.res
34 | *.rc
35 | /.qmake.cache
36 | /.qmake.stash
37 |
38 | # qtcreator generated files
39 | *.pro.user*
40 | CMakeLists.txt.user*
41 |
42 | # xemacs temporary files
43 | *.flc
44 |
45 | # Vim temporary files
46 | .*.swp
47 |
48 | # Visual Studio generated files
49 | *.ib_pdb_index
50 | *.idb
51 | *.ilk
52 | *.pdb
53 | *.sln
54 | *.suo
55 | *.vcproj
56 | *vcproj.*.*.user
57 | *.ncb
58 | *.sdf
59 | *.opensdf
60 | *.vcxproj
61 | *vcxproj.*
62 |
63 | # MinGW generated files
64 | *.Debug
65 | *.Release
66 |
67 | # Python byte code
68 | *.pyc
69 |
70 | # Binaries
71 | # --------
72 | *.dll
73 | *.exe
74 |
75 |
--------------------------------------------------------------------------------
/3dmaths/plane.h:
--------------------------------------------------------------------------------
1 | #ifndef PLANE_H
2 | #define PLANE_H
3 |
4 | #include "v3.h"
5 |
6 | namespace P3D
7 | {
8 | typedef enum FrustrumPlanes : unsigned int
9 | {
10 | Left = 0,
11 | Right = 1,
12 | Top = 2,
13 | Bottom = 3,
14 | Far = 4,
15 | Near = 5,
16 | } FrustrumPlanes;
17 |
18 | template class Plane
19 | {
20 | public:
21 | constexpr Plane() {}
22 | constexpr Plane(V3 normal, T distance) : n(normal), d(distance) {}
23 |
24 | constexpr void Normalise()
25 | {
26 | T length = n.Length();
27 | n = n.Normalised();
28 | d /= length;
29 | }
30 |
31 | constexpr T DistanceToPoint(const V3& v) const
32 | {
33 | return n.DotProduct(v) + d;
34 | }
35 |
36 | constexpr bool TriangleIsFrontside(const V3& v1, const V3& v2, const V3& v3) const
37 | {
38 | if ((DistanceToPoint(v1) < 0) && (DistanceToPoint(v2) < 0) && (DistanceToPoint(v3) < 0))
39 | return false;
40 |
41 | return true;
42 | }
43 |
44 | constexpr V3 Normal() const {return n;}
45 | constexpr T Distance() const {return d;}
46 |
47 | private:
48 | V3 n;
49 | T d;
50 | };
51 | }
52 |
53 | #endif // PLANE_H
54 |
55 |
--------------------------------------------------------------------------------
/Potato3dExample2/P3DExample2.pro:
--------------------------------------------------------------------------------
1 | QT += core gui widgets
2 |
3 | CONFIG += c++20
4 | CONFIG += force_debug_info
5 |
6 | # You can make your code fail to compile if it uses deprecated APIs.
7 | # In order to do so, uncomment the following line.
8 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
9 |
10 | SOURCES += \
11 | source/bspmodel.redir.iwram.cpp \
12 | source/camera.cpp \
13 | source/collision.cpp \
14 | source/mainloop.iwram.cpp \
15 | source/model.cpp \
16 | source/main.cpp \
17 | source/recip.redir.cpp \
18 | source/setup.cpp \
19 | source/videosystem.cpp \
20 | source/worldmodel.cpp
21 |
22 |
23 |
24 | HEADERS += \
25 | include/camera.h \
26 | include/common.h \
27 | include/mainloop.h \
28 | include/model.h \
29 | include/setup.h \
30 | include/videosystem.h \
31 | include/worldmodel.h \
32 | include/collision.h
33 |
34 |
35 | # Default rules for deployment.
36 | qnx: target.path = /tmp/$${TARGET}/bin
37 | else: unix:!android: target.path = /opt/$${TARGET}/bin
38 | !isEmpty(target.path): INSTALLS += target
39 |
40 | DISTFILES += \
41 | Makefile \
42 | source/fixeddiv.iwram.s
43 |
--------------------------------------------------------------------------------
/Potato3dExample/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 |
7 | #include "../potato3d.h"
8 |
9 | class MainWindow : public QMainWindow
10 | {
11 | Q_OBJECT
12 |
13 | public:
14 | MainWindow(QWidget *parent = nullptr);
15 | ~MainWindow();
16 |
17 | protected:
18 | void paintEvent(QPaintEvent *event) override;
19 |
20 | void keyPressEvent(QKeyEvent *event) override;
21 |
22 | private:
23 |
24 | QElapsedTimer fpsTimer;
25 | QElapsedTimer renderTimer;
26 |
27 |
28 | P3D::Object3d* object3d;
29 |
30 | QImage frameBufferImage;
31 |
32 | //static const int screenWidth = 1920;
33 | //static const int screenHeight = 1080;
34 |
35 | //static const int screenWidth = 1280;
36 | //static const int screenHeight = 1024;
37 |
38 | //static const int screenWidth = 640;
39 | //static const int screenHeight = 512;
40 |
41 | //static const int screenWidth = 160;
42 | //static const int screenHeight = 128;
43 |
44 | static const int screenWidth = 240;
45 | static const int screenHeight = 160;
46 |
47 | //static const int screenWidth = 256;
48 | //static const int screenHeight = 256;
49 | };
50 | #endif // MAINWINDOW_H
51 |
--------------------------------------------------------------------------------
/Potato3dExample/mainwindow2.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW2_H
2 | #define MAINWINDOW2_H
3 |
4 | #include
5 | #include
6 |
7 | #include "../RenderDevice.h"
8 | #include "../RenderTarget.h"
9 |
10 | class MainWindow2 : public QMainWindow
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | MainWindow2(QWidget *parent = nullptr);
16 | ~MainWindow2();
17 |
18 | protected:
19 | void paintEvent(QPaintEvent *event) override;
20 |
21 | void keyPressEvent(QKeyEvent *event) override;
22 |
23 | private:
24 |
25 | QElapsedTimer fpsTimer;
26 | QElapsedTimer renderTimer;
27 |
28 | QImage frameBufferImage;
29 |
30 | P3D::RenderTarget* render_target = nullptr;
31 | P3D::RenderDevice* render_device = nullptr;
32 |
33 | //static const int screenWidth = 1280;
34 | //static const int screenHeight = 1024;
35 |
36 | //static const int screenWidth = 640;
37 | //static const int screenHeight = 512;
38 |
39 | //static const int screenWidth = 160;
40 | //static const int screenHeight = 128;
41 |
42 | //static const int screenWidth = 240;
43 | //static const int screenHeight = 160;
44 |
45 | static const int screenWidth = 256;
46 | static const int screenHeight = 256;
47 | };
48 |
49 | #endif // MAINWINDOW2_H
50 |
--------------------------------------------------------------------------------
/ConfigUser.h:
--------------------------------------------------------------------------------
1 | #ifndef CONFIGUSER_H
2 | #define CONFIGUSER_H
3 |
4 | #include "3dmaths/f3dmath.h"
5 | #include "Pixel.h"
6 |
7 | namespace P3D
8 | {
9 | #ifndef __arm__
10 | #define RENDER_STATS
11 | #endif
12 |
13 | //Type of a texture and framebuffer pixel.
14 |
15 | typedef uint8_t pixel;
16 | typedef Pixel<3,2,3, pixel> pixelType;
17 |
18 | inline constexpr int LIGHT_LEVELS = 8;
19 | inline constexpr int FOG_LEVELS = 16;
20 |
21 |
22 | //Width & height of a texture in pixels.
23 | inline constexpr int TEX_SIZE = 64;
24 |
25 | //Maximum UV tiling. Increasing this will reduce bits available for perspective correct texture mapper.
26 | inline constexpr int TEX_MAX_TILE = 8;
27 |
28 | inline constexpr int CLIP_GUARD_BAND_SHIFT = 1;
29 |
30 |
31 | //#define USE_FLOAT
32 | #ifdef USE_FLOAT
33 | typedef double fp;
34 | #else
35 | typedef FP16 fp;
36 | #endif
37 |
38 | typedef fp z_val;
39 |
40 | inline constexpr int SUBDIVIDE_SPAN_LEN = 16;
41 | //inline constexpr fp SUBDIVIDE_Z_THREASHOLD = fp(5);
42 | inline constexpr fp SUBDIVIDE_Z_THREASHOLD = fp(2);
43 |
44 | //#define no_inline __attribute__((noinline))
45 | #define no_inline
46 |
47 | }
48 |
49 | #endif // CONFIGUSER_H
50 |
--------------------------------------------------------------------------------
/TextureCache.h:
--------------------------------------------------------------------------------
1 | #ifndef TEXTURECACHE_H
2 | #define TEXTURECACHE_H
3 |
4 | #include "Config.h"
5 |
6 | namespace P3D
7 | {
8 | class TextureCacheBase
9 | {
10 | public:
11 | TextureCacheBase() = default;
12 | virtual ~TextureCacheBase() = default;
13 |
14 | virtual void AddTexture(const pixel* texture, const signed char importance = 0) = 0;
15 | virtual void RemoveTexture(const pixel* texture) = 0;
16 | virtual const pixel* GetTexture(const pixel* texture) const = 0;
17 | virtual void ClearTextureCache() = 0;
18 | };
19 |
20 | class TextureCacheDefault final : public TextureCacheBase
21 | {
22 | public:
23 |
24 | TextureCacheDefault() = default;
25 | ~TextureCacheDefault() = default;
26 |
27 | void AddTexture(const pixel* texture, const signed char importance = 0)
28 | {
29 | (void)texture;
30 | (void)importance;
31 | }
32 |
33 | void RemoveTexture(const pixel* texture)
34 | {
35 | (void)texture;
36 | }
37 |
38 | const pixel* GetTexture(const pixel* texture) const
39 | {
40 | return texture;
41 | }
42 |
43 | virtual void ClearTextureCache() {}
44 | };
45 |
46 | };
47 |
48 | #endif // TEXTURECACHE_H
49 |
--------------------------------------------------------------------------------
/Potato3dExample2/include/mainloop.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINLOOP_H
2 | #define MAINLOOP_H
3 |
4 | #include "../include/common.h"
5 | #include "../../Config.h"
6 | #include "../../3dmaths/f3dmath.h"
7 |
8 | #include "../../RenderDevice.h"
9 | #include "../../PixelShaderGBA8.h"
10 |
11 | #include "../include/videosystem.h"
12 | #include "../include/camera.h"
13 | #include "../include/worldmodel.h"
14 | #include "../include/collision.h"
15 |
16 | class MainLoop
17 | {
18 | public:
19 | MainLoop();
20 |
21 | void Run();
22 |
23 | private:
24 |
25 | void UpdateFrustrumBB();
26 | void RenderModel();
27 | bool FrustrumTestTriangle(const P3D::BspModelTriangle* tri) const;
28 | void ResolveCollisions();
29 | void RunTimeslots();
30 |
31 | static constexpr P3D::fp zNear = 10;
32 | static constexpr P3D::fp zFar = 1500;
33 | static constexpr P3D::fp vFov = 60;
34 | static constexpr P3D::fp hFov = 90;
35 |
36 | static constexpr unsigned int frameTicks = 50;
37 |
38 | P3D::fp gravity_velocity = 0;
39 |
40 |
41 | P3D::V3 frustrumPoints[4]; //Top left and bottom-right frustrum points.
42 |
43 | P3D::Plane frustrumPlanes[6];
44 |
45 | P3D::AABB viewFrustrumBB;
46 |
47 | P3D::RenderDevice renderDev;
48 |
49 | Camera camera;
50 | WorldModel model;
51 | VideoSystem vid;
52 | Collision collision;
53 |
54 |
55 | unsigned short keyState = 0;
56 |
57 | std::vector triBuffer;
58 | };
59 |
60 | #endif // MAINLOOP_H
61 |
--------------------------------------------------------------------------------
/3dmaths/v2.h:
--------------------------------------------------------------------------------
1 | #ifndef V2_H
2 | #define V2_H
3 |
4 | #include "fp.h"
5 |
6 | namespace P3D
7 | {
8 | template class V2
9 | {
10 | public:
11 | T x;
12 | T y;
13 |
14 | V2(T x, T y) : x(x), y(y) {}
15 | V2() {}
16 | ~V2() {}
17 |
18 | constexpr V2 operator+(const V2& r) const
19 | {
20 | V2 v(x,y);
21 | return v+=r;
22 | }
23 |
24 | constexpr V2 operator-(const V2& r) const
25 | {
26 | V2 v(x,y);
27 | return v-=r;
28 | }
29 |
30 | const V2 operator*(const V2& r) const
31 | {
32 | V2 v(x,y);
33 | return v*=r;
34 | }
35 |
36 | constexpr V2 operator*(const T& r) const
37 | {
38 | V2 v(x,y);
39 |
40 | v.x *= r;
41 | v.y *= r;
42 |
43 | return v;
44 | }
45 |
46 | constexpr V2& operator+=(const V2& r)
47 | {
48 | x += r.x;
49 | y += r.y;
50 | return *this;
51 | }
52 |
53 | constexpr V2& operator-=(const V2& r)
54 | {
55 | x -= r.x;
56 | y -= r.y;
57 | return *this;
58 | }
59 |
60 | constexpr V2& operator*=(const V2& r)
61 | {
62 | x *= r.x;
63 | y *= r.y;
64 | return *this;
65 | }
66 | };
67 |
68 | typedef V2 V2F;
69 | typedef V2 V2D;
70 | typedef V2 V2FP;
71 |
72 | }
73 | #endif // V2_H
74 |
75 |
--------------------------------------------------------------------------------
/Potato3dExample2/source/camera.cpp:
--------------------------------------------------------------------------------
1 | #include "../include/camera.h"
2 |
3 | Camera::Camera()
4 | {
5 | position = P3D::V3(-2511,1050,-3108);
6 | //position = P3D::V3(-230,39,6152);
7 |
8 | //position = P3D::V3(8508,13,8563);
9 | //angle = P3D::V3(0,-236,0);
10 | }
11 |
12 | const P3D::V3& Camera::GetPosition() const
13 | {
14 | return position;
15 | }
16 |
17 | const P3D::V3 Camera::GetEyePosition() const
18 | {
19 | return (position + eyeOffset);
20 | }
21 |
22 | const P3D::V3& Camera::GetAngle() const
23 | {
24 | return angle;
25 | }
26 |
27 | void Camera::HandleInput(unsigned int keyState, P3D::fp gravity_velocity)
28 | {
29 | if(keyState & KeyLeft)
30 | angle.y += 5;
31 |
32 | if(keyState & KeyRight)
33 | angle.y -= 5;
34 |
35 | if(keyState & KeyUp)
36 | {
37 | P3D::V3 camAngle = angle;
38 |
39 | float angleYRad = P3D::pD2R(camAngle.y);
40 |
41 | P3D::V3 d((float)-(std::sin(angleYRad) *20), 0, (float)-(std::cos(angleYRad) *20));
42 |
43 | position += d;
44 | }
45 |
46 | if(keyState & KeyDown)
47 | {
48 | P3D::V3 camAngle = angle;
49 |
50 | float angleYRad = P3D::pD2R(camAngle.y);
51 |
52 | P3D::V3 d((float)-(std::sin(angleYRad) *20), 0, (float)-(std::cos(angleYRad) *20));
53 |
54 | position -= d;
55 | }
56 |
57 | position.y -= gravity_velocity;
58 |
59 | }
60 |
61 | void Camera::MovePosition(const P3D::V3& delta)
62 | {
63 | position += delta;
64 | }
65 |
66 | void Camera::SetPosition(const P3D::V3& pos)
67 | {
68 | position = pos;
69 | }
70 |
--------------------------------------------------------------------------------
/object3d.h:
--------------------------------------------------------------------------------
1 | #ifndef OBJECT3D_H
2 | #define OBJECT3D_H
3 |
4 | #include
5 | #include