Skip to content

Commit 9815a54

Browse files
Additional documentation and fixes.
Also added benchmarking capability.
1 parent 4e6acdb commit 9815a54

19 files changed

+339
-170
lines changed

Diff for: Blender/testmodels.blend

31.4 KB
Binary file not shown.

Diff for: Blender/world.blend

13.3 KB
Binary file not shown.

Diff for: README.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Pico3D Engine for the Pimoroni PicoSystem
22

3-
![Pico3D preview](docs/pico3d.jpeg)
3+
![Pico3D preview](docs/pico3d.jpg)
4+
5+
Created as part of a master's thesis at the Kempten University of Applied Sciences.
46

57
## Getting Started
68

@@ -13,9 +15,10 @@ Add pico_multicore to the target_link_libraries in picosystem.cmake found in pic
1315
You should now be able to compile all the examples including pico3d.
1416

1517

16-
## Tutorials
18+
## Blender Tutorials
1719
- [Creating and exporting a game world in Blender](docs/tutorial_blender_export.md)
18-
- [Material, Lights and Textures in Blender](docs/tutorial_blender_materials.md)
20+
- [Material, lights and textures in Blender](docs/tutorial_blender_materials.md)
21+
- [Exporting individual meshes](docs/tutorial_blender_mesh.md)
1922

2023

2124
## F.A.Q.

Diff for: chunk_data.h

+238-149
Large diffs are not rendered by default.

Diff for: docs/blender21.jpg

160 KB
Loading

Diff for: docs/pico3d.jpg

312 KB
Loading

Diff for: docs/tutorial_blender_materials.md

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ These are split between flat and gouraud shaded triangles (i.e. those which have
1010

1111
Gouraud:
1212
- glow: This ignores any lighting calculation onto the material. Useful for example to depict light sources which do not dim at night.
13-
- nolight: Always darkens triangles regardless of nearby light sources.
1413

1514
Textures:
1615
- scroll: Applies a scrolling effect like those used in the city billboards.

Diff for: docs/tutorial_blender_mesh.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Exporting individual meshes
2+
3+
While exporting chunks automatically is great for scenery, you will still need the individual object in the game world to either manipulate or have moving around.
4+
5+
In the prototype game of Pico3D, these separate meshes are:
6+
- The gates of Pico City, in file logic_gate.cpp and gate.h for the mesh
7+
- The grass as foliage, covered in logic_grass.cpp and grass.h for the mesh
8+
- The NPCs and zombies, which mainly consists of meshes with different poses to be interpolated from. Main logic is covered by logic_npc and logic_zombies.
9+
10+
All of these basically feed the 3D engine with the render_triangle() function, which only needs a triangle positioned in world coordinates and you are good to go. Have a look at any of those files as a reference once you have exported your mesh.
11+
12+
## Exporting a single mesh from Blender
13+
Exporting a single mesh can be done simply by putting a check box on "Export Single Model", then changing the "Mesh" name to the desired mesh and giving the resulting C array a name itself in "Model". Then choose a desired file path (testmodel.h for example) and press on EXPORT.
14+
15+
![Choose material name](blender21.jpg)
16+
17+
There are two options in Advanced that may be of interest:
18+
- 16-bit Vertex Ints: uses less flash/ram but the model can only be 64x64 units in size (i.e. 32 units from the local object origin in each direction). This is usually sufficient unless you need a really big model (e.g. a large world backdrop).
19+
- Store in RAM: This just adds the "const" keyword in front of the array letting the compiler know to store the mesh in flash memory. If you access the mesh frequently it may be better to keep it in RAM unless you are running low (more likely to be the case with large models).

Diff for: engine/render_globals.h

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ uint32_t perf_75_below = 0;
2323
uint32_t perf_75_above = 0;
2424
#endif
2525

26+
#ifdef BENCHMARK
27+
uint32_t perf_25_below = 0;
28+
uint32_t perf_50_below = 0;
29+
uint32_t perf_75_below = 0;
30+
uint32_t perf_75_above = 0;
31+
#endif
32+
2633
//Framebuffer for second core to render into
2734
color_t framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT] __attribute__ ((aligned (4))) = { };
2835
buffer_t *FRAMEBUFFER = buffer(SCREEN_WIDTH, SCREEN_HEIGHT, framebuffer);

Diff for: engine/render_sync.cpp

