├── .gitignore ├── CMakeLists.txt ├── INTEGRATION ├── LICENSE ├── LIMITATIONS ├── Makefile ├── README.md ├── Raw_Demos ├── CMakeLists.txt ├── Makefile ├── asciifractal.sh ├── bigfont.c ├── char.txt ├── gears.c ├── gears_orig.png └── t2i.c ├── SDL_Examples ├── .clang-format ├── Arnepalette.png ├── CMakeLists.txt ├── Makefile ├── WWGW.mp3 ├── code_format.sh ├── extrude.obj ├── game.c ├── gears.c ├── helloworld.c ├── menu.c ├── model.c ├── monkey3.obj ├── quick.sh ├── stdout.txt ├── tex.jpg ├── tex_hole.png ├── tex_old.jpg ├── texture.c └── texture.png ├── config.mk ├── doc ├── blend.gif ├── capture.gif ├── capture2.gif ├── helloworld.gif ├── menu.gif ├── model.gif ├── model2.gif ├── model2_lit.gif ├── model_hole.gif ├── model_lit.gif ├── specular.gif └── texture_test.png ├── include-demo ├── 3dMath.h ├── api_audio.h ├── chade.h ├── chadphys.h ├── lockstepthread.h ├── openimgui.h ├── resweep.h ├── stb_c_lexer.h ├── stb_connected_components.h ├── stb_divide.h ├── stb_ds.h ├── stb_dxt.h ├── stb_easy_font.h ├── stb_herringbone_wang_tile.h ├── stb_hexwave.h ├── stb_image.h ├── stb_image_resize.h ├── stb_image_write.h ├── stb_include.h ├── stb_leakcheck.h ├── stb_rect_pack.h ├── stb_sprintf.h ├── stb_textedit.h ├── stb_tilemap_editor.h ├── stb_truetype.h ├── stb_voxel_render.h ├── stringutil.h └── tobjparse.h ├── include ├── CMakeLists.txt ├── GL │ └── gl.h ├── zbuffer.h └── zfeatures.h ├── lib └── .gitkeep ├── src ├── .clang-format ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── Makefile_Backup ├── accum.c ├── api.c ├── arrays.c ├── clear.c ├── clip.c ├── code_format.sh ├── error_check.h ├── error_check_no_context.h ├── font8x8_basic.h ├── get.c ├── image_util.c ├── init.c ├── light.c ├── list.c ├── matrix.c ├── memory.c ├── misc.c ├── msghandling.c ├── msghandling.h ├── opinfo.h ├── quick.sh ├── select.c ├── specbuf.c ├── texture.c ├── vertex.c ├── zbuffer.c ├── zgl.h ├── zline.c ├── zline.h ├── zmath.c ├── zmath.h ├── zpostprocess.c ├── zraster.c ├── ztext.c ├── ztriangle.c └── ztriangle.h └── tgl_minimal.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.config 2 | *.creator* 3 | *.files 4 | *.includes 5 | 6 | # Ignore build outputs 7 | build 8 | src/*.o 9 | src/*.a 10 | Raw_Demos/bigfont 11 | Raw_Demos/gears 12 | Raw_Demos/t2i 13 | lib/*.a -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(tinygl 3 | DESCRIPTION "tinygl: The ultimate portable graphics library" 4 | HOMEPAGE_URL "https://github.com/C-Chads/tinygl" 5 | LANGUAGES C 6 | ) 7 | 8 | set(CMAKE_C_STANDARD 99) 9 | set(CMAKE_C_STANDARD_REQUIRED ON) 10 | set(CMAKE_C_EXTENSIONS OFF) 11 | 12 | # Set relative output directory paths, if not already defined 13 | if (NOT BIN_DIR) 14 | set(BIN_DIR bin) 15 | endif (NOT BIN_DIR) 16 | if (NOT INCLUDE_DIR) 17 | set(INCLUDE_DIR include) 18 | endif (NOT INCLUDE_DIR) 19 | if (NOT DEFINED LIB_DIR) 20 | set(LIB_DIR lib) 21 | endif (NOT DEFINED LIB_DIR) 22 | 23 | # Check for a math library 24 | include(CheckLibraryExists) 25 | check_library_exists(m cos "" HAVE_M_LIBRARY) 26 | if (HAVE_M_LIBRARY) 27 | set(M_LIBRARY m) 28 | endif (HAVE_M_LIBRARY) 29 | 30 | # Options 31 | option(TINYGL_BUILD_EXAMPLES "Build Examples" OFF) 32 | option(TINYGL_BUILD_SHARED "Build Shared Library" ON) 33 | option(TINYGL_BUILD_STATIC "Build Static Library" ON) 34 | 35 | # Build main library 36 | add_subdirectory(src) 37 | 38 | # Install logic for headers 39 | add_subdirectory(include) 40 | 41 | # Examples 42 | if(TINYGL_BUILD_EXAMPLES) 43 | 44 | enable_testing() 45 | 46 | # These deliberately do not depend on SDL. TODO - these could be used to 47 | # drive a "make test" system to check the correct functioning of the library 48 | # after compilation... 49 | add_subdirectory(Raw_Demos) 50 | 51 | # Examples that use SDL for interactive display 52 | add_subdirectory(SDL_Examples) 53 | 54 | endif() 55 | 56 | # Local Variables: 57 | # tab-width: 8 58 | # mode: cmake 59 | # indent-tabs-mode: t 60 | # End: 61 | # ex: shiftwidth=2 tabstop=8 62 | 63 | -------------------------------------------------------------------------------- /INTEGRATION: -------------------------------------------------------------------------------- 1 | I will teach you here how to integrate TinyGL into almost any project. 2 | 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | Method 1: Organized or "I'm a master software architect" 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | step 1: Copy the src directory into your project, and name it something like "src_tinygl" 7 | 8 | step 2: copy the contents of the include folder to your project's include folder, exactly one level above 9 | the aformentioned src directory. 10 | 11 | step 2.5: If you are using an alternate directory structure, adjust the includes. 12 | 13 | step 3: copy and alter the config.mk file into your project directory above the src_tinygl directory. 14 | You should modify the CC and CFLAGS to suit your project. 15 | 16 | step 4: add a step in your main project makefile to cd into the src_tinygl directory and `make -B` 17 | 18 | step 5: add a step in your main project makefile to copy libTinyGL.a from src_tinygl to the aforementioned "lib" directory. 19 | 20 | step 6: Compile your programs by including from the include directory 21 | (relative pathing is probably easiest, but you can do -Isystem) 22 | and linking to libTinyGL.a 23 | 24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 | Method 2: "One big program!" or "help I don't have ar in my toolchain!!!!" 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | step 1: Place everything in 'src' from this repository in a single folder. 28 | step 2: Place everything from 'include' into a single folder. 29 | step 3: adjust the #includes in all files so that they point to the correct target files. 30 | This will likely be an iterative process of compiling, 31 | seeing an error message about a missing include, and fixing it. 32 | 33 | step 4 v1: Compile all relevant C source files into your "one big program". No need for a ".a" statically linked library. 34 | you must link against the C standard library and specifically '-lm' for the math library. 35 | step 4 v2: Compile all relevant C source files into objects, and then use them later. You do not have to specify any linkages. 36 | In your final binary, you must link against the standard library and -lm. 37 | 38 | 39 | Note that ar is just a tool which merges object files into convenient archives. ar is not needed to build TinyGL. 40 | 41 | Whatever you're using to compile C source files will compile TinyGL. 42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | Q&A 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | What can I use TinyGL for? 48 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 | 1) Graphics library replacement. Who needs GPUs, am i right? 50 | 2) Cross platform code. TinyGL should run unmodified on almost any platform with a conformant floating point 51 | implementation and 32 bit integer types. 52 | 3) Serverside rendering. Put TinyGL in a program running on a server and stream the video over the network. Who needs X? 53 | 4) Pre-rendered graphics. Since TinyGL runs entirely on the CPU, it is very easy to customize its pipeline to create 54 | unique and interesting things. TinyGL 55 | 5) Porting programs written for OpenGL. TinyGL is *NOT* a standards-compliant OpenGL implementation, and 56 | will never be. TinyGL is NOT OpenGL and should not be confused with it. 57 | That said, since TinyGL's API is very *similar* to OpenGL's API, 58 | and since TinyGL will run on even the most obscure and inane architectures... 59 | once you port C code to using TinyGL, it is almost automatically usable on almost any device you can imagine. 60 | 61 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 | TinyGL uses too much memory? 63 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 64 | The library's defaults for the maximum number of textures, display lists, lights, and so-on are optimized for platforms 65 | with abundant memory. Configure these and other defaults in 'zgl.h' or 'zfeatures.h' 66 | 67 | Consider also reducing the texture size from the default 256x256 to 64x64 or 32x32 (for that N64 vibe) if you're desparate. 68 | 69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | How do I use 16 bit color? 71 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 72 | see zfeatures.h, you will have to modify these lines for full 16 bit compatibility: 73 | 74 | These lines are setup for 32 bit color,if you are going to use the NO_DRAW_COLOR or NO_COPY_COLOR then 75 | you should set these differently: 76 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 77 | #define TGL_NO_COPY_COLOR 0xff00ff 78 | #define TGL_NO_DRAW_COLOR 0xff00ff 79 | /* solid debug pink.*/ 80 | #define TGL_COLOR_MASK 0x00ffffff 81 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 82 | These lines configure the actual color bit depth: 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | #define TGL_FEATURE_16_BITS 0 85 | #define TGL_FEATURE_32_BITS 1 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice: 2 | 3 | (C) 1997-2021 Fabrice Bellard, Gek (DMHSW), C-Chads 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product and its documentation 16 | *is* required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | If you redistribute modified sources, I would appreciate that you 22 | include in the files history information documenting your changes. 23 | 24 | 25 | 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | For the SDL Examples. 28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | 30 | 31 | This program uses SDL 1.2, which is licensed under the GNU Lesser General Public Library, version 2.1. 32 | You can find a copy of this license at https://www.gnu.org/licenses/lgpl-2.1.en.html 33 | -------------------------------------------------------------------------------- /LIMITATIONS: -------------------------------------------------------------------------------- 1 | //Maintainer's note: This file is not maintained, it remains in the repository as a historical artifact. 2 | 3 | 4 | Here are listed the functions that TinyGL understands with the known 5 | limitations. The non mentionned functions are *not* implemented and 6 | must not be used. 7 | 8 | 9 | ************ glEnable / glDisable 10 | 11 | - The following flags are handled: 12 | 13 | GL_CULL_FACE, GL_LIGHTING, GL_COLOR_MATERIAL, GL_TEXTURE_2D, GL_NORMALIZE, 14 | GL_LIGHTx, GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_POINT, 15 | GL_POLYGON_OFFSET_LINE 16 | 17 | 18 | - GL_DEPTH_TEST is accepted, but it is only used for lines. For all 19 | other primitives, Z buffer use is assumed. The DepthMode is 20 | hardcoded as GL_LESS (OpenGL default). 21 | 22 | ************ glShadeModel 23 | 24 | OK. 25 | 26 | ************ glCullFace 27 | 28 | OK. 29 | 30 | ************ glPolygonMode 31 | 32 | OK. 33 | 34 | ************ glBegin 35 | 36 | No tests are performed to prevent some functions of being executed 37 | between glBegin/glEnd. 38 | 39 | ************ glEnd 40 | 41 | OK. 42 | 43 | ************ glVertex 44 | 45 | Some prototypes are not implemented. 46 | 47 | 48 | ************ glColor 49 | 50 | Some prototypes are not implemented. 51 | 52 | ************ glNormal 53 | 54 | Some prototypes are not implemented. 55 | 56 | ************ glTexCoord 57 | 58 | - Some prototypes are not implemented. 59 | 60 | - The Matrix transformation is not applied yet. 61 | 62 | ************ glEdgeFlag 63 | 64 | OK. The edge handling has to be tested, although it is not much useful 65 | in TinyGL. 66 | 67 | ************ glMatrixMode / glLoadMatrixf / glLoadIdentity / glMultMatrixf / 68 | glPushMatrix / glPopMatrix / glRotatef / glTranslatef / glScalef / 69 | glFrustum 70 | 71 | - The prototypes with doubles are not implemented. 72 | 73 | ************ glViewport 74 | 75 | GlViewport calls a function pointers to tell glx (or another display 76 | system) to resize the Z buffer and the ximage. Made optional in 77 | version 0.2. 78 | 79 | ************ glGenLists / glIsList / glNewList / glEndList / glCallList 80 | 81 | OK. 82 | 83 | ************ glClear / glClearColor / glClearDepth 84 | 85 | The whole zbuffer and the colors are cleared in any case. The clear color 86 | can be redefined, by *not* the initial z value. 87 | 88 | ************ glRenderMode 89 | 90 | Only the modes GL_RENDER and GL_SELECT are implemented. 91 | 92 | ************ glSelectBuffer / glInitNames / glPushName / glPopName / glLoadName 93 | 94 | OK. 95 | 96 | ************ glGenTextures / glDeleteTextures / glBindTexture 97 | 98 | OK. These functions should be used to get the maximum performance with 99 | TinyGL. 100 | 101 | ************ glTexImage2D 102 | 103 | The function accepts only RGB UNSIGNED_BYTES bitmaps. They are 104 | internally resized to 256x256 so you'd better use that size. No 105 | mipmapping is implemented although it will come if asked. No borders 106 | are implemented. 107 | 108 | ************ glTexEnvi 109 | 110 | The only supported mode is GL_DECAL, although others are planned if 111 | asked. 112 | 113 | 114 | ************ glTexParameteri 115 | 116 | The other prototypes are not implemented. Only the follwing mode are 117 | implemented: 118 | 119 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 120 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 121 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 122 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 123 | 124 | ************ glPixelStorei 125 | 126 | The pixels are alware byte aligned. 127 | 128 | ************ glMaterialfv / glMaterialf / glColorMaterial 129 | 130 | OK. 131 | 132 | 133 | ************ glLightfv / glLightf / glLightModeli / glLightModelfv 134 | 135 | OK. The OpenGL lightening is implemented but not optimized. 136 | 137 | 138 | ************ glFlush 139 | 140 | Ignored. 141 | 142 | ************ glHint 143 | 144 | Ignored. 145 | 146 | ************ glGetIntegerv 147 | 148 | - only GL_VIEWPORT, GL_MAX_MODELVIEW_STACK_DEPTH, 149 | GL_MAX_PROJECTION_STACK_DEPTH, GL_MAX_LIGHTS, GL_MAX_TEXTURE_SIZE, 150 | GL_MAX_TEXTURE_STACK_DEPTH 151 | 152 | ************ glGetIntegerv 153 | 154 | - only GL_TEXTURE_MATRIX, GL_PROJECTION_MATRIX, GL_MODELVIEW_MATRIX, 155 | GL_LINE_WIDTH, GL_LINE_WIDTH_RANGE, GL_POINT_SIZE, GL_POINT_SIZE_RANGE 156 | 157 | ************ glPolygonOffset 158 | 159 | - only API implemented. 160 | 161 | ************ glEnableClientState, glDisableClientState, 162 | 163 | - No support for GL_INDEX_ARRAY_POINTER or GL_EDGE_FLAG_ARRAY_POINTER 164 | 165 | ************ glVertexPointer, glNormalPointer, 166 | glColorPointer, glTexureCoordPointer 167 | 168 | - OK 169 | 170 | ------------------------------------------------------------------------------ 171 | 172 | TinyGL GLX emulation: 173 | 174 | 175 | ************ glXQueryExtension 176 | 177 | Returns always True 178 | 179 | ************ glXChooseVisual 180 | 181 | Only 8 bit Pseudocolor or 16 bit Truecolor Visual are accepted. The 182 | attribute list is ignored. 183 | 184 | ************ glXCreateContext 185 | 186 | The sharing is not implemented although the code could handle it. 187 | 188 | ************ glXDestroyContext 189 | 190 | OK. 191 | 192 | ************ glXMakeCurrent 193 | 194 | Not all the syntax is supported yet, in particular with the 'NULL' or 195 | 'None' parameters. 196 | 197 | 198 | ************ glXSwapBuffers 199 | 200 | OK. 201 | 202 | ************ glXWaitGL / glXWaitX 203 | 204 | Ignored. 205 | 206 | 207 | See README.BEOS for BeOS limitations. 208 | 209 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | LIBNAME=libTinyGL.a 3 | LIB=lib/$(LIBNAME) 4 | LIBDIR=/usr/local/lib 5 | INCDIR=/usr/local/include 6 | BINDIR=/usr/local/bin 7 | 8 | all: $(LIB) RDMOS 9 | @echo Done! 10 | 11 | $(LIB): 12 | cd src && $(MAKE) && cd .. 13 | cp src/*.a ./lib/ 14 | 15 | install: $(LIB) 16 | cp $(LIB) $(LIBDIR) 17 | mkdir $(INCDIR)/tinygl || echo "You installed before?" 18 | cp -r include/* $(INCDIR)/tinygl 19 | 20 | uninstall: 21 | rm -f $(LIBDIR)/$(LIBNAME) 22 | rm -rf $(INCDIR)/tinygl 23 | 24 | SDL_Examples: $(LIB) 25 | @echo "These demos require SDL 1.2 to compile." 26 | cd SDL_Examples && $(MAKE) && cd .. 27 | 28 | tglgears: $(LIB) 29 | @echo "These demos require SDL 1.2 to compile." 30 | cd SDL_Examples && $(MAKE) install_tglgears && cd .. 31 | 32 | RDMOS: $(LIB) 33 | @echo "Building the RAW DEMOS. These do not require anything special on your system, so they should succeed." 34 | cd Raw_Demos && $(MAKE) && cd .. 35 | 36 | clean: 37 | cd src && $(MAKE) clean && cd .. 38 | cd SDL_Examples && $(MAKE) clean && cd .. 39 | cd Raw_Demos && $(MAKE) clean && cd .. 40 | cd lib && rm -f *.a && cd .. 41 | #clean: 42 | # rm -f *~ *.o *.a 43 | # cd SDL_Examples && $(MAKE) clean && cd .. 44 | -------------------------------------------------------------------------------- /Raw_Demos/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(TARGET tinygl) 2 | set(TINYGL_LIB tinygl) 3 | elseif(TARGET tinygl-static) 4 | set(TINYGL_LIB tinygl-static) 5 | endif(TARGET tinygl) 6 | 7 | if(TINYGL_LIB) 8 | 9 | set(raw_names gears t2i bigfont) 10 | foreach(DEMO ${raw_names}) 11 | set(DEMO_NAME "raw_${DEMO}") 12 | add_executable(${DEMO_NAME} ${DEMO}.c) 13 | target_link_libraries(${DEMO_NAME} ${TINYGL_LIB} ${M_LIBRARY}) 14 | target_include_directories(${DEMO_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) 15 | endforeach() 16 | 17 | # Copy utility files to build dir 18 | configure_file(asciifractal.sh ${CMAKE_CURRENT_BINARY_DIR}/asciifractal.sh) 19 | configure_file(char.txt ${CMAKE_CURRENT_BINARY_DIR}/char.txt) 20 | 21 | # Check that the gears image is rendered 22 | add_test(NAME render_gears COMMAND raw_gears) 23 | add_test(NAME diff_gears COMMAND ${CMAKE_COMMAND} -E compare_files ${CMAKE_CURRENT_SOURCE_DIR}/gears_orig.png ${CMAKE_CURRENT_BINARY_DIR}/render.png) 24 | set_tests_properties(diff_gears PROPERTIES DEPENDS render_gears) 25 | 26 | endif(TINYGL_LIB) 27 | 28 | # Local Variables: 29 | # tab-width: 8 30 | # mode: cmake 31 | # indent-tabs-mode: t 32 | # End: 33 | # ex: shiftwidth=2 tabstop=8 34 | 35 | -------------------------------------------------------------------------------- /Raw_Demos/Makefile: -------------------------------------------------------------------------------- 1 | include ../config.mk 2 | #CC= gcc 3 | #CFLAGS = -g -Wall -O3 -w 4 | GL_LIBS= -L../ 5 | GL_INCLUDES= -I../include/ 6 | ALL_T= gears t2i bigfont 7 | LIB= ../lib/libTinyGL.a 8 | 9 | #For GCC on good OSes: 10 | # 11 | #for MinGW users: 12 | #SDL_LIBS= -lmingw32 -lSDLmain -lSDL 13 | 14 | 15 | 16 | all: $(ALL_T) 17 | clean: 18 | rm -f $(ALL_T) *.exe 19 | rm -f render.png 20 | rm -f t2i.png 21 | gears: 22 | $(CC) gears.c $(LIB) -o gears $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) -lm 23 | t2i: 24 | $(CC) t2i.c $(LIB) -o t2i $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) -lm 25 | bigfont: 26 | $(CC) bigfont.c $(LIB) -o bigfont $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) -lm 27 | -------------------------------------------------------------------------------- /Raw_Demos/asciifractal.sh: -------------------------------------------------------------------------------- 1 | 2 | export CHAR=¡ 3 | echo -n $CHAR | ./bigfont $CHAR | ./bigfont $CHAR | ./bigfont $CHAR | ./t2i -col 0xff00 -ts 1 -w 10000 -h 10000 && xviewer t2i.png 4 | -------------------------------------------------------------------------------- /Raw_Demos/bigfont.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../include/GL/gl.h" 5 | #include "../src/font8x8_basic.h" 6 | #include "../include-demo/stringutil.h" 7 | 8 | char fillchar = '#'; 9 | void render(unsigned char *bitmap, int x) { 10 | int y; 11 | int set; 12 | for (y=0; y < 8; y++) { 13 | set = bitmap[x] & (1 << y); //despite the naming convention... x is actually the row # not the column #. X IS Y, Y IS X, got it? 14 | fputc(set ? fillchar : ' ', stdout); 15 | } 16 | } 17 | 18 | int main(int argc, char **argv) { 19 | if(argc > 1) fillchar = argv[1][0]; 20 | 21 | { 22 | unsigned long l; 23 | unsigned char* b = (unsigned char*)read_until_terminator_alloced(stdin, &l, '\n', 30); 24 | if(b) 25 | do { 26 | for(unsigned int x = 0; x < 8; x++){ //Despite the name, this is actually the row 27 | fputc('\n', stdout); 28 | for(unsigned int i = 0; b[i] != '\n' && b[i] != '\0'; i++){ 29 | unsigned char *bitmap = (unsigned char*)font8x8_basic[ b[i] ]; 30 | render(bitmap, x); 31 | } 32 | } 33 | //Walk b until the next \n or null terminator. 34 | free(b); 35 | b = (unsigned char*)read_until_terminator_alloced(stdin, &l, '\n', 30); 36 | } while(!feof(stdin) && b); 37 | if(b) free(b); 38 | } 39 | fputc('\n', stdout); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Raw_Demos/char.txt: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /Raw_Demos/gears_orig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/Raw_Demos/gears_orig.png -------------------------------------------------------------------------------- /Raw_Demos/t2i.c: -------------------------------------------------------------------------------- 1 | /* sdlGears.c */ 2 | /* 3 | * 3-D gear wheels by Brian Paul. This program is in the public domain. 4 | * 5 | * ported to libSDL/TinyGL by Gerald Franz (gfz@o2online.de) 6 | */ 7 | 8 | //#define PLAY_MUSIC 9 | 10 | //Only C standard library includes. 11 | //These are ALL the external dependencies of this program!!! ALL of them!!! 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | //Doesn't drag in anything. 20 | #include "../include/GL/gl.h" 21 | 22 | //Doesn't drag in anything. 23 | #include "../include/zbuffer.h" 24 | #define CHAD_MATH_IMPL 25 | 26 | //Drags in Math and String (which are already dragged in above.) 27 | #include "../include-demo/3dMath.h" 28 | 29 | //Requires 30 | /* 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | and 37 | #include 38 | if I didn't define STBIW_ASSERT 39 | */ 40 | #define STBIW_ASSERT(x) /* a comment */ 41 | #define STB_IMAGE_WRITE_IMPLEMENTATION 42 | #include "../include-demo/stb_image_write.h" 43 | #include "../include-demo/stringutil.h" 44 | 45 | typedef unsigned char uchar; 46 | int tsize = 1; 47 | unsigned int color = 0xFF0000; 48 | 49 | #ifndef M_PI 50 | #define M_PI 3.14159265 51 | #endif 52 | 53 | //PIXEL hugefb[1<<28]; //256 million pixels 54 | 55 | int main(int argc, char** argv) { 56 | // initialize SDL video: 57 | unsigned int winSizeX = 640; 58 | unsigned int winSizeY = 480; 59 | PIXEL* imbuf = NULL; 60 | uchar* pbuf = NULL; 61 | if (argc > 1) { 62 | char* larg = ""; 63 | for (int i = 1; i < argc; i++) { 64 | if (!strcmp(larg, "-w")) 65 | winSizeX = atoi(argv[i]); 66 | if (!strcmp(larg, "-h")) 67 | winSizeY = atoi(argv[i]); 68 | if (!strcmp(larg, "-ts")) 69 | tsize = atoi(argv[i]); 70 | if (!strcmp(larg, "-col")) 71 | color = strtoull(argv[i],0,16); 72 | larg = argv[i]; 73 | } 74 | } 75 | unsigned long lout; 76 | char* text = read_until_terminator_alloced(stdin, &lout, '\0', 2); 77 | imbuf = calloc(1,sizeof(PIXEL) * winSizeX * winSizeY); 78 | ZBuffer* frameBuffer = NULL; 79 | if(TGL_FEATURE_RENDER_BITS == 32) 80 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_RGBA, 0); 81 | else 82 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_5R6G5B,0); 83 | if(!frameBuffer){printf("\nZB_open failed!");exit(1);} 84 | glInit(frameBuffer); 85 | 86 | // initialize GL: 87 | //TESTING BLENDING... 88 | //glDisable(GL_DEPTH_TEST); 89 | 90 | 91 | // variables for timing: 92 | 93 | //unsigned int tLastFps = tNow; 94 | 95 | // main loop: 96 | //float test = 0; 97 | if(!text) return 1; 98 | { 99 | 100 | //Depending on SDL to give us ticks even without a window open... 101 | // test = TEST_fastInvSqrt(tNow); 102 | // printf("\n%f",test); 103 | // do event handling: 104 | 105 | // draw scene: 106 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 107 | glTextSize(tsize); 108 | glDrawText((unsigned char*)text, 0, 0, color); 109 | 110 | // swap buffers: 111 | // Quickly convert all pixels to the correct format 112 | 113 | ZB_copyFrameBuffer(frameBuffer, imbuf, winSizeX * sizeof(PIXEL)); 114 | } 115 | if(TGL_FEATURE_RENDER_BITS == 32){ //very little conversion. 116 | pbuf = malloc(3 * winSizeX * winSizeY); 117 | for(int i = 0; i < winSizeX * winSizeY; i++){ 118 | //pbuf[3*i+0] = (imbuf[i]&0xff0000)>>16; 119 | //pbuf[3*i+1] = (imbuf[i]&0x00ff00)>>8; 120 | //pbuf[3*i+2] = (imbuf[i]&0x0000ff); 121 | pbuf[3*i+0] = GET_RED(imbuf[i]); 122 | pbuf[3*i+1] = GET_GREEN(imbuf[i]); 123 | pbuf[3*i+2] = GET_BLUE(imbuf[i]); 124 | } 125 | stbi_write_png("t2i.png", winSizeX, winSizeY, 3, pbuf, 0); 126 | free(imbuf); 127 | free(pbuf); 128 | } else if(TGL_FEATURE_RENDER_BITS == 16){ 129 | //puts("\nTesting 16 bit rendering...\n"); 130 | pbuf = malloc(3 * winSizeX * winSizeY); 131 | for(int i = 0; i < winSizeX * winSizeY; i++){ 132 | pbuf[3*i+0] = GET_RED(imbuf[i]); 133 | pbuf[3*i+1] = GET_GREEN(imbuf[i]); 134 | pbuf[3*i+2] = GET_BLUE(imbuf[i]); 135 | } 136 | stbi_write_png("t2i.png", winSizeX, winSizeY, 3, pbuf, 0); 137 | free(imbuf); 138 | free(pbuf); 139 | } 140 | free(text); 141 | // cleanup: 142 | ZB_close(frameBuffer); 143 | glClose(); 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /SDL_Examples/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: MultiLine 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Attach 41 | BreakBeforeInheritanceComma: false 42 | BreakInheritanceList: BeforeColon 43 | BreakBeforeTernaryOperators: true 44 | BreakConstructorInitializersBeforeComma: false 45 | BreakConstructorInitializers: BeforeColon 46 | BreakAfterJavaFieldAnnotations: false 47 | BreakStringLiterals: true 48 | ColumnLimit: 160 49 | CommentPragmas: '^ IWYU pragma:' 50 | CompactNamespaces: false 51 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 52 | ConstructorInitializerIndentWidth: 4 53 | ContinuationIndentWidth: 4 54 | Cpp11BracedListStyle: true 55 | DerivePointerAlignment: false 56 | DisableFormat: false 57 | ExperimentalAutoDetectBinPacking: false 58 | FixNamespaceComments: true 59 | ForEachMacros: 60 | - foreach 61 | - Q_FOREACH 62 | - BOOST_FOREACH 63 | IncludeBlocks: Preserve 64 | IncludeCategories: 65 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 66 | Priority: 2 67 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 68 | Priority: 3 69 | - Regex: '.*' 70 | Priority: 1 71 | IncludeIsMainRegex: '(Test)?$' 72 | IndentCaseLabels: false 73 | IndentPPDirectives: None 74 | IndentWidth: 4 75 | IndentWrappedFunctionNames: false 76 | JavaScriptQuotes: Leave 77 | JavaScriptWrapImports: true 78 | KeepEmptyLinesAtTheStartOfBlocks: true 79 | MacroBlockBegin: '' 80 | MacroBlockEnd: '' 81 | MaxEmptyLinesToKeep: 1 82 | NamespaceIndentation: None 83 | ObjCBinPackProtocolList: Auto 84 | ObjCBlockIndentWidth: 4 85 | ObjCSpaceAfterProperty: false 86 | ObjCSpaceBeforeProtocolList: true 87 | PenaltyBreakAssignment: 2 88 | PenaltyBreakBeforeFirstCallParameter: 19 89 | PenaltyBreakComment: 300 90 | PenaltyBreakFirstLessLess: 120 91 | PenaltyBreakString: 1000 92 | PenaltyBreakTemplateDeclaration: 10 93 | PenaltyExcessCharacter: 1000000 94 | PenaltyReturnTypeOnItsOwnLine: 60 95 | PointerAlignment: Left 96 | ReflowComments: true 97 | SortIncludes: true 98 | SortUsingDeclarations: true 99 | SpaceAfterCStyleCast: false 100 | SpaceAfterTemplateKeyword: true 101 | SpaceBeforeAssignmentOperators: true 102 | SpaceBeforeCpp11BracedList: false 103 | SpaceBeforeCtorInitializerColon: true 104 | SpaceBeforeInheritanceColon: true 105 | SpaceBeforeParens: ControlStatements 106 | SpaceBeforeRangeBasedForLoopColon: true 107 | SpaceInEmptyParentheses: false 108 | SpacesBeforeTrailingComments: 1 109 | SpacesInAngles: false 110 | SpacesInContainerLiterals: true 111 | SpacesInCStyleCastParentheses: false 112 | SpacesInParentheses: false 113 | SpacesInSquareBrackets: false 114 | Standard: Cpp11 115 | TabWidth: 4 116 | UseTab: Always 117 | ... 118 | 119 | -------------------------------------------------------------------------------- /SDL_Examples/Arnepalette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/Arnepalette.png -------------------------------------------------------------------------------- /SDL_Examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(SDL QUIET) 2 | find_package(OpenMP QUIET) 3 | 4 | if(SDL_FOUND) 5 | 6 | if(TARGET tinygl) 7 | set(TINYGL_LIB tinygl) 8 | elseif(TARGET tinygl-static) 9 | set(TINYGL_LIB tinygl-static) 10 | endif() 11 | 12 | if (TINYGL_LIB) 13 | 14 | set(demo_names game gears helloworld menu model texture) 15 | foreach(DEMO ${demo_names}) 16 | set(DEMO_NAME "sdl_${DEMO}") 17 | add_executable(${DEMO_NAME} ${DEMO}.c) 18 | target_link_libraries(${DEMO_NAME} PRIVATE ${TINYGL_LIB} ${M_LIBRARY} ${SDL_LIBRARY}) 19 | target_include_directories(${DEMO_NAME} PUBLIC ${SDL_INCLUDE_DIR}) 20 | if(NOT MSVC) 21 | target_compile_options(${DEMO_NAME} PRIVATE -O3 -DNDEBUG -pedantic -Wall) 22 | if(NOT CMAKE_CROSSCOMPILING) 23 | target_compile_options(tinygl PRIVATE -march=native) 24 | endif(NOT CMAKE_CROSSCOMPILING) 25 | endif(NOT MSVC) 26 | if(OPENMP_C_FOUND) 27 | target_link_libraries(${DEMO_NAME} PRIVATE OpenMP::OpenMP_C) 28 | endif(OPENMP_C_FOUND) 29 | endforeach() 30 | 31 | set(TINYGL_RESOURCES 32 | Arnepalette.png 33 | WWGW.mp3 34 | extrude.obj 35 | monkey3.obj 36 | tex.jpg 37 | tex_hole.png 38 | tex_old.jpg 39 | texture.png 40 | ) 41 | foreach(FILE ${TINYGL_RESOURCES}) 42 | get_filename_component(FILE_NAME ${FILE} NAME) 43 | configure_file(${FILE} ${FILE_NAME} COPYONLY) 44 | endforeach() 45 | 46 | endif (TINYGL_LIB) 47 | 48 | else(SDL_FOUND) 49 | 50 | message(STATUS "tinygl: SDL not found") 51 | 52 | endif(SDL_FOUND) 53 | 54 | # Local Variables: 55 | # tab-width: 8 56 | # mode: cmake 57 | # indent-tabs-mode: t 58 | # End: 59 | # ex: shiftwidth=2 tabstop=8 60 | 61 | -------------------------------------------------------------------------------- /SDL_Examples/Makefile: -------------------------------------------------------------------------------- 1 | include ../config.mk 2 | #CC= gcc 3 | #CFLAGS = -g -Wall -O3 -w 4 | GL_LIBS= -L../ 5 | GL_INCLUDES= -I../include/ 6 | ALL_T= gears texture model helloworld menu game 7 | LIB= ../lib/libTinyGL.a 8 | 9 | #For GCC on good OSes: 10 | SDL_LIBS= -lSDL 11 | #for MinGW users: 12 | #SDL_LIBS= -lmingw32 -lSDLmain -lSDL 13 | BINDIR=/usr/local/bin 14 | 15 | SDL_MIXERLIBS= -lSDL_mixer -lmad -logg -lmikmod -logg -DPLAY_MUSIC 16 | SDL_MIXERLIBS= 17 | all: $(ALL_T) 18 | clean: 19 | rm -f $(ALL_T) *.exe 20 | texture: 21 | $(CC) texture.c $(LIB) -o texture $(GL_INCLUDES) $(SDL_LIBS) $(SDL_MIXERLIBS) $(GL_LIBS) $(CFLAGS) -lm 22 | menu: 23 | $(CC) menu.c $(LIB) -o menu $(GL_INCLUDES) $(SDL_LIBS) $(SDL_MIXERLIBS) $(GL_LIBS) $(CFLAGS) -lm 24 | helloworld: 25 | $(CC) helloworld.c $(LIB) -o helloworld $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) $(SDL_LIBS) $(SDL_MIXERLIBS) -lm 26 | model: 27 | $(CC) model.c $(LIB) -o model $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) $(SDL_LIBS) $(SDL_MIXERLIBS) -lm 28 | game: 29 | $(CC) game.c $(LIB) -o game $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) $(SDL_LIBS) $(SDL_MIXERLIBS) -lm 30 | gears: 31 | $(CC) gears.c $(LIB) -o gears $(GL_INCLUDES) $(GL_LIBS) $(CFLAGS) $(SDL_LIBS) $(SDL_MIXERLIBS) -lm 32 | 33 | install_tglgears: gears 34 | cp gears $(BINDIR)/tglgears 35 | -------------------------------------------------------------------------------- /SDL_Examples/WWGW.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/WWGW.mp3 -------------------------------------------------------------------------------- /SDL_Examples/code_format.sh: -------------------------------------------------------------------------------- 1 | clang-format-8 -i *.c --style=file 2 | -------------------------------------------------------------------------------- /SDL_Examples/helloworld.c: -------------------------------------------------------------------------------- 1 | //#define PLAY_MUSIC 2 | 3 | #include "../include/GL/gl.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | //#include 9 | #include "../include/GL/gl.h" 10 | 11 | #include "../include/zbuffer.h" 12 | #define CHAD_API_IMPL 13 | #define CHAD_MATH_IMPL 14 | #include "../include-demo/3dMath.h" 15 | #ifdef PLAY_MUSIC 16 | #include "../include-demo/api_audio.h" 17 | #else 18 | typedef unsigned char uchar; 19 | #endif 20 | #include 21 | int noSDL = 0; 22 | int do2 = 0; 23 | #ifndef M_PI 24 | #define M_PI 3.14159265 25 | #endif 26 | 27 | GLuint tex = 0; 28 | double time_passed = 0.0; 29 | int winSizeX = 640; 30 | int winSizeY = 480; 31 | 32 | void draw() { 33 | // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 34 | // glEnable(GL_TEXTURE_2D); 35 | // glBindTexture(GL_TEXTURE_2D,tex); 36 | // time_passed += 0.0166666; 37 | glMatrixMode(GL_MODELVIEW); 38 | glLoadIdentity(); 39 | glPushMatrix(); 40 | glRotatef(time_passed, 0, 0, 1); 41 | glBegin(GL_TRIANGLES); 42 | glColor3f(0.2, 0.2, 1.0); // BLUE! 43 | // glColor3f(1.0, 0.2, 0.2); //RED! 44 | glVertex3f(-0.8, -0.8, 0.2); 45 | 46 | glColor3f(0.2, 1.0, 0.2); // GREEN! 47 | // glColor3f(1.0, 0.2, 0.2); //RED! 48 | glVertex3f(0.8, -0.8, 0.2); 49 | 50 | glColor3f(1.0, 0.2, 0.2); // RED! 51 | glVertex3f(0, 1.2, 0.2); 52 | glEnd(); 53 | glPopMatrix(); 54 | } 55 | 56 | void draw2() { 57 | // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 58 | int x = 0; 59 | // Select and setup the projection matrix 60 | glMatrixMode(GL_PROJECTION); 61 | glLoadIdentity(); 62 | mat4 m = perspective(65.0f, (GLfloat)winSizeX / (GLfloat)winSizeY, 1.0f, 100.0f); 63 | glLoadMatrixf(m.d); 64 | // GLfloat h = (GLfloat) winSizeY / (GLfloat) winSizeX; 65 | // glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 ); 66 | // Select and setup the modelview matrix 67 | glMatrixMode(GL_MODELVIEW); 68 | glLoadIdentity(); 69 | glRotatef(-90, 1, 0, 0); 70 | glTranslatef(0, 0, -1.0f); 71 | 72 | // Draw a rotating colorful triangle 73 | glTranslatef(0.0f, 14.0f, 0.0f); 74 | glRotatef(0.3f * (GLfloat)x + (GLfloat)time_passed * 100.0f, 0.0f, 0.0f, 1.0f); 75 | glBegin(GL_TRIANGLES); 76 | glColor4f(1.0f, 0.01f, 0.01f, 0.0f); 77 | glVertex3f(-5.0f, 0.0f, -4.0f); 78 | glColor4f(0.01f, 1.0f, 0.01f, 0.0f); 79 | glVertex3f(5.0f, 0.0f, -4.0f); 80 | glColor4f(0.01f, 0.01f, 1.0f, 0.0f); 81 | glVertex3f(0.0f, 0.0f, 6.0f); 82 | glEnd(); 83 | } 84 | 85 | void initScene() { 86 | 87 | // glLightfv( GL_LIGHT0, GL_AMBIENT, white); 88 | // glLightfv( GL_LIGHT0, GL_SPECULAR, white); 89 | // glEnable( GL_CULL_FACE ); 90 | glDisable(GL_CULL_FACE); 91 | glEnable(GL_LIGHTING); 92 | glDisable(GL_TEXTURE_2D); 93 | glDisable(GL_LIGHTING); 94 | // glEnable( GL_LIGHT0 ); 95 | glEnable(GL_DEPTH_TEST); 96 | glShadeModel(GL_SMOOTH); 97 | glTextSize(GL_TEXT_SIZE24x24); 98 | /* 99 | { 100 | int sw = 0, sh = 0, sc = 0; //sc goes unused. 101 | uchar* source_data = stbi_load("texture.png", &sw, &sh, &sc, 3); 102 | if(source_data){ 103 | tex = loadRGBTexture(source_data, sw, sh); 104 | free(source_data); 105 | } else { 106 | printf("\nCan't load texture!\n"); 107 | } 108 | }*/ 109 | glEnable(GL_NORMALIZE); 110 | } 111 | 112 | int main(int argc, char** argv) { 113 | // initialize SDL video: 114 | 115 | unsigned int fps = 0; 116 | char needsRGBAFix = 0; 117 | if (argc > 1) { 118 | char* larg = argv[1]; 119 | for (int i = 0; i < argc; i++) { 120 | if (!strcmp(larg, "-w")) 121 | winSizeX = atoi(argv[i]); 122 | if (!strcmp(larg, "-h")) 123 | winSizeY = atoi(argv[i]); 124 | if (!strcmp(larg, "-fps")) 125 | fps = strtoull(argv[i], 0, 10); 126 | if (!strcmp(argv[i], "-nosdl")) 127 | noSDL = 1; 128 | if (!strcmp(argv[i], "-2")) 129 | do2 = 1; 130 | larg = argv[i]; 131 | } 132 | } 133 | if (!noSDL) { 134 | #ifdef PLAY_MUSIC 135 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { 136 | #else 137 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 138 | #endif 139 | fprintf(stderr, "ERROR: cannot initialize SDL video.\n"); 140 | return 1; 141 | } 142 | } else if (SDL_Init(0) < 0) 143 | fprintf(stderr, "ERROR: cannot initialize SDL without video.\n"); 144 | #ifdef PLAY_MUSIC 145 | if (!noSDL) 146 | ainit(0); 147 | #endif 148 | SDL_Surface* screen = NULL; 149 | if (!noSDL) 150 | if ((screen = SDL_SetVideoMode(winSizeX, winSizeY, TGL_FEATURE_RENDER_BITS, SDL_SWSURFACE)) == 0) { 151 | fprintf(stderr, "ERROR: Video mode set failed.\n"); 152 | return 1; 153 | } 154 | if (!noSDL) { 155 | printf("\nRMASK IS %u", screen->format->Rmask); 156 | printf("\nGMASK IS %u", screen->format->Gmask); 157 | printf("\nBMASK IS %u", screen->format->Bmask); 158 | printf("\nAMASK IS %u", screen->format->Amask); 159 | } 160 | #if TGL_FEATURE_RENDER_BITS == 32 161 | if (!noSDL) 162 | if (screen->format->Rmask != 0x00FF0000 || screen->format->Gmask != 0x0000FF00 || screen->format->Bmask != 0x000000FF) { 163 | needsRGBAFix = 1; 164 | printf("\nYour screen is using an RGBA output different than this library expects."); 165 | printf("\nYou should consider using the 16 bit version for optimal performance"); 166 | } 167 | #endif 168 | if (!noSDL) { 169 | printf("\nRSHIFT IS %u", screen->format->Rshift); 170 | printf("\nGSHIFT IS %u", screen->format->Gshift); 171 | printf("\nBSHIFT IS %u", screen->format->Bshift); 172 | printf("\nASHIFT IS %u\n", screen->format->Ashift); 173 | } 174 | fflush(stdout); 175 | #ifdef PLAY_MUSIC 176 | track* myTrack = NULL; 177 | if (!noSDL) 178 | myTrack = lmus("WWGW.mp3"); 179 | if (!noSDL) 180 | mplay(myTrack, -1, 1000); 181 | #endif 182 | if (!noSDL) 183 | SDL_ShowCursor(SDL_DISABLE); 184 | if (!noSDL) 185 | SDL_WM_SetCaption(argv[0], 0); 186 | 187 | // initialize TinyGL: 188 | // unsigned int pitch; 189 | int mode; 190 | if (!noSDL) 191 | switch (screen->format->BitsPerPixel) { 192 | case 8: 193 | fprintf(stderr, "ERROR: Palettes are currently not supported.\n"); 194 | fprintf(stderr, "\nUnsupported by maintainer!!!"); 195 | return 1; 196 | case 16: 197 | 198 | // fprintf(stderr,"\nUnsupported by maintainer!!!"); 199 | mode = ZB_MODE_5R6G5B; 200 | // return 1; 201 | break; 202 | case 24: 203 | 204 | fprintf(stderr, "\nUnsupported by maintainer!!!"); 205 | mode = ZB_MODE_RGB24; 206 | return 1; 207 | break; 208 | case 32: 209 | 210 | mode = ZB_MODE_RGBA; 211 | break; 212 | default: 213 | return 1; 214 | break; 215 | } 216 | ZBuffer* frameBuffer = NULL; 217 | if (TGL_FEATURE_RENDER_BITS == 32) 218 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_RGBA, 0); 219 | else 220 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_5R6G5B, 0); 221 | glInit(frameBuffer); 222 | 223 | // initialize GL: 224 | glClearColor(0.0, 0.0, 0.0, 0.0); 225 | glViewport(0, 0, winSizeX, winSizeY); 226 | glEnable(GL_DEPTH_TEST); 227 | // GLfloat h = (GLfloat) winSizeY / (GLfloat) winSizeX; 228 | glMatrixMode(GL_PROJECTION); 229 | glLoadIdentity(); 230 | // glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 ); 231 | glMatrixMode(GL_MODELVIEW); 232 | glLoadIdentity(); 233 | // glTranslatef( 0.0, 0.0, -45.0 ); 234 | 235 | initScene(); 236 | 237 | // variables for timing: 238 | unsigned int frames = 0; 239 | unsigned int tNow = SDL_GetTicks(); 240 | unsigned int tLastFps = tNow; 241 | 242 | // main loop: 243 | int isRunning = 1; 244 | while (isRunning) { 245 | ++frames; 246 | tNow = SDL_GetTicks(); 247 | time_passed += 0.01666666; 248 | // do event handling: 249 | SDL_Event evt; 250 | while (SDL_PollEvent(&evt)) 251 | switch (evt.type) { 252 | case SDL_KEYDOWN: 253 | switch (evt.key.keysym.sym) { 254 | case SDLK_ESCAPE: 255 | case SDLK_q: 256 | isRunning = 0; 257 | default: 258 | break; 259 | } 260 | break; 261 | case SDL_QUIT: 262 | isRunning = 0; 263 | break; 264 | } 265 | 266 | // draw scene: 267 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 268 | if (do2) 269 | draw2(); 270 | else 271 | draw(); 272 | glDrawText((unsigned char*)"Hello World!\nFrom TinyGL", 0, 0, 0x00FFFFFF); 273 | // swap buffers: 274 | if (!noSDL) 275 | if (SDL_MUSTLOCK(screen) && (SDL_LockSurface(screen) < 0)) { 276 | fprintf(stderr, "SDL ERROR: Can't lock screen: %s\n", SDL_GetError()); 277 | return 1; 278 | } 279 | /* 280 | printf("\nRMASK IS %u",screen->format->Rmask); 281 | printf("\nGMASK IS %u",screen->format->Gmask); 282 | printf("\nBMASK IS %u",screen->format->Bmask); 283 | printf("\nAMASK IS %u",screen->format->Amask); 284 | */ 285 | // Quickly convert all pixels to the correct format 286 | #if TGL_FEATURE_RENDER_BITS == 32 287 | if (needsRGBAFix) 288 | for (int i = 0; i < frameBuffer->xsize * frameBuffer->ysize; i++) { 289 | #define DATONE (frameBuffer->pbuf[i]) 290 | DATONE = ((DATONE & 0x000000FF)) << screen->format->Rshift | ((DATONE & 0x0000FF00) >> 8) << screen->format->Gshift | 291 | ((DATONE & 0x00FF0000) >> 16) << screen->format->Bshift; 292 | } 293 | #endif 294 | if (!noSDL) 295 | ZB_copyFrameBuffer(frameBuffer, screen->pixels, screen->pitch); 296 | if (!noSDL) 297 | if (SDL_MUSTLOCK(screen)) 298 | SDL_UnlockSurface(screen); 299 | if (!noSDL) 300 | SDL_Flip(screen); 301 | if (!noSDL) 302 | if (fps > 0) 303 | if ((1000 / fps) > (SDL_GetTicks() - tNow)) { 304 | SDL_Delay((1000 / fps) - (SDL_GetTicks() - tNow)); // Yay stable framerate! 305 | } 306 | // check for error conditions: 307 | { 308 | char* sdl_error = SDL_GetError(); 309 | if (sdl_error[0] != '\0') { 310 | fprintf(stderr, "SDL ERROR: \"%s\"\n", sdl_error); 311 | SDL_ClearError(); 312 | } 313 | } 314 | // update fps: 315 | if (tNow >= tLastFps + 5000) { 316 | printf("%i frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f, 317 | (float)frames * 1000.0f / (float)(tNow - tLastFps)); 318 | tLastFps = tNow; 319 | frames = 0; 320 | } 321 | } 322 | printf("%i frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f, (float)frames * 1000.0f / (float)(tNow - tLastFps)); 323 | // cleanup: 324 | ZB_close(frameBuffer); 325 | glClose(); 326 | if (!noSDL) 327 | if (SDL_WasInit(SDL_INIT_VIDEO)) 328 | SDL_QuitSubSystem(SDL_INIT_VIDEO); 329 | #ifdef PLAY_MUSIC 330 | if (!noSDL) 331 | mhalt(); 332 | if (!noSDL) 333 | Mix_FreeMusic(myTrack); 334 | if (!noSDL) 335 | acleanup(); 336 | #endif 337 | SDL_Quit(); 338 | return 0; 339 | } 340 | -------------------------------------------------------------------------------- /SDL_Examples/quick.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | #escape character is used here to add a slash 3 | #This script was used to move these files to include. 4 | #sed -i 's/\"zbuffer.h/\"include\/zbuffer.h/g' *.c *.h 5 | #sed -i 's/\"zfeatures.h/\"include\/zfeatures.h/g' *.c *.h 6 | #sed -i 's/unsigned int/GLuint/g' *.c *.h 7 | #sed -i 's/float/GLfloat/g' *.c *.h 8 | #sed -i 's/char/GLbyte/g' *.c *.h 9 | #sed -i 's/unsigned GLbyte/GLubyte/g' *.c *.h 10 | #sed -i 's/ int/ GLint/g' *.c *.h 11 | #sed -i 's/unsigned GLshort/GLushort/g' *.c *.h 12 | sed -i 's/\~0xAA/0x55/g' *.c 13 | 14 | #gcc *.c -o executable.out -lglut -lGL -lm -lGLU 15 | -------------------------------------------------------------------------------- /SDL_Examples/stdout.txt: -------------------------------------------------------------------------------- 1 | 2 | RMASK IS 16711680 3 | GMASK IS 65280 4 | BMASK IS 255 5 | AMASK IS 0 6 | RSHIFT IS 16 7 | GSHIFT IS 8 8 | BSHIFT IS 0 9 | ASHIFT IS 0 10 | 11 | Version string: 12 | 1.0 TinyGLv1.0 Compiled using GCC 12.2.0 13 | Vendor string: 14 | Fabrice Bellard, Gek, and the C-Chads 15 | Renderer string: 16 | TinyGL 17 | Extensions string: 18 | TGL_TEXTURE TGL_SMOOTHSHADING TGL_LIGHTING TGL_OPTIMIZATION_HINT_BRANCH_COST=2 TGL_FEATURE_ARRAYS TGL_FEATURE_DISPLAYLISTS TGL_FEATURE_OPTIMIZED_TEXTURE_ACCESS TGL_FEATURE_TEXTURE_POW2=8 TGL_FEATURE_LIT_TEXTURES TGL_FEATURE_BLEND TGL_FEATURE_32_BITS TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST TGL_FEATURE_MULTI_THREADED TGL_FEATURE_MULTI_THREADED_POST_PROCESS TGL_FEATURE_MULTITHREADED_DRAWPIXELS TGL_FEATURE_MULTITHREADED_COPY_TEXIMAGE_2D TGL_BUFFER_EXT TGL_SOFTWARE_ACCELERATED 19 | License string: 20 | Copyright notice: 21 | 22 | (C) 1997-2021 Fabrice Bellard, Gek (DMHSW), C-Chads 23 | 24 | This software is provided 'as-is', without any express or implied 25 | warranty. In no event will the authors be held liable for any damages 26 | arising from the use of this software. 27 | 28 | Permission is granted to anyone to use this software for any purpose, 29 | including commercial applications, and to alter it and redistribute it 30 | freely, subject to the following restrictions: 31 | 32 | 1. The origin of this software must not be misrepresented; you must not 33 | claim that you wrote the original software. If you use this software 34 | in a product, an acknowledgment in the product and its documentation 35 | *is* required. 36 | 2. Altered source versions must be plainly marked as such, and must not be 37 | misrepresented as being the original software. 38 | 3. This notice may not be removed or altered from any source distribution. 39 | 40 | If you redistribute modified sources, I would appreciate that you 41 | include in the files history information documenting your changes.99 frames in 5.010000 secs, 19.760479 frames per second. 42 | 25 frames in 1.275000 secs, 19.607843 frames per second. 43 | -------------------------------------------------------------------------------- /SDL_Examples/tex.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/tex.jpg -------------------------------------------------------------------------------- /SDL_Examples/tex_hole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/tex_hole.png -------------------------------------------------------------------------------- /SDL_Examples/tex_old.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/tex_old.jpg -------------------------------------------------------------------------------- /SDL_Examples/texture.c: -------------------------------------------------------------------------------- 1 | /* texture.c */ 2 | /* 3 | * Texture test written by Gek 4 | * 5 | */ 6 | //#define PLAY_MUSIC 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../include/GL/gl.h" 14 | 15 | #include "../include/zbuffer.h" 16 | #define CHAD_API_IMPL 17 | #define CHAD_MATH_IMPL 18 | #include "../include-demo/3dMath.h" 19 | #ifdef PLAY_MUSIC 20 | #include "../include-demo/api_audio.h" 21 | #else 22 | typedef unsigned char uchar; 23 | #endif 24 | #define STB_IMAGE_IMPLEMENTATION 25 | #include "../include-demo/stb_image.h" 26 | #include 27 | int noSDL = 0; 28 | int doPostProcess = 0; 29 | 30 | #include 31 | #ifndef M_PI 32 | #define M_PI 3.14159265 33 | #endif 34 | 35 | GLuint tex = 0; 36 | GLuint tex2 = 0; 37 | GLuint do1D = 0; 38 | GLint Row1D = 30; 39 | GLint dorect = 0; 40 | GLfloat texture_mult = 1.0; 41 | GLuint loadRGBTexture(unsigned char* buf, unsigned int w, unsigned int h) { 42 | GLuint t = 0; 43 | glGenTextures(1, &t); 44 | // for(unsigned int i = 0; i < w * h; i++) 45 | // { 46 | // unsigned char t = 0; 47 | // unsigned char* r = buf + i*3; 48 | // // unsigned char* g = buf + i*3+1; 49 | // unsigned char* b = buf + i*3+2; 50 | // t = *r; 51 | // *r = *b; 52 | // *b = t; 53 | // } 54 | glBindTexture(GL_TEXTURE_2D, t); 55 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 56 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 57 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 58 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 59 | if (!do1D) 60 | glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf); 61 | else 62 | glTexImage1D(GL_TEXTURE_1D, 0, 3, w, 0, GL_RGB, GL_UNSIGNED_BYTE, buf + Row1D * w * 3); 63 | return t; 64 | } 65 | 66 | GLuint postProcessingStep(GLint x, GLint y, GLuint pixel, GLushort z) { 67 | #if TGL_FEATURE_RENDER_BITS == 32 68 | // 32 bit pixel 69 | return pixel & 0x8F8F8F; // Half color mode. 70 | #else 71 | // 16 bit mode 72 | return pixel & (63 << 5); // Solid green 73 | #endif 74 | } 75 | 76 | void draw() { 77 | glClearColor(0.0, 0.0, 0.0, 0.0); 78 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 79 | glEnable(GL_TEXTURE_2D); 80 | glBindTexture(GL_TEXTURE_2D, tex); 81 | 82 | if (dorect) 83 | glColor3f(1.0, 1.0, 1.0); 84 | glBegin(GL_TRIANGLES); 85 | // TRIANGLE 1, 86 | glTexCoord2f(0, 0); 87 | glVertex3f(-1, -1, 0.5); 88 | 89 | glTexCoord2f(1 * texture_mult, -1 * texture_mult); 90 | glVertex3f(1, 1, 0.5); 91 | 92 | glTexCoord2f(0, -1 * texture_mult); 93 | glVertex3f(-1, 1, 0.5); 94 | // TRIANGLE 2 95 | glTexCoord2f(0, 0); 96 | glVertex3f(-1, -1, 0.5); 97 | 98 | glTexCoord2f(1 * texture_mult, 0); 99 | glVertex3f(1, -1, 0.5); 100 | 101 | glTexCoord2f(1 * texture_mult, -1 * texture_mult); 102 | glVertex3f(1, 1, 0.5); 103 | glEnd(); 104 | if (dorect) { 105 | // glDisable(GL_DEPTH_TEST);glDepthMask(GL_FALSE); 106 | glDisable(GL_TEXTURE_2D); 107 | glColor3f(1.0, 0, 0); 108 | glRectf(0, 0, 1, 1); 109 | // glEnable(GL_DEPTH_TEST);glDepthMask(GL_TRUE); 110 | } 111 | if (doPostProcess) 112 | glPostProcess(postProcessingStep); // do a post processing step on the rendered geometry. 113 | } 114 | 115 | void initScene() { 116 | 117 | glEnable(GL_CULL_FACE); 118 | // glDisable( GL_CULL_FACE ); 119 | glDisable(GL_BLEND); 120 | // glEnable(GL_LIGHTING); 121 | glEnable(GL_TEXTURE_2D); 122 | glDisable(GL_LIGHTING); 123 | // glEnable( GL_LIGHT0 ); 124 | glEnable(GL_DEPTH_TEST); 125 | glShadeModel(GL_SMOOTH); 126 | glTextSize(GL_TEXT_SIZE24x24); 127 | { 128 | int sw = 0, sh = 0, sc = 0; // sc goes unused. 129 | uchar* source_data = stbi_load("texture.png", &sw, &sh, &sc, 3); 130 | if (source_data) { 131 | tex = loadRGBTexture(source_data, sw, sh); 132 | free(source_data); 133 | } else { 134 | printf("\nCan't load texture!\n"); 135 | } 136 | } 137 | { 138 | int sw = 0, sh = 0, sc = 0; // sc goes unused. 139 | uchar* source_data = stbi_load("tex.jpg", &sw, &sh, &sc, 3); 140 | if (source_data) { 141 | tex2 = loadRGBTexture(source_data, sw, sh); 142 | free(source_data); 143 | } else { 144 | printf("\nCan't load texture!\n"); 145 | } 146 | } 147 | glEnable(GL_NORMALIZE); 148 | } 149 | 150 | int main(int argc, char** argv) { 151 | // initialize SDL video: 152 | int winSizeX = 640; 153 | int winSizeY = 480; 154 | unsigned int fps = 0; 155 | char needsRGBAFix = 0; 156 | if (argc > 1) { 157 | char* larg = argv[1]; 158 | for (int i = 0; i < argc; i++) { 159 | if (!strcmp(argv[i], "-pp")) 160 | doPostProcess = 1; 161 | if (!strcmp(argv[i], "-rect")) 162 | dorect = 1; 163 | if (!strcmp(larg, "-w")) 164 | winSizeX = atoi(argv[i]); 165 | if (!strcmp(larg, "-h")) 166 | winSizeY = atoi(argv[i]); 167 | if (!strcmp(larg, "-fps")) 168 | fps = strtoull(argv[i], 0, 10); 169 | if (!strcmp(larg, "-texscale")) 170 | texture_mult = atof(argv[i]); 171 | if (!strcmp(larg, "-1D")) { 172 | do1D = 1; 173 | Row1D = atoi(argv[i]); 174 | } 175 | larg = argv[i]; 176 | } 177 | } 178 | #ifdef PLAY_MUSIC 179 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { 180 | #else 181 | if (SDL_Init(SDL_INIT_VIDEO) < 0) { 182 | #endif 183 | fprintf(stderr, "ERROR: cannot initialize SDL video.\n"); 184 | return 1; 185 | } 186 | #ifdef PLAY_MUSIC 187 | ainit(0); 188 | #endif 189 | SDL_Surface* screen = NULL; 190 | if ((screen = SDL_SetVideoMode(winSizeX, winSizeY, TGL_FEATURE_RENDER_BITS, SDL_SWSURFACE)) == 0) { 191 | fprintf(stderr, "ERROR: Video mode set failed.\n"); 192 | return 1; 193 | } 194 | printf("\nRMASK IS %u", screen->format->Rmask); 195 | printf("\nGMASK IS %u", screen->format->Gmask); 196 | printf("\nBMASK IS %u", screen->format->Bmask); 197 | printf("\nAMASK IS %u", screen->format->Amask); 198 | #if TGL_FEATURE_RENDER_BITS == 32 199 | if (screen->format->Rmask != 0x00FF0000 || screen->format->Gmask != 0x0000FF00 || screen->format->Bmask != 0x000000FF) { 200 | needsRGBAFix = 1; 201 | printf("\nYour screen is using an RGBA output different than this library expects."); 202 | printf("\nYou should consider using the 16 bit version for optimal performance"); 203 | } 204 | #endif 205 | 206 | printf("\nRSHIFT IS %u", screen->format->Rshift); 207 | printf("\nGSHIFT IS %u", screen->format->Gshift); 208 | printf("\nBSHIFT IS %u", screen->format->Bshift); 209 | printf("\nASHIFT IS %u\n", screen->format->Ashift); 210 | fflush(stdout); 211 | 212 | #ifdef PLAY_MUSIC 213 | track* myTrack = NULL; 214 | myTrack = lmus("WWGW.mp3"); 215 | mplay(myTrack, -1, 1000); 216 | #endif 217 | SDL_ShowCursor(SDL_DISABLE); 218 | SDL_WM_SetCaption(argv[0], 0); 219 | 220 | // initialize TinyGL: 221 | 222 | switch (screen->format->BitsPerPixel) { 223 | case 16: 224 | 225 | // fprintf(stderr,"\nUnsupported by maintainer!!!"); 226 | 227 | // return 1; 228 | break; 229 | case 32: 230 | break; 231 | default: 232 | return 1; 233 | break; 234 | } 235 | ZBuffer* frameBuffer = NULL; 236 | if (TGL_FEATURE_RENDER_BITS == 32) 237 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_RGBA, 0); 238 | else 239 | frameBuffer = ZB_open(winSizeX, winSizeY, ZB_MODE_5R6G5B, 0); 240 | glInit(frameBuffer); 241 | 242 | // initialize GL: 243 | glClearColor(0.0, 0.0, 0.0, 0.0); 244 | glViewport(0, 0, winSizeX, winSizeY); 245 | glEnable(GL_DEPTH_TEST); 246 | // GLfloat h = (GLfloat) winSizeY / (GLfloat) winSizeX; 247 | glMatrixMode(GL_PROJECTION); 248 | glLoadIdentity(); 249 | // glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 ); 250 | glMatrixMode(GL_MODELVIEW); 251 | glLoadIdentity(); 252 | // glTranslatef( 0.0, 0.0, -45.0 ); 253 | 254 | initScene(); 255 | 256 | // variables for timing: 257 | unsigned int frames = 0; 258 | unsigned int tNow = SDL_GetTicks(); 259 | unsigned int tLastFps = tNow; 260 | unsigned int frames_notreset = 0; 261 | // main loop: 262 | int isRunning = 1; 263 | while (isRunning) { 264 | ++frames; 265 | frames_notreset++; 266 | tNow = SDL_GetTicks(); 267 | // do event handling: 268 | SDL_Event evt; 269 | while (SDL_PollEvent(&evt)) 270 | switch (evt.type) { 271 | case SDL_KEYDOWN: 272 | switch (evt.key.keysym.sym) { 273 | break; 274 | case SDLK_ESCAPE: 275 | case SDLK_q: 276 | isRunning = 0; 277 | default: 278 | break; 279 | } 280 | break; 281 | case SDL_QUIT: 282 | isRunning = 0; 283 | break; 284 | } 285 | 286 | // draw scene: 287 | 288 | draw(); 289 | glDrawText((unsigned char*)"\nBlitting text\nto the screen!", 0, 0, 0x000000FF); 290 | glPixelZoom(2.0, 0.7); 291 | glRasterPos3f(0, -1, fabs(sinf(frames_notreset / 200.0))); 292 | { 293 | GLint xsize, ysize; 294 | void* data = glGetTexturePixmap(tex2, 0, &xsize, &ysize); 295 | // for(int i = 0; i < winSizeX; i++) 296 | // for(int j = 0; j < winSizeY; j++){ 297 | // glPlotPixel(i,j,rand() & 0xFFFFFF); 298 | //} 299 | if (data) 300 | glDrawPixels(xsize, ysize, GL_RGB, (TGL_FEATURE_RENDER_BITS == 32) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, data); 301 | } 302 | // swap buffers: 303 | if (SDL_MUSTLOCK(screen) && (SDL_LockSurface(screen) < 0)) { 304 | fprintf(stderr, "SDL ERROR: Can't lock screen: %s\n", SDL_GetError()); 305 | return 1; 306 | } 307 | /* 308 | printf("\nRMASK IS %u",screen->format->Rmask); 309 | printf("\nGMASK IS %u",screen->format->Gmask); 310 | printf("\nBMASK IS %u",screen->format->Bmask); 311 | printf("\nAMASK IS %u",screen->format->Amask); 312 | */ 313 | // Quickly convert all pixels to the correct format 314 | #if TGL_FEATURE_RENDER_BITS == 32 315 | if (needsRGBAFix) 316 | for (int i = 0; i < frameBuffer->xsize * frameBuffer->ysize; i++) { 317 | #define DATONE (frameBuffer->pbuf[i]) 318 | DATONE = ((DATONE & 0x000000FF)) << screen->format->Rshift | ((DATONE & 0x0000FF00) >> 8) << screen->format->Gshift | 319 | ((DATONE & 0x00FF0000) >> 16) << screen->format->Bshift; 320 | } 321 | #endif 322 | ZB_copyFrameBuffer(frameBuffer, screen->pixels, screen->pitch); 323 | if (SDL_MUSTLOCK(screen)) 324 | SDL_UnlockSurface(screen); 325 | SDL_Flip(screen); 326 | if (fps > 0) 327 | if ((1000 / fps) > (SDL_GetTicks() - tNow)) { 328 | SDL_Delay((1000 / fps) - (SDL_GetTicks() - tNow)); // Yay stable framerate! 329 | } 330 | // check for error conditions: 331 | char* sdl_error = SDL_GetError(); 332 | if (sdl_error[0] != '\0') { 333 | fprintf(stderr, "SDL ERROR: \"%s\"\n", sdl_error); 334 | SDL_ClearError(); 335 | } 336 | // update fps: 337 | if (tNow >= tLastFps + 5000) { 338 | printf("%i frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f, 339 | (float)frames * 1000.0f / (float)(tNow - tLastFps)); 340 | tLastFps = tNow; 341 | frames = 0; 342 | } 343 | } 344 | printf("%i frames in %f secs, %f frames per second.\n", frames, (float)(tNow - tLastFps) * 0.001f, (float)frames * 1000.0f / (float)(tNow - tLastFps)); 345 | // cleanup: 346 | ZB_close(frameBuffer); 347 | glClose(); 348 | if (SDL_WasInit(SDL_INIT_VIDEO)) 349 | SDL_QuitSubSystem(SDL_INIT_VIDEO); 350 | #ifdef PLAY_MUSIC 351 | mhalt(); 352 | Mix_FreeMusic(myTrack); 353 | acleanup(); 354 | #endif 355 | SDL_Quit(); 356 | return 0; 357 | } 358 | -------------------------------------------------------------------------------- /SDL_Examples/texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/SDL_Examples/texture.png -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # C compiler 3 | 4 | #CC= clang 5 | #CC=cc 6 | CC=gcc 7 | #CC=tcc 8 | #uncomment the following line for compiling the lib using tinyc. 9 | #note that the demos will fail to build with tinyc, but you can 10 | #-link- to tinygl built with tinyc using gcc. 11 | #CC= tcc 12 | #CFLAGS= -Wall -w -O3 -g -std=c99 -mtune=native -DNDEBUG 13 | #CFLAGS= -Wall -w -O3 -g -std=c99 -march=native -DNDEBUG 14 | 15 | #extract the maximum possible performance from gcc. 16 | 17 | 18 | #CFLAGS= -Wall -O3 -std=c99 -DNDEBUG -march=native -Wno-unused-function 19 | CFLAGS= -Wall -O3 -std=c99 -DNDEBUG -march=native -fopenmp -Wno-unused-function 20 | #CFLAGS_LIB= -Wall -O3 -std=c99 -pedantic -DNDEBUG -march=native -Wno-unused-function 21 | CFLAGS_LIB= -Wall -O3 -std=c99 -pedantic -DNDEBUG -fopenmp -march=native -Wno-unused-function 22 | 23 | 24 | #CFLAGS= -Wall -Ofast -std=gnu99 -DNDEBUG -mtune=native 25 | #uncomment the following line for compiling the lib with tinyc 26 | #keep these flags for compiling with gcc if you are linking with tinygl compiled with tcc. 27 | #CFLAGS= -Wall -O3 -std=gnu99 -DNDEBUG -g 28 | #CFLAGS= -Wall -O1 -g -std=c99 -Wno-undef -DNDEBUG 29 | LFLAGS= 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /doc/blend.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/blend.gif -------------------------------------------------------------------------------- /doc/capture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/capture.gif -------------------------------------------------------------------------------- /doc/capture2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/capture2.gif -------------------------------------------------------------------------------- /doc/helloworld.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/helloworld.gif -------------------------------------------------------------------------------- /doc/menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/menu.gif -------------------------------------------------------------------------------- /doc/model.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/model.gif -------------------------------------------------------------------------------- /doc/model2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/model2.gif -------------------------------------------------------------------------------- /doc/model2_lit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/model2_lit.gif -------------------------------------------------------------------------------- /doc/model_hole.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/model_hole.gif -------------------------------------------------------------------------------- /doc/model_lit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/model_lit.gif -------------------------------------------------------------------------------- /doc/specular.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/specular.gif -------------------------------------------------------------------------------- /doc/texture_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/doc/texture_test.png -------------------------------------------------------------------------------- /include-demo/api_audio.h: -------------------------------------------------------------------------------- 1 | /* Public Domain / CC0 Audio Playback Mini Library 2 | 3 | 4 | Written by Gek (DMHSW) in 2020 5 | 6 | 7 | */ 8 | 9 | /* 10 | HOW TO BUILD THINGS USING THIS LIBRARY 11 | #define CHAD_API_IMPL 12 | ^ This line goes in the file you want the "implementation" in. 13 | #include "api_audio.h" 14 | 15 | 16 | */ 17 | #define USE_MIXER 18 | 19 | #include 20 | #include 21 | #include 22 | #define SDL_MAIN_HANDLED 23 | #include 24 | 25 | 26 | 27 | #ifdef CHAD_API_IMPL 28 | #define CHAD_MATH_IMPL 29 | #endif 30 | #include "3dMath.h" 31 | typedef unsigned char uchar; 32 | 33 | extern uint R_; 34 | extern uint G_; 35 | extern uint B_; 36 | extern uint A_; 37 | 38 | 39 | #ifdef USE_MIXER 40 | #include 41 | void ainit(int needsSDLINIT); 42 | void acleanup(); 43 | typedef Mix_Chunk samp; 44 | typedef Mix_Music track; 45 | samp* lwav(const char* t); 46 | track* lmus(const char* t); 47 | samp* qlwav(Uint8* w); 48 | int aplay(samp* samp, int loops); 49 | void aPos(int chan, int angle, unsigned char dist); 50 | void aHalt(int chan); 51 | int mplay(track* mus,int loops, int ms); 52 | void mhalt(); 53 | #ifdef CHAD_API_IMPL 54 | void ainit(int needsSDLINIT){ 55 | if(needsSDLINIT) 56 | if (SDL_Init(SDL_INIT_AUDIO)!=0) 57 | {fprintf(stderr, "SDL_Init Error: %s\n", SDL_GetError());exit(0);} 58 | Mix_Init(MIX_INIT_OGG | MIX_INIT_MP3); 59 | if(-1 == Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)) {printf("\nAudio can't init :(");exit(2);} 60 | } 61 | void acleanup(){ 62 | Mix_CloseAudio(); 63 | Mix_Quit(); 64 | SDL_Quit(); 65 | } 66 | 67 | 68 | samp* lwav(const char* t){return Mix_LoadWAV(t);} 69 | track* lmus(const char* t){return Mix_LoadMUS(t);} 70 | samp* qlwav(Uint8* w){return Mix_QuickLoad_WAV(w);} 71 | int aplay(samp* samp, int loops){return Mix_PlayChannel(-1, samp, loops);} 72 | void aPos(int chan, int angle, unsigned char dist){Mix_SetPosition(chan,angle,dist);} 73 | void aHalt(int chan){Mix_HaltChannel(chan);} 74 | int mplay(track* mus,int loops, int ms){return Mix_FadeInMusic(mus,loops,ms);} 75 | void mhalt(){Mix_HaltMusic();} 76 | 77 | #endif 78 | 79 | #endif 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /include-demo/chade.h: -------------------------------------------------------------------------------- 1 | 2 | #include "3dMath.h" 3 | 4 | #include "chadphys.h" 5 | #include "../include/GL/gl.h" 6 | #include "../include/zbuffer.h" 7 | #include "api_audio.h" 8 | #include "tobjparse.h" 9 | 10 | static inline GLuint loadRGBTexture(unsigned char* buf, unsigned int w, unsigned int h) { 11 | GLuint t = 0; 12 | glGenTextures(1, &t); 13 | glBindTexture(GL_TEXTURE_2D, t); 14 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 15 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 16 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 17 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 18 | glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buf); 19 | return t; 20 | } 21 | 22 | static inline GLuint createModelDisplayList( 23 | vec3* points, GLuint npoints, vec3* colors, vec3* normals, vec3* texcoords) { 24 | GLuint i, ret = 0; 25 | if (!points) 26 | return 0; 27 | ret = glGenLists(1); 28 | glNewList(ret, GL_COMPILE); 29 | glBegin(GL_TRIANGLES); 30 | for (i = 0; i < npoints; i++) { 31 | if (colors) { 32 | glColor3f(colors[i].d[0], colors[i].d[1], colors[i].d[2]); 33 | } 34 | if (texcoords) 35 | glTexCoord2f(texcoords[i].d[0], texcoords[i].d[1]); 36 | if (normals) 37 | glNormal3f(normals[i].d[0], normals[i].d[1], normals[i].d[2]); 38 | glVertex3f(points[i].d[0], points[i].d[1], points[i].d[2]); 39 | } 40 | glEnd(); 41 | glEndList(); 42 | return ret; 43 | } 44 | 45 | 46 | static inline void drawModel( 47 | vec3* points, GLuint npoints, vec3* colors, vec3* normals, vec3* texcoords) { 48 | GLuint i; 49 | if (!points) 50 | return; 51 | glBegin(GL_TRIANGLES); 52 | for (i = 0; i < npoints; i++) { 53 | if (colors) { 54 | glColor3f(colors[i].d[0], colors[i].d[1], colors[i].d[2]); 55 | } 56 | if (texcoords) 57 | glTexCoord2f(texcoords[i].d[0], texcoords[i].d[1]); 58 | if (normals) 59 | glNormal3f(normals[i].d[0], normals[i].d[1], normals[i].d[2]); 60 | glVertex3f(points[i].d[0], points[i].d[1], points[i].d[2]); 61 | } 62 | glEnd(); 63 | return; 64 | } 65 | 66 | typedef struct { 67 | phys_body body; /*body*/ 68 | GLuint dl; /*Rendering details*/ 69 | } ChadEntity; 70 | 71 | typedef struct{ 72 | phys_world world; 73 | ChadEntity** ents; 74 | long n_ents; /*ents and ents_phys must contain the same number of elements.*/ 75 | long max_ents; 76 | } ChadWorld; 77 | 78 | static inline void initChadWorld(ChadWorld* w, long max_entities){ 79 | *w = (ChadWorld){0}; 80 | w->world.ms = 1000;/*plenty fast*/ 81 | w->world.g = (vec3){{0,-1,0}};/*plenty realistic*/ 82 | w->ents = calloc(1, sizeof(void*) * max_entities); 83 | if(w->ents == NULL)exit(1); 84 | w->max_ents = max_entities; 85 | w->n_ents = 0; 86 | } 87 | 88 | static inline void stepChadWorld(ChadWorld* world, long iter){ 89 | stepPhysWorld(&world->world, iter); 90 | } 91 | static inline long ChadWorld_AddEntity(ChadWorld* world, ChadEntity* ent){ 92 | /*safety check. 93 | for(long i = 0; i < world->max_ents; i++) 94 | if(world->ents[i] == ent) return i; 95 | */ 96 | for(long i = 0; i < world->max_ents; i++){ 97 | if(world->ents[i] == NULL){ 98 | world->ents[i] = ent; 99 | world->world.bodies[i] = &ent->body; 100 | if(world->n_ents <= i){ 101 | world->n_ents = i + 1; 102 | world->world.nbodies = i+1; 103 | } 104 | return i; 105 | } 106 | } 107 | return -1; 108 | 109 | } 110 | 111 | static inline void ChadWorld_RemoveEntityByPointer(ChadWorld* world, ChadEntity* ent){ 112 | for(long i = 0; i < world->max_ents; i++) 113 | if(world->ents[i] == ent) { 114 | world->ents[i] = NULL; 115 | world->world.bodies[i] = NULL; 116 | } 117 | //recalculate n_ents 118 | for(long i = 0; i < world->max_ents; i++) 119 | if(world->ents[i]) 120 | {world->n_ents = i + 1;world->world.nbodies = i+1;} 121 | } 122 | 123 | 124 | static inline void renderChadWorld(ChadWorld* world){ 125 | long i; 126 | /*The user will already have set up the viewport, the camera, and the lights.*/ 127 | for(i = 0; i < world->n_ents; i++) 128 | if(world->ents[i]){ 129 | glPushMatrix(); 130 | /*build the transformation matrix*/ 131 | glTranslatef( world->ents[i]->body.shape.c.d[0], 132 | world->ents[i]->body.shape.c.d[1], 133 | world->ents[i]->body.shape.c.d[2] 134 | ); 135 | glMultMatrixf(world->ents[i]->body.localt.d); 136 | /*Render that shizzle!*/ 137 | glCallList( 138 | world->ents[i]->dl 139 | ); 140 | glPopMatrix(); 141 | } 142 | } 143 | 144 | -------------------------------------------------------------------------------- /include-demo/chadphys.h: -------------------------------------------------------------------------------- 1 | #ifndef CHAD_PHYS_H 2 | #define CHAD_PHYS_H 3 | #include "3dMath.h" 4 | typedef struct { 5 | aabb shape; //c.d[3] is sphere radius. 6 | //if it's zero or less, it's not a sphere, it's a box 7 | mat4 localt; //Local Transform. 8 | vec3 v; //velocity 9 | vec3 a; //Body specific acceleration, combined with gravity 10 | f_ mass; //0 means kinematic, or static. Defaults to zero. 11 | f_ bounciness; //default 0, put portion of displacement into velocity. 12 | f_ airfriction; //default 1, multiplied by velocity every time timestep. 13 | f_ friction; //default 0.1 14 | } phys_body; 15 | typedef struct{ 16 | vec3 g; //gravity 17 | phys_body** bodies; 18 | f_ ms; //max speed 19 | long nbodies; //number of bodies 20 | char is_2d; //is this a 2-dimensional simulation? 21 | } phys_world; 22 | 23 | 24 | 25 | static inline void initPhysBody(phys_body* body){ 26 | body->shape = (aabb){ 27 | .c=(vec4){.d[0] = 0,.d[1] = 0,.d[2] = 0,.d[3] = 0}, 28 | .e=(vec3){.d[0] = 0,.d[1] = 0,.d[2] = 0} 29 | }; 30 | body->mass = 0; 31 | body->bounciness = 0; 32 | body->friction = 0.99; //The amount of coplanar velocity preserved in collisions. 33 | body->airfriction = 0.99; 34 | body->a = (vec3){.d[0] = 0,.d[1] = 0,.d[2] = 0}; 35 | body->localt = identitymat4(); 36 | } 37 | static inline mat4 getPhysBodyRenderTransform(phys_body* body){ 38 | return multm4( 39 | translate(downv4(body->shape.c)), 40 | body->localt 41 | ); 42 | } 43 | 44 | //Check for and, if necessary, resolve colliding bodies. 45 | static inline void resolveBodies(phys_body* a, phys_body* b){ 46 | vec4 penvec; vec3 penvecnormalized, comvel; f_ friction, bdisplacefactor, adisplacefactor; 47 | if(a->mass > 0 || b->mass > 0){ //Perform a preliminary check. Do we even have to do anything? 48 | /*We must do shit*/ 49 | } else {return;} 50 | if(a->mass < -0 || b->mass < -0) return; /*ERROR- for the branch predictor, that is...*/ 51 | /*Optimized for branch prediction.*/ 52 | penvec = (vec4){ 53 | .d[0]=0, 54 | .d[1]=0, 55 | .d[2]=0, 56 | .d[3]=0 57 | }; 58 | /*Check if the two bodies are colliding.*/ 59 | if(a->shape.c.d[3] > 0 && b->shape.c.d[3] > 0) //Both Spheres! 60 | { 61 | penvec = spherevsphere(a->shape.c, b->shape.c); 62 | } else if(a->shape.c.d[3] <= 0 && b->shape.c.d[3] <= 0) //Both boxes! 63 | { 64 | penvec = boxvbox(a->shape,b->shape); 65 | } else if (a->shape.c.d[3] > 0 && b->shape.c.d[3] <= 0) //a is a sphere, b is a box 66 | { 67 | penvec = spherevaabb(a->shape.c,b->shape); 68 | } else if (a->shape.c.d[3] <= 0 && b->shape.c.d[3] > 0){ //a is a box, b is a sphere 69 | penvec = spherevaabb(b->shape.c,a->shape); 70 | penvec.d[0] *= -1; 71 | penvec.d[1] *= -1; 72 | penvec.d[2] *= -1; 73 | } 74 | #ifdef CHADPHYS_DEBUG 75 | else { 76 | puts("\nInvalid configuration. Error.\n"); 77 | } 78 | #endif 79 | if(penvec.d[3] <= 0.0){return;}//No penetration detected, or invalid configuration. 80 | penvecnormalized = scalev3(1.0/penvec.d[3], downv4(penvec)); //the penetration vector points into B... 81 | friction = a->friction * b->friction; 82 | //We now have the penetration vector. There is a penetration. 83 | //determine how much each should be displaced by. 84 | //The penvec points INTO A and is of length penvec.d[3] 85 | bdisplacefactor = a->mass / (a->mass + b->mass); 86 | adisplacefactor = b->mass / (a->mass + b->mass); 87 | if(!(a->mass > 0)) { 88 | adisplacefactor = 0; bdisplacefactor = 1; 89 | }else if(!(b->mass > 0)) { 90 | bdisplacefactor = 0; adisplacefactor = 1; 91 | } 92 | comvel = addv3( scalev3(bdisplacefactor, a->v), scalev3(adisplacefactor, b->v)); 93 | if(a->mass > 0){ 94 | vec4 displacea; vec3 a_relvel, a_planarvel; 95 | displacea = scalev4(-adisplacefactor, penvec); 96 | a_relvel = subv3(a->v, comvel); 97 | float test = dotv3(a_relvel, penvecnormalized); 98 | if(test > 0) 99 | a_planarvel = subv3(a_relvel, 100 | scalev3( 101 | test, 102 | penvecnormalized 103 | ) 104 | ); 105 | else 106 | a_planarvel = a_relvel; 107 | a->shape.c.d[0] += displacea.d[0]; 108 | a->shape.c.d[1] += displacea.d[1]; 109 | a->shape.c.d[2] += displacea.d[2]; 110 | a->v = addv3( comvel, scalev3(friction, a_planarvel) ); //The center of mass velocity, plus a portion of coplanar velocity. 111 | a->v = addv3(a->v, scalev3( a->bounciness, downv4(displacea) ) ); 112 | } 113 | if(b->mass > 0){ 114 | vec4 displaceb; vec3 b_relvel, b_planarvel; 115 | displaceb = scalev4(bdisplacefactor, penvec); 116 | b_relvel = subv3(b->v, comvel); 117 | float test = dotv3(b_relvel, penvecnormalized); //the component in that direction 118 | if(test < 0) 119 | b_planarvel = subv3(b_relvel, //brelvel - portion of brelvel in the direction of penvecnormalized 120 | scalev3( 121 | test, //the component in that direction 122 | penvecnormalized //that direction 123 | ) 124 | ); 125 | else 126 | b_planarvel = b_relvel; 127 | b->shape.c.d[0] += displaceb.d[0]; 128 | b->shape.c.d[1] += displaceb.d[1]; 129 | b->shape.c.d[2] += displaceb.d[2]; 130 | b->v = addv3(comvel, scalev3(friction, b_planarvel) ); //The center of mass velocity, plus a portion of coplanar velocity. 131 | b->v = addv3(b->v, scalev3( b->bounciness, downv4(displaceb) ) ); 132 | } 133 | } 134 | 135 | static inline void stepPhysWorld(phys_world* world, const long collisioniter){ 136 | for(long i = 0; i < world->nbodies; i++) 137 | if(world->bodies[i] && world->bodies[i]->mass > 0){ 138 | phys_body* body = world->bodies[i]; 139 | vec3 bodypos = addv3(downv4(body->shape.c),body->v); 140 | body->shape.c.d[0] = bodypos.d[0]; 141 | body->shape.c.d[1] = bodypos.d[1]; 142 | body->shape.c.d[2] = bodypos.d[2]; 143 | body->v = addv3(body->v, body->a); 144 | body->v = addv3(body->v, world->g); 145 | if( (dotv3(body->v, body->v) > world->ms * world->ms)){ 146 | body->v = normalizev3(body->v); 147 | body->v = scalev3(world->ms, body->v); 148 | } 149 | body->v = scalev3(body->airfriction, body->v); 150 | if(world->is_2d) {body->shape.c.d[2] = 0;} 151 | } 152 | 153 | //Resolve collisions (if any) 154 | for(long iter = 0; iter < collisioniter; iter++) 155 | for(long i = 0; i < (long)(world->nbodies-1); i++){ 156 | if(world->bodies[i]){ 157 | for(long j = i+1; j < (long)world->nbodies; j++) 158 | if(world->bodies[j]) 159 | resolveBodies(world->bodies[i], world->bodies[j]); 160 | } 161 | } 162 | } 163 | #endif 164 | -------------------------------------------------------------------------------- /include-demo/lockstepthread.h: -------------------------------------------------------------------------------- 1 | 2 | /* Public Domain / CC0 3d Lock-Step Threading Implementation 3 | 4 | 5 | Written by Gek (DMHSW) in 2020 6 | 7 | 8 | */ 9 | 10 | #ifndef LOCKSTEPTHREAD_H 11 | #define LOCKSTEPTHREAD_H 12 | #include 13 | #include 14 | typedef struct { 15 | pthread_mutex_t myMutex; 16 | pthread_barrier_t myBarrier; 17 | pthread_t myThread; 18 | int isThreadLive; 19 | int shouldKillThread; 20 | int state; 21 | void (*execute)(void*); 22 | void* argument; 23 | } lsthread; 24 | void init_lsthread(lsthread* t); 25 | void start_lsthread(lsthread* t); 26 | void kill_lsthread(lsthread* t); 27 | void destroy_lsthread(lsthread* t); 28 | void lock(lsthread* t); 29 | void step(lsthread* t); 30 | void* lsthread_func(void* me_void); 31 | #ifdef LOCKSTEPTHREAD_IMPL 32 | //function declarations 33 | 34 | void init_lsthread(lsthread* t){ 35 | t->myMutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; 36 | pthread_barrier_init(&t->myBarrier, NULL, 2); 37 | t->isThreadLive = 0; 38 | t->shouldKillThread = 0; 39 | t->state = 0; 40 | t->execute = NULL; 41 | t->argument = NULL; 42 | } 43 | void destroy_lsthread(lsthread* t){ 44 | pthread_mutex_destroy(&t->myMutex); 45 | pthread_barrier_destroy(&t->myBarrier); 46 | } 47 | void lock(lsthread* t){ 48 | if(t->state == 1)return;//if already locked, nono 49 | if(!t->isThreadLive)return; 50 | //exit(1) 51 | pthread_barrier_wait(&t->myBarrier); 52 | //exit(1) 53 | if(pthread_mutex_lock(&t->myMutex)) 54 | exit(1); 55 | t->state = 1; 56 | //exit(1) 57 | } 58 | 59 | void step(lsthread* t){ 60 | if(t->state == -1)return; //if already stepping, nono 61 | if(!t->isThreadLive)return; 62 | //exit(1) 63 | if(pthread_mutex_unlock(&(t->myMutex))) 64 | exit(1); 65 | //exit(1) 66 | pthread_barrier_wait(&t->myBarrier); 67 | t->state = -1; 68 | //exit(1) 69 | } 70 | void kill_lsthread(lsthread* t){ 71 | if(!t->isThreadLive)return; 72 | //exit(1) 73 | if(t->state != 1){ 74 | lock(t); 75 | //exit(1) 76 | } 77 | t->shouldKillThread = 1; 78 | 79 | step(t); 80 | //exit(1) 81 | pthread_join(t->myThread,NULL); 82 | //if(pthread_kill(t->myThread)){ 83 | // exit(1) 84 | //} 85 | t->isThreadLive = 0; 86 | t->shouldKillThread = 0; 87 | } 88 | void* lsthread_func(void* me_void){ 89 | lsthread* me = (lsthread*) me_void; 90 | int ret = 0; 91 | if (!me)pthread_exit(NULL); 92 | while (1) { 93 | //ret = pthread_cond_wait(&(me->myCond), &(me->myMutex)); 94 | pthread_barrier_wait(&me->myBarrier); 95 | //exit(1) 96 | pthread_mutex_lock(&me->myMutex); 97 | //exit(1) 98 | //if(ret)pthread_exit(NULL); 99 | if (!(me->shouldKillThread) && me->execute) 100 | me->execute(me->argument); 101 | else if(me->shouldKillThread){ 102 | pthread_mutex_unlock(&me->myMutex); 103 | //exit(1) 104 | //pthread_barrier_wait(&me->myBarrier); 105 | //exit(1) 106 | pthread_exit(NULL); 107 | } 108 | //exit(1) 109 | pthread_mutex_unlock(&me->myMutex); 110 | //exit(1) 111 | pthread_barrier_wait(&me->myBarrier); 112 | //exit(1) 113 | } 114 | pthread_exit(NULL); 115 | } 116 | void start_lsthread(lsthread* t){ 117 | if(t->isThreadLive)return; 118 | t->isThreadLive = 1; 119 | t->shouldKillThread = 0; 120 | if(pthread_mutex_lock(&t->myMutex)) 121 | exit(1); 122 | t->state = 1; //LOCKED 123 | pthread_create( 124 | &t->myThread, 125 | NULL, 126 | lsthread_func, 127 | (void*)t 128 | ); 129 | } 130 | #endif 131 | //end of implementation 132 | 133 | #endif 134 | //end of header 135 | -------------------------------------------------------------------------------- /include-demo/resweep.h: -------------------------------------------------------------------------------- 1 | //unlicense'd 2 | /* 3 | This is free and unencumbered software released into the public domain. 4 | 5 | Anyone is free to copy, modify, publish, use, compile, sell, or 6 | distribute this software, either in source code form or as a compiled 7 | binary, for any purpose, commercial or non-commercial, and by any 8 | means. 9 | 10 | In jurisdictions that recognize copyright laws, the author or authors 11 | of this software dedicate any and all copyright interest in the 12 | software to the public domain. We make this dedication for the benefit 13 | of the public at large and to the detriment of our heirs and 14 | successors. We intend this dedication to be an overt act of 15 | relinquishment in perpetuity of all present and future rights to this 16 | software under copyright law. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | 26 | For more information, please refer to 27 | */ 28 | 29 | 30 | //#pragma once 31 | #ifndef RESWEEP_H 32 | #define RESWEEP_H 33 | 34 | #ifdef RESWEEP_IMPLEMENTATION 35 | 36 | #include 37 | 38 | #ifndef M_PI 39 | #define M_PI 3.14159265358979323846 40 | #endif 41 | 42 | #ifndef M_1_PI 43 | #define M_1_PI 0.31830988618379067154 44 | #endif 45 | 46 | #define SIDELOBE_HEIGHT 96 47 | #define UP_TRANSITION_WIDTH (1.0 / 32.0) 48 | #define DOWN_TRANSITION_WIDTH (1.0 / 128.0) 49 | #define MAX_SINC_WINDOW_SIZE 2048 50 | #define RESAMPLE_LUT_STEP 128 51 | 52 | typedef struct 53 | { 54 | float value; 55 | float delta; 56 | } 57 | lutEntry_t; 58 | 59 | lutEntry_t dynamicLut[RESAMPLE_LUT_STEP * MAX_SINC_WINDOW_SIZE]; 60 | 61 | static inline unsigned int calc_gcd(unsigned int a, unsigned int b) 62 | { 63 | while (b) 64 | { 65 | unsigned int t = b; 66 | b = a % b; 67 | a = t; 68 | } 69 | 70 | return a; 71 | } 72 | 73 | static inline double exact_nsinc(double x) 74 | { 75 | if (x == 0.0) 76 | return 1.0; 77 | 78 | return ((double)(M_1_PI) / x) * sin(M_PI * x); 79 | } 80 | 81 | // Modified Bessel function of the first kind, order 0 82 | // https://ccrma.stanford.edu/~jos/sasp/Kaiser_Window.html 83 | static inline double I0(double x) 84 | { 85 | double r = 1.0, xx = x * x, xpow = xx, coeff = 0.25; 86 | int k; 87 | 88 | // iterations until coeff ~= 0 89 | // 19 for float32, 89 for float64, 880 for float80 90 | for (k = 1; k < 89; k++) 91 | { 92 | r += xpow * coeff; 93 | coeff /= (4 * k + 8) * k + 4; 94 | xpow *= xx; 95 | } 96 | 97 | return r; 98 | } 99 | 100 | // https://ccrma.stanford.edu/~jos/sasp/Kaiser_Window.html 101 | static inline double kaiser(int n, int length, double beta) 102 | { 103 | double mid = 2 * n / (double)(length - 1) - 1.0; 104 | 105 | return I0(beta * sqrt(1.0 - mid * mid)) / I0(beta); 106 | } 107 | 108 | static inline void sinc_resample_createLut(int inFreq, int cutoffFreq2, int windowSize, double beta) 109 | { 110 | double windowLut[windowSize]; 111 | double freqAdjust = (double)cutoffFreq2 / (double)inFreq; 112 | lutEntry_t *out, *in; 113 | int i, j; 114 | 115 | for (i = 0; i < windowSize; i++) 116 | windowLut[i] = kaiser(i, windowSize, beta); 117 | 118 | out = dynamicLut; 119 | for (i = 0; i < RESAMPLE_LUT_STEP; i++) 120 | { 121 | double offset = i / (double)(RESAMPLE_LUT_STEP - 1) - windowSize / 2; 122 | double sum = 0.0; 123 | for (j = 0; j < windowSize; j++) 124 | { 125 | double s = exact_nsinc((j + offset) * freqAdjust); 126 | out->value = s * windowLut[j]; 127 | sum += s; 128 | out++; 129 | } 130 | 131 | out -= windowSize; 132 | for (j = 0; j < windowSize; j++) 133 | { 134 | out->value /= sum; 135 | out++; 136 | } 137 | } 138 | 139 | out = dynamicLut; 140 | in = out + windowSize; 141 | for (i = 0; i < RESAMPLE_LUT_STEP - 1; i++) 142 | { 143 | for (j = 0; j < windowSize; j++) 144 | { 145 | out->delta = in->value - out->value; 146 | out++; 147 | in++; 148 | } 149 | } 150 | 151 | for (j = 0; j < windowSize; j++) 152 | { 153 | out->delta = 0; 154 | out++; 155 | } 156 | } 157 | 158 | static inline void sinc_resample_internal(short *wavOut, int sizeOut, int outFreq, const short *wavIn, int sizeIn, int inFreq, int cutoffFreq2, int numChannels, int windowSize, double beta) 159 | { 160 | float y[windowSize * numChannels]; 161 | const short *sampleIn, *wavInEnd = wavIn + (sizeIn / 2); 162 | short *sampleOut, *wavOutEnd = wavOut + (sizeOut / 2); 163 | float outPeriod; 164 | int subpos = 0; 165 | int gcd = calc_gcd(inFreq, outFreq); 166 | int i, c, next; 167 | float dither[numChannels]; 168 | 169 | sinc_resample_createLut(inFreq, cutoffFreq2, windowSize, beta); 170 | 171 | inFreq /= gcd; 172 | outFreq /= gcd; 173 | outPeriod = 1.0f / outFreq; 174 | 175 | for (c = 0; c < numChannels; c++) 176 | dither[c] = 0.0f; 177 | 178 | for (i = 0; i < windowSize / 2 - 1; i++) 179 | { 180 | for (c = 0; c < numChannels; c++) 181 | y[i * numChannels + c] = 0; 182 | } 183 | 184 | sampleIn = wavIn; 185 | for (; i < windowSize; i++) 186 | { 187 | for (c = 0; c < numChannels; c++) 188 | y[i * numChannels + c] = (sampleIn < wavInEnd) ? *sampleIn++ : 0; 189 | } 190 | 191 | sampleOut = wavOut; 192 | next = 0; 193 | while (sampleOut < wavOutEnd) 194 | { 195 | float samples[numChannels]; 196 | float offset = 1.0f - subpos * outPeriod; 197 | float interp; 198 | lutEntry_t *lutPart; 199 | int index; 200 | 201 | for (c = 0; c < numChannels; c++) 202 | samples[c] = 0.0f; 203 | 204 | interp = offset * (RESAMPLE_LUT_STEP - 1); 205 | index = interp; 206 | interp -= index; 207 | lutPart = dynamicLut + index * windowSize; 208 | 209 | for (i = next; i < windowSize; i++, lutPart++) 210 | { 211 | float scale = lutPart->value + lutPart->delta * interp; 212 | 213 | for (c = 0; c < numChannels; c++) 214 | samples[c] += y[i * numChannels + c] * scale; 215 | } 216 | 217 | for (i = 0; i < next; i++, lutPart++) 218 | { 219 | float scale = lutPart->value + lutPart->delta * interp; 220 | 221 | for (c = 0; c < numChannels; c++) 222 | samples[c] += y[i * numChannels + c] * scale; 223 | } 224 | 225 | for (c = 0; c < numChannels; c++) 226 | { 227 | float r = roundf(samples[c] + dither[c]); 228 | dither[c] += samples[c] - r; 229 | 230 | if (r > 32767) 231 | *sampleOut++ = 32767; 232 | else if (r < -32768) 233 | *sampleOut++ = -32768; 234 | else 235 | *sampleOut++ = r; 236 | } 237 | 238 | subpos += inFreq; 239 | while (subpos >= outFreq) 240 | { 241 | subpos -= outFreq; 242 | 243 | for (c = 0; c < numChannels; c++) 244 | y[next * numChannels + c] = (sampleIn < wavInEnd) ? *sampleIn++ : 0; 245 | 246 | next = (next + 1) % windowSize; 247 | } 248 | } 249 | } 250 | 251 | void sinc_resample(short *wavOut, int sizeOut, int outFreq, const short *wavIn, int sizeIn, int inFreq, int numChannels) 252 | { 253 | double sidelobeHeight = SIDELOBE_HEIGHT; 254 | double transitionWidth; 255 | double beta = 0.0; 256 | int cutoffFreq2; 257 | int windowSize; 258 | 259 | // Just copy if no resampling necessary 260 | if (outFreq == inFreq) 261 | { 262 | memcpy(wavOut, wavIn, (sizeOut < sizeIn) ? sizeOut : sizeIn); 263 | return; 264 | } 265 | 266 | transitionWidth = (outFreq > inFreq) ? UP_TRANSITION_WIDTH : DOWN_TRANSITION_WIDTH; 267 | 268 | // cutoff freq is ideally half transition width away from output freq 269 | cutoffFreq2 = outFreq - transitionWidth * inFreq * 0.5; 270 | 271 | // FIXME: Figure out why there are bad effects with cutoffFreq2 > inFreq 272 | if (cutoffFreq2 > inFreq) 273 | cutoffFreq2 = inFreq; 274 | 275 | // https://www.mathworks.com/help/signal/ug/kaiser-window.html 276 | if (sidelobeHeight > 50) 277 | beta = 0.1102 * (sidelobeHeight - 8.7); 278 | else if (sidelobeHeight >= 21) 279 | beta = 0.5842 * pow(sidelobeHeight - 21.0, 0.4) + 0.07886 * (sidelobeHeight - 21.0); 280 | 281 | windowSize = (sidelobeHeight - 8.0) / (2.285 * transitionWidth * M_PI) + 1; 282 | 283 | if (windowSize > MAX_SINC_WINDOW_SIZE) 284 | windowSize = MAX_SINC_WINDOW_SIZE; 285 | 286 | // should compile as different paths 287 | // number of channels need to be compiled as separate paths to ensure good 288 | // vectorization by the compiler 289 | if (numChannels == 1) 290 | sinc_resample_internal(wavOut, sizeOut, outFreq, wavIn, sizeIn, inFreq, cutoffFreq2, 1, windowSize, beta); 291 | else if (numChannels == 2) 292 | sinc_resample_internal(wavOut, sizeOut, outFreq, wavIn, sizeIn, inFreq, cutoffFreq2, 2, windowSize, beta); 293 | else 294 | sinc_resample_internal(wavOut, sizeOut, outFreq, wavIn, sizeIn, inFreq, cutoffFreq2, numChannels, windowSize, beta); 295 | 296 | } 297 | // RESWEEP_IMPLEMENTATION 298 | #endif 299 | //RESWEEP_H 300 | #endif 301 | -------------------------------------------------------------------------------- /include-demo/stb_include.h: -------------------------------------------------------------------------------- 1 | // stb_include.h - v0.02 - parse and process #include directives - public domain 2 | // 3 | // To build this, in one source file that includes this file do 4 | // #define STB_INCLUDE_IMPLEMENTATION 5 | // 6 | // This program parses a string and replaces lines of the form 7 | // #include "foo" 8 | // with the contents of a file named "foo". It also embeds the 9 | // appropriate #line directives. Note that all include files must 10 | // reside in the location specified in the path passed to the API; 11 | // it does not check multiple directories. 12 | // 13 | // If the string contains a line of the form 14 | // #inject 15 | // then it will be replaced with the contents of the string 'inject' passed to the API. 16 | // 17 | // Options: 18 | // 19 | // Define STB_INCLUDE_LINE_GLSL to get GLSL-style #line directives 20 | // which use numbers instead of filenames. 21 | // 22 | // Define STB_INCLUDE_LINE_NONE to disable output of #line directives. 23 | // 24 | // Standard libraries: 25 | // 26 | // stdio.h FILE, fopen, fclose, fseek, ftell 27 | // stdlib.h malloc, realloc, free 28 | // string.h strcpy, strncmp, memcpy 29 | // 30 | // Credits: 31 | // 32 | // Written by Sean Barrett. 33 | // 34 | // Fixes: 35 | // Michal Klos 36 | 37 | #ifndef STB_INCLUDE_STB_INCLUDE_H 38 | #define STB_INCLUDE_STB_INCLUDE_H 39 | 40 | // Do include-processing on the string 'str'. To free the return value, pass it to free() 41 | char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); 42 | 43 | // Concatenate the strings 'strs' and do include-processing on the result. To free the return value, pass it to free() 44 | char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); 45 | 46 | // Load the file 'filename' and do include-processing on the string therein. note that 47 | // 'filename' is opened directly; 'path_to_includes' is not used. To free the return value, pass it to free() 48 | char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]); 49 | 50 | #endif 51 | 52 | 53 | #ifdef STB_INCLUDE_IMPLEMENTATION 54 | 55 | #include 56 | #include 57 | #include 58 | 59 | static char *stb_include_load_file(char *filename, size_t *plen) 60 | { 61 | char *text; 62 | size_t len; 63 | FILE *f = fopen(filename, "rb"); 64 | if (f == 0) return 0; 65 | fseek(f, 0, SEEK_END); 66 | len = (size_t) ftell(f); 67 | if (plen) *plen = len; 68 | text = (char *) malloc(len+1); 69 | if (text == 0) return 0; 70 | fseek(f, 0, SEEK_SET); 71 | fread(text, 1, len, f); 72 | fclose(f); 73 | text[len] = 0; 74 | return text; 75 | } 76 | 77 | typedef struct 78 | { 79 | int offset; 80 | int end; 81 | char *filename; 82 | int next_line_after; 83 | } include_info; 84 | 85 | static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line) 86 | { 87 | include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1)); 88 | z[len].offset = offset; 89 | z[len].end = end; 90 | z[len].filename = filename; 91 | z[len].next_line_after = next_line; 92 | return z; 93 | } 94 | 95 | static void stb_include_free_includes(include_info *array, int len) 96 | { 97 | int i; 98 | for (i=0; i < len; ++i) 99 | free(array[i].filename); 100 | free(array); 101 | } 102 | 103 | static int stb_include_isspace(int ch) 104 | { 105 | return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); 106 | } 107 | 108 | // find location of all #include and #inject 109 | static int stb_include_find_includes(char *text, include_info **plist) 110 | { 111 | int line_count = 1; 112 | int inc_count = 0; 113 | char *s = text, *start; 114 | include_info *list = NULL; 115 | while (*s) { 116 | // parse is always at start of line when we reach here 117 | start = s; 118 | while (*s == ' ' || *s == '\t') 119 | ++s; 120 | if (*s == '#') { 121 | ++s; 122 | while (*s == ' ' || *s == '\t') 123 | ++s; 124 | if (0==strncmp(s, "include", 7) && stb_include_isspace(s[7])) { 125 | s += 7; 126 | while (*s == ' ' || *s == '\t') 127 | ++s; 128 | if (*s == '"') { 129 | char *t = ++s; 130 | while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0) 131 | ++t; 132 | if (*t == '"') { 133 | char *filename = (char *) malloc(t-s+1); 134 | memcpy(filename, s, t-s); 135 | filename[t-s] = 0; 136 | s=t; 137 | while (*s != '\r' && *s != '\n' && *s != 0) 138 | ++s; 139 | // s points to the newline, so s-start is everything except the newline 140 | list = stb_include_append_include(list, inc_count++, start-text, s-text, filename, line_count+1); 141 | } 142 | } 143 | } else if (0==strncmp(s, "inject", 6) && (stb_include_isspace(s[6]) || s[6]==0)) { 144 | while (*s != '\r' && *s != '\n' && *s != 0) 145 | ++s; 146 | list = stb_include_append_include(list, inc_count++, start-text, s-text, NULL, line_count+1); 147 | } 148 | } 149 | while (*s != '\r' && *s != '\n' && *s != 0) 150 | ++s; 151 | if (*s == '\r' || *s == '\n') { 152 | s = s + (s[0] + s[1] == '\r' + '\n' ? 2 : 1); 153 | } 154 | ++line_count; 155 | } 156 | *plist = list; 157 | return inc_count; 158 | } 159 | 160 | // avoid dependency on sprintf() 161 | static void stb_include_itoa(char str[9], int n) 162 | { 163 | int i; 164 | for (i=0; i < 8; ++i) 165 | str[i] = ' '; 166 | str[i] = 0; 167 | 168 | for (i=1; i < 8; ++i) { 169 | str[7-i] = '0' + (n % 10); 170 | n /= 10; 171 | if (n == 0) 172 | break; 173 | } 174 | } 175 | 176 | static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen) 177 | { 178 | str = (char *) realloc(str, *curlen + addlen); 179 | memcpy(str + *curlen, addstr, addlen); 180 | *curlen += addlen; 181 | return str; 182 | } 183 | 184 | char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename, char error[256]) 185 | { 186 | char temp[4096]; 187 | include_info *inc_list; 188 | int i, num = stb_include_find_includes(str, &inc_list); 189 | size_t source_len = strlen(str); 190 | char *text=0; 191 | size_t textlen=0, last=0; 192 | for (i=0; i < num; ++i) { 193 | text = stb_include_append(text, &textlen, str+last, inc_list[i].offset - last); 194 | // write out line directive for the include 195 | #ifndef STB_INCLUDE_LINE_NONE 196 | #ifdef STB_INCLUDE_LINE_GLSL 197 | if (textlen != 0) // GLSL #version must appear first, so don't put a #line at the top 198 | #endif 199 | { 200 | strcpy(temp, "#line "); 201 | stb_include_itoa(temp+6, 1); 202 | strcat(temp, " "); 203 | #ifdef STB_INCLUDE_LINE_GLSL 204 | stb_include_itoa(temp+15, i+1); 205 | #else 206 | strcat(temp, "\""); 207 | if (inc_list[i].filename == 0) 208 | strcmp(temp, "INJECT"); 209 | else 210 | strcat(temp, inc_list[i].filename); 211 | strcat(temp, "\""); 212 | #endif 213 | strcat(temp, "\n"); 214 | text = stb_include_append(text, &textlen, temp, strlen(temp)); 215 | } 216 | #endif 217 | if (inc_list[i].filename == 0) { 218 | if (inject != 0) 219 | text = stb_include_append(text, &textlen, inject, strlen(inject)); 220 | } else { 221 | char *inc; 222 | strcpy(temp, path_to_includes); 223 | strcat(temp, "/"); 224 | strcat(temp, inc_list[i].filename); 225 | inc = stb_include_file(temp, inject, path_to_includes, error); 226 | if (inc == NULL) { 227 | stb_include_free_includes(inc_list, num); 228 | return NULL; 229 | } 230 | text = stb_include_append(text, &textlen, inc, strlen(inc)); 231 | free(inc); 232 | } 233 | // write out line directive 234 | #ifndef STB_INCLUDE_LINE_NONE 235 | strcpy(temp, "\n#line "); 236 | stb_include_itoa(temp+6, inc_list[i].next_line_after); 237 | strcat(temp, " "); 238 | #ifdef STB_INCLUDE_LINE_GLSL 239 | stb_include_itoa(temp+15, 0); 240 | #else 241 | strcat(temp, filename != 0 ? filename : "source-file"); 242 | #endif 243 | text = stb_include_append(text, &textlen, temp, strlen(temp)); 244 | // no newlines, because we kept the #include newlines, which will get appended next 245 | #endif 246 | last = inc_list[i].end; 247 | } 248 | text = stb_include_append(text, &textlen, str+last, source_len - last + 1); // append '\0' 249 | stb_include_free_includes(inc_list, num); 250 | return text; 251 | } 252 | 253 | char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename, char error[256]) 254 | { 255 | char *text; 256 | char *result; 257 | int i; 258 | size_t length=0; 259 | for (i=0; i < count; ++i) 260 | length += strlen(strs[i]); 261 | text = (char *) malloc(length+1); 262 | length = 0; 263 | for (i=0; i < count; ++i) { 264 | strcpy(text + length, strs[i]); 265 | length += strlen(strs[i]); 266 | } 267 | result = stb_include_string(text, inject, path_to_includes, filename, error); 268 | free(text); 269 | return result; 270 | } 271 | 272 | char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]) 273 | { 274 | size_t len; 275 | char *result; 276 | char *text = stb_include_load_file(filename, &len); 277 | if (text == NULL) { 278 | strcpy(error, "Error: couldn't load '"); 279 | strcat(error, filename); 280 | strcat(error, "'"); 281 | return 0; 282 | } 283 | result = stb_include_string(text, inject, path_to_includes, filename, error); 284 | free(text); 285 | return result; 286 | } 287 | 288 | #if 0 // @TODO, GL_ARB_shader_language_include-style system that doesn't touch filesystem 289 | char *stb_include_preloaded(char *str, char *inject, char *includes[][2], char error[256]) 290 | { 291 | 292 | } 293 | #endif 294 | 295 | #endif // STB_INCLUDE_IMPLEMENTATION 296 | -------------------------------------------------------------------------------- /include-demo/stb_leakcheck.h: -------------------------------------------------------------------------------- 1 | // stb_leakcheck.h - v0.6 - quick & dirty malloc leak-checking - public domain 2 | // LICENSE 3 | // 4 | // See end of file. 5 | 6 | #ifdef STB_LEAKCHECK_IMPLEMENTATION 7 | #undef STB_LEAKCHECK_IMPLEMENTATION // don't implement more than once 8 | 9 | // if we've already included leakcheck before, undefine the macros 10 | #ifdef malloc 11 | #undef malloc 12 | #undef free 13 | #undef realloc 14 | #endif 15 | 16 | #ifndef STB_LEAKCHECK_OUTPUT_PIPE 17 | #define STB_LEAKCHECK_OUTPUT_PIPE stdout 18 | #endif 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | typedef struct malloc_info stb_leakcheck_malloc_info; 26 | 27 | struct malloc_info 28 | { 29 | const char *file; 30 | int line; 31 | size_t size; 32 | stb_leakcheck_malloc_info *next,*prev; 33 | }; 34 | 35 | static stb_leakcheck_malloc_info *mi_head; 36 | 37 | void *stb_leakcheck_malloc(size_t sz, const char *file, int line) 38 | { 39 | stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) malloc(sz + sizeof(*mi)); 40 | if (mi == NULL) return mi; 41 | mi->file = file; 42 | mi->line = line; 43 | mi->next = mi_head; 44 | if (mi_head) 45 | mi->next->prev = mi; 46 | mi->prev = NULL; 47 | mi->size = (int) sz; 48 | mi_head = mi; 49 | return mi+1; 50 | } 51 | 52 | void stb_leakcheck_free(void *ptr) 53 | { 54 | if (ptr != NULL) { 55 | stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; 56 | mi->size = ~mi->size; 57 | #ifndef STB_LEAKCHECK_SHOWALL 58 | if (mi->prev == NULL) { 59 | assert(mi_head == mi); 60 | mi_head = mi->next; 61 | } else 62 | mi->prev->next = mi->next; 63 | if (mi->next) 64 | mi->next->prev = mi->prev; 65 | free(mi); 66 | #endif 67 | } 68 | } 69 | 70 | void *stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line) 71 | { 72 | if (ptr == NULL) { 73 | return stb_leakcheck_malloc(sz, file, line); 74 | } else if (sz == 0) { 75 | stb_leakcheck_free(ptr); 76 | return NULL; 77 | } else { 78 | stb_leakcheck_malloc_info *mi = (stb_leakcheck_malloc_info *) ptr - 1; 79 | if (sz <= mi->size) 80 | return ptr; 81 | else { 82 | #ifdef STB_LEAKCHECK_REALLOC_PRESERVE_MALLOC_FILELINE 83 | void *q = stb_leakcheck_malloc(sz, mi->file, mi->line); 84 | #else 85 | void *q = stb_leakcheck_malloc(sz, file, line); 86 | #endif 87 | if (q) { 88 | memcpy(q, ptr, mi->size); 89 | stb_leakcheck_free(ptr); 90 | } 91 | return q; 92 | } 93 | } 94 | } 95 | 96 | static void stblkck_internal_print(const char *reason, stb_leakcheck_malloc_info *mi) 97 | { 98 | #if defined(_MSC_VER) && _MSC_VER < 1900 // 1900=VS 2015 99 | // Compilers that use the old MS C runtime library don't have %zd 100 | // and the older ones don't even have %lld either... however, the old compilers 101 | // without "long long" don't support 64-bit targets either, so here's the 102 | // compromise: 103 | #if _MSC_VER < 1400 // before VS 2005 104 | fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %8d bytes at %p\n", reason, mi->file, mi->line, (int)mi->size, (void*)(mi+1)); 105 | #else 106 | fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %16lld bytes at %p\n", reason, mi->file, mi->line, (long long)mi->size, (void*)(mi+1)); 107 | #endif 108 | #else 109 | // Assume we have %zd on other targets. 110 | #ifdef __MINGW32__ 111 | __mingw_fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); 112 | #else 113 | fprintf(STB_LEAKCHECK_OUTPUT_PIPE, "%s: %s (%4d): %zd bytes at %p\n", reason, mi->file, mi->line, mi->size, (void*)(mi+1)); 114 | #endif 115 | #endif 116 | } 117 | 118 | void stb_leakcheck_dumpmem(void) 119 | { 120 | stb_leakcheck_malloc_info *mi = mi_head; 121 | while (mi) { 122 | if ((ptrdiff_t) mi->size >= 0) 123 | stblkck_internal_print("LEAKED", mi); 124 | mi = mi->next; 125 | } 126 | #ifdef STB_LEAKCHECK_SHOWALL 127 | mi = mi_head; 128 | while (mi) { 129 | if ((ptrdiff_t) mi->size < 0) 130 | stblkck_internal_print("FREED ", mi); 131 | mi = mi->next; 132 | } 133 | #endif 134 | } 135 | #endif // STB_LEAKCHECK_IMPLEMENTATION 136 | 137 | #if !defined(INCLUDE_STB_LEAKCHECK_H) || !defined(malloc) 138 | #define INCLUDE_STB_LEAKCHECK_H 139 | 140 | #include // we want to define the macros *after* stdlib to avoid a slew of errors 141 | 142 | #define malloc(sz) stb_leakcheck_malloc(sz, __FILE__, __LINE__) 143 | #define free(p) stb_leakcheck_free(p) 144 | #define realloc(p,sz) stb_leakcheck_realloc(p,sz, __FILE__, __LINE__) 145 | 146 | extern void * stb_leakcheck_malloc(size_t sz, const char *file, int line); 147 | extern void * stb_leakcheck_realloc(void *ptr, size_t sz, const char *file, int line); 148 | extern void stb_leakcheck_free(void *ptr); 149 | extern void stb_leakcheck_dumpmem(void); 150 | 151 | #endif // INCLUDE_STB_LEAKCHECK_H 152 | 153 | 154 | /* 155 | ------------------------------------------------------------------------------ 156 | This software is available under 2 licenses -- choose whichever you prefer. 157 | ------------------------------------------------------------------------------ 158 | ALTERNATIVE A - MIT License 159 | Copyright (c) 2017 Sean Barrett 160 | Permission is hereby granted, free of charge, to any person obtaining a copy of 161 | this software and associated documentation files (the "Software"), to deal in 162 | the Software without restriction, including without limitation the rights to 163 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 164 | of the Software, and to permit persons to whom the Software is furnished to do 165 | so, subject to the following conditions: 166 | The above copyright notice and this permission notice shall be included in all 167 | copies or substantial portions of the Software. 168 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 169 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 170 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 171 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 172 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 173 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 174 | SOFTWARE. 175 | ------------------------------------------------------------------------------ 176 | ALTERNATIVE B - Public Domain (www.unlicense.org) 177 | This is free and unencumbered software released into the public domain. 178 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 179 | software, either in source code form or as a compiled binary, for any purpose, 180 | commercial or non-commercial, and by any means. 181 | In jurisdictions that recognize copyright laws, the author or authors of this 182 | software dedicate any and all copyright interest in the software to the public 183 | domain. We make this dedication for the benefit of the public at large and to 184 | the detriment of our heirs and successors. We intend this dedication to be an 185 | overt act of relinquishment in perpetuity of all present and future rights to 186 | this software under copyright law. 187 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 188 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 189 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 190 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 191 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 192 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 193 | ------------------------------------------------------------------------------ 194 | */ 195 | -------------------------------------------------------------------------------- /include/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(zhdrs 2 | zbuffer.h 3 | zfeatures.h 4 | ) 5 | 6 | install(FILES ${zhdrs} DESTINATION ${INCLUDE_DIR}) 7 | 8 | install(FILES GL/gl.h DESTINATION ${INCLUDE_DIR}/TGL) 9 | -------------------------------------------------------------------------------- /include/zfeatures.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_features_h_ 2 | #define _tgl_features_h_ 3 | /* It is possible to enable/disable (compile time) features in this 4 | header file. */ 5 | /* 6 | Enables setting the error flags when there's an error, so you can check it with glGetError 7 | Disabling this has slight performance gains. 8 | */ 9 | #define TGL_FEATURE_ERROR_CHECK 0 10 | /* 11 | Strict out-of-memory checking. All OpenGL function calls are invalidated (ALL OF THEM) if a GL_OUT_OF_MEMORY error occurs. 12 | This means that TinyGL has to constantly check all gl_malloc() attempts for errors and the state of the error state variable. 13 | The checks slow down the renderer so it is not recommended , but 14 | it's in the GL spec that this should occur. 15 | */ 16 | #define TGL_FEATURE_STRICT_OOM_CHECKS 0 17 | 18 | /* 19 | Swap between using the inline'd malloc(), calloc(), and free() in zbuffer.h, or 20 | a replacement gl_malloc(), gl_zalloc(), and gl_free() in memory.c 21 | */ 22 | #define TGL_FEATURE_CUSTOM_MALLOC 0 23 | 24 | /* 25 | Use Fast Inverse Square Root. Toggleable because it's actually slower on some platforms, 26 | And because some systems may have float types which are incompatible with it. 27 | */ 28 | #define TGL_FEATURE_FISR 0 29 | 30 | #define TGL_FEATURE_ARRAYS 1 31 | 32 | #define TGL_FEATURE_DISPLAYLISTS 1 33 | 34 | #define TGL_FEATURE_LIT_TEXTURES 1 35 | /*Enable the patternized "discard"-ing of pixels.*/ 36 | #define TGL_FEATURE_POLYGON_STIPPLE 1 37 | /*Enable the use of GL_SELECT and GL_FEEDBACK*/ 38 | #define TGL_FEATURE_ALT_RENDERMODES 0 39 | /* 40 | Enable the rendering of large polygons (in terms of vertex count) 41 | Also enabled the rendering of line loops. 42 | the maximum number of vertices in a polygon is defined in zgl.h 43 | */ 44 | #define TGL_FEATURE_GL_POLYGON 0 45 | 46 | #define TGL_FEATURE_BLEND 1 47 | 48 | #define TGL_FEATURE_BLEND_DRAW_PIXELS 0 49 | /*The width of textures as a power of 2. The default is 8, or 256x256 textures.*/ 50 | #define TGL_FEATURE_TEXTURE_POW2 8 51 | #define TGL_FEATURE_TEXTURE_DIM (1< 110 | #define TGL_ALIGN alignas(16) 111 | #else 112 | #define TGL_ALIGN /*a comment*/ 113 | #endif 114 | 115 | 116 | #define TGL_FEATURE_16_BITS 0 117 | #define TGL_FEATURE_32_BITS 1 118 | 119 | #if TGL_FEATURE_32_BITS == 1 120 | #define TGL_FEATURE_RENDER_BITS 32 121 | 122 | #elif TGL_FEATURE_16_BITS == 1 123 | #define TGL_FEATURE_RENDER_BITS 16 124 | 125 | #else 126 | #error "Unsupported TGL_FEATURE_XX_BITS" 127 | 128 | #endif 129 | 130 | /*The fraction bits in the fixed point values used for S and T in interpolatiion.*/ 131 | #define ZB_POINT_S_FRAC_BITS 10 132 | #define ZB_POINT_T_FRAC_BITS (ZB_POINT_S_FRAC_BITS + TGL_FEATURE_TEXTURE_POW2) 133 | 134 | /*Test the compatibility of the target platform at glInit() time.*/ 135 | #define TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST 1 136 | 137 | #define TINYGL_VERSION 1.0 138 | 139 | #endif 140 | /* _tgl_features_h_ */ 141 | 142 | 143 | -------------------------------------------------------------------------------- /lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/lib/.gitkeep -------------------------------------------------------------------------------- /src/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: MultiLine 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: true 37 | SplitEmptyRecord: true 38 | SplitEmptyNamespace: true 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeBraces: Attach 41 | BreakBeforeInheritanceComma: false 42 | BreakInheritanceList: BeforeColon 43 | BreakBeforeTernaryOperators: true 44 | BreakConstructorInitializersBeforeComma: false 45 | BreakConstructorInitializers: BeforeColon 46 | BreakAfterJavaFieldAnnotations: false 47 | BreakStringLiterals: true 48 | ColumnLimit: 160 49 | CommentPragmas: '^ IWYU pragma:' 50 | CompactNamespaces: false 51 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 52 | ConstructorInitializerIndentWidth: 4 53 | ContinuationIndentWidth: 4 54 | Cpp11BracedListStyle: true 55 | DerivePointerAlignment: false 56 | DisableFormat: false 57 | ExperimentalAutoDetectBinPacking: false 58 | FixNamespaceComments: true 59 | ForEachMacros: 60 | - foreach 61 | - Q_FOREACH 62 | - BOOST_FOREACH 63 | IncludeBlocks: Preserve 64 | IncludeCategories: 65 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 66 | Priority: 2 67 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 68 | Priority: 3 69 | - Regex: '.*' 70 | Priority: 1 71 | IncludeIsMainRegex: '(Test)?$' 72 | IndentCaseLabels: false 73 | IndentPPDirectives: None 74 | IndentWidth: 4 75 | IndentWrappedFunctionNames: false 76 | JavaScriptQuotes: Leave 77 | JavaScriptWrapImports: true 78 | KeepEmptyLinesAtTheStartOfBlocks: true 79 | MacroBlockBegin: '' 80 | MacroBlockEnd: '' 81 | MaxEmptyLinesToKeep: 1 82 | NamespaceIndentation: None 83 | ObjCBinPackProtocolList: Auto 84 | ObjCBlockIndentWidth: 4 85 | ObjCSpaceAfterProperty: false 86 | ObjCSpaceBeforeProtocolList: true 87 | PenaltyBreakAssignment: 2 88 | PenaltyBreakBeforeFirstCallParameter: 19 89 | PenaltyBreakComment: 300 90 | PenaltyBreakFirstLessLess: 120 91 | PenaltyBreakString: 1000 92 | PenaltyBreakTemplateDeclaration: 10 93 | PenaltyExcessCharacter: 1000000 94 | PenaltyReturnTypeOnItsOwnLine: 60 95 | PointerAlignment: Left 96 | ReflowComments: true 97 | SortIncludes: true 98 | SortUsingDeclarations: true 99 | SpaceAfterCStyleCast: false 100 | SpaceAfterTemplateKeyword: true 101 | SpaceBeforeAssignmentOperators: true 102 | SpaceBeforeCpp11BracedList: false 103 | SpaceBeforeCtorInitializerColon: true 104 | SpaceBeforeInheritanceColon: true 105 | SpaceBeforeParens: ControlStatements 106 | SpaceBeforeRangeBasedForLoopColon: true 107 | SpaceInEmptyParentheses: false 108 | SpacesBeforeTrailingComments: 1 109 | SpacesInAngles: false 110 | SpacesInContainerLiterals: true 111 | SpacesInCStyleCastParentheses: false 112 | SpacesInParentheses: false 113 | SpacesInSquareBrackets: false 114 | Standard: Cpp11 115 | TabWidth: 4 116 | UseTab: Always 117 | ... 118 | 119 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 2 | 3 | set(tinygl_srcs 4 | accum.c 5 | api.c 6 | arrays.c 7 | clear.c 8 | clip.c 9 | get.c 10 | image_util.c 11 | init.c 12 | light.c 13 | list.c 14 | matrix.c 15 | memory.c 16 | misc.c 17 | msghandling.c 18 | select.c 19 | specbuf.c 20 | texture.c 21 | vertex.c 22 | zbuffer.c 23 | zline.c 24 | zmath.c 25 | zpostprocess.c 26 | zraster.c 27 | ztext.c 28 | ztriangle.c 29 | ) 30 | 31 | find_package(OpenMP) 32 | 33 | if(TINYGL_BUILD_SHARED) 34 | add_library(tinygl SHARED ${tinygl_srcs}) 35 | target_include_directories(tinygl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) 36 | install(TARGETS tinygl 37 | RUNTIME DESTINATION ${BIN_DIR} 38 | LIBRARY DESTINATION ${LIB_DIR} 39 | ARCHIVE DESTINATION ${LIB_DIR}) 40 | if(NOT MSVC) 41 | target_compile_options(tinygl PRIVATE -O3 -DNDEBUG -pedantic -Wall -Wno-unused-function) 42 | if(NOT CMAKE_CROSSCOMPILING) 43 | target_compile_options(tinygl PRIVATE -march=native) 44 | endif(NOT CMAKE_CROSSCOMPILING) 45 | endif(NOT MSVC) 46 | if(OPENMP_C_FOUND) 47 | target_link_libraries(tinygl PUBLIC OpenMP::OpenMP_C) 48 | endif(OPENMP_C_FOUND) 49 | endif(TINYGL_BUILD_SHARED) 50 | 51 | if(TINYGL_BUILD_STATIC) 52 | add_library(tinygl-static STATIC ${tinygl_srcs}) 53 | target_include_directories(tinygl-static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include) 54 | install(TARGETS tinygl-static 55 | RUNTIME DESTINATION ${BIN_DIR} 56 | LIBRARY DESTINATION ${LIB_DIR} 57 | ARCHIVE DESTINATION ${LIB_DIR}) 58 | if(NOT MSVC) 59 | target_compile_options(tinygl-static PRIVATE -O3 -DNDEBUG -pedantic -Wall -Wno-unused-function) 60 | if(NOT CMAKE_CROSSCOMPILING) 61 | target_compile_options(tinygl-static PRIVATE -march=native) 62 | endif(NOT CMAKE_CROSSCOMPILING) 63 | endif(NOT MSVC) 64 | if(OPENMP_C_FOUND) 65 | target_link_libraries(tinygl-static PUBLIC OpenMP::OpenMP_C) 66 | endif(OPENMP_C_FOUND) 67 | endif(TINYGL_BUILD_STATIC) 68 | 69 | # Local Variables: 70 | # tab-width: 8 71 | # mode: cmake 72 | # indent-tabs-mode: t 73 | # End: 74 | # ex: shiftwidth=2 tabstop=8 75 | 76 | -------------------------------------------------------------------------------- /src/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice: 2 | 3 | (C) 1997-2021 Fabrice Bellard, Gek (DMHSW), C-Chads 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product and its documentation 16 | *is* required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | If you redistribute modified sources, I would appreciate that you 22 | include in the files history information documenting your changes. 23 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | include ../config.mk 2 | 3 | OBJS= api.o list.o vertex.o init.o matrix.o texture.o \ 4 | misc.o clear.o light.o clip.o select.o get.o \ 5 | zbuffer.o zline.o ztriangle.o \ 6 | zmath.o image_util.o msghandling.o \ 7 | arrays.o specbuf.o memory.o ztext.o zraster.o accum.o zpostprocess.o 8 | 9 | 10 | INCLUDES = -I./include 11 | LIB = libTinyGL.a 12 | 13 | all: $(LIB) 14 | 15 | $(LIB): $(OBJS) 16 | rm -f $(LIB) 17 | ar rcs $(LIB) $(OBJS) 18 | clean: 19 | rm -f *~ *.o *.a 20 | .c.o: 21 | $(CC) $(CFLAGS_LIB) -c $*.c 22 | -------------------------------------------------------------------------------- /src/Makefile_Backup: -------------------------------------------------------------------------------- 1 | include ../config.mk 2 | 3 | OBJS= api.o list.o vertex.o init.o matrix.o texture.o \ 4 | misc.o clear.o light.o clip.o select.o get.o \ 5 | zbuffer.o zline.o ztriangle.o \ 6 | zmath.o image_util.o msghandling.o \ 7 | arrays.o specbuf.o memory.o ztext.o zraster.o accum.o 8 | 9 | 10 | INCLUDES = -I./include 11 | LIB = libTinyGL.a 12 | 13 | all: $(LIB) 14 | # mv $(LIB) ../lib/ 15 | 16 | $(LIB): $(OBJS) 17 | rm -f $(LIB) 18 | ar rcs $(LIB) $(OBJS) 19 | 20 | #SDL_Examples: 21 | # cd SDL_Examples && $(MAKE) && cd .. 22 | clean: 23 | rm -f *~ *.o *.a 24 | # cd SDL_Examples && $(MAKE) clean && cd .. 25 | .c.o: 26 | $(CC) $(CFLAGS) $(INCLUDES) -c $*.c 27 | 28 | clip.o: zgl.h ../include/zfeatures.h 29 | vertex.o: zgl.h ../include/zfeatures.h 30 | light.o: zgl.h ../include/zfeatures.h 31 | matrix.o: zgl.h ../include/zfeatures.h 32 | list.o: zgl.h opinfo.h ../include/zfeatures.h 33 | arrays.c: zgl.h ../include/zfeatures.h 34 | specbuf.o: zgl.h ../include/zfeatures.h 35 | glx.o: zgl.h ../include/zfeatures.h 36 | nglx.o: zgl.h ../include/zfeatures.h 37 | zline.o: zgl.h ../include/zfeatures.h zline.h 38 | 39 | ztriangle.o: ztriangle.c ztriangle.h zgl.h ../include/zfeatures.h 40 | $(CC) $(CFLAGS) -Wno-uninitialized $(INCLUDES) -c $*.c 41 | -------------------------------------------------------------------------------- /src/accum.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | -------------------------------------------------------------------------------- /src/clear.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | void glopClearColor(GLParam* p) { 4 | GLContext* c = gl_get_context(); 5 | c->clear_color.v[0] = p[1].f; 6 | c->clear_color.v[1] = p[2].f; 7 | c->clear_color.v[2] = p[3].f; 8 | c->clear_color.v[3] = p[4].f; 9 | } 10 | void glopClearDepth(GLParam* p) { 11 | GLContext* c = gl_get_context(); 12 | c->clear_depth = p[1].f; 13 | } 14 | 15 | void glopClear(GLParam* p) { 16 | GLContext* c = gl_get_context(); 17 | GLint mask = p[1].i; 18 | GLint z = 0; 19 | GLint r = (GLint)(c->clear_color.v[0] * COLOR_MULT_MASK); 20 | GLint g = (GLint)(c->clear_color.v[1] * COLOR_MULT_MASK); 21 | GLint b = (GLint)(c->clear_color.v[2] * COLOR_MULT_MASK); 22 | 23 | /* TODO : correct value of Z */ 24 | 25 | ZB_clear(c->zb, mask & GL_DEPTH_BUFFER_BIT, z, mask & GL_COLOR_BUFFER_BIT, r, g, b); 26 | } 27 | -------------------------------------------------------------------------------- /src/code_format.sh: -------------------------------------------------------------------------------- 1 | clang-format-8 -i *.c *.h --style=file 2 | -------------------------------------------------------------------------------- /src/error_check.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RETVAL 3 | #define RETVAL /* a comment*/ 4 | #endif 5 | 6 | #if TGL_FEATURE_ERROR_CHECK == 1 7 | 8 | 9 | 10 | #ifndef ERROR_FLAG 11 | 12 | 13 | 14 | #if TGL_FEATURE_STRICT_OOM_CHECKS == 1 15 | if (c->error_flag == GL_OUT_OF_MEMORY) 16 | return RETVAL; 17 | #endif 18 | 19 | 20 | #elif ERROR_FLAG != GL_OUT_OF_MEMORY 21 | { 22 | c->error_flag = ERROR_FLAG; 23 | return RETVAL; 24 | } 25 | 26 | #else 27 | { 28 | c->error_flag = GL_OUT_OF_MEMORY; 29 | return RETVAL; 30 | } 31 | #endif 32 | 33 | 34 | 35 | #endif 36 | 37 | 38 | 39 | #undef RETVAL 40 | #undef ERROR_FLAG 41 | -------------------------------------------------------------------------------- /src/error_check_no_context.h: -------------------------------------------------------------------------------- 1 | #ifndef RETVAL 2 | #define RETVAL /* a comment*/ 3 | #endif 4 | 5 | #if TGL_FEATURE_ERROR_CHECK == 1 6 | 7 | 8 | #if TGL_FEATURE_STRICT_OOM_CHECKS == 1 9 | GLContext* c = gl_get_context(); 10 | if (c->error_flag == GL_OUT_OF_MEMORY) 11 | return RETVAL; 12 | #elif defined(NEED_CONTEXT) 13 | GLContext* c = gl_get_context(); 14 | #endif 15 | 16 | #endif 17 | 18 | #undef RETVAL 19 | #undef NEED_CONTEXT 20 | -------------------------------------------------------------------------------- /src/image_util.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | /* 4 | * image conversion 5 | */ 6 | 7 | void gl_convertRGB_to_5R6G5B(GLushort* pixmap, GLubyte* rgb, GLint xsize, GLint ysize) { 8 | GLint i, n; 9 | GLubyte* p; 10 | 11 | p = rgb; 12 | n = xsize * ysize; 13 | for (i = 0; i < n; i++) { 14 | pixmap[i] = ((p[0] & 0xF8) << 8) | ((p[1] & 0xFC) << 3) | ((p[2] & 0xF8) >> 3); 15 | p += 3; 16 | } 17 | } 18 | 19 | /* 20 | This actually converts to ARGB!!! 21 | This is the format of the entire engine!!! 22 | */ 23 | void gl_convertRGB_to_8A8R8G8B(GLuint* pixmap, GLubyte* rgb, GLint xsize, GLint ysize) { 24 | GLint i, n; 25 | GLubyte* p; 26 | 27 | p = rgb; 28 | n = xsize * ysize; 29 | for (i = 0; i < n; i++) { 30 | pixmap[i] = (((GLuint)p[0]) << 16) | (((GLuint)p[1]) << 8) | (((GLuint)p[2])); 31 | p += 3; 32 | } 33 | } 34 | 35 | /* 36 | * linear GLinterpolation with xf,yf normalized to 2^16 37 | */ 38 | 39 | #define INTERP_NORM_BITS 16 40 | #define INTERP_NORM (1 << INTERP_NORM_BITS) 41 | 42 | static GLint GLinterpolate_imutil(GLint v00, GLint v01, GLint v10, GLint xf, GLint yf) { 43 | return v00 + (((v01 - v00) * xf + (v10 - v00) * yf) >> INTERP_NORM_BITS); 44 | } 45 | 46 | /* 47 | * TODO: more accurate resampling 48 | */ 49 | 50 | void gl_resizeImage(GLubyte* dest, GLint xsize_dest, GLint ysize_dest, GLubyte* src, GLint xsize_src, GLint ysize_src) { 51 | GLubyte *pix, *pix_src; 52 | GLfloat x1, y1, x1inc, y1inc; 53 | GLint xi, yi, j, xf, yf, x, y; 54 | 55 | pix = dest; 56 | pix_src = src; 57 | 58 | x1inc = (GLfloat)(xsize_src - 1) / (GLfloat)(xsize_dest - 1); 59 | y1inc = (GLfloat)(ysize_src - 1) / (GLfloat)(ysize_dest - 1); 60 | 61 | y1 = 0; 62 | for (y = 0; y < ysize_dest; y++) { 63 | x1 = 0; 64 | for (x = 0; x < xsize_dest; x++) { 65 | xi = (GLint)x1; 66 | yi = (GLint)y1; 67 | xf = (GLint)((x1 - floor(x1)) * INTERP_NORM); 68 | yf = (GLint)((y1 - floor(y1)) * INTERP_NORM); 69 | 70 | if ((xf + yf) <= INTERP_NORM) { 71 | for (j = 0; j < 3; j++) { 72 | pix[j] = GLinterpolate_imutil(pix_src[(yi * xsize_src + xi) * 3 + j], pix_src[(yi * xsize_src + xi + 1) * 3 + j], 73 | pix_src[((yi + 1) * xsize_src + xi) * 3 + j], xf, yf); 74 | } 75 | } else { 76 | xf = INTERP_NORM - xf; 77 | yf = INTERP_NORM - yf; 78 | for (j = 0; j < 3; j++) { 79 | pix[j] = GLinterpolate_imutil(pix_src[((yi + 1) * xsize_src + xi + 1) * 3 + j], pix_src[((yi + 1) * xsize_src + xi) * 3 + j], 80 | pix_src[(yi * xsize_src + xi + 1) * 3 + j], xf, yf); 81 | } 82 | } 83 | 84 | pix += 3; 85 | x1 += x1inc; 86 | } 87 | y1 += y1inc; 88 | } 89 | 90 | } 91 | 92 | #define FRAC_BITS 16 93 | 94 | /* resizing with no GLinterlating nor nearest pixel */ 95 | 96 | void gl_resizeImageNoInterpolate(GLubyte* dest, GLint xsize_dest, GLint ysize_dest, GLubyte* src, GLint xsize_src, GLint ysize_src) { 97 | GLubyte *pix, *pix_src, *pix1; 98 | GLint x1, y1, x1inc, y1inc; 99 | GLint xi, yi, x, y; 100 | 101 | pix = dest; 102 | pix_src = src; 103 | 104 | x1inc = (GLint)((GLfloat)((xsize_src) << FRAC_BITS) / (GLfloat)(xsize_dest)); 105 | y1inc = (GLint)((GLfloat)((ysize_src) << FRAC_BITS) / (GLfloat)(ysize_dest)); 106 | 107 | y1 = 0; 108 | for (y = 0; y < ysize_dest; y++) { 109 | x1 = 0; 110 | for (x = 0; x < xsize_dest; x++) { 111 | xi = x1 >> FRAC_BITS; 112 | yi = y1 >> FRAC_BITS; 113 | pix1 = pix_src + (yi * xsize_src + xi) * 3; 114 | 115 | pix[0] = pix1[0]; 116 | pix[1] = pix1[1]; 117 | pix[2] = pix1[2]; 118 | 119 | pix += 3; 120 | x1 += x1inc; 121 | } 122 | y1 += y1inc; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | GLContext gl_ctx; 4 | static const GLContext empty_gl_ctx = {0}; 5 | 6 | static void initSharedState(GLContext* c) { 7 | GLSharedState* s = &c->shared_state; 8 | s->lists = gl_zalloc(sizeof(GLList*) * MAX_DISPLAY_LISTS); 9 | if (!s->lists) 10 | gl_fatal_error("TINYGL_CANNOT_INIT_OOM"); 11 | s->texture_hash_table = gl_zalloc(sizeof(GLTexture*) * TEXTURE_HASH_TABLE_SIZE); 12 | if (!s->texture_hash_table) 13 | gl_fatal_error("TINYGL_CANNOT_INIT_OOM"); 14 | s->buffers = gl_zalloc(sizeof(GLBuffer*) * MAX_BUFFERS); 15 | if (!s->buffers) 16 | gl_fatal_error("TINYGL_CANNOT_INIT_OOM"); 17 | alloc_texture(0); 18 | #include "error_check.h" 19 | } 20 | 21 | static void endSharedState(GLContext* c) { 22 | GLSharedState* s = &c->shared_state; 23 | GLint i; 24 | GLList* l; 25 | GLParamBuffer *pb, *pb1; 26 | GLTexture *t, *n; 27 | for (i = 0; i < MAX_DISPLAY_LISTS; i++) 28 | if (s->lists[i]) { 29 | l = s->lists[i]; 30 | pb = l->first_op_buffer; 31 | while (pb != NULL) { 32 | pb1 = pb->next; 33 | gl_free(pb); 34 | pb = pb1; 35 | } 36 | gl_free(l); 37 | s->lists[i] = NULL; 38 | } 39 | gl_free(s->lists); 40 | for (i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) { 41 | t = s->texture_hash_table[i]; 42 | while (t) { 43 | GLTexture** ht; 44 | if (t->prev == NULL) { 45 | ht = &c->shared_state.texture_hash_table[t->handle & TEXTURE_HASH_TABLE_MASK]; 46 | *ht = t->next; 47 | } else { 48 | t->prev->next = t->next; 49 | } 50 | n = t->next; 51 | if (t->next != NULL) 52 | t->next->prev = t->prev; 53 | gl_free(t); 54 | t = n; 55 | } 56 | } 57 | gl_free(s->texture_hash_table); 58 | for (i = 0; i < MAX_BUFFERS; i++) { 59 | if (s->buffers[i]) { 60 | if (s->buffers[i]->data) { 61 | gl_free(s->buffers[i]->data); 62 | } 63 | gl_free(s->buffers[i]); 64 | } 65 | } 66 | gl_free(s->buffers); 67 | } 68 | 69 | #if TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST == 1 70 | 71 | #define TGL_FLOAT_ERR(a, b) ((a - b) / b) 72 | static int TinyGLRuntimeCompatibilityTest() { 73 | GLfloat t = -0, tf2; 74 | GLint t2 = 1 << 31; 75 | memcpy(&tf2, &t2, 4); 76 | if (tf2 != t) return 1; 77 | t2 = 3212836864; 78 | t = -1; 79 | memcpy(&tf2, &t2, 4); 80 | if (tf2 != t)return 1; 81 | 82 | if (((GLint)255 << 8) != 65280) 83 | return 1; 84 | if ((GLint)65280 >> 8 != 255) 85 | return 1; 86 | if (((GLint)-1) >> 14 != -1) 87 | return 1; 88 | if (((GLuint)255 << 8) != 65280) 89 | return 1; 90 | if ((GLuint)65280 >> 8 != 255) 91 | return 1; 92 | if (((GLushort)255 << 8) != 65280) 93 | return 1; 94 | if ((GLushort)65280 >> 8 != 255) 95 | return 1; 96 | if (((GLshort)255 << 8) != 65280) 97 | return 1; 98 | if ((GLshort)65280 >> 8 != -1) 99 | return 1; 100 | #if TGL_FEATURE_FISR == 1 101 | t = fastInvSqrt(37); 102 | tf2 = 1.0 / sqrt(37); 103 | if (TGL_FLOAT_ERR(t, tf2) > 0.05) 104 | return 1; 105 | t = fastInvSqrt(59); 106 | tf2 = 1.0 / sqrt(59); 107 | if (TGL_FLOAT_ERR(t, tf2) > 0.05) 108 | return 1; 109 | t = fastInvSqrt(1023); 110 | tf2 = 1.0 / sqrt(1023); 111 | if (TGL_FLOAT_ERR(t, tf2) > 0.05) 112 | return 1; 113 | 114 | t = fastInvSqrt(10000); 115 | tf2 = 1.0 / sqrt(10000); 116 | if (TGL_FLOAT_ERR(t, tf2) > 0.05) 117 | return 1; 118 | #endif 119 | { 120 | GLint i; 121 | GLuint buf1[10]; 122 | GLuint buf2[10]; 123 | for (i = 0; i < 10; i++) 124 | buf1[i] = (1023 << i) + i + i % -1; 125 | for (i = 0; i < 10; i++) 126 | buf2[i] = (14 << i) + i + i % -4; 127 | memcpy(buf1, buf2, 10 * 4); 128 | for (i = 0; i < 10; i++) 129 | if (buf2[i] != buf1[i]) 130 | return 1; 131 | } 132 | if (sizeof(void*) < 4) 133 | return 1; 134 | /* ZALLOC TEST*/ 135 | { 136 | GLint i, j; 137 | for (i = 0; i < 10; i++) { 138 | GLubyte* data = gl_zalloc(1024); 139 | if (!data) 140 | return 1; 141 | for (j = 0; j < 1024; j++) 142 | if (data[j] != 0) 143 | return 1; 144 | gl_free(data); 145 | } 146 | } 147 | return 0; 148 | } 149 | #endif 150 | 151 | void glInit(void* zbuffer1) { 152 | GLContext* c; 153 | GLViewport* v; 154 | GLint i; 155 | ZBuffer* zbuffer = (ZBuffer*)zbuffer1; 156 | #if TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST == 1 157 | if (TinyGLRuntimeCompatibilityTest()) 158 | gl_fatal_error("TINYGL_FAILED_RUNTIME_COMPAT_TEST"); 159 | #endif 160 | gl_ctx = empty_gl_ctx; 161 | c = &gl_ctx; 162 | if (!c) 163 | gl_fatal_error("TINYGL_CANNOT_INIT_OOM"); 164 | 165 | c->zb = zbuffer; 166 | #if TGL_FEATURE_ERROR_CHECK == 1 167 | c->error_flag = GL_NO_ERROR; 168 | #endif 169 | /* allocate GLVertex array */ 170 | /*c->vertex_max = POLYGON_MAX_VERTEX;*/ 171 | /*c->vertex = gl_malloc(POLYGON_MAX_VERTEX * sizeof(GLVertex));*/ 172 | /*if(!c->vertex) gl_fatal_error("TINYGL_CANNOT_INIT_OOM");*/ 173 | /* viewport */ 174 | v = &c->viewport; 175 | v->xmin = 0; 176 | v->ymin = 0; 177 | v->xsize = zbuffer->xsize; 178 | v->ysize = zbuffer->ysize; 179 | gl_eval_viewport(); 180 | /* buffer stuff GL 1.1 */ 181 | c->drawbuffer = GL_FRONT; 182 | c->readbuffer = GL_FRONT; 183 | /* shared state */ 184 | initSharedState(c); 185 | /* ztext */ 186 | c->textsize = 1; 187 | /* buffer */ 188 | c->boundarraybuffer = 0; 189 | c->boundvertexbuffer = 0; 190 | c->boundcolorbuffer = 0; 191 | c->boundnormalbuffer = 0; 192 | c->boundtexcoordbuffer = 0; 193 | /* lists */ 194 | 195 | c->exec_flag = 1; 196 | c->compile_flag = 0; 197 | c->print_flag = 0; 198 | c->listbase = 0; 199 | c->in_begin = 0; 200 | 201 | /* lights */ 202 | for (i = 0; i < MAX_LIGHTS; i++) { 203 | GLLight* l = &c->lights[i]; 204 | l->ambient = gl_V4_New(0, 0, 0, 1); 205 | l->diffuse = gl_V4_New(1, 1, 1, 1); 206 | l->specular = gl_V4_New(1, 1, 1, 1); 207 | l->position = gl_V4_New(0, 0, 1, 0); 208 | l->norm_position = gl_V3_New(0, 0, 1); 209 | l->spot_direction = gl_V3_New(0, 0, -1); 210 | l->norm_spot_direction = gl_V3_New(0, 0, -1); 211 | l->spot_exponent = 0; 212 | l->spot_cutoff = 180; 213 | l->attenuation[0] = 1; 214 | l->attenuation[1] = 0; 215 | l->attenuation[2] = 0; 216 | l->enabled = 0; 217 | } 218 | c->first_light = NULL; 219 | c->ambient_light_model = gl_V4_New(0.2, 0.2, 0.2, 1); 220 | c->local_light_model = 0; 221 | c->lighting_enabled = 0; 222 | c->light_model_two_side = 0; 223 | 224 | /* default materials */ 225 | for (i = 0; i < 2; i++) { 226 | GLMaterial* m = &c->materials[i]; 227 | m->emission = gl_V4_New(0, 0, 0, 1); 228 | m->ambient = gl_V4_New(0.2, 0.2, 0.2, 1); 229 | m->diffuse = gl_V4_New(0.8, 0.8, 0.8, 1); 230 | m->specular = gl_V4_New(0, 0, 0, 1); 231 | m->shininess = 0; 232 | } 233 | c->current_color_material_mode = GL_FRONT_AND_BACK; 234 | c->current_color_material_type = GL_AMBIENT_AND_DIFFUSE; 235 | c->color_material_enabled = 0; 236 | 237 | /* textures */ 238 | /*glInitTextures(c);*/ 239 | glInitTextures(); //Bug Fix! 240 | 241 | /* blending */ 242 | c->zb->enable_blend = 0; 243 | c->zb->sfactor = GL_ONE; 244 | c->zb->dfactor = GL_ZERO; 245 | c->zb->blendeq = GL_FUNC_ADD; 246 | 247 | /* default state */ 248 | c->current_color.X = 1.0; 249 | c->current_color.Y = 1.0; 250 | c->current_color.Z = 1.0; 251 | c->current_color.W = 0.0; 252 | 253 | c->current_normal.X = 1.0; 254 | c->current_normal.Y = 0.0; 255 | c->current_normal.Z = 0.0; 256 | c->current_normal.W = 0.0; 257 | 258 | c->current_edge_flag = 1; 259 | 260 | c->current_tex_coord.X = 0; 261 | c->current_tex_coord.Y = 0; 262 | c->current_tex_coord.Z = 0; 263 | c->current_tex_coord.W = 1; 264 | 265 | c->polygon_mode_front = GL_FILL; 266 | c->polygon_mode_back = GL_FILL; 267 | 268 | c->current_front_face = 0; /* 0 = GL_CCW 1 = GL_CW */ 269 | c->current_cull_face = GL_BACK; 270 | c->current_shade_model = GL_SMOOTH; 271 | c->cull_face_enabled = 0; 272 | 273 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 274 | c->zb->dostipple = 0; 275 | for (i = 0; i < 128; i++) 276 | c->zb->stipplepattern[i] = 0xFF; 277 | #endif 278 | /* clear */ 279 | c->clear_color.v[0] = 0; 280 | c->clear_color.v[1] = 0; 281 | c->clear_color.v[2] = 0; 282 | c->clear_color.v[3] = 0; 283 | c->clear_depth = 0; 284 | 285 | /* selection */ 286 | #if TGL_FEATURE_ALT_RENDERMODES == 1 287 | c->render_mode = GL_RENDER; 288 | c->select_buffer = NULL; 289 | c->name_stack_size = 0; 290 | 291 | /* feedback */ 292 | c->feedback_buffer = NULL; 293 | c->feedback_ptr = NULL; 294 | c->feedback_size = 0; 295 | c->feedback_hits = 0; 296 | c->feedback_overflow = 0; 297 | #endif 298 | /* matrix */ 299 | c->matrix_mode = 0; 300 | 301 | c->matrix_stack_depth_max[0] = MAX_MODELVIEW_STACK_DEPTH; 302 | c->matrix_stack_depth_max[1] = MAX_PROJECTION_STACK_DEPTH; 303 | c->matrix_stack_depth_max[2] = MAX_TEXTURE_STACK_DEPTH; 304 | 305 | for (i = 0; i < 3; i++) { 306 | c->matrix_stack[i] = gl_zalloc(c->matrix_stack_depth_max[i] * sizeof(M4)); 307 | if (!(c->matrix_stack[i])) 308 | gl_fatal_error("TINYGL_CANNOT_INIT_OOM"); 309 | c->matrix_stack_ptr[i] = c->matrix_stack[i]; 310 | } 311 | 312 | glMatrixMode(GL_PROJECTION); 313 | glLoadIdentity(); 314 | glMatrixMode(GL_TEXTURE); 315 | glLoadIdentity(); 316 | glMatrixMode(GL_MODELVIEW); 317 | glLoadIdentity(); 318 | 319 | c->matrix_model_projection_updated = 1; 320 | 321 | /* opengl 1.1 arrays */ 322 | c->client_states = 0; 323 | 324 | /* opengl 1.1 polygon offset */ 325 | c->offset_states = 0; 326 | 327 | /* clear the resize callback function pointer */ 328 | c->gl_resize_viewport = NULL; 329 | 330 | /* specular buffer */ 331 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 332 | c->specbuf_first = NULL; 333 | c->specbuf_used_counter = 0; 334 | c->specbuf_num_buffers = 0; 335 | #endif 336 | c->zEnableSpecular = 0; 337 | /* depth test */ 338 | c->zb->depth_test = 0; 339 | c->zb->depth_write = 1; 340 | c->zb->pointsize = 1; 341 | 342 | /* raster position */ 343 | c->rasterpos.X = 0; 344 | c->rasterpos.Y = 0; 345 | c->rasterpos.Z = 0; 346 | c->rasterpos.W = 1; 347 | 348 | c->rastervertex.pc.X = 0; 349 | c->rastervertex.pc.Y = 0; 350 | c->rastervertex.pc.Z = 0; 351 | c->rastervertex.pc.W = 1; 352 | c->rasterposvalid = 0; 353 | c->pzoomx = 1; 354 | c->pzoomy = 1; 355 | } 356 | 357 | void glClose(void) { 358 | 359 | GLuint i; 360 | GLContext* c = gl_get_context(); 361 | for (i = 0; i < 3; i++) { 362 | gl_free(c->matrix_stack[i]); 363 | } 364 | i = 0; 365 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 366 | { 367 | GLSpecBuf *b, *n = NULL; 368 | for (b = c->specbuf_first; b != NULL; b = n) { 369 | n = b->next; 370 | gl_free(b); 371 | i++; 372 | } 373 | } 374 | #endif 375 | endSharedState(c); 376 | gl_ctx = empty_gl_ctx; 377 | } 378 | -------------------------------------------------------------------------------- /src/light.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | 4 | void glopMaterial(GLParam* p) { 5 | GLContext* c = gl_get_context(); 6 | GLint mode = p[1].i; 7 | GLint type = p[2].i; 8 | GLfloat v[4]; 9 | v[0] = p[3].f; 10 | v[1] = p[4].f; 11 | v[2] = p[5].f; 12 | v[3] = p[6].f; 13 | GLint i; 14 | GLMaterial* m; 15 | 16 | if (mode == GL_FRONT_AND_BACK) { 17 | p[1].i = GL_FRONT; 18 | glopMaterial(p); 19 | mode = GL_BACK; 20 | } 21 | if (mode == GL_FRONT) 22 | m = &c->materials[0]; 23 | else 24 | m = &c->materials[1]; 25 | 26 | switch (type) { 27 | case GL_EMISSION: 28 | for (i = 0; i < 4; i++) 29 | m->emission.v[i] = clampf(v[i], 0, 1); 30 | break; 31 | case GL_AMBIENT: 32 | for (i = 0; i < 4; i++) 33 | m->ambient.v[i] = clampf(v[i], 0, 1); 34 | break; 35 | case GL_DIFFUSE: 36 | for (i = 0; i < 4; i++) 37 | m->diffuse.v[i] = clampf(v[i], 0, 1); 38 | break; 39 | case GL_SPECULAR: 40 | for (i = 0; i < 4; i++) 41 | m->specular.v[i] = clampf(v[i], 0, 1); 42 | break; 43 | case GL_SHININESS: 44 | m->shininess = v[0]; 45 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 46 | m->shininess_i = (v[0] / 128.0f) * SPECULAR_BUFFER_SIZE; 47 | #endif 48 | break; 49 | case GL_AMBIENT_AND_DIFFUSE: 50 | for (i = 0; i < 4; i++) 51 | m->diffuse.v[i] = clampf(v[i], 0, 1); 52 | 53 | for (i = 0; i < 4; i++) 54 | m->ambient.v[i] = clampf(v[i], 0, 1); 55 | break; 56 | 57 | #if TGL_FEATURE_ERROR_CHECK == 1 58 | default: 59 | #define ERROR_FLAG GL_INVALID_ENUM 60 | #include "error_check.h" 61 | #else 62 | /* default: return;*/ 63 | #endif 64 | } 65 | } 66 | 67 | void glopColorMaterial(GLParam* p) { 68 | GLContext* c = gl_get_context(); 69 | GLint mode = p[1].i; 70 | GLint type = p[2].i; 71 | 72 | c->current_color_material_mode = mode; 73 | c->current_color_material_type = type; 74 | } 75 | 76 | void glopLight(GLParam* p) { 77 | GLContext* c = gl_get_context(); 78 | GLint light = p[1].i; 79 | GLint type = p[2].i; 80 | V4 v; 81 | GLLight* l; 82 | GLint i; 83 | 84 | /* assert(light >= GL_LIGHT0 && light < GL_LIGHT0 + MAX_LIGHTS);*/ 85 | 86 | #if TGL_FEATURE_ERROR_CHECK == 1 87 | if (!(light >= GL_LIGHT0 && light < GL_LIGHT0 + MAX_LIGHTS)) 88 | #define ERROR_FLAG GL_INVALID_OPERATION 89 | #include "error_check.h" 90 | 91 | #else 92 | /* if(!(light >= GL_LIGHT0 && light < GL_LIGHT0 + MAX_LIGHTS)) return;*/ 93 | #endif 94 | 95 | l = &c->lights[light - GL_LIGHT0]; 96 | 97 | for (i = 0; i < 4; i++) 98 | if (type != GL_POSITION && type != GL_SPOT_DIRECTION && type != GL_SPOT_EXPONENT && type != GL_SPOT_CUTOFF && type != GL_LINEAR_ATTENUATION && 99 | type != GL_CONSTANT_ATTENUATION && type != GL_QUADRATIC_ATTENUATION) 100 | v.v[i] = clampf(p[3 + i].f, 0, 1); 101 | else 102 | v.v[i] = p[3 + i].f; 103 | 104 | switch (type) { 105 | case GL_AMBIENT: 106 | l->ambient = v; 107 | break; 108 | case GL_DIFFUSE: 109 | l->diffuse = v; 110 | break; 111 | case GL_SPECULAR: 112 | l->specular = v; 113 | break; 114 | case GL_POSITION: { 115 | V4 pos; 116 | gl_M4_MulV4(&pos, c->matrix_stack_ptr[0], &v); 117 | 118 | l->position = pos; 119 | 120 | if (l->position.v[3] == 0) { 121 | l->norm_position.X = pos.X; 122 | l->norm_position.Y = pos.Y; 123 | l->norm_position.Z = pos.Z; 124 | /* gl_V3_Norm(&l->norm_position);*/ 125 | gl_V3_Norm_Fast(&l->norm_position); 126 | } 127 | } break; 128 | case GL_SPOT_DIRECTION: 129 | for (i = 0; i < 3; i++) { 130 | l->spot_direction.v[i] = v.v[i]; 131 | l->norm_spot_direction.v[i] = v.v[i]; 132 | } 133 | gl_V3_Norm_Fast(&l->norm_spot_direction); 134 | break; 135 | case GL_SPOT_EXPONENT: 136 | l->spot_exponent = v.v[0]; 137 | break; 138 | case GL_SPOT_CUTOFF: { 139 | GLfloat a = v.v[0]; 140 | 141 | #if TGL_FEATURE_ERROR_CHECK == 1 142 | #define ERROR_FLAG GL_INVALID_VALUE 143 | #include "error_check.h" 144 | #else 145 | /* assert(a == 180 || (a >= 0 && a <= 90));*/ 146 | #endif 147 | 148 | l->spot_cutoff = a; 149 | if (a != 180) 150 | l->cos_spot_cutoff = cos(a * M_PI / 180.0); 151 | } break; 152 | case GL_CONSTANT_ATTENUATION: 153 | l->attenuation[0] = v.v[0]; 154 | break; 155 | case GL_LINEAR_ATTENUATION: 156 | l->attenuation[1] = v.v[0]; 157 | break; 158 | case GL_QUADRATIC_ATTENUATION: 159 | l->attenuation[2] = v.v[0]; 160 | break; 161 | default: 162 | #if TGL_FEATURE_ERROR_CHECK == 1 163 | #define ERROR_FLAG GL_INVALID_ENUM 164 | #include "error_check.h" 165 | #endif 166 | return; 167 | } 168 | } 169 | 170 | void glopLightModel(GLParam* p) { 171 | GLContext* c = gl_get_context(); 172 | GLint pname = p[1].i; 173 | GLint* v = &p[2].i; 174 | GLint i; 175 | 176 | switch (pname) { 177 | case GL_LIGHT_MODEL_AMBIENT: 178 | for (i = 0; i < 4; i++) 179 | c->ambient_light_model.v[i] = p[2 + i].f; 180 | break; 181 | case GL_LIGHT_MODEL_LOCAL_VIEWER: 182 | c->local_light_model = (GLint)v[0]; 183 | break; 184 | case GL_LIGHT_MODEL_TWO_SIDE: 185 | c->light_model_two_side = (GLint)v[0]; 186 | break; 187 | default: 188 | #if TGL_FEATURE_ERROR_CHECK == 1 189 | #define ERROR_FLAG GL_INVALID_ENUM 190 | #include "error_check.h" 191 | #endif 192 | /* 193 | tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname); 194 | assert(0); 195 | */ 196 | break; 197 | } 198 | } 199 | 200 | void gl_enable_disable_light(GLint light, GLint v) { 201 | GLContext* c = gl_get_context(); 202 | GLLight* l = &c->lights[light]; 203 | if (v && !l->enabled) { 204 | l->enabled = 1; 205 | l->next = c->first_light; 206 | c->first_light = l; 207 | l->prev = NULL; 208 | } else if (!v && l->enabled) { 209 | l->enabled = 0; 210 | if (l->prev == NULL) 211 | c->first_light = l->next; 212 | else 213 | l->prev->next = l->next; 214 | if (l->next != NULL) 215 | l->next->prev = l->prev; 216 | } 217 | } 218 | 219 | 220 | void glSetEnableSpecular(GLint s) { 221 | GLParam p[2]; 222 | #include "error_check_no_context.h" 223 | p[1].i = s; 224 | p[0].op = OP_SetEnableSpecular; 225 | gl_add_op(p); 226 | } 227 | void glopSetEnableSpecular(GLParam* p) { 228 | 229 | gl_get_context()->zEnableSpecular = p[1].i; 230 | } 231 | /* non optimized lightening model */ 232 | void gl_shade_vertex(GLVertex* v) { 233 | GLContext* c = gl_get_context(); 234 | GLfloat R, G, B, A; 235 | GLMaterial* m; 236 | GLLight* l; 237 | V3 n, s, d; 238 | GLfloat dist=0, tmp, att, dot, dot_spot, dot_spec; 239 | GLint twoside = c->light_model_two_side; 240 | 241 | m = &c->materials[0]; 242 | 243 | n.X = v->normal.X; 244 | n.Y = v->normal.Y; 245 | n.Z = v->normal.Z; 246 | 247 | R = m->emission.v[0] + m->ambient.v[0] * c->ambient_light_model.v[0]; 248 | G = m->emission.v[1] + m->ambient.v[1] * c->ambient_light_model.v[1]; 249 | B = m->emission.v[2] + m->ambient.v[2] * c->ambient_light_model.v[2]; 250 | A = m->diffuse.v[3]; 251 | 252 | for (l = c->first_light; l != NULL; l = l->next) { 253 | 254 | 255 | 256 | GLfloat lR, lB, lG; 257 | 258 | /* ambient */ 259 | lR = l->ambient.v[0] * m->ambient.v[0]; 260 | lG = l->ambient.v[1] * m->ambient.v[1]; 261 | lB = l->ambient.v[2] * m->ambient.v[2]; 262 | 263 | if (l->position.v[3] == 0) { 264 | /* light at infinity */ 265 | /* Fixed by Gek, it used to use the unnormalized position?*/ 266 | d.X = l->norm_position.v[0]; 267 | d.Y = l->norm_position.v[1]; 268 | d.Z = l->norm_position.v[2]; 269 | att = 1; 270 | } else { 271 | /* distance attenuation */ 272 | d.X = l->position.v[0] - v->ec.v[0]; 273 | d.Y = l->position.v[1] - v->ec.v[1]; 274 | d.Z = l->position.v[2] - v->ec.v[2]; 275 | #if TGL_FEATURE_FISR == 1 276 | tmp = fastInvSqrt(d.X * d.X + d.Y * d.Y + d.Z * d.Z); /* FISR IMPL, MATCHED!*/ 277 | { 278 | d.X *= tmp; 279 | d.Y *= tmp; 280 | d.Z *= tmp; 281 | } 282 | #else 283 | dist = sqrt(d.X * d.X + d.Y * d.Y + d.Z * d.Z); 284 | if (dist > 1E-3) { 285 | tmp = 1 / dist; 286 | d.X *= tmp; 287 | d.Y *= tmp; 288 | d.Z *= tmp; 289 | } 290 | #endif 291 | att = 1.0f / (l->attenuation[0] + dist * (l->attenuation[1] + dist * l->attenuation[2])); 292 | } 293 | dot = d.X * n.X + d.Y * n.Y + d.Z * n.Z; 294 | if (twoside && dot < 0) 295 | dot = -dot; 296 | if (dot > 0) { 297 | /* diffuse light */ 298 | lR += dot * l->diffuse.v[0] * m->diffuse.v[0]; 299 | lG += dot * l->diffuse.v[1] * m->diffuse.v[1]; 300 | lB += dot * l->diffuse.v[2] * m->diffuse.v[2]; 301 | 302 | /* spot light */ 303 | if (l->spot_cutoff != 180) { 304 | dot_spot = -(d.X * l->norm_spot_direction.v[0] + d.Y * l->norm_spot_direction.v[1] + d.Z * l->norm_spot_direction.v[2]); 305 | if (twoside && dot_spot < 0) 306 | dot_spot = -dot_spot; 307 | if (dot_spot < l->cos_spot_cutoff) { 308 | /* no contribution */ 309 | continue; 310 | } else { 311 | /* TODO: pow table for spot_exponent?*/ 312 | if (l->spot_exponent > 0) { 313 | att = att * pow(dot_spot, l->spot_exponent); 314 | } 315 | } 316 | 317 | 318 | } 319 | 320 | /* specular light */ 321 | if (c->zEnableSpecular) { 322 | if (c->local_light_model) { 323 | V3 vcoord; 324 | vcoord.X = v->ec.X; 325 | vcoord.Y = v->ec.Y; 326 | vcoord.Z = v->ec.Z; 327 | 328 | gl_V3_Norm_Fast(&vcoord); 329 | s.X = d.X - vcoord.X; 330 | s.Y = d.Y - vcoord.X; 331 | s.Z = d.Z - vcoord.X; 332 | } else { 333 | 334 | s.X = d.X; 335 | s.Y = d.Y; 336 | s.Z = d.Z - 1.0; 337 | } 338 | 339 | dot_spec = n.X * s.X + n.Y * s.Y + n.Z * s.Z; 340 | if (twoside && dot_spec < 0) 341 | dot_spec = -dot_spec; 342 | if (dot_spec > 0) { 343 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 344 | GLSpecBuf* specbuf; 345 | GLint idx; 346 | #endif 347 | dot_spec = clampf(dot_spec, 0, 1); 348 | #if TGL_FEATURE_FISR == 1 349 | tmp = fastInvSqrt(s.X * s.X + s.Y * s.Y + s.Z * s.Z); 350 | 351 | { dot_spec = dot_spec * tmp; } 352 | 353 | #else 354 | 355 | tmp = sqrt(s.X * s.X + s.Y * s.Y + s.Z * s.Z); 356 | if (tmp > 1E-3) { 357 | dot_spec = dot_spec / tmp; 358 | } else 359 | dot_spec = 0; 360 | #endif 361 | /* dot_spec= pow(dot_spec,m->shininess);*/ 362 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 363 | specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess); 364 | /* Check for GL_OUT_OF_MEMORY*/ 365 | #if TGL_FEATURE_ERROR_CHECK == 1 366 | #include "error_check.h" 367 | #endif 368 | #else 369 | dot_spec = pow(dot_spec, m->shininess); 370 | #endif 371 | 372 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 373 | idx = (GLint)(dot_spec * SPECULAR_BUFFER_SIZE); 374 | if (idx > SPECULAR_BUFFER_SIZE) 375 | idx = SPECULAR_BUFFER_SIZE; /* NOTE by GEK: this is poorly written, it's actually 1 larger.*/ 376 | dot_spec = specbuf->buf[idx]; 377 | #endif 378 | lR += dot_spec * l->specular.v[0] * m->specular.v[0]; 379 | lG += dot_spec * l->specular.v[1] * m->specular.v[1]; 380 | lB += dot_spec * l->specular.v[2] * m->specular.v[2]; 381 | } 382 | } 383 | } 384 | 385 | R += att * lR; 386 | G += att * lG; 387 | B += att * lB; 388 | } /* End of light loop.*/ 389 | 390 | v->color.v[0] = clampf(R, 0, 1); 391 | v->color.v[1] = clampf(G, 0, 1); 392 | v->color.v[2] = clampf(B, 0, 1); 393 | v->color.v[3] = A; 394 | } 395 | -------------------------------------------------------------------------------- /src/list.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | 4 | /* 5 | static char* op_table_str[] = { 6 | #define ADD_OP(a, b, c) "gl" #a " " #c, 7 | 8 | #include "opinfo.h" 9 | }; 10 | */ 11 | 12 | void (*op_table_func[])(GLParam*) = { 13 | #define ADD_OP(a, b, c) glop##a, 14 | 15 | #include "opinfo.h" 16 | }; 17 | 18 | GLint op_table_size[] = { 19 | #define ADD_OP(a, b, c) b + 1, 20 | 21 | #include "opinfo.h" 22 | }; 23 | 24 | static GLList* find_list(GLuint list) { return gl_get_context()->shared_state.lists[list]; } 25 | 26 | static void delete_list(GLint list) { 27 | GLContext* c = gl_get_context(); 28 | GLParamBuffer *pb, *pb1; 29 | GLList* l; 30 | 31 | l = find_list(list); 32 | if (l == NULL) { 33 | return; 34 | } 35 | 36 | 37 | /* free param buffer */ 38 | pb = l->first_op_buffer; 39 | while (pb != NULL) { 40 | pb1 = pb->next; 41 | gl_free(pb); 42 | pb = pb1; 43 | } 44 | 45 | gl_free(l); 46 | c->shared_state.lists[list] = NULL; 47 | } 48 | void glDeleteLists(GLuint list, GLuint range) { 49 | GLuint i; 50 | #include "error_check_no_context.h" 51 | for (i = 0; i < list + range; i++) 52 | glDeleteList(list + i); 53 | } 54 | void glDeleteList(GLuint list) { 55 | #include "error_check_no_context.h" 56 | delete_list(list); 57 | } 58 | 59 | static GLList* alloc_list(GLint list) { 60 | GLList* l; 61 | GLParamBuffer* ob; 62 | GLContext* c = gl_get_context(); 63 | #define RETVAL NULL 64 | #include "error_check.h" 65 | l = gl_zalloc(sizeof(GLList)); 66 | ob = gl_zalloc(sizeof(GLParamBuffer)); 67 | 68 | #if TGL_FEATURE_ERROR_CHECK 69 | if (!l || !ob) 70 | #define ERROR_FLAG GL_OUT_OF_MEMORY 71 | #define RETVAL NULL 72 | #include "error_check.h" 73 | 74 | #else 75 | /* 76 | if(!l || !ob) gl_fatal_error("GL_OUT_OF_MEMORY"); 77 | This will crash a few lines down, so, let it! 78 | */ 79 | #endif 80 | ob->next = NULL; 81 | l->first_op_buffer = ob; 82 | 83 | ob->ops[0].op = OP_EndList; 84 | 85 | c->shared_state.lists[list] = l; 86 | return l; 87 | } 88 | /* 89 | void gl_print_op(FILE* f, GLParam* p) { 90 | GLint op; 91 | char* s; 92 | 93 | op = p[0].op; 94 | p++; 95 | s = op_table_str[op]; 96 | while (*s != 0) { 97 | if (*s == '%') { 98 | s++; 99 | switch (*s++) { 100 | case 'f': 101 | fpr_ntf(f, "%g", p[0].f); 102 | break; 103 | default: 104 | fpr_ntf(f, "%d", p[0].i); 105 | break; 106 | } 107 | p++; 108 | } else { 109 | fputc(*s, f); 110 | s++; 111 | } 112 | } 113 | tgl_warning(f, "\n"); 114 | } 115 | */ 116 | void glListBase(GLint n) { 117 | GLContext* c = gl_get_context(); 118 | #include "error_check.h" 119 | c->listbase = n; 120 | } 121 | void glCallLists(GLsizei n, GLenum type, const GLuint* lists) { 122 | GLint i; 123 | GLContext* c = gl_get_context(); 124 | #include "error_check.h" 125 | #if TGL_FEATURE_ERROR_CHECK == 1 126 | if(type != GL_UNSIGNED_INT && 127 | type != GL_INT) 128 | #define ERROR_FLAG GL_INVALID_ENUM 129 | #include "error_check.h" 130 | #endif 131 | for (i = 0; i < n; i++) 132 | glCallList(c->listbase + lists[i]); 133 | } 134 | void gl_compile_op(GLParam* p) { 135 | GLContext* c = gl_get_context(); 136 | GLint op, op_size; 137 | GLParamBuffer *ob, *ob1; 138 | GLint index, i; 139 | #include "error_check.h" 140 | op = p[0].op; 141 | op_size = op_table_size[op]; 142 | index = c->current_op_buffer_index; 143 | ob = c->current_op_buffer; 144 | 145 | /* we should be able to add a NextBuffer opcode */ 146 | if ((index + op_size) > (OP_BUFFER_MAX_SIZE - 2)) { 147 | 148 | ob1 = gl_zalloc(sizeof(GLParamBuffer)); 149 | 150 | #if TGL_FEATURE_ERROR_CHECK == 1 151 | if (!ob1) 152 | #define ERROR_FLAG GL_OUT_OF_MEMORY 153 | #include "error_check.h" 154 | #else 155 | 156 | 157 | #endif 158 | ob1->next = NULL; 159 | 160 | ob->next = ob1; 161 | ob->ops[index].op = OP_NextBuffer; 162 | ob->ops[index + 1].p = (void*)ob1; 163 | 164 | c->current_op_buffer = ob1; 165 | ob = ob1; 166 | index = 0; 167 | } 168 | 169 | for (i = 0; i < op_size; i++) { 170 | ob->ops[index] = p[i]; 171 | index++; 172 | } 173 | c->current_op_buffer_index = index; 174 | } 175 | /* this opcode is never called directly */ 176 | void glopEndList(GLParam* p) { exit(1); } 177 | 178 | /* this opcode is never called directly */ 179 | void glopNextBuffer(GLParam* p) { exit(1); } 180 | 181 | void glopCallList(GLParam* p) { 182 | 183 | GLList* l; 184 | GLint list; 185 | #include "error_check_no_context.h" 186 | list = p[1].ui; 187 | l = find_list(list); 188 | 189 | #if TGL_FEATURE_ERROR_CHECK == 1 190 | if (l == NULL) { 191 | gl_fatal_error("Bad list op, not defined"); 192 | } 193 | #else 194 | 195 | #endif 196 | p = l->first_op_buffer->ops; 197 | 198 | while (1) { 199 | GLint op; 200 | #include "error_check.h" 201 | op = p[0].op; 202 | if (op == OP_EndList) 203 | break; 204 | if (op == OP_NextBuffer) { 205 | p = (GLParam*)p[1].p; 206 | } else { 207 | op_table_func[op](p); 208 | p += op_table_size[op]; 209 | } 210 | } 211 | } 212 | 213 | void glNewList(GLuint list, GLint mode) { 214 | GLList* l; 215 | GLContext* c = gl_get_context(); 216 | #include "error_check.h" 217 | 218 | #if TGL_FEATURE_ERROR_CHECK == 1 219 | 220 | if (!(mode == GL_COMPILE || mode == GL_COMPILE_AND_EXECUTE)) 221 | #define ERROR_FLAG GL_INVALID_ENUM 222 | #include "error_check.h" 223 | 224 | if (!(c->compile_flag == 0)) 225 | #define ERROR_FLAG GL_INVALID_OPERATION 226 | #include "error_check.h" 227 | 228 | #else 229 | 230 | 231 | #endif 232 | l = find_list(list); 233 | if (l != NULL) 234 | delete_list(list); 235 | l = alloc_list(list); 236 | #include "error_check.h" 237 | #if TGL_FEATURE_ERROR_CHECK == 1 238 | if (l == NULL) 239 | #define ERROR_FLAG GL_OUT_OF_MEMORY 240 | #include "error_check.h" 241 | #else 242 | 243 | if (l == NULL) 244 | gl_fatal_error("Could not find or allocate list."); 245 | #endif 246 | c->current_op_buffer = l->first_op_buffer; 247 | c->current_op_buffer_index = 0; 248 | 249 | c->compile_flag = 1; 250 | c->exec_flag = (mode == GL_COMPILE_AND_EXECUTE); 251 | } 252 | 253 | void glEndList(void) { 254 | GLContext* c = gl_get_context(); 255 | GLParam p[1]; 256 | #include "error_check.h" 257 | #if TGL_FEATURE_ERROR_CHECK == 1 258 | if (c->compile_flag != 1) 259 | #define ERROR_FLAG GL_INVALID_OPERATION 260 | #include "error_check.h" 261 | #else 262 | if (c->compile_flag != 1) 263 | return; 264 | #endif 265 | /* end of list */ 266 | p[0].op = OP_EndList; 267 | gl_compile_op(p); 268 | 269 | c->compile_flag = 0; 270 | c->exec_flag = 1; 271 | } 272 | 273 | GLint glIsList(GLuint list) { 274 | 275 | GLList* l; 276 | l = find_list(list); 277 | return (l != NULL); 278 | } 279 | 280 | GLuint glGenLists(GLint range) { 281 | GLint count, i, list; 282 | GLList** lists; 283 | GLContext* c = gl_get_context(); 284 | #define RETVAL 0 285 | #include "error_check.h" 286 | lists = c->shared_state.lists; 287 | count = 0; 288 | for (i = 0; i < MAX_DISPLAY_LISTS; i++) { 289 | if (lists[i] == NULL) { 290 | count++; 291 | if (count == range) { 292 | list = i - range + 1; 293 | for (i = 0; i < range; i++) { 294 | alloc_list(list + i); 295 | } 296 | return list; 297 | } 298 | } else { 299 | count = 0; 300 | } 301 | } 302 | return 0; 303 | } 304 | -------------------------------------------------------------------------------- /src/matrix.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | void gl_print_matrix(const GLfloat* m) { 4 | GLint i; 5 | 6 | for (i = 0; i < 4; i++) { 7 | tgl_warning("%f %f %f %f\n", m[i], m[4 + i], m[8 + i], m[12 + i]); 8 | } 9 | } 10 | 11 | static void gl_matrix_update() { 12 | GLContext* c = gl_get_context(); 13 | c->matrix_model_projection_updated = (c->matrix_mode <= 1); 14 | } 15 | 16 | void glopMatrixMode(GLParam* p) { 17 | GLContext* c = gl_get_context(); 18 | GLint mode = p[1].i; 19 | switch (mode) { 20 | case GL_MODELVIEW: 21 | c->matrix_mode = 0; 22 | break; 23 | case GL_PROJECTION: 24 | c->matrix_mode = 1; 25 | break; 26 | case GL_TEXTURE: 27 | c->matrix_mode = 2; 28 | break; 29 | default: 30 | break; 31 | 32 | } 33 | } 34 | 35 | void glopLoadMatrix(GLParam* p) { 36 | GLContext* c = gl_get_context(); 37 | M4* m; 38 | GLint i; 39 | 40 | GLParam* q; 41 | 42 | m = c->matrix_stack_ptr[c->matrix_mode]; 43 | q = p + 1; 44 | 45 | for (i = 0; i < 4; i++) { 46 | m->m[0][i] = q[0].f; 47 | m->m[1][i] = q[1].f; 48 | m->m[2][i] = q[2].f; 49 | m->m[3][i] = q[3].f; 50 | q += 4; 51 | } 52 | 53 | gl_matrix_update(); 54 | } 55 | 56 | void glopLoadIdentity(GLParam* p) { 57 | GLContext* c = gl_get_context(); 58 | 59 | gl_M4_Id(c->matrix_stack_ptr[c->matrix_mode]); 60 | 61 | gl_matrix_update(); 62 | } 63 | 64 | void glopMultMatrix(GLParam* p) { 65 | GLContext* c = gl_get_context(); 66 | M4 m; 67 | GLint i; 68 | 69 | GLParam* q; 70 | q = p + 1; 71 | 72 | for (i = 0; i < 4; i++) { 73 | m.m[0][i] = q[0].f; 74 | m.m[1][i] = q[1].f; 75 | m.m[2][i] = q[2].f; 76 | m.m[3][i] = q[3].f; 77 | q += 4; 78 | } 79 | 80 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode], &m); 81 | 82 | gl_matrix_update(); 83 | } 84 | 85 | void glopPushMatrix(GLParam* p) { 86 | GLContext* c = gl_get_context(); 87 | GLint n = c->matrix_mode; 88 | M4* m; 89 | 90 | #if TGL_FEATURE_ERROR_CHECK == 1 91 | if (!((c->matrix_stack_ptr[n] - c->matrix_stack[n] + 1) < c->matrix_stack_depth_max[n])) 92 | #define ERROR_FLAG GL_INVALID_OPERATION 93 | #include "error_check.h" 94 | #endif 95 | 96 | m = ++c->matrix_stack_ptr[n]; 97 | 98 | gl_M4_Move(&m[0], &m[-1]); 99 | 100 | gl_matrix_update(); 101 | } 102 | 103 | void glopPopMatrix(GLParam* p) { 104 | GLContext* c = gl_get_context(); 105 | GLint n = c->matrix_mode; 106 | 107 | 108 | 109 | #if TGL_FEATURE_ERROR_CHECK == 1 110 | if (!(c->matrix_stack_ptr[n] > c->matrix_stack[n])) 111 | #define ERROR_FLAG GL_INVALID_OPERATION 112 | #include "error_check.h" 113 | #endif 114 | c->matrix_stack_ptr[n]--; 115 | gl_matrix_update(); 116 | } 117 | 118 | void glopRotate(GLParam* p) { 119 | GLContext* c = gl_get_context(); 120 | M4 m; 121 | GLfloat u[3]; 122 | GLfloat angle; 123 | GLint dir_code; 124 | 125 | angle = p[1].f * M_PI / 180.0; 126 | u[0] = p[2].f; 127 | u[1] = p[3].f; 128 | u[2] = p[4].f; 129 | 130 | /* simple case detection */ 131 | dir_code = ((u[0] != 0) << 2) | ((u[1] != 0) << 1) | (u[2] != 0); 132 | 133 | switch (dir_code) { 134 | case 0: 135 | gl_M4_Id(&m); 136 | break; 137 | case 4: 138 | if (u[0] < 0) 139 | angle = -angle; 140 | gl_M4_Rotate(&m, angle, 0); 141 | break; 142 | case 2: 143 | if (u[1] < 0) 144 | angle = -angle; 145 | gl_M4_Rotate(&m, angle, 1); 146 | break; 147 | case 1: 148 | if (u[2] < 0) 149 | angle = -angle; 150 | gl_M4_Rotate(&m, angle, 2); 151 | break; 152 | default: { 153 | GLfloat cost, sint; 154 | 155 | /* normalize vector */ 156 | 157 | #if TGL_FEATURE_FISR == 1 158 | GLfloat len = u[0] + u[1] + u[2]; 159 | if (len == 0.0f) 160 | return; 161 | len = fastInvSqrt(len); /* FISR*/ 162 | #else 163 | GLfloat len = u[0] * u[0] + u[1] * u[1] + u[2] * u[2]; 164 | if (len == 0.0f) 165 | return; 166 | len = 1.0f / sqrt(len); 167 | #endif 168 | u[0] *= len; 169 | u[1] *= len; 170 | u[2] *= len; 171 | /* store cos and sin values */ 172 | cost = cos(angle); 173 | sint = sin(angle); 174 | 175 | /* fill in the values */ 176 | m.m[3][0] = m.m[3][1] = m.m[3][2] = m.m[0][3] = m.m[1][3] = m.m[2][3] = 0.0f; 177 | m.m[3][3] = 1.0f; 178 | 179 | /* do the math */ 180 | m.m[0][0] = u[0] * u[0] + cost * (1 - u[0] * u[0]); 181 | m.m[1][0] = u[0] * u[1] * (1 - cost) - u[2] * sint; 182 | m.m[2][0] = u[2] * u[0] * (1 - cost) + u[1] * sint; 183 | m.m[0][1] = u[0] * u[1] * (1 - cost) + u[2] * sint; 184 | m.m[1][1] = u[1] * u[1] + cost * (1 - u[1] * u[1]); 185 | m.m[2][1] = u[1] * u[2] * (1 - cost) - u[0] * sint; 186 | m.m[0][2] = u[2] * u[0] * (1 - cost) - u[1] * sint; 187 | m.m[1][2] = u[1] * u[2] * (1 - cost) + u[0] * sint; 188 | m.m[2][2] = u[2] * u[2] + cost * (1 - u[2] * u[2]); 189 | } 190 | } 191 | 192 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode], &m); 193 | 194 | gl_matrix_update(); 195 | } 196 | 197 | void glopScale(GLParam* p) { 198 | GLContext* c = gl_get_context(); 199 | GLfloat* m; 200 | GLfloat x = p[1].f, y = p[2].f, z = p[3].f; 201 | 202 | m = &c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; 203 | 204 | m[0] *= x; 205 | m[1] *= y; 206 | m[2] *= z; 207 | m[4] *= x; 208 | m[5] *= y; 209 | m[6] *= z; 210 | m[8] *= x; 211 | m[9] *= y; 212 | m[10] *= z; 213 | m[12] *= x; 214 | m[13] *= y; 215 | m[14] *= z; 216 | gl_matrix_update(); 217 | } 218 | 219 | void glopTranslate(GLParam* p) { 220 | GLContext* c = gl_get_context(); 221 | GLfloat* m; 222 | GLfloat x = p[1].f, y = p[2].f, z = p[3].f; 223 | 224 | m = &c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; 225 | 226 | m[3] = m[0] * x + m[1] * y + m[2] * z + m[3]; 227 | m[7] = m[4] * x + m[5] * y + m[6] * z + m[7]; 228 | m[11] = m[8] * x + m[9] * y + m[10] * z + m[11]; 229 | m[15] = m[12] * x + m[13] * y + m[14] * z + m[15]; 230 | 231 | gl_matrix_update(); 232 | } 233 | 234 | void glopFrustum(GLParam* p) { 235 | GLContext* c = gl_get_context(); 236 | GLfloat* r; 237 | M4 m; 238 | GLfloat left = p[1].f; 239 | GLfloat right = p[2].f; 240 | GLfloat bottom = p[3].f; 241 | GLfloat top = p[4].f; 242 | GLfloat near = p[5].f; 243 | GLfloat farp = p[6].f; 244 | GLfloat x, y, A, B, C, D; 245 | 246 | x = (2.0 * near) / (right - left); 247 | y = (2.0 * near) / (top - bottom); 248 | A = (right + left) / (right - left); 249 | B = (top + bottom) / (top - bottom); 250 | C = -(farp + near) / (farp - near); 251 | D = -(2.0 * farp * near) / (farp - near); 252 | 253 | r = &m.m[0][0]; 254 | r[0] = x; 255 | r[1] = 0; 256 | r[2] = A; 257 | r[3] = 0; 258 | r[4] = 0; 259 | r[5] = y; 260 | r[6] = B; 261 | r[7] = 0; 262 | r[8] = 0; 263 | r[9] = 0; 264 | r[10] = C; 265 | r[11] = D; 266 | r[12] = 0; 267 | r[13] = 0; 268 | r[14] = -1; 269 | r[15] = 0; 270 | 271 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode], &m); 272 | 273 | gl_matrix_update(); 274 | } 275 | -------------------------------------------------------------------------------- /src/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory allocator for TinyGL 3 | */ 4 | 5 | static inline void required_for_compilation_(){ 6 | return; 7 | } 8 | 9 | #if TGL_FEATURE_CUSTOM_MALLOC == 1 10 | #include "zgl.h" 11 | 12 | /* modify these functions so that they suit your needs */ 13 | 14 | #include 15 | void gl_free(void* p) { free(p); } 16 | 17 | void* gl_malloc(GLint size) { return malloc(size); } 18 | 19 | void* gl_zalloc(GLint size) { return calloc(1, size); } 20 | #endif 21 | -------------------------------------------------------------------------------- /src/misc.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | 4 | void glPolygonStipple(void* a) { 5 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 6 | GLContext* c = gl_get_context(); 7 | #include "error_check.h" 8 | ZBuffer* zb = c->zb; 9 | 10 | memcpy(zb->stipplepattern, a, TGL_POLYGON_STIPPLE_BYTES); 11 | for (GLint i = 0; i < TGL_POLYGON_STIPPLE_BYTES; i++) { 12 | zb->stipplepattern[i] = ((GLubyte*)a)[i]; 13 | } 14 | #endif 15 | } 16 | 17 | void glopViewport(GLParam* p) { 18 | GLContext* c = gl_get_context(); 19 | GLint xsize, ysize, xmin, ymin, xsize_req, ysize_req; 20 | 21 | xmin = p[1].i; 22 | ymin = p[2].i; 23 | xsize = p[3].i; 24 | ysize = p[4].i; 25 | 26 | /* we may need to resize the zbuffer */ 27 | 28 | if (c->viewport.xmin != xmin || c->viewport.ymin != ymin || c->viewport.xsize != xsize || c->viewport.ysize != ysize) { 29 | 30 | xsize_req = xmin + xsize; 31 | ysize_req = ymin + ysize; 32 | 33 | if (c->gl_resize_viewport && c->gl_resize_viewport(&xsize_req, &ysize_req) != 0) { 34 | gl_fatal_error("glViewport: error while resizing display"); 35 | } 36 | if (xsize <= 0 || ysize <= 0) { 37 | gl_fatal_error("glViewport: size too small"); 38 | } 39 | 40 | 41 | c->viewport.xmin = xmin; 42 | c->viewport.ymin = ymin; 43 | c->viewport.xsize = xsize; 44 | c->viewport.ysize = ysize; 45 | 46 | 47 | gl_eval_viewport(); 48 | 49 | } 50 | } 51 | void glBlendFunc(GLenum sfactor, GLenum dfactor) { 52 | GLParam p[3]; 53 | #include "error_check_no_context.h" 54 | p[0].op = OP_BlendFunc; 55 | p[1].i = sfactor; 56 | p[2].i = dfactor; 57 | gl_add_op(p); 58 | return; 59 | } 60 | void glopBlendFunc(GLParam* p) { 61 | GLContext* c = gl_get_context(); 62 | c->zb->sfactor = p[1].i; 63 | c->zb->dfactor = p[2].i; 64 | } 65 | 66 | void glBlendEquation(GLenum mode) { 67 | GLParam p[2]; 68 | #include "error_check_no_context.h" 69 | p[0].op = OP_BlendEquation; 70 | p[1].i = mode; 71 | gl_add_op(p); 72 | } 73 | void glopBlendEquation(GLParam* p) { 74 | GLContext* c = gl_get_context(); 75 | c->zb->blendeq = p[1].i; 76 | } 77 | 78 | void glopPointSize(GLParam* p) { 79 | GLContext* c = gl_get_context(); 80 | c->zb->pointsize = p[1].f; 81 | } 82 | void glPointSize(GLfloat f) { 83 | GLParam p[2]; 84 | p[0].op = OP_PointSize; 85 | #include "error_check_no_context.h" 86 | p[1].f = f; 87 | gl_add_op(p); 88 | } 89 | 90 | void glopEnableDisable(GLParam* p) { 91 | GLContext* c = gl_get_context(); 92 | GLint code = p[1].i; 93 | GLint v = p[2].i; 94 | 95 | switch (code) { 96 | case GL_CULL_FACE: 97 | c->cull_face_enabled = v; 98 | break; 99 | case GL_LIGHTING: 100 | c->lighting_enabled = v; 101 | break; 102 | case GL_COLOR_MATERIAL: 103 | c->color_material_enabled = v; 104 | break; 105 | case GL_TEXTURE_2D: 106 | c->texture_2d_enabled = v; 107 | break; 108 | case GL_BLEND: 109 | c->zb->enable_blend = v; 110 | break; 111 | case GL_NORMALIZE: 112 | c->normalize_enabled = v; 113 | break; 114 | case GL_DEPTH_TEST: 115 | c->zb->depth_test = v; 116 | break; 117 | case GL_POLYGON_OFFSET_FILL: 118 | if (v) 119 | c->offset_states |= TGL_OFFSET_FILL; 120 | else 121 | c->offset_states &= ~TGL_OFFSET_FILL; 122 | break; 123 | case GL_POLYGON_STIPPLE: 124 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 125 | c->zb->dostipple = v; 126 | #endif 127 | break; 128 | case GL_POLYGON_OFFSET_POINT: 129 | if (v) 130 | c->offset_states |= TGL_OFFSET_POINT; 131 | else 132 | c->offset_states &= ~TGL_OFFSET_POINT; 133 | break; 134 | case GL_POLYGON_OFFSET_LINE: 135 | if (v) 136 | c->offset_states |= TGL_OFFSET_LINE; 137 | else 138 | c->offset_states &= ~TGL_OFFSET_LINE; 139 | break; 140 | default: 141 | if (code >= GL_LIGHT0 && code < GL_LIGHT0 + MAX_LIGHTS) { 142 | gl_enable_disable_light(code - GL_LIGHT0, v); 143 | } else { 144 | tgl_warning("glEnableDisable: 0x%X not supported.\n", code); 145 | } 146 | break; 147 | } 148 | } 149 | 150 | void glopShadeModel(GLParam* p) { 151 | GLContext* c = gl_get_context(); 152 | GLint code = p[1].i; 153 | c->current_shade_model = code; 154 | } 155 | 156 | void glopCullFace(GLParam* p) { 157 | GLContext* c = gl_get_context(); 158 | GLint code = p[1].i; 159 | c->current_cull_face = code; 160 | } 161 | 162 | void glopFrontFace(GLParam* p) { 163 | GLContext* c = gl_get_context(); 164 | GLint code = p[1].i; 165 | c->current_front_face = code; 166 | } 167 | 168 | void glopPolygonMode(GLParam* p) { 169 | GLContext* c = gl_get_context(); 170 | GLint face = p[1].i; 171 | GLint mode = p[2].i; 172 | 173 | switch (face) { 174 | case GL_BACK: 175 | c->polygon_mode_back = mode; 176 | break; 177 | case GL_FRONT: 178 | c->polygon_mode_front = mode; 179 | break; 180 | case GL_FRONT_AND_BACK: 181 | c->polygon_mode_front = mode; 182 | c->polygon_mode_back = mode; 183 | break; 184 | default: 185 | break; 186 | } 187 | } 188 | 189 | void glopPolygonOffset(GLParam* p) { 190 | GLContext* c = gl_get_context(); 191 | c->offset_factor = p[1].f; 192 | c->offset_units = p[2].f; 193 | } 194 | 195 | GLenum glGetError() { 196 | #if TGL_FEATURE_ERROR_CHECK == 1 197 | GLContext* c = gl_get_context(); 198 | GLenum eflag = c->error_flag; 199 | if (eflag != GL_OUT_OF_MEMORY) 200 | c->error_flag = GL_NO_ERROR; 201 | return eflag; 202 | #else 203 | return GL_NO_ERROR; 204 | #endif 205 | } 206 | 207 | void glDrawBuffer(GLenum mode) { 208 | GLContext* c = gl_get_context(); 209 | #include "error_check.h" 210 | if ((mode != GL_FRONT && mode != GL_NONE) || c->in_begin) { 211 | #if TGL_FEATURE_ERROR_CHECK == 1 212 | #define ERROR_FLAG GL_INVALID_OPERATION 213 | #include "error_check.h" 214 | #else 215 | return; 216 | #endif 217 | } 218 | c->drawbuffer = mode; 219 | } 220 | 221 | void glReadBuffer(GLenum mode) { 222 | GLContext* c = gl_get_context(); 223 | #include "error_check.h" 224 | if ((mode != GL_FRONT && mode != GL_NONE) || c->in_begin) { 225 | #if TGL_FEATURE_ERROR_CHECK == 1 226 | #define ERROR_FLAG GL_INVALID_OPERATION 227 | #include "error_check.h" 228 | #else 229 | return; 230 | #endif 231 | } 232 | c->readbuffer = mode; 233 | } 234 | 235 | 236 | void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* data) { 237 | GLContext* c = gl_get_context(); 238 | #include "error_check.h" 239 | if (c->readbuffer != GL_FRONT || (format != GL_RGBA && format != GL_RGB && format != GL_DEPTH_COMPONENT) || 240 | #if TGL_FEATURE_RENDER_BITS == 32 241 | (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_INT_8_8_8_8) 242 | #elif TGL_FEATURE_RENDER_BITS == 16 243 | (type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_SHORT_5_6_5) 244 | #else 245 | #error "Unsupported TGL_FEATURE_RENDER_BITS" 246 | #endif 247 | 248 | ) { 249 | #if TGL_FEATURE_ERROR_CHECK 250 | #define ERROR_FLAG GL_INVALID_OPERATION 251 | #include "error_check.h" 252 | #else 253 | return; 254 | #endif 255 | } 256 | /* TODO: implement read pixels.*/ 257 | } 258 | 259 | void glFinish() { return; } 260 | -------------------------------------------------------------------------------- /src/msghandling.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "../include/GL/gl.h" 3 | #include "zgl.h" 4 | #include 5 | 6 | 7 | #ifdef __TINYC__ 8 | #define NO_DEBUG_OUTPUT 9 | #endif 10 | 11 | #ifndef NO_DEBUG_OUTPUT 12 | #include 13 | #endif 14 | /* Use this function to output messages when something unexpected 15 | happens (which might be an indication of an error). *Don't* use it 16 | when there's GLinternal errors in the code - these should be handled 17 | by asserts. */ 18 | void tgl_warning(const char* format, ...) { 19 | #ifndef NO_DEBUG_OUTPUT 20 | va_list args; 21 | va_start(args, format); 22 | fprintf(stderr, "*WARNING* "); 23 | vfprintf(stderr, format, args); 24 | va_end(args); 25 | #endif /* !NO_DEBUG_OUTPUT */ 26 | } 27 | 28 | /* This function should be used for debug output only. */ 29 | void tgl_trace(const char* format, ...) { 30 | #ifndef NO_DEBUG_OUTPUT 31 | va_list args; 32 | va_start(args, format); 33 | fprintf(stderr, "*DEBUG* "); 34 | vfprintf(stderr, format, args); 35 | va_end(args); 36 | #endif /* !NO_DEBUG_OUTPUT */ 37 | } 38 | 39 | /* Use this function to output info about things in the code which 40 | should be fixed (missing handling of special cases, important 41 | features not implemented, known bugs/buglets, ...). */ 42 | void tgl_fixme(const char* format, ...) { 43 | #ifndef NO_DEBUG_OUTPUT 44 | va_list args; 45 | va_start(args, format); 46 | fprintf(stderr, "*FIXME* "); 47 | vfprintf(stderr, format, args); 48 | va_end(args); 49 | #endif /* !NO_DEBUG_OUTPUT */ 50 | } 51 | 52 | void gl_fatal_error(char* format, ...) { 53 | #ifndef NO_DEBUG_OUTPUT 54 | va_list ap; 55 | va_start(ap, format); 56 | fprintf(stderr, "TinyGL: fatal error: "); 57 | vfprintf(stderr, format, ap); 58 | fprintf(stderr, "\n"); 59 | exit(1); 60 | va_end(ap); 61 | #else 62 | exit(1); 63 | #endif 64 | } 65 | -------------------------------------------------------------------------------- /src/msghandling.h: -------------------------------------------------------------------------------- 1 | #ifndef _msghandling_h_ 2 | #define _msghandling_h_ 3 | #include "../include/GL/gl.h" 4 | extern void tgl_warning(const char* text, ...); 5 | extern void tgl_trace(const char* text, ...); 6 | extern void tgl_fixme(const char* text, ...); 7 | 8 | #endif /* _msghandling_h_ */ 9 | -------------------------------------------------------------------------------- /src/opinfo.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | ADD_OP(Color, 7, "%f %f %f %f %d %d %d") 4 | ADD_OP(TexCoord, 4, "%f %f %f %f") 5 | ADD_OP(EdgeFlag, 1, "%d") 6 | ADD_OP(Normal, 3, "%f %f %f") 7 | 8 | ADD_OP(Begin, 1, "%C") 9 | ADD_OP(Vertex, 4, "%f %f %f %f") 10 | ADD_OP(End, 0, "") 11 | 12 | ADD_OP(EnableDisable, 2, "%C %d") 13 | 14 | ADD_OP(MatrixMode, 1, "%C") 15 | ADD_OP(LoadMatrix, 16, "") 16 | ADD_OP(LoadIdentity, 0, "") 17 | ADD_OP(MultMatrix, 16, "") 18 | ADD_OP(PushMatrix, 0, "") 19 | ADD_OP(PopMatrix, 0, "") 20 | ADD_OP(Rotate, 4, "%f %f %f %f") 21 | ADD_OP(Translate, 3, "%f %f %f") 22 | ADD_OP(Scale, 3, "%f %f %f") 23 | 24 | ADD_OP(Viewport, 4, "%d %d %d %d") 25 | ADD_OP(Frustum, 6, "%f %f %f %f %f %f") 26 | 27 | ADD_OP(Material, 6, "%C %C %f %f %f %f") 28 | ADD_OP(ColorMaterial, 2, "%C %C") 29 | ADD_OP(Light, 6, "%C %C %f %f %f %f") 30 | ADD_OP(LightModel, 5, "%C %f %f %f %f") 31 | 32 | ADD_OP(Clear, 1, "%d") 33 | ADD_OP(ClearColor, 4, "%f %f %f %f") 34 | ADD_OP(ClearDepth, 1, "%f") 35 | 36 | ADD_OP(InitNames, 0, "") 37 | ADD_OP(PushName, 1, "%d") 38 | ADD_OP(PopName, 0, "") 39 | ADD_OP(LoadName, 1, "%d") 40 | 41 | ADD_OP(TexImage2D, 9, "%d %d %d %d %d %d %d %d %d") 42 | ADD_OP(TexImage1D, 8, "%d %d %d %d %d %d %d %d") 43 | ADD_OP(CopyTexImage2D, 8, "%d %d %d %d %d %d %d %d") 44 | ADD_OP(BindTexture, 2, "%C %d") 45 | 46 | 47 | 48 | 49 | ADD_OP(ShadeModel, 1, "%C") 50 | ADD_OP(CullFace, 1, "%C") 51 | ADD_OP(FrontFace, 1, "%C") 52 | ADD_OP(PolygonMode, 2, "%C %C") 53 | 54 | ADD_OP(CallList, 1, "%d") 55 | 56 | 57 | /* special opcodes */ 58 | ADD_OP(EndList, 0, "") 59 | ADD_OP(NextBuffer, 1, "%p") 60 | 61 | /* opengl 1.1 arrays */ 62 | ADD_OP(ArrayElement, 1, "%d") 63 | ADD_OP(EnableClientState, 1, "%C") 64 | ADD_OP(DisableClientState, 1, "%C") 65 | ADD_OP(VertexPointer, 4, "%d %C %d %p") 66 | ADD_OP(ColorPointer, 4, "%d %C %d %p") 67 | ADD_OP(NormalPointer, 3, "%C %d %p") 68 | ADD_OP(TexCoordPointer, 4, "%d %C %d %p") 69 | 70 | /* opengl 1.1 polygon offset */ 71 | ADD_OP(PolygonOffset, 2, "%f %f") 72 | 73 | /* blending */ 74 | ADD_OP(BlendEquation, 1, "%d") 75 | ADD_OP(BlendFunc, 2, "%d %d") 76 | 77 | /* point size */ 78 | ADD_OP(PointSize, 1, "%f") 79 | 80 | /* raster position */ 81 | ADD_OP(RasterPos, 4, "%f %f %f %f") 82 | ADD_OP(PixelZoom, 2, "%f %f") 83 | /* Draw pixels*/ 84 | /* Width, Height, Data*/ 85 | ADD_OP(DrawPixels, 3, "%d %d %p") 86 | 87 | /* Gek's Added Functions */ 88 | ADD_OP(PlotPixel, 2, "%d %d") 89 | ADD_OP(TextSize, 1, "%d") 90 | ADD_OP(SetEnableSpecular, 1, "%d") 91 | 92 | #undef ADD_OP 93 | -------------------------------------------------------------------------------- /src/quick.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | #escape character is used here to add a slash 3 | #This script was used to move these files to include. 4 | #sed -i 's/\"zbuffer.h/\"include\/zbuffer.h/g' *.c *.h 5 | #sed -i 's/\"zfeatures.h/\"include\/zfeatures.h/g' *.c *.h 6 | #sed -i 's/unsigned int/GLuint/g' *.c *.h 7 | #sed -i 's/float/GLfloat/g' *.c *.h 8 | #sed -i 's/char/GLbyte/g' *.c *.h 9 | #sed -i 's/unsigned GLbyte/GLubyte/g' *.c *.h 10 | #sed -i 's/ int/ GLint/g' *.c *.h 11 | sed -i 's/inline//g' *.c *.h 12 | 13 | #gcc *.c -o executable.out -lglut -lGL -lm -lGLU 14 | -------------------------------------------------------------------------------- /src/specbuf.c: -------------------------------------------------------------------------------- 1 | #include "msghandling.h" 2 | #include "zgl.h" 3 | #include 4 | #include 5 | 6 | #if TGL_FEATURE_SPECULAR_BUFFERS == 1 7 | 8 | static void calc_buf(GLSpecBuf* buf, const GLfloat shininess) { 9 | GLint i; 10 | GLfloat val, inc; 11 | val = 0.0f; 12 | inc = 1.0f / SPECULAR_BUFFER_SIZE; 13 | for (i = 0; i <= SPECULAR_BUFFER_SIZE; i++) { 14 | buf->buf[i] = pow(val, shininess); 15 | val += inc; 16 | } 17 | } 18 | 19 | GLSpecBuf* specbuf_get_buffer(GLContext* c, const GLint shininess_i, const GLfloat shininess) { 20 | GLSpecBuf *found, *oldest; 21 | found = oldest = c->specbuf_first; 22 | while (found && found->shininess_i != shininess_i) { 23 | if (found->last_used < oldest->last_used) { 24 | oldest = found; 25 | } 26 | found = found->next; 27 | } 28 | if (found) { /* hey, found one! */ 29 | found->last_used = c->specbuf_used_counter++; 30 | return found; 31 | } 32 | if (oldest == NULL || c->specbuf_num_buffers < MAX_SPECULAR_BUFFERS) { 33 | /* create new buffer */ 34 | GLSpecBuf* buf = gl_malloc(sizeof(GLSpecBuf)); 35 | #if TGL_FEATURE_ERROR_CHECK == 1 36 | if (!buf) 37 | #define ERROR_FLAG GL_OUT_OF_MEMORY 38 | #define RETVAL NULL 39 | #include "error_check.h" 40 | #else 41 | 42 | 43 | #endif 44 | c->specbuf_num_buffers++; 45 | buf->next = c->specbuf_first; 46 | c->specbuf_first = buf; 47 | buf->last_used = c->specbuf_used_counter++; 48 | buf->shininess_i = shininess_i; 49 | calc_buf(buf, shininess); 50 | return buf; 51 | } 52 | /* overwrite the lru buffer */ 53 | /*tgl_trace("overwriting spec buffer :(\n");*/ 54 | oldest->shininess_i = shininess_i; 55 | oldest->last_used = c->specbuf_used_counter++; 56 | calc_buf(oldest, shininess); 57 | return oldest; 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/zbuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Z buffer: 16 bits Z / 16 bits color 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include "../include/zbuffer.h" 11 | #include "msghandling.h" 12 | ZBuffer* ZB_open(GLint xsize, GLint ysize, GLint mode, 13 | 14 | void* frame_buffer) { 15 | ZBuffer* zb; 16 | GLint size; 17 | 18 | zb = gl_malloc(sizeof(ZBuffer)); 19 | if (zb == NULL) 20 | return NULL; 21 | 22 | zb->xsize = xsize & ~3; 23 | zb->ysize = ysize; 24 | 25 | 26 | zb->linesize = (xsize * PSZB); 27 | 28 | switch (mode) { 29 | #if TGL_FEATURE_32_BITS == 1 30 | case ZB_MODE_RGBA: 31 | break; 32 | #endif 33 | #if TGL_FEATURE_16_BITS == 1 34 | case ZB_MODE_5R6G5B: 35 | break; 36 | #endif 37 | 38 | default: 39 | goto error; 40 | } 41 | 42 | size = zb->xsize * zb->ysize * sizeof(GLushort); 43 | 44 | zb->zbuf = gl_malloc(size); 45 | if (zb->zbuf == NULL) 46 | goto error; 47 | 48 | if (frame_buffer == NULL) { 49 | zb->pbuf = gl_malloc(zb->ysize * zb->linesize); 50 | if (zb->pbuf == NULL) { 51 | gl_free(zb->zbuf); 52 | goto error; 53 | } 54 | zb->frame_buffer_allocated = 1; 55 | } else { 56 | zb->frame_buffer_allocated = 0; 57 | zb->pbuf = frame_buffer; 58 | } 59 | 60 | zb->current_texture = NULL; 61 | 62 | return zb; 63 | error: 64 | gl_free(zb); 65 | return NULL; 66 | } 67 | 68 | void ZB_close(ZBuffer* zb) { 69 | 70 | if (zb->frame_buffer_allocated) 71 | gl_free(zb->pbuf); 72 | 73 | gl_free(zb->zbuf); 74 | gl_free(zb); 75 | } 76 | 77 | void ZB_resize(ZBuffer* zb, void* frame_buffer, GLint xsize, GLint ysize) { 78 | GLint size; 79 | 80 | /* xsize must be a multiple of 4 */ 81 | xsize = xsize & ~3; 82 | 83 | zb->xsize = xsize; 84 | zb->ysize = ysize; 85 | zb->linesize = (xsize * PSZB); 86 | 87 | size = zb->xsize * zb->ysize * sizeof(GLushort); 88 | 89 | gl_free(zb->zbuf); 90 | zb->zbuf = gl_malloc(size); 91 | if (zb->zbuf == NULL) 92 | exit(1); 93 | if (zb->frame_buffer_allocated) 94 | gl_free(zb->pbuf); 95 | 96 | if (frame_buffer == NULL) { 97 | zb->pbuf = gl_malloc(zb->ysize * zb->linesize); 98 | if (!zb->pbuf) 99 | exit(1); 100 | zb->frame_buffer_allocated = 1; 101 | } else { 102 | zb->pbuf = frame_buffer; 103 | zb->frame_buffer_allocated = 0; 104 | } 105 | } 106 | 107 | #if TGL_FEATURE_32_BITS == 1 108 | PIXEL pxReverse32(PIXEL x) { 109 | return 110 | ((x & 0xFF000000) >> 24) | /*______AA*/ 111 | ((x & 0x00FF0000) >> 8) | /*____RR__*/ 112 | ((x & 0x0000FF00) << 8) | /*__GG____*/ 113 | ((x & 0x000000FF) << 24); /* BB______*/ 114 | } 115 | #endif 116 | 117 | static void ZB_copyBuffer(ZBuffer* zb, void* buf, GLint linesize) { 118 | GLint y, i; 119 | #if TGL_FEATURE_MULTITHREADED_ZB_COPYBUFFER == 1 120 | #ifdef _OPENMP 121 | #pragma omp parallel for 122 | #endif 123 | for (y = 0; y < zb->ysize; y++) { 124 | PIXEL* q; 125 | GLubyte* p1; 126 | q = zb->pbuf + y * zb->xsize; 127 | p1 = (GLubyte*)buf + y * linesize; 128 | #if TGL_FEATURE_NO_COPY_COLOR == 1 129 | for (i = 0; i < zb->xsize; i++) { 130 | if ((*(q + i) & TGL_COLOR_MASK) != TGL_NO_COPY_COLOR) 131 | *(((PIXEL*)p1) + i) = *(q + i); 132 | } 133 | #else 134 | memcpy(p1, q, linesize); 135 | #endif 136 | 137 | 138 | } 139 | #else 140 | for (y = 0; y < zb->ysize; y++) { 141 | PIXEL* q; 142 | GLubyte* p1; 143 | q = zb->pbuf + y * zb->xsize; 144 | p1 = (GLubyte*)buf + y * linesize; 145 | #if TGL_FEATURE_NO_COPY_COLOR == 1 146 | for (i = 0; i < zb->xsize; i++) { 147 | if ((*(q + i) & TGL_COLOR_MASK) != TGL_NO_COPY_COLOR) 148 | *(((PIXEL*)p1) + i) = *(q + i); 149 | } 150 | #else 151 | memcpy(p1, q, linesize); 152 | #endif 153 | } 154 | #endif 155 | } 156 | 157 | #if TGL_FEATURE_RENDER_BITS == 16 158 | 159 | /* 32 bpp copy */ 160 | /* 161 | 162 | #ifdef TGL_FEATURE_32_BITS 163 | 164 | #define RGB16_TO_RGB32(p0,p1,v)\ 165 | {\ 166 | GLuint g,b,gb;\ 167 | g = (v & 0x07E007E0) << 5;\ 168 | b = (v & 0x001F001F) << 3;\ 169 | gb = g | b;\ 170 | p0 = (gb & 0x0000FFFF) | ((v & 0x0000F800) << 8);\ 171 | p1 = (gb >> 16) | ((v & 0xF8000000) >> 8);\ 172 | } 173 | 174 | 175 | static void ZB_copyFrameBufferRGB32(ZBuffer * zb, 176 | void *buf, 177 | GLint linesize) 178 | { 179 | GLushort *q; 180 | GLuint *p, *p1, v, w0, w1; 181 | GLint y, n; 182 | 183 | q = zb->pbuf; 184 | p1 = (GLuint *) buf; 185 | 186 | for (y = 0; y < zb->ysize; y++) { 187 | p = p1; 188 | n = zb->xsize >> 2; 189 | do { 190 | v = *(GLuint *) q; 191 | RGB16_TO_RGB32(w1, w0, v); 192 | p[0] = w0; 193 | p[1] = w1; 194 | v = *(GLuint *) (q + 2); 195 | RGB16_TO_RGB32(w1, w0, v); 196 | p[2] = w0; 197 | p[3] = 0; 198 | 199 | q += 4; 200 | p += 4; 201 | } while (--n > 0); 202 | 203 | p1 += linesize; 204 | } 205 | } 206 | */ 207 | #endif 208 | 209 | /* 24 bit packed pixel handling */ 210 | 211 | #ifdef TGL_FEATURE_24_BITS 212 | 213 | /* order: RGBR GBRG BRGB */ 214 | 215 | /* XXX: packed pixel 24 bit support not tested */ 216 | /* XXX: big endian case not optimised */ 217 | /* 218 | #if BYTE_ORDER == BIG_ENDIAN 219 | 220 | #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ 221 | {\ 222 | GLuint r1,g1,b1,gb1,g2,b2,gb2;\ 223 | v1 = (v1 << 16) | (v1 >> 16);\ 224 | v2 = (v2 << 16) | (v2 >> 16);\ 225 | r1 = (v1 & 0xF800F800);\ 226 | g1 = (v1 & 0x07E007E0) << 5;\ 227 | b1 = (v1 & 0x001F001F) << 3;\ 228 | gb1 = g1 | b1;\ 229 | p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ 230 | g2 = (v2 & 0x07E007E0) << 5;\ 231 | b2 = (v2 & 0x001F001F) << 3;\ 232 | gb2 = g2 | b2;\ 233 | p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ 234 | p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ 235 | } 236 | 237 | #else 238 | 239 | #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ 240 | {\ 241 | GLuint r1,g1,b1,gb1,g2,b2,gb2;\ 242 | r1 = (v1 & 0xF800F800);\ 243 | g1 = (v1 & 0x07E007E0) << 5;\ 244 | b1 = (v1 & 0x001F001F) << 3;\ 245 | gb1 = g1 | b1;\ 246 | p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ 247 | g2 = (v2 & 0x07E007E0) << 5;\ 248 | b2 = (v2 & 0x001F001F) << 3;\ 249 | gb2 = g2 | b2;\ 250 | p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ 251 | p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ 252 | } 253 | 254 | #endif 255 | */ 256 | /* 257 | static void ZB_copyFrameBufferRGB24(ZBuffer * zb, 258 | void *buf, 259 | GLint linesize) 260 | { 261 | GLushort *q; 262 | GLuint *p, *p1, w0, w1, w2, v0, v1; 263 | GLint y, n; 264 | 265 | q = zb->pbuf; 266 | p1 = (GLuint *) buf; 267 | linesize = linesize * 3; 268 | 269 | for (y = 0; y < zb->ysize; y++) { 270 | p = p1; 271 | n = zb->xsize >> 2; 272 | do { 273 | v0 = *(GLuint *) q; 274 | v1 = *(GLuint *) (q + 2); 275 | RGB16_TO_RGB24(w0, w1, w2, v0, v1); 276 | p[0] = w0; 277 | p[1] = w1; 278 | p[2] = w2; 279 | 280 | q += 4; 281 | p += 3; 282 | } while (--n > 0); 283 | 284 | *((GLbyte *) p1) += linesize; 285 | } 286 | } 287 | */ 288 | #endif 289 | 290 | #if TGL_FEATURE_RENDER_BITS == 16 291 | 292 | void ZB_copyFrameBuffer(ZBuffer* zb, void* buf, GLint linesize) { 293 | 294 | ZB_copyBuffer(zb, buf, linesize); 295 | } 296 | 297 | #endif 298 | /*^ TGL_FEATURE_RENDER_BITS == 16 */ 299 | 300 | 301 | #if TGL_FEATURE_RENDER_BITS == 32 302 | 303 | #define RGB32_TO_RGB16(v) (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v)&0xff) >> 3)) 304 | 305 | 306 | void ZB_copyFrameBuffer(ZBuffer* zb, void* buf, GLint linesize) { 307 | ZB_copyBuffer(zb, buf, linesize); 308 | } 309 | 310 | #endif 311 | /* ^TGL_FEATURE_RENDER_BITS == 32 */ 312 | 313 | /* 314 | * adr must be aligned on an 'int' 315 | */ 316 | static void memset_s(void* adr, GLint val, GLint count) { 317 | GLint i, n, v; 318 | GLuint* p; 319 | GLushort* q; 320 | 321 | p = adr; 322 | v = val | (val << 16); 323 | 324 | n = count >> 3; 325 | for (i = 0; i < n; i++) { 326 | p[0] = v; 327 | p[1] = v; 328 | p[2] = v; 329 | p[3] = v; 330 | p += 4; 331 | } 332 | 333 | q = (GLushort*)p; 334 | n = count & 7; 335 | for (i = 0; i < n; i++) 336 | *q++ = val; 337 | } 338 | 339 | /* Used in 32 bit mode*/ 340 | static void memset_l(void* adr, GLint val, GLint count) { 341 | GLint i, n, v; 342 | GLuint* p; 343 | p = adr; 344 | v = val; 345 | n = count >> 2; 346 | for (i = 0; i < n; i++) { 347 | p[0] = v; 348 | p[1] = v; 349 | p[2] = v; 350 | p[3] = v; 351 | p += 4; 352 | } 353 | n = count & 3; 354 | for (i = 0; i < n; i++) 355 | *p++ = val; 356 | } 357 | 358 | void ZB_clear(ZBuffer* zb, GLint clear_z, GLint z, GLint clear_color, GLint r, GLint g, GLint b) { 359 | GLuint color; 360 | GLint y; 361 | PIXEL* pp; 362 | if (clear_z) { 363 | memset_s(zb->zbuf, z, zb->xsize * zb->ysize); 364 | } 365 | if (clear_color) { 366 | pp = zb->pbuf; 367 | for (y = 0; y < zb->ysize; y++) { 368 | #if TGL_FEATURE_RENDER_BITS == 15 || TGL_FEATURE_RENDER_BITS == 16 369 | // color = RGB_TO_PIXEL(r, g, b); 370 | #if TGL_FEATURE_FORCE_CLEAR_NO_COPY_COLOR 371 | color = TGL_NO_COPY_COLOR; 372 | #else 373 | color = RGB_TO_PIXEL(r, g, b); 374 | #endif 375 | memset_s(pp, color, zb->xsize); 376 | #elif TGL_FEATURE_RENDER_BITS == 32 377 | #if TGL_FEATURE_FORCE_CLEAR_NO_COPY_COLOR 378 | color = TGL_NO_COPY_COLOR; 379 | #else 380 | color = RGB_TO_PIXEL(r, g, b); 381 | #endif 382 | memset_l(pp, color, zb->xsize); 383 | #else 384 | #error BADJUJU 385 | #endif 386 | pp = (PIXEL*)((GLbyte*)pp + zb->linesize); 387 | } 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /src/zline.c: -------------------------------------------------------------------------------- 1 | #include "../include/zbuffer.h" 2 | #include 3 | 4 | #define ZCMP(z, zpix) (!(zbdt) || z >= (zpix)) 5 | 6 | /* TODO: Implement point size. */ 7 | /* TODO: Implement blending for lines and points. */ 8 | 9 | void ZB_plot(ZBuffer* zb, ZBufferPoint* p) { 10 | 11 | GLint zz, y, x; 12 | GLubyte zbdw = zb->depth_write; 13 | GLubyte zbdt = zb->depth_test; 14 | GLfloat zbps = zb->pointsize; 15 | TGL_BLEND_VARS 16 | zz = p->z >> ZB_POINT_Z_FRAC_BITS; 17 | 18 | if (zbps == 1) { 19 | GLushort* pz; 20 | PIXEL* pp; 21 | pz = zb->zbuf + (p->y * zb->xsize + p->x); 22 | pp = (PIXEL*)((GLbyte*)zb->pbuf + zb->linesize * p->y + p->x * PSZB); 23 | 24 | if (ZCMP(zz, *pz)) { 25 | #if TGL_FEATURE_BLEND == 1 26 | if (!zb->enable_blend) 27 | *pp = RGB_TO_PIXEL(p->r, p->g, p->b); 28 | else 29 | TGL_BLEND_FUNC_RGB(p->r, p->g, p->b, (*pp)) 30 | #else 31 | *pp = RGB_TO_PIXEL(p->r, p->g, p->b); 32 | #endif 33 | if (zbdw) 34 | *pz = zz; 35 | } 36 | } else { 37 | PIXEL col = RGB_TO_PIXEL(p->r, p->g, p->b); 38 | GLfloat hzbps = zbps / 2.0f; 39 | GLint bx = (GLfloat)p->x - hzbps; 40 | GLint ex = (GLfloat)p->x + hzbps; 41 | GLint by = (GLfloat)p->y - hzbps; 42 | GLint ey = (GLfloat)p->y + hzbps; 43 | bx = (bx < 0) ? 0 : bx; 44 | by = (by < 0) ? 0 : by; 45 | ex = (ex > zb->xsize) ? zb->xsize : ex; 46 | ey = (ey > zb->ysize) ? zb->ysize : ey; 47 | for (y = by; y < ey; y++) 48 | for (x = bx; x < ex; x++) { 49 | GLushort* pz = zb->zbuf + (y * zb->xsize + x); 50 | PIXEL* pp = (PIXEL*)((GLbyte*)zb->pbuf + zb->linesize * y + x * PSZB); 51 | 52 | if (ZCMP(zz, *pz)) { 53 | #if TGL_FEATURE_BLEND == 1 54 | if (!zb->enable_blend) 55 | *pp = col; 56 | else 57 | TGL_BLEND_FUNC_RGB(p->r, p->g, p->b, (*pp)) 58 | #else 59 | *pp = col; 60 | #endif 61 | if (zbdw) 62 | *pz = zz; 63 | } 64 | } 65 | } 66 | } 67 | 68 | #define INTERP_Z 69 | static void ZB_line_flat_z(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2, GLint color) { 70 | 71 | GLubyte zbdt = zb->depth_test; 72 | GLubyte zbdw = zb->depth_write; 73 | #include "zline.h" 74 | } 75 | 76 | /* line with color GLinterpolation */ 77 | #define INTERP_Z 78 | #define INTERP_RGB 79 | static void ZB_line_interp_z(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2) { 80 | 81 | GLubyte zbdt = zb->depth_test; 82 | GLubyte zbdw = zb->depth_write; 83 | #include "zline.h" 84 | } 85 | 86 | /* no Z GLinterpolation */ 87 | 88 | static void ZB_line_flat(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2, GLint color) { 89 | 90 | 91 | #include "zline.h" 92 | } 93 | 94 | #define INTERP_RGB 95 | static void ZB_line_interp(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2) { 96 | 97 | #include "zline.h" 98 | } 99 | 100 | void ZB_line_z(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2) { 101 | GLint color1, color2; 102 | 103 | color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); 104 | color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); 105 | 106 | /* choose if the line should have its color GLinterpolated or not */ 107 | if (color1 == color2) { 108 | ZB_line_flat_z(zb, p1, p2, color1); 109 | } else { 110 | ZB_line_interp_z(zb, p1, p2); 111 | } 112 | } 113 | 114 | void ZB_line(ZBuffer* zb, ZBufferPoint* p1, ZBufferPoint* p2) { 115 | GLint color1, color2; 116 | 117 | color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); 118 | color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); 119 | 120 | /* choose if the line should have its color GLinterpolated or not */ 121 | if (color1 == color2) { 122 | ZB_line_flat(zb, p1, p2, color1); 123 | } else { 124 | ZB_line_interp(zb, p1, p2); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/zline.h: -------------------------------------------------------------------------------- 1 | 2 | { 3 | GLint n, dx, dy, sx, pp_inc_1, pp_inc_2; 4 | register GLint a; 5 | register PIXEL* pp; 6 | #if defined(INTERP_RGB) 7 | register GLuint r, g, b; 8 | #endif 9 | #ifdef INTERP_RGB 10 | register GLuint rinc, ginc, binc; 11 | #endif 12 | #ifdef INTERP_Z 13 | register GLushort* pz; 14 | GLint zinc; 15 | register GLint z, zz; 16 | #endif 17 | 18 | if (p1->y > p2->y || (p1->y == p2->y && p1->x > p2->x)) { 19 | ZBufferPoint* tmp; 20 | tmp = p1; 21 | p1 = p2; 22 | p2 = tmp; 23 | } 24 | sx = zb->xsize; 25 | pp = (PIXEL*)((GLbyte*)zb->pbuf + zb->linesize * p1->y + p1->x * PSZB); 26 | #ifdef INTERP_Z 27 | pz = zb->zbuf + (p1->y * sx + p1->x); 28 | z = p1->z; 29 | #endif 30 | 31 | dx = p2->x - p1->x; 32 | dy = p2->y - p1->y; 33 | #ifdef INTERP_RGB 34 | r = p2->r << 8; 35 | g = p2->g << 8; 36 | b = p2->b << 8; 37 | #endif 38 | 39 | #ifdef INTERP_RGB 40 | #define RGB(x) x 41 | #define RGBPIXEL *pp = RGB_TO_PIXEL(r >> 8, g >> 8, b >> 8) 42 | 43 | 44 | #else /* INTERP_RGB */ 45 | #define RGB(x) 46 | #if TGL_FEATURE_RENDER_BITS == 24 47 | #define RGBPIXEL pp[0] = r, pp[1] = g, pp[2] = b 48 | #else 49 | #define RGBPIXEL *pp = color 50 | 51 | #endif 52 | #endif /* INTERP_RGB */ 53 | 54 | #ifdef INTERP_Z 55 | #define ZZ(x) x 56 | #define PUTPIXEL() \ 57 | { \ 58 | zz = z >> ZB_POINT_Z_FRAC_BITS; \ 59 | if (ZCMP(zz, *pz)) { \ 60 | RGBPIXEL; \ 61 | if (zbdw) { \ 62 | *pz = zz; \ 63 | } \ 64 | } \ 65 | } 66 | #else /* INTERP_Z */ 67 | #define ZZ(x) 68 | #define PUTPIXEL() RGBPIXEL 69 | #endif /* INTERP_Z */ 70 | 71 | #define DRAWLINE(dx, dy, inc_1, inc_2) \ 72 | n = dx; \ 73 | ZZ(zinc = (p2->z - p1->z) / n); \ 74 | RGB(rinc = ((p2->r - p1->r) << 8) / n; ginc = ((p2->g - p1->g) << 8) / n; binc = ((p2->b - p1->b) << 8) / n); \ 75 | a = 2 * dy - dx; \ 76 | dy = 2 * dy; \ 77 | dx = 2 * dx - dy; \ 78 | pp_inc_1 = (inc_1)*PSZB; \ 79 | pp_inc_2 = (inc_2)*PSZB; \ 80 | do { \ 81 | PUTPIXEL(); \ 82 | ZZ(z += zinc); \ 83 | RGB(r += rinc; g += ginc; b += binc); \ 84 | if (a > 0) { \ 85 | pp = (PIXEL*)((GLbyte*)pp + pp_inc_1); \ 86 | ZZ(pz += (inc_1)); \ 87 | a -= dx; \ 88 | } else { \ 89 | pp = (PIXEL*)((GLbyte*)pp + pp_inc_2); \ 90 | ZZ(pz += (inc_2)); \ 91 | a += dy; \ 92 | } \ 93 | } while (--n >= 0); 94 | 95 | /* fin macro */ 96 | 97 | if (dx == 0 && dy == 0) { 98 | PUTPIXEL(); 99 | } else if (dx > 0) { 100 | if (dx >= dy) { 101 | DRAWLINE(dx, dy, sx + 1, 1); 102 | } else { 103 | DRAWLINE(dy, dx, sx + 1, sx); 104 | } 105 | } else { 106 | dx = -dx; 107 | if (dx >= dy) { 108 | DRAWLINE(dx, dy, sx - 1, -1); 109 | } else { 110 | DRAWLINE(dy, dx, sx - 1, sx); 111 | } 112 | } 113 | } 114 | 115 | #undef INTERP_Z 116 | #undef INTERP_RGB 117 | 118 | /* GLinternal defines */ 119 | #undef DRAWLINE 120 | #undef PUTPIXEL 121 | #undef ZZ 122 | #undef RGB 123 | #undef RGBPIXEL 124 | -------------------------------------------------------------------------------- /src/zmath.c: -------------------------------------------------------------------------------- 1 | /* Some simple mathematical functions. Don't look for some logic in 2 | the function names :-) */ 3 | 4 | #include "zmath.h" 5 | 6 | #include 7 | #include 8 | 9 | /* ******* Gestion des matrices 4x4 ****** */ 10 | 11 | void gl_M4_Id(M4* a) { 12 | /* 13 | GLint i, j; 14 | #ifdef _OPENMP 15 | #pragma omp simd collapse(2) 16 | #endif 17 | for (i = 0; i < 4; i++) 18 | for (j = 0; j < 4; j++) 19 | if (i == j) 20 | a->m[i][j] = 1.0; 21 | else 22 | a->m[i][j] = 0.0; 23 | */ 24 | const M4 c = (M4){{ 25 | {1, 0, 0, 0}, 26 | {0, 1, 0, 0}, 27 | {0, 0, 1, 0}, 28 | {0, 0, 0, 1}, 29 | }}; 30 | *a = c; 31 | } 32 | 33 | GLint gl_M4_IsId(M4* a) { 34 | 35 | const M4 c = (M4){{ 36 | {1, 0, 0, 0}, 37 | {0, 1, 0, 0}, 38 | {0, 0, 1, 0}, 39 | {0, 0, 0, 1}, 40 | }}; 41 | return (memcmp(a->m, c.m, 16 * sizeof(GLfloat)) == 0); 42 | /* 43 | for (i = 0; i < 4; i++) 44 | for (j = 0; j < 4; j++) { 45 | if (i == j) { 46 | if (a->m[i][j] != 1.0) 47 | return 0; 48 | } else if (a->m[i][j] != 0.0) 49 | return 0; 50 | } 51 | return 1; 52 | */ 53 | } 54 | 55 | void gl_M4_Mul(M4* c, M4* a, M4* b) { 56 | GLint i, j, k; 57 | GLfloat s; 58 | #ifdef _OPENMP 59 | #pragma omp simd 60 | #endif 61 | for (i = 0; i < 4; i++) 62 | for (j = 0; j < 4; j++) { 63 | s = 0.0; 64 | for (k = 0; k < 4; k++) 65 | s += a->m[i][k] * b->m[k][j]; 66 | c->m[i][j] = s; 67 | } 68 | } 69 | 70 | /* c=c*a */ 71 | void gl_M4_MulLeft(M4* c, M4* b) { 72 | GLint i, j, k; 73 | GLfloat s; 74 | M4 a; 75 | 76 | /*memcpy(&a, c, 16*sizeof(GLfloat)); 77 | */ 78 | a = *c; 79 | #ifdef _OPENMP 80 | #pragma omp simd 81 | #endif 82 | for (i = 0; i < 4; i++) 83 | for (j = 0; j < 4; j++) { 84 | s = 0.0; 85 | for (k = 0; k < 4; k++) 86 | s += a.m[i][k] * b->m[k][j]; 87 | c->m[i][j] = s; 88 | } 89 | } 90 | 91 | void gl_M4_Move(M4* a, M4* b) { memcpy(a, b, sizeof(M4)); } 92 | 93 | void gl_MoveV3(V3* a, V3* b) { memcpy(a, b, sizeof(V3)); } 94 | 95 | void gl_MulM4V3(V3* a, M4* b, V3* c) { 96 | a->X = b->m[0][0] * c->X + b->m[0][1] * c->Y + b->m[0][2] * c->Z + b->m[0][3]; 97 | a->Y = b->m[1][0] * c->X + b->m[1][1] * c->Y + b->m[1][2] * c->Z + b->m[1][3]; 98 | a->Z = b->m[2][0] * c->X + b->m[2][1] * c->Y + b->m[2][2] * c->Z + b->m[2][3]; 99 | } 100 | 101 | void gl_MulM3V3(V3* a, M4* b, V3* c) { 102 | a->X = b->m[0][0] * c->X + b->m[0][1] * c->Y + b->m[0][2] * c->Z; 103 | a->Y = b->m[1][0] * c->X + b->m[1][1] * c->Y + b->m[1][2] * c->Z; 104 | a->Z = b->m[2][0] * c->X + b->m[2][1] * c->Y + b->m[2][2] * c->Z; 105 | } 106 | 107 | void gl_M4_MulV4(V4* a, M4* b, V4* c) { 108 | { 109 | a->X = b->m[0][0] * c->X + b->m[0][1] * c->Y + b->m[0][2] * c->Z + b->m[0][3] * c->W; 110 | a->Y = b->m[1][0] * c->X + b->m[1][1] * c->Y + b->m[1][2] * c->Z + b->m[1][3] * c->W; 111 | a->Z = b->m[2][0] * c->X + b->m[2][1] * c->Y + b->m[2][2] * c->Z + b->m[2][3] * c->W; 112 | a->W = b->m[3][0] * c->X + b->m[3][1] * c->Y + b->m[3][2] * c->Z + b->m[3][3] * c->W; 113 | } 114 | } 115 | 116 | /* transposition of a 4x4 matrix */ 117 | void gl_M4_Transpose(M4* a, M4* b) { 118 | { 119 | a->m[0][0] = b->m[0][0]; 120 | a->m[0][1] = b->m[1][0]; 121 | a->m[0][2] = b->m[2][0]; 122 | a->m[0][3] = b->m[3][0]; 123 | 124 | a->m[1][0] = b->m[0][1]; 125 | a->m[1][1] = b->m[1][1]; 126 | a->m[1][2] = b->m[2][1]; 127 | a->m[1][3] = b->m[3][1]; 128 | 129 | a->m[2][0] = b->m[0][2]; 130 | a->m[2][1] = b->m[1][2]; 131 | a->m[2][2] = b->m[2][2]; 132 | a->m[2][3] = b->m[3][2]; 133 | 134 | a->m[3][0] = b->m[0][3]; 135 | a->m[3][1] = b->m[1][3]; 136 | a->m[3][2] = b->m[2][3]; 137 | a->m[3][3] = b->m[3][3]; 138 | } 139 | } 140 | 141 | /* inversion of an orthogonal matrix of type Y=M.X+P */ 142 | void gl_M4_InvOrtho(M4* a, M4 b) { 143 | GLint i, j; 144 | GLfloat s; 145 | #ifdef _OPENMP 146 | #pragma omp simd 147 | #endif 148 | for (i = 0; i < 3; i++) 149 | for (j = 0; j < 3; j++) 150 | a->m[i][j] = b.m[j][i]; 151 | a->m[3][0] = 0.0; 152 | a->m[3][1] = 0.0; 153 | a->m[3][2] = 0.0; 154 | a->m[3][3] = 1.0; 155 | 156 | for (i = 0; i < 3; i++) { 157 | s = 0; 158 | #ifdef _OPENMP 159 | #pragma omp simd 160 | #endif 161 | for (j = 0; j < 3; j++) 162 | s -= b.m[j][i] * b.m[j][3]; 163 | a->m[i][3] = s; 164 | } 165 | } 166 | 167 | /* Inversion of a general nxn matrix. 168 | Note : m is destroyed */ 169 | 170 | GLint Matrix_Inv(GLfloat* r, GLfloat* m, GLint n) { 171 | GLint i, j, k, l; 172 | GLfloat max, tmp, t; 173 | 174 | /* */ 175 | #ifdef _OPENMP 176 | #pragma omp simd 177 | #endif 178 | for (i = 0; i < n * n; i++) 179 | r[i] = 0; 180 | for (i = 0; i < n; i++) 181 | r[i * n + i] = 1; 182 | for (j = 0; j < n; j++) { 183 | 184 | /* recherche du nombre de plus grand module sur la colonne j */ 185 | max = m[j * n + j]; 186 | k = j; 187 | for (i = j + 1; i < n; i++) 188 | if (fabs(m[i * n + j]) > fabs(max)) { 189 | k = i; 190 | max = m[i * n + j]; 191 | } 192 | 193 | /* non GLintersible matrix */ 194 | if (max == 0) 195 | return 1; 196 | 197 | /* permutation des lignes j et k */ 198 | if (k != j) { 199 | #ifdef _OPENMP 200 | #pragma omp simd 201 | #endif 202 | for (i = 0; i < n; i++) { 203 | tmp = m[j * n + i]; 204 | m[j * n + i] = m[k * n + i]; 205 | m[k * n + i] = tmp; 206 | 207 | tmp = r[j * n + i]; 208 | r[j * n + i] = r[k * n + i]; 209 | r[k * n + i] = tmp; 210 | } 211 | } 212 | 213 | /* multiplication de la ligne j par 1/max */ 214 | max = 1 / max; 215 | #ifdef _OPENMP 216 | #pragma omp simd 217 | #endif 218 | for (i = 0; i < n; i++) { 219 | m[j * n + i] *= max; 220 | r[j * n + i] *= max; 221 | } 222 | for (l = 0; l < n; l++) 223 | if (l != j) { 224 | t = m[l * n + j]; 225 | for (i = 0; i < n; i++) { 226 | m[l * n + i] -= m[j * n + i] * t; 227 | r[l * n + i] -= r[j * n + i] * t; 228 | } 229 | } 230 | } 231 | 232 | return 0; 233 | } 234 | 235 | /* inversion of a 4x4 matrix */ 236 | 237 | void gl_M4_Inv(M4* a, M4* b) { 238 | M4 tmp; 239 | memcpy(&tmp, b, sizeof(M4)); 240 | /*tmp=*b;*/ 241 | Matrix_Inv(&a->m[0][0], &tmp.m[0][0], 4); 242 | } 243 | 244 | void gl_M4_Rotate(M4* a, GLfloat t, GLint u) { 245 | GLfloat s, c; 246 | GLint v, w; 247 | if ((v = u + 1) > 2) 248 | v = 0; 249 | if ((w = v + 1) > 2) 250 | w = 0; 251 | s = sin(t); 252 | c = cos(t); 253 | gl_M4_Id(a); 254 | a->m[v][v] = c; 255 | a->m[v][w] = -s; 256 | a->m[w][v] = s; 257 | a->m[w][w] = c; 258 | } 259 | 260 | /* inverse of a 3x3 matrix */ 261 | void gl_M3_Inv(M3* a, M3* m) { 262 | GLfloat det; 263 | 264 | det = m->m[0][0] * m->m[1][1] * m->m[2][2] - m->m[0][0] * m->m[1][2] * m->m[2][1] - m->m[1][0] * m->m[0][1] * m->m[2][2] + 265 | m->m[1][0] * m->m[0][2] * m->m[2][1] + m->m[2][0] * m->m[0][1] * m->m[1][2] - m->m[2][0] * m->m[0][2] * m->m[1][1]; 266 | a->m[0][0] = (m->m[1][1] * m->m[2][2] - m->m[1][2] * m->m[2][1]) / det; 267 | a->m[0][1] = -(m->m[0][1] * m->m[2][2] - m->m[0][2] * m->m[2][1]) / det; 268 | a->m[0][2] = -(-m->m[0][1] * m->m[1][2] + m->m[0][2] * m->m[1][1]) / det; 269 | 270 | a->m[1][0] = -(m->m[1][0] * m->m[2][2] - m->m[1][2] * m->m[2][0]) / det; 271 | a->m[1][1] = (m->m[0][0] * m->m[2][2] - m->m[0][2] * m->m[2][0]) / det; 272 | a->m[1][2] = -(m->m[0][0] * m->m[1][2] - m->m[0][2] * m->m[1][0]) / det; 273 | 274 | a->m[2][0] = (m->m[1][0] * m->m[2][1] - m->m[1][1] * m->m[2][0]) / det; 275 | a->m[2][1] = -(m->m[0][0] * m->m[2][1] - m->m[0][1] * m->m[2][0]) / det; 276 | a->m[2][2] = (m->m[0][0] * m->m[1][1] - m->m[0][1] * m->m[1][0]) / det; 277 | } 278 | 279 | /* vector arithmetic */ 280 | 281 | 282 | 283 | 284 | /* 285 | int gl_V3_Norm(V3* a) { 286 | GLfloat n; 287 | n = sqrt(a->X * a->X + a->Y * a->Y + a->Z * a->Z); 288 | if (n == 0) 289 | return 1; 290 | a->X /= n; 291 | a->Y /= n; 292 | a->Z /= n; 293 | return 0; 294 | } 295 | */ 296 | V3 gl_V3_New(GLfloat x, GLfloat y, GLfloat z) { 297 | V3 a; 298 | a.X = x; 299 | a.Y = y; 300 | a.Z = z; 301 | return a; 302 | } 303 | 304 | V4 gl_V4_New(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { 305 | V4 a; 306 | a.X = x; 307 | a.Y = y; 308 | a.Z = z; 309 | a.W = w; 310 | return a; 311 | } 312 | -------------------------------------------------------------------------------- /src/zmath.h: -------------------------------------------------------------------------------- 1 | #ifndef __ZMATH__ 2 | #define __ZMATH__ 3 | #include "../include/GL/gl.h" 4 | #include "../include/zfeatures.h" 5 | #include 6 | #include 7 | #include 8 | /* Matrix & Vertex */ 9 | 10 | typedef struct { 11 | TGL_ALIGN GLfloat m[4][4]; 12 | } M4; 13 | 14 | typedef struct { 15 | TGL_ALIGN GLfloat m[3][3]; 16 | } M3; 17 | 18 | typedef struct { 19 | TGL_ALIGN GLfloat m[3][4]; 20 | } M34; 21 | 22 | #define X v[0] 23 | #define Y v[1] 24 | #define Z v[2] 25 | #define W v[3] 26 | 27 | typedef struct { 28 | TGL_ALIGN GLfloat v[3]; 29 | } V3; 30 | 31 | typedef struct { 32 | TGL_ALIGN GLfloat v[4]; 33 | } V4; 34 | 35 | void gl_M4_Id(M4* a); 36 | GLint gl_M4_IsId(M4* a); 37 | void gl_M4_Move(M4* a, M4* b); 38 | void gl_MoveV3(V3* a, V3* b); 39 | void gl_MulM4V3(V3* a, M4* b, V3* c); 40 | void gl_MulM3V3(V3* a, M4* b, V3* c); 41 | 42 | void gl_M4_MulV4(V4* a, M4* b, V4* c); 43 | void gl_M4_InvOrtho(M4* a, M4 b); 44 | void gl_M4_Inv(M4* a, M4* b); 45 | void gl_M4_Mul(M4* c, M4* a, M4* b); 46 | void gl_M4_MulLeft(M4* c, M4* a); 47 | void gl_M4_Transpose(M4* a, M4* b); 48 | void gl_M4_Rotate(M4* c, GLfloat t, GLint u); 49 | 50 | 51 | 52 | V3 gl_V3_New(GLfloat x, GLfloat y, GLfloat z); 53 | V4 gl_V4_New(GLfloat x, GLfloat y, GLfloat z, GLfloat w); 54 | 55 | GLint gl_Matrix_Inv(GLfloat* r, GLfloat* m, GLint n); 56 | 57 | 58 | #if TGL_FEATURE_FISR == 1 59 | static GLfloat fastInvSqrt(GLfloat x) { 60 | GLint i; 61 | GLfloat x2; 62 | memcpy(&i, &x, 4); 63 | i = 0x5F1FFFF9 - (i >> 1); 64 | memcpy(&x2, &i, 4); 65 | x2 *= 0.703952253f * (2.38924456f - x * x2 * x2); 66 | return x2; 67 | } 68 | #endif 69 | 70 | static int gl_V3_Norm_Fast(V3* a) { 71 | GLfloat n; 72 | #if TGL_FEATURE_FISR == 1 73 | n = fastInvSqrt(a->X * a->X + a->Y * a->Y + a->Z * a->Z); 74 | if (n > 1E+3) 75 | return 1; 76 | #else 77 | n = sqrt(a->X * a->X + a->Y * a->Y + a->Z * a->Z); 78 | if (n == 0) 79 | return 1; 80 | n = 1.0 / n; 81 | #endif 82 | a->X *= n; 83 | a->Y *= n; 84 | a->Z *= n; 85 | return 0; 86 | } 87 | #endif 88 | 89 | -------------------------------------------------------------------------------- /src/zpostprocess.c: -------------------------------------------------------------------------------- 1 | #include "../include/GL/gl.h" 2 | #include "../include/zbuffer.h" 3 | #include "zgl.h" 4 | 5 | void glPostProcess(GLuint (*postprocess)(GLint x, GLint y, GLuint pixel, GLushort z)) { 6 | GLint i, j; 7 | GLContext* c = gl_get_context(); 8 | #ifdef _OPENMP 9 | #pragma omp parallel for collapse(2) 10 | #endif 11 | for (j = 0; j < c->zb->ysize; j++) 12 | for (i = 0; i < c->zb->xsize; i++) 13 | c->zb->pbuf[i + j * (c->zb->xsize)] = postprocess(i, j, c->zb->pbuf[i + j * (c->zb->xsize)], c->zb->zbuf[i + j * (c->zb->xsize)]); 14 | } 15 | -------------------------------------------------------------------------------- /src/zraster.c: -------------------------------------------------------------------------------- 1 | #include "../include/GL/gl.h" 2 | #include "../include/zbuffer.h" 3 | #include "msghandling.h" 4 | #include "zgl.h" 5 | 6 | static void gl_vertex_transform_raster(GLVertex* v) { 7 | GLContext* c = gl_get_context(); 8 | 9 | { 10 | /* no eye coordinates needed, no normal */ 11 | /* NOTE: W = 1 is assumed */ 12 | GLfloat* m = &c->matrix_model_projection.m[0][0]; 13 | 14 | v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]); 15 | v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]); 16 | v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]); 17 | 18 | if (c->matrix_model_projection_no_w_transform) { 19 | v->pc.W = m[15]; 20 | } else { 21 | v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]); 22 | } 23 | m = &c->matrix_stack_ptr[0]->m[0][0]; 24 | v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]); 25 | v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]); 26 | v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]); 27 | v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]); 28 | } 29 | 30 | v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W); 31 | } 32 | 33 | void glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) { 34 | GLParam p[5]; 35 | p[0].op = OP_RasterPos; 36 | p[1].f = x; 37 | p[2].f = y; 38 | p[3].f = z; 39 | p[4].f = w; 40 | gl_add_op(p); 41 | } 42 | void glopRasterPos(GLParam* p) { 43 | GLContext* c = gl_get_context(); 44 | GLVertex v; 45 | v.coord.X = p[1].f; 46 | v.coord.Y = p[2].f; 47 | v.coord.Z = p[3].f; 48 | v.coord.W = p[4].f; 49 | gl_vertex_transform_raster(&v); 50 | if (v.clip_code == 0) { 51 | { 52 | GLfloat winv = 1.0 / v.pc.W; 53 | v.zp.x = (GLint)(v.pc.X * winv * c->viewport.scale.X + c->viewport.trans.X); 54 | v.zp.y = (GLint)(v.pc.Y * winv * c->viewport.scale.Y + c->viewport.trans.Y); 55 | v.zp.z = (GLint)(v.pc.Z * winv * c->viewport.scale.Z + c->viewport.trans.Z); 56 | } 57 | c->rasterpos.v[0] = v.zp.x; 58 | c->rasterpos.v[1] = v.zp.y; 59 | c->rastervertex = v; 60 | /* c->rasterpos.v[2] = v.zp.z;*/ 61 | c->rasterpos_zz = v.zp.z >> ZB_POINT_Z_FRAC_BITS; 62 | c->rasterposvalid = 1; 63 | } else 64 | c->rasterposvalid = 0; 65 | } 66 | 67 | void glRasterPos2f(GLfloat x, GLfloat y) { glRasterPos4f(x, y, 0, 1); } 68 | void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) { glRasterPos4f(x, y, z, 1); } 69 | 70 | void glRasterPos2fv(GLfloat* v) { glRasterPos2f(v[0], v[1]); } 71 | void glRasterPos3fv(GLfloat* v) { glRasterPos3f(v[0], v[1], v[2]); } 72 | void glRasterPos4fv(GLfloat* v) { glRasterPos4f(v[0], v[1], v[2], v[3]); } 73 | 74 | void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, void* data) { 75 | /* TODO: Come up with a clever scheme for storing the data to avoid pointer dependency. */ 76 | #if TGL_FEATURE_RENDER_BITS == 32 77 | if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_INT_8_8_8_8) { 78 | tgl_warning("\nERROR: Incorrect type for glDrawPixels. It MUST be GL_UNSIGNED_INT or GL_UNSIGNED_INT_8_8_8_8, A R G B!"); 79 | return; 80 | } 81 | #elif TGL_FEATURE_RENDER_BITS == 16 82 | if (type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_SHORT_5_6_5) { 83 | tgl_warning("\nERROR: Incorrect type for glDrawPixels. it MUST be GL_UNSIGNED_SHORT or GL_UNSIGNED_SHORT_5_6_5, R5 G6 B5!"); 84 | return; 85 | } 86 | #else 87 | #error "Bad TGL_FEATURE_RENDER_BITS" 88 | #endif 89 | if (format != GL_RGB) { 90 | tgl_warning("\nERROR: Incorrect format for glDrawPixels."); 91 | return; 92 | } 93 | GLParam p[6]; 94 | p[0].op = OP_DrawPixels; 95 | p[1].i = width; 96 | p[2].i = height; 97 | p[3].p = data; 98 | gl_add_op(p); 99 | } 100 | #define ZCMP(z, zpix) (!(zbdt) || z >= (zpix)) 101 | #define CLIPTEST(_x, _y, _w, _h) ((0 <= _x) && (_w > _x) && (0 <= _y) && (_h > _y)) 102 | void glopDrawPixels(GLParam* p) { 103 | GLContext* c = gl_get_context(); 104 | GLint sy, sx, ty, tx; 105 | 106 | GLint w = p[1].i; 107 | GLint h = p[2].i; 108 | V4 rastpos = c->rasterpos; 109 | ZBuffer* zb = c->zb; 110 | PIXEL* d = p[3].p; 111 | PIXEL* pbuf = zb->pbuf; 112 | GLushort* zbuf = zb->zbuf; 113 | 114 | GLubyte zbdw = zb->depth_write; 115 | GLubyte zbdt = zb->depth_test; 116 | GLint tw = zb->xsize; 117 | GLint th = zb->ysize; 118 | GLfloat pzoomx = c->pzoomx; 119 | GLfloat pzoomy = c->pzoomy; 120 | 121 | GLint zz = c->rasterpos_zz; 122 | #if TGL_FEATURE_BLEND_DRAW_PIXELS == 1 123 | TGL_BLEND_VARS 124 | #endif 125 | #if TGL_FEATURE_BLEND == 1 126 | #if TGL_FEATURE_BLEND_DRAW_PIXELS == 1 127 | GLuint zbeb = zb->enable_blend; 128 | #endif 129 | #endif 130 | if (!c->rasterposvalid)return; 131 | 132 | #if TGL_FEATURE_ALT_RENDERMODES == 1 133 | if (c->render_mode == GL_SELECT) { 134 | gl_add_select(zz, zz); 135 | return; 136 | } else if (c->render_mode == GL_FEEDBACK) { 137 | gl_add_feedback(GL_DRAW_PIXEL_TOKEN, &(c->rastervertex), NULL, NULL, 0); 138 | return; 139 | } 140 | #endif 141 | 142 | #if TGL_FEATURE_MULTITHREADED_DRAWPIXELS == 1 143 | 144 | #ifdef _OPENMP 145 | #pragma omp parallel for 146 | #endif 147 | for (sy = 0; sy < h; sy++) 148 | for (sx = 0; sx < w; sx++) { 149 | PIXEL col = d[sy * w + sx]; 150 | V4 rastoffset; 151 | rastoffset.v[0] = rastpos.v[0] + (GLfloat)sx * pzoomx; 152 | rastoffset.v[1] = rastpos.v[1] - ((GLfloat)(h - sy) * pzoomy); 153 | rastoffset.v[2] = rastoffset.v[0] + pzoomx; 154 | rastoffset.v[3] = rastoffset.v[1] - pzoomy; 155 | 156 | for (ty = rastoffset.v[1]; (GLfloat)ty > rastoffset.v[3]; ty--) 157 | for (tx = rastoffset.v[0]; (GLfloat)tx < rastoffset.v[2]; tx++) 158 | if (CLIPTEST(tx, ty, tw, th)) { 159 | GLushort* pz = zbuf + (ty * tw + tx); 160 | 161 | if (ZCMP(zz, *pz)) { 162 | 163 | #if TGL_FEATURE_BLEND == 1 164 | #if TGL_FEATURE_BLEND_DRAW_PIXELS == 1 165 | if (!zbeb) 166 | pbuf[tx + ty * tw] = col; 167 | else 168 | TGL_BLEND_FUNC(col, pbuf[tx + ty * tw]) 169 | #else 170 | pbuf[tx + ty * tw] = col; 171 | #endif 172 | #else 173 | pbuf[tx + ty * tw] = col; 174 | #endif 175 | if (zbdw) 176 | *pz = zz; 177 | } 178 | } 179 | } 180 | #else 181 | for (sy = 0; sy < h; sy++) 182 | for (sx = 0; sx < w; sx++) { 183 | PIXEL col = d[sy * w + sx]; 184 | V4 rastoffset; 185 | rastoffset.v[0] = rastpos.v[0] + (GLfloat)sx * pzoomx; 186 | rastoffset.v[1] = rastpos.v[1] - ((GLfloat)(h - sy) * pzoomy); 187 | rastoffset.v[2] = rastoffset.v[0] + pzoomx; 188 | rastoffset.v[3] = rastoffset.v[1] - pzoomy; 189 | 190 | for (ty = rastoffset.v[1]; (GLfloat)ty > rastoffset.v[3]; ty--) 191 | for (tx = rastoffset.v[0]; (GLfloat)tx < rastoffset.v[2]; tx++) 192 | if (CLIPTEST(tx, ty, tw, th)) { 193 | GLushort* pz = zbuf + (ty * tw + tx); 194 | 195 | if (ZCMP(zz, *pz)) { 196 | 197 | #if TGL_FEATURE_BLEND == 1 198 | #if TGL_FEATURE_BLEND_DRAW_PIXELS == 1 199 | if (!zbeb) 200 | pbuf[tx + ty * tw] = col; 201 | else 202 | TGL_BLEND_FUNC(col, pbuf[tx + ty * tw]) 203 | #else 204 | pbuf[tx + ty * tw] = col; 205 | #endif 206 | #else 207 | pbuf[tx + ty * tw] = col; 208 | #endif 209 | if (zbdw) 210 | *pz = zz; 211 | } 212 | } 213 | } 214 | #endif 215 | } 216 | 217 | void glPixelZoom(GLfloat x, GLfloat y) { 218 | GLParam p[3]; 219 | p[0].op = OP_PixelZoom; 220 | p[1].f = x; 221 | p[2].f = y; 222 | gl_add_op(p); 223 | } 224 | 225 | void glopPixelZoom(GLParam* p) { 226 | GLContext* c = gl_get_context(); 227 | c->pzoomx = p[1].f; 228 | c->pzoomy = p[2].f; 229 | } 230 | -------------------------------------------------------------------------------- /src/ztext.c: -------------------------------------------------------------------------------- 1 | #include "../include/GL/gl.h" 2 | #include "../include/zbuffer.h" 3 | #include "font8x8_basic.h" 4 | #include "zgl.h" 5 | 6 | 7 | #include 8 | 9 | 10 | void glTextSize(GLTEXTSIZE mode) { 11 | #define NEED_CONTEXT 12 | #include "error_check_no_context.h" 13 | #if TGL_FEATURE_ERROR_CHECK == 1 14 | if (mode < 1 || GL_MAX_TEXT_SIZE < mode) 15 | #define ERROR_FLAG GL_INVALID_ENUM 16 | #include "error_check.h" 17 | #endif 18 | GLParam p[2]; 19 | p[0].op = OP_TextSize; 20 | p[1].ui = mode; 21 | gl_add_op(p); 22 | } 23 | void glopTextSize(GLParam* p) { 24 | GLContext* c = gl_get_context(); 25 | c->textsize = p[1].ui; 26 | } 27 | static void renderchar(GLbyte* bitmap, GLint _x, GLint _y, GLuint p) { 28 | GLint x, y, i, j; 29 | GLint set; 30 | GLContext* c = gl_get_context(); 31 | GLint mult = c->textsize; 32 | for (x = 0; x < 8; x++) { 33 | for (y = 0; y < 8; y++) { 34 | set = bitmap[x] & (1 << y); 35 | if (set) 36 | for (i = 0; i < mult; i++) 37 | for (j = 0; j < mult; j++) 38 | glPlotPixel(y * mult + i + _x, x * mult + j + _y, p); 39 | } 40 | } 41 | } 42 | 43 | void glopPlotPixel(GLParam* p) { 44 | GLContext* c = gl_get_context(); 45 | GLint x = p[1].i; 46 | PIXEL pix = p[2].ui; 47 | c->zb->pbuf[x] = pix; 48 | 49 | } 50 | 51 | void glPlotPixel(GLint x, GLint y, GLuint pix) { 52 | GLParam p[3]; 53 | GLContext* c = gl_get_context(); 54 | #include "error_check.h" 55 | 56 | GLint w = c->zb->xsize; 57 | GLint h = c->zb->ysize; 58 | p[0].op = OP_PlotPixel; 59 | 60 | if (x > -1 && x < w && y > -1 && y < h) { 61 | #if TGL_FEATURE_RENDER_BITS == 16 62 | pix = RGB_TO_PIXEL((pix & COLOR_MULT_MASK), ((pix & 0xFF00) << (COLOR_SHIFT - 8)), ((pix & 255) << COLOR_SHIFT)); 63 | #endif 64 | p[1].i = x + y * w; 65 | p[2].ui = pix; 66 | gl_add_op(p); 67 | } 68 | } 69 | void glDrawText(const GLubyte* text, GLint x, GLint y, GLuint p) { 70 | GLContext* c = gl_get_context(); 71 | GLint i = 0; 72 | #include "error_check.h" 73 | 74 | #if TGL_FEATURE_ERROR_CHECK == 1 75 | if (!text) 76 | #define ERROR_FLAG GL_INVALID_VALUE 77 | #include "error_check.h" 78 | #endif 79 | 80 | GLint w = c->zb->xsize; 81 | GLint h = c->zb->ysize; 82 | GLint xoff = 0; 83 | GLint yoff = 0; 84 | GLint mult = c->textsize; 85 | for (; text[i] != '\0' && y + 7 < h; i++) { 86 | if (text[i] != '\n' && xoff + x < w) { 87 | renderchar(font8x8_basic[text[i]], x + xoff, y + yoff, p); 88 | xoff += 8 * mult; 89 | } else if (text[i] == '\n') { 90 | xoff = 0; 91 | yoff += 8 * mult; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/ztriangle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * An eXtReMeLy complicated, delicate, tuned triangle rasterizer 3 | * Aight, so basically this is the most complicated code you'll ever read in your life. 4 | * The lifetime of variables has been... SUPER Optimized, that's why there's so many random ass curly braces everywhere. 5 | * Yes, it is necessary to do that. This code is extremely delicate 6 | * and even a minor fuck-up is gonna tank the framerate 7 | 8 | Before committing any changes, run gears, model, and texture on your changed code to make sure you didn't 9 | fuck up! 10 | 11 | Things to keep in mind: 12 | 1) Tight control of the lifetimes, scopes, and usage of variables lets us use registers more often and memory less 13 | 2) Doing the same operation on multiple items is faster than doing different things on different items, generally, because 14 | they will be able to take advantage of any/all applicable SIMD/vector ops on your hardware. 15 | 3) Divide operations are vastly more expensive than add/sub/bitwise/etc 16 | 4) Bit shifting is your friend, it's the fast way to multiply or divide by 2. 17 | 5) Fixed point math is used for the depth "z" buffer 18 | 6) We're not just using floats for everything because this is still supposed to be fast on platforms without SSE2 19 | 7) Fewer variables is usually better 20 | */ 21 | 22 | { 23 | GLfloat fdx1, fdx2, fdy1, fdy2; 24 | GLushort* pz1; 25 | PIXEL* pp1; 26 | 27 | GLint part; 28 | GLint dx1, dy1, dx2, dy2; 29 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 30 | GLint the_y; 31 | #endif 32 | GLint error, derror; 33 | GLint x1, dxdy_min, dxdy_max; 34 | /* warning: x2 is multiplied by 2^16 */ 35 | GLint x2=0, dx2dy2=0; 36 | 37 | #ifdef INTERP_Z 38 | GLint z1, dzdx, dzdy, dzdl_min, dzdl_max; 39 | #endif 40 | #ifdef INTERP_RGB 41 | GLint r1, drdx, drdy, drdl_min, drdl_max; 42 | GLint g1, dgdx, dgdy, dgdl_min, dgdl_max; 43 | GLint b1, dbdx, dbdy, dbdl_min, dbdl_max; 44 | #endif 45 | #ifdef INTERP_ST 46 | GLint s1, dsdx, dsdy, dsdl_min, dsdl_max; 47 | GLint t1, dtdx, dtdy, dtdl_min, dtdl_max; 48 | #endif 49 | #ifdef INTERP_STZ 50 | GLfloat sz1, dszdx, dszdy, dszdl_min, dszdl_max; 51 | GLfloat tz1, dtzdx, dtzdy, dtzdl_min, dtzdl_max; 52 | GLfloat fdzdx, fndzdx, ndszdx, ndtzdx; 53 | #endif 54 | 55 | /* we sort the vertex with increasing y */ 56 | if (p1->y < p0->y) { 57 | ZBufferPoint* t = p0; 58 | p0 = p1; 59 | p1 = t; 60 | } 61 | if (p2->y < p0->y) { 62 | ZBufferPoint* t = p2; 63 | p2 = p1; 64 | p1 = p0; 65 | p0 = t; 66 | } else if (p2->y < p1->y) { 67 | ZBufferPoint* t = p1; 68 | p1 = p2; 69 | p2 = t; 70 | } 71 | 72 | /* we compute dXdx and dXdy for all GLinterpolated values */ 73 | fdx1 = p1->x - p0->x; 74 | fdy1 = p1->y - p0->y; 75 | 76 | fdx2 = p2->x - p0->x; 77 | fdy2 = p2->y - p0->y; 78 | 79 | GLfloat fz = fdx1 * fdy2 - fdx2 * fdy1; 80 | /* 81 | if (fz == 0) 82 | return; 83 | fz = 1.0 / fz; 84 | */ 85 | if (fz != 0.0) 86 | fz = 1.0 / fz; 87 | 88 | fdx1 *= fz; 89 | fdy1 *= fz; 90 | fdx2 *= fz; 91 | fdy2 *= fz; 92 | 93 | { 94 | GLfloat d1, d2; 95 | #ifdef INTERP_Z 96 | { 97 | d1 = p1->z - p0->z; 98 | d2 = p2->z - p0->z; 99 | dzdx = (GLint)(fdy2 * d1 - fdy1 * d2); 100 | dzdy = (GLint)(fdx1 * d2 - fdx2 * d1); 101 | } 102 | #endif 103 | 104 | #ifdef INTERP_RGB 105 | { 106 | d1 = p1->r - p0->r; 107 | d2 = p2->r - p0->r; 108 | drdx = (GLint)(fdy2 * d1 - fdy1 * d2); 109 | drdy = (GLint)(fdx1 * d2 - fdx2 * d1); 110 | } 111 | { 112 | d1 = p1->g - p0->g; 113 | d2 = p2->g - p0->g; 114 | dgdx = (GLint)(fdy2 * d1 - fdy1 * d2); 115 | dgdy = (GLint)(fdx1 * d2 - fdx2 * d1); 116 | } 117 | { 118 | d1 = p1->b - p0->b; 119 | d2 = p2->b - p0->b; 120 | dbdx = (GLint)(fdy2 * d1 - fdy1 * d2); 121 | dbdy = (GLint)(fdx1 * d2 - fdx2 * d1); 122 | } 123 | #endif 124 | 125 | #ifdef INTERP_ST 126 | { 127 | d1 = p1->s - p0->s; 128 | d2 = p2->s - p0->s; 129 | dsdx = (GLint)(fdy2 * d1 - fdy1 * d2); 130 | dsdy = (GLint)(fdx1 * d2 - fdx2 * d1); 131 | } 132 | { 133 | d1 = p1->t - p0->t; 134 | d2 = p2->t - p0->t; 135 | dtdx = (GLint)(fdy2 * d1 - fdy1 * d2); 136 | dtdy = (GLint)(fdx1 * d2 - fdx2 * d1); 137 | } 138 | #endif 139 | 140 | #ifdef INTERP_STZ 141 | { 142 | GLfloat zedzed; 143 | zedzed = (GLfloat)p0->z; 144 | p0->sz = (GLfloat)p0->s * zedzed; 145 | p0->tz = (GLfloat)p0->t * zedzed; 146 | zedzed = (GLfloat)p1->z; 147 | p1->sz = (GLfloat)p1->s * zedzed; 148 | p1->tz = (GLfloat)p1->t * zedzed; 149 | zedzed = (GLfloat)p2->z; 150 | p2->sz = (GLfloat)p2->s * zedzed; 151 | p2->tz = (GLfloat)p2->t * zedzed; 152 | } 153 | { 154 | d1 = p1->sz - p0->sz; 155 | d2 = p2->sz - p0->sz; 156 | dszdx = (fdy2 * d1 - fdy1 * d2); 157 | dszdy = (fdx1 * d2 - fdx2 * d1); 158 | } 159 | { 160 | d1 = p1->tz - p0->tz; 161 | d2 = p2->tz - p0->tz; 162 | dtzdx = (fdy2 * d1 - fdy1 * d2); 163 | dtzdy = (fdx1 * d2 - fdx2 * d1); 164 | } 165 | #endif 166 | } 167 | /* screen coordinates */ 168 | 169 | pp1 = (PIXEL*)(zb->pbuf) + zb->xsize * p0->y; 170 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 171 | the_y = p0->y; 172 | #endif 173 | pz1 = zb->zbuf + p0->y * zb->xsize; 174 | 175 | DRAW_INIT(); 176 | /* 177 | part used here and down. 178 | TODO: #pragma omp parallel for private(a, b, c) 179 | Required reading: 180 | jakascorner.com/blog/2016/06/omp-data-sharing-attributes.html 181 | I'd also like to figure out if the main while() loop over raster lines can be OMP parallelized, but I suspect it isn't worth it. 182 | */ 183 | ZBufferPoint *pr1, *pr2, *l1, *l2; 184 | for (part = 0; part < 2; part++) { 185 | GLint nb_lines; 186 | { 187 | register GLint update_left, update_right; 188 | if (part == 0) { 189 | if (fz > 0) { 190 | update_left = 1; 191 | update_right = 1; 192 | l1 = p0; 193 | l2 = p2; 194 | pr1 = p0; 195 | pr2 = p1; 196 | } else { 197 | update_left = 1; 198 | update_right = 1; 199 | l1 = p0; 200 | l2 = p1; 201 | pr1 = p0; 202 | pr2 = p2; 203 | } 204 | nb_lines = p1->y - p0->y; 205 | } else { 206 | /* second part */ 207 | if (fz > 0) { 208 | update_left = 0; 209 | update_right = 1; 210 | pr1 = p1; 211 | pr2 = p2; 212 | } else { 213 | update_left = 1; 214 | update_right = 0; 215 | l1 = p1; 216 | l2 = p2; 217 | } 218 | nb_lines = p2->y - p1->y + 1; 219 | } 220 | /* compute the values for the left edge */ 221 | /*pr1 and pr2 are not used inside this area.*/ 222 | if (update_left) { 223 | { 224 | register GLint tmp; 225 | dy1 = l2->y - l1->y; 226 | dx1 = l2->x - l1->x; 227 | if (dy1 > 0) 228 | tmp = (dx1 << 16) / dy1; 229 | else 230 | tmp = 0; 231 | x1 = l1->x; 232 | error = 0; 233 | derror = tmp & 0x0000ffff; 234 | dxdy_min = tmp >> 16; 235 | } 236 | dxdy_max = dxdy_min + 1; 237 | #ifdef INTERP_Z 238 | z1 = l1->z; 239 | dzdl_min = (dzdy + dzdx * dxdy_min); 240 | dzdl_max = dzdl_min + dzdx; 241 | #endif 242 | #ifdef INTERP_RGB 243 | r1 = l1->r; 244 | drdl_min = (drdy + drdx * dxdy_min); 245 | drdl_max = drdl_min + drdx; 246 | g1 = l1->g; 247 | dgdl_min = (dgdy + dgdx * dxdy_min); 248 | dgdl_max = dgdl_min + dgdx; 249 | b1 = l1->b; 250 | dbdl_min = (dbdy + dbdx * dxdy_min); 251 | dbdl_max = dbdl_min + dbdx; 252 | #endif 253 | #ifdef INTERP_ST 254 | s1 = l1->s; 255 | dsdl_min = (dsdy + dsdx * dxdy_min); 256 | dsdl_max = dsdl_min + dsdx; 257 | t1 = l1->t; 258 | dtdl_min = (dtdy + dtdx * dxdy_min); 259 | dtdl_max = dtdl_min + dtdx; 260 | #endif 261 | #ifdef INTERP_STZ 262 | sz1 = l1->sz; 263 | dszdl_min = (dszdy + dszdx * dxdy_min); 264 | dszdl_max = dszdl_min + dszdx; 265 | tz1 = l1->tz; 266 | dtzdl_min = (dtzdy + dtzdx * dxdy_min); 267 | dtzdl_max = dtzdl_min + dtzdx; 268 | #endif 269 | } 270 | /* compute values for the right edge */ 271 | 272 | if (update_right) { /*Update right tested*/ 273 | dx2 = (pr2->x - pr1->x); 274 | dy2 = (pr2->y - pr1->y); /*LAST USAGE OF PR2*/ 275 | if (dy2 > 0) 276 | dx2dy2 = (dx2 << 16) / dy2; 277 | else 278 | dx2dy2 = 0; 279 | x2 = pr1->x << 16; /*LAST USAGE OF PR1*/ 280 | } /*EOF update right*/ 281 | } /*End of lifetime for ZBufferpoints*/ 282 | /* we draw all the scan line of the part */ 283 | 284 | while (nb_lines > 0) { 285 | nb_lines--; 286 | #ifndef DRAW_LINE 287 | /* generic draw line */ 288 | { 289 | register PIXEL* pp; 290 | register GLint n; 291 | #ifdef INTERP_Z 292 | register GLushort* pz; 293 | register GLuint z; 294 | #endif 295 | #ifdef INTERP_RGB 296 | register GLint or1, og1, ob1; 297 | #endif 298 | #ifdef INTERP_ST 299 | register GLuint s, t; 300 | #endif 301 | #ifdef INTERP_STZ 302 | 303 | #endif 304 | 305 | n = (x2 >> 16) - x1; 306 | 307 | pp = (PIXEL*)pp1 + x1; 308 | #ifdef INTERP_Z 309 | pz = pz1 + x1; 310 | z = z1; 311 | #endif 312 | #ifdef INTERP_RGB 313 | or1 = r1; 314 | og1 = g1; 315 | ob1 = b1; 316 | #endif 317 | #ifdef INTERP_ST 318 | s = s1; 319 | t = t1; 320 | #endif 321 | #ifdef INTERP_STZ 322 | 323 | 324 | #endif 325 | while (n >= 3) { 326 | PUT_PIXEL(0); /*the_x++;*/ 327 | PUT_PIXEL(1); /*the_x++;*/ 328 | PUT_PIXEL(2); /*the_x++;*/ 329 | PUT_PIXEL(3); /*the_x++;*/ 330 | #ifdef INTERP_Z 331 | pz += 4; 332 | #endif 333 | 334 | pp += 4; 335 | n -= 4; 336 | } 337 | while (n >= 0) { 338 | PUT_PIXEL(0); /*the_x++;*/ 339 | #ifdef INTERP_Z 340 | 341 | pz++; 342 | #endif 343 | /*pp = (PIXEL*)((GLbyte*)pp + PS_ZB);*/ 344 | pp++; 345 | n--; 346 | } 347 | } 348 | #else 349 | DRAW_LINE(); 350 | #endif 351 | 352 | /* left edge */ 353 | error += derror; 354 | if (error > 0) { 355 | error -= 0x10000; 356 | x1 += dxdy_max; 357 | #ifdef INTERP_Z 358 | z1 += dzdl_max; 359 | #endif 360 | #ifdef INTERP_RGB 361 | r1 += drdl_max; 362 | g1 += dgdl_max; 363 | b1 += dbdl_max; 364 | #endif 365 | #ifdef INTERP_ST 366 | s1 += dsdl_max; 367 | t1 += dtdl_max; 368 | #endif 369 | #ifdef INTERP_STZ 370 | sz1 += dszdl_max; 371 | tz1 += dtzdl_max; 372 | #endif 373 | } else { 374 | x1 += dxdy_min; 375 | #ifdef INTERP_Z 376 | z1 += dzdl_min; 377 | #endif 378 | #ifdef INTERP_RGB 379 | r1 += drdl_min; 380 | g1 += dgdl_min; 381 | b1 += dbdl_min; 382 | #endif 383 | #ifdef INTERP_ST 384 | s1 += dsdl_min; 385 | t1 += dtdl_min; 386 | #endif 387 | #ifdef INTERP_STZ 388 | sz1 += dszdl_min; 389 | tz1 += dtzdl_min; 390 | #endif 391 | } 392 | 393 | /* right edge */ 394 | x2 += dx2dy2; 395 | 396 | /* screen coordinates */ 397 | 398 | pp1 += zb->xsize; 399 | #if TGL_FEATURE_POLYGON_STIPPLE == 1 400 | the_y++; 401 | #endif 402 | pz1 += zb->xsize; 403 | } 404 | } 405 | } 406 | 407 | #undef INTERP_Z 408 | #undef INTERP_RGB 409 | #undef INTERP_ST 410 | #undef INTERP_STZ 411 | 412 | #undef DRAW_INIT 413 | #undef DRAW_LINE 414 | #undef PUT_PIXEL 415 | -------------------------------------------------------------------------------- /tgl_minimal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/C-Chads/tinygl/36a7987e7bebfda19615ea33341b1cc0ff9c3b13/tgl_minimal.png --------------------------------------------------------------------------------