Compare commits
56 Commits
ps2-maze_1
...
master
Author | SHA1 | Date | |
---|---|---|---|
6bbe7a7970 | |||
e72d10925c | |||
0bc14e3ea8 | |||
d636d35f38 | |||
cb75c48a80 | |||
2c0c4c485d | |||
8284f29be2 | |||
c52bf93daf | |||
51addcae02 | |||
7b03cd0aa6 | |||
e4789d6156 | |||
ee8d4635fa | |||
29e73a36b8 | |||
cf228eee94 | |||
5966782b90 | |||
8a1534004c | |||
20a8c65266 | |||
dcca92ee43 | |||
2cef922233 | |||
3ef1233ee5 | |||
8457fdbe39 | |||
5b437adf8e | |||
29358c9258 | |||
31ccf3c218 | |||
1db028c814 | |||
a1182995ae | |||
1f3b6a973d | |||
a2d38044f0 | |||
ccc017c647 | |||
300bdb3e31 | |||
96cc0a246c | |||
a009fd3749 | |||
787786bfa4 | |||
ff826b1806 | |||
c0f1685cbb | |||
082a084971 | |||
9511c07f3e | |||
a17ef2d379 | |||
dd68a9115e | |||
0ff396757b | |||
8ffad9e6b9 | |||
aa65ae8142 | |||
1de3a60aef | |||
93d9113451 | |||
7b530a67f1 | |||
2a8cb45651 | |||
4bba0346dd | |||
1d17372d8e | |||
dfa6176182 | |||
b2963910d9 | |||
e1847d5d67 | |||
a38bcd51dd | |||
4d00379ace | |||
8b227bf993 | |||
1fddf39939 | |||
8bfe2301a7 |
2
.clangd
Normal file
2
.clangd
Normal file
@ -0,0 +1,2 @@
|
||||
CompileFlags: # Tweak the parse settings
|
||||
Add: [-Iunigi/]
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ ignore/
|
||||
*.obj
|
||||
*.cam
|
||||
*.tar.gz
|
||||
*.zip
|
||||
*.Identifier
|
||||
callgrind.*
|
||||
|
||||
|
19
.gitmodules
vendored
19
.gitmodules
vendored
@ -1,15 +1,12 @@
|
||||
[submodule "haloo3d"]
|
||||
path = haloo3d
|
||||
url = https://github.com/randomouscrap98/haloo3d.git
|
||||
[submodule "unigi/unigi"]
|
||||
path = unigi/unigi
|
||||
url = https://git.lumen.sh/Fierelier/unigi.git
|
||||
[submodule "unigi/unigi.headers"]
|
||||
path = unigi/unigi.headers
|
||||
url = https://git.lumen.sh/Fierelier/unigi.headers.git
|
||||
[submodule "unigi/unigi.ext"]
|
||||
path = unigi/unigi.ext
|
||||
url = https://git.lumen.sh/Fierelier/unigi.ext
|
||||
[submodule "unigi/unigi.platform.sdl1"]
|
||||
path = unigi/unigi.platform.sdl1
|
||||
[submodule "unigi.platform.sdl2"]
|
||||
path = unigi.platform.sdl2
|
||||
url = https://git.lumen.sh/Fierelier/unigi.platform.sdl2.git
|
||||
[submodule "unigi.platform.sdl1"]
|
||||
path = unigi.platform.sdl1
|
||||
url = https://git.lumen.sh/Fierelier/unigi.platform.sdl1.git
|
||||
[submodule "unigi"]
|
||||
path = unigi
|
||||
url = https://git.lumen.sh/Fierelier/unigi.git
|
||||
|
23
Makefile
23
Makefile
@ -21,28 +21,39 @@ else
|
||||
endif
|
||||
|
||||
HALOOLIB = haloo3d/build/haloo3d_full.a
|
||||
UNIGIPLAT = $(BUILDD)/unigi.platform.sdl2.o
|
||||
UNIGILIB = $(BUILDD)/unigi.a
|
||||
ALLH3DFILES = haloo3d/*.c haloo3d/*.h
|
||||
|
||||
.PHONY: clean
|
||||
.PHONY: full
|
||||
.PHONY: libs
|
||||
|
||||
full:
|
||||
echo "Please specify a sample to build (ends with .exe)"
|
||||
libs: $(UNIGILIB) $(HALOOLIB)
|
||||
@echo "Built libs!"
|
||||
|
||||
$(HALOOLIB):
|
||||
$(HALOOLIB): $(ALLH3DFILES)
|
||||
cd haloo3d && $(MAKE) full
|
||||
|
||||
$(UNIGIPLAT): unigi.platform.sdl2/main.c
|
||||
mkdir -p $(BUILDD)
|
||||
$(CC) $(CFLAGS) -I. -c $< -o $@
|
||||
|
||||
$(UNIGILIB): $(UNIGIPLAT)
|
||||
ar -vr $@ $^
|
||||
|
||||
# Rule to build .o files in main folder
|
||||
$(BUILDD)/%.o: %.c %.h
|
||||
mkdir -p $(BUILDD)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Rule to build any sample. We ALWAYS need math so... link it
|
||||
%.exe: %.o $(HALOOLIB)
|
||||
$(CC) $(CFLAGS) $< $(HALOOLIB) -o $@ -lm -lSDL
|
||||
%.exe: %.o $(UNIGILIB) $(HALOOLIB)
|
||||
$(CC) $(CFLAGS) $^ -o $@ -lm -lSDL2
|
||||
|
||||
# Rule to clean the build files
|
||||
clean:
|
||||
rm -rf $(BUILDD)
|
||||
rm -f *.o *.elf
|
||||
find . -name "*.exe" -type f -delete
|
||||
cd haloo3d && $(MAKE) clean
|
||||
|
||||
|
45
Makefile_PS2
Normal file
45
Makefile_PS2
Normal file
@ -0,0 +1,45 @@
|
||||
# _____ ___ ____ ___ ____
|
||||
# ____| | ____| | | |____|
|
||||
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2001-2022, ps2dev - http://www.ps2dev.org
|
||||
# Licenced under Academic Free License version 2.0
|
||||
# Review ps2sdk README & LICENSE files for further details.
|
||||
|
||||
EE_BIN = $(PROGRAM_PS2).elf
|
||||
|
||||
# KERNEL_NOPATCH = 1
|
||||
# NEWLIB_NANO = 1
|
||||
|
||||
# NOTE: CANNOT USE JUST 'PS2' AS A DEFINE, IT BREAKS EVERYTHING!
|
||||
EE_OBJS = $(PROGRAM_PS2).o
|
||||
EE_CFLAGS += -fdata-sections -ffunction-sections -I$(PS2SDK)/ports/include -Wformat=0
|
||||
EE_LDFLAGS += -L$(PS2SDK)/ports/lib -L$(GSKIT)/lib -lSDL2 -lgskit -ldmakit -lps2_drivers -lm -Wl,--gc-sections
|
||||
|
||||
ifeq ($(DUMMY_TIMEZONE), 1)
|
||||
EE_CFLAGS += -DDUMMY_TIMEZONE
|
||||
endif
|
||||
|
||||
ifeq ($(DUMMY_LIBC_INIT), 1)
|
||||
EE_CFLAGS += -DDUMMY_LIBC_INIT
|
||||
endif
|
||||
|
||||
ifeq ($(KERNEL_NOPATCH), 1)
|
||||
EE_CFLAGS += -DKERNEL_NOPATCH
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
EE_CFLAGS += -DDEBUG -O0 -g
|
||||
else
|
||||
EE_CFLAGS += -Os
|
||||
EE_LDFLAGS += -s
|
||||
endif
|
||||
|
||||
all: $(EE_BIN)
|
||||
|
||||
clean:
|
||||
rm -rf $(EE_OBJS) $(EE_BIN)
|
||||
|
||||
# Include makefiles
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
13
README.md
13
README.md
@ -3,7 +3,7 @@
|
||||
Everything in here is a little sample program or otherwise which
|
||||
uses [haloo3d](https://github.com/randomouscrap98/haloo3d) and
|
||||
[unigi](https://git.lumen.sh/Fierelier/unigi). It's all software
|
||||
rendered, but you'll need to get sdl1 so it can render to screen.
|
||||
rendered, but you'll need to get sdl2 so it can render to screen.
|
||||
|
||||
The libraries required are set as submodules, so you can pull them
|
||||
when cloning with:
|
||||
@ -33,14 +33,13 @@ make FORCE=1 maze.exe
|
||||
|
||||
## Unigi
|
||||
|
||||
For the time being, unigi is designed such that it expects you to
|
||||
compile your entire program as a single unit. This means you must
|
||||
include all your .c files into the main file, in the right order.
|
||||
|
||||
This may change in the future.
|
||||
Unigi is a small library and is built manually using the 3dtoys makefile.
|
||||
You can tinker around with Unigi if you like; it has its own make system,
|
||||
but I'm not sure what is required. The parts that are required for 3dtoys
|
||||
are handled with the 3dtoys makefile.
|
||||
|
||||
Unigi expects some kind of graphics backend to run. In this case,
|
||||
our samples use SDL1, so you'll need to get that.
|
||||
our samples use SDL2, so you'll need to get that.
|
||||
|
||||
## Haloo3d
|
||||
|
||||
|
137
commonobj.c
Normal file
137
commonobj.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_gen.h"
|
||||
#include "haloo3d/haloo3dex_obj.h"
|
||||
|
||||
#ifndef TREECOL
|
||||
#define TREECOL 0xF070
|
||||
#endif
|
||||
#ifndef TREETRUNKCOL
|
||||
#define TREETRUNKCOL 0xF950
|
||||
#endif
|
||||
#ifndef TREEBOTTOM
|
||||
#define TREEBOTTOM -0.333
|
||||
#endif
|
||||
#ifndef TREETOPWIDTH
|
||||
#define TREETOPWIDTH 1.0
|
||||
#endif
|
||||
#ifndef TREETRUNKWIDTH
|
||||
#define TREETRUNKWIDTH 0.2
|
||||
#endif
|
||||
|
||||
#define TOWERTHICK 0.65
|
||||
|
||||
#define COMVERT(m, _x, _y, _z) \
|
||||
haloo3d_obj_addvertex(m, (struct vec4){.x = _x, .y = _y, .z = _z, .w = 1})
|
||||
#define COMCOL(m, col) haloo3d_obj_addvtexture(m, haloo3d_gen_paletteuv(col))
|
||||
|
||||
// Fill a face with a solid color given by the tex
|
||||
void fastface(haloo3d_facei face, uint16_t tex, uint16_t v0, uint16_t v1,
|
||||
uint16_t v2) {
|
||||
face[0].texi = tex;
|
||||
face[1].texi = tex;
|
||||
face[2].texi = tex;
|
||||
face[0].posi = v0;
|
||||
face[1].posi = v1;
|
||||
face[2].posi = v2;
|
||||
}
|
||||
|
||||
static inline uint16_t fastface2(haloo3d_obj *model, uint16_t tex, uint16_t v0,
|
||||
uint16_t v1, uint16_t v2) {
|
||||
haloo3d_facei face;
|
||||
fastface(face, tex, v0, v1, v2);
|
||||
return haloo3d_obj_addface(model, face);
|
||||
}
|
||||
|
||||
// Generate a basic tree model
|
||||
void gen_tree_model(haloo3d_obj *tree) {
|
||||
haloo3d_obj_resetfixed(tree, 12, 24);
|
||||
int treeuv = COMCOL(tree, TREECOL);
|
||||
int trunkuv = COMCOL(tree, TREETRUNKCOL);
|
||||
uint16_t top = COMVERT(tree, 0, 1, 0);
|
||||
uint16_t tree1 = COMVERT(tree, -TREETOPWIDTH, TREEBOTTOM, -TREETOPWIDTH);
|
||||
uint16_t tree2 = COMVERT(tree, TREETOPWIDTH, TREEBOTTOM, -TREETOPWIDTH);
|
||||
uint16_t tree3 = COMVERT(tree, 0, TREEBOTTOM, TREETOPWIDTH);
|
||||
uint16_t trunk1 = COMVERT(tree, -TREETRUNKWIDTH, -1, -TREETRUNKWIDTH);
|
||||
uint16_t trunk2 = COMVERT(tree, TREETRUNKWIDTH, -1, -TREETRUNKWIDTH);
|
||||
uint16_t trunk3 = COMVERT(tree, 0, -1, TREETRUNKWIDTH);
|
||||
fastface2(tree, treeuv, top, tree1, tree3);
|
||||
fastface2(tree, treeuv, top, tree3, tree2);
|
||||
fastface2(tree, treeuv, top, tree2, tree1);
|
||||
fastface2(tree, trunkuv, top, trunk1, trunk3);
|
||||
fastface2(tree, trunkuv, top, trunk3, trunk2);
|
||||
fastface2(tree, trunkuv, top, trunk2, trunk1);
|
||||
haloo3d_obj_shrinktofit(tree);
|
||||
}
|
||||
|
||||
void gen_circle_model(haloo3d_obj *model, uint16_t color, int vertices) {
|
||||
haloo3d_obj_resetfixed(model, vertices, vertices + 1);
|
||||
int circleuv = COMCOL(model, color);
|
||||
// Add the center
|
||||
uint16_t middle = COMVERT(model, 0, 0, 0);
|
||||
// Go in a circle of course
|
||||
float angle = 0;
|
||||
float angle_inc = MPI * 2 / vertices;
|
||||
uint16_t lastv = 0;
|
||||
uint16_t firstv = 0;
|
||||
for (int i = 0; i < vertices; i++) {
|
||||
uint16_t thisv = COMVERT(model, cos(angle), sin(angle), 0);
|
||||
if (i == 0) {
|
||||
firstv = thisv;
|
||||
} else {
|
||||
fastface2(model, circleuv, middle, lastv, thisv);
|
||||
}
|
||||
angle += angle_inc;
|
||||
lastv = thisv;
|
||||
}
|
||||
fastface2(model, circleuv, middle, lastv, firstv);
|
||||
}
|
||||
|
||||
void gen_flower_model(haloo3d_obj *model, uint16_t color) {
|
||||
haloo3d_obj_resetfixed(model, 2, 5);
|
||||
uint16_t vs[5];
|
||||
uint16_t col = COMCOL(model, color);
|
||||
vs[0] = COMVERT(model, 0, -1, 0); // The shared middle
|
||||
vs[1] = COMVERT(model, 1, 1, 0);
|
||||
vs[2] = COMVERT(model, -1, 1, 0);
|
||||
vs[3] = COMVERT(model, 0, 1, 1);
|
||||
vs[4] = COMVERT(model, 0, 1, -1);
|
||||
fastface2(model, col, vs[0], vs[1], vs[2]);
|
||||
fastface2(model, col, vs[0], vs[3], vs[4]);
|
||||
}
|
||||
|
||||
void gen_horibox(haloo3d_obj *model, uint16_t col, mfloat_t wid, mfloat_t bot,
|
||||
mfloat_t hei) {
|
||||
uint16_t box[8];
|
||||
box[0] = COMVERT(model, -wid, bot, wid);
|
||||
box[1] = COMVERT(model, -wid, bot + hei, wid);
|
||||
box[2] = COMVERT(model, wid, bot, wid);
|
||||
box[3] = COMVERT(model, wid, bot + hei, wid);
|
||||
box[4] = COMVERT(model, wid, bot, -wid);
|
||||
box[5] = COMVERT(model, wid, bot + hei, -wid);
|
||||
box[6] = COMVERT(model, -wid, bot, -wid);
|
||||
box[7] = COMVERT(model, -wid, bot + hei, -wid);
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
fastface2(model, col, box[i], box[(i + 3) & 7], box[(i + 1) & 7]);
|
||||
fastface2(model, col, box[i], box[(i + 2) & 7], box[(i + 3) & 7]);
|
||||
}
|
||||
}
|
||||
|
||||
void gen_tower_model(haloo3d_obj *model, uint16_t color) {
|
||||
haloo3d_obj_resetfixed(model, 100, 100);
|
||||
uint16_t col = COMCOL(model, color);
|
||||
uint16_t top = COMVERT(model, 0, 1, 0);
|
||||
fastface2(model, col, top, COMVERT(model, -1, -1, 1),
|
||||
COMVERT(model, -TOWERTHICK, -1, TOWERTHICK));
|
||||
fastface2(model, col, top, COMVERT(model, 1, -1, 1),
|
||||
COMVERT(model, TOWERTHICK, -1, TOWERTHICK));
|
||||
fastface2(model, col, top, COMVERT(model, -1, -1, -1),
|
||||
COMVERT(model, -TOWERTHICK, -1, -TOWERTHICK));
|
||||
fastface2(model, col, top, COMVERT(model, 1, -1, -1),
|
||||
COMVERT(model, TOWERTHICK, -1, -TOWERTHICK));
|
||||
gen_horibox(model, col, 0.2, 0.8, 0.03);
|
||||
gen_horibox(model, col, 0.8, -0.4, 0.05);
|
||||
for (mfloat_t f = 0.7; f >= -0.4; f -= 0.2) {
|
||||
gen_horibox(model, col, (1 - f) * 0.5, f, 0.01);
|
||||
}
|
||||
haloo3d_obj_shrinktofit(model);
|
||||
}
|
155
ecs2.h
155
ecs2.h
@ -13,6 +13,10 @@
|
||||
#define ECS_MAXENTITIES 1024
|
||||
#endif
|
||||
|
||||
#ifndef ECS_FNTYPE
|
||||
#define ECS_FNTYPE
|
||||
#endif
|
||||
|
||||
// We reserve one slot to automatically point back to the ecs system.
|
||||
// This is the unusable 64th ID = 63 (your ids should start from 0)
|
||||
#define ECS_MAXCTYPES 63
|
||||
@ -24,6 +28,8 @@
|
||||
typedef unsigned long long ecs_cid;
|
||||
typedef int ecs_eid;
|
||||
|
||||
// -------------- ECS BUILDERS -----------------------
|
||||
|
||||
#define ECS_START(name) \
|
||||
typedef struct name name; \
|
||||
struct name { \
|
||||
@ -34,10 +40,30 @@ typedef int ecs_eid;
|
||||
#define ECS_END(name) \
|
||||
} \
|
||||
; \
|
||||
const ecs_cid name##_fl = ECS_SELFFLAG;
|
||||
|
||||
// Create an ECS component within an ECS struct
|
||||
#define ECS_COMPONENT(type) type c_##type[ECS_MAXENTITIES];
|
||||
|
||||
// Define the CIDs necessary to access a component (each component MUST
|
||||
// have a unique id and I can't do that inside a macro without requiring
|
||||
// extensions). Note: can't use enum, because we need the flag value too.
|
||||
// (unless you have a compiler that supports iterating over macro varargs)
|
||||
#define ECS_CID(type, id) \
|
||||
const int type##_id = id; \
|
||||
const ecs_cid type##_fl = (1ULL << id);
|
||||
|
||||
// -------------- ECS EXTRA FUNCTIONS -----------------------
|
||||
|
||||
// NOTE: these generate functions individually because some systems might
|
||||
// not allow unused functions and you may not need them all
|
||||
#define ECS_FN_INIT(name) \
|
||||
/* Always initialize the ecs system when you create a new one! */ \
|
||||
static void name##_init(name *_ecs) { memset(_ecs, 0, sizeof(name)); } \
|
||||
ECS_FNTYPE void name##_init(name *_ecs) { memset(_ecs, 0, sizeof(name)); }
|
||||
|
||||
#define ECS_FN_NEWENTITY(name) \
|
||||
/* Create an entity with the given base components (usually 0) */ \
|
||||
static ecs_eid name##_newentity(name *_ecs, ecs_cid basecomponents) { \
|
||||
ECS_FNTYPE ecs_eid name##_newentity(name *_ecs, ecs_cid basecomponents) { \
|
||||
for (int i = 0; i < ECS_MAXENTITIES; i++) { \
|
||||
ecs_eid id = _ecs->entitytop; \
|
||||
_ecs->entitytop = (_ecs->entitytop + 1) % ECS_MAXENTITIES; \
|
||||
@ -48,19 +74,23 @@ typedef int ecs_eid;
|
||||
} \
|
||||
} \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ECS_FN_DELETEENTITY(name) \
|
||||
/* Delete an entity by eid from the given ecs sys */ \
|
||||
static void name##_deleteentity(name *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void name##_deleteentity(name *_ecs, ecs_eid eid) { \
|
||||
if (eid >= 0 && eid < ECS_MAXENTITIES) \
|
||||
_ecs->entities[eid] = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ECS_FN_QUERY(name) \
|
||||
/* Whether an entity matches a given list of components by flag */ \
|
||||
static int name##_match(name *_ecs, ecs_eid _eid, ecs_cid _comps) { \
|
||||
ECS_FNTYPE int name##_match(name *_ecs, ecs_eid _eid, ecs_cid _comps) { \
|
||||
ecs_cid _realcomps = ECS_SELFFLAG | _comps; \
|
||||
return (_ecs->entities[_eid] & _realcomps) == _realcomps; \
|
||||
} \
|
||||
/* fill given list with eids of entities that match. careful with size */ \
|
||||
static int name##_query(name *_ecs, ecs_cid _comps, ecs_eid *out) { \
|
||||
ECS_FNTYPE int name##_query(name *_ecs, ecs_cid _comps, ecs_eid *out) { \
|
||||
int count = 0; \
|
||||
for (int i = 0; i < ECS_MAXENTITIES; i++) { \
|
||||
if (name##_match(_ecs, i, _comps)) { \
|
||||
@ -68,36 +98,105 @@ typedef int ecs_eid;
|
||||
} \
|
||||
} \
|
||||
return count; \
|
||||
} \
|
||||
/* Calculate the eid from a double ecs pointer. Useful to get eid in sys */ \
|
||||
static ecs_eid name##_eid(name **_ecs) { \
|
||||
return (ecs_eid)(_ecs - (*_ecs)->c_##name); \
|
||||
} \
|
||||
const ecs_cid name##_fl = ECS_SELFFLAG;
|
||||
}
|
||||
|
||||
// Create an ECS component within an ECS struct
|
||||
#define ECS_COMPONENT(type) type c_##type[ECS_MAXENTITIES];
|
||||
#define ECS_FN_EID(name) \
|
||||
/* Calculate the eid from a double ecs pointer. Useful to get eid in sys */ \
|
||||
ECS_FNTYPE ecs_eid name##_eid(name **_ecs) { \
|
||||
return (ecs_eid)(_ecs - (*_ecs)->c_##name); \
|
||||
}
|
||||
|
||||
// ------------------ ECS GENERAL MACROS ----------------------------
|
||||
|
||||
#define ECS_COMPONENTS(_ecs, eid) (_ecs->entities[eid])
|
||||
|
||||
#define ECS_HASCOMPONENT(_ecs, eid, type) \
|
||||
((_ecs->entities[eid] & type##_fl) != 0)
|
||||
|
||||
#define ECS_GETCOMPONENT(_ecs, eid, type) (_ecs)->c_##type[eid]
|
||||
|
||||
// Define the CIDs necessary to access a component (each component MUST
|
||||
// have a unique id and I can't do that inside a macro without requiring
|
||||
// extensions)
|
||||
#define ECS_CID(type, id) \
|
||||
const int type##_id = id; \
|
||||
const ecs_cid type##_fl = (1ULL << id);
|
||||
|
||||
// Set the given entity to have the given component (by type). Follow this
|
||||
// macro immediately with the struct initializer
|
||||
#define ECS_SETCOMPONENT(_ecs, eid, type) \
|
||||
(_ecs)->entities[eid] |= type##_fl; \
|
||||
(_ecs)->c_##type[eid] = (type)
|
||||
|
||||
// Internal-use loop for ECS_RUNSYSTEM
|
||||
#define _ECS_RSLOOP(_i, _ecs, _comps) \
|
||||
for (int _i = 0; _i < ECS_MAXENTITIES; _i++) \
|
||||
if (((_ecs)->entities[_i] & _comps) == _comps)
|
||||
|
||||
// A shortcut to run a system against all matching components. You could also
|
||||
// define systems using ECS_SYSTEM1 etc. and call them per entity.
|
||||
// Make sure you pass int the name of YOUR system, not the "run" function (you
|
||||
// don't need the run function when using these macros)
|
||||
#define ECS_RUNSYSTEM1(_ecs, _system, type1) \
|
||||
{ \
|
||||
ecs_cid _ecsflags = ECS_SELFFLAG | type1##_fl; \
|
||||
_ECS_RSLOOP(eid, _ecs, _ecsflags) { _system((_ecs)->c_##type1 + eid); } \
|
||||
}
|
||||
|
||||
// A shortcut to run a system against all matching components. You could also
|
||||
// define systems using ECS_SYSTEM2 etc. and call them per entity.
|
||||
// Make sure you pass int the name of YOUR system, not the "run" function (you
|
||||
// don't need the run function when using these macros)
|
||||
#define ECS_RUNSYSTEM2(_ecs, _system, t1, t2) \
|
||||
{ \
|
||||
ecs_cid _ecsflags = ECS_SELFFLAG | t1##_fl | t2##_fl; \
|
||||
_ECS_RSLOOP(eid, _ecs, _ecsflags) { \
|
||||
_system((_ecs)->c_##t1 + eid, (_ecs)->c_##t2 + eid); \
|
||||
} \
|
||||
}
|
||||
|
||||
// A shortcut to run a system against all matching components. You could also
|
||||
// define systems using ECS_SYSTEM3 etc. and call them per entity.
|
||||
// Make sure you pass int the name of YOUR system, not the "run" function (you
|
||||
// don't need the run function when using these macros)
|
||||
#define ECS_RUNSYSTEM3(_ecs, _system, t1, t2, t3) \
|
||||
{ \
|
||||
ecs_cid _ecsflags = ECS_SELFFLAG | t1##_fl | t2##_fl | t3##_fl; \
|
||||
_ECS_RSLOOP(eid, _ecs, _ecsflags) { \
|
||||
_system((_ecs)->c_##t1 + eid, (_ecs)->c_##t2 + eid, \
|
||||
(_ecs)->c_##t3 + eid); \
|
||||
} \
|
||||
}
|
||||
|
||||
// A shortcut to run a system against all matching components. You could also
|
||||
// define systems using ECS_SYSTEM4 etc. and call them per entity.
|
||||
// Make sure you pass int the name of YOUR system, not the "run" function (you
|
||||
// don't need the run function when using these macros)
|
||||
#define ECS_RUNSYSTEM4(_ecs, _system, t1, t2, t3, t4) \
|
||||
{ \
|
||||
ecs_cid _ecsflags = ECS_SELFFLAG | t1##_fl | t2##_fl | t3##_fl | t4##_fl; \
|
||||
_ECS_RSLOOP(eid, _ecs, _ecsflags) { \
|
||||
_system((_ecs)->c_##t1 + eid, (_ecs)->c_##t2 + eid, \
|
||||
(_ecs)->c_##t3 + eid, (_ecs)->c_##t4 + eid); \
|
||||
} \
|
||||
}
|
||||
|
||||
// A shortcut to run a system against all matching components. You could also
|
||||
// define systems using ECS_SYSTEM5 etc. and call them per entity.
|
||||
// Make sure you pass int the name of YOUR system, not the "run" function (you
|
||||
// don't need the run function when using these macros)
|
||||
#define ECS_RUNSYSTEM5(_ecs, _system, t1, t2, t3, t4, t5) \
|
||||
{ \
|
||||
ecs_cid _ecsflags = \
|
||||
ECS_SELFFLAG | t1##_fl | t2##_fl | t3##_fl | t4##_fl | t5##_fl; \
|
||||
_ECS_RSLOOP(eid, _ecs, _ecsflags) { \
|
||||
_system(_ecs->c_##t1 + eid, _ecs->c_##t2 + eid, _ecs->c_##t3 + eid, \
|
||||
_ecs->c_##t4 + eid, _ecs->c_##t5 + eid); \
|
||||
} \
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// YOU DON'T NEED THIS STUFF IF YOU USE ECS_RUNSYSTEM
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// Add a system function which automatically calls your given function with
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM1(ecsname, fname, type1) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
fname(_ecs->c_##type1 + eid); \
|
||||
@ -108,7 +207,7 @@ typedef int ecs_eid;
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM2(ecsname, fname, type1, type2) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl | type2##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
fname(_ecs->c_##type1 + eid, _ecs->c_##type2 + eid); \
|
||||
@ -119,7 +218,7 @@ typedef int ecs_eid;
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM3(ecsname, fname, type1, type2, type3) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl | type2##_fl | type3##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
fname(_ecs->c_##type1 + eid, _ecs->c_##type2 + eid, \
|
||||
@ -131,7 +230,7 @@ typedef int ecs_eid;
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM4(ecsname, fname, type1, type2, type3, type4) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl | type2##_fl | type3##_fl | type4##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
fname(_ecs->c_##type1 + eid, _ecs->c_##type2 + eid, \
|
||||
@ -143,7 +242,7 @@ typedef int ecs_eid;
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM5(ecsname, fname, type1, type2, type3, type4, type5) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = \
|
||||
type1##_fl | type2##_fl | type3##_fl | type4##_fl | type5##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
@ -157,7 +256,7 @@ typedef int ecs_eid;
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM6(ecsname, fname, type1, type2, type3, type4, type5, type6) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ECS_FNTYPE void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl | type2##_fl | type3##_fl | type4##_fl | \
|
||||
type5##_fl | type6##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
|
2
haloo3d
2
haloo3d
@ -1 +1 @@
|
||||
Subproject commit 9fbc0948f182cd46c4aaff43b632f92f72fb4fb2
|
||||
Subproject commit 1667617d89a80f7802aca9260b9e79dd63ac56f6
|
18
make_ps2.sh
Executable file
18
make_ps2.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt "1" ]; then
|
||||
echo "ERROR: You must pass the program name! For instance, to build maze.elf,"
|
||||
echo "pass in just 'maze'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make -f Makefile_PS2 PROGRAM_PS2="$1"
|
||||
|
||||
if [ "$#" -gt "1" ]; then
|
||||
echo "Running on $2"
|
||||
ps2client -h "$2" reset
|
||||
sleep 1
|
||||
ps2client -h "$2" execee host:$1.elf
|
||||
fi
|
86
maze.c
86
maze.c
@ -1,13 +1,33 @@
|
||||
// NOTE: CANNOT USE JUST 'PS2' AS A DEFINE, IT BREAKS EVERYTHING
|
||||
#ifdef _EE
|
||||
#define DIRECTBUILD
|
||||
#define H3D_VOLATILE_FLOATS
|
||||
#endif
|
||||
|
||||
#ifdef DIRECTBUILD
|
||||
// clang-format off
|
||||
#define MATHC_USE_UNIONS
|
||||
#define MATHC_NO_STRUCT_FUNCTIONS
|
||||
#include "haloo3d/lib/mathc.c"
|
||||
#define FNL_IMPL
|
||||
#include "haloo3d/lib/FastNoiseLite.h"
|
||||
#include "haloo3d/haloo3d.c"
|
||||
#include "haloo3d/haloo3dex_console.c"
|
||||
#include "haloo3d/haloo3dex_easy.c"
|
||||
#include "haloo3d/haloo3dex_gen.c"
|
||||
#include "haloo3d/haloo3dex_obj.c"
|
||||
#include "haloo3d/haloo3dex_print.c"
|
||||
#include "unigi.platform.sdl2/main.c"
|
||||
// clang-format on
|
||||
#else
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_console.h"
|
||||
#include "haloo3d/haloo3dex_easy.h"
|
||||
#include "haloo3d/haloo3dex_gen.h"
|
||||
// #include "haloo3d/haloo3dex_img.h"
|
||||
#include "haloo3d/haloo3dex_obj.h"
|
||||
#include "haloo3d/haloo3dex_print.h"
|
||||
|
||||
#include "unigi/unigi.headers/src/main.h"
|
||||
#include "unigi/unigi.platform.sdl1/src/main.c"
|
||||
#include "unigi/main.h"
|
||||
#endif
|
||||
|
||||
#include "ecs2.h"
|
||||
#include "keys.h"
|
||||
@ -23,25 +43,34 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
// INteresting flags for debugging
|
||||
#define FASTFILL
|
||||
#define NUMMICE 1
|
||||
#define MOUSELOGGING
|
||||
// #define NOWALLS
|
||||
|
||||
#ifdef _EE
|
||||
#define WIDTH 160
|
||||
#define HEIGHT 120
|
||||
#define SCREENSCALE 4
|
||||
#define DITHERSTART 2.5
|
||||
#define DITHEREND 3.5
|
||||
int fps = 20;
|
||||
#else
|
||||
#define WIDTH 480
|
||||
#define HEIGHT 300
|
||||
#define ASPECT ((float)WIDTH / HEIGHT)
|
||||
#define SCREENSCALE 2
|
||||
#define MOUSELOGGING
|
||||
#define DITHERSTART 10000
|
||||
#define DITHEREND 10000
|
||||
int fps = 30;
|
||||
#endif
|
||||
|
||||
#define ASPECT ((float)WIDTH / HEIGHT)
|
||||
#define SWIDTH (WIDTH * SCREENSCALE)
|
||||
#define SHEIGHT (HEIGHT * SCREENSCALE)
|
||||
#define NEARCLIP 0.01
|
||||
#define FARCLIP 100.0
|
||||
#define LIGHTANG -MPI / 4.0
|
||||
#define AVGWEIGHT 0.85
|
||||
// Try 0.5 and 3.5 or something
|
||||
#define DITHERSTART 10000
|
||||
#define DITHEREND 10000
|
||||
|
||||
// Game options
|
||||
#define MAZESIZE 15
|
||||
@ -97,8 +126,7 @@ const char POLYNAMES[NUMPOLYS][20] = {"tetrahedron"};
|
||||
float fov = 90.0;
|
||||
float minlight = 0.15;
|
||||
float speed = 1.0;
|
||||
int fps = 30;
|
||||
uint16_t sky = 0xF000;
|
||||
uint16_t sky = 0xF644;
|
||||
|
||||
struct vec2i dirtovec(uint8_t dir) {
|
||||
struct vec2i result;
|
||||
@ -969,10 +997,20 @@ void create_paintingobj(haloo3d_obj *obj) {
|
||||
}
|
||||
}
|
||||
|
||||
int main() { // int argc, char **argv) {
|
||||
int main() { // int argc, char *argv[]) {
|
||||
|
||||
srand(clock());
|
||||
|
||||
// Init unigi system
|
||||
unigi_type_event event;
|
||||
unigi_type_resolution res;
|
||||
res.width = SWIDTH;
|
||||
res.height = SHEIGHT;
|
||||
res.depth = 0;
|
||||
|
||||
unigi_graphics_init();
|
||||
unigi_window_create(res, "maze.exe"); // render.printbuf);
|
||||
|
||||
haloo3d_easystore storage;
|
||||
haloo3d_easystore_init(&storage);
|
||||
|
||||
@ -986,6 +1024,7 @@ int main() { // int argc, char **argv) {
|
||||
render.autolightfix = 1;
|
||||
render.rendersettings.ditherclose = DITHERSTART;
|
||||
render.rendersettings.ditherfar = DITHEREND;
|
||||
// render.rendersettings.flags &= ~H3DR_PCT;
|
||||
// render.rendersettings.flags &= ~(H3DR_LIGHTING);
|
||||
render.rendersettings.pctminsize = 100;
|
||||
eprintf("Initialized renderer\n");
|
||||
@ -1071,25 +1110,11 @@ int main() { // int argc, char **argv) {
|
||||
init_billboard(endi, 0.25);
|
||||
eprintf("Setup all static object instances\n");
|
||||
|
||||
unigi_type_event event;
|
||||
unigi_type_resolution res;
|
||||
res.width = SWIDTH;
|
||||
res.height = SHEIGHT;
|
||||
res.depth = 0;
|
||||
|
||||
int totaldrawn = 0;
|
||||
|
||||
eprintf("Scene has %d tris, %d verts\n", render.totalfaces,
|
||||
render.totalverts);
|
||||
|
||||
// Init unigi system
|
||||
unigi_graphics_init();
|
||||
unigi_window_create(res, "maze.exe"); // render.printbuf);
|
||||
|
||||
// render.camera.pos.y = 4; // 5;
|
||||
// render.camera.pitch = MPI - 0.1; // 2.2;
|
||||
// ceili->pos.y = -10;
|
||||
|
||||
haloo3d_debugconsole dc;
|
||||
haloo3d_debugconsole_init(&dc);
|
||||
|
||||
@ -1191,17 +1216,10 @@ int main() { // int argc, char **argv) {
|
||||
|
||||
while (1) {
|
||||
haloo3d_easytimer_start(&frametimer);
|
||||
// render.camera.yaw += 0.008;
|
||||
haloo3d_perspective(render.perspective, fov, ASPECT, NEARCLIP, FARCLIP);
|
||||
haloo3d_easyrender_beginframe(&render);
|
||||
haloo3d_fb_clear(&render.window, sky);
|
||||
|
||||
// walli->scale.y = fabs(sin(3 * render.camera.yaw));
|
||||
// render.camera.up.x = sin(render.camera.yaw);
|
||||
// render.camera.up.y = cos(render.camera.yaw);
|
||||
// walli->up.x = sin(3 * render.camera.yaw);
|
||||
// walli->up.y = cos(4 * render.camera.yaw);
|
||||
|
||||
do {
|
||||
unigi_event_get(&event);
|
||||
switch (event.type) {
|
||||
|
@ -126,6 +126,12 @@ ECS_COMPONENT(ecs_object);
|
||||
ECS_COMPONENT(ecs_mazeentity);
|
||||
ECS_END(mecs)
|
||||
|
||||
ECS_FN_INIT(mecs)
|
||||
ECS_FN_NEWENTITY(mecs)
|
||||
ECS_FN_DELETEENTITY(mecs)
|
||||
ECS_FN_EID(mecs)
|
||||
ECS_FN_QUERY(mecs)
|
||||
|
||||
// And then a copy of the components here... that sucksssss
|
||||
ECS_CID(ecs_worldstate, 0);
|
||||
ECS_CID(ecs_world, 1);
|
||||
|
3
modeleditor/go.mod
Normal file
3
modeleditor/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module gitlumen.sh/haloopdy/3dtoys/modeleditor
|
||||
|
||||
go 1.23.0
|
9
modeleditor/main.go
Normal file
9
modeleditor/main.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Program starting\n")
|
||||
}
|
BIN
modeleditor/modeleditor
Executable file
BIN
modeleditor/modeleditor
Executable file
Binary file not shown.
3
notes.txt
Normal file
3
notes.txt
Normal file
@ -0,0 +1,3 @@
|
||||
1) MAKE SURE DEFINES ARE ISOLATED!
|
||||
Minxrod gave a very useful command to find them:
|
||||
find . -name '*.[ch]' | xargs grep -n -d recurse '#define .* [-+*/] .*' | grep -v '[(].* [-+*/] .*[)]'
|
@ -1,12 +1,11 @@
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_easy.h"
|
||||
// #include "haloo3d/haloo3dex_easy.h"
|
||||
#include "haloo3d/haloo3dex_gen.h"
|
||||
#include "haloo3d/haloo3dex_img.h"
|
||||
#include "haloo3d/haloo3dex_obj.h"
|
||||
#include "haloo3d/haloo3dex_print.h"
|
||||
|
||||
#include "unigi/unigi.headers/src/main.h"
|
||||
#include "unigi/unigi.platform.sdl1/src/main.c"
|
||||
#include "unigi/main.h"
|
||||
// #include "unigi/unigi.ext/src/main.c"
|
||||
|
||||
#include "camera.h"
|
||||
@ -16,7 +15,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#define DOLIGHTING
|
||||
#define FASTTRIS
|
||||
// #define FASTTRIS
|
||||
|
||||
// IDK you probably have to change this based on your display.
|
||||
// Maybe there's a way to fix this?
|
||||
@ -25,6 +24,7 @@
|
||||
|
||||
#define DITHERSTART 100
|
||||
#define DITHEREND 101
|
||||
#define PCTSTART 100
|
||||
|
||||
#define WIDTH 640
|
||||
#define HEIGHT 480
|
||||
@ -45,13 +45,13 @@
|
||||
#define NUMINSTANCES (NUMOBJECTS - 1 + NUMFLOWERS)
|
||||
#define MAXCAM 1200
|
||||
|
||||
#ifdef FASTTRIS
|
||||
#define WBUFCLEAR FARCLIP
|
||||
#define TRIFUNC haloo3d_texturedtriangle_fast
|
||||
#else
|
||||
#define WBUFCLEAR 0
|
||||
#define TRIFUNC haloo3d_texturedtriangle
|
||||
#endif
|
||||
// #ifdef FASTTRIS
|
||||
// #define WBUFCLEAR FARCLIP
|
||||
// #define TRIFUNC haloo3d_texturedtriangle_fast
|
||||
// #else
|
||||
// #define WBUFCLEAR 0
|
||||
// #define TRIFUNC haloo3d_texturedtriangle
|
||||
// #endif
|
||||
|
||||
#define CALCTIME(thistime, start, end, sum) \
|
||||
thistime = 1000.0 * (float)(end - start) / CLOCKS_PER_SEC; \
|
||||
@ -166,6 +166,9 @@ int main(int argc, char **argv) {
|
||||
// present in this
|
||||
haloo3d_trirender rendersettings;
|
||||
haloo3d_trirender_init(&rendersettings);
|
||||
rendersettings.ditherfar = DITHEREND;
|
||||
rendersettings.ditherclose = DITHERSTART;
|
||||
rendersettings.pctminsize = PCTSTART;
|
||||
|
||||
eprintf("Scene has %d tris, %d verts\n", totalfaces, totalverts);
|
||||
|
||||
@ -198,7 +201,7 @@ int main(int argc, char **argv) {
|
||||
camera.pitch = cams[cami].pitch + MPI_2;
|
||||
|
||||
// REMEMBER TO CLEAR DEPTH BUFFER
|
||||
haloo3d_fb_cleardepth(&fb, WBUFCLEAR);
|
||||
haloo3d_fb_cleardepth(&fb);
|
||||
|
||||
// Screen matrix calc. We multiply the modelview matrix with this later
|
||||
haloo3d_camera_calclook(&camera, matrixcam);
|
||||
@ -223,8 +226,9 @@ int main(int argc, char **argv) {
|
||||
objects[i].model->vtexture, face);
|
||||
int tris = haloo3d_facef_clip(face, outfaces);
|
||||
if (tris > 0) {
|
||||
haloo3d_easy_calcdither4x4(&rendersettings, face, DITHERSTART,
|
||||
DITHEREND);
|
||||
// haloo3d_getdither4x4(float dither, uint8_t *buf)
|
||||
// haloo3d_easy_calcdither4x4(&rendersettings, face, DITHERSTART,
|
||||
// DITHEREND);
|
||||
rendersettings.intensity = 1.0;
|
||||
if (objects[i].lighting) {
|
||||
haloo3d_obj_facef(objects[i].model, objects[i].model->faces[fi],
|
||||
@ -242,7 +246,7 @@ int main(int argc, char **argv) {
|
||||
// We still have to convert the points into the view
|
||||
haloo3d_facef_viewport_into(outfaces[ti], WIDTH, HEIGHT);
|
||||
// eprintf("RENDER TRI\n");
|
||||
TRIFUNC(&fb, &rendersettings, outfaces[ti]);
|
||||
haloo3d_triangle(&fb, &rendersettings, outfaces[ti]);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,9 +4,7 @@
|
||||
#include "haloo3d/haloo3dex_obj.h"
|
||||
#include "haloo3d/haloo3dex_print.h"
|
||||
|
||||
#include "unigi/unigi.headers/src/main.h"
|
||||
#include "unigi/unigi.platform.sdl1/src/main.c"
|
||||
// #include "unigi/unigi.ext/src/main.c"
|
||||
#include "unigi/main.h"
|
||||
|
||||
#include "camera.h"
|
||||
#include "keys.h"
|
||||
@ -227,7 +225,7 @@ int main(int argc, char **argv) {
|
||||
// camera.pitch = cams[cami].pitch + MPI_2;
|
||||
|
||||
// REMEMBER TO CLEAR DEPTH BUFFER
|
||||
haloo3d_fb_cleardepth(&fb, WBUFCLEAR);
|
||||
haloo3d_fb_cleardepth(&fb);
|
||||
|
||||
// Screen matrix calc. We multiply the modelview matrix with this later
|
||||
haloo3d_camera_calclook(&camera, matrixcam);
|
||||
@ -264,7 +262,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
// We still have to convert the points into the view
|
||||
haloo3d_facef_viewport_into(outfaces[ti], WIDTH, HEIGHT);
|
||||
TRIFUNC(&fb, &rendersettings, outfaces[ti]);
|
||||
haloo3d_triangle(&fb, &rendersettings, outfaces[ti]);
|
||||
}
|
||||
}
|
||||
}
|
922
terrain.c
Normal file
922
terrain.c
Normal file
@ -0,0 +1,922 @@
|
||||
#ifdef _EE
|
||||
#define DIRECTBUILD
|
||||
#define H3D_VOLATILE_FLOATS
|
||||
#endif
|
||||
|
||||
#ifdef DIRECTBUILD
|
||||
// clang-format off
|
||||
#define MATHC_USE_UNIONS
|
||||
#define MATHC_NO_STRUCT_FUNCTIONS
|
||||
#include "haloo3d/lib/mathc.c"
|
||||
#define FNL_IMPL
|
||||
#include "haloo3d/lib/FastNoiseLite.h"
|
||||
#include "haloo3d/haloo3d.c"
|
||||
#include "haloo3d/haloo3dex_easy.c"
|
||||
#include "haloo3d/haloo3dex_gen.c"
|
||||
#include "haloo3d/haloo3dex_obj.c"
|
||||
#include "haloo3d/haloo3dex_print.c"
|
||||
#include "unigi.platform.sdl2/main.c"
|
||||
// clang-format on
|
||||
#else
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_easy.h"
|
||||
#include "haloo3d/haloo3dex_gen.h"
|
||||
#include "haloo3d/haloo3dex_obj.h"
|
||||
#include "haloo3d/haloo3dex_print.h"
|
||||
#include "haloo3d/lib/FastNoiseLite.h"
|
||||
#include "haloo3d/lib/mathc.h"
|
||||
#include "unigi/main.h"
|
||||
#endif
|
||||
|
||||
// #include "keys.h"
|
||||
// #define ECS_MAXENTITIES 30000
|
||||
#include "terrain_ecstypes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
// #define LIMITEDPRINT
|
||||
// #define NOPRINT
|
||||
|
||||
#ifdef _EE
|
||||
#define WIDTH 160
|
||||
#define HEIGHT 120
|
||||
#define SCREENSCALE 4
|
||||
#define VIEWDISTANCE 2 // MAX IS AROUND 12
|
||||
#define MAXTREEPERCELL 4
|
||||
#define MAXTREEACROSS 2
|
||||
#define CHUNKINITFACES (H3D_OBJ_MAXFACES / 2)
|
||||
#define CHUNKINITVERTS (H3D_OBJ_MAXVERTICES / 2)
|
||||
#define INIT_DITHEREND 999
|
||||
#define INIT_DITHERSTART 999
|
||||
#else
|
||||
#define WIDTH 480
|
||||
#define HEIGHT 300
|
||||
#define SCREENSCALE 2
|
||||
#define VIEWDISTANCE 10 // MAX IS AROUND 12
|
||||
#define MAXTREEPERCELL 9
|
||||
#define MAXTREEACROSS 3
|
||||
#define CHUNKINITFACES H3D_OBJ_MAXFACES
|
||||
#define CHUNKINITVERTS H3D_OBJ_MAXVERTICES
|
||||
#define INIT_DITHEREND H3DVF(VIEWDISTANCE - 1.0)
|
||||
#define INIT_DITHERSTART H3DVF(INIT_DITHEREND * 0.5)
|
||||
#endif
|
||||
#define SWIDTH (WIDTH * SCREENSCALE)
|
||||
#define SHEIGHT (HEIGHT * SCREENSCALE)
|
||||
#define AVGWEIGHT H3DVF(0.85)
|
||||
#define DEFAULTUP \
|
||||
{ .x = 0, .y = 1, .z = 0 }
|
||||
// Lookvec for objects which all face forward along with the player
|
||||
#define DEFAULTLOOK \
|
||||
{ .x = 0, .y = 0, .z = -1 }
|
||||
|
||||
// How big each chunk is (x and y, square). MUST BE POWER OF 2 - 1
|
||||
#define CHUNKSIZE 7 // This is the width in tiles
|
||||
#define CHUNKSCALE H3DVF(1.0 / CHUNKSIZE)
|
||||
// This is how many vertices across a chunk is
|
||||
#define CHUNKVSIZE (CHUNKSIZE + 1)
|
||||
#define PLBOXEDGE (VIEWDISTANCE * 2 + 1)
|
||||
#define MAXCHUNKPERFRAME PLBOXEDGE
|
||||
|
||||
// Generation consts / things for looks
|
||||
#define COLOREDTERRAIN // Some cost, not much
|
||||
#define LANDHEIGHT H3DVF(4.0)
|
||||
#define LANDCOL 0xF7C3 // 0xF4E1
|
||||
#define FLANDCOL 0xF260 // 0xF3A0 // 0xF4E1
|
||||
#define UWLANDCOL 0xF026
|
||||
#define SEACOL 0xF28D // 0xF26C
|
||||
#define SKYCOL 0xF96E // 0xF77F
|
||||
#define SKYCOL2 0xFFAF // 0xF77F
|
||||
#define CLOUDCOL 0xFFDE
|
||||
#define TREECOL 0xF070
|
||||
#define TREETRUNKCOL 0xF950
|
||||
#define REDFLOWERCOL 0xFF46 // 0xFF9A
|
||||
#define YELLOWFLOWERCOL 0xFEE0
|
||||
#define TOWERCOL 0xF111
|
||||
#define LIGHTCOL 0xFF00
|
||||
#define SANDCOL 0xFDD8
|
||||
#define TOWERLOW H3DVF(0.755) // small changes to this make a huge difference
|
||||
#define TOWERLIGHTMINSIZE H3DVF(CHUNKSCALE * 0.1)
|
||||
#define TOWERLIGHTMAXSIZE H3DVF(CHUNKSCALE * 0.3)
|
||||
#define TOWERLIGHTMINTRANS H3DVF(0)
|
||||
#define TOWERLIGHTMAXTRANS H3DVF(0.4)
|
||||
#define TOWERLIGHTRATE H3DVF(1.5)
|
||||
#define SANDSTART H3DVF(0.085)
|
||||
#define TREEBOTTOM H3DVF(-0.333)
|
||||
#define TREETRUNKWIDTH H3DVF(0.20)
|
||||
#define SEATRANS H3DVF(0.5)
|
||||
#define CLOUDTRANSMIN H3DVF(0.1)
|
||||
#define CLOUDTRANSMAX H3DVF(0.2)
|
||||
#define CLOUDHEIGHT H3DVF(1 + VIEWDISTANCE * 0.1)
|
||||
#define CLOUDSTRETCH H3DVF(2)
|
||||
#define CLOUDCHANCE H3DVF(0.1)
|
||||
#define INIT_LIGHTPITCH H3DVF(MPI_2 * 1.65)
|
||||
#define INIT_LIGHTYAW H3DVF(MPI_2 * 0.65)
|
||||
#define INIT_MINLIGHT H3DVF(0.2)
|
||||
#define MAXTREECLOSENESS H3DVF(0.2)
|
||||
|
||||
// Player things
|
||||
#define INIT_FOV H3DVF(90.0)
|
||||
#define INIT_CAMPITCH H3DVF(MPI_2 * 1.3) // MPI_2 * 1.6 // 1.575
|
||||
#define INIT_PLAYERHEIGHT H3DVF(0.65)
|
||||
#define INIT_NEARCLIP H3DVF(0.010)
|
||||
#define INIT_FARCLIP H3DVF(100.0)
|
||||
#define INIT_PLAYERSPEED \
|
||||
{ .x = 0, .y = 0, .z = -1.5 }
|
||||
|
||||
#define RANDF() ((float)rand() / H3DVF(RAND_MAX))
|
||||
#define OFLOOR(v) (floor(fabs(v)) * ((v) < 0 ? -1 : 1))
|
||||
|
||||
// Some globals you can mess around with potentially
|
||||
int fps = 60;
|
||||
|
||||
#define PALETTEKEY "palette"
|
||||
#define TREEKEY "tree"
|
||||
#define CLOUDKEY "cloud"
|
||||
#define LIGHTKEY "light"
|
||||
#define REDFLOWERKEY "redflower"
|
||||
#define YELLOWFLOWERKEY "yellowflower"
|
||||
#define TOWERKEY "tower"
|
||||
|
||||
#include "commonobj.c"
|
||||
|
||||
static int gen_terrain_seed = 0;
|
||||
|
||||
static inline mfloat_t calc_barycentric(mfloat_t *point, mfloat_t *values,
|
||||
struct vec2 *triedge, int count) {
|
||||
mfloat_t we[3];
|
||||
for (int i = 0; i < count; i++) {
|
||||
int ofs = i * 3;
|
||||
we[0] = haloo3d_edgefunc(triedge[ofs + 1].v, triedge[ofs + 2].v, point);
|
||||
we[1] = haloo3d_edgefunc(triedge[ofs + 2].v, triedge[ofs + 0].v, point);
|
||||
we[2] = haloo3d_edgefunc(triedge[ofs + 0].v, triedge[ofs + 1].v, point);
|
||||
if (we[0] < 0 || we[1] < 0 || we[2] < 0) {
|
||||
continue;
|
||||
}
|
||||
return we[0] * values[ofs] + we[1] * values[ofs + 1] +
|
||||
we[2] * values[ofs + 2];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gen_tower(haloo3d_obj *model, haloo3d_obj *tower, tecs *ecs,
|
||||
render_context *ctx, struct vec3i chunk, struct vec3 pos) {
|
||||
const float scale = 0.5;
|
||||
pos.x += H3DVF(0.5);
|
||||
pos.y += scale;
|
||||
pos.z -= H3DVF(0.5);
|
||||
haloo3d_obj_addobj(model, tower, pos, (struct vec3)DEFAULTLOOK,
|
||||
(struct vec3)DEFAULTUP,
|
||||
(struct vec3){.x = scale, .y = scale, .z = scale});
|
||||
// Put a nice little light on top
|
||||
pos.y += scale;
|
||||
haloo3d_obj *light = haloo3d_easystore_getobj(&ecs->storage, LIGHTKEY);
|
||||
ecs_eid lightid = tecs_newentity(ecs, 0);
|
||||
eprintf("LIGHTING SPAWN: %d (%d,%d)\n", lightid, chunk.x, chunk.z);
|
||||
ECS_SETCOMPONENT(ecs, lightid, ecs_playergarbage){};
|
||||
ECS_SETCOMPONENT(ecs, lightid, ecs_towerlight){.timer = 0};
|
||||
ECS_SETCOMPONENT(ecs, lightid, ecs_placement){
|
||||
.up = DEFAULTUP,
|
||||
.lookvec = DEFAULTLOOK,
|
||||
.pos = (struct vec3){.x = chunk.x + pos.x * CHUNKSCALE,
|
||||
.y = pos.y * CHUNKSCALE * LANDHEIGHT,
|
||||
.z = chunk.z + pos.z * CHUNKSCALE}};
|
||||
ECS_SETCOMPONENT(ecs, lightid, ecs_object){
|
||||
.flatdither = 0.2,
|
||||
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
|
||||
.scale = {.x = CHUNKSCALE, .y = CHUNKSCALE, .z = CHUNKSCALE},
|
||||
.lighting = NULL,
|
||||
.stoplighting = 0,
|
||||
.model = light,
|
||||
.cullbackface = 0,
|
||||
.context = {ctx},
|
||||
.contextcount = 1};
|
||||
}
|
||||
|
||||
void gen_cloud(render_context *ctx, tecs *ecs, struct vec3i pos) {
|
||||
haloo3d_obj *cloud = haloo3d_easystore_getobj(&ecs->storage, CLOUDKEY);
|
||||
ecs_eid cloudid = tecs_newentity(ecs, 0);
|
||||
ECS_SETCOMPONENT(ecs, cloudid, ecs_playergarbage){};
|
||||
ECS_SETCOMPONENT(ecs, cloudid, ecs_placement){
|
||||
.up = DEFAULTUP,
|
||||
.lookvec = DEFAULTLOOK,
|
||||
.pos = {.x = pos.x + RANDF(),
|
||||
.y = CLOUDHEIGHT + H3DVF(0.5) * RANDF(),
|
||||
.z = pos.z - 0.9}};
|
||||
ECS_SETCOMPONENT(ecs, cloudid, ecs_object){
|
||||
.flatdither = CLOUDTRANSMIN + (CLOUDTRANSMAX - CLOUDTRANSMIN) * RANDF(),
|
||||
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
|
||||
.scale = {.x = H3DVF(1) + RANDF(),
|
||||
.y = H3DVF(1.0 / CLOUDSTRETCH),
|
||||
.z = 1},
|
||||
.lighting = NULL,
|
||||
.stoplighting = 0,
|
||||
.model = cloud,
|
||||
.cullbackface = 0,
|
||||
.context = {ctx},
|
||||
.contextcount = 1};
|
||||
}
|
||||
|
||||
uint16_t gen_terrain(struct vec3i pos, haloo3d_obj *model, tecs *ecs,
|
||||
render_context *ctx) {
|
||||
haloo3d_easystore *storage = &ecs->storage;
|
||||
eprintf("Generating terrain at %d,%d\n", pos.x, pos.z);
|
||||
haloo3d_obj *tree = haloo3d_easystore_getobj(storage, TREEKEY);
|
||||
haloo3d_obj *tower = haloo3d_easystore_getobj(storage, TOWERKEY);
|
||||
haloo3d_obj *flowers[2];
|
||||
flowers[0] = haloo3d_easystore_getobj(storage, REDFLOWERKEY);
|
||||
flowers[1] = haloo3d_easystore_getobj(storage, YELLOWFLOWERKEY);
|
||||
// Don't allow the model to have more than some amount of faces/vertices.
|
||||
haloo3d_obj_resetfixed(model, CHUNKINITFACES, CHUNKINITVERTS);
|
||||
#define LCOLSTEP 8
|
||||
// uint16_t sandcol = COMCOL(model, 0xFFF7);
|
||||
uint16_t landcols[(LCOLSTEP + 1) * 2];
|
||||
for (int i = 0; i <= LCOLSTEP; i++) {
|
||||
landcols[i] = COMCOL(
|
||||
model, haloo3d_col_lerp(LANDCOL, FLANDCOL, (float)i / H3DVF(LCOLSTEP)));
|
||||
landcols[i + LCOLSTEP + 1] =
|
||||
// 0xFDE6
|
||||
COMCOL(model, haloo3d_col_lerp(SANDCOL, UWLANDCOL,
|
||||
(float)i / H3DVF(LCOLSTEP)));
|
||||
}
|
||||
fnl_state ns = fnlCreateState();
|
||||
ns.noise_type = FNL_NOISE_OPENSIMPLEX2;
|
||||
ns.seed = gen_terrain_seed;
|
||||
ns.frequency = H3DVF(0.025);
|
||||
ns.fractal_type = FNL_FRACTAL_RIDGED;
|
||||
float noisex = pos.x * CHUNKSIZE;
|
||||
float noisey = -pos.z * CHUNKSIZE;
|
||||
for (int z = 0; z < CHUNKVSIZE; z++) {
|
||||
for (int x = 0; x < CHUNKVSIZE; x++) {
|
||||
// clang-format off
|
||||
haloo3d_obj_addvertex(model, (struct vec4){
|
||||
.x = x, .y = fnlGetNoise2D(&ns, noisex + x, noisey + z), .z = -z, .w = 1 });
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
struct vec2 triedge[6];
|
||||
mfloat_t heights[6];
|
||||
uint16_t faces[2];
|
||||
uint8_t gentower = 0;
|
||||
// A funny little thing... we're going to add flowers to this alternative
|
||||
// model, then add them to the end of the real model with a pointer saying
|
||||
// "don't do lighting past this point"
|
||||
haloo3d_obj nl_model;
|
||||
haloo3d_obj_resetfixed(&nl_model, H3D_OBJ_MAXFACES, H3D_OBJ_MAXVERTICES);
|
||||
for (int i = 0; i < CHUNKVSIZE * (CHUNKVSIZE - 1); i++) {
|
||||
if ((i & CHUNKSIZE) == CHUNKSIZE) {
|
||||
continue;
|
||||
}
|
||||
// Change frequency for subthings
|
||||
// ns.seed = 0;
|
||||
ns.frequency = 0.01; // 0.02;
|
||||
ns.fractal_type = FNL_FRACTAL_NONE;
|
||||
uint16_t bl = i;
|
||||
uint16_t br = i + 1;
|
||||
uint16_t tl = i + CHUNKVSIZE;
|
||||
uint16_t tr = i + CHUNKVSIZE + 1;
|
||||
faces[0] = fastface2(model, landcols[0], bl, br, tl);
|
||||
faces[1] = fastface2(model, landcols[0], br, tr, tl);
|
||||
float lowys[2];
|
||||
float highys[2];
|
||||
for (int t = 0; t < 2; t++) {
|
||||
lowys[t] = H3DVF(999);
|
||||
highys[t] = H3DVF(-999);
|
||||
for (int v = 0; v < 3; v++) {
|
||||
int ofs = t * 3;
|
||||
// NOTE: WE SWTICH Y AND Z TO MAKE THE EDGE FUNCTION WORK
|
||||
triedge[ofs + v].x = model->vertices[model->faces[faces[t]][v].posi].x;
|
||||
triedge[ofs + v].y = model->vertices[model->faces[faces[t]][v].posi].z;
|
||||
heights[ofs + v] = model->vertices[model->faces[faces[t]][v].posi].y;
|
||||
if (heights[ofs + v] < lowys[t])
|
||||
lowys[t] = heights[ofs + v];
|
||||
if (heights[ofs + v] > highys[t])
|
||||
highys[t] = heights[ofs + v];
|
||||
}
|
||||
#ifdef COLOREDTERRAIN
|
||||
uint16_t tfvi = model->faces[faces[t]][0].posi;
|
||||
float nlayer = fnlGetNoise2D(&ns, noisex + model->vertices[tfvi].x,
|
||||
noisey + model->vertices[tfvi].z);
|
||||
int landcol;
|
||||
if (highys[t] < SANDSTART) {
|
||||
landcol = LCOLSTEP + 1 + LCOLSTEP * fabs(highys[t]);
|
||||
} else {
|
||||
landcol = LCOLSTEP * fabs(lowys[t]) * (H3DVF(1) + nlayer) * H3DVF(0.5);
|
||||
}
|
||||
for (int v = 0; v < 3; v++) {
|
||||
model->faces[faces[t]][v].texi = landcols[landcol];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
float lowy = MIN(lowys[0], lowys[1]);
|
||||
int treecount = 0;
|
||||
for (int t = 0; t < MAXTREEPERCELL; t++) {
|
||||
// We know that the first vec in the first triangle is bl, which is our
|
||||
// base to start generating trees
|
||||
struct vec2 treepos = {
|
||||
.x = triedge[0].x + H3DVF(1.0 / MAXTREEACROSS) *
|
||||
((t % MAXTREEACROSS) +
|
||||
(H3DVF(1.0) - MAXTREECLOSENESS) * RANDF()),
|
||||
.y = triedge[0].y - (H3DVF(1.0 / MAXTREEACROSS) *
|
||||
((int)(t / MAXTREEACROSS) +
|
||||
(H3DVF(1.0) - MAXTREECLOSENESS) * RANDF()))};
|
||||
float y = calc_barycentric(treepos.v, heights, triedge, 2);
|
||||
float pick = RANDF(); // pow(RANDF(), 2);
|
||||
float nlayer = fnlGetNoise2D(&ns, noisex + treepos.x, noisey + treepos.y);
|
||||
if (pick < y * (H3DVF(1) + nlayer) * H3DVF(0.5)) {
|
||||
// Generate tree
|
||||
float scale = H3DVF(0.1) + RANDF() * H3DVF(0.05);
|
||||
float height = H3DVF(0.5) + RANDF() * H3DVF(0.5);
|
||||
haloo3d_obj_addobj(
|
||||
model, tree,
|
||||
(struct vec3){
|
||||
.x = treepos.x, .y = y + scale * height, .z = treepos.y},
|
||||
(struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP,
|
||||
(struct vec3){.x = scale, .y = scale * height, .z = scale});
|
||||
treecount++;
|
||||
} else if ((rand() & 3) == 0 && y < H3DVF(0.4) && y > H3DVF(0) &&
|
||||
RANDF() < -nlayer) {
|
||||
// Generate flower of random-ish color
|
||||
float scale = H3DVF(0.04);
|
||||
float vertscale = scale * (H3DVF(1) - H3DVF(0.5) * RANDF());
|
||||
haloo3d_obj_addobj(
|
||||
&nl_model, flowers[nlayer > H3DVF(-0.9)],
|
||||
(struct vec3){.x = treepos.x,
|
||||
.y = y + vertscale * H3DVF(0.5),
|
||||
.z = treepos.y},
|
||||
(struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP,
|
||||
(struct vec3){.x = scale, .y = vertscale, .z = scale});
|
||||
}
|
||||
}
|
||||
// You can put towers in cells with no trees that are high enough, as long
|
||||
// as this chunk doesn't already have one
|
||||
if (treecount == 0 && lowy > TOWERLOW && !gentower) {
|
||||
gentower = 1;
|
||||
gen_tower(&nl_model, tower, ecs, ctx, pos,
|
||||
(struct vec3){.x = triedge[0].x, .y = lowy, .z = triedge[0].y});
|
||||
}
|
||||
}
|
||||
// A silly hack to get a single model to render in multiple ways. Not good!
|
||||
uint16_t stoplighting = model->numfaces;
|
||||
haloo3d_obj_addobj(model, &nl_model, (struct vec3){.x = 0, .y = 0, .z = 0},
|
||||
(struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP,
|
||||
(struct vec3){.x = 1, .y = 1, .z = 1});
|
||||
haloo3d_obj_free(&nl_model);
|
||||
// Generate a cloud maybe
|
||||
if (RANDF() < CLOUDCHANCE)
|
||||
gen_cloud(ctx, ecs, pos);
|
||||
return stoplighting;
|
||||
}
|
||||
|
||||
// Generate the entity/components/terrain for the chunk at the given
|
||||
// coordinates.
|
||||
// NOTE: chunks are per x/y tile (terrain inside is just scaled
|
||||
// down to fit inside the 1x1 box)
|
||||
void gen_chunk(render_context *ctx, tecs *ecs, struct vec3i pos) {
|
||||
// eprintf("Generating chunk at %d,%d\n", pos.x, pos.y);
|
||||
ecs_eid id = tecs_newentity(ecs, 0);
|
||||
ecs_playergarbage garbage;
|
||||
sprintf(garbage.dynmodel, "e%d", id);
|
||||
haloo3d_obj *model =
|
||||
haloo3d_easystore_addobj(&ecs->storage, garbage.dynmodel);
|
||||
uint16_t stoplighting = gen_terrain(pos, model, ecs, ctx);
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_playergarbage) garbage;
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_chunk){.pos = pos};
|
||||
ECS_SETCOMPONENT(ecs, id,
|
||||
ecs_placement){.up = DEFAULTUP,
|
||||
.lookvec = DEFAULTLOOK,
|
||||
.pos = {.x = pos.x, .y = pos.y, .z = pos.z}};
|
||||
// TODO: an easy place for optimization (if it's even needed)
|
||||
// eprintf("TEX: %p\n", haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY));
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_object){
|
||||
.flatdither = 0,
|
||||
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
|
||||
.scale = {.x = CHUNKSCALE, .y = CHUNKSCALE * LANDHEIGHT, .z = CHUNKSCALE},
|
||||
.lighting = &ecs->chunklight,
|
||||
.stoplighting = stoplighting,
|
||||
.model = model,
|
||||
.cullbackface = 1,
|
||||
.context = {ctx},
|
||||
.contextcount = 1};
|
||||
}
|
||||
|
||||
void player_chunkload(ecs_placement *ppos, render_context *ctx, tecs *ecs) {
|
||||
struct vec3i pchunk = {.x = OFLOOR(ppos->pos.x),
|
||||
.y = OFLOOR(ppos->pos.y),
|
||||
.z = OFLOOR(ppos->pos.z)};
|
||||
// This is our little array of "filled chunks" around the player. We
|
||||
// use this to figure out what to generate
|
||||
ecs_eid surround[PLBOXEDGE][PLBOXEDGE] = {0};
|
||||
// Need to pull all existing objects that are killable
|
||||
ecs_eid matches[ECS_MAXENTITIES];
|
||||
// Find + iterate over killable objects placed in world
|
||||
int mcount = tecs_query(
|
||||
ecs, ecs_playergarbage_fl | ecs_placement_fl | ecs_object_fl, matches);
|
||||
int lostobjects = 0;
|
||||
for (int i = 0; i < mcount; i++) {
|
||||
ecs_placement *placement =
|
||||
&ECS_GETCOMPONENT(ecs, matches[i], ecs_placement);
|
||||
ecs_object *obj = &ECS_GETCOMPONENT(ecs, matches[i], ecs_object);
|
||||
// If this object is outside the view distance, we no longer have access to
|
||||
// it
|
||||
if (fabs(OFLOOR(placement->pos.x) - pchunk.x) > VIEWDISTANCE ||
|
||||
fabs(OFLOOR(placement->pos.z) - pchunk.z) > VIEWDISTANCE) {
|
||||
// OK, reduce the item refcount, since we're no longer close to it
|
||||
obj->contextcount--;
|
||||
lostobjects++;
|
||||
}
|
||||
// This is specifically a chunk, it might be within our view radius.
|
||||
if (ECS_HASCOMPONENT(ecs, matches[i], ecs_chunk)) {
|
||||
ecs_chunk *chunk = &ECS_GETCOMPONENT(ecs, matches[i], ecs_chunk);
|
||||
int surx = chunk->pos.x - pchunk.x + VIEWDISTANCE;
|
||||
int surz = chunk->pos.z - pchunk.z + VIEWDISTANCE;
|
||||
if (surx >= 0 && surz >= 0 && surx < PLBOXEDGE && surz < PLBOXEDGE) {
|
||||
// eprintf("SUR: %d %d\n", surx, sury);
|
||||
surround[surz][surx] = 1; // matches[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lostobjects) {
|
||||
eprintf("KILLABLE OBJS: %d PCHUNK: %d,%d\n", mcount, pchunk.x, pchunk.y);
|
||||
}
|
||||
int chunkgen = 0;
|
||||
// We now have our view radius box and which chunks are not loaded. Up to
|
||||
// some amount, let's load them
|
||||
for (int z = pchunk.z - VIEWDISTANCE; z <= pchunk.z + VIEWDISTANCE; z++) {
|
||||
for (int x = pchunk.x - VIEWDISTANCE; x <= pchunk.x + VIEWDISTANCE; x++) {
|
||||
int surx = x - pchunk.x + VIEWDISTANCE;
|
||||
int surz = z - pchunk.z + VIEWDISTANCE;
|
||||
if (!surround[surz][surx]) {
|
||||
gen_chunk(ctx, ecs, (struct vec3i){.x = x, .y = 0, .z = z});
|
||||
if (++chunkgen >= MAXCHUNKPERFRAME) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// The terrain ecs systems
|
||||
// ---------------------------------------------------
|
||||
|
||||
// All initialization for a specific render context
|
||||
void sys_rendercontext(ecs_rendercontext *erc, ecs_placement *p, tecs **ecs) {
|
||||
render_context *rc = *erc;
|
||||
struct vec3 lookat;
|
||||
mfloat_t cammatrix[MAT4_SIZE];
|
||||
mfloat_t perspective[MAT4_SIZE];
|
||||
// Some initial clearing
|
||||
haloo3d_fb_cleardepth(&rc->window);
|
||||
if (rc->windowclear & 0xF000) {
|
||||
haloo3d_fb_clear(&rc->window, rc->windowclear);
|
||||
}
|
||||
if (rc->backtex) {
|
||||
haloo3d_fb_fill_raw(&rc->window, rc->backtex, 0);
|
||||
}
|
||||
// Precalc stuff for later object rendering
|
||||
rc->precalc_halfwidth = rc->window.width * H3DVF(0.5);
|
||||
rc->precalc_halfheight = rc->window.height * H3DVF(0.5);
|
||||
haloo3d_perspective(perspective, rc->fov,
|
||||
(mfloat_t)rc->window.width / rc->window.height,
|
||||
rc->nearclip, rc->farclip);
|
||||
vec3_add(lookat.v, p->pos.v, p->lookvec.v);
|
||||
haloo3d_my_lookat(cammatrix, p->pos.v, lookat.v, p->up.v);
|
||||
mat4_inverse(cammatrix, cammatrix);
|
||||
mat4_multiply(rc->precalc_screen, perspective, cammatrix);
|
||||
|
||||
// Well, since we're here... might as well do the player-related stuff.
|
||||
// After all, we can be sure this is a player... right?
|
||||
player_chunkload(p, rc, *ecs);
|
||||
}
|
||||
|
||||
void sys_towerlight(ecs_towerlight *tl, tecs **ecs, ecs_object *o) {
|
||||
tl->timer += (*ecs)->delta_s;
|
||||
float ang = fabs(sin(tl->timer * TOWERLIGHTRATE));
|
||||
o->flatdither =
|
||||
TOWERLIGHTMINTRANS + (TOWERLIGHTMAXTRANS - TOWERLIGHTMINTRANS) * ang;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
o->scale.v[i] =
|
||||
TOWERLIGHTMINSIZE + (TOWERLIGHTMAXSIZE - TOWERLIGHTMINSIZE) * ang;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply rotation to lookvec of placement, overrides lookvec
|
||||
void sys_rotation(ecs_placement *p, ecs_rotation *r) {
|
||||
YAWP2VEC(r->yaw, r->pitch, p->lookvec.v);
|
||||
}
|
||||
|
||||
void sys_movement(ecs_placement *p, ecs_movement *m, tecs **ecs) {
|
||||
mfloat_t temp[VEC3_SIZE];
|
||||
vec3_multiply_f(temp, m->lookvec.v, (*ecs)->delta_s);
|
||||
vec3_add(p->lookvec.v, p->lookvec.v, temp);
|
||||
vec3_multiply_f(temp, m->up.v, (*ecs)->delta_s);
|
||||
vec3_add(p->up.v, p->up.v, temp);
|
||||
vec3_multiply_f(temp, m->pos.v, (*ecs)->delta_s);
|
||||
vec3_add(p->pos.v, p->pos.v, temp);
|
||||
// vec3_multiply(p->pos.v, p->pos.v, p->pos.v);
|
||||
}
|
||||
|
||||
// Perform the entire rendering of an object
|
||||
void sys_renderobject(ecs_placement *p, ecs_object *o, tecs **ecs) {
|
||||
// --**-- First, precalc all the vertices in the object --**--
|
||||
mfloat_t tmp[VEC4_SIZE];
|
||||
mfloat_t modelm[MAT4_SIZE];
|
||||
mfloat_t finalmatrix[MAT4_SIZE];
|
||||
struct vec4 precalc_verts[H3D_OBJ_MAXVERTICES];
|
||||
vec3_add(tmp, p->pos.v, p->lookvec.v);
|
||||
haloo3d_my_lookat(modelm, p->pos.v, tmp, p->up.v);
|
||||
// Apply scale such that it looks like it was applied first (this prevents
|
||||
// scaling applying skew to a rotated object)
|
||||
haloo3d_mat4_prescalev(modelm, o->scale.v);
|
||||
haloo3d_trirender rsettings;
|
||||
// We might be rendering into multiple contexts in a multiplayer game (or
|
||||
// just different angles or something)
|
||||
for (int ctx = 0; ctx < o->contextcount; ctx++) {
|
||||
memcpy(&rsettings, &o->context[ctx]->rendersettings,
|
||||
sizeof(haloo3d_trirender));
|
||||
rsettings.texture = o->texture;
|
||||
if (o->flatdither > 0) {
|
||||
rsettings.ditherflat = o->flatdither;
|
||||
}
|
||||
mat4_multiply(finalmatrix, o->context[ctx]->precalc_screen, modelm);
|
||||
haloo3d_precalc_verts(o->model, finalmatrix, precalc_verts);
|
||||
// --**-- Next, setup some rendering invariants --**--
|
||||
struct vec3 lighting;
|
||||
// The compiler is complaining about lighting being used unitialized, even
|
||||
// though it's not. Just shut it up
|
||||
vec3(lighting.v, 0, 0, 0);
|
||||
if (o->lighting) {
|
||||
if (o->lighting->autolightfix) {
|
||||
// Lighting doesn't rotate with the model unless you do it yourself.
|
||||
// In the easy system, you can request the renderer to do it for you
|
||||
struct vec4 ltmp, lout;
|
||||
// Lighting is centered at 0
|
||||
vec4(ltmp.v, 0, 0, 0, 1);
|
||||
// Calc the same lookat just without translation. THis should be the
|
||||
// same rotation matrix used on the model
|
||||
haloo3d_my_lookat(modelm, ltmp.v, p->lookvec.v, p->up.v);
|
||||
// We actually want the inverse. Apparently to speed things up, the
|
||||
// transpose works for rotation matrices(?) but I don't trust that
|
||||
// this lookat does that mat4_inverse(modelm, modelm);
|
||||
mat4_transpose(modelm, modelm);
|
||||
// We HAVE to have a vec4 (oof)
|
||||
vec4(ltmp.v, o->lighting->dir.x, o->lighting->dir.y, o->lighting->dir.z,
|
||||
1);
|
||||
haloo3d_vec4_multmat_into(<mp, modelm, &lout);
|
||||
// No need to fix W, should all be good (no perspective divide). But
|
||||
// we DO need to pull out that result
|
||||
vec3(lighting.v, lout.x, lout.y, lout.z);
|
||||
vec3_normalize(lighting.v, lighting.v);
|
||||
} else {
|
||||
vec3_assign(lighting.v, o->lighting->dir.v);
|
||||
}
|
||||
}
|
||||
// --**-- Finally, actually render faces --**--
|
||||
haloo3d_facef face, baseface;
|
||||
haloo3d_facef outfaces[H3D_FACEF_MAXCLIP];
|
||||
for (int facei = 0; facei < o->model->numfaces; facei++) {
|
||||
// Copy face values out of precalc array and clip them
|
||||
haloo3d_make_facef(o->model->faces[facei], precalc_verts,
|
||||
o->model->vtexture, face);
|
||||
int tris = haloo3d_facef_clip(face, outfaces);
|
||||
if (tris > 0) {
|
||||
uint8_t oflags = rsettings.flags;
|
||||
if (o->lighting && facei < o->stoplighting) {
|
||||
haloo3d_obj_facef(o->model, o->model->faces[facei], baseface);
|
||||
rsettings.intensity =
|
||||
haloo3d_calc_light(lighting.v, o->lighting->minlight, baseface);
|
||||
} else {
|
||||
rsettings.intensity = H3DVF(1.0);
|
||||
}
|
||||
// if ((r->_objstate[object - r->objects] & H3D_EASYOBJSTATE_NOTRANS))
|
||||
// {
|
||||
// r->rendersettings.flags &= ~H3DR_TRANSPARENCY;
|
||||
// }
|
||||
for (int ti = 0; ti < tris; ti++) {
|
||||
int backface = !haloo3d_facef_finalize(outfaces[ti]);
|
||||
if (o->cullbackface && facei < o->stoplighting && backface) {
|
||||
continue;
|
||||
}
|
||||
(*ecs)->totaldrawn++;
|
||||
// We still have to convert the points into the view
|
||||
haloo3d_facef_viewport_into_fast(outfaces[ti],
|
||||
o->context[ctx]->precalc_halfwidth,
|
||||
o->context[ctx]->precalc_halfheight);
|
||||
haloo3d_triangle(&o->context[ctx]->window, &rsettings, outfaces[ti]);
|
||||
}
|
||||
rsettings.flags = oflags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sys_playerinput(ecs_input *in) {
|
||||
in->numevents = 0;
|
||||
unigi_type_event event;
|
||||
do {
|
||||
unigi_event_get(&event);
|
||||
switch (event.type) {
|
||||
case unigi_enum_event_input_keyboard:
|
||||
if (event.data.input_keyboard.down) {
|
||||
switch (event.data.input_keyboard.button) {
|
||||
// case KEY_SPACE:
|
||||
// haloo3d_debugconsole_beginprompt(&dc);
|
||||
// break;
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
in->numevents++;
|
||||
} while (event.type != unigi_enum_event_none);
|
||||
}
|
||||
|
||||
void sys_playergarbage(ecs_playergarbage *pg, ecs_object *ob, tecs **ecs) {
|
||||
ecs_eid id = tecs_eid(ecs);
|
||||
if (ob->contextcount <= 0) {
|
||||
eprintf("Deleting object %d\n", id);
|
||||
if (pg->dynmodel[0]) {
|
||||
haloo3d_easystore_deleteobj(&(*ecs)->storage, pg->dynmodel,
|
||||
haloo3d_obj_free);
|
||||
}
|
||||
tecs_deleteentity(*ecs, id);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_placement_lock(ecs_placement_lock *lock, ecs_placement *pl) {
|
||||
if (lock->options & TECS_PLOCK_LOCKUP) {
|
||||
pl->up = lock->link->up;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKPOSX) {
|
||||
pl->pos.x = lock->link->pos.x;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKPOSY) {
|
||||
pl->pos.y = lock->link->pos.y;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKPOSZ) {
|
||||
pl->pos.z = lock->link->pos.z;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKLOOKX) {
|
||||
pl->lookvec.x = lock->link->lookvec.x;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKLOOKY) {
|
||||
pl->lookvec.y = lock->link->lookvec.y;
|
||||
}
|
||||
if (lock->options & TECS_PLOCK_LOCKLOOKZ) {
|
||||
pl->lookvec.z = lock->link->lookvec.z;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Setup functions
|
||||
// ---------------------------------------------------
|
||||
|
||||
ecs_eid setup_player(tecs *ecs, render_context *context) {
|
||||
ecs_eid playerid = tecs_newentity(ecs, 0);
|
||||
ECS_SETCOMPONENT(ecs, playerid, ecs_placement){
|
||||
.pos = {.x = 0, .y = INIT_PLAYERHEIGHT, .z = 0}, .up = DEFAULTUP};
|
||||
ECS_SETCOMPONENT(ecs, playerid, ecs_movement){.pos = INIT_PLAYERSPEED};
|
||||
ECS_SETCOMPONENT(ecs, playerid, ecs_rotation){.yaw = 0,
|
||||
.pitch = INIT_CAMPITCH};
|
||||
ECS_SETCOMPONENT(ecs, playerid, ecs_rendercontext) context;
|
||||
ECS_SETCOMPONENT(ecs, playerid, ecs_input){};
|
||||
return playerid;
|
||||
}
|
||||
|
||||
ecs_eid setup_sea(tecs *ecs, render_context *ctx, ecs_placement *playerpos,
|
||||
haloo3d_easystore *storage) {
|
||||
ecs_eid seaid = tecs_newentity(ecs, 0);
|
||||
ECS_SETCOMPONENT(ecs, seaid, ecs_placement){
|
||||
.pos = {.x = 0, .y = 0, .z = 0}, .lookvec = DEFAULTLOOK, .up = DEFAULTUP};
|
||||
ECS_SETCOMPONENT(ecs, seaid, ecs_placement_lock){
|
||||
.options = TECS_PLOCK_LOCKPOSX | TECS_PLOCK_LOCKPOSZ | TECS_PLOCK_LOCKUP,
|
||||
.link = playerpos,
|
||||
};
|
||||
haloo3d_obj *model = haloo3d_easystore_addobj(storage, "sea");
|
||||
haloo3d_obj_resetfixed(model, 2, 4);
|
||||
struct vec3 seacol = haloo3d_gen_paletteuv(SEACOL); // 0xF26F);
|
||||
int seauv = haloo3d_obj_addvtexture(model, seacol);
|
||||
// clang-format off
|
||||
// REMEMBER: NEGATIVE Z IS FORWARD
|
||||
int tl = haloo3d_obj_addvertex(model, (struct vec4){.x = -1, .y = 0, .z = -1, .w = 1});
|
||||
int tr = haloo3d_obj_addvertex(model, (struct vec4){.x = 1, .y = 0, .z = -1, .w = 1});
|
||||
int bl = haloo3d_obj_addvertex(model, (struct vec4){.x = -1, .y = 0, .z = 1, .w = 1});
|
||||
int br = haloo3d_obj_addvertex(model, (struct vec4){.x = 1, .y = 0, .z = 1, .w = 1});
|
||||
// clang-format on
|
||||
haloo3d_facei face;
|
||||
fastface(face, seauv, bl, br, tl);
|
||||
haloo3d_obj_addface(model, face);
|
||||
fastface(face, seauv, br, tr, tl);
|
||||
haloo3d_obj_addface(model, face);
|
||||
ECS_SETCOMPONENT(ecs, seaid, ecs_object){
|
||||
.flatdither = SEATRANS,
|
||||
.texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY),
|
||||
.scale = {.x = VIEWDISTANCE * 1.5,
|
||||
.y = VIEWDISTANCE * 1.5,
|
||||
.z = VIEWDISTANCE * 1.5},
|
||||
.lighting = NULL,
|
||||
.model = model,
|
||||
.cullbackface = 1,
|
||||
.context = {ctx},
|
||||
.contextcount = 1};
|
||||
return seaid;
|
||||
}
|
||||
|
||||
void draw_gradient(haloo3d_fb *buf, uint16_t topcol, uint16_t botcol,
|
||||
int height) {
|
||||
// Precalc an array indicating the bands of color.
|
||||
int row[64]; // not sure how many bands there can be but...
|
||||
uint16_t col[64];
|
||||
int bandscount = 1;
|
||||
row[0] = 0;
|
||||
col[0] = topcol;
|
||||
uint8_t dither[4];
|
||||
for (int y = 1; y < height; y++) {
|
||||
uint16_t thiscol =
|
||||
haloo3d_col_lerp(topcol, botcol, (float)y / (height - 1));
|
||||
if (thiscol != col[bandscount - 1]) {
|
||||
row[bandscount] = y;
|
||||
col[bandscount] = thiscol;
|
||||
bandscount++;
|
||||
}
|
||||
}
|
||||
for (int band = 0; band < bandscount - 1; band++) {
|
||||
for (int r = row[band]; r < row[band + 1]; r++) {
|
||||
haloo3d_getdither4x4((float)(r - row[band]) / (row[band + 1] - row[band]),
|
||||
dither);
|
||||
uint8_t df = dither[r & 3];
|
||||
for (int b = 0; b < 8; b++) {
|
||||
haloo3d_fb_set(buf, b, r, (df & 1) ? col[band + 1] : col[band]);
|
||||
df >>= 1;
|
||||
}
|
||||
uint16_t *bufstart = buf->buffer + r * buf->width;
|
||||
// Then, a repeated growing copy to minimize copies? IDK
|
||||
for (int size = 8; size < buf->width; size <<= 1) {
|
||||
memcpy(bufstart + size, bufstart,
|
||||
sizeof(uint16_t) * MIN(size, buf->width - size));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// MAIN FUNCTION
|
||||
// ---------------------------------------------------
|
||||
|
||||
int main() { // int argc, char **argv) {
|
||||
srand(clock());
|
||||
gen_terrain_seed = rand();
|
||||
|
||||
// Init unigi system. Can use anything here that can render to screen
|
||||
unigi_type_resolution res;
|
||||
res.width = SWIDTH;
|
||||
res.height = SHEIGHT;
|
||||
res.depth = 0;
|
||||
|
||||
unigi_graphics_init();
|
||||
unigi_window_create(res, "terrain.exe"); // render.printbuf);
|
||||
|
||||
eprintf("Initialized unigi system\n");
|
||||
|
||||
haloo3d_fb screen;
|
||||
haloo3d_fb_init(&screen, SWIDTH, SHEIGHT);
|
||||
haloo3d_print_tracker pt;
|
||||
char printbuf[8192];
|
||||
haloo3d_print_initdefault(&pt, printbuf, sizeof(printbuf));
|
||||
pt.fb = &screen;
|
||||
pt.scale = 1;
|
||||
|
||||
haloo3d_easytimer frametimer, drawtimer, sdltimer;
|
||||
haloo3d_easytimer_init(&frametimer, AVGWEIGHT);
|
||||
haloo3d_easytimer_init(&drawtimer, AVGWEIGHT);
|
||||
haloo3d_easytimer_init(&sdltimer, AVGWEIGHT);
|
||||
|
||||
haloo3d_fb skygrad;
|
||||
haloo3d_fb_init_tex(&skygrad, 1 << (int)ceil(log2(WIDTH)),
|
||||
1 << (int)ceil(log2(HEIGHT)));
|
||||
haloo3d_fb_clear(&skygrad, SKYCOL2);
|
||||
draw_gradient(&skygrad, SKYCOL, SKYCOL2, HEIGHT / 2);
|
||||
eprintf("Sky texture size: %dx%d\n", skygrad.width, skygrad.height);
|
||||
|
||||
render_context context;
|
||||
context.backtex = &skygrad;
|
||||
context.windowclear = 0; // SKYCOL;
|
||||
context.nearclip = INIT_NEARCLIP;
|
||||
context.farclip = INIT_FARCLIP;
|
||||
context.fov = INIT_FOV;
|
||||
haloo3d_trirender_init(&context.rendersettings);
|
||||
// context.rendersettings.flags &= ~H3DR_PCT;
|
||||
// context.rendersettings.flags &= ~H3DR_DITHERPIX;
|
||||
// context.rendersettings.flags |= H3DR_DITHERTRI;
|
||||
context.rendersettings.ditherclose = INIT_DITHERSTART;
|
||||
context.rendersettings.ditherfar = INIT_DITHEREND;
|
||||
// context.rendersettings.pctminsize = 500;
|
||||
haloo3d_fb_init(&context.window, WIDTH, HEIGHT);
|
||||
|
||||
eprintf("Initialized screen buffers, context, and timers\n");
|
||||
|
||||
tecs ecs;
|
||||
ecs.delta_s = 0;
|
||||
tecs_init(&ecs);
|
||||
int tecs_size = sizeof(tecs);
|
||||
YAWP2VEC(INIT_LIGHTYAW, INIT_LIGHTPITCH, ecs.globallighting.v);
|
||||
// An issue? Not a pointer? Eeehhh....
|
||||
ecs.chunklight.dir = ecs.globallighting;
|
||||
ecs.chunklight.minlight = INIT_MINLIGHT;
|
||||
ecs.chunklight.autolightfix = 0;
|
||||
|
||||
haloo3d_easystore_init(&ecs.storage);
|
||||
haloo3d_fb *palettetex = haloo3d_easystore_addtex(&ecs.storage, PALETTEKEY);
|
||||
haloo3d_gen_palettetex(palettetex);
|
||||
haloo3d_obj *treemodel = haloo3d_easystore_addobj(&ecs.storage, TREEKEY);
|
||||
gen_tree_model(treemodel);
|
||||
haloo3d_obj *cloudmodel = haloo3d_easystore_addobj(&ecs.storage, CLOUDKEY);
|
||||
gen_circle_model(cloudmodel, CLOUDCOL, 32);
|
||||
haloo3d_obj *lightmodel = haloo3d_easystore_addobj(&ecs.storage, LIGHTKEY);
|
||||
gen_circle_model(lightmodel, LIGHTCOL, 16);
|
||||
haloo3d_obj *redflower = haloo3d_easystore_addobj(&ecs.storage, REDFLOWERKEY);
|
||||
gen_flower_model(redflower, REDFLOWERCOL);
|
||||
haloo3d_obj *yellowflower =
|
||||
haloo3d_easystore_addobj(&ecs.storage, YELLOWFLOWERKEY);
|
||||
gen_flower_model(yellowflower, YELLOWFLOWERCOL);
|
||||
haloo3d_obj *tower = haloo3d_easystore_addobj(&ecs.storage, TOWERKEY);
|
||||
gen_tower_model(tower, TOWERCOL);
|
||||
|
||||
eprintf("Setup ECS system + obj/tex storage (%d bytes)\n", tecs_size);
|
||||
|
||||
ecs_eid playerid = setup_player(&ecs, &context);
|
||||
ecs_placement *playerpos = &ECS_GETCOMPONENT(&ecs, playerid, ecs_placement);
|
||||
ecs_eid seaid = setup_sea(&ecs, &context, playerpos, &ecs.storage);
|
||||
|
||||
eprintf("Setup player(%d) + sea(%d)\n", playerid, seaid);
|
||||
|
||||
// MAIN LOOP
|
||||
while (1) {
|
||||
haloo3d_easytimer_start(&frametimer);
|
||||
haloo3d_print_refresh(&pt);
|
||||
ecs.totaldrawn = 0;
|
||||
|
||||
// ECS logic (which includes rendering)
|
||||
if (ecs.delta_s) {
|
||||
ECS_RUNSYSTEM1(&ecs, sys_playerinput, ecs_input);
|
||||
ECS_RUNSYSTEM2(&ecs, sys_rotation, ecs_placement, ecs_rotation);
|
||||
ECS_RUNSYSTEM3(&ecs, sys_movement, ecs_placement, ecs_movement, tecs);
|
||||
ECS_RUNSYSTEM2(&ecs, sys_placement_lock, ecs_placement_lock,
|
||||
ecs_placement);
|
||||
ECS_RUNSYSTEM3(&ecs, sys_rendercontext, ecs_rendercontext, ecs_placement,
|
||||
tecs);
|
||||
ECS_RUNSYSTEM3(&ecs, sys_playergarbage, ecs_playergarbage, ecs_object,
|
||||
tecs);
|
||||
ECS_RUNSYSTEM3(&ecs, sys_towerlight, ecs_towerlight, tecs, ecs_object);
|
||||
haloo3d_easytimer_start(&drawtimer);
|
||||
ECS_RUNSYSTEM3(&ecs, sys_renderobject, ecs_placement, ecs_object, tecs);
|
||||
haloo3d_easytimer_end(&drawtimer);
|
||||
}
|
||||
|
||||
// Scale 3D into final buffer
|
||||
haloo3d_fb_fill(&screen, &context.window);
|
||||
|
||||
#ifndef NOPRINT
|
||||
// clang-format off
|
||||
haloo3d_print(&pt,
|
||||
"Pframe: %05.2f (%05.2f) DT: %0.3f\n"
|
||||
#ifndef LIMITEDPRINT
|
||||
"PSDLFl: %05.2f (%05.2f)\n"
|
||||
"Render: %05.2f (%05.2f)\n"
|
||||
"PlPos: %05.2f (%05.2f)\n"
|
||||
#endif
|
||||
"Tris: %d\n",
|
||||
frametimer.last * 1000, frametimer.sum * 1000, ecs.delta_s,
|
||||
#ifndef LIMITEDPRINT
|
||||
sdltimer.last * 1000, sdltimer.sum * 1000,
|
||||
drawtimer.last * 1000, drawtimer.sum * 1000,
|
||||
playerpos->pos.x, playerpos->pos.z,
|
||||
#endif
|
||||
ecs.totaldrawn);
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
// Finally, actually put buffer onto screen
|
||||
haloo3d_easytimer_start(&sdltimer);
|
||||
unigi_graphics_blit(0, (unigi_type_color *)screen.buffer,
|
||||
res.width * res.height);
|
||||
unigi_graphics_flush();
|
||||
haloo3d_easytimer_end(&sdltimer);
|
||||
|
||||
haloo3d_easytimer_end(&frametimer);
|
||||
|
||||
// Wait for next frame based on fps
|
||||
float waittime = (1.0 / fps) - frametimer.last;
|
||||
if (waittime > 0) {
|
||||
unigi_time_sleep(waittime * unigi_time_clocks_per_s);
|
||||
}
|
||||
ecs.delta_s = frametimer.last + MAX(waittime, 0);
|
||||
}
|
||||
|
||||
haloo3d_fb_free(&screen);
|
||||
haloo3d_fb_free(&context.window);
|
||||
haloo3d_easystore_deleteallobj(&ecs.storage, haloo3d_obj_free);
|
||||
haloo3d_easystore_deletealltex(&ecs.storage, haloo3d_fb_free);
|
||||
}
|
174
terrain_ecstypes.h
Normal file
174
terrain_ecstypes.h
Normal file
@ -0,0 +1,174 @@
|
||||
#ifndef __TERRAIN_ECSTYPES
|
||||
#define __TERRAIN_ECSTYPES
|
||||
|
||||
#define ECS_FNTYPE static
|
||||
|
||||
#include "ecs2.h"
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_easy.h"
|
||||
|
||||
#define TERRAIN_MAXPLAYERS 4
|
||||
|
||||
// Baseline render context. When a pointer to this is attached as a component,
|
||||
// it becomes a render target, and that entity will perform the precalcs
|
||||
// necessary for later object rendering.
|
||||
typedef struct {
|
||||
mfloat_t precalc_screen[MAT4_SIZE];
|
||||
mfloat_t precalc_halfwidth; // Optimization for reducing calcs per tri
|
||||
mfloat_t precalc_halfheight; // Optimization for reducing calcs per tri
|
||||
mfloat_t fov;
|
||||
mfloat_t nearclip;
|
||||
mfloat_t farclip;
|
||||
// NOTE: aspect ratio calculated from window
|
||||
haloo3d_fb window;
|
||||
haloo3d_fb *backtex;
|
||||
// Baseline render settings. Some of these settings will be applied to
|
||||
// each object associated with this context
|
||||
haloo3d_trirender rendersettings;
|
||||
// If alpha is 0, screen is not cleared
|
||||
uint16_t windowclear;
|
||||
} render_context;
|
||||
|
||||
// Associate this to some entity along with a placement and it will be the
|
||||
// main "renderer" for a viewpoint
|
||||
typedef render_context *ecs_rendercontext;
|
||||
|
||||
// Associate lighting with some object. Since this is part of the renderer,
|
||||
// this isn't a component you can assign (it also doesn't mean anything on its
|
||||
// own)
|
||||
typedef struct {
|
||||
struct vec3 dir;
|
||||
mfloat_t minlight;
|
||||
// Whether to automatically move lighting when models have a
|
||||
// lookvec. This also normalizes the light
|
||||
uint8_t autolightfix;
|
||||
} object_lighting;
|
||||
|
||||
// All values which allow rendering of a 3d object
|
||||
typedef struct {
|
||||
// haloo3d_trirender rendersettings; // baseline settings for THIS object.
|
||||
render_context *context[TERRAIN_MAXPLAYERS]; // What to render into
|
||||
struct vec3 scale; // how big the thing should be in world
|
||||
object_lighting *lighting; // a pointer to lighting, null for none
|
||||
haloo3d_obj *model;
|
||||
haloo3d_fb *texture;
|
||||
uint16_t stoplighting;
|
||||
uint8_t cullbackface; // Whether to cull backfaces (you probably should)
|
||||
uint8_t contextcount; // How many contexts we render into
|
||||
float flatdither; // A flat dither amount. Set to -1 to disable
|
||||
} ecs_object;
|
||||
|
||||
// Some placement within the world. Doesn't imply anything other than a
|
||||
// position and a facing direction
|
||||
typedef struct {
|
||||
struct vec3 pos;
|
||||
struct vec3 up;
|
||||
struct vec3 lookvec;
|
||||
} ecs_placement;
|
||||
|
||||
// If set, locks the placement of one entity to another
|
||||
typedef struct {
|
||||
ecs_placement *link;
|
||||
// struct vec3 posofs; // The offset from linked pos
|
||||
uint8_t options; // Which things to lock
|
||||
} ecs_placement_lock;
|
||||
|
||||
#define TECS_PLOCK_LOCKLOOKX 1
|
||||
#define TECS_PLOCK_LOCKLOOKY 2
|
||||
#define TECS_PLOCK_LOCKLOOKZ 4
|
||||
#define TECS_PLOCK_LOCKPOSX 8
|
||||
#define TECS_PLOCK_LOCKPOSY 16
|
||||
#define TECS_PLOCK_LOCKPOSZ 32
|
||||
#define TECS_PLOCK_LOCKUP 64
|
||||
|
||||
// typedef ecs_placement *ecs_placement_lock;
|
||||
|
||||
typedef struct {
|
||||
// The data required to animate the tower light
|
||||
float timer;
|
||||
} ecs_towerlight;
|
||||
|
||||
// Movement is applied to placement and may also be used to check for
|
||||
// collisions and whatever
|
||||
typedef struct {
|
||||
struct vec3 pos;
|
||||
struct vec3 up;
|
||||
struct vec3 lookvec;
|
||||
} ecs_movement;
|
||||
|
||||
// Use rotation to override the lookvec of an ecs_placement
|
||||
typedef struct {
|
||||
mfloat_t yaw;
|
||||
mfloat_t pitch;
|
||||
} ecs_rotation;
|
||||
|
||||
// Type to track and mark some entity as receiving input events.
|
||||
typedef struct {
|
||||
int numevents;
|
||||
} ecs_input;
|
||||
|
||||
// Simple component for some entity that should clean itself up
|
||||
// when there are no more "references" to it. Whatever that means...
|
||||
// some fields are for special cleanup
|
||||
typedef struct {
|
||||
char dynmodel[8]; // A model we may have to cleanup
|
||||
} ecs_playergarbage;
|
||||
|
||||
// Represents the singular object that is the entire stationary
|
||||
// object of terrain. The position is the "chunk position", which
|
||||
// should be integer aligned. Not necessarily 1:1 with world
|
||||
// coordinates?
|
||||
typedef struct {
|
||||
struct vec3i pos;
|
||||
// uint8_t generation; // The type(?) of generation (idk honestly)
|
||||
} ecs_chunk;
|
||||
|
||||
// // A billboard for OUR system, which does not look up or down at the target.
|
||||
// As
|
||||
// // such, no matter what the lookat is set to, y is always going to be equal
|
||||
// to
|
||||
// // the y of the instance, so it appears to be looking "straight"
|
||||
// typedef struct {
|
||||
// haloo3d_obj_instance *obj;
|
||||
// struct vec3 *lookat;
|
||||
// } ecs_billboard;
|
||||
|
||||
// Setup ECS system for our game
|
||||
ECS_START(tecs)
|
||||
float delta_s; // Store delta time in ecs
|
||||
int totaldrawn; // A place to store total drawn tris
|
||||
struct vec3 globallighting; // the global lighting to apply to terrain
|
||||
object_lighting chunklight; // lighting to assign to a chunk
|
||||
// Everyone needs to be able to get and set obj/texture
|
||||
haloo3d_easystore storage;
|
||||
ECS_COMPONENT(ecs_rendercontext)
|
||||
ECS_COMPONENT(ecs_object)
|
||||
ECS_COMPONENT(ecs_placement)
|
||||
ECS_COMPONENT(ecs_rotation)
|
||||
ECS_COMPONENT(ecs_movement)
|
||||
ECS_COMPONENT(ecs_input)
|
||||
ECS_COMPONENT(ecs_playergarbage)
|
||||
ECS_COMPONENT(ecs_chunk)
|
||||
ECS_COMPONENT(ecs_placement_lock)
|
||||
ECS_COMPONENT(ecs_towerlight)
|
||||
ECS_END(tecs)
|
||||
|
||||
ECS_FN_INIT(tecs)
|
||||
ECS_FN_NEWENTITY(tecs)
|
||||
ECS_FN_DELETEENTITY(tecs)
|
||||
ECS_FN_EID(tecs)
|
||||
ECS_FN_QUERY(tecs)
|
||||
|
||||
// And then a copy of the components here... that sucksssss
|
||||
ECS_CID(ecs_rendercontext, 0)
|
||||
ECS_CID(ecs_object, 1)
|
||||
ECS_CID(ecs_placement, 2)
|
||||
ECS_CID(ecs_rotation, 3)
|
||||
ECS_CID(ecs_movement, 4)
|
||||
ECS_CID(ecs_input, 5)
|
||||
ECS_CID(ecs_playergarbage, 6)
|
||||
ECS_CID(ecs_chunk, 7)
|
||||
ECS_CID(ecs_placement_lock, 8)
|
||||
ECS_CID(ecs_towerlight, 9)
|
||||
|
||||
#endif
|
1
unigi
Submodule
1
unigi
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8767a3dd8538c6650ab06f36c15d926d12a4b081
|
1
unigi.platform.sdl1
Submodule
1
unigi.platform.sdl1
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c2bb042dcb29e55879f9b0b415c2989afed56132
|
1
unigi.platform.sdl2
Submodule
1
unigi.platform.sdl2
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 7761a397a86b0e94bf5d7280b3c2c65e3713fae8
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
cd unigi
|
||||
git pull
|
||||
cd ../unigi.headers
|
||||
git pull
|
||||
cd ../unigi.ext
|
||||
git pull
|
||||
cd ../unigi.platform.sdl1
|
||||
git pull
|
@ -1 +0,0 @@
|
||||
Subproject commit 34aa7f0a1cd24939c2de879b5dcce03daa0c7de2
|
@ -1 +0,0 @@
|
||||
Subproject commit cf21dd85c6d49509c946ab9f462edc2e8a73327c
|
@ -1 +0,0 @@
|
||||
Subproject commit ab07d46aac8d7043399437b83f81ce8ce3bf1233
|
@ -1 +0,0 @@
|
||||
Subproject commit e407020c2118d7ad2f4d43eca5214b6360a0b7cc
|
Loading…
Reference in New Issue
Block a user