+16-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,21 @@ int32_t render_sync() {
3737

3838

3939
//performance counters
40-
#ifdef FRAME_COUNTER
40+
#ifdef BENCHMARK
41+
if (benchmark_complete == 0) {
42+
if (core1_time < 25000) {
43+
perf_25_below++;
44+
} else if (core1_time < 50000) {
45+
perf_50_below++;
46+
} else if (core1_time < 75000) {
47+
perf_75_below++;
48+
} else if (core1_time >= 75000) {
49+
perf_75_above++;
50+
}
51+
benchmark_frames++;
52+
avg_frametime += core1_time;
53+
}
54+
#elif FRAME_COUNTER
4155
if (core1_time < 25000) {
4256
perf_25_below++;
4357
} else if (core1_time < 50000) {
@@ -49,6 +63,7 @@ int32_t render_sync() {
4963
}
5064
#endif
5165

66+
5267
//if core 1 is still rendering, we have to keep the old frame and old triangle lists
5368
} else {
5469
//skipped_frames++;

Diff for: engine/render_triangle.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ void render_triangle(struct triangle_32 &in) {
196196
render_lighting(in);
197197
}
198198

199-
//if the shaders are meant to glow at night, reduce them to the correct one and return
199+
//if the shaders are meant to glow at night, reduce them to the correct shader_id and return
200200
if (in.shader_id > 10 && in.shader_id < 20) {
201201
in.shader_id -= 10;
202-
}
202+
}
203203

204204
//if the triangle still exists at this point, we can add it to the triangle list
205205
triangle_list_next[number_triangles].vertex1.x = x1;

Diff for: game/logic_demo.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,11 @@ void logic_demo() {
5454
demo_progress++;
5555
if (demo_progress >= 7000) {
5656
demo_progress = 0;
57+
#ifdef BENCHMARK
58+
if(benchmark_complete == 0) {
59+
benchmark_complete = 1;
60+
avg_frametime = avg_frametime / benchmark_frames;
61+
}
62+
#endif
5763
}
5864
}

Diff for: game/logic_events.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ void logic_new_game() {
1717
//camera_position[2] = 8;
1818

1919
//in the outskirts
20-
camera_position[0] = 35;
21-
camera_position[2] = -20;
20+
//camera_position[0] = 35;
21+
//camera_position[2] = -20;
2222

2323
pitch = 0;
2424
yaw = 0;

Diff for: game/logic_info_text.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ void display_info() {
116116

117117
//show talk button if quest/shop npc is close
118118
if (close_npc != -1) {
119-
if (close_npc == 1 && npc_quest_list[close_npc].dialogue == 11) {
119+
if (close_npc == 1 && (npc_quest_list[close_npc].dialogue == 11 || npc_quest_list[close_npc].dialogue == 12)) {
120120
text("A: Buy Ammo", 0, 110);
121121
}else {
122122
text("A: Talk", 0, 110);
@@ -164,17 +164,17 @@ void display_info() {
164164

165165

166166
case 10:text("Need Bullets?", 0, 90); text("10$ for 5.", 0, 100);break;
167-
case 11:text("Good hunting.", 0, 90); break;
167+
case 11:text("Good hunting.", 0, 90); text(str(player_money + QUEST_AMMO_COST) + "$ -> " + str(player_money) + "$", 0, 100); break;
168168
case 12:text("You don't have", 0, 90); text("enough money.", 0, 100); break;
169169

170170

171171
case 20: text("Oh, well done for", 0, 90); text("making it here.", 0, 100);break;
172172
case 21: text("The fire keeps the", 0, 90); text("zombies away.", 0, 100);break;
173173
case 22: text("This place used to", 0, 90); text("have horses but...", 0, 100); break;
174174
case 23: text("I mean look at the", 0, 90); text("surroundings...", 0, 100); break;
175-
case 24: text("The owner is very", 0, 90); text("unhappy due to this.", 0, 100); break;
176-
case 25: text("Sells ammo to anyone,", 0, 90); text("hoping it will help.", 0, 100); break;
177-
case 26: text("Don't get killed", 0, 90); text("and stock up.", 0, 100); break;
175+
case 24: text("The stable owner is", 0, 90); text("pretty unhappy.", 0, 100); break;
176+
case 25: text("Sells ammo to anyone", 0, 90); text("hoping it will help.", 0, 100); break;
177+
case 26: text("Don't get killed and", 0, 90); text("get some rest here.", 0, 100); break;
178178
}
179179
#endif
180180

Diff for: game/logic_input.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,12 @@ void logic_input() {
145145

146146
} else if (menu == MENU_START) {
147147

148+
#ifndef BENCHMARK //Benchmark disables inputs
148149
if (pressed(A) || pressed(B) || pressed(X) || pressed(Y) || pressed(UP) || pressed(DOWN) || pressed(LEFT) || pressed(RIGHT)) {
149150
logic_new_game();
150151
menu = 0;
151152
}
153+
#endif
152154

153155
} else if (menu == MENU_DEATH) {
154156

Diff for: game/logic_menu.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ void display_menu() {
4444
} else if (menu == MENU_START) {
4545
pen(15, 15, 15);
4646

47+
#ifdef BENCHMARK
48+
if (benchmark_complete == 0) {
49+
text("BENCHMARKING", 0, 0);
50+
}
51+
#else
4752
if (demo_progress < 2500) {
4853
text("Pico3D Engine", 28, 20);
4954
text("by: Bernhard Strobl", 10, 30);
@@ -52,6 +57,7 @@ void display_menu() {
5257
if ((demo_progress / 32) % 2 == 0) {
5358
text("Press any button", 20, 90);
5459
}
60+
#endif
5561

5662
} else if (menu == MENU_DEATH) {
5763
pen(15, 0, 0);

Diff for: game/logic_quest_npcs.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ void init_quest_npcs() {
2020
npc_quest_list[1].y = -41 * FIXED_POINT_FACTOR;
2121

2222

23-
2423
//Fireplace guy
2524
npc_quest_list[2].status = 1;
2625
npc_quest_list[2].direction = 1;
27-
npc_quest_list[2].shirt_color = 0xA00A;
28-
npc_quest_list[2].dialogue = 20;
26+
npc_quest_list[2].shirt_color = 0xAF0A;
27+
npc_quest_list[2].dialogue = 20;
2928
npc_quest_list[2].x = 48 * FIXED_POINT_FACTOR;
3029
npc_quest_list[2].y = -35 * FIXED_POINT_FACTOR;
3130
}
@@ -39,22 +38,24 @@ void talk_quest_npc() {
3938

4039
} else {
4140
dialogue_display = npc_quest_list[close_npc].dialogue;
42-
npc_quest_list[close_npc].dialogue++;
41+
npc_quest_list[close_npc].dialogue++; //increase dialogue counter
4342

4443
//give out same text for guard once conversation limit is reached
4544
if (npc_quest_list[close_npc].dialogue == 7) {
4645
npc_quest_list[close_npc].dialogue = 6;
4746
}
4847

4948
//Stable owner
50-
if (npc_quest_list[close_npc].dialogue == 11 || npc_quest_list[close_npc].dialogue == 12 || npc_quest_list[close_npc].dialogue == 13) {
49+
if (npc_quest_list[close_npc].dialogue == 12 || npc_quest_list[close_npc].dialogue == 13) {
5150

5251
if (player_money >= QUEST_AMMO_COST) {
5352
player_money -= QUEST_AMMO_COST;
5453
player_ammo += QUEST_AMMO_PURCHASE;
5554
npc_quest_list[close_npc].dialogue = 11;
55+
dialogue_display = 11;
5656
} else {
5757
npc_quest_list[close_npc].dialogue = 12;
58+
dialogue_display = 12;
5859
}
5960
}
6061

Diff for: main.cpp

+24-2
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,19 @@ using namespace picosystem;
2020
//#define FRAME_COUNTER //tallies frametimes for performance analysis
2121
//#define CONTENTION_COUNTER //enables counters for RAM contention on the 4 main banks
2222
//#define CPU_LED_LOAD //CPU load on LED (Core1: Green-40fps, Yellow-20fps, Red-10fps), blue if core 0 overloaded (logic too slow)
23+
//#define BENCHMARK //starts a benchmark recording average frametime and rough fps counter (takes 3 minutes!)
2324

2425
int32_t logic_time;
25-
2626
int32_t show_battery = 0;
2727

28+
#ifdef BENCHMARK
29+
#define NO_NPCS //disable npcs for predictable performance
30+
uint32_t avg_frametime = 0;
31+
uint32_t benchmark_frames = 0;
32+
int32_t benchmark_complete = 0;
33+
#endif
34+
35+
2836
#include "engine/render_globals.h"
2937
#include "engine/chunk_globals.h" //chunk settings
3038
#include "chunk_data.h" //contains all the chunk data of the game world (exported by Blender addon)
@@ -290,7 +298,7 @@ void draw(uint32_t tick) {
290298

291299

292300

293-
//DEBUG
301+
//DEBUG INFORMATION BELOW
294302
//clear the screen when all else fails to get at least debug output
295303
/*
296304
pen(0, 0, 0);
@@ -341,5 +349,19 @@ void draw(uint32_t tick) {
341349
}
342350
#endif
343351

352+
#ifdef BENCHMARK
353+
if (benchmark_complete == 1) {
354+
text("Benchmark results:", 0, 0);
355+
text("40 FPS:" + str(perf_25_below), 0, 10);
356+
text("20 FPS:" + str(perf_50_below), 0, 20);
357+
text("13 FPS:" + str(perf_75_below), 0, 30);
358+
text("<13 FPS:" + str(perf_75_above), 0, 40);
359+
text("Average frame time:", 0, 50);
360+
text(str(avg_frametime), 0, 60);
361+
text("Frames rendered:", 0, 70);
362+
text(str(benchmark_frames), 0, 80);
363+
}
364+
#endif
365+
344366
}
345367

Diff for: pico3d.jpeg

-1.73 MB
Binary file not shown.

0 commit comments

Comments
 (0)