From c5697e42a76142c339806e1c0bc7ed15e3ace548 Mon Sep 17 00:00:00 2001 From: vimene Date: Sun, 19 Nov 2023 23:25:06 +0100 Subject: started switching to autotools --- src/Makefile.am | 2 + src/Makefile.in | 617 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/chfb.cpp | 152 +++++++++++++ src/chfb.h | 28 +++ src/config.h | 88 ++++++++ src/config.h.in | 87 ++++++++ src/main.cpp | 508 ++++++++++++++++++++++++++++++++++++++++++ src/math_vector.cpp | 173 +++++++++++++++ src/math_vector.h | 69 ++++++ src/obj3d.cpp | 46 ++++ src/obj3d.h | 42 ++++ src/pixfb.cpp | 153 +++++++++++++ src/pixfb.h | 29 +++ src/stamp-h1 | 1 + src/tri_vertex.cpp | 314 ++++++++++++++++++++++++++ src/tri_vertex.h | 29 +++ src/vertex.cpp | 16 ++ src/vertex.h | 25 +++ src/vertex_data.cpp | 12 + src/vertex_data.h | 12 + 20 files changed, 2403 insertions(+) create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/chfb.cpp create mode 100644 src/chfb.h create mode 100644 src/config.h create mode 100644 src/config.h.in create mode 100644 src/main.cpp create mode 100644 src/math_vector.cpp create mode 100644 src/math_vector.h create mode 100644 src/obj3d.cpp create mode 100644 src/obj3d.h create mode 100644 src/pixfb.cpp create mode 100644 src/pixfb.h create mode 100644 src/stamp-h1 create mode 100644 src/tri_vertex.cpp create mode 100644 src/tri_vertex.h create mode 100644 src/vertex.cpp create mode 100644 src/vertex.h create mode 100644 src/vertex_data.cpp create mode 100644 src/vertex_data.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..99ac33d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,2 @@ +bin_PROGRAMS = main +main_SOURCES = main.cpp math_vector.cpp chfb.cpp pixfb.cpp obj3d.cpp vertex_data.cpp vertex.cpp tri_vertex.cpp diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..c364a1f --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,617 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = main$(EXEEXT) +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_main_OBJECTS = main.$(OBJEXT) math_vector.$(OBJEXT) chfb.$(OBJEXT) \ + pixfb.$(OBJEXT) obj3d.$(OBJEXT) vertex_data.$(OBJEXT) \ + vertex.$(OBJEXT) tri_vertex.$(OBJEXT) +main_OBJECTS = $(am_main_OBJECTS) +main_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/chfb.Po ./$(DEPDIR)/main.Po \ + ./$(DEPDIR)/math_vector.Po ./$(DEPDIR)/obj3d.Po \ + ./$(DEPDIR)/pixfb.Po ./$(DEPDIR)/tri_vertex.Po \ + ./$(DEPDIR)/vertex.Po ./$(DEPDIR)/vertex_data.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(main_SOURCES) +DIST_SOURCES = $(main_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +main_SOURCES = main.cpp math_vector.cpp chfb.cpp pixfb.cpp obj3d.cpp vertex_data.cpp vertex.cpp tri_vertex.cpp +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status src/config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +main$(EXEEXT): $(main_OBJECTS) $(main_DEPENDENCIES) $(EXTRA_main_DEPENDENCIES) + @rm -f main$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(main_OBJECTS) $(main_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chfb.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/math_vector.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obj3d.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pixfb.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tri_vertex.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vertex.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vertex_data.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) config.h +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/chfb.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/math_vector.Po + -rm -f ./$(DEPDIR)/obj3d.Po + -rm -f ./$(DEPDIR)/pixfb.Po + -rm -f ./$(DEPDIR)/tri_vertex.Po + -rm -f ./$(DEPDIR)/vertex.Po + -rm -f ./$(DEPDIR)/vertex_data.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/chfb.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/math_vector.Po + -rm -f ./$(DEPDIR)/obj3d.Po + -rm -f ./$(DEPDIR)/pixfb.Po + -rm -f ./$(DEPDIR)/tri_vertex.Po + -rm -f ./$(DEPDIR)/vertex.Po + -rm -f ./$(DEPDIR)/vertex_data.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: all install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/chfb.cpp b/src/chfb.cpp new file mode 100644 index 0000000..249fb16 --- /dev/null +++ b/src/chfb.cpp @@ -0,0 +1,152 @@ +#include "chfb.h" +#include +#include +#include +#include "math_vector.h" +#include "vertex.h" +#include "tri_vertex.h" +#include "vertex_data.h" + +CharacterFrameBuffer::CharacterFrameBuffer(unsigned int w, unsigned int h) { + resize(w, h); +} + +void CharacterFrameBuffer::resize(unsigned int w, unsigned int h) { + this->w = w; + this->h = h; + chars_vector.resize(w * h); + depth_buf.resize(w * h); + clear(); +} + +unsigned int CharacterFrameBuffer::width() const { + return w; +} + +unsigned int CharacterFrameBuffer::height() const { + return h; +} + +const char* CharacterFrameBuffer::chars() const { + return chars_vector.data(); +} + +void CharacterFrameBuffer::clear() { + std::fill(chars_vector.begin(), chars_vector.end(), ' '); + std::fill(depth_buf.begin(), depth_buf.end(), 1.f); + face_ind = -1; +} + +void CharacterFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { + std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; + +#define SWAP_IF_LT(X,Y) ({\ + if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ + Vertex3* temp = sorted_vs[X];\ + sorted_vs[X] = sorted_vs[Y];\ + sorted_vs[Y] = temp;\ + }\ + }) + SWAP_IF_LT(1, 0); + SWAP_IF_LT(2, 1); + SWAP_IF_LT(1, 0); +#undef SWAP_IF_LT + + Vertex3 middle_vl = *sorted_vs[1]; + float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); + Vertex3 middle_vr{ + { + sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), + sorted_vs[1]->point.y, + sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) + }, + VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) + }; + if (middle_vr.point.x < middle_vl.point.x) { + Vertex3 temp = middle_vr; + middle_vr = middle_vl; + middle_vl = temp; + } + + // top triangle + { + if (sorted_vs[0]->point.y != sorted_vs[1]->point.y) { + int top_y = static_cast(std::floor(sorted_vs[0]->point.y + 1.f)); + int bottom_y = static_cast(std::ceil(sorted_vs[1]->point.y - 1.f)); + for (int y = top_y; y <= bottom_y; y++) { + float iy = static_cast(y); + float s = (iy - sorted_vs[0]->point.y) / (sorted_vs[1]->point.y - sorted_vs[0]->point.y); + float xl = sorted_vs[0]->point.x + s * (middle_vl.point.x - sorted_vs[0]->point.x); + float xr = sorted_vs[0]->point.x + s * (middle_vr.point.x - sorted_vs[0]->point.x); + int left_x = static_cast(std::ceil(xl)); + int right_x = static_cast(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast(x); + float t = (ix - xl) / (xr - xl); + // depth and vd don't take into account perspective + float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + chars_vector[x + y * w] = face_char(); + } + } + } + } + } + + // bottom triangle + { + if (sorted_vs[1]->point.y != sorted_vs[2]->point.y) { + int bottom_y = static_cast(std::floor(sorted_vs[2]->point.y)); + int top_y = static_cast(std::ceil(sorted_vs[1]->point.y)); + for (int y = top_y; y <= bottom_y; y++) { + float iy = static_cast(y); + float s = (iy - sorted_vs[2]->point.y) / (sorted_vs[1]->point.y - sorted_vs[2]->point.y); + float xl = sorted_vs[2]->point.x + s * (middle_vl.point.x - sorted_vs[2]->point.x); + float xr = sorted_vs[2]->point.x + s * (middle_vr.point.x - sorted_vs[2]->point.x); + int left_x = static_cast(std::ceil(xl)); + int right_x = static_cast(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast(x); + float t = (ix - xl) / (xr - xl); + // depth and vd don't take into account perspective + float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + chars_vector[x + y * w] = face_char(); + } + } + } + } + } +} + +void CharacterFrameBuffer::draw_triangle(TriangleVertex4 triangle) { + face_ind++; + for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { + for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { + MathVector2 pp1 = t2.vertex1.point.xy(), + pp2 = t2.vertex2.point.xy(), + pp3 = t2.vertex3.point.xy(); + if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; + t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + float fw = static_cast(w), fh = static_cast(h); + t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; + t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; + t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; + t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; + t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; + t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; + _draw_cropped_triangle(t2); + } + } +} + +char CharacterFrameBuffer::face_char() const { + int n = 1 + face_ind / 2; + return (n < 10 ? '0' : 'A' - 10) + n; +} diff --git a/src/chfb.h b/src/chfb.h new file mode 100644 index 0000000..66fd79c --- /dev/null +++ b/src/chfb.h @@ -0,0 +1,28 @@ +#ifndef CHFB_H +#define CHFB_H + +#include +#include "math_vector.h" +#include "tri_vertex.h" + +class CharacterFrameBuffer { + public: + CharacterFrameBuffer(unsigned int w, unsigned int h); + void resize(unsigned int w, unsigned int h); + unsigned int width() const; + unsigned int height() const; + const char* chars() const; + void clear(); + void draw_triangle(TriangleVertex4 triangle); + + private: + unsigned int w, h; + std::vector chars_vector; + std::vector depth_buf; + int face_ind; + + void _draw_cropped_triangle(TriangleVertex3 triangle); + char face_char() const; +}; + +#endif // CHFB_H diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..c56505a --- /dev/null +++ b/src/config.h @@ -0,0 +1,88 @@ +/* src/config.h. Generated from config.h.in by configure. */ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Enable ncurses */ +#define ENABLE_NCURSES 0 + +/* Define to 1 if you have the `floor' function. */ +/* #undef HAVE_FLOOR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `SDL2' library (-lSDL2). */ +#define HAVE_LIBSDL2 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +#define PACKAGE "engine" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "vincent.menegaux@gmail.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "engine" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "engine alpha" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "engine" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "alpha" + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "alpha" + +/* Linux OS */ +#define VIMENE_LINUX 0 + +/* OS */ +#define VIMENE_OS VIMENE_LINUX + +/* Windows OS */ +#define VIMENE_WINDOWS 1 + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..4e60460 --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,87 @@ +/* src/config.h.in. Generated from configure.ac by autoheader. */ + +/* Enable ncurses */ +#undef ENABLE_NCURSES + +/* Define to 1 if you have the `floor' function. */ +#undef HAVE_FLOOR + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `SDL2' library (-lSDL2). */ +#undef HAVE_LIBSDL2 + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Linux OS */ +#undef VIMENE_LINUX + +/* OS */ +#undef VIMENE_OS + +/* Windows OS */ +#undef VIMENE_WINDOWS + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..c246491 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,508 @@ +#include "config.h" +#include + +//#include + +#if VIMENE_OS==VIMENE_WINDOWS +#include +#endif + +#include +#include +#include +#include +#include "chfb.h" +#include "pixfb.h" +#include "obj3d.h" +#include "math_vector.h" +#include "vertex.h" +#include "vertex_data.h" +#include "tri_vertex.h" + +#define MKEY_Z 122 +#define MKEY_Q 113 +#define MKEY_S 115 +#define MKEY_D 100 + +#define MKEY_ESC 27 + +#define FPS 60 + +#define PI 3.1415926535f + +#if ENABLE_NCURSES==1 +void main_term() { + // init + setlocale(LC_ALL, ""); + initscr(); + cbreak(); + noecho(); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + set_escdelay(0); + curs_set(0); + + int w, h; + getmaxyx(stdscr, h, w); + CharacterFrameBuffer cfb{static_cast(w), static_cast(h)}; + + MathVector3 a{0.f, 0.f, 0.f}; + float dist = 4.f; + while (1) { + //timeout(1000 / FPS); + timeout(10); + int c = getch(); + + if (c == MKEY_ESC) break; + switch (c) { + case KEY_UP: + // a.x += 0.1f; + dist += .1f; + break; + case KEY_DOWN: + // a.x -= 0.1f; + dist -= .1f; + break; + case KEY_LEFT: + // a.y += 0.1f; + break; + case KEY_RIGHT: + // a.y -= 0.1f; + break; + case MKEY_Q: + // a.z += 0.1f; + break; + case MKEY_D: + // a.z -= 0.1f; + break; + } + + a.x += .0050f; + a.y += .0065f; + a.z += .0080f; + + getmaxyx(stdscr, h, w); + cfb.resize(static_cast(w), static_cast(h)); + + float rad = 5.f; + MathVector3 ca{std::cos(a.x), std::cos(a.y), std::cos(a.z)}; + MathVector3 sa{std::sin(a.x), std::sin(a.y), std::sin(a.z)}; + + std::array rot_x = {{ + { 1.f, 0.f, 0.f }, + { 0.f, ca.x, sa.x }, + { 0.f, -sa.x, ca.x }, + }}; + std::array rot_y = {{ + { ca.y, 0.f, -sa.y }, + { 0.f, 1.f, 0.f }, + { sa.y, 0.f, ca.y }, + }}; + std::array rot_z = {{ + { ca.z, sa.z, 0.f }, + { -sa.z, ca.z, 0.f }, + { 0.f, 0.f, 1.f }, + }}; + + auto [e_x, e_y, e_z] = rot_x; + e_x = e_x.x * rot_y[0] + e_x.y * rot_y[1] + e_x.z * rot_y[2]; + e_y = e_y.x * rot_y[0] + e_y.y * rot_y[1] + e_y.z * rot_y[2]; + e_z = e_z.x * rot_y[0] + e_z.y * rot_y[1] + e_z.z * rot_y[2]; + e_x = e_x.x * rot_z[0] + e_x.y * rot_z[1] + e_x.z * rot_z[2]; + e_y = e_y.x * rot_z[0] + e_y.y * rot_z[1] + e_y.z * rot_z[2]; + e_z = e_z.x * rot_z[0] + e_z.y * rot_z[1] + e_z.z * rot_z[2]; + + std::array objs{{ + { + { + { + rad * (-e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + } + }, + { + // face 1 + { 0, 2, 3 }, + { 0, 3, 1 }, + + // face 2 + { 0, 4, 6 }, + { 0, 6, 2 }, + + // face 3 + { 0, 1, 5 }, + { 0, 5, 4 }, + + // face 4 + { 7, 6, 4 }, + { 7, 4, 5 }, + + // face 5 + { 7, 3, 2 }, + { 7, 2, 6 }, + + // face 6 + { 7, 5, 1 }, + { 7, 1, 3 }, + } + }, + { + { + { + rad * (-e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + } + }, + { + // face 1 + { 0, 2, 3 }, + { 0, 3, 1 }, + + // face 2 + { 0, 4, 6 }, + { 0, 6, 2 }, + + // face 3 + { 0, 1, 5 }, + { 0, 5, 4 }, + + // face 4 + { 7, 6, 4 }, + { 7, 4, 5 }, + + // face 5 + { 7, 3, 2 }, + { 7, 2, 6 }, + + // face 6 + { 7, 5, 1 }, + { 7, 1, 3 }, + } + } + }}; + cfb.clear(); + float min_z = 2.f, max_z = 50.f; + float fac_for_aspect_ratio = 2.f * static_cast(cfb.height()) / static_cast(cfb.width()); + for (auto obj : objs) { + for (auto triangle : obj) { + TriangleVertex4 t{triangle}; + + // should be multiplied by a matrix, temporary replacement + t.vertex1.point.x *= fac_for_aspect_ratio; + t.vertex1.point.y = -t.vertex1.point.y; + t.vertex1.point.w = -t.vertex1.point.z; + t.vertex1.point.z = 2.f * (-t.vertex1.point.z - min_z) / (max_z - min_z) - 1.f; + t.vertex2.point.x *= fac_for_aspect_ratio; + t.vertex2.point.y = -t.vertex2.point.y; + t.vertex2.point.w = -t.vertex2.point.z; + t.vertex2.point.z = 2.f * (-t.vertex2.point.z - min_z) / (max_z - min_z) - 1.f; + t.vertex3.point.x *= fac_for_aspect_ratio; + t.vertex3.point.y = -t.vertex3.point.y; + t.vertex3.point.w = -t.vertex3.point.z; + t.vertex3.point.z = 2.f * (-t.vertex3.point.z - min_z) / (max_z - min_z) - 1.f; + + cfb.draw_triangle(t); + } + } + mvaddnstr(0, 0, cfb.chars(), cfb.width() * cfb.height()); + } + + // terminate + endwin(); +} +#endif + +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +void main_SDL() { + SDL_Window* window = NULL; + SDL_Renderer* renderer = NULL; + SDL_Texture* texture = NULL; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Error: SDL_Init error: %s\n", SDL_GetError()); + return; + } + window = SDL_CreateWindow("Engine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + if (window == NULL) { + fprintf(stderr, "Error: SDL_CreateWindow error: %s\n", SDL_GetError()); + return; + } + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT); + PixelFrameBuffer pfb{SCREEN_WIDTH, SCREEN_HEIGHT}; + + MathVector3 a{0.f, 0.f, 0.f}; + float dist = 4.f; + SDL_Event e; + bool quit = false; + while (!quit) { + a.x += .0050f; + a.y += .0065f; + a.z += .0080f; + + float rad = 5.f; + MathVector3 ca{std::cos(a.x), std::cos(a.y), std::cos(a.z)}; + MathVector3 sa{std::sin(a.x), std::sin(a.y), std::sin(a.z)}; + + std::array rot_x = {{ + { 1.f, 0.f, 0.f }, + { 0.f, ca.x, sa.x }, + { 0.f, -sa.x, ca.x }, + }}; + std::array rot_y = {{ + { ca.y, 0.f, -sa.y }, + { 0.f, 1.f, 0.f }, + { sa.y, 0.f, ca.y }, + }}; + std::array rot_z = {{ + { ca.z, sa.z, 0.f }, + { -sa.z, ca.z, 0.f }, + { 0.f, 0.f, 1.f }, + }}; + + auto [e_x, e_y, e_z] = rot_x; + e_x = e_x.x * rot_y[0] + e_x.y * rot_y[1] + e_x.z * rot_y[2]; + e_y = e_y.x * rot_y[0] + e_y.y * rot_y[1] + e_y.z * rot_y[2]; + e_z = e_z.x * rot_y[0] + e_z.y * rot_y[1] + e_z.z * rot_y[2]; + e_x = e_x.x * rot_z[0] + e_x.y * rot_z[1] + e_x.z * rot_z[2]; + e_y = e_y.x * rot_z[0] + e_y.y * rot_z[1] + e_y.z * rot_z[2]; + e_z = e_z.x * rot_z[0] + e_z.y * rot_z[1] + e_z.z * rot_z[2]; + + std::array objs{{ + { + { + { + rad * (-e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + -e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + +e_z - .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + } + }, + { + // face 1 + { 0, 2, 3 }, + { 0, 3, 1 }, + + // face 2 + { 0, 4, 6 }, + { 0, 6, 2 }, + + // face 3 + { 0, 1, 5 }, + { 0, 5, 4 }, + + // face 4 + { 7, 6, 4 }, + { 7, 4, 5 }, + + // face 5 + { 7, 3, 2 }, + { 7, 2, 6 }, + + // face 6 + { 7, 5, 1 }, + { 7, 1, 3 }, + } + }, + { + { + { + rad * (-e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + -e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + -e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (-e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + }, + { + rad * (+e_x + +e_y + +e_z + .5f * (e_x + e_y + e_z)) - dist * rad * MathVector3{0.f, 0.f, 1.f}, + {} + } + }, + { + // face 1 + { 0, 2, 3 }, + { 0, 3, 1 }, + + // face 2 + { 0, 4, 6 }, + { 0, 6, 2 }, + + // face 3 + { 0, 1, 5 }, + { 0, 5, 4 }, + + // face 4 + { 7, 6, 4 }, + { 7, 4, 5 }, + + // face 5 + { 7, 3, 2 }, + { 7, 2, 6 }, + + // face 6 + { 7, 5, 1 }, + { 7, 1, 3 }, + } + } + }}; + pfb.clear(); + float min_z = 2.f, max_z = 50.f; + float fac_for_aspect_ratio = 2.f * static_cast(pfb.height()) / static_cast(pfb.width()); + for (auto obj : objs) { + for (auto triangle : obj) { + TriangleVertex4 t{triangle}; + + // should be multiplied by a matrix, temporary replacement + t.vertex1.point.x *= fac_for_aspect_ratio; + t.vertex1.point.y = -t.vertex1.point.y; + t.vertex1.point.w = -t.vertex1.point.z; + t.vertex1.point.z = 2.f * (-t.vertex1.point.z - min_z) / (max_z - min_z) - 1.f; + t.vertex2.point.x *= fac_for_aspect_ratio; + t.vertex2.point.y = -t.vertex2.point.y; + t.vertex2.point.w = -t.vertex2.point.z; + t.vertex2.point.z = 2.f * (-t.vertex2.point.z - min_z) / (max_z - min_z) - 1.f; + t.vertex3.point.x *= fac_for_aspect_ratio; + t.vertex3.point.y = -t.vertex3.point.y; + t.vertex3.point.w = -t.vertex3.point.z; + t.vertex3.point.z = 2.f * (-t.vertex3.point.z - min_z) / (max_z - min_z) - 1.f; + + pfb.draw_triangle(t); + } + } + SDL_UpdateTexture(texture, NULL, pfb.pixels(), SCREEN_WIDTH * 4); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + SDL_UpdateWindowSurface(window); + while (SDL_WaitEventTimeout(&e, 10)) { + if (e.type == SDL_QUIT) { + quit = true; + } + } + } + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); +} + +#if VIMENE_OS==VIMENE_LINUX +int main(int argc, char *argv[]) { + (void) argc; + (void) argv; +#elif VIMENE_OS==VIMENE_WINDOWS +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { +#endif + // main_term(); + main_SDL(); +#if VIMENE_OS==VIMENE_LINUX + return EXIT_SUCCESS; +#elif VIMENE_OS==VIMENE_WINDOWS + return 0; +#endif +} diff --git a/src/math_vector.cpp b/src/math_vector.cpp new file mode 100644 index 0000000..60081bf --- /dev/null +++ b/src/math_vector.cpp @@ -0,0 +1,173 @@ +#include "math_vector.h" +#include + +MathVector2::MathVector2() { +} + +MathVector2::MathVector2(float x, float y) : x{x}, y{y} { +} + +bool MathVector2::operator==(MathVector2 other) const { + return x == other.x && y == other.y; +} + +bool MathVector2::operator!=(MathVector2 other) const { + return !(*this == other); +} + +MathVector2 MathVector2::operator+() const { + return *this; +} + +MathVector2 MathVector2::operator-() const { + return { -x, -y }; +} + +MathVector2 MathVector2::operator+(MathVector2 other) const { + return { x + other.x, y + other.y }; +} + +MathVector2 MathVector2::operator-(MathVector2 other) const { + return *this + (-other); +} + +float MathVector2::det(MathVector2 other) const { + return this->x * other.y - other.x * this->y; +} + +MathVector2 MathVector2::round() const { + return { std::round(x), std::round(y) }; +} + +MathVector2 operator*(float n, MathVector2 other) { + return { n * other.x, n * other.y }; +} + +MathVector2 operator*(MathVector2 other, float n) { + return n * other; +} + +MathVector2 operator/(MathVector2 other, float n) { + return { other.x / n, other.y / n }; +} + +MathVector3::MathVector3() { +} + +MathVector3::MathVector3(float x, float y, float z) : x{x}, y{y}, z{z} { +} + +bool MathVector3::operator==(MathVector3 other) const { + return x == other.x && y == other.y && z == other.z; +} + +bool MathVector3::operator!=(MathVector3 other) const { + return !(*this == other); +} + +MathVector3 MathVector3::operator+() const { + return *this; +} + +MathVector3 MathVector3::operator-() const { + return { -x, -y, -z }; +} + +MathVector3 MathVector3::operator+(MathVector3 other) const { + return { x + other.x, y + other.y, z + other.z }; +} + +MathVector3 MathVector3::operator-(MathVector3 other) const { + return *this + (-other); +} + +MathVector3 MathVector3::round() const { + return { std::round(x), std::round(y), std::round(z) }; +} + +MathVector2 MathVector3::xy() const { + return { x, y }; +} + +MathVector3 MathVector3::cross(MathVector3 other) const { + return { + y * other.z - z * other.y, + z * other.x - x * other.z, + x * other.y - y * other.x + }; +} + +MathVector3 operator*(float n, MathVector3 other) { + return { n * other.x, n * other.y, n * other.z }; +} + +MathVector3 operator*(MathVector3 other, float n) { + return n * other; +} + +MathVector3 operator/(MathVector3 other, float n) { + return { other.x / n, other.y / n, other.z / n }; +} + +MathVector4::MathVector4() { +} + +MathVector4::MathVector4(float x, float y, float z, float w) : x{x}, y{y}, z{z}, w{w} { +} + +MathVector4::MathVector4(float x, float y, float z) : x{x}, y{y}, z{z}, w{1.f} { +} + +MathVector4::MathVector4(MathVector3 v, float w) : x{v.x}, y{v.y}, z{v.z}, w{w} { +} + +MathVector4::MathVector4(MathVector3 v) : x{v.x}, y{v.y}, z{v.z}, w{1.f} { +} + +bool MathVector4::operator==(MathVector4 other) const { + return x == other.x && y == other.y && z == other.z && w == other.w; +} + +bool MathVector4::operator!=(MathVector4 other) const { + return !(*this == other); +} + +MathVector4 MathVector4::operator+() const { + return *this; +} + +MathVector4 MathVector4::operator-() const { + return { -x, -y, -z, -w }; +} + +MathVector4 MathVector4::operator+(MathVector4 other) const { + return { x + other.x, y + other.y, z + other.z, w + other.w }; +} + +MathVector4 MathVector4::operator-(MathVector4 other) const { + return *this + (-other); +} + +MathVector4 MathVector4::round() const { + return { std::round(x), std::round(y), std::round(z), std::round(w) }; +} + +MathVector3 MathVector4::xyz() const { + return { x, y, z }; +} + +MathVector3 MathVector4::div_by_w() const { + return xyz() / w; +} + +MathVector4 operator*(float n, MathVector4 other) { + return { n * other.x, n * other.y, n * other.z, n * other.w }; +} + +MathVector4 operator*(MathVector4 other, float n) { + return n * other; +} + +MathVector4 operator/(MathVector4 other, float n) { + return { other.x / n, other.y / n, other.z / n, other.w / n }; +} diff --git a/src/math_vector.h b/src/math_vector.h new file mode 100644 index 0000000..336c3fe --- /dev/null +++ b/src/math_vector.h @@ -0,0 +1,69 @@ +#ifndef MATH_VECTOR_H +#define MATH_VECTOR_H + +class MathVector2 { + public: + float x, y; + + MathVector2(); + MathVector2(float x, float y); + bool operator==(MathVector2 other) const; + bool operator!=(MathVector2 other) const; + MathVector2 operator+() const; + MathVector2 operator-() const; + MathVector2 operator+(MathVector2 other) const; + MathVector2 operator-(MathVector2 other) const; + float det(MathVector2 other) const; + MathVector2 round() const; +}; + +MathVector2 operator*(float n, MathVector2 other); +MathVector2 operator*(MathVector2 other, float n); +MathVector2 operator/(MathVector2 other, float n); + +class MathVector3 { + public: + float x, y, z; + + MathVector3(); + MathVector3(float x, float y, float z); + bool operator==(MathVector3 other) const; + bool operator!=(MathVector3 other) const; + MathVector3 operator+() const; + MathVector3 operator-() const; + MathVector3 operator+(MathVector3 other) const; + MathVector3 operator-(MathVector3 other) const; + MathVector3 round() const; + MathVector2 xy() const; + MathVector3 cross(MathVector3 other) const; +}; + +MathVector3 operator*(float n, MathVector3 other); +MathVector3 operator*(MathVector3 other, float n); +MathVector3 operator/(MathVector3 other, float n); + +class MathVector4 { + public: + float x, y, z, w; + + MathVector4(); + MathVector4(float x, float y, float z, float w); + MathVector4(float x, float y, float z); + MathVector4(MathVector3 v, float w); + MathVector4(MathVector3 v); + bool operator==(MathVector4 other) const; + bool operator!=(MathVector4 other) const; + MathVector4 operator+() const; + MathVector4 operator-() const; + MathVector4 operator+(MathVector4 other) const; + MathVector4 operator-(MathVector4 other) const; + MathVector4 round() const; + MathVector3 xyz() const; + MathVector3 div_by_w() const; +}; + +MathVector4 operator*(float n, MathVector4 other); +MathVector4 operator*(MathVector4 other, float n); +MathVector4 operator/(MathVector4 other, float n); + +#endif // MATH_VECTOR_H diff --git a/src/obj3d.cpp b/src/obj3d.cpp new file mode 100644 index 0000000..3902d30 --- /dev/null +++ b/src/obj3d.cpp @@ -0,0 +1,46 @@ +#include "obj3d.h" +#include +#include +#include "vertex.h" +#include "tri_vertex.h" + +Object3D::TriangleVertex3Iterator::TriangleVertex3Iterator(const Object3D* obj, int face_ind) : obj{obj}, face_ind{face_ind} { +} + +Object3D::TriangleVertex3Iterator& Object3D::TriangleVertex3Iterator::operator++() { + face_ind++; + return *this; +} + +Object3D::TriangleVertex3Iterator Object3D::TriangleVertex3Iterator::operator++(int) { + TriangleVertex3Iterator retval = *this; + ++(*this); + return retval; +} + +bool Object3D::TriangleVertex3Iterator::operator==(TriangleVertex3Iterator other) const { + return obj == other.obj && face_ind == other.face_ind; +} + +bool Object3D::TriangleVertex3Iterator::operator!=(TriangleVertex3Iterator other) const { + return !(*this == other); +} + +Object3D::TriangleVertex3Iterator::reference Object3D::TriangleVertex3Iterator::operator*() const { + return { + obj->pts[obj->faces[face_ind][0]], + obj->pts[obj->faces[face_ind][1]], + obj->pts[obj->faces[face_ind][2]] + }; +} + +Object3D::Object3D(std::vector pts, std::vector> faces) : pts{pts}, faces{faces} { +} + +Object3D::TriangleVertex3Iterator Object3D::begin() { + return Object3D::TriangleVertex3Iterator{this}; +} + +Object3D::TriangleVertex3Iterator Object3D::end() { + return Object3D::TriangleVertex3Iterator{this, static_cast(faces.size())}; +} diff --git a/src/obj3d.h b/src/obj3d.h new file mode 100644 index 0000000..b76f06d --- /dev/null +++ b/src/obj3d.h @@ -0,0 +1,42 @@ +#ifndef OBJ3D_H +#define OBJ3D_H + +#include +#include +#include +#include "vertex.h" +#include "tri_vertex.h" + +class Object3D { + public: + class TriangleVertex3Iterator { + public: + using iterator_category = std::input_iterator_tag; + using value_type = TriangleVertex3; + using difference_type = TriangleVertex3; + using pointer = const TriangleVertex3*; + using reference = TriangleVertex3; + + explicit TriangleVertex3Iterator(const Object3D* obj, int face_ind = 0); + TriangleVertex3Iterator& operator++(); + TriangleVertex3Iterator operator++(int); + bool operator==(TriangleVertex3Iterator other) const; + bool operator!=(TriangleVertex3Iterator other) const; + reference operator*() const; + + private: + const Object3D* obj; + int face_ind; + + }; + + Object3D(std::vector pts, std::vector> faces); + TriangleVertex3Iterator begin(); + TriangleVertex3Iterator end(); + + private: + std::vector pts; + std::vector> faces; +}; + +#endif // OBJ3D_H diff --git a/src/pixfb.cpp b/src/pixfb.cpp new file mode 100644 index 0000000..f84bf2f --- /dev/null +++ b/src/pixfb.cpp @@ -0,0 +1,153 @@ +#include "pixfb.h" +#include +#include +#include +#include +#include "math_vector.h" +#include "vertex.h" +#include "tri_vertex.h" +#include "vertex_data.h" + +PixelFrameBuffer::PixelFrameBuffer(unsigned int w, unsigned int h) { + resize(w, h); +} + +void PixelFrameBuffer::resize(unsigned int w, unsigned int h) { + this->w = w; + this->h = h; + pixels_vector.resize(w * h); + depth_buf.resize(w * h); + clear(); +} + +unsigned int PixelFrameBuffer::width() const { + return w; +} + +unsigned int PixelFrameBuffer::height() const { + return h; +} + +const uint32_t* PixelFrameBuffer::pixels() const { + return pixels_vector.data(); +} + +void PixelFrameBuffer::clear() { + std::fill(pixels_vector.begin(), pixels_vector.end(), 0x000000FF); + std::fill(depth_buf.begin(), depth_buf.end(), 1.f); + face_ind = -1; +} + +void PixelFrameBuffer::_draw_cropped_triangle(TriangleVertex3 triangle) { + std::array sorted_vs = { &triangle.vertex1, &triangle.vertex2, &triangle.vertex3 }; + +#define SWAP_IF_LT(X,Y) ({\ + if (sorted_vs[X]->point.y < sorted_vs[Y]->point.y) {\ + Vertex3* temp = sorted_vs[X];\ + sorted_vs[X] = sorted_vs[Y];\ + sorted_vs[Y] = temp;\ + }\ + }) + SWAP_IF_LT(1, 0); + SWAP_IF_LT(2, 1); + SWAP_IF_LT(1, 0); +#undef SWAP_IF_LT + + Vertex3 middle_vl = *sorted_vs[1]; + float fac = (sorted_vs[1]->point.y - sorted_vs[0]->point.y) / (sorted_vs[2]->point.y - sorted_vs[0]->point.y); + Vertex3 middle_vr{ + { + sorted_vs[0]->point.x + fac * (sorted_vs[2]->point.x - sorted_vs[0]->point.x), + sorted_vs[1]->point.y, + sorted_vs[0]->point.z + fac * (sorted_vs[2]->point.z - sorted_vs[0]->point.z) + }, + VertexData::lerp(sorted_vs[0]->data, sorted_vs[2]->data, fac) + }; + if (middle_vr.point.x < middle_vl.point.x) { + Vertex3 temp = middle_vr; + middle_vr = middle_vl; + middle_vl = temp; + } + + // top triangle + { + if (sorted_vs[0]->point.y != sorted_vs[1]->point.y) { + int top_y = static_cast(std::floor(sorted_vs[0]->point.y + 1.f)); + int bottom_y = static_cast(std::ceil(sorted_vs[1]->point.y - 1.f)); + for (int y = top_y; y <= bottom_y; y++) { + float iy = static_cast(y); + float s = (iy - sorted_vs[0]->point.y) / (sorted_vs[1]->point.y - sorted_vs[0]->point.y); + float xl = sorted_vs[0]->point.x + s * (middle_vl.point.x - sorted_vs[0]->point.x); + float xr = sorted_vs[0]->point.x + s * (middle_vr.point.x - sorted_vs[0]->point.x); + int left_x = static_cast(std::ceil(xl)); + int right_x = static_cast(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast(x); + float t = (ix - xl) / (xr - xl); + // depth and vd don't take into account perspective + float depth = sorted_vs[0]->point.z + s * (middle_vl.point.z - sorted_vs[0]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[0]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + pixels_vector[x + y * w] = face_color(); + } + } + } + } + } + + // bottom triangle + { + if (sorted_vs[1]->point.y != sorted_vs[2]->point.y) { + int bottom_y = static_cast(std::floor(sorted_vs[2]->point.y)); + int top_y = static_cast(std::ceil(sorted_vs[1]->point.y)); + for (int y = top_y; y <= bottom_y; y++) { + float iy = static_cast(y); + float s = (iy - sorted_vs[2]->point.y) / (sorted_vs[1]->point.y - sorted_vs[2]->point.y); + float xl = sorted_vs[2]->point.x + s * (middle_vl.point.x - sorted_vs[2]->point.x); + float xr = sorted_vs[2]->point.x + s * (middle_vr.point.x - sorted_vs[2]->point.x); + int left_x = static_cast(std::ceil(xl)); + int right_x = static_cast(std::ceil(xr - 1.f)); + for (int x = left_x; x <= right_x; x++) { + float ix = static_cast(x); + float t = (ix - xl) / (xr - xl); + // depth and vd don't take into account perspective + float depth = sorted_vs[2]->point.z + s * (middle_vl.point.z - sorted_vs[2]->point.z + t * (middle_vr.point.z - middle_vl.point.z)); + // VertexData vd = VertexData::bilerp(sorted_vs[2]->data, middle_vl.data, middle_vr.data, s, t); + if (depth < depth_buf[x + y * w]) { + depth_buf[x + y * w] = depth; + pixels_vector[x + y * w] = face_color(); + } + } + } + } + } +} + +void PixelFrameBuffer::draw_triangle(TriangleVertex4 triangle) { + face_ind++; + for (auto t1 : triangle.crop_z_out(-1.f, 1.f)) { + for (auto t2 : t1.div_by_w().crop_xy_out(-1.f, 1.f, -1.f, 1.f)) { + MathVector2 pp1 = t2.vertex1.point.xy(), + pp2 = t2.vertex2.point.xy(), + pp3 = t2.vertex3.point.xy(); + if ((pp2 - pp1).det(pp3 - pp1) >= 0.f) continue; + t2.vertex1.point = (t2.vertex1.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex2.point = (t2.vertex2.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + t2.vertex3.point = (t2.vertex3.point + MathVector3{1.f, 1.f, 0.f}) / 2.f; + float fw = static_cast(w), fh = static_cast(h); + t2.vertex1.point.x = t2.vertex1.point.x * fw - .5f; + t2.vertex1.point.y = t2.vertex1.point.y * fh - .5f; + t2.vertex2.point.x = t2.vertex2.point.x * fw - .5f; + t2.vertex2.point.y = t2.vertex2.point.y * fh - .5f; + t2.vertex3.point.x = t2.vertex3.point.x * fw - .5f; + t2.vertex3.point.y = t2.vertex3.point.y * fh - .5f; + _draw_cropped_triangle(t2); + } + } +} + +uint32_t PixelFrameBuffer::face_color() const { + int n = face_ind / 2; + return ((n % 2 ? 0xFF000000 : 0x55000000) >> ((n % 6) / 2 * 8)) | 0xFF; +} diff --git a/src/pixfb.h b/src/pixfb.h new file mode 100644 index 0000000..c54b5fb --- /dev/null +++ b/src/pixfb.h @@ -0,0 +1,29 @@ +#ifndef PIXFB_H +#define PIXFB_H + +#include +#include +#include "math_vector.h" +#include "tri_vertex.h" + +class PixelFrameBuffer { + public: + PixelFrameBuffer(unsigned int w, unsigned int h); + void resize(unsigned int w, unsigned int h); + unsigned int width() const; + unsigned int height() const; + const uint32_t* pixels() const; + void clear(); + void draw_triangle(TriangleVertex4 triangle); + + private: + unsigned int w, h; + std::vector pixels_vector; + std::vector depth_buf; + int face_ind; + + void _draw_cropped_triangle(TriangleVertex3 triangle); + uint32_t face_color() const; +}; + +#endif // PIXFB_H diff --git a/src/stamp-h1 b/src/stamp-h1 new file mode 100644 index 0000000..57ea58e --- /dev/null +++ b/src/stamp-h1 @@ -0,0 +1 @@ +timestamp for src/config.h diff --git a/src/tri_vertex.cpp b/src/tri_vertex.cpp new file mode 100644 index 0000000..cd07770 --- /dev/null +++ b/src/tri_vertex.cpp @@ -0,0 +1,314 @@ +#include "tri_vertex.h" +#include +#include "math_vector.h" +#include "vertex_data.h" +#include "vertex.h" +#include "tri_vertex.h" + +TriangleVertex3::TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { +} + +#define P1_OUT 1 +#define P2_OUT 2 +#define P3_OUT 4 +static void _crop_x(std::vector& tris, TriangleVertex3 t, int n, float x) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex3* q1; + Vertex3* q2; + Vertex3* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector3 dq2 = q1->point - q2->point; + float fac2 = (x - q2->point.x) / dq2.x; + Vertex3 r2{ + { + x, + q2->point.y + fac2 * dq2.y, + q2->point.z + fac2 * dq2.z + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector3 dq3 = q1->point - q3->point; + float fac3 = (x - q3->point.x) / dq3.x; + Vertex3 r3{ + { + x, + q3->point.y + fac3 * dq3.y, + q3->point.z + fac3 * dq3.z + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +static void _crop_y(std::vector& tris, TriangleVertex3 t, int n, float y) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex3* q1; + Vertex3* q2; + Vertex3* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector3 dq2 = q1->point - q2->point; + float fac2 = (y - q2->point.y) / dq2.y; + Vertex3 r2{ + { + q2->point.x + fac2 * dq2.x, + y, + q2->point.z + fac2 * dq2.z + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector3 dq3 = q1->point - q3->point; + float fac3 = (y - q3->point.y) / dq3.y; + Vertex3 r3{ + { + q3->point.x + fac3 * dq3.x, + y, + q3->point.z + fac3 * dq3.z + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +std::vector TriangleVertex3::crop_xy_out(float x1, float x2, float y1, float y2) const { + std::vector tris_final; + std::vector tris1; + _crop_x(tris1, *this, (vertex1.point.x < x1) | ((vertex2.point.x < x1) << 1) | ((vertex3.point.x < x1) << 2), x1); + for (auto t1 : tris1) { + std::vector tris2; + _crop_x(tris2, t1, (t1.vertex1.point.x > x2) | ((t1.vertex2.point.x > x2) << 1) | ((t1.vertex3.point.x > x2) << 2), x2); + for (auto t2 : tris2) { + std::vector tris3; + _crop_y(tris3, t2, (t2.vertex1.point.y < y1) | ((t2.vertex2.point.y < y1) << 1) | ((t2.vertex3.point.y < y1) << 2), y1); + for (auto t3 : tris3) + _crop_y(tris_final, t3, (t3.vertex1.point.y > y2) | ((t3.vertex2.point.y > y2) << 1) | ((t3.vertex3.point.y > y2) << 2), y2); + } + } + return tris_final; +} +#undef P1_OUT +#undef P2_OUT +#undef P3_OUT + +TriangleVertex4::TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3) : vertex1{vertex1}, vertex2{vertex2}, vertex3{vertex3} { +} + +TriangleVertex4::TriangleVertex4(TriangleVertex3 triangle) : vertex1{triangle.vertex1}, vertex2{triangle.vertex2}, vertex3{triangle.vertex3} { +} + +#define P1_OUT 1 +#define P2_OUT 2 +#define P3_OUT 4 +static void _crop_z(std::vector& tris, TriangleVertex4 t, int n, float z) { + switch (n) { + case 0: + tris.push_back(t); + break; + case P1_OUT: + case P2_OUT: + case P3_OUT: + case P2_OUT | P3_OUT: + case P1_OUT | P3_OUT: + case P1_OUT | P2_OUT: + { + Vertex4* q1; + Vertex4* q2; + Vertex4* q3; + switch (n) { + case P1_OUT: + case P2_OUT | P3_OUT: + q1 = &t.vertex1; + q2 = &t.vertex2; + q3 = &t.vertex3; + break; + case P2_OUT: + case P1_OUT | P3_OUT: + q1 = &t.vertex2; + q2 = &t.vertex1; + q3 = &t.vertex3; + break; + case P3_OUT: + case P1_OUT | P2_OUT: + q1 = &t.vertex3; + q2 = &t.vertex2; + q3 = &t.vertex1; + break; + } + MathVector4 dq2 = q1->point - q2->point; + float fac2 = (z - q2->point.z) / dq2.z; + Vertex4 r2{ + { + q2->point.x + fac2 * dq2.x, + q2->point.y + fac2 * dq2.y, + z, + q2->point.w + fac2 * dq2.w + }, + VertexData::lerp(q2->data, q1->data, fac2) + }; + MathVector4 dq3 = q1->point - q3->point; + float fac3 = (z - q3->point.z) / dq3.z; + Vertex4 r3{ + { + q3->point.x + fac3 * dq3.x, + q3->point.y + fac3 * dq3.y, + z, + q3->point.w + fac3 * dq3.w + }, + VertexData::lerp(q3->data, q1->data, fac3) + }; + switch (n) { + case P1_OUT: + tris.push_back({r3, *q2, *q3}); + tris.push_back({r3, r2, *q2}); + break; + case P2_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P3_OUT: + tris.push_back({r2, *q3, *q2}); + tris.push_back({r2, r3, *q3}); + break; + case P2_OUT | P3_OUT: + tris.push_back({*q1, r2, r3}); + break; + case P1_OUT | P3_OUT: + tris.push_back({*q1, r3, r2}); + break; + case P1_OUT | P2_OUT: + tris.push_back({*q1, r3, r2}); + break; + } + } + break; + case P1_OUT | P2_OUT | P3_OUT: + break; + } +} + +std::vector TriangleVertex4::crop_z_out(float z1, float z2) const { + std::vector tris; + _crop_z(tris, *this, (vertex1.point.z < z1) | ((vertex2.point.z < z1) << 1) | ((vertex3.point.z < z1) << 2), z1); + std::vector tris2; + for (auto t : tris) + _crop_z(tris2, t, (t.vertex1.point.z > z2) | ((t.vertex2.point.z > z2) << 1) | ((t.vertex3.point.z > z2) << 2), z2); + return tris2; +} +#undef P1_OUT +#undef P2_OUT +#undef P3_OUT + +TriangleVertex3 TriangleVertex4::div_by_w() const { + return {vertex1.div_by_w(), vertex2.div_by_w(), vertex3.div_by_w()}; +} diff --git a/src/tri_vertex.h b/src/tri_vertex.h new file mode 100644 index 0000000..5bbdd40 --- /dev/null +++ b/src/tri_vertex.h @@ -0,0 +1,29 @@ +#ifndef TRI_VERTEX_H +#define TRI_VERTEX_H + +#include "vertex.h" +#include + +class TriangleVertex3 { + public: + Vertex3 vertex1; + Vertex3 vertex2; + Vertex3 vertex3; + + TriangleVertex3(Vertex3 vertex1, Vertex3 vertex2, Vertex3 vertex3); + std::vector crop_xy_out(float x1, float x2, float y1, float y2) const; +}; + +class TriangleVertex4 { + public: + Vertex4 vertex1; + Vertex4 vertex2; + Vertex4 vertex3; + + TriangleVertex4(Vertex4 vertex1, Vertex4 vertex2, Vertex4 vertex3); + TriangleVertex4(TriangleVertex3 triangle); + std::vector crop_z_out(float z1, float z2) const; + TriangleVertex3 div_by_w() const; +}; + +#endif // TRI_VERTEX_H diff --git a/src/vertex.cpp b/src/vertex.cpp new file mode 100644 index 0000000..d136754 --- /dev/null +++ b/src/vertex.cpp @@ -0,0 +1,16 @@ +#include "vertex.h" +#include "math_vector.h" +#include "vertex_data.h" + +Vertex3::Vertex3(MathVector3 point, VertexData data) : point{point}, data{data} { +} + +Vertex4::Vertex4(MathVector4 point, VertexData data) : point{point}, data{data} { +} + +Vertex4::Vertex4(Vertex3 vertex) : point{vertex.point}, data{vertex.data} { +} + +Vertex3 Vertex4::div_by_w() const { + return {point.div_by_w(), data}; +} diff --git a/src/vertex.h b/src/vertex.h new file mode 100644 index 0000000..92b7dcb --- /dev/null +++ b/src/vertex.h @@ -0,0 +1,25 @@ +#ifndef VERTEX_H +#define VERTEX_H + +#include "math_vector.h" +#include "vertex_data.h" + +class Vertex3 { + public: + MathVector3 point; + VertexData data; + + Vertex3(MathVector3 point, VertexData data); +}; + +class Vertex4 { + public: + MathVector4 point; + VertexData data; + + Vertex4(MathVector4 point, VertexData data); + Vertex4(Vertex3 vertex); + Vertex3 div_by_w() const; +}; + +#endif // VERTEX_H diff --git a/src/vertex_data.cpp b/src/vertex_data.cpp new file mode 100644 index 0000000..23c8b03 --- /dev/null +++ b/src/vertex_data.cpp @@ -0,0 +1,12 @@ +#include "vertex_data.h" + +VertexData VertexData::lerp(VertexData& vd1, VertexData& vd2, float s) { + return {}; +} + +VertexData VertexData::bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t) { + return {}; +} + +VertexData::VertexData() { +} diff --git a/src/vertex_data.h b/src/vertex_data.h new file mode 100644 index 0000000..e35d65a --- /dev/null +++ b/src/vertex_data.h @@ -0,0 +1,12 @@ +#ifndef VERTEX_DATA_H +#define VERTEX_DATA_H + +class VertexData { + public: + static VertexData lerp(VertexData& vd1, VertexData& vd2, float s); + static VertexData bilerp(VertexData& vd1, VertexData& vd2, VertexData& vd3, float s, float t); + + VertexData(); +}; + +#endif // VERTEX_DATA_H -- cgit v1.2.3