From 97d6b8c0419fa96896fb600983fd080122463518 Mon Sep 17 00:00:00 2001 From: xtreme8000 Date: Fri, 11 Nov 2022 19:00:55 +0100 Subject: [PATCH] Codebase ported from old project also added many new things --- .clang-format | 38 + .editorconfig | 5 + Makefile | 150 ++++ icon.png | Bin 0 -> 7708 bytes meta.xml | 10 + source/block/aabb.c | 72 ++ source/block/aabb.h | 22 + source/block/block_bed.c | 80 ++ source/block/block_bedrock.c | 44 ++ source/block/block_bricks.c | 44 ++ source/block/block_brown_mushroom.c | 45 ++ source/block/block_cactus.c | 57 ++ source/block/block_cake.c | 62 ++ source/block/block_cast_block.c | 104 +++ source/block/block_chest.c | 126 +++ source/block/block_clay.c | 44 ++ source/block/block_cobblestone.c | 63 ++ source/block/block_crops.c | 44 ++ source/block/block_dirt.c | 44 ++ source/block/block_double_slab.c | 57 ++ source/block/block_farmland.c | 53 ++ source/block/block_fire.c | 44 ++ source/block/block_flower.c | 45 ++ source/block/block_furnace.c | 82 ++ source/block/block_glass.c | 45 ++ source/block/block_glowstone.c | 44 ++ source/block/block_grass.c | 57 ++ source/block/block_gravel.c | 44 ++ source/block/block_ice.c | 45 ++ source/block/block_ladder.c | 61 ++ source/block/block_lava.c | 62 ++ source/block/block_leaves.c | 62 ++ source/block/block_log.c | 67 ++ source/block/block_obsidian.c | 44 ++ source/block/block_ore.c | 138 ++++ source/block/block_planks.c | 44 ++ source/block/block_portal.c | 43 ++ source/block/block_pumpkin.c | 82 ++ source/block/block_rail.c | 94 +++ source/block/block_red_mushroom.c | 45 ++ source/block/block_reed.c | 45 ++ source/block/block_rose.c | 45 ++ source/block/block_sand.c | 44 ++ source/block/block_sandstone.c | 48 ++ source/block/block_sapling.c | 49 ++ source/block/block_slab.c | 61 ++ source/block/block_snow.c | 48 ++ source/block/block_spawner.c | 44 ++ source/block/block_stairs.c | 59 ++ source/block/block_stone.c | 44 ++ source/block/block_tallgrass.c | 70 ++ source/block/block_torch.c | 93 +++ source/block/block_water.c | 57 ++ source/block/block_workbench.c | 52 ++ source/block/blocks.c | 182 +++++ source/block/blocks.h | 169 +++++ source/block/face_occlusion.c | 96 +++ source/block/face_occlusion.h | 23 + source/chunk.c | 574 ++++++++++++++ source/chunk.h | 52 ++ source/displaylist.c | 44 ++ source/displaylist.h | 20 + source/render_block.c | 736 ++++++++++++++++++ source/render_block.h | 63 ++ source/stack.c | 80 ++ source/stack.h | 30 + source/triangle.c | 1094 +++++++++++++++++++++++++++ source/world.c | 24 + source/world.h | 37 + 69 files changed, 6295 insertions(+) create mode 100755 .clang-format create mode 100755 .editorconfig create mode 100644 Makefile create mode 100644 icon.png create mode 100644 meta.xml create mode 100644 source/block/aabb.c create mode 100644 source/block/aabb.h create mode 100644 source/block/block_bed.c create mode 100755 source/block/block_bedrock.c create mode 100644 source/block/block_bricks.c create mode 100644 source/block/block_brown_mushroom.c create mode 100644 source/block/block_cactus.c create mode 100644 source/block/block_cake.c create mode 100644 source/block/block_cast_block.c create mode 100644 source/block/block_chest.c create mode 100644 source/block/block_clay.c create mode 100755 source/block/block_cobblestone.c create mode 100644 source/block/block_crops.c create mode 100644 source/block/block_dirt.c create mode 100644 source/block/block_double_slab.c create mode 100644 source/block/block_farmland.c create mode 100644 source/block/block_fire.c create mode 100644 source/block/block_flower.c create mode 100644 source/block/block_furnace.c create mode 100644 source/block/block_glass.c create mode 100644 source/block/block_glowstone.c create mode 100755 source/block/block_grass.c create mode 100644 source/block/block_gravel.c create mode 100644 source/block/block_ice.c create mode 100644 source/block/block_ladder.c create mode 100644 source/block/block_lava.c create mode 100644 source/block/block_leaves.c create mode 100644 source/block/block_log.c create mode 100644 source/block/block_obsidian.c create mode 100644 source/block/block_ore.c create mode 100644 source/block/block_planks.c create mode 100644 source/block/block_portal.c create mode 100644 source/block/block_pumpkin.c create mode 100644 source/block/block_rail.c create mode 100644 source/block/block_red_mushroom.c create mode 100644 source/block/block_reed.c create mode 100644 source/block/block_rose.c create mode 100644 source/block/block_sand.c create mode 100644 source/block/block_sandstone.c create mode 100644 source/block/block_sapling.c create mode 100644 source/block/block_slab.c create mode 100644 source/block/block_snow.c create mode 100644 source/block/block_spawner.c create mode 100644 source/block/block_stairs.c create mode 100644 source/block/block_stone.c create mode 100644 source/block/block_tallgrass.c create mode 100644 source/block/block_torch.c create mode 100644 source/block/block_water.c create mode 100644 source/block/block_workbench.c create mode 100755 source/block/blocks.c create mode 100755 source/block/blocks.h create mode 100644 source/block/face_occlusion.c create mode 100644 source/block/face_occlusion.h create mode 100644 source/chunk.c create mode 100644 source/chunk.h create mode 100644 source/displaylist.c create mode 100644 source/displaylist.h create mode 100644 source/render_block.c create mode 100644 source/render_block.h create mode 100755 source/stack.c create mode 100755 source/stack.h create mode 100644 source/triangle.c create mode 100644 source/world.c create mode 100644 source/world.h diff --git a/.clang-format b/.clang-format new file mode 100755 index 0000000..c66e129 --- /dev/null +++ b/.clang-format @@ -0,0 +1,38 @@ +--- +BasedOnStyle: WebKit +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: 'false' +AlignConsecutiveDeclarations: 'false' +AlignTrailingComments: 'true' +AllowAllParametersOfDeclarationOnNextLine: 'true' +AllowShortBlocksOnASingleLine: 'true' +AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: 'false' +AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: 'false' +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: 'false' +Cpp11BracedListStyle: 'true' +ExperimentalAutoDetectBinPacking: 'false' +IndentCaseLabels: 'true' +KeepEmptyLinesAtTheStartOfBlocks: 'false' +Language: Cpp +PointerAlignment: Left +SortIncludes: 'true' +SpaceAfterCStyleCast: 'false' +SpaceBeforeAssignmentOperators: 'true' +SpaceBeforeParens: Never +SpaceInEmptyParentheses: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInParentheses: 'false' +SpacesInSquareBrackets: 'false' +TabWidth: '4' +UseTab: Always +MaxEmptyLinesToKeep: 1 +ReflowComments: 'true' +ColumnLimit: '80' + +... diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..5d5968c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*] +indent_style = tab +indent_size = 4 +end_of_line = lf +trim_trailing_whitespace = true diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..084fffc --- /dev/null +++ b/Makefile @@ -0,0 +1,150 @@ +#--------------------------------------------------------------------------------- +# Clear the implicit built in rules +#--------------------------------------------------------------------------------- +.SUFFIXES: +.SECONDARY: +#--------------------------------------------------------------------------------- +# prevent deletion of implicit targets +#--------------------------------------------------------------------------------- +.SECONDARY: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +include $(DEVKITPPC)/wii_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source source/block +DATA := +TEXTURES := textures +INCLUDES := + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- + +CFLAGS = -std=c99 -pedantic -Wextra -Wno-unused-parameter -flto=auto -O3 -Wall $(MACHDEP) $(INCLUDE) +CXXFLAGS = $(CFLAGS) + +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := -lwiiuse -lfat -lbte -logc -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(foreach dir,$(TEXTURES),$(CURDIR)/$(dir)) + + +export DEPSDIR := $(CURDIR)/$(BUILD) + +#--------------------------------------------------------------------------------- +# automatically build a list of object files for our project +#--------------------------------------------------------------------------------- +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +SCFFILES := $(foreach dir,$(TEXTURES),$(notdir $(wildcard $(dir)/*.scf))) +TPLFILES := $(SCFFILES:.scf=.tpl) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) + export LD := $(CC) +else + export LD := $(CXX) +endif + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(addsuffix .o,$(TPLFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ + $(sFILES:.s=.o) $(SFILES:.S=.o) + +#--------------------------------------------------------------------------------- +# build a list of include paths +#--------------------------------------------------------------------------------- +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) \ + -I$(LIBOGC_INC) + +#--------------------------------------------------------------------------------- +# build a list of library paths +#--------------------------------------------------------------------------------- +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + -L$(LIBOGC_LIB) + +export OUTPUT := $(CURDIR)/$(TARGET) +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol +#--------------------------------------------------------------------------------- +run: + wiiload $(OUTPUT).dol + +#--------------------------------------------------------------------------------- +else + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).dol: $(OUTPUT).elf +$(OUTPUT).elf: $(OFILES) + +#--------------------------------------------------------------------------------- +# This rule links in binary data with the .bin extension +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + $(bin2o) + +#--------------------------------------------------------------------------------- +%.tpl.o : %.tpl +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPSDIR)/*.d + +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..32fd04c9aea2d210a137f95f6e7327ed94410c73 GIT binary patch literal 7708 zcmV+%9^>JOP)ktI)g)@F)l`kqg3W|T2BS4qjK)xTlswU< z;#3Q0#Y?~lsFC25f>9Yl5F99j*E^hPPiytZyU%ylJ?YaX_Xp4Au+Q3SeZ%{`->~50 z$B$=>DWw==X_`tYl~Tr-G)m2tgtuK`Et#5ZF2Xs^|=v;FJo(PzaIB zBng=mJ=r9ENDunMI?8bzR{!bm?^j9%LEtzJUJ3QkT6h5@MdG%VM=ujX#7snSECgr9 zaL$!U!zhuG>r@ENHT0@{JP+~FE69_y*5z^;mPN;)XYha!0;WxSprd-8N8Sm^LRF+} zh))O+1c8*YR;xh=jIk(+u)eJfrPRQ{fbaWI3{+@)Gt86(LcUJoBHc(SrIe~xtC0bE zo=09xW=;nnbZSB&ESjdN<2bes4C6vMqz}!Q=9+Py8Y7HhjHiiVI%14*F4$nfVV6mg z#Bog9fW5I@Fv(IF^ zsVJ;+6EbEv7gBJ;h2T78TnJ%=YJzw=9^Q!Kk#`bg;a$L47;g{+fMbdQkiHP2P$&R8 za7>&La){$tN=b-^U*H_TcLD<`WgN%AZ30X(CW-{u6@-(fDZVI#P!JaBiY$mCp)tmF z-DtY=W09b)wigS(?$Q+>tin@Re_zlqn+K+8{j^p5U#+b~|5ZOrw zkRaZtl!~IrbzN-5COjlfXaXx@yLc-dfSkgshj2U1VV_Zlnl|$Y` zt5NKwkP8iwqYzO6Um&By!&>VoieURVKH?3Y#BqGz2L#z+A8SIU#6++kgaoo_o4GV` z2l_-&d>}_A|8iZI{D}Alft4Lt=xnrzjdxArAR$tu8AKJhV1hHov@wh^C8e@L3%#z1 zbm32WJ5d(`A{beFdwUc`)oQg?tAQ8QYBeIM^ zkC1?4(zmd=;p_CFO;wwine9?d zp@qIqe>TN`+98-2eHX|XMG;WjMh21^Nf66QDSh7uh(ivPcF}vA_yw$!K-G0!Bu_T` z!0)+S4vHZkf>|rP&yM)M?;{34+YkZ%iu2f!mW;^uUy5Be5R(Y-B-G!8X7(=xZZ@Z; zKt=3}_75rBoR|n3>`_YTx^AUX34$OD!zLV~7*3XlK%FE>7>2}F>9F{rxMD{s$OMX^ zgri!m+Q5+MvI(^zGUPs<=V4JWIi*ygP^eTY0|Ns#4W+G+A(PFLc~ZD;N}C7e4VDMk zTCx3xbO6hMZ4!Y7+5|y>)QsXJA)d{Yf*=5^rjTgE2-IAw)gS@i_mxthn^6=|um!kd zw}{?ELl7S908X*fPMB33$CN}s=g7#yFhrFGv55Qt_=SIE)(?>fdn=_<$xh1c@Jor6 z9i^KByX{!yTUejmJc^=&2M^jMfkL4GYo(}2aF0J-*G2kCB^C+{c!lr#q!{9`bq!G>+@rDs&3P@wN5Nm446U>y{ekNI;p%v8CmddGo$}^2rlM zjp}M^YxO)Oc@kGjrB4nVc>lfkUV8G$ho5_{)I^HN*r@<#*YC(hJV!Z7a-$7nLaHQ5 z9LZA7v^JVC%{UN-puEYMV3o3^<*O@Ke!ZiE{RKZ!clTKf7xrt<`|C#^T{L<$@F9ve zegFG6|K>MNZ*Q;TI7q$_Atf?C2(%+0_fX zLPC&50WE_vnW` zKgJkVsjOJCY*J^dCL(#4+>c z-PGMZh+o=lhY$XN0$kTUuyb9OF2!k@>RSKaB#Ala0|yTPmxyE7#zm}`b8dtfEY?J8 z{{IPIYt2!@OE+%((b~07op)XfV~mM0V{W?PhL?Z((<-MZd)vtcNX3ZNPeZ)Fu z&OGbfb7!A@_E}wBk}<}_(4kk{b=STfJMR4BAB`QW?T~2y6)A=9`{jdg2Z5Jr_DN5f zbD@o4hI5fI9O9RNGGWP@iY>Nc7-JuNaQnp?(Toyxl>Z6Hf7$t3yZ}%glv2G;idcbH5j&Cuxd(i8U|OZ)sPwD zBq+2}l^i4$K9S4i#03}J{)I2prEdlX)-7Ck+Qk>&`SYK@{_)40b3X9ut1A{Qx_0*L z>o;vG*99_iIujW_=3kw*-IJSD9lvP~q=HaL~f=bJ(VHj01_Yr=-2G@W_r zrIYHX(t798rGNj(BNfOIHkFB^ukVHHuDf&P%Geb#xRxPqDaC`DEX|ci;K_vpaUGBSw!=j<=jjI?n4aw|S-W=jEw}VWRwSoujW%u7-vNLwE0UCoemH+S_lx zx@OH2t5)sjoC~2j=fd~TT(<14S+j=MD;8kt#o~x!am2WBXYAYe$kJtN%jNvYuC7YC zv}5aA{f8gX${1rTmz(*yGj7}dP_5iwIda^wt*xzx4juA5Z^$|4OsiW)n!dJr^}aN9 z^Fd%MfOBLyS<=)bdg?f$?1=Ux++zPd_x#JGN#8mAaL$;Nn zbUfym(<+rudV706{q)lhKm5=bW2R0$eZ+{mKFgaocUP+^*`4hHRNTd8Pz}xHa@4Ja zVvI5Qd_JGgqi-CBq4V;~Ki;^p9@ScA%sAt8-_M9=_1E{`zb;KVwd|>RX_vkkVpPOHW|*ewu(meYc;Le=TZ|CW{w}qmD4P8#0T7@4Y;ot# zEt$uJt5+|2;)z5`k#2i${lZ(Go;vmVjt*G*l&KScxpa#$EM{{3#+UX_n%u=XW30V> z=5fb8^6IPYh@451UZDez||(J`tyFW zAdG?!FaXdbN~IOgJoA<7t{ZOYwZH%0@4N31=fbA!SOv9%TCG+tS26^ID{#(*Fm>-# zRJ$h@NOc(WMH`jXLHSM=&?oY!s{+J0ceU*WnQPOCt|5F z9FY%%l?updno7?*_3X2U4fd**mN{2n{foQq>c^4o`K3dL4l!edl!CKF8=PDl%~@m8 zB5O%fctpU&yHU9%O!PdjT&)@)8DmlwhYU$}?`~9JNY+S#nxc(ej{e*O4?J-3#YYaJ zK>vF^0G@{;*V`|?xch_?juwJ3K6L1*lTTds`tK@2_~NXyrq_D_0|VX5mp5jl*x(qj zckk_&Uiz#t4pq@>wHgjfLCbL*6h3JY>L18!ubtm0InarQU3lR)*REZ-Ws9=2-@3Um zW;ExFbIy>rb3vJyF@_l<2ls0mxBmU~I8Wl|wdHB2oY@lVUabaZOqo)r2FaE!&+gru zQje@Dx#7Ig%17dfF&rA6z-SQYBbpyD%_K?EY16*@#V>Yb$4U3@-LtD+>n;@Le)F3% zlwz<~yV@+J5?ml9bR5U6r?i4{0?q}E)!AKR1Oti$`2C}uJ9`>ve)P0y!|eA_XTQ;M z;{4Qejw3h0E+(M(8^B#I)i8s~)_$FPcC8@t&)%{KdL8fB5L5YN;Alxhhz3-k3BD!-0W;TCG+| zSZ}%7vv$qaOsst5$mvIoVSM)7Q(Pnf=D>l~D_3UYTusws_79DFg5!fYQ0oaT`%0za zI8LorgFu5DZ@jr)Z8qlPr=Pxe*RDgqzxUoJ`}#80EXG`Z`Mj}X8+oWswI)_d)RB0R zNr6w2*Bc8>Jw>f`rBXo#K)X~Qez;=m*0fRKx%!q{hEmmtl$WL8t*uvFcimLw3?Dx8 zZ~kWSiWUDhYZfzyAKuoOgiQB+{9dh8WpPy-mS~flaMJOeoed9QdWZ@q4)rE?CjW2hS% z#yI0f8#ICwWC^C;fj3&9dxr@rVfM0Rw~iZEx4?AEmgVc#Y4ho))dnt$LU9P^EJ<~$wRVHkzH#Ge)}X5A204d& zihEKsW(KNJ97Qj`^=6d4z2o?4-#hilqeMm`Ha+|7r-+}_sBx{;utClRC<<`Kt_2Z+ z#x!`=fbzUEE%2#UU-;S2UNI(XQ%6ge-u3Rgbpv-!K6%k)mo>&x;yB41IZZUH5Akts zj5bJ7kt)O9Q4>Yb!|rML0_8pA7i{z9A3gTi`}LR+1Sc(6@Zy>^cieQ-%&}t&EiEmF zO`m?j?YA%8uwmJZ8TCxv?BD;;f(5G?V{Ff!UG+f9m>56)8{fWlf^dV+TzdKZ|9t-b z6HYKm9M(=w#5rdyP2YQB`Q{OqU2$4gR@1$o z?kbgDx#`L~26{o`Qt5b~dt&vEjyh^^I@lA;*Bbapl0?u*GwOepN(G<<`j3hrO;aIG?E2pK&R?|X$=$oF zgLWJj` z_OV^V+Y%Gk!Z6V$Hmatbjjz8}8Z5GEb=^}>RZwoSFBUWkKy_Lr|EwRObv5RE&b)a9 zK2h}AgAYCvh8$B7RMStAr04Ft?|=XO`kwQ%W_@qY9N{=lYfFpkxG>B#NnrCNeQk7_ zrcwym-rf$_u?LTnB*7FPDT<~iG1Z-J+xDwp{9@I?g9+ybbWKXhO&nMH`aXRB{oife z_^-F!_N^sLw(i{+arh*kN65ZF%2!dEDQ>=bhiLym#>p%a?tu({%f; z-QKaEJ-nqQCr!Eh(I0khc;=b+DyC2qxrn=|bgKsrj5+VTV;Y%+e*5jkOP0Kk6q1rb z#u)Rw6E3^#bGh7K*bv^^-Mwbu@&!MgK0TM|ueyHy{N>BD(NC%oq4p`Yey68r%FLM~ zvoh+4apOMe?%w75#m*r^IyySyB+(cdF@|xTYRx%ghDjj|GkoI2iL`G3B5c3Cy`9>& zzVBmdHBHlUx!l*+M+3ulxy|k~P(=j;AXN6T=L}UEavcgGnK6#!LOPst&6VLI)?9i% zje!z9qmgU`D%c7QM%bhFc8i~ilr$(t={nWBs5eO!(|kTpc`^;%P$iYP7NU1kD<%j6 zG_?i>21=z;T+ckDQp{woV2n;vt>C%#Z5z9~N#Te_A}GY!{YBy)bP1s8PEQkvW!b;u zn`)$W!h~YXF~aB4X^icKAM24nb07O?ms037wFp=24ZiD+;hR zdsds85B9h<%~;sua+D}C#!S#El`@!6r(SNo6oXSWjm6tsne0PKSu7R{g#r>6Y=h>S zs0duE)kx6De&}8z5-7Y8i`aJ;E0s#ISR}@X5 zDPy!w5~d{MJaaLqlm-GYR_A#hT@-;g*j+PwyvM%jM@2X471PKCVjSI?6GHHM-;J<~ zE|b_dvuKJIIwsKvLD13Bfx00a4%4gP&9qO#u^20vi;i-P#svjqjENJ?r4pR$G*!5>NrOZ*Tt{~bsmV#t5Zv1%b@-4H zecMP;&ciXN+KRwK5KMgxxE&QEDPYhglOPBRg#vOem?6%I^cAxXG}lkQ3%Mjof_f)i z+M=tkRK~#(;8oP*qESIQ8V~{-23QT6s;@^5&bd@7HJS^N7^9?2lZ39vNY7L7wWg7O z45iXV19%y-N4sx~^HA_1|Aja@J3FP6hYlU0P(~x0O*6LCzovRR&A37CX_{h?#P|JN zE(fJnDizeWXv%>!m(S;6>6A!fdw_l#TL-d}i{lQ3Jts=Oi0Tj$Rhk&b8}W9!v|}rS zJjT|F0`_Wcn2|JoLVSa!5J9DBMv)r%ghC{A#BJO^DHICDVsXfjA+Q~cQrpspE7%il zP@&z%BUbOF_P285j z`ZyYxK4Jq!Acz~lMK?sqTR@aU$k8g8$`%&{ox3LY{xD>ZR#$YJE z?^DMHr~s7%i|BSDT}84lgCM1#RFo!#8utT`G8Bu&VzEe8KpLj`Vc1AEp{^91gNR*6 zM+Y#PDh)Ps1)#UJwZY#}*ns)>_4S2eSSS?GfJ0(gC=|5TeSLkfJKSf7Dp?5?`8*&ypU-1&aK11MVGsZ@pc&#lOquXaR!}&kA Wl0_CBaO8IY0000 + + CavEX + Alpha 0.1.0 + 20221110000000 + ByteBit/xtreme8000 + + https://github.com/xtreme8000/CavEX + + diff --git a/source/block/aabb.c b/source/block/aabb.c new file mode 100644 index 0000000..4d74e9e --- /dev/null +++ b/source/block/aabb.c @@ -0,0 +1,72 @@ +#include +#include + +#include "aabb.h" + +void aabb_setsize(struct AABB* a, float sx, float sy, float sz) { + assert(a); + + a->x1 = 0.5F - sx / 2.0F; + a->y1 = 0; + a->z1 = 0.5F - sz / 2.0F; + + a->x2 = 0.5F + sx / 2.0F; + a->y2 = sy; + a->z2 = 0.5F + sz / 2.0F; +} + +void aabb_translate(struct AABB* a, float x, float y, float z) { + assert(a); + + a->x1 += x; + a->y1 += y; + a->z1 += z; + + a->x2 += x; + a->y2 += y; + a->z2 += z; +} + +// see: https://tavianator.com/2011/ray_box.html +bool aabb_intersection_ray(struct AABB* a, struct ray* r, enum side* s) { + assert(a && r); + + float inv_x = 1.0F / r->dx; + float tx1 = (a->x1 - r->x) * inv_x; + float tx2 = (a->x2 - r->x) * inv_x; + + float tmin = fminf(tx1, tx2); + float tmax = fmaxf(tx1, tx2); + + float inv_y = 1.0F / r->dy; + float ty1 = (a->y1 - r->y) * inv_y; + float ty2 = (a->y2 - r->y) * inv_y; + + tmin = fmaxf(tmin, fminf(fminf(ty1, ty2), tmax)); + tmax = fminf(tmax, fmaxf(fmaxf(ty1, ty2), tmin)); + + float inv_z = 1.0F / r->dz; + float tz1 = (a->z1 - r->z) * inv_z; + float tz2 = (a->z2 - r->z) * inv_z; + + tmin = fmaxf(tmin, fminf(fminf(tz1, tz2), tmax)); + tmax = fminf(tmax, fmaxf(fmaxf(tz1, tz2), tmin)); + + // is fine since fmaxf and fminf return the same value as one of the inputs + if(s) { + if(tmin == tx1) + *s = SIDE_LEFT; + else if(tmin == tx2) + *s = SIDE_RIGHT; + else if(tmin == ty1) + *s = SIDE_BOTTOM; + else if(tmin == ty2) + *s = SIDE_TOP; + else if(tmin == tz1) + *s = SIDE_FRONT; + else if(tmin == tz2) + *s = SIDE_BACK; + } + + return tmax > fmax(tmin, 0.0F); +} diff --git a/source/block/aabb.h b/source/block/aabb.h new file mode 100644 index 0000000..e9b7239 --- /dev/null +++ b/source/block/aabb.h @@ -0,0 +1,22 @@ +#ifndef AABB_H +#define AABB_H + +#include + +struct AABB { + float x1, y1, z1; + float x2, y2, z2; +}; + +struct ray { + float x, y, z; + float dx, dy, dz; +}; + +#include "blocks.h" + +void aabb_setsize(struct AABB* a, float sx, float sy, float sz); +void aabb_translate(struct AABB* a, float x, float y, float z); +bool aabb_intersection_ray(struct AABB* a, struct ray* r, enum side* s); + +#endif diff --git a/source/block/block_bed.c b/source/block/block_bed.c new file mode 100644 index 0000000..c0c0e45 --- /dev/null +++ b/source/block/block_bed.c @@ -0,0 +1,80 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 0.5625F, 1.0F); + return true; +} + +// TODO: add missing bed legs to mask? (difficult, many states) +struct face_occlusion side_mask = { + .mask = {0x00000000, 0x00000000, 0x00000000, 0x0000FFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFF0000, 0x00000000}, +}; + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return face_occlusion_empty(); + default: return &side_mask; + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + if(this->block->metadata & 0x8) { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(7, 8); + case SIDE_LEFT: + case SIDE_RIGHT: + return (this->block->metadata & 0x1) ? TEXTURE_INDEX(11, 8) : + TEXTURE_INDEX(10, 8); + case SIDE_FRONT: + case SIDE_BACK: + return (this->block->metadata & 0x1) ? TEXTURE_INDEX(10, 8) : + TEXTURE_INDEX(11, 8); + default: return TEXTURE_INDEX(4, 0); + } + } else { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(6, 8); + case SIDE_LEFT: + case SIDE_RIGHT: + return (this->block->metadata & 0x1) ? TEXTURE_INDEX(8, 8) : + TEXTURE_INDEX(9, 8); + case SIDE_FRONT: + case SIDE_BACK: + return (this->block->metadata & 0x1) ? TEXTURE_INDEX(9, 8) : + TEXTURE_INDEX(8, 8); + default: return TEXTURE_INDEX(4, 0); + } + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_bed = { + .name = "Bed", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_bed, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_bedrock.c b/source/block/block_bedrock.c new file mode 100755 index 0000000..4400c1b --- /dev/null +++ b/source/block/block_bedrock.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(1, 1); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_bedrock = { + .name = "Bedrock", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_bricks.c b/source/block/block_bricks.c new file mode 100644 index 0000000..86eb7e4 --- /dev/null +++ b/source/block/block_bricks.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(7, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_bricks = { + .name = "Bricks", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_brown_mushroom.c b/source/block/block_brown_mushroom.c new file mode 100644 index 0000000..bbb38f9 --- /dev/null +++ b/source/block/block_brown_mushroom.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.375F, 0.375F, 0.375F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(13, 1); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_brown_mushroom = { + .name = "Brown mushroom", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 1, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_cactus.c b/source/block/block_cactus.c new file mode 100644 index 0000000..18ebfa4 --- /dev/null +++ b/source/block/block_cactus.c @@ -0,0 +1,57 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.875F, 1.0F, 0.875F); + return true; +} + +struct face_occlusion side_top_bottom = { + .mask = {0x00007FFE, 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE7FFE, + 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE0000}, +}; + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return &side_top_bottom; + default: return face_occlusion_empty(); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(5, 4); + case SIDE_BOTTOM: return TEXTURE_INDEX(7, 4); + default: return TEXTURE_INDEX(6, 4); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_cactus = { + .name = "Cactus", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cactus, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_cake.c b/source/block/block_cake.c new file mode 100644 index 0000000..9f5231e --- /dev/null +++ b/source/block/block_cake.c @@ -0,0 +1,62 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOL; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + // TODO: AABB hitbox for all states + aabb_setsize(x, 0.875F - 0.125F * this->block->metadata, 0.5F, 0.875F); + aabb_translate(x, 0.0625F * this->block->metadata, 0, 0); + return true; +} + +// TODO: mask not correct for all states +struct face_occlusion bottom_mask = { + .mask = {0x00007FFE, 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE7FFE, + 0x7FFE7FFE, 0x7FFE7FFE, 0x7FFE0000}, +}; + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_BOTTOM: return &bottom_mask; + default: return face_occlusion_empty(); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(9, 7); + case SIDE_BOTTOM: return TEXTURE_INDEX(12, 7); + case SIDE_LEFT: + return (this->block->metadata > 0) ? TEXTURE_INDEX(11, 7) : + TEXTURE_INDEX(10, 7); + default: return TEXTURE_INDEX(10, 7); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_cake = { + .name = "Cake", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cake, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_cast_block.c b/source/block/block_cast_block.c new file mode 100644 index 0000000..2239100 --- /dev/null +++ b/source/block/block_cast_block.c @@ -0,0 +1,104 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex1(struct block_info* this, enum side side) { + return TEXTURE_INDEX(6, 1); +} + +static uint8_t getTextureIndex2(struct block_info* this, enum side side) { + return TEXTURE_INDEX(7, 1); +} + +static uint8_t getTextureIndex3(struct block_info* this, enum side side) { + return TEXTURE_INDEX(8, 1); +} + +static uint8_t getTextureIndex4(struct block_info* this, enum side side) { + return TEXTURE_INDEX(0, 9); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_iron = { + .name = "Block of Iron", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex1, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_gold = { + .name = "Block of Gold", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex2, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_diamond = { + .name = "Diamond Block", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex3, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_lapis = { + .name = "Lapis Block", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex4, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_chest.c b/source/block/block_chest.c new file mode 100644 index 0000000..4424794 --- /dev/null +++ b/source/block/block_chest.c @@ -0,0 +1,126 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + struct block_data right + = world_get_block(this->world, this->x + 1, this->y, this->z); + struct block_data left + = world_get_block(this->world, this->x - 1, this->y, this->z); + struct block_data back + = world_get_block(this->world, this->x, this->y, this->z + 1); + struct block_data front + = world_get_block(this->world, this->x, this->y, this->z - 1); + + if(right.type == this->block->type) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1); + case SIDE_BACK: return TEXTURE_INDEX(9, 2); + case SIDE_FRONT: return TEXTURE_INDEX(10, 3); + default: return TEXTURE_INDEX(10, 1); + } + } + + if(left.type == this->block->type) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1); + case SIDE_BACK: return TEXTURE_INDEX(10, 2); + case SIDE_FRONT: return TEXTURE_INDEX(9, 3); + default: return TEXTURE_INDEX(10, 1); + } + } + + if(back.type == this->block->type) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1); + case SIDE_RIGHT: return TEXTURE_INDEX(10, 2); + case SIDE_LEFT: return TEXTURE_INDEX(9, 3); + default: return TEXTURE_INDEX(10, 1); + } + } + + if(front.type == this->block->type) { + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1); + case SIDE_RIGHT: return TEXTURE_INDEX(9, 2); + case SIDE_LEFT: return TEXTURE_INDEX(10, 3); + default: return TEXTURE_INDEX(10, 1); + } + } + + uint8_t tex[SIDE_MAX] = { + [SIDE_TOP] = TEXTURE_INDEX(9, 1), [SIDE_BOTTOM] = TEXTURE_INDEX(9, 1), + [SIDE_BACK] = TEXTURE_INDEX(10, 1), [SIDE_FRONT] = TEXTURE_INDEX(10, 1), + [SIDE_LEFT] = TEXTURE_INDEX(10, 1), [SIDE_RIGHT] = TEXTURE_INDEX(10, 1), + }; + + if(left.type && !right.type) + tex[SIDE_RIGHT] = TEXTURE_INDEX(11, 1); + else if(right.type && !left.type) + tex[SIDE_LEFT] = TEXTURE_INDEX(11, 1); + else if(front.type && !back.type) + tex[SIDE_BACK] = TEXTURE_INDEX(11, 1); + else if(back.type && !front.type) + tex[SIDE_FRONT] = TEXTURE_INDEX(11, 1); + else + tex[SIDE_BACK] = TEXTURE_INDEX(11, 1); + + return tex[side]; +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_chest = { + .name = "Chest", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_locked_chest = { + .name = "Chest", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 15, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_clay.c b/source/block/block_clay.c new file mode 100644 index 0000000..2b78f8f --- /dev/null +++ b/source/block/block_clay.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_SAND; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(8, 4); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_clay = { + .name = "Clay", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_cobblestone.c b/source/block/block_cobblestone.c new file mode 100755 index 0000000..166b2a0 --- /dev/null +++ b/source/block/block_cobblestone.c @@ -0,0 +1,63 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->type) { + default: return TEXTURE_INDEX(0, 1); + case 48: return TEXTURE_INDEX(4, 2); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_cobblestone = { + .name = "Cobblestone", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_mossstone = { + .name = "Moss Stone", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_crops.c b/source/block/block_crops.c new file mode 100644 index 0000000..a682878 --- /dev/null +++ b/source/block/block_crops.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 0.25F, 1.0F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(this->block->metadata + 6, 5); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_crops = { + .name = "Crops", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_crops, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_dirt.c b/source/block/block_dirt.c new file mode 100644 index 0000000..e5333d2 --- /dev/null +++ b/source/block/block_dirt.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(2, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_dirt = { + .name = "Dirt", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_double_slab.c b/source/block/block_double_slab.c new file mode 100644 index 0000000..4169d84 --- /dev/null +++ b/source/block/block_double_slab.c @@ -0,0 +1,57 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->metadata) { + default: + case 0: + return (side == SIDE_TOP || side == SIDE_BOTTOM) ? + TEXTURE_INDEX(6, 0) : + TEXTURE_INDEX(5, 0); + case 1: + return (side == SIDE_TOP) ? + TEXTURE_INDEX(0, 11) : + ((side == SIDE_BOTTOM) ? TEXTURE_INDEX(0, 13) : + TEXTURE_INDEX(0, 12)); + case 2: return TEXTURE_INDEX(4, 0); + case 3: return TEXTURE_INDEX(0, 1); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_double_slab = { + .name = "Double Slab", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_farmland.c b/source/block/block_farmland.c new file mode 100644 index 0000000..930c9db --- /dev/null +++ b/source/block/block_farmland.c @@ -0,0 +1,53 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 0.9375F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_TOP: return face_occlusion_empty(); + case SIDE_BOTTOM: return face_occlusion_full(); + default: return face_occlusion_rect(15); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: + return (this->block->metadata < 7) ? TEXTURE_INDEX(5, 5) : + TEXTURE_INDEX(4, 5); + default: return TEXTURE_INDEX(2, 0); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_farmland = { + .name = "Farmland", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_farmland, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = true, +}; diff --git a/source/block/block_fire.c b/source/block/block_fire.c new file mode 100644 index 0000000..be85155 --- /dev/null +++ b/source/block/block_fire.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_fire = { + .name = "Fire", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = true, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_flower.c b/source/block/block_flower.c new file mode 100644 index 0000000..55e2b5f --- /dev/null +++ b/source/block/block_flower.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.375F, 0.625F, 0.375F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(13, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_flower = { + .name = "Flower", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_furnace.c b/source/block/block_furnace.c new file mode 100644 index 0000000..5c71a37 --- /dev/null +++ b/source/block/block_furnace.c @@ -0,0 +1,82 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_FRONT: + if(this->block->metadata == 2) + return TEXTURE_INDEX(12, 2); + else + return TEXTURE_INDEX(13, 2); + case SIDE_BACK: + if(this->block->metadata == 3) + return TEXTURE_INDEX(12, 2); + else + return TEXTURE_INDEX(13, 2); + case SIDE_RIGHT: + if(this->block->metadata == 5) + return TEXTURE_INDEX(12, 2); + else + return TEXTURE_INDEX(13, 2); + case SIDE_LEFT: + if(this->block->metadata == 4) + return TEXTURE_INDEX(12, 2); + else + return TEXTURE_INDEX(13, 2); + default: return TEXTURE_INDEX(13, 4); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_furnaceoff = { + .name = "Furnace", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_furnaceon = { + .name = "Furnace", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 13, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_glass.c b/source/block/block_glass.c new file mode 100644 index 0000000..d2afeff --- /dev/null +++ b/source/block/block_glass.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_GLASS; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return (it->block->type == this->block->type) ? face_occlusion_full() : + face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(1, 3); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_glass = { + .name = "Glass", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_glowstone.c b/source/block/block_glowstone.c new file mode 100644 index 0000000..9314ce5 --- /dev/null +++ b/source/block/block_glowstone.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_GLASS; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(9, 6); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_glowstone = { + .name = "Glowstone", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 15, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_grass.c b/source/block/block_grass.c new file mode 100755 index 0000000..a7e3d63 --- /dev/null +++ b/source/block/block_grass.c @@ -0,0 +1,57 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(5, 9); + case SIDE_BOTTOM: return TEXTURE_INDEX(2, 0); + default: + if(world_get_block(this->world, this->x, this->y + 1, this->z).type + == BLOCK_SNOW) { + return TEXTURE_INDEX(4, 4); + } else { + return TEXTURE_INDEX(5, 10); + } + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: return 0x619961; + default: return 0xFFFFFF; + } +} + +struct block block_grass = { + .name = "Grass", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_gravel.c b/source/block/block_gravel.c new file mode 100644 index 0000000..e9e11cd --- /dev/null +++ b/source/block/block_gravel.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 1); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_gravel = { + .name = "Gravel", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_ice.c b/source/block/block_ice.c new file mode 100644 index 0000000..982ee0c --- /dev/null +++ b/source/block/block_ice.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return (it->block->type == this->block->type) ? face_occlusion_full() : + face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 4); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_ice = { + .name = "Ice", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = true, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_ladder.c b/source/block/block_ladder.c new file mode 100644 index 0000000..0e33ba2 --- /dev/null +++ b/source/block/block_ladder.c @@ -0,0 +1,61 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + switch(this->block->metadata) { + case 2: + aabb_setsize(x, 1.0F, 1.0F, 0.125F); + aabb_translate(x, 0, 0, 0.4375F); + return true; + case 3: + aabb_setsize(x, 1.0F, 1.0F, 0.125F); + aabb_translate(x, 0, 0, -0.4375F); + return true; + case 4: + aabb_setsize(x, 0.125F, 1.0F, 1.0F); + aabb_translate(x, 0.4375F, 0, 0); + return true; + case 5: + aabb_setsize(x, 0.125F, 1.0F, 1.0F); + aabb_translate(x, -0.4375F, 0, 0); + return true; + default: return false; + } +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_LADDER; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 5); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_ladder = { + .name = "Ladder", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_ladder, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_lava.c b/source/block/block_lava.c new file mode 100644 index 0000000..5a9d9e3 --- /dev/null +++ b/source/block/block_lava.c @@ -0,0 +1,62 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + int block_height = (this->block->metadata & 0x8) ? + 16 : + (8 - this->block->metadata) * 2 * 7 / 8; + aabb_setsize(x, 1.0F, (float)block_height / 16.0F, 1.0F); + return false; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + int block_height = (this->block->metadata & 0x8) ? + 16 : + (8 - this->block->metadata) * 2 * 7 / 8; + switch(side) { + case SIDE_TOP: + return (it->block->type == this->block->type) ? + face_occlusion_full() : + face_occlusion_empty(); + case SIDE_BOTTOM: return face_occlusion_full(); + default: + return (world_get_block(this->world, this->x, this->y + 1, this->z) + .type + == this->block->type) ? + face_occlusion_full() : + face_occlusion_rect(block_height); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FLUID; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(2, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_lava = { + .name = "Lava", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = true, + .getBaseColor = getBaseColor, + .renderBlock = render_block_fluid, + .luminance = 15, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_leaves.c b/source/block/block_leaves.c new file mode 100644 index 0000000..fbd8ad3 --- /dev/null +++ b/source/block/block_leaves.c @@ -0,0 +1,62 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +struct face_occlusion sides_mask = { + .mask = {0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA, + 0xAAAAAAAA, 0xAAAAAAAA, 0xAAAAAAAA}, +}; + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return (it->block->type == this->block->type) ? + ((side == SIDE_RIGHT || side == SIDE_BACK || side == SIDE_BOTTOM) ? + face_occlusion_full() : + &sides_mask) : + &sides_mask; +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->metadata & 0x3) { + case 1: return TEXTURE_INDEX(4, 8); + case 2: return TEXTURE_INDEX(4, 3); + default: return TEXTURE_INDEX(5, 11); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + switch(this->block->metadata & 0x3) { + case 0: return 0x619961; + case 1: return 0x48B518; + case 2: return 0x80A755; + default: return 0xFFFFFF; + } +} + +struct block block_leaves = { + .name = "Leaves", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_log.c b/source/block/block_log.c new file mode 100644 index 0000000..53c30f0 --- /dev/null +++ b/source/block/block_log.c @@ -0,0 +1,67 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->metadata) { + default: + case 0: + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1); + default: return TEXTURE_INDEX(4, 1); + } + break; + case 1: + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1); + default: return TEXTURE_INDEX(4, 7); + } + break; + case 2: + switch(side) { + case SIDE_TOP: + case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1); + default: return TEXTURE_INDEX(5, 7); + } + break; + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_log = { + .name = "Log", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_obsidian.c b/source/block/block_obsidian.c new file mode 100644 index 0000000..3afea5f --- /dev/null +++ b/source/block/block_obsidian.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(5, 2); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_obsidian = { + .name = "Obsidian", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_ore.c b/source/block/block_ore.c new file mode 100644 index 0000000..1a9ef70 --- /dev/null +++ b/source/block/block_ore.c @@ -0,0 +1,138 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->type) { + case 14: // gold + return TEXTURE_INDEX(0, 2); + case 15: // iron + return TEXTURE_INDEX(1, 2); + case 16: // coal + return TEXTURE_INDEX(2, 2); + case 21: // lapis + return TEXTURE_INDEX(0, 10); + case 56: // diamond + return TEXTURE_INDEX(2, 3); + case 73: // redstone + case 74: return TEXTURE_INDEX(3, 3); + default: return TEXTURE_INDEX(1, 0); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_coalore = { + .name = "Coal ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_ironore = { + .name = "Iron ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_goldore = { + .name = "Gold ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_diamondore = { + .name = "Diamond ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_redstoneore = { + .name = "Redstone ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_lapisore = { + .name = "Lapis lazuli ore", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_planks.c b/source/block/block_planks.c new file mode 100644 index 0000000..f47d3d5 --- /dev/null +++ b/source/block/block_planks.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(4, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_planks = { + .name = "Planks", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_portal.c b/source/block/block_portal.c new file mode 100644 index 0000000..5b0339f --- /dev/null +++ b/source/block/block_portal.c @@ -0,0 +1,43 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + return false; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(0, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_portal = { + .name = "Portal", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = true, + .getBaseColor = getBaseColor, + .renderBlock = render_block_portal, + .luminance = 11, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_pumpkin.c b/source/block/block_pumpkin.c new file mode 100644 index 0000000..f4670a7 --- /dev/null +++ b/source/block/block_pumpkin.c @@ -0,0 +1,82 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_FRONT: + if(this->block->metadata == 2) + return TEXTURE_INDEX(7, 7); + else + return TEXTURE_INDEX(6, 7); + case SIDE_BACK: + if(this->block->metadata == 0) + return TEXTURE_INDEX(7, 7); + else + return TEXTURE_INDEX(6, 7); + case SIDE_RIGHT: + if(this->block->metadata == 3) + return TEXTURE_INDEX(7, 7); + else + return TEXTURE_INDEX(6, 7); + case SIDE_LEFT: + if(this->block->metadata == 1) + return TEXTURE_INDEX(7, 7); + else + return TEXTURE_INDEX(6, 7); + default: return TEXTURE_INDEX(6, 6); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_pumpkin = { + .name = "Pumpkin", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; + +struct block block_pumpkin_lit = { + .name = "Jack o'Lantern", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 15, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_rail.c b/source/block/block_rail.c new file mode 100644 index 0000000..2510e70 --- /dev/null +++ b/source/block/block_rail.c @@ -0,0 +1,94 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, + ((this->block->metadata & 0x7) > 1 + && (this->block->metadata & 0x7) < 6) ? + 0.625F : + 0.125F, + 1.0F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FLAT; +} + +static uint8_t getTextureIndex1(struct block_info* this, enum side side) { + return (this->block->metadata < 6) ? TEXTURE_INDEX(0, 8) : + TEXTURE_INDEX(0, 7); +} + +static uint8_t getTextureIndex2(struct block_info* this, enum side side) { + return (this->block->metadata & 0x8) ? TEXTURE_INDEX(3, 11) : + TEXTURE_INDEX(3, 10); +} + +static uint8_t getTextureIndex3(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 12); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_rail = { + .name = "Rail", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex1, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_rail, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.rail_curved_possible = true, + .ignore_lighting = false, +}; + +struct block block_powered_rail = { + .name = "Powered rail", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex2, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_rail, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.rail_curved_possible = false, + .ignore_lighting = false, +}; + +struct block block_detector_rail = { + .name = "Detector rail", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex3, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_rail, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.rail_curved_possible = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_red_mushroom.c b/source/block/block_red_mushroom.c new file mode 100644 index 0000000..d72dade --- /dev/null +++ b/source/block/block_red_mushroom.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.375F, 0.375F, 0.375F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(12, 1); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_red_mushroom = { + .name = "Red mushroom", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_reed.c b/source/block/block_reed.c new file mode 100644 index 0000000..2a22113 --- /dev/null +++ b/source/block/block_reed.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.75F, 1.0F, 0.75F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(9, 4); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_reed = { + .name = "Reed", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_rose.c b/source/block/block_rose.c new file mode 100644 index 0000000..1b97dff --- /dev/null +++ b/source/block/block_rose.c @@ -0,0 +1,45 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.375F, 0.625F, 0.375F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(12, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_rose = { + .name = "Rose", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_sand.c b/source/block/block_sand.c new file mode 100644 index 0000000..fdd52ef --- /dev/null +++ b/source/block/block_sand.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_SAND; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(2, 1); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_sand = { + .name = "Sand", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_sandstone.c b/source/block/block_sandstone.c new file mode 100644 index 0000000..69e2627 --- /dev/null +++ b/source/block/block_sandstone.c @@ -0,0 +1,48 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_TOP: return TEXTURE_INDEX(0, 11); + case SIDE_BOTTOM: return TEXTURE_INDEX(0, 13); + default: return TEXTURE_INDEX(0, 12); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_sandstone = { + .name = "Sandstone", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_sapling.c b/source/block/block_sapling.c new file mode 100644 index 0000000..ef06ccb --- /dev/null +++ b/source/block/block_sapling.c @@ -0,0 +1,49 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.8125F, 0.8125F, 0.8125F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->metadata) { + case 1: return TEXTURE_INDEX(7, 2); + case 2: return TEXTURE_INDEX(8, 2); + default: return TEXTURE_INDEX(6, 2); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_sapling = { + .name = "Sapling", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_slab.c b/source/block/block_slab.c new file mode 100644 index 0000000..f94c8ae --- /dev/null +++ b/source/block/block_slab.c @@ -0,0 +1,61 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 0.5F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_TOP: return face_occlusion_empty(); + case SIDE_BOTTOM: return face_occlusion_full(); + default: return face_occlusion_rect(8); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_HALF; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(this->block->metadata) { + default: + case 0: + return (side == SIDE_TOP || side == SIDE_BOTTOM) ? + TEXTURE_INDEX(6, 0) : + TEXTURE_INDEX(5, 0); + case 1: + return (side == SIDE_TOP) ? + TEXTURE_INDEX(0, 11) : + ((side == SIDE_BOTTOM) ? TEXTURE_INDEX(0, 13) : + TEXTURE_INDEX(0, 12)); + case 2: return TEXTURE_INDEX(4, 0); + case 3: return TEXTURE_INDEX(0, 1); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_slab = { + .name = "Slab", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_slab, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = true, +}; diff --git a/source/block/block_snow.c b/source/block/block_snow.c new file mode 100644 index 0000000..0094770 --- /dev/null +++ b/source/block/block_snow.c @@ -0,0 +1,48 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOL; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 0.125F * (this->block->metadata + 1), 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + switch(side) { + case SIDE_TOP: return face_occlusion_empty(); + case SIDE_BOTTOM: return face_occlusion_full(); + default: return face_occlusion_rect((this->block->metadata + 1) * 2); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_LAYER; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(2, 4); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_snow = { + .name = "Snow", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_spawner.c b/source/block/block_spawner.c new file mode 100644 index 0000000..7694389 --- /dev/null +++ b/source/block/block_spawner.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(1, 4); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_spawner = { + .name = "Monster Spawner", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_stairs.c b/source/block/block_stairs.c new file mode 100644 index 0000000..89ef0f3 --- /dev/null +++ b/source/block/block_stairs.c @@ -0,0 +1,59 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +/*static struct rectangle getSideMask(struct block_info* this, enum side side, +struct block_info* it) { switch(side) { case SIDE_TOP: return +rectangle_from(0,0,16,8); case SIDE_BOTTOM: return rectangle_full(); case +SIDE_LEFT: return rectangle_from(0,8,16,8); case SIDE_RIGHT: return +rectangle_full(); case SIDE_FRONT: case SIDE_BACK: + { + struct rectangle rect; + rect.length = 2; + rectangle_from2(&rect,0,0,8,16,8); + rectangle_from2(&rect,1,8,0,8,8); + return rect; + } + } +}*/ + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_STAIRS; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(4, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_stairs = { + .name = "Stairs", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = true, +}; diff --git a/source/block/block_stone.c b/source/block/block_stone.c new file mode 100644 index 0000000..a4c9566 --- /dev/null +++ b/source/block/block_stone.c @@ -0,0 +1,44 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(1, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_stone = { + .name = "Stone", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_tallgrass.c b/source/block/block_tallgrass.c new file mode 100644 index 0000000..3dc3e0a --- /dev/null +++ b/source/block/block_tallgrass.c @@ -0,0 +1,70 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_ORGANIC; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.8125F, 0.8125F, 0.8125F); + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex1(struct block_info* this, enum side side) { + switch(this->block->metadata) { + case 1: return TEXTURE_INDEX(5, 12); // tallgrass + case 2: return TEXTURE_INDEX(5, 13); // fern + default: return TEXTURE_INDEX(6, 3); // deadbush + } +} + +static uint8_t getTextureIndex2(struct block_info* this, enum side side) { + return TEXTURE_INDEX(6, 3); // deadbush +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return (this->block->metadata == 0) ? 0xFFFFFF : 0x619961; +} + +struct block block_tallgrass = { + .name = "Tallgrass", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex1, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = true, + .ignore_lighting = false, +}; + +struct block block_deadbush = { + .name = "Deadbush", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex2, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_cross, + .luminance = 0, + .double_sided = true, + .can_see_through = true, + .render_block_data.cross_random_displacement = false, + .ignore_lighting = false, +}; diff --git a/source/block/block_torch.c b/source/block/block_torch.c new file mode 100644 index 0000000..c2ce0de --- /dev/null +++ b/source/block/block_torch.c @@ -0,0 +1,93 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 0.3125F, 0.625F, 0.3125F); + + switch(this->block->metadata) { + case 1: aabb_translate(x, -0.34375F, 0.1875F, 0); break; + case 2: aabb_translate(x, 0.34375F, 0.1875F, 0); break; + case 3: aabb_translate(x, 0, 0.1875F, -0.34375F); break; + case 4: aabb_translate(x, 0, 0.1875F, 0.34375F); break; + default: aabb_setsize(x, 0.2F, 0.6F, 0.2F); break; + } + + return !entity; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_empty(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_CROSS; +} + +static uint8_t getTextureIndex1(struct block_info* this, enum side side) { + return TEXTURE_INDEX(0, 5); +} + +static uint8_t getTextureIndex2(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 7); +} + +static uint8_t getTextureIndex3(struct block_info* this, enum side side) { + return TEXTURE_INDEX(3, 6); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_torch = { + .name = "Torch", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex1, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_torch, + .luminance = 14, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; + +struct block block_redstone_torch = { + .name = "Redstone Torch", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex2, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_torch, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; + +struct block block_redstone_torch_lit = { + .name = "Redstone Torch", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex3, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_torch, + .luminance = 7, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_water.c b/source/block/block_water.c new file mode 100644 index 0000000..1bc6f7b --- /dev/null +++ b/source/block/block_water.c @@ -0,0 +1,57 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_STONE; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + int block_height = (this->block->metadata & 0x8) ? + 16 : + (8 - this->block->metadata) * 2 * 7 / 8; + aabb_setsize(x, 1.0F, (float)block_height / 16.0F, 1.0F); + return false; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + int block_height = (this->block->metadata & 0x8) ? + 16 : + (8 - this->block->metadata) * 2 * 7 / 8; + switch(side) { + case SIDE_TOP: + return (it->block->type == this->block->type) ? + face_occlusion_full() : + face_occlusion_empty(); + case SIDE_BOTTOM: return face_occlusion_full(); + default: return face_occlusion_rect(block_height); + } +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FLUID; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + return TEXTURE_INDEX(1, 0); +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_water = { + .name = "Water", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = true, + .getBaseColor = getBaseColor, + .renderBlock = render_block_fluid, + .luminance = 0, + .double_sided = false, + .can_see_through = true, + .ignore_lighting = false, +}; diff --git a/source/block/block_workbench.c b/source/block/block_workbench.c new file mode 100644 index 0000000..4b7a596 --- /dev/null +++ b/source/block/block_workbench.c @@ -0,0 +1,52 @@ +#include "blocks.h" + +static enum block_material getMaterial(struct block_info* this) { + return MATERIAL_WOOD; +} + +static bool getBoundingBox(struct block_info* this, bool entity, + struct AABB* x) { + aabb_setsize(x, 1.0F, 1.0F, 1.0F); + return true; +} + +static struct face_occlusion* +getSideMask(struct block_info* this, enum side side, struct block_info* it) { + return face_occlusion_full(); +} + +static enum block_render_type getRenderType(struct block_info* this) { + return RENDERTYPE_FULL; +} + +static uint8_t getTextureIndex(struct block_info* this, enum side side) { + switch(side) { + case SIDE_FRONT: + case SIDE_LEFT: return TEXTURE_INDEX(12, 3); + case SIDE_RIGHT: + case SIDE_BACK: return TEXTURE_INDEX(11, 3); + case SIDE_TOP: return TEXTURE_INDEX(11, 2); + default: + case SIDE_BOTTOM: return TEXTURE_INDEX(4, 0); + } +} + +static uint32_t getBaseColor(struct block_info* this, enum side side) { + return 0xFFFFFF; +} + +struct block block_workbench = { + .name = "Workbench", + .getRenderType = getRenderType, + .getSideMask = getSideMask, + .getBoundingBox = getBoundingBox, + .getMaterial = getMaterial, + .getTextureIndex = getTextureIndex, + .transparent = false, + .getBaseColor = getBaseColor, + .renderBlock = render_block_full, + .luminance = 0, + .double_sided = false, + .can_see_through = false, + .ignore_lighting = false, +}; diff --git a/source/block/blocks.c b/source/block/blocks.c new file mode 100755 index 0000000..9621d96 --- /dev/null +++ b/source/block/blocks.c @@ -0,0 +1,182 @@ +#include +#include + +#include "blocks.h" + +struct block* blocks[256]; + +void blocks_init() { + for(int k = 0; k < 256; k++) + blocks[k] = NULL; + + blocks[1] = &block_stone; + blocks[2] = &block_grass; + blocks[3] = &block_dirt; + blocks[4] = &block_cobblestone; + blocks[5] = &block_planks; + blocks[6] = &block_sapling; + blocks[7] = &block_bedrock; + blocks[8] = &block_water; + blocks[9] = &block_water; + blocks[10] = &block_lava; + blocks[11] = &block_lava; + blocks[12] = &block_sand; + blocks[13] = &block_gravel; + blocks[14] = &block_goldore; + blocks[15] = &block_ironore; + blocks[16] = &block_coalore; + blocks[17] = &block_log; + blocks[18] = &block_leaves; + // sponge + blocks[20] = &block_glass; + blocks[21] = &block_lapisore; + blocks[22] = &block_lapis; + // dispenser + blocks[24] = &block_sandstone; + // note block + blocks[26] = &block_bed; + blocks[27] = &block_powered_rail; + blocks[28] = &block_detector_rail; + // sticky piston + // cobweb + blocks[31] = &block_tallgrass; + blocks[32] = &block_deadbush; + // piston + // piston head + // wool + // moving piston head + blocks[37] = &block_flower; + blocks[38] = &block_rose; + blocks[39] = &block_brown_mushroom; + blocks[40] = &block_red_mushroom; + blocks[41] = &block_gold; + blocks[42] = &block_iron; + blocks[43] = &block_double_slab; + blocks[44] = &block_slab; + blocks[45] = &block_bricks; + // tnt + // bookshelf + blocks[48] = &block_mossstone; + blocks[49] = &block_obsidian; + blocks[50] = &block_torch; + // TODO: blocks[51] = &block_fire; + blocks[52] = &block_spawner; + blocks[53] = &block_stairs; + blocks[54] = &block_chest; + // redstone wire + blocks[56] = &block_diamondore; + blocks[57] = &block_diamond; + blocks[58] = &block_workbench; + blocks[59] = &block_crops; + blocks[60] = &block_farmland; + blocks[61] = &block_furnaceoff; + blocks[62] = &block_furnaceon; + // sign standing + // wooden door + blocks[65] = &block_ladder; + blocks[66] = &block_rail; + // cobblestone stairs + // sign wall mounted + // lever + // stone pressure plate + // iron door + // wooden pressure plate + blocks[73] = &block_redstoneore; + blocks[74] = &block_redstoneore; + blocks[75] = &block_redstone_torch; + blocks[76] = &block_redstone_torch_lit; + // button + blocks[78] = &block_snow; + blocks[79] = &block_ice; + // snow block + blocks[81] = &block_cactus; + blocks[82] = &block_clay; + blocks[83] = &block_reed; + // jukebox + // fence + blocks[86] = &block_pumpkin; + // netherrack + // soul sand + blocks[89] = &block_glowstone; + blocks[90] = &block_portal; + blocks[91] = &block_pumpkin_lit; + blocks[92] = &block_cake; + // repeater + // repeater + blocks[95] = &block_locked_chest; + // trap door + + for(int k = 0; k < 256; k++) { + if(blocks[k]) { + assert(blocks[k]->getRenderType); + assert(blocks[k]->getMaterial); + assert(blocks[k]->getTextureIndex); + assert(blocks[k]->getSideMask); + assert(blocks[k]->getBoundingBox); + assert(blocks[k]->getBaseColor); + assert(blocks[k]->renderBlock); + } + } +} + +enum side blocks_side_opposite(enum side s) { + switch(s) { + default: + case SIDE_TOP: return SIDE_BOTTOM; + case SIDE_BOTTOM: return SIDE_TOP; + case SIDE_LEFT: return SIDE_RIGHT; + case SIDE_RIGHT: return SIDE_LEFT; + case SIDE_FRONT: return SIDE_BACK; + case SIDE_BACK: return SIDE_FRONT; + } +} + +const char* block_side_name(enum side s) { + switch(s) { + case SIDE_TOP: return "top"; + case SIDE_BOTTOM: return "bottom"; + case SIDE_LEFT: return "left"; + case SIDE_RIGHT: return "right"; + case SIDE_FRONT: return "front"; + case SIDE_BACK: return "back"; + default: return "invalid"; + } +} + +void blocks_side_offset(enum side s, int* x, int* y, int* z) { + assert(x && y && z); + + switch(s) { + default: + case SIDE_TOP: + *x = 0; + *y = 1; + *z = 0; + break; + case SIDE_BOTTOM: + *x = 0; + *y = -1; + *z = 0; + break; + case SIDE_LEFT: + *x = -1; + *y = 0; + *z = 0; + break; + case SIDE_RIGHT: + *x = 1; + *y = 0; + *z = 0; + break; + case SIDE_BACK: + *x = 0; + *y = 0; + *z = 1; + break; + case SIDE_FRONT: + *x = 0; + *y = 0; + *z = -1; + break; + } +} diff --git a/source/block/blocks.h b/source/block/blocks.h new file mode 100755 index 0000000..92fb97f --- /dev/null +++ b/source/block/blocks.h @@ -0,0 +1,169 @@ +#ifndef BLOCKS_H +#define BLOCKS_H +#include "face_occlusion.h" +#include +#include + +#include "../displaylist.h" +#include "../world.h" + +#define TEXTURE_INDEX(x, y) (((y)*14) + (x)) +#define TEXTURE_X(idx) ((idx) % 14) +#define TEXTURE_Y(idx) ((idx) / 14) + +enum block_material { + MATERIAL_WOOD, + MATERIAL_STONE, + MATERIAL_WOOL, + MATERIAL_ORGANIC, + MATERIAL_SAND, + MATERIAL_GLASS, +}; + +enum side { + SIDE_TOP = 0, + SIDE_BOTTOM = 1, + SIDE_LEFT = 2, + SIDE_RIGHT = 3, + SIDE_FRONT = 4, + SIDE_BACK = 5, + SIDE_MAX +}; + +enum block_render_type { + RENDERTYPE_FULL, + RENDERTYPE_FULL_OVERLAY, + RENDERTYPE_HALF, + RENDERTYPE_STAIRS, + RENDERTYPE_CROSS, + RENDERTYPE_CAKE, + RENDERTYPE_FLAT, + RENDERTYPE_LADDER, + RENDERTYPE_CACTUS, + RENDERTYPE_DOOR, + RENDERTYPE_TRAPDOOR, + RENDERTYPE_FLUID, + RENDERTYPE_LAYER +}; + +enum block_type { + BLOCK_AIR = 0, + BLOCK_STONE = 1, + BLOCK_GRASS = 2, + BLOCK_DIRT = 3, + BLOCK_COBBLESTONE = 4, + BLOCK_WATER_FLOW = 8, + BLOCK_WATER_STILL = 9, + BLOCK_LAVA_FLOW = 10, + BLOCK_LAVA_STILL = 11, + BLOCK_SAND = 12, + BLOCK_GRAVEL = 13, + BLOCK_LOG = 17, + BLOCK_LEAVES = 18, + BLOCK_TALL_GRASS = 31, + BLOCK_MOSSY_COBBLE = 48, + BLOCK_OBSIDIAN = 49, + BLOCK_SNOW = 78, + BLOCK_ICE = 79, + BLOCK_PORTAL = 90, +}; + +#include "aabb.h" + +struct block { + char name[32]; + enum block_render_type (*getRenderType)(struct block_info*); + enum block_material (*getMaterial)(struct block_info*); + uint8_t (*getTextureIndex)(struct block_info*, enum side); + struct face_occlusion* (*getSideMask)(struct block_info*, enum side, + struct block_info*); + bool (*getBoundingBox)(struct block_info*, bool, struct AABB*); + uint32_t (*getBaseColor)(struct block_info*, enum side); + size_t (*renderBlock)(struct displaylist*, struct block_info*, enum side, + struct block_info*, uint8_t*, bool); + bool transparent; + int luminance; + bool double_sided; + bool can_see_through; + bool ignore_lighting; + union { + bool cross_random_displacement; + bool rail_curved_possible; + } render_block_data; +}; + +extern struct block block_bedrock; +extern struct block block_slab; +extern struct block block_dirt; +extern struct block block_log; +extern struct block block_stone; +extern struct block block_leaves; +extern struct block block_grass; +extern struct block block_water; +extern struct block block_lava; +extern struct block block_sand; +extern struct block block_sandstone; +extern struct block block_gravel; +extern struct block block_ice; +extern struct block block_snow; +extern struct block block_tallgrass; +extern struct block block_deadbush; +extern struct block block_flower; +extern struct block block_rose; +extern struct block block_furnaceoff; +extern struct block block_furnaceon; +extern struct block block_workbench; +extern struct block block_glass; +extern struct block block_clay; +extern struct block block_coalore; +extern struct block block_ironore; +extern struct block block_goldore; +extern struct block block_diamondore; +extern struct block block_redstoneore; +extern struct block block_lapisore; +extern struct block block_stairs; +extern struct block block_obsidian; +extern struct block block_spawner; +extern struct block block_cobblestone; +extern struct block block_mossstone; +extern struct block block_chest; +extern struct block block_locked_chest; +extern struct block block_cactus; +extern struct block block_pumpkin; +extern struct block block_pumpkin_lit; +extern struct block block_brown_mushroom; +extern struct block block_red_mushroom; +extern struct block block_reed; +extern struct block block_glowstone; +extern struct block block_torch; +extern struct block block_rail; +extern struct block block_powered_rail; +extern struct block block_detector_rail; +extern struct block block_redstone_torch; +extern struct block block_redstone_torch_lit; +extern struct block block_ladder; +extern struct block block_farmland; +extern struct block block_crops; +extern struct block block_planks; +extern struct block block_portal; +extern struct block block_iron; +extern struct block block_gold; +extern struct block block_diamond; +extern struct block block_lapis; +extern struct block block_cake; +extern struct block block_fire; +extern struct block block_double_slab; +extern struct block block_bed; +extern struct block block_sapling; +extern struct block block_bricks; + +extern struct block* blocks[256]; + +#include "../render_block.h" + +void blocks_init(void); +enum side blocks_side_opposite(enum side s); +void blocks_side_offset(enum side s, int* x, int* y, int* z); +const char* block_side_name(enum side s); + +#endif diff --git a/source/block/face_occlusion.c b/source/block/face_occlusion.c new file mode 100644 index 0000000..8e1c201 --- /dev/null +++ b/source/block/face_occlusion.c @@ -0,0 +1,96 @@ +#include "face_occlusion.h" + +struct face_occlusion face_occlusion_s[] = { + { + .mask = {0, 0, 0, 0, 0, 0, 0, 0}, + }, + { + .mask = {0, 0, 0, 0, 0, 0, 0, 0xFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0, 0, 0, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0, 0, 0xFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask + = {0, 0, 0, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask + = {0, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF}, + }, + { + .mask = {0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, + { + .mask = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + }, +}; + +struct face_occlusion* face_occlusion_full() { + return face_occlusion_rect(16); +} + +struct face_occlusion* face_occlusion_empty() { + return face_occlusion_rect(0); +} + +struct face_occlusion* face_occlusion_rect(int size) { + return face_occlusion_s + size; +} + +bool face_occlusion_test(struct face_occlusion* a, struct face_occlusion* b) { + bool is_empty_a = true; + + for(size_t k = 0; k < FACE_OCCLUSION_ARR_LENGTH; k++) { + if(a->mask[k]) { + is_empty_a = false; + break; + } + } + + if(is_empty_a) + return true; + + for(size_t k = 0; k < FACE_OCCLUSION_ARR_LENGTH; k++) { + if(a->mask[k] != b->mask[k] && (a->mask[k] | b->mask[k]) == a->mask[k]) + return true; + } + + return false; +} diff --git a/source/block/face_occlusion.h b/source/block/face_occlusion.h new file mode 100644 index 0000000..2460dbd --- /dev/null +++ b/source/block/face_occlusion.h @@ -0,0 +1,23 @@ +#ifndef FACE_OCCLUSION_H +#define FACE_OCCLUSION_H + +#include +#include +#include + +#define FACE_OCCLUSION_SIZE (16 * 16) +#define FACE_OCCLUSION_ARR_LENGTH \ + ((FACE_OCCLUSION_SIZE + (sizeof(uint32_t) * 8) - 1) \ + / (sizeof(uint32_t) * 8)) + +struct face_occlusion { + uint32_t mask[FACE_OCCLUSION_ARR_LENGTH]; +}; + +struct face_occlusion* face_occlusion_full(); +struct face_occlusion* face_occlusion_empty(); +struct face_occlusion* face_occlusion_rect(int size); + +bool face_occlusion_test(struct face_occlusion* a, struct face_occlusion* b); + +#endif diff --git a/source/chunk.c b/source/chunk.c new file mode 100644 index 0000000..7591bd5 --- /dev/null +++ b/source/chunk.c @@ -0,0 +1,574 @@ +#include +#include +#include +#include +#include +#include + +#include "block/blocks.h" +#include "chunk.h" +#include "stack.h" + +#define CHUNK_INDEX(x, y, z) ((x) + ((z) + (y)*CHUNK_SIZE) * CHUNK_SIZE) +#define CHUNK_LIGHT_INDEX(x, y, z) \ + ((x) + ((z) + (y) * (CHUNK_SIZE + 2)) * (CHUNK_SIZE + 2)) + +extern void log_num(int x, int offset, bool flip); + +void chunk_init(struct chunk* c, struct world* world, w_coord_t x, w_coord_t y, + w_coord_t z) { + assert(c && world); + + c->blocks = malloc(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 3); + assert(c->blocks); + + memset(c->blocks, BLOCK_AIR, CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * 3); + + c->x = x; + c->y = y; + c->z = z; + + for(int k = 0; k < 13; k++) + c->has_displist[k] = false; + c->rebuild_displist = false; + c->world = world; +} + +void chunk_destroy(struct chunk* c) { + assert(c); + + free(c->blocks); + + for(int k = 0; k < 13; k++) { + if(c->has_displist[k]) + displaylist_destroy(c->mesh + k); + } +} + +struct block_data chunk_get_block(struct chunk* c, c_coord_t x, c_coord_t y, + c_coord_t z) { + assert(c && x < CHUNK_SIZE && y < CHUNK_SIZE && z < CHUNK_SIZE); + + return (struct block_data) { + .type = c->blocks[CHUNK_INDEX(x, y, z) * 3 + 0], + .metadata = c->blocks[CHUNK_INDEX(x, y, z) * 3 + 1], + .sky_light = c->blocks[CHUNK_INDEX(x, y, z) * 3 + 2] & 0xF, + .torch_light = c->blocks[CHUNK_INDEX(x, y, z) * 3 + 2] >> 4, + }; +} + +static struct block_data chunk_lookup_block(struct chunk* c, w_coord_t x, + w_coord_t y, w_coord_t z) { + assert(c); + struct chunk* other = c; + + if(x < c->x || y < c->y || z < c->z || x >= c->x + CHUNK_SIZE + || y >= c->y + CHUNK_SIZE || z >= c->z + CHUNK_SIZE) + other = world_find_chunk(c->world, x, y, z); + + return other ? chunk_get_block(other, x & CHUNK_SIZE_BITS, + y & CHUNK_SIZE_BITS, z & CHUNK_SIZE_BITS) : + (struct block_data) { + .type = (y < WORLD_HEIGHT) ? 1 : 0, + .metadata = 0, + .sky_light = 0, + .torch_light = 0, + }; +} + +void chunk_set_block(struct chunk* c, c_coord_t x, c_coord_t y, c_coord_t z, + struct block_data blk) { + assert(c && x < CHUNK_SIZE && y < CHUNK_SIZE && z < CHUNK_SIZE); + + c->blocks[CHUNK_INDEX(x, y, z) * 3 + 0] = blk.type; + c->blocks[CHUNK_INDEX(x, y, z) * 3 + 1] = blk.metadata; + c->blocks[CHUNK_INDEX(x, y, z) * 3 + 2] + = (blk.torch_light << 4) | blk.sky_light; + c->rebuild_displist = true; + + // TODO: diagonal chunks, just sharing edge or single point + + if(x == 0) { + struct chunk* other = world_find_chunk(c->world, c->x - 1, c->y, c->z); + if(other) + other->rebuild_displist = true; + } + + if(x == CHUNK_SIZE - 1) { + struct chunk* other + = world_find_chunk(c->world, c->x + CHUNK_SIZE, c->y, c->z); + if(other) + other->rebuild_displist = true; + } + + if(y == 0) { + struct chunk* other = world_find_chunk(c->world, c->x, c->y - 1, c->z); + if(other) + other->rebuild_displist = true; + } + + if(y == CHUNK_SIZE - 1) { + struct chunk* other + = world_find_chunk(c->world, c->x, c->y + CHUNK_SIZE, c->z); + if(other) + other->rebuild_displist = true; + } + + if(z == 0) { + struct chunk* other = world_find_chunk(c->world, c->x, c->y, c->z - 1); + if(other) + other->rebuild_displist = true; + } + + if(z == CHUNK_SIZE - 1) { + struct chunk* other + = world_find_chunk(c->world, c->x, c->y, c->z + CHUNK_SIZE); + if(other) + other->rebuild_displist = true; + } +} + +static int chunk_test_side(enum side* on_sides, c_coord_t x, c_coord_t y, + c_coord_t z) { + assert(on_sides); + + int count = 0; + + if(x == 0) + on_sides[count++] = SIDE_LEFT; + + if(x == CHUNK_SIZE - 1) + on_sides[count++] = SIDE_RIGHT; + + if(y == 0) + on_sides[count++] = SIDE_BOTTOM; + + if(y == CHUNK_SIZE - 1) + on_sides[count++] = SIDE_TOP; + + if(z == 0) + on_sides[count++] = SIDE_FRONT; + + if(z == CHUNK_SIZE - 1) + on_sides[count++] = SIDE_BACK; + + return count; +} + +static void chunk_test2(struct chunk* c, struct stack* queue, bool* visited, + uint8_t* reachable, c_coord_t x, c_coord_t y, + c_coord_t z) { + assert(queue && visited && reachable); + + if(visited[CHUNK_INDEX(x, y, z)] + || (blocks[c->blocks[CHUNK_INDEX(x, y, z) * 3 + 0]] + && !blocks[c->blocks[CHUNK_INDEX(x, y, z) * 3 + 0]] + ->can_see_through)) + return; + + stack_clear(queue); + stack_push(queue, (uint8_t[]) {x, y, z}); + visited[CHUNK_INDEX(x, y, z)] = true; + + uint8_t reached_sides = 0; + + while(!stack_empty(queue)) { + uint8_t block[3]; + stack_pop(queue, block); + + enum side on_sides[3]; + size_t on_sides_len + = chunk_test_side(on_sides, block[0], block[1], block[2]); + assert(on_sides_len <= 3); + + for(size_t k = 0; k < on_sides_len; k++) + reached_sides |= (1 << on_sides[k]); + + for(int s = 0; s < 6; s++) { + int nx, ny, nz; + blocks_side_offset(s, &nx, &ny, &nz); + nx += block[0]; + ny += block[1]; + nz += block[2]; + + if(nx >= 0 && ny >= 0 && nz >= 0 && nx < CHUNK_SIZE + && ny < CHUNK_SIZE && nz < CHUNK_SIZE + && !visited[CHUNK_INDEX(nx, ny, nz)] + && (!blocks[c->blocks[CHUNK_INDEX(nx, ny, nz) * 3 + 0]] + || blocks[c->blocks[CHUNK_INDEX(nx, ny, nz) * 3 + 0]] + ->can_see_through)) { + stack_push(queue, (uint8_t[]) {nx, ny, nz}); + visited[CHUNK_INDEX(nx, ny, nz)] = true; + } + } + } + + for(int s = 0; s < 6; s++) { + if(reached_sides & (1 << s)) + reachable[s] |= reached_sides; + } +} + +void chunk_test(struct chunk* c) { + assert(c); + + memset(c->reachable, 0, sizeof(c->reachable)); + + bool* visited = malloc(CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE); + assert(visited); + + memset(visited, false, CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE); + + struct stack queue; + stack_create(&queue, CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE / 4, + sizeof(uint8_t[3])); + + for(int y = 0; y < CHUNK_SIZE; y++) { + for(int x = 0; x < CHUNK_SIZE; x++) { + chunk_test2(c, &queue, visited, c->reachable, x, y, 0); + chunk_test2(c, &queue, visited, c->reachable, x, 0, y); + chunk_test2(c, &queue, visited, c->reachable, 0, x, y); + chunk_test2(c, &queue, visited, c->reachable, x, y, CHUNK_SIZE - 1); + chunk_test2(c, &queue, visited, c->reachable, x, CHUNK_SIZE - 1, y); + chunk_test2(c, &queue, visited, c->reachable, CHUNK_SIZE - 1, x, y); + } + } + + stack_destroy(&queue); + free(visited); +} + +static void chunk_vertex_light(struct chunk* c, uint8_t* light_data) { + assert(c && light_data); + + for(c_coord_t y = 0; y < CHUNK_SIZE + 2; y++) { + for(c_coord_t z = 0; z < CHUNK_SIZE + 2; z++) { + for(c_coord_t x = 0; x < CHUNK_SIZE + 2; x++) { + struct block_data b1[4] = { + chunk_lookup_block(c, c->x + x + 0, c->y + y - 1, + c->z + z + 0), + chunk_lookup_block(c, c->x + x - 1, c->y + y - 1, + c->z + z + 0), + chunk_lookup_block(c, c->x + x + 0, c->y + y - 1, + c->z + z - 1), + chunk_lookup_block(c, c->x + x - 1, c->y + y - 1, + c->z + z - 1), + }; + + struct block_data b2[4] = { + chunk_lookup_block(c, c->x + x - 1, c->y + y + 0, + c->z + z + 0), + chunk_lookup_block(c, c->x + x - 1, c->y + y - 1, + c->z + z + 0), + chunk_lookup_block(c, c->x + x - 1, c->y + y + 0, + c->z + z - 1), + chunk_lookup_block(c, c->x + x - 1, c->y + y - 1, + c->z + z - 1), + }; + + struct block_data b3[4] = { + chunk_lookup_block(c, c->x + x + 0, c->y + y + 0, + c->z + z - 1), + chunk_lookup_block(c, c->x + x - 1, c->y + y + 0, + c->z + z - 1), + chunk_lookup_block(c, c->x + x + 0, c->y + y - 1, + c->z + z - 1), + chunk_lookup_block(c, c->x + x - 1, c->y + y - 1, + c->z + z - 1), + }; + + int shade_table[5] = {0, 1, 3, 5, 0}; + + int sum_sky, sum_torch, count; + + sum_sky = sum_torch = count = 0; + for(int k = 0; k < 4; k++) { + if(!blocks[b1[k].type] + || (blocks[b1[k].type]->can_see_through + && !blocks[b1[k].type]->ignore_lighting)) { + sum_sky += b1[k].sky_light; + sum_torch += b1[k].torch_light; + count++; + } + } + + sum_torch = count > 0 ? (sum_torch + count - 1) / count : 0; + sum_sky = count > 0 ? (sum_sky + count - 1) / count : 0; + sum_torch = MAX(sum_torch - shade_table[4 - count], 0); + sum_sky = MAX(sum_sky - shade_table[4 - count], 0); + + light_data[CHUNK_LIGHT_INDEX(x, y, z) * 3 + 0] + = (sum_torch << 4) | sum_sky; + + sum_sky = sum_torch = count = 0; + for(int k = 0; k < 4; k++) { + if(!blocks[b2[k].type] + || (blocks[b2[k].type]->can_see_through + && !blocks[b2[k].type]->ignore_lighting)) { + sum_sky += b2[k].sky_light; + sum_torch += b2[k].torch_light; + count++; + } + } + + sum_torch = count > 0 ? (sum_torch + count - 1) / count : 0; + sum_sky = count > 0 ? (sum_sky + count - 1) / count : 0; + sum_torch = MAX(sum_torch - shade_table[4 - count], 0); + sum_sky = MAX(sum_sky - shade_table[4 - count], 0); + + light_data[CHUNK_LIGHT_INDEX(x, y, z) * 3 + 1] + = (sum_torch << 4) | sum_sky; + + sum_sky = sum_torch = count = 0; + for(int k = 0; k < 4; k++) { + if(!blocks[b3[k].type] + || (blocks[b3[k].type]->can_see_through + && !blocks[b3[k].type]->ignore_lighting)) { + sum_sky += b3[k].sky_light; + sum_torch += b3[k].torch_light; + count++; + } + } + + sum_torch = count > 0 ? (sum_torch + count - 1) / count : 0; + sum_sky = count > 0 ? (sum_sky + count - 1) / count : 0; + sum_torch = MAX(sum_torch - shade_table[4 - count], 0); + sum_sky = MAX(sum_sky - shade_table[4 - count], 0); + + light_data[CHUNK_LIGHT_INDEX(x, y, z) * 3 + 2] + = (sum_torch << 4) | sum_sky; + } + } + } +} + +static size_t chunk_rebuild(struct chunk* c, struct displaylist* d, + uint8_t* light_data, bool count_only, + bool transparent, enum side side_only, + bool double_sided_only) { + assert(c && d && light_data); + + size_t visible_faces = 0; + + for(c_coord_t y = 0; y < CHUNK_SIZE; y++) { + for(c_coord_t z = 0; z < CHUNK_SIZE; z++) { + for(c_coord_t x = 0; x < CHUNK_SIZE; x++) { + struct block_data local = chunk_get_block(c, x, y, z); + + if(blocks[local.type] + && transparent == blocks[local.type]->transparent + && double_sided_only == blocks[local.type]->double_sided) { + struct block_info local_info = (struct block_info) { + .block = &local, + .world = c->world, + .x = c->x + x, + .y = c->y + y, + .z = c->z + z, + }; + + uint8_t vertex_light[24] = { + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 0) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 0, z + 0) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 0, z + 1) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 1) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 2, z + 0) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 2, z + 0) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 2, z + 1) * 3 + + 0], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 2, z + 1) * 3 + + 0], + + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 0) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 1, z + 0) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 1, z + 1) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 1) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 2, y + 0, z + 0) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 2, y + 1, z + 0) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 2, y + 1, z + 1) * 3 + + 1], + light_data[CHUNK_LIGHT_INDEX(x + 2, y + 0, z + 1) * 3 + + 1], + + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 0) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 0, z + 0) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 1, z + 0) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 1, z + 0) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 0, z + 2) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 0, z + 2) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 1, y + 1, z + 2) * 3 + + 2], + light_data[CHUNK_LIGHT_INDEX(x + 0, y + 1, z + 2) * 3 + + 2], + }; + + for(int k = 0; k < ((side_only == SIDE_MAX) ? 6 : 1); k++) { + enum side s = (side_only == SIDE_MAX) ? (enum side)k : + side_only; + + int ox, oy, oz; + blocks_side_offset(s, &ox, &oy, &oz); + + struct block_data neighbours = chunk_lookup_block( + c, c->x + x + ox, c->y + y + oy, c->z + z + oz); + + struct block_info neighbours_info + = (struct block_info) { + .block = &neighbours, + .world = c->world, + .x = c->x + x + ox, + .y = c->y + y + oy, + .z = c->z + z + oz, + }; + + bool face_visible = true; + + if(blocks[neighbours.type] + && ((!transparent + && !blocks[neighbours.type]->transparent) + || transparent)) { + struct face_occlusion* a + = blocks[local.type]->getSideMask( + &local_info, s, &neighbours_info); + struct face_occlusion* b + = blocks[neighbours.type]->getSideMask( + &neighbours_info, blocks_side_opposite(s), + &local_info); + + face_visible = face_occlusion_test(a, b); + } + + if(face_visible) + visible_faces += blocks[local.type]->renderBlock( + d, &local_info, s, &neighbours_info, + vertex_light, count_only); + } + } + } + } + } + + return visible_faces; +} + +void chunk_check_built(struct chunk* c) { + assert(c); + + if(c->rebuild_displist) { + uint8_t* light_data = malloc((CHUNK_SIZE + 2) * (CHUNK_SIZE + 2) + * (CHUNK_SIZE + 2) * 3); + assert(light_data); + + chunk_vertex_light(c, light_data); + + for(int k = 0; k < 13; k++) { + if(c->has_displist[k]) + displaylist_destroy(c->mesh + k); + + size_t vertices + = chunk_rebuild(c, c->mesh + k, light_data, true, + k >= 6 && k != 12, + (k == 12) ? SIDE_MAX : (k % 6), k == 12) + * 4; + + if(vertices > 0 && vertices <= 0xFFFF * 4) { + displaylist_init(c->mesh + k, vertices, 3 * 2 + 2 * 1 + 1); + + displaylist_begin(c->mesh + k); + GX_Begin(GX_QUADS, GX_VTXFMT0, vertices); + chunk_rebuild(c, c->mesh + k, light_data, false, + k >= 6 && k != 12, (k == 12) ? SIDE_MAX : (k % 6), + k == 12); + GX_End(); + displaylist_end(c->mesh + k); + c->has_displist[k] = true; + } else { + c->has_displist[k] = false; + } + } + + free(light_data); + + chunk_test(c); + + c->rebuild_displist = false; + } +} + +void chunk_pre_render(struct chunk* c, Mtx view) { + assert(c && view); + + Mtx model; + guMtxTrans(model, c->x, c->y, c->z); + guMtxConcat(view, model, c->model_view); +} + +static void check_matrix_set(struct chunk* c, bool* needs_matrix) { + if(*needs_matrix) { + GX_LoadPosMtxImm(c->model_view, GX_PNMTX0); + *needs_matrix = false; + } +} + +void chunk_render(struct chunk* c, bool pass, float x, float y, float z) { + assert(c); + + chunk_check_built(c); + + bool needs_matrix = true; + int offset = pass ? 6 : 0; + + if(y < c->y + CHUNK_SIZE && c->has_displist[SIDE_BOTTOM + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_BOTTOM + offset); + } + + if(y > c->y && c->has_displist[SIDE_TOP + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_TOP + offset); + } + + if(x < c->x + CHUNK_SIZE && c->has_displist[SIDE_LEFT + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_LEFT + offset); + } + + if(x > c->x && c->has_displist[SIDE_RIGHT + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_RIGHT + offset); + } + + if(z < c->z + CHUNK_SIZE && c->has_displist[SIDE_FRONT + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_FRONT + offset); + } + + if(z > c->z && c->has_displist[SIDE_BACK + offset]) { + check_matrix_set(c, &needs_matrix); + displaylist_render(c->mesh + SIDE_BACK + offset); + } + + if(!pass && c->has_displist[12]) { + check_matrix_set(c, &needs_matrix); + GX_SetCullMode(GX_CULL_NONE); + displaylist_render(c->mesh + 12); + GX_SetCullMode(GX_CULL_BACK); + } +} diff --git a/source/chunk.h b/source/chunk.h new file mode 100644 index 0000000..dd0f2f1 --- /dev/null +++ b/source/chunk.h @@ -0,0 +1,52 @@ +#ifndef CHUNK_H +#define CHUNK_H + +#include +#include +#include +#include + +#include "block/blocks.h" +#include "displaylist.h" +#include "intrusive_list.h" +#include "world.h" + +#define CHUNK_SIZE_BITS 0xF +#define CHUNK_SIZE 16 + +#define W2C_COORD(x) ((x)&CHUNK_SIZE_BITS) + +typedef uint32_t c_coord_t; + +struct chunk { + Mtx model_view; + w_coord_t x, y, z; + uint8_t* blocks; + bool has_faces; + struct displaylist mesh[13]; + bool has_displist[13]; + bool rebuild_displist; + struct world* world; + uint8_t reachable[6]; + struct chunk_step { + bool visited; + enum side from; + uint8_t used_exit_sides; + int steps; + } tmp_data; + ILIST_INTERFACE(ilist_chunks, struct chunk); +}; + +void chunk_init(struct chunk* c, struct world* world, w_coord_t x, w_coord_t y, + w_coord_t z); +void chunk_destroy(struct chunk* c); +struct block_data chunk_get_block(struct chunk* c, c_coord_t x, c_coord_t y, + c_coord_t z); +void chunk_set_block(struct chunk* c, c_coord_t x, c_coord_t y, c_coord_t z, + struct block_data blk); +void chunk_check_built(struct chunk* c); +void chunk_render(struct chunk* c, bool pass, float x, float y, float z); +void chunk_pre_render(struct chunk* c, Mtx view); +void chunk_test(struct chunk* c); + +#endif diff --git a/source/displaylist.c b/source/displaylist.c new file mode 100644 index 0000000..5951a82 --- /dev/null +++ b/source/displaylist.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "displaylist.h" + +#define DISPLAYLIST_CLL 32 +#define DISPLAYLIST_CACHE_LINES(v, s) \ + (((v) * (s) + 3 + DISPLAYLIST_CLL - 1) / DISPLAYLIST_CLL * DISPLAYLIST_CLL) + +void displaylist_init(struct displaylist* l, size_t vertices, + size_t vertex_size) { + assert(l && vertices > 0 && vertex_size > 0); + + l->length = DISPLAYLIST_CACHE_LINES(vertices, vertex_size); + l->data = memalign(DISPLAYLIST_CLL, l->length); + DCInvalidateRange(l->data, l->length); +} + +void displaylist_destroy(struct displaylist* l) { + assert(l); + + free(l->data); +} + +void displaylist_begin(struct displaylist* l) { + assert(l); + + GX_BeginDispList(l->data, l->length); +} + +void displaylist_end(struct displaylist* l) { + assert(l); + + // has bug when exact size is given to GX_BeginDispList() (see docs), don't + // check result + GX_EndDispList(); +} + +void displaylist_render(struct displaylist* l) { + assert(l); + + GX_CallDispList(l->data, l->length); +} diff --git a/source/displaylist.h b/source/displaylist.h new file mode 100644 index 0000000..ce7a1c8 --- /dev/null +++ b/source/displaylist.h @@ -0,0 +1,20 @@ +#ifndef DISPLAYLIST_H +#define DISPLAYLIST_H + +#include +#include + +struct displaylist { + void* data; + size_t length; + bool dirty; +}; + +void displaylist_init(struct displaylist* l, size_t vertices, + size_t vertex_size); +void displaylist_destroy(struct displaylist* l); +void displaylist_begin(struct displaylist* l); +void displaylist_end(struct displaylist* l); +void displaylist_render(struct displaylist* l); + +#endif diff --git a/source/render_block.c b/source/render_block.c new file mode 100644 index 0000000..7b0791e --- /dev/null +++ b/source/render_block.c @@ -0,0 +1,736 @@ +#include +#include + +#include "block/blocks.h" +#include "chunk.h" +#include "render_block.h" + +#define BLK_LEN 256 + +#define TEX_OFFSET(x) ((x)*18 + 3) + +static inline uint8_t MAX_LIGHT(uint8_t a, uint8_t b) { + return a > b ? a : b; +} + +static uint8_t level_table_0[16] = { + 0, 0, 0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, +}; + +static uint8_t level_table_1[16] = { + 0, 0, 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, +}; + +static uint8_t level_table_2[16] = { + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +}; + +static inline uint8_t DIM_LIGHT(uint8_t l, uint8_t* table, bool shade_sides, + uint8_t luminance) { + return shade_sides ? + (table[MAX_LIGHT(l >> 4, luminance)] << 4) | table[l & 0x0F] : + (MAX_LIGHT(l >> 4, luminance) << 4) | (l & 0x0F); +} + +static inline void render_block_side_adv(struct displaylist* d, int16_t x, + int16_t y, int16_t z, uint16_t width, + uint16_t height, uint8_t tex_x, + uint8_t tex_y, bool tex_flip_h, + int tex_rotate, bool shade_sides, + enum side side, uint8_t* vertex_light, + uint8_t luminance) { + uint8_t tex_coords[2][4][2] = { + { + {tex_x, tex_y}, + {tex_x + width / 16, tex_y}, + {tex_x + width / 16, tex_y + height / 16}, + {tex_x, tex_y + height / 16}, + }, + { + {tex_x + width / 16, tex_y}, + {tex_x, tex_y}, + {tex_x, tex_y + height / 16}, + {tex_x + width / 16, tex_y + height / 16}, + }, + }; + + switch(side) { + case SIDE_LEFT: { // x minus + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[8], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + GX_Position3s16(x, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[9], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x, y + height, z + width); + GX_Color1x8(DIM_LIGHT(vertex_light[10], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + GX_Position3s16(x, y, z + width); + GX_Color1x8(DIM_LIGHT(vertex_light[11], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + } break; + case SIDE_RIGHT: { // x positive + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[12], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + GX_Position3s16(x, y, z + width); + GX_Color1x8(DIM_LIGHT(vertex_light[15], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + GX_Position3s16(x, y + height, z + width); + GX_Color1x8(DIM_LIGHT(vertex_light[14], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[13], level_table_1, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + } break; + case SIDE_TOP: { // y positive + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[4], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x + width, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[5], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + GX_Position3s16(x + width, y, z + height); + GX_Color1x8(DIM_LIGHT(vertex_light[6], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + GX_Position3s16(x, y, z + height); + GX_Color1x8(DIM_LIGHT(vertex_light[7], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + } break; + case SIDE_BOTTOM: { // y negative + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[0], level_table_0, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + GX_Position3s16(x, y, z + height); + GX_Color1x8(DIM_LIGHT(vertex_light[3], level_table_0, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x + width, y, z + height); + GX_Color1x8(DIM_LIGHT(vertex_light[2], level_table_0, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + GX_Position3s16(x + width, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[1], level_table_0, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + } break; + case SIDE_FRONT: { // z minus + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[16], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + GX_Position3s16(x + width, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[17], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + GX_Position3s16(x + width, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[18], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[19], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + } break; + case SIDE_BACK: { // z positive + GX_Position3s16(x, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[20], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 3) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 3) % 4][1]); + GX_Position3s16(x, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[23], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 0) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 0) % 4][1]); + GX_Position3s16(x + width, y + height, z); + GX_Color1x8(DIM_LIGHT(vertex_light[22], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 1) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 1) % 4][1]); + GX_Position3s16(x + width, y, z); + GX_Color1x8(DIM_LIGHT(vertex_light[21], level_table_2, shade_sides, + luminance)); + GX_TexCoord2u8(tex_coords[tex_flip_h][(tex_rotate + 2) % 4][0], + tex_coords[tex_flip_h][(tex_rotate + 2) % 4][1]); + } break; + default: break; + } +} + +static inline void render_block_side(struct displaylist* d, int16_t x, + int16_t y, int16_t z, int16_t yoffset, + uint16_t height, uint8_t tex, + uint8_t luminance, bool shade_sides, + uint16_t inset, bool tex_flip_h, + int tex_rotate, enum side side, + uint8_t* vertex_light) { + uint8_t tex_x = TEX_OFFSET(TEXTURE_X(tex)); + uint8_t tex_y = TEX_OFFSET(TEXTURE_Y(tex)); + + switch(side) { + case SIDE_LEFT: // x minus + render_block_side_adv( + d, x * BLK_LEN + inset, y * BLK_LEN + yoffset, z * BLK_LEN, + BLK_LEN, height, tex_x, tex_y + (16 - height / 16), tex_flip_h, + tex_rotate, shade_sides, SIDE_LEFT, vertex_light, luminance); + break; + case SIDE_RIGHT: // x positive + render_block_side_adv(d, x * BLK_LEN + BLK_LEN - inset, + y * BLK_LEN + yoffset, z * BLK_LEN, BLK_LEN, + height, tex_x, tex_y + (16 - height / 16), + tex_flip_h, tex_rotate, shade_sides, + SIDE_RIGHT, vertex_light, luminance); + break; + case SIDE_BOTTOM: // y minus + render_block_side_adv(d, x * BLK_LEN, y * BLK_LEN + yoffset + inset, + z * BLK_LEN, BLK_LEN, BLK_LEN, tex_x, tex_y, + tex_flip_h, tex_rotate, shade_sides, + SIDE_BOTTOM, vertex_light, luminance); + break; + case SIDE_TOP: // y positive + render_block_side_adv( + d, x * BLK_LEN, y * BLK_LEN + yoffset + height - inset, + z * BLK_LEN, BLK_LEN, BLK_LEN, tex_x, tex_y, tex_flip_h, + tex_rotate, shade_sides, SIDE_TOP, vertex_light, luminance); + break; + case SIDE_FRONT: // z minus + render_block_side_adv( + d, x * BLK_LEN, y * BLK_LEN + yoffset, z * BLK_LEN + inset, + BLK_LEN, height, tex_x, tex_y + (16 - height / 16), tex_flip_h, + tex_rotate, shade_sides, SIDE_FRONT, vertex_light, luminance); + break; + case SIDE_BACK: // z positive + render_block_side_adv(d, x * BLK_LEN, y * BLK_LEN + yoffset, + z * BLK_LEN + BLK_LEN - inset, BLK_LEN, + height, tex_x, tex_y + (16 - height / 16), + tex_flip_h, tex_rotate, shade_sides, + SIDE_BACK, vertex_light, luminance); + break; + default: break; + } +} + +size_t render_block_cross(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(side != SIDE_TOP) + return 0; + + if(!count_only) { + int16_t x = W2C_COORD(this->x) * BLK_LEN; + int16_t y = W2C_COORD(this->y) * BLK_LEN; + int16_t z = W2C_COORD(this->z) * BLK_LEN; + + if(blocks[this->block->type] + ->render_block_data.cross_random_displacement) { + x += rand() % 129 - 64; + z += rand() % 129 - 64; + } + + uint8_t tex + = blocks[this->block->type]->getTextureIndex(this, SIDE_TOP); + uint8_t tex_x = TEX_OFFSET(TEXTURE_X(tex)); + uint8_t tex_y = TEX_OFFSET(TEXTURE_Y(tex)); + uint8_t light = (MAX_LIGHT(this->block->torch_light, + blocks[this->block->type]->luminance) + << 4) + | this->block->sky_light; + + GX_Position3s16(x, y, z); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x, y + BLK_LEN, z); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x + BLK_LEN, y + BLK_LEN, z + BLK_LEN); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 16, tex_y); + GX_Position3s16(x + BLK_LEN, y, z + BLK_LEN); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + + GX_Position3s16(x + BLK_LEN, y, z); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x + BLK_LEN, y + BLK_LEN, z); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x, y + BLK_LEN, z + BLK_LEN); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 16, tex_y); + GX_Position3s16(x, y, z + BLK_LEN); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + } + + return 2; +} + +size_t render_block_torch(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(side == SIDE_BOTTOM) + return 0; + + if(!count_only) { + int16_t x = W2C_COORD(this->x); + int16_t y = W2C_COORD(this->y); + int16_t z = W2C_COORD(this->z); + uint8_t tex = blocks[this->block->type]->getTextureIndex(this, side); + uint8_t tex_x = TEX_OFFSET(TEXTURE_X(tex)); + uint8_t tex_y = TEX_OFFSET(TEXTURE_Y(tex)); + uint8_t light = (MAX_LIGHT(this->block->torch_light, + blocks[this->block->type]->luminance) + << 4) + | this->block->sky_light; + + int s1x, s1y; // wall offset + int s2x, s2y; // layer shift + int s3 = 48; // y offset + + switch(this->block->metadata) { + case 1: + s1x = -128; + s1y = 0; + s2x = 104; + s2y = 0; + break; + case 2: + s1x = 128; + s1y = 0; + s2x = -104; + s2y = 0; + break; + case 3: + s1x = 0; + s1y = -128; + s2x = 0; + s2y = 104; + break; + case 4: + s1x = 0; + s1y = 128; + s2x = 0; + s2y = -104; + break; + default: s1x = s1y = s2x = s2y = s3 = 0; break; + } + + switch(side) { + case SIDE_LEFT: + GX_Position3s16(x * BLK_LEN + 112 + s1x, y * BLK_LEN + s3, + z * BLK_LEN + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x * BLK_LEN + 112 + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x * BLK_LEN + 112 + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + BLK_LEN + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y); + GX_Position3s16(x * BLK_LEN + 112 + s1x, y * BLK_LEN + s3, + z * BLK_LEN + BLK_LEN + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + break; + case SIDE_RIGHT: + GX_Position3s16(x * BLK_LEN + 144 + s1x, y * BLK_LEN + s3, + z * BLK_LEN + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + GX_Position3s16(x * BLK_LEN + 144 + s1x, y * BLK_LEN + s3, + z * BLK_LEN + BLK_LEN + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x * BLK_LEN + 144 + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + BLK_LEN + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x * BLK_LEN + 144 + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_1, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y); + break; + case SIDE_BACK: + GX_Position3s16(x * BLK_LEN + s1x, y * BLK_LEN + s3, + z * BLK_LEN + 144 + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x * BLK_LEN + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + 144 + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x * BLK_LEN + BLK_LEN + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + 144 + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y); + GX_Position3s16(x * BLK_LEN + BLK_LEN + s1x, y * BLK_LEN + s3, + z * BLK_LEN + 144 + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + break; + case SIDE_FRONT: + GX_Position3s16(x * BLK_LEN + s1x, y * BLK_LEN + s3, + z * BLK_LEN + 112 + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y + 16); + GX_Position3s16(x * BLK_LEN + BLK_LEN + s1x, y * BLK_LEN + s3, + z * BLK_LEN + 112 + s1y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x, tex_y + 16); + GX_Position3s16(x * BLK_LEN + BLK_LEN + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + 112 + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x * BLK_LEN + s1x + s2x, + y * BLK_LEN + BLK_LEN + s3, + z * BLK_LEN + 112 + s1y + s2y); + GX_Color1x8(DIM_LIGHT(light, level_table_2, true, 0)); + GX_TexCoord2u8(tex_x + 16, tex_y); + break; + case SIDE_TOP: + GX_Position3s16(x * BLK_LEN + 112 + s1x + s2x * 10 / 16, + y * BLK_LEN + 160 + s3, + z * BLK_LEN + 112 + s1y + s2y * 10 / 16); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 7, tex_y + 6); + GX_Position3s16(x * BLK_LEN + 144 + s1x + s2x * 10 / 16, + y * BLK_LEN + 160 + s3, + z * BLK_LEN + 112 + s1y + s2y * 10 / 16); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 9, tex_y + 6); + GX_Position3s16(x * BLK_LEN + 144 + s1x + s2x * 10 / 16, + y * BLK_LEN + 160 + s3, + z * BLK_LEN + 144 + s1y + s2y * 10 / 16); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 9, tex_y + 8); + GX_Position3s16(x * BLK_LEN + 112 + s1x + s2x * 10 / 16, + y * BLK_LEN + 160 + s3, + z * BLK_LEN + 144 + s1y + s2y * 10 / 16); + GX_Color1x8(light); + GX_TexCoord2u8(tex_x + 7, tex_y + 8); + break; + default: break; + } + } + + return 1; +} + +size_t render_block_cactus(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + BLK_LEN, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, + (side == SIDE_TOP || side == SIDE_BOTTOM) ? 0 : 16, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_portal(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + // TODO: handle case with neighbour obsidian blocks correctly (low priority) + if(it->block->type == BLOCK_OBSIDIAN || it->block->type == BLOCK_PORTAL + || side == SIDE_TOP || side == SIDE_BOTTOM) + return 0; + + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + BLK_LEN, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 96, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_fluid(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) { + uint16_t height = (this->block->metadata & 0x8) ? + BLK_LEN : + (8 - this->block->metadata) * 14 * 2; + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + height, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 0, false, 0, side, + vertex_light); + } + + return 1; +} + +size_t render_block_rail(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(side != SIDE_TOP) + return 0; + + if(!count_only) { + int16_t x = W2C_COORD(this->x); + int16_t y = W2C_COORD(this->y); + int16_t z = W2C_COORD(this->z); + uint8_t tex = blocks[this->block->type]->getTextureIndex(this, side); + uint8_t luminance = blocks[this->block->type]->luminance; + + uint8_t tex_coords[4][2] = { + {TEX_OFFSET(TEXTURE_X(tex)), TEX_OFFSET(TEXTURE_Y(tex))}, + {TEX_OFFSET(TEXTURE_X(tex)) + 16, TEX_OFFSET(TEXTURE_Y(tex))}, + {TEX_OFFSET(TEXTURE_X(tex)) + 16, TEX_OFFSET(TEXTURE_Y(tex)) + 16}, + {TEX_OFFSET(TEXTURE_X(tex)), TEX_OFFSET(TEXTURE_Y(tex)) + 16}, + }; + int tex_rotate = 0; + + uint16_t a = 16, b = 16, c = 16, d = 16; + + switch(this->block->metadata & 0x7) { + case 1: tex_rotate = 1; break; + case 2: + b = 272; + c = 272; + tex_rotate = 1; + break; + case 3: + a = 272; + d = 272; + tex_rotate = 1; + break; + case 4: + a = 272; + b = 272; + break; + case 5: + c = 272; + d = 272; + break; + } + + if(blocks[this->block->type]->render_block_data.rail_curved_possible) { + switch(this->block->metadata) { + case 6: tex_rotate = 0; break; + case 7: tex_rotate = 3; break; + case 8: tex_rotate = 2; break; + } + } + + GX_Position3s16(x * BLK_LEN, y * BLK_LEN + a, z * BLK_LEN); + GX_Color1x8(DIM_LIGHT(vertex_light[4], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[(tex_rotate + 0) % 4][0], + tex_coords[(tex_rotate + 0) % 4][1]); + GX_Position3s16(x * BLK_LEN + BLK_LEN, y * BLK_LEN + b, z * BLK_LEN); + GX_Color1x8(DIM_LIGHT(vertex_light[5], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[(tex_rotate + 1) % 4][0], + tex_coords[(tex_rotate + 1) % 4][1]); + GX_Position3s16(x * BLK_LEN + BLK_LEN, y * BLK_LEN + c, + z * BLK_LEN + BLK_LEN); + GX_Color1x8(DIM_LIGHT(vertex_light[6], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[(tex_rotate + 2) % 4][0], + tex_coords[(tex_rotate + 2) % 4][1]); + GX_Position3s16(x * BLK_LEN, y * BLK_LEN + d, z * BLK_LEN + BLK_LEN); + GX_Color1x8(DIM_LIGHT(vertex_light[7], NULL, false, luminance)); + GX_TexCoord2u8(tex_coords[(tex_rotate + 3) % 4][0], + tex_coords[(tex_rotate + 3) % 4][1]); + } + + return 1; +} + +size_t render_block_ladder(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if((this->block->metadata == 2 && side != SIDE_FRONT) + || (this->block->metadata == 3 && side != SIDE_BACK) + || (this->block->metadata == 4 && side != SIDE_LEFT) + || (this->block->metadata == 5 && side != SIDE_RIGHT)) + return 0; + + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + BLK_LEN, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 240, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_crops(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(side == SIDE_TOP || side == SIDE_BOTTOM) + return 0; + + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), -16, + BLK_LEN, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, false, 64, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_cake(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) { + uint8_t tex = blocks[this->block->type]->getTextureIndex(this, side); + uint8_t luminance = blocks[this->block->type]->luminance; + + switch(side) { + case SIDE_FRONT: + render_block_side_adv(d, + W2C_COORD(this->x) * BLK_LEN + + this->block->metadata * 32 + 16, + W2C_COORD(this->y) * BLK_LEN, + W2C_COORD(this->z) * BLK_LEN + 16, + (7 - this->block->metadata) * 32, 128, + TEX_OFFSET(TEXTURE_X(tex)) + 1, + TEX_OFFSET(TEXTURE_Y(tex)) + 8, false, 0, + true, side, vertex_light, luminance); + break; + case SIDE_BACK: + render_block_side_adv(d, + W2C_COORD(this->x) * BLK_LEN + + this->block->metadata * 32 + 16, + W2C_COORD(this->y) * BLK_LEN, + W2C_COORD(this->z) * BLK_LEN + 240, + (7 - this->block->metadata) * 32, 128, + TEX_OFFSET(TEXTURE_X(tex)) + 1 + + this->block->metadata * 2, + TEX_OFFSET(TEXTURE_Y(tex)) + 8, false, 0, + true, side, vertex_light, luminance); + break; + case SIDE_TOP: + render_block_side_adv(d, + W2C_COORD(this->x) * BLK_LEN + + this->block->metadata * 32 + 16, + W2C_COORD(this->y) * BLK_LEN + 128, + W2C_COORD(this->z) * BLK_LEN + 16, + (7 - this->block->metadata) * 32, 224, + TEX_OFFSET(TEXTURE_X(tex)) + 1 + + this->block->metadata * 2, + TEX_OFFSET(TEXTURE_Y(tex)) + 1, false, 0, + true, side, vertex_light, luminance); + break; + case SIDE_BOTTOM: + render_block_side_adv(d, + W2C_COORD(this->x) * BLK_LEN + + this->block->metadata * 32 + 16, + W2C_COORD(this->y) * BLK_LEN, + W2C_COORD(this->z) * BLK_LEN + 16, + (7 - this->block->metadata) * 32, 224, + TEX_OFFSET(TEXTURE_X(tex)) + 1 + + this->block->metadata * 2, + TEX_OFFSET(TEXTURE_Y(tex)) + 1, false, 0, + true, side, vertex_light, luminance); + break; + default: + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), + W2C_COORD(this->z), 0, 128, tex, luminance, true, + (side == SIDE_LEFT) ? (16 + this->block->metadata * 32) : + 16, + false, 0, side, vertex_light); + } + } + + return 1; +} + +size_t render_block_farmland(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + 240, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 0, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_bed(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + 144, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, + (side == SIDE_BOTTOM) ? 48 : 0, + (side == SIDE_RIGHT && (this->block->metadata & 0x3) == 0) + || (side == SIDE_BACK && (this->block->metadata & 0x3) == 1) + || (side == SIDE_LEFT && (this->block->metadata & 0x3) == 2) + || (side == SIDE_FRONT && (this->block->metadata & 0x3) == 3), + (side == SIDE_TOP || side == SIDE_BOTTOM) ? + (3 - (this->block->metadata & 0x3)) : + 0, + side, vertex_light); + return 1; +} + +size_t render_block_slab(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + 128, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 0, false, 0, side, + vertex_light); + return 1; +} + +size_t render_block_full(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only) { + if(!count_only) + render_block_side( + d, W2C_COORD(this->x), W2C_COORD(this->y), W2C_COORD(this->z), 0, + BLK_LEN, blocks[this->block->type]->getTextureIndex(this, side), + blocks[this->block->type]->luminance, true, 0, false, 0, side, + vertex_light); + return 1; +} diff --git a/source/render_block.h b/source/render_block.h new file mode 100644 index 0000000..de416f9 --- /dev/null +++ b/source/render_block.h @@ -0,0 +1,63 @@ +#ifndef RENDER_BLOCK_H +#define RENDER_BLOCK_H + +#include +#include + +#include "block/blocks.h" +#include "displaylist.h" +#include "world.h" + +size_t render_block_cross(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_fluid(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_full(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_slab(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_bed(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_farmland(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_crops(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_torch(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_cactus(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_portal(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_rail(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_ladder(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +size_t render_block_cake(struct displaylist* d, struct block_info* this, + enum side side, struct block_info* it, + uint8_t* vertex_light, bool count_only); + +#endif diff --git a/source/stack.c b/source/stack.c new file mode 100755 index 0000000..cc6be03 --- /dev/null +++ b/source/stack.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +#include "stack.h" + +void stack_create(struct stack* stk, size_t inital_size, size_t element_size) { + assert(stk != NULL && inital_size > 0 && element_size > 0); + + stk->element_size = element_size; + stk->index = 0; + stk->length = inital_size; + stk->data = malloc(stk->length * stk->element_size); + assert(stk->data); +} + +void stack_push(struct stack* stk, void* obj) { + assert(stk != NULL && obj != NULL); + + if(stk->index >= stk->length) { + stk->length *= 2; + stk->data = realloc(stk->data, stk->length * stk->element_size); + assert(stk->data); + } + + memcpy((uint8_t*)stk->data + (stk->index++) * stk->element_size, obj, + stk->element_size); +} + +bool stack_empty(struct stack* stk) { + assert(stk != NULL); + + return stk->index == 0; +} + +size_t stack_size(struct stack* stk) { + assert(stk != NULL); + + return stk->index; +} + +void stack_at(struct stack* stk, void* obj, size_t index) { + assert(stk != NULL && obj != NULL); + + if(index < stk->index) + memcpy(obj, (uint8_t*)stk->data + index * stk->element_size, + stk->element_size); +} + +bool stack_pop(struct stack* stk, void* obj) { + assert(stk != NULL && obj != NULL); + + if(stack_empty(stk)) + return false; + + memcpy(obj, (uint8_t*)stk->data + (--stk->index) * stk->element_size, + stk->element_size); + + /*if(stk->index * 4 <= stk->length) { + stk->length /= 2; + stk->data = realloc(stk->data, stk->length * stk->element_size); + assert(stk->data); + }*/ + + return true; +} + +void stack_clear(struct stack* stk) { + assert(stk != NULL); + + stk->index = 0; +} + +void stack_destroy(struct stack* stk) { + assert(stk != NULL); + + if(stk->data) + free(stk->data); +} diff --git a/source/stack.h b/source/stack.h new file mode 100755 index 0000000..42cff04 --- /dev/null +++ b/source/stack.h @@ -0,0 +1,30 @@ +#ifndef STACK_H +#define STACK_H + +#include +#include + +struct stack { + size_t length; + size_t index; + size_t element_size; + void* data; +}; + +void stack_create(struct stack* stk, size_t inital_size, size_t element_size); + +void stack_push(struct stack* stk, void* obj); + +bool stack_empty(struct stack* stk); + +size_t stack_size(struct stack* stk); + +void stack_at(struct stack* stk, void* obj, size_t index); + +bool stack_pop(struct stack* stk, void* obj); + +void stack_clear(struct stack* stk); + +void stack_destroy(struct stack* stk); + +#endif diff --git a/source/triangle.c b/source/triangle.c new file mode 100644 index 0000000..7feaede --- /dev/null +++ b/source/triangle.c @@ -0,0 +1,1094 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "textures.h" +#include "textures_tpl.h" + +#include "block/blocks.h" +#include "chunk.h" +#include "displaylist.h" +#include "stack.h" + +#include "cglm/cglm.h" + +ILIST_DEF(ilist_chunks, struct chunk, M_POD_OPLIST) +DICT_DEF2(dict_chunks, uint64_t, M_BASIC_OPLIST, struct chunk*, M_PTR_OPLIST) + +GXRModeObj* screenMode; +#define FIFO_SIZE (256 * 1024) + +u8 colors[256 * 3] ATTRIBUTE_ALIGN(32); + +char* chunk_files[] = { + "x0 z-10.vc", "x-1 z-2.vc", "x-3 z-5.vc", "x-5 z-8.vc", "x-8 z-11.vc", + "x0 z-11.vc", "x-1 z-3.vc", "x-3 z-6.vc", "x-5 z-9.vc", "x-8 z-1.vc", + "x0 z-1.vc", "x-1 z-4.vc", "x-3 z-7.vc", "x-6 z-10.vc", "x-8 z-2.vc", + "x0 z-2.vc", "x-1 z-5.vc", "x-3 z-8.vc", "x-6 z-11.vc", "x-8 z-3.vc", + "x0 z-3.vc", "x-1 z-6.vc", "x-3 z-9.vc", "x-6 z-1.vc", "x-8 z-4.vc", + "x0 z-4.vc", "x-1 z-7.vc", "x-4 z-10.vc", "x-6 z-2.vc", "x-8 z-5.vc", + "x0 z-5.vc", "x-1 z-8.vc", "x-4 z-11.vc", "x-6 z-3.vc", "x-8 z-6.vc", + "x0 z-6.vc", "x-1 z-9.vc", "x-4 z-1.vc", "x-6 z-4.vc", "x-8 z-7.vc", + "x0 z-7.vc", "x-2 z-10.vc", "x-4 z-2.vc", "x-6 z-5.vc", "x-8 z-8.vc", + "x0 z-8.vc", "x-2 z-11.vc", "x-4 z-3.vc", "x-6 z-6.vc", "x-8 z-9.vc", + "x0 z-9.vc", "x-2 z-1.vc", "x-4 z-4.vc", "x-6 z-7.vc", "x-9 z-10.vc", + "x-10 z-10.vc", "x-2 z-2.vc", "x-4 z-5.vc", "x-6 z-8.vc", "x-9 z-11.vc", + "x-10 z-11.vc", "x-2 z-3.vc", "x-4 z-6.vc", "x-6 z-9.vc", "x-9 z-1.vc", + "x-10 z-1.vc", "x-2 z-4.vc", "x-4 z-7.vc", "x-7 z-10.vc", "x-9 z-2.vc", + "x-10 z-2.vc", "x-2 z-5.vc", "x-4 z-8.vc", "x-7 z-11.vc", "x-9 z-3.vc", + "x-10 z-3.vc", "x-2 z-6.vc", "x-4 z-9.vc", "x-7 z-1.vc", "x-9 z-4.vc", + "x-10 z-4.vc", "x-2 z-7.vc", "x-5 z-10.vc", "x-7 z-2.vc", "x-9 z-5.vc", + "x-10 z-5.vc", "x-2 z-8.vc", "x-5 z-11.vc", "x-7 z-3.vc", "x-9 z-6.vc", + "x-10 z-6.vc", "x-2 z-9.vc", "x-5 z-1.vc", "x-7 z-4.vc", "x-9 z-7.vc", + "x-10 z-7.vc", "x-3 z-10.vc", "x-5 z-2.vc", "x-7 z-5.vc", "x-9 z-8.vc", + "x-10 z-8.vc", "x-3 z-11.vc", "x-5 z-3.vc", "x-7 z-6.vc", "x-9 z-9.vc", + "x-10 z-9.vc", "x-3 z-1.vc", "x-5 z-4.vc", "x-7 z-7.vc", "x-1 z-10.vc", + "x-3 z-2.vc", "x-5 z-5.vc", "x-7 z-8.vc", "x-1 z-11.vc", "x-3 z-3.vc", + "x-5 z-6.vc", "x-7 z-9.vc", "x-1 z-1.vc", "x-3 z-4.vc", "x-5 z-7.vc", + "x-8 z-10.vc", +}; + +dict_chunks_t chunks; +struct chunk chunks_base[sizeof(chunk_files) / sizeof(*chunk_files) * 8]; +struct chunk* chunks_end = chunks_base; +#define CHUNK_TO_ID(x, y, z) \ + ((((int64_t)(z)&0x3FFFFFFF) << 34) | (((int64_t)(x)&0x3FFFFFFF) << 4) \ + | ((int64_t)(y)&0xF)) + +void load_chunk(struct chunk** c, char* file) { + uint8_t* chunk_data = malloc(16 * 16 * 128 * 3); + + int32_t chunk_x, chunk_z; + + FILE* f = fopen(file, "rb"); + assert(f); + fread((uint8_t*)&chunk_x + 3, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_x + 2, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_x + 1, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_x + 0, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_z + 3, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_z + 2, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_z + 1, sizeof(uint8_t), 1, f); + fread((uint8_t*)&chunk_z + 0, sizeof(uint8_t), 1, f); + fread(chunk_data, 1, 16 * 16 * 128 * 3, f); + fclose(f); + + struct world w; + + for(int k = 0; k < 8; k++) { + chunk_init(*c, &w, chunk_x * 16, k * 16, chunk_z * 16); + dict_chunks_set_at(chunks, CHUNK_TO_ID(chunk_x, k, chunk_z), *c); + + for(int y = 0; y < CHUNK_SIZE; y++) { + for(int z = 0; z < CHUNK_SIZE; z++) { + for(int x = 0; x < CHUNK_SIZE; x++) { + uint8_t blockid + = chunk_data[(x + ((y + k * 16) * 16 + z) * 16) * 3 + + 0]; + uint8_t metadata + = chunk_data[(x + ((y + k * 16) * 16 + z) * 16) * 3 + + 1]; + uint8_t light + = chunk_data[(x + ((y + k * 16) * 16 + z) * 16) * 3 + + 2]; + + chunk_set_block(*c, x, y, z, + (struct block_data) { + .type = blockid, + .metadata = metadata, + .sky_light = light & 0xF, + .torch_light = light >> 4, + }); + } + } + } + + (*c)++; + } + + free(chunk_data); +} + +struct chunk* world_find_chunk_neighbour(struct world* w, struct chunk* c, + enum side s) { + assert(w && c); + + int x, y, z; + blocks_side_offset(s, &x, &y, &z); + + if(y + c->y / CHUNK_SIZE < 0 + || y + c->y / CHUNK_SIZE >= WORLD_HEIGHT / CHUNK_SIZE) + return NULL; + + struct chunk** res = dict_chunks_get(chunks, + CHUNK_TO_ID(x + c->x / CHUNK_SIZE, + y + c->y / CHUNK_SIZE, + z + c->z / CHUNK_SIZE)); + + return res ? *res : NULL; +} + +struct chunk* world_find_chunk(struct world* w, w_coord_t x, w_coord_t y, + w_coord_t z) { + assert(w); + + if(y < 0 || y >= WORLD_HEIGHT) + return NULL; + + int cx = x < 0 ? ((x + 1) / CHUNK_SIZE - 1) : x / CHUNK_SIZE; + int cy = y / CHUNK_SIZE; + int cz = z < 0 ? ((z + 1) / CHUNK_SIZE - 1) : z / CHUNK_SIZE; + + struct chunk** res = dict_chunks_get(chunks, CHUNK_TO_ID(cx, cy, cz)); + + return res ? *res : NULL; +} + +void* frameBuffer[3]; + +static void flip_buffers() { + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + GX_CopyDisp(frameBuffer[0], GX_TRUE); + VIDEO_SetNextFramebuffer(frameBuffer[0]); + VIDEO_Flush(); +} + +void draw_dirt_bg() { + GX_Begin(GX_QUADS, GX_VTXFMT2, 4 * 13 * 8); + for(int y = 0; y < 8; y++) { + for(int x = 0; x < 13; x++) { + uint8_t scale = 16 * 4; + + GX_Position3s16(x * scale, y * scale, -9); + GX_Color4u8(0x40, 0x40, 0x40, 0xFF); + GX_TexCoord2u8(39, 3); + GX_Position3s16(x * scale + scale, y * scale, -9); + GX_Color4u8(0x40, 0x40, 0x40, 0xFF); + GX_TexCoord2u8(55, 3); + GX_Position3s16(x * scale + scale, y * scale + scale, -9); + GX_Color4u8(0x40, 0x40, 0x40, 0xFF); + GX_TexCoord2u8(55, 19); + GX_Position3s16(x * scale, y * scale + scale, -9); + GX_Color4u8(0x40, 0x40, 0x40, 0xFF); + GX_TexCoord2u8(39, 19); + } + } + GX_End(); +} + +void setup_drawing(bool bg) { + Mtx44 projection; + Mtx44 identity; + guMtxIdentity(identity); + + guOrtho(projection, 0, 480, 0, 782, 0, 10); + GX_LoadProjectionMtx(projection, GX_ORTHOGRAPHIC); + GX_LoadPosMtxImm(identity, GX_PNMTX0); + + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); + + if(bg) { + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + draw_dirt_bg(); + } + + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR0A0); +} + +uint8_t font_char_width[256] = { + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 1, 4, 5, 5, 5, 5, 2, 4, 4, 4, 5, + 1, 5, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 4, 5, 4, 5, 6, 5, + 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 3, 5, 3, 5, 5, 2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 5, 4, 2, 5, + 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 4, 1, 4, 6, 5, +}; + +void draw_text(int x, int y, char* str, int scale) { + GX_Begin(GX_QUADS, GX_VTXFMT1, strlen(str) * 4 * 2); + + while(*str) { + uint8_t tex_x = *str % 16 * 8; + uint8_t tex_y = *str / 16 * 8; + uint8_t width = (font_char_width[(int)*str] + 1) * scale / 8; + + GX_Position3s16(x + scale / 8, y + scale / 8, -2); + GX_Color4u8(0x80, 0x80, 0x80, 0xFF); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x + scale + scale / 8, y + scale / 8, -2); + GX_Color4u8(0x80, 0x80, 0x80, 0xFF); + GX_TexCoord2u8(tex_x + 8, tex_y); + GX_Position3s16(x + scale + scale / 8, y + scale + scale / 8, -2); + GX_Color4u8(0x80, 0x80, 0x80, 0xFF); + GX_TexCoord2u8(tex_x + 8, tex_y + 8); + GX_Position3s16(x + scale / 8, y + scale + scale / 8, -2); + GX_Color4u8(0x80, 0x80, 0x80, 0xFF); + GX_TexCoord2u8(tex_x, tex_y + 8); + + GX_Position3s16(x, y, -1); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tex_x, tex_y); + GX_Position3s16(x + scale, y, -1); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tex_x + 8, tex_y); + GX_Position3s16(x + scale, y + scale, -1); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tex_x + 8, tex_y + 8); + GX_Position3s16(x, y + scale, -1); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tex_x, tex_y + 8); + + x += width; + str++; + } + + GX_End(); +} + +void draw_textured_quad(int x, int y, int tx, int ty, int sx, int sy, + int scale) { + GX_Begin(GX_QUADS, GX_VTXFMT2, 4); + GX_Position3s16(x, y, -2); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tx, ty); + GX_Position3s16(x + sx * scale, y, -2); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tx + sx, ty); + GX_Position3s16(x + sx * scale, y + sy * scale, -2); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tx + sx, ty + sy); + GX_Position3s16(x, y + sy * scale, -2); + GX_Color4u8(0xFF, 0xFF, 0xFF, 0xFF); + GX_TexCoord2u8(tx, ty + sy); + GX_End(); +} + +static void bfs(struct world* w, ilist_chunks_t render, float x, float y, + float z, vec4* planes) { + for(struct chunk* c = chunks_base; c != chunks_end; c++) { + c->tmp_data.visited = false; + c->tmp_data.steps = 0; + } + + enum side sides[6] + = {SIDE_TOP, SIDE_LEFT, SIDE_BACK, SIDE_BOTTOM, SIDE_RIGHT, SIDE_FRONT}; + + struct chunk* c_camera = world_find_chunk(w, x, y, z); + + ilist_chunks_t queue; + ilist_chunks_init(queue); + + if(!c_camera) + return; + + ilist_chunks_push_back(queue, c_camera); + c_camera->tmp_data.from = SIDE_MAX; + c_camera->tmp_data.used_exit_sides = 0; + c_camera->tmp_data.steps = 0; + c_camera->tmp_data.visited = true; + + while(!ilist_chunks_empty_p(queue)) { + struct chunk* current = ilist_chunks_pop_front(queue); + ilist_chunks_push_back(render, current); + + for(int s = 0; s < 6; s++) { + struct chunk* neigh + = world_find_chunk_neighbour(w, current, sides[s]); + + if(neigh && !neigh->tmp_data.visited && neigh->tmp_data.steps < 6 + && !(current->tmp_data.used_exit_sides & (1 << sides[s])) + && (current->tmp_data.from == SIDE_MAX + || current->reachable[current->tmp_data.from] + & (1 << sides[s])) + && glm_aabb_frustum( + (vec3[2]) {{neigh->x, neigh->y, neigh->z}, + {neigh->x + CHUNK_SIZE, neigh->y + CHUNK_SIZE, + neigh->z + CHUNK_SIZE}}, + planes)) { + ilist_chunks_push_back(queue, neigh); + neigh->tmp_data.from = blocks_side_opposite(sides[s]); + neigh->tmp_data.used_exit_sides + = current->tmp_data.used_exit_sides + | (1 << blocks_side_opposite(sides[s])); + neigh->tmp_data.steps + = current->tmp_data.steps + (neigh->y < 64) ? 1 : 0; + neigh->tmp_data.visited = true; + } + } + } +} + +mqbox_t frame_draw; +mqbox_t frame_empty; + +/*static void* thread_vsync(void* user) { + void* current_frame = NULL; + + while(1) { + mqmsg_t input_frame; + MQ_Receive(frame_draw, &input_frame, MQ_MSG_BLOCK); + + VIDEO_SetNextFramebuffer(input_frame); + VIDEO_Flush(); + + if(current_frame) + MQ_Send(frame_empty, current_frame, MQ_MSG_BLOCK); + + current_frame = input_frame; + + VIDEO_WaitVSync(); + } + + return NULL; +}*/ + +static volatile mqmsg_t current_frame = NULL; + +static void copy_buffers(u32 cnt) { + mqmsg_t input_frame; + + if(MQ_Receive(frame_draw, &input_frame, MQ_MSG_NOBLOCK)) { + VIDEO_SetNextFramebuffer(input_frame); + VIDEO_Flush(); + + if(current_frame) + MQ_Send(frame_empty, current_frame, MQ_MSG_BLOCK); + + current_frame = input_frame; + } +} + +bool is_block_air(struct ray* r, w_coord_t x, w_coord_t y, w_coord_t z, + enum side* s) { + struct world w; + struct block_data blk = world_get_block(&w, x, y, z); + + if(blocks[blk.type]) { + struct AABB bbox; + + if(blocks[blk.type]->getBoundingBox( + &(struct block_info) { + .block = &blk, .world = &w, .x = x, .y = y, .z = z}, + false, &bbox)) { + aabb_translate(&bbox, x, y, z); + return !aabb_intersection_ray(&bbox, r, s); + } else { + return true; + } + } + + return true; +} + +// all vectors normalized +float plane_distance(vec3 n, vec3 p0, vec3 l0, vec3 l) { + float d = glm_vec3_dot(n, l); + + if(d < GLM_FLT_EPSILON) + return FLT_MAX; + + vec3 tmp; + glm_vec3_sub(p0, l0, tmp); + return glm_vec3_dot(tmp, n) / d; +} + +bool camera_pick(float gx0, float gy0, float gz0, float gx1, float gy1, + float gz1, int* bx, int* by, int* bz, enum side* s) { + int sx = gx1 > gx0 ? 1 : -1; + int sy = gy1 > gy0 ? 1 : -1; + int sz = gz1 > gz0 ? 1 : -1; + + int gx = floor(gx0); + int gy = floor(gy0); + int gz = floor(gz0); + + int x1 = floor(gx1); + int y1 = floor(gy1); + int z1 = floor(gz1); + + vec3 dir = {gx1 - gx0, gy1 - gy0, gz1 - gz0}; + glm_vec3_normalize(dir); + + while(1) { + if(!is_block_air(&(struct ray) {.x = gx0, + .y = gy0, + .z = gz0, + .dx = dir[0], + .dy = dir[1], + .dz = dir[2]}, + gx, gy, gz, s)) { + *bx = gx; + *by = gy; + *bz = gz; + return true; + } + + if(gx == x1 && gy == y1 && gz == z1) + return false; + + float t1 = plane_distance((vec3) {sx, 0, 0}, + (vec3) {gx + (sx + 1) / 2, 0, 0}, + (vec3) {gx0, gy0, gz0}, dir); + float t2 = plane_distance((vec3) {0, sy, 0}, + (vec3) {0, gy + (sy + 1) / 2, 0}, + (vec3) {gx0, gy0, gz0}, dir); + float t3 = plane_distance((vec3) {0, 0, sz}, + (vec3) {0, 0, gz + (sz + 1) / 2}, + (vec3) {gx0, gy0, gz0}, dir); + + if(t1 <= t2 && t1 <= t3) { + gx += sx; + } else if(t2 <= t1 && t2 <= t3) { + gy += sy; + } else if(t3 <= t1 && t3 <= t2) { + gz += sz; + } + } +} + +void draw_selection_box(struct AABB* box) { + assert(box); + + int pad = 1; + + GX_Begin(GX_LINES, GX_VTXFMT3, 24); + + // bottom + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + // top + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + // vertical + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + -pad + box->z1 * 256); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(-pad + box->x1 * 256, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(-pad + box->x1 * 256, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_Position3s16(box->x2 * 256 + pad, -pad + box->y1 * 256, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + GX_Position3s16(box->x2 * 256 + pad, box->y2 * 256 + pad, + box->z2 * 256 + pad); + GX_Color4u8(0, 0, 0, 153); + GX_TexCoord2u8(0, 0); + + GX_End(); +} + +int main(void) { + settime((uint64_t)0); + + float light_lookup[16] = { + 0.05F, 0.067F, 0.085F, 0.106F, 0.129F, 0.156F, 0.186F, 0.221F, + 0.261F, 0.309F, 0.367F, 0.437F, 0.525F, 0.638F, 0.789F, 1.0F, + }; + + for(int sky = 0; sky < 16; sky++) { + for(int torch = 0; torch < 16; torch++) { + float gray = fmaxf(light_lookup[torch], light_lookup[sky]) * 255.0F; + colors[(torch * 16 + sky) * 3 + 0] = gray; + colors[(torch * 16 + sky) * 3 + 1] = gray; + colors[(torch * 16 + sky) * 3 + 2] = gray; + } + } + + Mtx44 projection; + GXColor backgroundColor = {0x79, 0xA6, 0xFF, 255}; + void* fifoBuffer = NULL; + + VIDEO_Init(); + WPAD_Init(); + WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); + + screenMode = VIDEO_GetPreferredMode(NULL); + frameBuffer[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(screenMode)); + frameBuffer[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(screenMode)); + frameBuffer[2] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(screenMode)); + + MQ_Init(&frame_draw, 3); + MQ_Init(&frame_empty, 3); + + MQ_Send(frame_empty, frameBuffer[0], MQ_MSG_BLOCK); + MQ_Send(frame_empty, frameBuffer[1], MQ_MSG_BLOCK); + MQ_Send(frame_empty, frameBuffer[2], MQ_MSG_BLOCK); + + if(CONF_GetAspectRatio() == CONF_ASPECT_16_9) { + screenMode->viWidth = 678; + } else { + screenMode->viWidth = 672; + } + + if(VIDEO_GetCurrentTvMode() == VI_PAL) { + // screenMode->viHeight = VI_MAX_HEIGHT_PAL; + screenMode->viXOrigin = (VI_MAX_WIDTH_PAL - screenMode->viWidth) / 2; + screenMode->viYOrigin = (VI_MAX_HEIGHT_PAL - screenMode->viHeight) / 2; + } else { + // screenMode->viHeight = VI_MAX_HEIGHT_NTSC; + screenMode->viXOrigin = (VI_MAX_WIDTH_NTSC - screenMode->viWidth) / 2; + screenMode->viYOrigin = (VI_MAX_HEIGHT_NTSC - screenMode->viHeight) / 2; + } + + s8 hoffset = 0; + CONF_GetDisplayOffsetH(&hoffset); + screenMode->viXOrigin += hoffset; + + VIDEO_Configure(screenMode); + VIDEO_SetNextFramebuffer(frameBuffer[0]); + VIDEO_SetPreRetraceCallback(copy_buffers); + VIDEO_SetBlack(false); + VIDEO_Flush(); + + assert(fatInitDefault()); + + fifoBuffer = MEM_K0_TO_K1(memalign(32, FIFO_SIZE)); + memset(fifoBuffer, 0, FIFO_SIZE); + + GX_Init(fifoBuffer, FIFO_SIZE); + GX_SetCopyClear(backgroundColor, 0x00FFFFFF); + GX_SetViewport(0, 0, screenMode->fbWidth, screenMode->efbHeight, 0, 1); + GX_SetDispCopyYScale( + GX_GetYScaleFactor(screenMode->efbHeight, screenMode->xfbHeight)); + GX_SetScissor(0, 0, screenMode->fbWidth, screenMode->efbHeight); + GX_SetDispCopySrc(0, 0, screenMode->fbWidth, screenMode->efbHeight); + GX_SetDispCopyDst(screenMode->fbWidth, screenMode->xfbHeight); + GX_SetCopyFilter(screenMode->aa, screenMode->sample_pattern, GX_TRUE, + screenMode->vfilter); + GX_SetFieldMode(screenMode->field_rendering, + ((screenMode->viHeight == 2 * screenMode->xfbHeight) ? + GX_ENABLE : + GX_DISABLE)); + + GX_SetCullMode(GX_CULL_BACK); + GX_CopyDisp(frameBuffer[0], GX_TRUE); + GX_SetDispCopyGamma(GX_GM_1_0); + + GX_InvalidateTexAll(); + GX_ClearVtxDesc(); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + + // blocks + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 8); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); + + // font drawing + GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); + GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_U8, 7); + + // gui + GX_SetVtxAttrFmt(GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); + GX_SetVtxAttrFmt(GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT2, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); + + // blocks etc with direct color + GX_SetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_S16, 8); + GX_SetVtxAttrFmt(GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GX_SetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); + + GX_SetArray(GX_VA_CLR0, colors, 3 * sizeof(u8)); + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + + GXTexObj terrain, font, anim, gui2; + TPLFile spriteTPL; + TPL_OpenTPLFromMemory(&spriteTPL, (void*)textures_tpl, textures_tpl_size); + TPL_GetTexture(&spriteTPL, texture_terrain, &terrain); + GX_InitTexObjLOD(&terrain, GX_NEAR, GX_NEAR, 0, 0, 0, GX_DISABLE, + GX_DISABLE, GX_ANISO_1); + GX_LoadTexObj(&terrain, GX_TEXMAP0); + + TPL_GetTexture(&spriteTPL, texture_font, &font); + GX_InitTexObjLOD(&font, GX_NEAR, GX_NEAR, 0, 0, 0, GX_DISABLE, GX_DISABLE, + GX_ANISO_1); + GX_LoadTexObj(&font, GX_TEXMAP1); + + TPL_GetTexture(&spriteTPL, texture_anim, &anim); + GX_InitTexObjLOD(&anim, GX_NEAR, GX_NEAR, 0, 0, 0, GX_DISABLE, GX_DISABLE, + GX_ANISO_1); + GX_LoadTexObj(&anim, GX_TEXMAP2); + + TPL_GetTexture(&spriteTPL, texture_gui2, &gui2); + GX_InitTexObjLOD(&gui2, GX_NEAR, GX_NEAR, 0, 0, 0, GX_DISABLE, GX_DISABLE, + GX_ANISO_1); + GX_LoadTexObj(&gui2, GX_TEXMAP4); + + GX_SetAlphaCompare(GX_GEQUAL, 16, GX_AOP_AND, GX_ALWAYS, 0); + GX_SetZCompLoc(GX_FALSE); + + blocks_init(); + + dict_chunks_init(chunks); + + for(size_t k = 0; k < sizeof(chunk_files) / sizeof(*chunk_files); k++) + load_chunk(&chunks_end, chunk_files[k]); + + flip_buffers(); + + float rotate_x = DegToRad(-26), rotate_y = DegToRad(91); + float center_x = -66.5F, center_y = 72.5F, center_z = -83.5F; + // float center_x = -34.5F, center_y = 77.5F, center_z = -171.5F; + // float center_x = 0, center_y = 72, center_z = 0; + int center_cnt = 0; + float avg_chunk_time = 0.0F; + for(struct chunk* c = chunks_base; c != chunks_end; c++) { + // center_x += c->x + CHUNK_SIZE / 2; + // center_z += c->z + CHUNK_SIZE / 2; + center_cnt++; + uint64_t s = gettime(); + chunk_check_built(c); + uint64_t e = gettime(); + + avg_chunk_time += (float)(e - s) / (float)(1000UL * TB_TIMER_CLOCK); + + setup_drawing(true); + + char str[16]; + sprintf(str, "%i %0.1fms", center_cnt, + avg_chunk_time * 1000.0F / center_cnt); + draw_text(10, 10, str, 16); + GX_DrawDone(); + flip_buffers(); + } + + // center_x /= center_cnt; + // center_z /= center_cnt; + + uint64_t last_frame = gettime(); + + ilist_chunks_t render; + mqmsg_t frame = NULL; + + int frame_counter = 0; + float daytime = 1.0F; + + float speed_x = 0, speed_y = 0, speed_z = 0; + + while(1) { + uint64_t this_frame = gettime(); + float dt = (float)(this_frame - last_frame) + / (float)(1000UL * TB_TIMER_CLOCK); + float fps = 1.0F / dt; + last_frame = this_frame; + + WPAD_ScanPads(); + + expansion_t e; + WPAD_Expansion(WPAD_CHAN_0, &e); + + if(e.type == WPAD_EXP_NUNCHUK && e.nunchuk.js.mag > 0.1F) { + rotate_x -= sin(DegToRad(e.nunchuk.js.ang)) * e.nunchuk.js.mag * dt + * 2.0F; + rotate_y -= cos(DegToRad(e.nunchuk.js.ang)) * e.nunchuk.js.mag * dt + * 2.0F; + } + + u32 held = WPAD_ButtonsHeld(0); + + float acc_x = 0, acc_y = 0, acc_z = 0; + float speed_c = 40.0F; + float air_friction = 0.05F; + + if(held & WPAD_BUTTON_LEFT) { + acc_x += cos(rotate_x) * speed_c; + acc_z -= sin(rotate_x) * speed_c; + } + + if(held & WPAD_BUTTON_RIGHT) { + acc_x -= cos(rotate_x) * speed_c; + acc_z += sin(rotate_x) * speed_c; + } + + if(held & WPAD_BUTTON_UP) { + acc_x += sin(rotate_x) * sin(rotate_y) * speed_c; + acc_y += cos(rotate_y) * speed_c; + acc_z += cos(rotate_x) * sin(rotate_y) * speed_c; + } + + if(held & WPAD_BUTTON_DOWN) { + acc_x -= sin(rotate_x) * sin(rotate_y) * speed_c; + acc_y -= cos(rotate_y) * speed_c; + acc_z -= cos(rotate_x) * sin(rotate_y) * speed_c; + } + + if(held & WPAD_BUTTON_B) { + acc_y += speed_c; + } + + if(held & WPAD_BUTTON_A) { + acc_y -= speed_c; + } + + speed_x += acc_x * dt; + speed_y += acc_y * dt; + speed_z += acc_z * dt; + + speed_x *= powf(air_friction, dt); + speed_y *= powf(air_friction, dt); + speed_z *= powf(air_friction, dt); + + center_x += speed_x * dt; + center_y += speed_y * dt; + center_z += speed_z * dt; + + if(held & WPAD_BUTTON_1) { + daytime = fminf(daytime + 0.1F * dt, 1.0F); + } + + if(held & WPAD_BUTTON_2) { + daytime = fmaxf(daytime - 0.1F * dt, 0.0F); + } + + rotate_y = fminf(M_PI - 0.05F, fmaxf(0.05F, rotate_y)); + + guPerspective(projection, 75.0F, 1.628F, 0.1F, 192.0F); + + Mtx viewMatrix; + guVector camera = {center_x, center_y, center_z}; + guVector up = {0.0F, 1.0F, 0.0F}; + guVector look = {center_x + sin(rotate_x) * sin(rotate_y), + center_y + cos(rotate_y), + center_z + cos(rotate_x) * sin(rotate_y)}; + guLookAt(viewMatrix, &camera, &up, &look); + + mat4 dest, test1, test2; + vec4 planes[6]; + glm_perspective(DegToRad(75.0F), 1.628F, 0.1F, 192.0F, test1); + glm_lookat((vec3) {center_x, center_y, center_z}, + (vec3) {look.x, look.y, look.z}, (vec3) {0, 1, 0}, test2); + glm_mat4_mul(test1, test2, dest); + glm_frustum_planes(dest, planes); + + ilist_chunks_init(render); + + struct world w; + bfs(&w, render, center_x, center_y, center_z, planes); + + for(int sky = 0; sky < 16; sky++) { + for(int torch = 0; torch < 16; torch++) { + uint8_t gray = roundf( + fmaxf(light_lookup[torch], light_lookup[sky] * daytime) + * 255.0F); + colors[(torch * 16 + sky) * 3 + 0] = gray; + colors[(torch * 16 + sky) * 3 + 1] = gray; + colors[(torch * 16 + sky) * 3 + 2] = gray; + } + } + + DCStoreRange(colors, sizeof(colors)); + + ilist_chunks_it_t it; + ilist_chunks_it(it, render); + + while(!ilist_chunks_end_p(it)) { + chunk_pre_render(ilist_chunks_ref(it), viewMatrix); + ilist_chunks_next(it); + } + + if(e.type == WPAD_EXP_NUNCHUK) { + int bx, by, bz; + enum side s; + if(camera_pick(center_x, center_y, center_z, + center_x + sin(rotate_x) * sin(rotate_y) * 16.0F, + center_y + cos(rotate_y) * 16.0F, + center_z + cos(rotate_x) * sin(rotate_y) * 16.0F, + &bx, &by, &bz, &s)) { + if(WPAD_ButtonsDown(0) & WPAD_NUNCHUK_BUTTON_C) { + int x, y, z; + blocks_side_offset(s, &x, &y, &z); + + struct world w; + world_set_block(&w, bx + x, by + y, bz + z, + (struct block_data) { + .type = BLOCK_DIRT, + .metadata = 0, + .sky_light = 0, + .torch_light = 0, + }); + } + + if(WPAD_ButtonsDown(0) & WPAD_NUNCHUK_BUTTON_Z) { + struct world w; + world_set_block(&w, bx, by, bz, + (struct block_data) { + .type = BLOCK_AIR, + .metadata = 0, + .sky_light = 15, + .torch_light = 0, + }); + } + } + } + + uint64_t gpu_wait_start = gettime(); + GX_WaitDrawDone(); + uint64_t gpu_wait_end = gettime(); + + if(frame) + MQ_Send(frame_draw, frame, MQ_MSG_BLOCK); + MQ_Receive(frame_empty, &frame, MQ_MSG_BLOCK); + uint64_t vsync_wait = gettime(); + + GX_InvVtxCache(); + backgroundColor.r = 0x79 * daytime; + backgroundColor.g = 0xA6 * daytime; + backgroundColor.b = 0xFF * daytime; + GX_SetCopyClear(backgroundColor, 0x00FFFFFF); + + GX_LoadProjectionMtx(projection, GX_PERSPECTIVE); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8); + + int chunks_inview = 0; + + ilist_chunks_it(it, render); + + while(!ilist_chunks_end_p(it)) { + chunk_render(ilist_chunks_ref(it), false, center_x, center_y, + center_z); + chunks_inview++; + + ilist_chunks_next(it); + } + + enum side s; + + { + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, + GX_LO_NOOP); + int bx, by, bz; + + if(camera_pick(center_x, center_y, center_z, + center_x + sin(rotate_x) * sin(rotate_y) * 16.0F, + center_y + cos(rotate_y) * 16.0F, + center_z + cos(rotate_x) * sin(rotate_y) * 16.0F, + &bx, &by, &bz, &s)) { + Mtx model, test; + guMtxTrans(model, bx, by, bz); + guMtxConcat(viewMatrix, model, test); + GX_LoadPosMtxImm(test, GX_PNMTX0); + + GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + struct world w; + struct block_data blk = world_get_block(&w, bx, by, bz); + + if(blocks[blk.type]) { + struct AABB bbox; + + if(blocks[blk.type]->getBoundingBox( + &(struct block_info) {.block = &blk, + .world = &w, + .x = bx, + .y = by, + .z = bz}, + false, &bbox)) + draw_selection_box(&bbox); + } + + GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); + } + + GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8); + } + + GX_SetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GX_SetZCompLoc(GX_TRUE); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, + GX_LO_NOOP); + GX_SetColorUpdate(GX_FALSE); + + Mtx anim_mtx; + int anim = (frame_counter / 8) % 24; + guMtxTrans(anim_mtx, (anim / 14) * 0.3515625F, (anim % 14) * 0.0703125F, + 0.0F); + + GX_LoadTexMtxImm(anim_mtx, GX_TEXMTX0, GX_MTX2x4); + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0); + frame_counter++; + + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP2, GX_COLOR0A0); + + for(int pass = 0; pass < 2; pass++) { + if(pass == 1) { + GX_SetColorUpdate(GX_TRUE); + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE); + } + + ilist_chunks_it(it, render); + while(!ilist_chunks_end_p(it)) { + chunk_render(ilist_chunks_ref(it), true, center_x, center_y, + center_z); + ilist_chunks_next(it); + } + } + + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetAlphaCompare(GX_GEQUAL, 16, GX_AOP_AND, GX_ALWAYS, 0); + GX_SetZCompLoc(GX_FALSE); + GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_NOOP); + + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, + GX_LO_NOOP); + + setup_drawing(false); + + char str[64]; + + draw_text(4, 4 + 16 * 0, "CavEX Alpha (impl. MC B1.7.3)", 16); + + float gpu_dt = (float)(gpu_wait_end - gpu_wait_start) + / (float)(1000UL * TB_TIMER_CLOCK); + + float vsync_dt = (float)(vsync_wait - gpu_wait_end) + / (float)(1000UL * TB_TIMER_CLOCK); + + sprintf(str, "%0.1f fps, wait: gpu %0.1fms, vsync %0.1fms", fps, + gpu_dt * 1000.0F, vsync_dt * 1000.0F); + draw_text(4, 4 + 17 * 1, str, 16); + + sprintf(str, "%i chunks", chunks_inview); + draw_text(4, 4 + 17 * 2, str, 16); + + sprintf(str, "(%0.1f, %0.1f, %0.1f)", center_x, center_y, center_z); + draw_text(4, 4 + 17 * 3, str, 16); + + sprintf(str, "daytime: %0.2f", daytime); + draw_text(4, 4 + 17 * 4, str, 16); + + sprintf(str, "side: %s", block_side_name(s)); + draw_text(4, 4 + 17 * 5, str, 16); + + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP4, GX_COLOR0A0); + /*draw_textured_quad((782 - 182 * 2) / 2, 480 - 22 * 2, 0, 0, 182, 22, + 2); draw_textured_quad((782 - 182 * 2) / 2 - 2, 480 - 23 * 2, 208, 0, + 24, 24, 2);*/ + + GX_SetBlendMode(GX_BM_LOGIC, GX_BL_ZERO, GX_BL_ZERO, GX_LO_INV); + draw_textured_quad((782 - 16 * 2) / 2, (480 - 16 * 2) / 2, 0, 229, 16, + 16, 2); + + GX_SetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_NOOP); + + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + GX_CopyDisp(frame, GX_TRUE); + GX_SetDrawDone(); + + if(WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) + exit(0); + } + return 0; +} diff --git a/source/world.c b/source/world.c new file mode 100644 index 0000000..22dbc03 --- /dev/null +++ b/source/world.c @@ -0,0 +1,24 @@ +#include + +#include "chunk.h" +#include "world.h" + +struct block_data world_get_block(struct world* w, w_coord_t x, w_coord_t y, + w_coord_t z) { + assert(w); + struct chunk* c = world_find_chunk(w, x, y, z); + + return c ? chunk_get_block(c, x & CHUNK_SIZE_BITS, y & CHUNK_SIZE_BITS, + z & CHUNK_SIZE_BITS) : + (struct block_data) {.type = (y < WORLD_HEIGHT) ? 1 : 0}; +} + +void world_set_block(struct world* w, w_coord_t x, w_coord_t y, w_coord_t z, + struct block_data blk) { + assert(w); + struct chunk* c = world_find_chunk(w, x, y, z); + + if(c) + chunk_set_block(c, x & CHUNK_SIZE_BITS, y & CHUNK_SIZE_BITS, + z & CHUNK_SIZE_BITS, blk); +} diff --git a/source/world.h b/source/world.h new file mode 100644 index 0000000..6eaafc2 --- /dev/null +++ b/source/world.h @@ -0,0 +1,37 @@ +#ifndef WORLD_H +#define WORLD_H + +#include +#include + +#define WORLD_HEIGHT 128 + +typedef int32_t w_coord_t; + +struct block_data { + uint8_t type; + uint8_t metadata : 4; + uint8_t sky_light : 4; + uint8_t torch_light : 4; +}; + +struct block_info { + struct block_data* block; + struct world* world; + w_coord_t x, y, z; +}; + +struct world { + int test; +}; + +void world_init(struct world* w, size_t chunks); +void world_destroy(struct world* w); +struct chunk* world_find_chunk(struct world* w, w_coord_t x, w_coord_t y, + w_coord_t z); +struct block_data world_get_block(struct world* w, w_coord_t x, w_coord_t y, + w_coord_t z); +void world_set_block(struct world* w, w_coord_t x, w_coord_t y, w_coord_t z, + struct block_data blk); + +#endif