├── .gitignore ├── COPYING ├── Makefile ├── README.md ├── doc ├── Makefile ├── libc3-flowchart.dot └── libc3-flowchart.pdf ├── extras ├── c3cairo.c └── c3cairo.h ├── libc3.pc ├── src ├── c3.c ├── c3.h ├── c3algebra.c ├── c3algebra.h ├── c3arcball.c ├── c3arcball.h ├── c3camera.c ├── c3camera.h ├── c3config-darwin.h ├── c3config-linux.h ├── c3config.h ├── c3context.c ├── c3context.h ├── c3cube.c ├── c3cube.h ├── c3driver.h ├── c3driver_context.h ├── c3driver_geometry.h ├── c3driver_object.h ├── c3geometry.c ├── c3geometry.h ├── c3light.c ├── c3light.h ├── c3lines.c ├── c3lines.h ├── c3model_obj.c ├── c3model_obj.h ├── c3model_stl.c ├── c3model_stl.h ├── c3object.c ├── c3object.h ├── c3pixels.c ├── c3pixels.h ├── c3program.c ├── c3program.h ├── c3quaternion.c ├── c3quaternion.h ├── c3sphere.c ├── c3sphere.h ├── c3texture.c ├── c3texture.h ├── c3transform.c ├── c3transform.h ├── c3types.h ├── c_array.h ├── c_utils.c └── c_utils.h └── srcgl ├── c3gl.c ├── c3gl.h ├── c3gl_fbo.c └── c3gl_fbo.h /.gitignore: -------------------------------------------------------------------------------- 1 | ._* 2 | obj-* 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | VERSION = 0.1.1 3 | REVISION = 1 4 | 5 | SHELL := ${shell which bash} 6 | 7 | IPATH += src 8 | IPATH += srcgl 9 | VPATH += src 10 | VPATH += srcgl 11 | 12 | OBJ := obj-${shell $(CC) -dumpmachine} 13 | 14 | C3SRC = ${wildcard src/*.c} 15 | C3OBJ = ${patsubst src/%,${OBJ}/%,${C3SRC:.c=.lo}} 16 | 17 | C3GLSRC = ${wildcard srcgl/*.c} 18 | C3GLOBJ = ${patsubst srcgl/%,${OBJ}/%,${C3GLSRC:.c=.lo}} 19 | 20 | CC = clang 21 | PKGCONFIG = pkg-config 22 | INSTALL = install 23 | 24 | PLATFORM = ${shell uname | tr '[A-Z]' '[a-z]'} 25 | 26 | ifeq (${PLATFORM}, darwin) 27 | # you need to install libtool via 'brew install libtool' on the mac 28 | LIBTOOL = glibtool 29 | else 30 | LIBTOOL = libtool 31 | endif 32 | 33 | CONFIG_H = c3config-${PLATFORM}.h 34 | CPPCAIRO := ${shell $(PKGCONFIG) --cflags pango cairo 2>/dev/null} 35 | 36 | CFLAGS = -g -O2 37 | CPPFLAGS := --std=gnu99 -fPIC 38 | CPPFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} 39 | CPPFLAGS += $(CPPCAIRO) 40 | 41 | LDFLAGS += 42 | 43 | DESTDIR = /usr/local 44 | 45 | -include ${wildcard .make.options*} 46 | 47 | all: ${OBJ} src/$(CONFIG_H) ${OBJ}/libc3.la ${OBJ}/libc3gl.la 48 | 49 | ${OBJ}: 50 | mkdir -p ${OBJ} 51 | 52 | ifneq (${V}, 1) 53 | E=@ 54 | LIBTOOL += --quiet 55 | endif 56 | 57 | src/$(CONFIG_H): Makefile 58 | $(E)rm -f $@ 59 | $(E)echo CONFIG $@ 60 | $(E)( \ 61 | printf "#ifndef __C3_CONFIG__\n#define __C3_CONFIG__\n"; \ 62 | printf "#define CONFIG_C3_VERSION \"$(VERSION)\"\n"; \ 63 | printf "#define CONFIG_C3_PLATFORM \"$(PLATFORM)\"\n"; \ 64 | $(PKGCONFIG) --exists pango cairo || printf "// " ; \ 65 | printf "#define CONFIG_C3_CAIRO 1\n"; \ 66 | printf "#endif\n"; \ 67 | ) >$@ 68 | 69 | ${OBJ}/libc3.la: ${C3OBJ} 70 | @echo LINK $@ 71 | $(E)$(LIBTOOL) --mode=link --tag=CC \ 72 | $(CC) $(CPPFLAGS) $(CFLAGS) \ 73 | $^ -o $@ \ 74 | -version-info 0:1:0 \ 75 | -rpath $(DESTDIR)/lib $(LDFLAGS) 76 | 77 | ${OBJ}/libc3gl.la: ${C3GLOBJ} 78 | @echo LINK $@ 79 | $(E)$(LIBTOOL) --mode=link --tag=CC \ 80 | $(CC) $(CPPFLAGS) $(CFLAGS) \ 81 | $^ -o $@ \ 82 | -version-info 0:1:0 \ 83 | -rpath $(DESTDIR)/lib $(LDFLAGS) 84 | 85 | ${OBJ}/%.lo: %.c 86 | @echo CC $< 87 | $(E)$(LIBTOOL) --mode=compile --tag=CC \ 88 | $(CC) $(CPPFLAGS) $(CFLAGS) -MT $@ -MMD \ 89 | $< -c -o $@ 90 | 91 | install: 92 | mkdir -p $(DESTDIR)/lib/pkgconfig $(DESTDIR)/include/c3 93 | rm -f $(DESTDIR)/lib/libc3* $(DESTDIR)/include/c3/* 94 | $(INSTALL) src/*.h $(DESTDIR)/include/c3/ 95 | cp -a ${OBJ}/.libs/*.a ${OBJ}/.libs/*.so* $(DESTDIR)/lib/ 96 | sed -e 's|PREFIX|${DESTDIR}|g' -e 's|VERSION|${VERSION}|g' \ 97 | libc3.pc >$(DESTDIR)/lib/pkgconfig/libc3.pc 98 | 99 | clean: 100 | rm -rf ${OBJ} 101 | 102 | # include the dependency files generated by gcc, if any 103 | -include ${wildcard ${OBJ}/*.d} 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **libc3** - No frill 'scene' graph library in C 2 | ===== 3 | (C) 2012 Michel Pollet 4 | 5 | **WARNING** This API is not your nanny. It is made to be lean, mean, efficient 6 | with no frill, no asserts, no bounds checking, no sugar coating. 7 | 8 | On the other hand it's fast, reasonably clean and is a micro-fraction of the 9 | other giganormous 'scene graphs' or 'game engine' libraries around. 10 | 11 | It's vaguely inspired by THREE.js funnily enough, because it allows you to 12 | hack around and quickly get stuff on screen with the minimal amount of 13 | effort. 14 | 15 | Introduction 16 | ----------- 17 | The general idea is that the library keeps track of geometry and stuff, but doesn't 18 | do *any* opengl or related calls. Instead, it uses callbacks into code that will 19 | take care of the rendering related tasks. 20 | 21 | So for example a c3pixels represents a texture, but a callback into the rendering 22 | layer will be responsible to push the pixels to OpenGL, and store the object back 23 | into the c3pixels for reference. 24 | 25 | Status 26 | ------- 27 | The API is generally functional, but it's brand new. I try not to add bits that 28 | I aren't needed, and I also don't add stuff that isn't tested. 29 | 30 | There is an ASCII STL file loader that works, and a few other bit of geometry related 31 | helpers. 32 | 33 | It's currently used in one 'serious' project and also in my [3D printer simulator](https://github.com/buserror-uk/simreprap). 34 | libc3 also builds a companion library called *libc3-gl* that implements a default OpenGL 35 | renderer 'driver' as a set of callbacks. *libc3-gl* does the 'dirty' work for loading 36 | shaders, creating and maintaining frame buffer objects, vertex buffer objects etc. 37 | 38 | General Roadmap 39 | --------------- 40 | There is a [PDF Flowchart](https://github.com/buserror-uk/libc3/raw/master/doc/libc3-flowchart.pdf) 41 | of how things are mostly organized as far as data structure goes, but the following is a 42 | breakdown of the major components. 43 | 44 | The API has various bits: 45 | * c3algebra: C derivative of an old C++ piece of code I had lying around and that has 46 | been present in my toolset for a long time. It gives you *vectors* (c3vec2, c3vec3, c3vec4) 47 | and *matrices* (c3mat3, c3mat4) with various tools to manipulate them. 48 | * c3quaternion: Quaternion implementation using c3algebra 49 | * c3camera/c3arcball: camera manipulation bits 50 | 51 | The basic data structure is as follow: 52 | * *c3context*: 53 | Hosts a "root" object, and a list of 'viewpoints' (ie either cameras, or lights). 54 | it can reproject the objects & geometries, and call the callbacks to draw them. 55 | 56 | The context also keeps a list of *c3pixels* and *c3program* that are referenced 57 | by the geometries. 58 | * *c3object*: 59 | * Has a list of (sub) c3objects 60 | * Has a list of c3transforms (ie matrices) 61 | * Has a list of c3geometry (ie real vertices and stuff) 62 | The object is a container for other objects, and for geometry itself. Objects don't 63 | necessary have geometry and/or sub objects, and don't even need transforms if their 64 | vertices are already projected. 65 | * *c3geometry*: 66 | * Has a 'type' (raw for simple vertices, texture, triangles etc) 67 | * Has a 'subtype' (mostly can be used to draw GL types) 68 | * Has a 'material' (ie color, texture, a GPU program... to be completed) 69 | * Has a list of vertices 70 | * Has a list of texture coordinates (optional) 71 | * Has a list of vertices colors (optional) 72 | * Had a list of vertices indexes (optional) 73 | * *c3transform*: 74 | Is just a sugar coated matrix, with an optional name. 75 | 76 | Also there are: 77 | * *c3pixels*: 78 | Is just a wrapper/holder for some pixels, either allocated, or inherited, 79 | it's mostly used for *c3texture* 80 | * *c3texture*: 81 | Associates a *c3geometry* with a *c3pixels* and has a standard Quad 82 | for vertices. The OpenGL drawing is not done there, it's done by the application using 83 | the generic *c3context* driver. 84 | * *c3cairo*: 85 | Placeholder for now, inherits from *c3texture* and will contain a 86 | cairo surface mapped to a GL texture. 87 | * *c3light*: 88 | Source of light, as a hidden geometry do it get transformed like a normal 89 | one. Right now the implementation uses glLight unless there is a shader 90 | installed. 91 | 92 | Draw Drivers "Inheritance" 93 | ------------ 94 | Various object uses static tables of callbacks to implement their behaviours 95 | it's kinda cheap c++ inheritance, without the usual bloat. 96 | 97 | There just a couple macros to call the driver chain for a particular function call. 98 | The relevant bits are in c3driver*.h. 99 | 100 | Mostly the code looks for a matching callback in a static table, and call it if found. 101 | If that callback wants, it can also call the inherited object callback too. 102 | 103 | Dirtyness 104 | --------- 105 | There is a notion of 'dirtyness' in the tree, when you touch a *c3transform*, and/remove 106 | objects and geometry, a dirty bit is propagated up the tree of object. This tells the 107 | rendering it needs to reproject the dirty bits and repopulate the projected vertice 108 | cache. 109 | 110 | The 'dirty' bit moves both ways, when setting a dirty bit to true, it propagates upward, 111 | when you set it to false, it propagates downward in the tree. 112 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: libc3-flowchart.pdf 3 | 4 | %.pdf : %.dot 5 | dot -Tpdf $^ -o $@ 6 | -------------------------------------------------------------------------------- /doc/libc3-flowchart.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | // label = "libc3\n - lightweight scene graph library - Data Structure Hierarchy"; 3 | label = < 4 | libc3 - 5 | http://github.com/buserror-uk/libc3 6 | - Lightweight C Scene Graph Library - Data Structure Flowchart 7 | >; 8 | node [fontsize=24,shape=box]; 9 | // concentrate=true; 10 | 11 | c3context [shape=none, label=< 12 | 13 | 14 | 19 |
c3context
15 | Keeps track of a root c3object,
16 | possible multiple views, and also stores
17 | texture pixels and shader programs 18 |
20 | >]; 21 | c3gl [shape=none, label=< 22 | 23 | 24 | 28 |
c3gl
25 | OpenGL/ES layer to render
26 | libc3 geometry 27 |
29 | >]; 30 | c3context_view [shape=none, label=< 31 | 32 | 33 | 37 |
c3context_view
34 | Keep tracks of a scene point of view.
35 | used for the eye(s), and the light(s) 36 |
38 | >]; 39 | c3camera [shape=none, label=< 40 | 41 | 42 | 47 |
c3camera
43 | Keeps an 'eye' point, a 'lookat'
44 | point the related vectors, and a
45 | transform matrix 46 |
48 | >]; 49 | c3object [shape=none, label=< 50 | 51 | 52 | 57 |
c3object
53 | Anchor point that holds optional
54 | transform matrices, other sub-c3objects
55 | and c3geometries
56 |
58 | >]; 59 | c3transform [shape=none, label=< 60 | 61 | 62 | 66 |
c3transform
63 | Holds a matrix to be applies to
64 | a c3object and it's descendants 65 |
67 | >]; 68 | c3cairo [shape=none, label=< 69 | 70 | 71 | 75 |
c3cairo
72 | Maps a Cairo image surface
73 | to a c3texture - Optional. 74 |
76 | >]; 77 | c3texture [shape=none, label=< 78 | 79 | 80 | 84 |
c3texture
81 | Provides a geometry to render a
82 | c3pixel (and anonymous texture) 83 |
85 | >]; 86 | c3geometry [shape=none, label=< 87 | 88 | 89 | 93 |
c3geometry
90 | Contains the real drawing data, vertices,
91 | tex coordinates, normals and a material. 92 |
94 | >]; 95 | c3pixels [shape=none, label=< 96 | 97 | 98 | 102 |
c3pixels
99 | Basic description of a pixmap
100 | to be loaded as a texture. 101 |
103 | >]; 104 | c3program [shape=none, label=< 105 | 106 | 107 | 111 |
c3program
108 | Holds a vertex/fragment/... program,
109 | also parses them for uniform/parameters 110 |
112 | >]; 113 | c3color [shape=none, label=< 114 | 115 | 116 | 119 |
c3color
117 | Base RGBA float color 118 |
120 | >]; 121 | c3vertex [shape=none, label=< 122 | 123 | 124 | 128 |
c3vertex
125 | Array of X,Y,Z coordinates,
126 | with associated buffer object 127 |
129 | >]; 130 | c3normal [shape=none, label=< 131 | 132 | 133 | 137 |
c3normal
134 | Array of normals with
135 | associated buffer object 136 |
138 | >]; 139 | c3tex [shape=none, label=< 140 | 141 | 142 | 146 |
c3tex
143 | Array of texture coordinates
144 | with associated buffer object 145 |
147 | >]; 148 | c3indice [shape=none, label=< 149 | 150 | 151 | 155 |
c3indice
152 | Array of indices into
153 | the other arrays 154 |
156 | >]; 157 | c3mat [shape=none, label=< 158 | 159 | 160 | 164 |
c3mat
161 | Geometry material related data
162 | ie color, texture, program. 163 |
165 | >]; 166 | c3stl [shape=none, label=< 167 | 168 | 169 | 173 |
c3stl
170 | Loads ASCII STL model files
171 | and generates corresponding c3object. 172 |
174 | >]; 175 | c3lines [shape=none, label=< 176 | 177 | 178 | 183 |
c3lines
179 | Converts segments into a textured
180 | triangle mesh for wide,
181 | antialiasied lines 182 |
184 | >]; 185 | c3sphere [shape=none, label=< 186 | 187 | 188 | 192 |
c3sphere
189 | Creares geometry for a sphere
190 | with texture coordinaes&normals 191 |
193 | >]; 194 | 195 | { rank = same; c3context; c3gl; } 196 | c3context -> c3gl [ weight=0.1, color="gray" ]; 197 | c3gl -> c3context [ weight=0.1, color="gray" ]; 198 | c3context -> c3context_view; 199 | c3context -> c3object [style=bold]; 200 | c3context -> c3pixels [style=dashed]; 201 | c3context -> c3program [style=dashed]; 202 | 203 | c3context_view -> c3camera; 204 | 205 | { rank = same; c3object; c3stl; } 206 | { rank = same; c3geometry; c3lines; c3sphere; } 207 | c3stl -> c3object [ weight=0.1, color="gray" ]; 208 | c3lines -> c3geometry [ weight=0.1, color="gray" ]; 209 | c3sphere -> c3geometry [ weight=0.1, color="gray" ]; 210 | 211 | c3texture -> c3geometry; 212 | { node [style=dashed]; c3cairo; } 213 | c3cairo -> c3texture; 214 | 215 | c3object -> c3geometry [style=bold]; 216 | c3object -> c3texture; 217 | c3object -> c3cairo; 218 | c3object -> c3transform; 219 | 220 | c3object -> c3object; 221 | 222 | c3geometry -> c3vertex; 223 | c3geometry -> c3normal ; 224 | c3geometry -> c3tex; 225 | c3geometry -> c3mat; 226 | c3geometry -> c3indice; 227 | 228 | c3mat -> c3pixels; 229 | c3mat -> c3program; 230 | c3mat -> c3color; 231 | 232 | c3texture -> c3pixels; 233 | }; 234 | -------------------------------------------------------------------------------- /doc/libc3-flowchart.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buserror/libc3/3dc6072bd877ee336f73420689efbbef7afc1d46/doc/libc3-flowchart.pdf -------------------------------------------------------------------------------- /extras/c3cairo.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3cairo.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c3cairo.h" 24 | #include "c3driver_geometry.h" 25 | 26 | #if CONFIG_C3_CAIRO 27 | 28 | void 29 | _c3cairo_dispose( 30 | c3geometry_p g, 31 | const c3driver_geometry_t * d) 32 | { 33 | c3cairo_p c = (c3cairo_p)g; 34 | 35 | if (c->cr) 36 | cairo_destroy(c->cr); 37 | if (c->surface) 38 | cairo_surface_destroy(c->surface); 39 | C3_DRIVER_INHERITED(g, d, dispose); 40 | } 41 | 42 | static void 43 | _c3cairo_project( 44 | c3geometry_p g, 45 | const struct c3driver_geometry_t *d, 46 | c3mat4p m) 47 | { 48 | C3_DRIVER_INHERITED(g, d, project, m); 49 | } 50 | 51 | const c3driver_geometry_t c3cairo_base_driver = { 52 | .dispose = _c3cairo_dispose, 53 | .project = _c3cairo_project, 54 | }; 55 | extern const c3driver_geometry_t c3texture_driver; 56 | extern const c3driver_geometry_t c3geometry_driver; 57 | 58 | c3cairo_p 59 | c3cairo_new( 60 | struct c3object_t * parent) 61 | { 62 | c3cairo_p res = malloc(sizeof(*res)); 63 | return c3cairo_init(res, parent); 64 | } 65 | 66 | c3cairo_p 67 | c3cairo_init( 68 | c3cairo_p o, 69 | struct c3object_t * parent) 70 | { 71 | memset(o, 0, sizeof(*o)); 72 | c3texture_init(&o->tex, parent); 73 | 74 | static const c3driver_geometry_t * list[] = { 75 | &c3cairo_base_driver, &c3texture_driver, &c3geometry_driver, NULL, 76 | }; 77 | ((c3geometry_p)o)->driver = list; 78 | 79 | return o; 80 | } 81 | 82 | c3cairo_p 83 | c3cairo_new_offscreen( 84 | struct c3object_t * parent, 85 | int w, int h) 86 | { 87 | c3cairo_p o = c3cairo_new(parent); 88 | 89 | o->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); 90 | o->cr = cairo_create(o->surface); 91 | 92 | c3pixels_p dst = c3pixels_new(w, h, 4, 93 | cairo_image_surface_get_stride(o->surface), 94 | cairo_image_surface_get_data(o->surface)); 95 | o->tex.geometry.mat.texture = dst; 96 | 97 | return o; 98 | } 99 | 100 | #if 0 101 | cairo_surface_destroy(_surface); 102 | else 103 | cairo_surface_finish(_surface); 104 | #endif 105 | #endif // CONFIG_C3_CAIRO 106 | -------------------------------------------------------------------------------- /extras/c3cairo.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3cairo.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3CAIRO_H___ 24 | #define __C3CAIRO_H___ 25 | 26 | #include "c3config.h" 27 | #include "c3texture.h" 28 | #include "c3pixels.h" 29 | 30 | #if CONFIG_C3_CAIRO 31 | #include 32 | 33 | typedef struct c3cairo_t { 34 | c3texture_t tex; 35 | cairo_t * cr; 36 | cairo_surface_t * surface; 37 | } c3cairo_t, *c3cairo_p; 38 | 39 | c3cairo_p 40 | c3cairo_new( 41 | struct c3object_t * parent /* = NULL */); 42 | 43 | c3cairo_p 44 | c3cairo_init( 45 | c3cairo_p o, 46 | struct c3object_t * parent /* = NULL */); 47 | 48 | c3cairo_p 49 | c3cairo_new_offscreen( 50 | struct c3object_t * parent /* = NULL */, 51 | int w, int h); 52 | 53 | #endif // CONFIG_C3_CAIRO 54 | 55 | #endif /* __C3CAIRO_H___ */ 56 | -------------------------------------------------------------------------------- /libc3.pc: -------------------------------------------------------------------------------- 1 | libc3.pc: 2 | prefix=PREFIX 3 | exec_prefix=${prefix} 4 | includedir=${prefix}/include 5 | libdir=${exec_prefix}/lib 6 | 7 | Name: libc3 8 | Description: Lightweight scene graph library in C 9 | Version: VERSION 10 | Cflags: -I${includedir} 11 | Requires.private: pangocairo 12 | Libs: -L${libdir} -llibc3 13 | -------------------------------------------------------------------------------- /src/c3.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c3.h" 24 | #include "c3config.h" 25 | 26 | const char * 27 | c3version() 28 | { 29 | return CONFIG_C3_VERSION; 30 | } 31 | -------------------------------------------------------------------------------- /src/c3.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3_H___ 24 | #define __C3_H___ 25 | 26 | #include "c3context.h" 27 | #include "c3object.h" 28 | #include "c3geometry.h" 29 | #include "c3transform.h" 30 | #include "c3texture.h" 31 | 32 | const char * 33 | c3version(); 34 | 35 | #endif /* __C3_H___ */ 36 | -------------------------------------------------------------------------------- /src/c3algebra.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3algebra.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | Derivative and inspiration from original C++: 7 | Paul Rademacher & Jean-Francois DOUEG, 8 | 9 | This file is part of libc3. 10 | 11 | libc3 is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | libc3 is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with libc3. If not, see . 23 | */ 24 | 25 | 26 | #ifndef __C3ALGEBRA_H___ 27 | #define __C3ALGEBRA_H___ 28 | 29 | 30 | #ifndef M_PI 31 | #define M_PI 3.141592654 32 | #endif 33 | #define PI_OVER_180 0.017453292519943295769236907684886 34 | #define PI_OVER_360 0.0087266462599716478846184538424431 35 | 36 | enum {VX, VY, VZ, VW}; // axes 37 | enum {PA, PB, PC, PD}; // planes 38 | enum {RED, GREEN, BLUE, ALPHA}; // colors 39 | enum {KA, KD, KS, ES}; // phong coefficients 40 | 41 | typedef float c3f; 42 | typedef c3f (*V_FCT_PTR)(c3f); 43 | 44 | typedef union c3vec2 { 45 | struct { c3f x,y; }; 46 | c3f n[2]; 47 | } c3vec2; 48 | 49 | typedef union c3vec3 { 50 | struct { c3f x,y,z; }; 51 | c3f n[3]; 52 | } c3vec3; 53 | 54 | typedef union c3vec4 { 55 | struct { c3f x,y,z,w; }; 56 | c3f n[4]; 57 | } c3vec4, * c3vec4p; 58 | 59 | typedef union c3mat3 { 60 | c3vec3 v[3]; 61 | c3f n[3*3]; 62 | } c3mat3, * c3mat3p; 63 | 64 | typedef union c3mat4 { 65 | c3vec4 v[4]; 66 | c3f n[4*4]; 67 | } c3mat4, * c3mat4p; 68 | 69 | /* 70 | * c3vec2 related 71 | */ 72 | 73 | c3vec2 c3vec2_zero(); 74 | c3vec2 c3vec2f(c3f x, c3f y); 75 | 76 | c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v); 77 | c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v); 78 | c3vec2 c3vec2_mulf(c3vec2 a, c3f d); 79 | c3vec2 c3vec2_divf(c3vec2 a, c3f d); 80 | 81 | c3f c3vec2_length2(const c3vec2 a); 82 | c3f c3vec2_length(const c3vec2 a); 83 | c3vec2 c3vec2_normalize(const c3vec2 a); // it is up to caller to avoid divide-by-zero 84 | c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct); 85 | c3vec2 c3vec2_minus(const c3vec2 a); 86 | c3f c3vec2_dot(const c3vec2 a, const c3vec2 b); 87 | c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b); 88 | c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b); 89 | c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b); 90 | 91 | /* 92 | * c3vec3 related 93 | */ 94 | 95 | c3vec3 c3vec3_zero(); 96 | c3vec3 c3vec3f(c3f x, c3f y, c3f z); 97 | c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d); 98 | c3vec3 c3vec3_vec2(const c3vec2 v); 99 | c3vec3 c3vec3_vec4(const c3vec4 v); // it is up to caller to avoid divide-by-zero 100 | 101 | c3vec3 c3vec3_add(const c3vec3 a, const c3vec3 v); 102 | c3vec3 c3vec3_sub(const c3vec3 a, const c3vec3 v); 103 | c3vec3 c3vec3_mulf(const c3vec3 a, c3f d); 104 | c3vec3 c3vec3_divf(const c3vec3 a, c3f d); 105 | 106 | c3f c3vec3_length2(const c3vec3 a); 107 | c3f c3vec3_length(const c3vec3 a); 108 | c3vec3 c3vec3_normalize(const c3vec3 a); // it is up to caller to avoid divide-by-zero 109 | c3vec3 c3vec3_homogenize(c3vec3 a); // it is up to caller to avoid divide-by-zero 110 | c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct); 111 | c3vec3 c3vec3_minus(const c3vec3 a); 112 | c3f c3vec3_dot(const c3vec3 a, const c3vec3 b); 113 | int c3vec3_equal(const c3vec3 a, const c3vec3 b); 114 | c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b); 115 | c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b); 116 | c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b); 117 | 118 | c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b); 119 | c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b); 120 | c3vec3 c3vec3_polar(const c3vec3 a); // returns phi, theta, length 121 | 122 | /* 123 | * c3vec4 related 124 | */ 125 | 126 | c3vec4 c3vec4_zero(); 127 | c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w); 128 | c3vec4 c3vec4_vec3(const c3vec3 v); 129 | c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d); 130 | 131 | c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v); 132 | c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v); 133 | c3vec4 c3vec4_mulf(c3vec4 a, c3f d); 134 | c3vec4 c3vec4_divf(c3vec4 a, c3f d); 135 | 136 | c3f c3vec4_length2(const c3vec4 a); 137 | c3f c3vec4_length(const c3vec4 a); 138 | c3vec4 c3vec4_normalize(c3vec4 a); // it is up to caller to avoid divide-by-zero 139 | c3vec4 c3vec4_homogenize(c3vec4 a); // it is up to caller to avoid divide-by-zero 140 | c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct); 141 | c3vec4 c3vec4_minus(const c3vec4 a); 142 | int c3vec4_equal(const c3vec4 a, const c3vec4 b); 143 | c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b); 144 | c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b); 145 | c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b); 146 | 147 | /* 148 | * c3mat3 related 149 | */ 150 | 151 | c3mat3 c3mat3_identity(); 152 | c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2); 153 | c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m); 154 | c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m); 155 | c3mat3p c3mat3_mulf(const c3mat3p a, c3f d); 156 | c3mat3p c3mat3_divf(const c3mat3p a, c3f d); 157 | 158 | c3mat3 c3mat3_transpose(const c3mat3p a); 159 | c3mat3 c3mat3_inverse(const c3mat3p m); // Gauss-Jordan elimination with partial pivoting 160 | c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct); 161 | c3mat3 c3mat3_minus(const c3mat3p a); 162 | 163 | c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b); 164 | int c3mat3_equal(const c3mat3p a, const c3mat3p b); 165 | 166 | c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v); 167 | c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v); 168 | c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a); 169 | c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a); 170 | 171 | c3mat3 identity2D(); 172 | c3mat3 translation2D(const c3vec2 v); 173 | c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg); 174 | c3mat3 scaling2D(const c3vec2 scaleVector); 175 | 176 | /* 177 | * c3mat4 related 178 | */ 179 | 180 | c3mat4 c3mat4_identity(); 181 | c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3); 182 | c3mat4 c3mat4f( 183 | c3f a00, c3f a01, c3f a02, c3f a03, 184 | c3f a10, c3f a11, c3f a12, c3f a13, 185 | c3f a20, c3f a21, c3f a22, c3f a23, 186 | c3f a30, c3f a31, c3f a32, c3f a33 ); 187 | 188 | c3mat4 c3mat4_minus(const c3mat4p a); 189 | c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m); 190 | c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b); 191 | c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m); 192 | c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b); 193 | c3mat4p c3mat4p_mulf(c3mat4p a, c3f d); 194 | c3mat4 c3mat4_mulf(const c3mat4p a, c3f d); 195 | c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b); 196 | c3mat4p c3mat4p_divf(c3mat4p a, c3f d); 197 | c3mat4 c3mat4_divf(const c3mat4p a, c3f d); 198 | 199 | c3mat4 c3mat4_transpose(const c3mat4p a); 200 | c3mat4 c3mat4_inverse(const c3mat4p m); // Gauss-Jordan elimination with partial pivoting 201 | c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct); 202 | c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j); 203 | c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j); 204 | int c3mat4_equal(const c3mat4p a, const c3mat4p b); 205 | 206 | c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a); 207 | c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v); 208 | c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v); 209 | 210 | c3mat4 identity3D(); 211 | c3mat4 translation3D(const c3vec3 v); 212 | c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg); 213 | c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad); 214 | c3mat4 scaling3D(const c3vec3 scaleVector); 215 | c3mat4 frustum3D( 216 | c3f left, c3f right, c3f bottom, c3f top, 217 | c3f znear, c3f zfar); 218 | c3mat4 perspective3D(c3f fov, c3f aspect, c3f znear, c3f zfar); 219 | c3mat4 ortho3D( 220 | c3f left, c3f right, c3f bottom, c3f top, 221 | c3f near, c3f far); 222 | c3mat4 screen_ortho3D( 223 | c3f left, c3f right, c3f bottom, c3f top, 224 | c3f near, c3f far); 225 | 226 | #endif /* __C3ALGEBRA_H___ */ 227 | -------------------------------------------------------------------------------- /src/c3arcball.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3arcball.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include "c3arcball.h" 24 | 25 | 26 | /**************************************** c3arcball_init_mat4() ****/ 27 | /* Takes as argument a c3mat4 to use instead of the internal rot */ 28 | 29 | void 30 | c3arcball_init_mat4( 31 | c3arcballp a, 32 | c3mat4p mtx ) 33 | { 34 | c3arcball_init(a); 35 | a->rot_ptr = mtx; 36 | } 37 | 38 | 39 | /**************************************** c3arcball_init_center() ****/ 40 | /* A constructor that accepts the screen center and arcball radius*/ 41 | 42 | void 43 | c3arcball_init_center( 44 | c3arcballp a, 45 | const c3vec2 center, 46 | c3f radius ) 47 | { 48 | c3arcball_init(a); 49 | c3arcball_set_params(a, center, radius); 50 | } 51 | 52 | 53 | /************************************** c3arcball_set_params() ****/ 54 | 55 | void 56 | c3arcball_set_params( 57 | c3arcballp a, 58 | const c3vec2 center, 59 | c3f radius) 60 | { 61 | a->center = center; 62 | a->radius = radius; 63 | } 64 | 65 | /*************************************** c3arcball_init() **********/ 66 | 67 | void 68 | c3arcball_init( 69 | c3arcballp a ) 70 | { 71 | a->center = c3vec2f( 0.0, 0.0 ); 72 | a->radius = 1.0; 73 | a->q_now = c3quat_identity(); 74 | a->rot_ptr = &a->rot; 75 | a->rot = identity3D(); 76 | a->q_increment = c3quat_identity(); 77 | a->rot_increment = identity3D(); 78 | a->is_mouse_down = false; 79 | a->is_spinning = false; 80 | a->damp_factor = 0.0; 81 | a->zero_increment = true; 82 | } 83 | 84 | /*********************************** c3arcball_mouse_to_sphere() ****/ 85 | 86 | c3vec3 87 | c3arcball_mouse_to_sphere( 88 | c3arcballp a, 89 | const c3vec2 p) 90 | { 91 | c3f mag; 92 | c3vec2 v2 = c3vec2_divf(c3vec2_sub(p, a->center), a->radius); 93 | c3vec3 v3 = c3vec3f( v2.n[0], v2.n[1], 0.0 ); 94 | 95 | mag = c3vec2_dot(v2, v2); 96 | 97 | if ( mag > 1.0 ) 98 | v3 = c3vec3_normalize(v3); 99 | else 100 | v3.n[VZ] = (c3f) sqrt( 1.0 - mag ); 101 | 102 | /* Now we add constraints - X takes precedence over Y */ 103 | if ( a->constraint_x ) { 104 | v3 = c3arcball_constrain_vector( v3, c3vec3f( 1.0, 0.0, 0.0 )); 105 | } else if ( a->constraint_y ) { 106 | v3 = c3arcball_constrain_vector( v3, c3vec3f( 0.0, 1.0, 0.0 )); 107 | } 108 | 109 | return v3; 110 | } 111 | 112 | 113 | /************************************ c3arcball_constrain_vector() ****/ 114 | 115 | c3vec3 116 | c3arcball_constrain_vector( 117 | const c3vec3 vector, 118 | const c3vec3 axis) 119 | { 120 | // return (vector - (vector * axis) * axis).normalize(); 121 | return vector; 122 | } 123 | 124 | /************************************ c3arcball_mouse_down() **********/ 125 | 126 | void 127 | c3arcball_mouse_down( 128 | c3arcballp a, 129 | int x, 130 | int y) 131 | { 132 | a->down_pt = c3vec2f( (c3f)x, (c3f) y ); 133 | a->is_mouse_down = true; 134 | 135 | a->q_increment = c3quat_identity(); 136 | a->rot_increment = identity3D(); 137 | a->zero_increment = true; 138 | } 139 | 140 | 141 | /************************************ c3arcball_mouse_up() **********/ 142 | 143 | void 144 | c3arcball_mouse_up( 145 | c3arcballp a) 146 | { 147 | a->q_now = c3quat_mul(a->q_drag, a->q_now); 148 | a->is_mouse_down = false; 149 | } 150 | 151 | 152 | /********************************** c3arcball_mouse_motion() **********/ 153 | 154 | void 155 | c3arcball_mouse_motion( 156 | c3arcballp a, 157 | int x, 158 | int y, 159 | int shift, 160 | int ctrl, 161 | int alt) 162 | { 163 | /* Set the X constraint if CONTROL key is pressed, Y if ALT key */ 164 | c3arcball_set_constraints(a, ctrl != 0, alt != 0 ); 165 | 166 | c3vec2 new_pt = c3vec2f( (c3f)x, (c3f) y ); 167 | c3vec3 v0 = c3arcball_mouse_to_sphere(a, a->down_pt ); 168 | c3vec3 v1 = c3arcball_mouse_to_sphere(a, new_pt ); 169 | 170 | c3vec3 cross = c3vec3_cross(v0, v1); 171 | 172 | a->q_drag = c3quat_vec3(cross, c3vec3_dot(v0, v1)); 173 | 174 | // *rot_ptr = (q_drag * q_now).to_mat4(); 175 | c3mat4 temp = c3quat_to_mat4(a->q_drag); 176 | *a->rot_ptr = c3mat4_mul(a->rot_ptr, &temp); 177 | 178 | a->down_pt = new_pt; 179 | 180 | /* We keep a copy of the current incremental rotation (= q_drag) */ 181 | a->q_increment = a->q_drag; 182 | a->rot_increment = c3quat_to_mat4(a->q_increment); 183 | 184 | c3arcball_set_constraints(a, false, false); 185 | 186 | if (a->q_increment.s < .999999) { 187 | a->is_spinning = true; 188 | a->zero_increment = false; 189 | } else { 190 | a->is_spinning = false; 191 | a->zero_increment = true; 192 | } 193 | } 194 | 195 | 196 | /********************************** c3arcball_mouse_motion() **********/ 197 | #if 0 198 | void 199 | c3arcball_mouse_motion( 200 | c3arcballp a, 201 | int x, 202 | int y) 203 | { 204 | mouse_motion(x, y, 0, 0, 0); 205 | } 206 | #endif 207 | 208 | /***************************** c3arcball_set_constraints() **********/ 209 | 210 | void 211 | c3arcball_set_constraints( 212 | c3arcballp a, 213 | bool _constraint_x, 214 | bool _constraint_y) 215 | { 216 | a->constraint_x = _constraint_x; 217 | a->constraint_y = _constraint_y; 218 | } 219 | 220 | /***************************** c3arcball_idle() *********************/ 221 | 222 | void 223 | c3arcball_idle( 224 | c3arcballp a) 225 | { 226 | if (a->is_mouse_down) { 227 | a->is_spinning = false; 228 | a->zero_increment = true; 229 | } 230 | 231 | if (a->damp_factor < 1.0f) 232 | c3quat_scale_angle(&a->q_increment, 1.0f - a->damp_factor); 233 | 234 | a->rot_increment = c3quat_to_mat4(a->q_increment); 235 | 236 | if (a->q_increment.s >= .999999f) { 237 | a->is_spinning = false; 238 | a->zero_increment = true; 239 | } 240 | } 241 | 242 | 243 | /************************ c3arcball_set_damping() *********************/ 244 | 245 | void 246 | c3arcball_set_damping( 247 | c3arcballp a, 248 | c3f d) 249 | { 250 | a->damp_factor = d; 251 | } 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /src/c3arcball.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3arcball.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | Copyright (c) 1998 Paul Rademacher 6 | Feb 1998, Paul Rademacher (rademach@cs.unc.edu) 7 | Oct 2003, Nigel Stewart - GLUI Code Cleaning 8 | 9 | This file is part of libc3. 10 | 11 | libc3 is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | libc3 is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with libc3. If not, see . 23 | */ 24 | 25 | /* 26 | Arcball, as described by Ken 27 | Shoemake in Graphics Gems IV. 28 | This class takes as input mouse events (mouse down, mouse drag, 29 | mouse up), and creates the appropriate quaternions and 4x4 matrices 30 | to represent the rotation given by the mouse. 31 | 32 | This class is used as follows: 33 | - initialize [either in the constructor or with set_params()], the 34 | center position (x,y) of the arcball on the screen, and the radius 35 | - on mouse down, call mouse_down(x,y) with the mouse position 36 | - as the mouse is dragged, repeatedly call mouse_motion() with the 37 | current x and y positions. One can optionally pass in the current 38 | state of the SHIFT, ALT, and CONTROL keys (passing zero if keys 39 | are not pressed, non-zero otherwise), which constrains 40 | the rotation to certain axes (X for CONTROL, Y for ALT). 41 | - when the mouse button is released, call mouse_up() 42 | 43 | Axis constraints can also be explicitly set with the 44 | set_constraints() function. 45 | 46 | The current rotation is stored in the 4x4 float matrix 'rot'. 47 | It is also stored in the quaternion 'q_now'. 48 | */ 49 | 50 | #ifndef __C3ARCBALL_H___ 51 | #define __C3ARCBALL_H___ 52 | 53 | #include "c3quaternion.h" 54 | 55 | typedef struct c3arcball { 56 | int is_mouse_down : 1, /* true for down, false for up */ 57 | is_spinning : 1, 58 | constraint_x : 1, 59 | constraint_y : 1, 60 | zero_increment : 1; 61 | c3quat q_now, q_down, q_drag, q_increment; 62 | c3vec2 down_pt; 63 | c3mat4 rot, rot_increment; 64 | c3mat4 *rot_ptr; 65 | 66 | c3vec2 center; 67 | c3f radius, damp_factor; 68 | } c3arcball, *c3arcballp; 69 | 70 | void 71 | c3arcball_init( 72 | c3arcballp a ); 73 | void 74 | c3arcball_init_mat4( 75 | c3arcballp a, 76 | c3mat4p mtx ); 77 | void 78 | c3arcball_init_center( 79 | c3arcballp a, 80 | const c3vec2 center, 81 | c3f radius ); 82 | void 83 | c3arcball_set_params( 84 | c3arcballp a, 85 | const c3vec2 center, 86 | c3f radius); 87 | c3vec3 88 | c3arcball_mouse_to_sphere( 89 | c3arcballp a, 90 | const c3vec2 p); 91 | c3vec3 92 | c3arcball_constrain_vector( 93 | const c3vec3 vector, 94 | const c3vec3 axis); 95 | void 96 | c3arcball_mouse_down( 97 | c3arcballp a, 98 | int x, 99 | int y); 100 | void 101 | c3arcball_mouse_up( 102 | c3arcballp a); 103 | 104 | void 105 | c3arcball_mouse_motion( 106 | c3arcballp a, 107 | int x, 108 | int y, 109 | int shift, 110 | int ctrl, 111 | int alt); 112 | void 113 | c3arcball_set_constraints( 114 | c3arcballp a, 115 | bool _constraint_x, 116 | bool _constraint_y); 117 | void 118 | c3arcball_idle( 119 | c3arcballp a); 120 | void 121 | c3arcball_set_damping( 122 | c3arcballp a, 123 | c3f d); 124 | 125 | #endif /* __C3ARCBALL_H___ */ 126 | -------------------------------------------------------------------------------- /src/c3camera.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3camera.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | Copyright (c) 1998 Paul Rademacher 6 | 7 | This file is part of libc3. 8 | 9 | libc3 is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | libc3 is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with libc3. If not, see . 21 | */ 22 | 23 | #include 24 | #include 25 | #include "c3camera.h" 26 | 27 | 28 | void 29 | c3cam_set_distance( 30 | c3cam_p c, 31 | const c3f new_distance) 32 | { 33 | if ( new_distance <= 0.0 ) /* Distance has to be positive */ 34 | return; 35 | 36 | /* We find the current forward vector */ 37 | // forward = lookat - eye; 38 | c->forward = c3vec3_normalize(c3vec3_sub(c->lookat, c->eye)); 39 | 40 | /* Set distance */ 41 | c->distance = new_distance; 42 | 43 | /* Find new eye point */ 44 | c->eye = c3vec3_sub(c->lookat, c3vec3_mulf(c->forward, c->distance)); 45 | c3cam_update(c); 46 | } 47 | 48 | void 49 | c3cam_set_upv( 50 | c3cam_p c, 51 | const c3vec3 new_up) 52 | { 53 | c->up = new_up; 54 | c3cam_update(c); 55 | } 56 | 57 | void 58 | c3cam_set_upf( 59 | c3cam_p c, 60 | const c3f x, 61 | const c3f y, 62 | const c3f z) 63 | { 64 | c3cam_set_upv(c, c3vec3f(x,y,z)); 65 | } 66 | 67 | void 68 | c3cam_set_eyev( 69 | c3cam_p c, 70 | const c3vec3 new_eye) 71 | { 72 | c->eye = new_eye; 73 | c3cam_update(c); 74 | } 75 | 76 | void 77 | c3cam_set_eyef( 78 | c3cam_p c, 79 | const c3f x, 80 | const c3f y, 81 | const c3f z) 82 | { 83 | c3cam_set_eyev(c, c3vec3f(x,y,z)); 84 | } 85 | 86 | void 87 | c3cam_set_lookatv( 88 | c3cam_p c, 89 | const c3vec3 new_lookat) 90 | { 91 | c->lookat = new_lookat; 92 | c3cam_update(c); 93 | } 94 | 95 | void 96 | c3cam_set_lookatf( 97 | c3cam_p c, 98 | const c3f x, 99 | const c3f y, 100 | const c3f z) 101 | { 102 | c3cam_set_lookatv(c, c3vec3f(x,y,z)); 103 | } 104 | 105 | 106 | void 107 | c3cam_roll( 108 | c3cam_p c, 109 | const c3f angle) 110 | { 111 | c3mat4 rot = rotation3D(c->forward, angle ); 112 | c->up = c3mat4_mulv3(&rot, c->up); 113 | c3cam_update(c); 114 | } 115 | 116 | void 117 | c3cam_eye_yaw( 118 | c3cam_p c, 119 | const c3f angle) 120 | { 121 | c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ 122 | c3mat4 rot = rotation3D( c->up, angle ); 123 | 124 | eye_pt = c3mat4_mulv3(&rot, eye_pt); 125 | c->eye = c3vec3_add(c->lookat, eye_pt); 126 | 127 | c3cam_update(c); 128 | } 129 | 130 | void 131 | c3cam_eye_yaw_abs( 132 | c3cam_p c, 133 | const c3f angle, 134 | const c3vec3 axis) 135 | { 136 | c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ 137 | c3mat4 rot = rotation3D( axis, angle ); 138 | 139 | eye_pt = c3mat4_mulv3(&rot, eye_pt); 140 | c->eye = c3vec3_add(c->lookat, eye_pt); 141 | 142 | c->up = c3mat4_mulv3(&rot, c->up); 143 | 144 | c3cam_update(c); 145 | } 146 | 147 | 148 | void 149 | c3cam_eye_pitch( 150 | c3cam_p c, 151 | const c3f angle) 152 | { 153 | c3vec3 eye_pt = c3vec3_sub(c->eye, c->lookat); /* eye w/lookat at center */ 154 | c3mat4 rot = rotation3D( c->side, angle ); 155 | 156 | eye_pt = c3mat4_mulv3(&rot, eye_pt); 157 | c->eye = c3vec3_add(c->lookat, eye_pt); 158 | 159 | c->up = c3mat4_mulv3(&rot, c->up); 160 | 161 | c3cam_update(c); 162 | } 163 | 164 | void 165 | c3cam_lookat_yaw( 166 | c3cam_p c, 167 | const c3f angle) 168 | { 169 | c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ 170 | c3mat4 rot = rotation3D( c->up, -angle ); 171 | 172 | lookat_pt = c3mat4_mulv3(&rot, lookat_pt); 173 | c->lookat = c3vec3_add(c->eye, lookat_pt); 174 | 175 | c3cam_update(c); 176 | } 177 | 178 | void 179 | c3cam_lookat_pitch( 180 | c3cam_p c, 181 | const c3f angle) 182 | { 183 | c3vec3 lookat_pt = c3vec3_sub(c->lookat, c->eye); /* lookat w/eye at center */ 184 | c3mat4 rot = rotation3D( c->side, -angle ); 185 | 186 | lookat_pt = c3mat4_mulv3(&rot, lookat_pt); 187 | c->lookat = c3vec3_add(c->eye, lookat_pt); 188 | 189 | c->up = c3mat4_mulv3(&rot, c->up); 190 | 191 | c3cam_update(c); 192 | } 193 | 194 | void 195 | c3cam_reset_up_axis( 196 | c3cam_p c, 197 | const int axis_num) 198 | { 199 | c3vec3 eye_pt = c3vec3_sub(c->lookat, c->eye); /* eye w/lookat at center */ 200 | c3f eye_distance = c3vec3_length(eye_pt); 201 | c->eye.n[axis_num] = c->lookat.n[axis_num]; 202 | /* Bring eye to same level as lookat */ 203 | 204 | c3vec3 vector = c3vec3_sub(c->eye, c->lookat); 205 | vector = c3vec3_normalize(vector); 206 | vector = c3vec3_mulf(vector, eye_distance); 207 | 208 | c->eye = c3vec3_add(c->lookat, vector); 209 | c->up = c3vec3f( 0.0, 0.0, 0.0 ); 210 | c->up.n[axis_num] = 1.0; 211 | 212 | c3cam_update(c); 213 | } 214 | 215 | void 216 | c3cam_reset_up( 217 | c3cam_p c) 218 | { 219 | c3cam_reset_up_axis(c, VY ); /* Resets to the Y axis */ 220 | } 221 | 222 | void 223 | c3cam_movef( 224 | c3cam_p c, 225 | const c3f side_move, 226 | const c3f up_move, 227 | const c3f forw_move) 228 | { 229 | c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->forward, forw_move)); 230 | c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->side, side_move)); 231 | c->eye = c3vec3_add(c->eye, c3vec3_mulf(c->up, up_move)); 232 | c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->forward, forw_move)); 233 | c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->side, side_move)); 234 | c->lookat = c3vec3_add(c->lookat, c3vec3_mulf(c->up, up_move)); 235 | c3cam_update(c); 236 | } 237 | 238 | void 239 | c3cam_movev( 240 | c3cam_p c, 241 | const c3vec3 v) /* A vector version of the above command */ 242 | { 243 | c3cam_movef(c, v.n[VX], v.n[VY], v.n[VZ] ); 244 | } 245 | 246 | void 247 | c3cam_move_by_eye( 248 | c3cam_p c, 249 | const c3vec3 new_eye) 250 | { 251 | c3vec3 diff = c3vec3_sub(new_eye, c->eye); 252 | 253 | c->lookat = c3vec3_add(c->lookat, diff); 254 | c->eye = c3vec3_add(c->eye, diff); 255 | 256 | c3cam_update(c); 257 | } 258 | 259 | void 260 | c3cam_move_by_lookat( 261 | c3cam_p c, 262 | const c3vec3 new_lookat) 263 | { 264 | c3vec3 diff = c3vec3_sub(new_lookat, c->lookat); 265 | 266 | c->lookat = c3vec3_add(c->lookat, diff); 267 | c->eye = c3vec3_add(c->eye, diff); 268 | 269 | c3cam_update(c); 270 | } 271 | 272 | void 273 | c3cam_move_abs( 274 | c3cam_p c, 275 | const c3vec3 v) 276 | { 277 | c->lookat = c3vec3_add(c->lookat, v); 278 | c->eye = c3vec3_add(c->eye, v); 279 | 280 | c3cam_update(c); 281 | } 282 | 283 | void 284 | c3cam_rot_about_eye( 285 | c3cam_p c, 286 | const c3mat4p rot) 287 | { 288 | c3vec3 view = c3vec3_sub(c->lookat, c->eye); 289 | 290 | view = c3mat4_mulv3(rot, view); 291 | c->up = c3mat4_mulv3(rot, c->up); 292 | 293 | c->lookat = c3vec3_add(c->eye, view); 294 | 295 | c3cam_update(c); 296 | } 297 | 298 | void 299 | c3cam_rot_about_lookat( 300 | c3cam_p c, 301 | const c3mat4p rot) 302 | { 303 | // NOT QUITE RIGHT YET 304 | 305 | c3vec3 view = c3vec3_sub(c->eye, c->lookat); 306 | 307 | view = c3mat4_mulv3(rot, view); 308 | c->up = c3mat4_mulv3(rot, c->up); 309 | 310 | c->eye = c3vec3_add(c->lookat, view); 311 | 312 | c3cam_update(c); 313 | } 314 | 315 | void 316 | c3cam_update_matrix( 317 | c3cam_p c) 318 | { 319 | c3cam_update(c); 320 | 321 | c3mat4 m1 = translation3D(c3vec3_minus(c->eye)); 322 | c3mat4 m2 = c3mat4_vec4( 323 | c3vec4f(c->side.n[VX], c->up.n[VX], c->forward.n[VX], 0.0), 324 | c3vec4f(c->side.n[VY], c->up.n[VY], c->forward.n[VY], 0.0), 325 | c3vec4f(c->side.n[VZ], c->up.n[VZ], c->forward.n[VZ], 0.0), 326 | c3vec4f(0.0, 0.0, 0.0, 1.0)); 327 | c->mtx = c3mat4_mul(&m2, &m1); 328 | } 329 | 330 | void 331 | c3cam_reset( 332 | c3cam_p c) 333 | { 334 | memset(c, 0, sizeof(*c)); 335 | c->up = c3vec3f( 0.0, 1.0, 0.0 ); 336 | c->eye = c3vec3f(0.0, 0.0, 10.0); 337 | c->lookat = c3vec3f(0.0,0.0,0.0); 338 | c->fov = 50.0f; 339 | c->mtx = identity3D(); 340 | 341 | c3cam_update(c); 342 | } 343 | 344 | c3cam_p 345 | c3cam_new() 346 | { 347 | c3cam_p c = malloc(sizeof(*c)); 348 | memset(c, 0, sizeof(*c)); 349 | c3cam_reset(c); 350 | return c; 351 | } 352 | 353 | void 354 | c3cam_init( 355 | c3cam_p c) 356 | { 357 | memset(c, 0, sizeof(*c)); 358 | c3cam_reset(c); 359 | } 360 | 361 | void 362 | c3cam_update( 363 | c3cam_p c) 364 | { 365 | /* get proper side and forward vectors, and distance */ 366 | c->forward = c3vec3_minus(c3vec3_sub(c->lookat, c->eye)); 367 | c->distance = c3vec3_length(c->forward); 368 | c->forward = c3vec3_divf(c->forward, c->distance); 369 | 370 | c->side = c3vec3_cross(c->up, c->forward); 371 | c->up = c3vec3_cross(c->forward, c->side); 372 | 373 | c->forward = c3vec3_normalize(c->forward); 374 | c->up = c3vec3_normalize(c->up); 375 | c->side = c3vec3_normalize(c->side); 376 | } 377 | -------------------------------------------------------------------------------- /src/c3camera.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3camera.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | Copyright (c) 1998 Paul Rademacher 6 | 7 | This file is part of libc3. 8 | 9 | libc3 is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | libc3 is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with libc3. If not, see . 21 | */ 22 | 23 | #ifndef __C3VIEW_H___ 24 | #define __C3VIEW_H___ 25 | 26 | #include "c3algebra.h" 27 | 28 | typedef struct c3cam_t { 29 | c3vec3 eye, lookat; 30 | c3vec3 up, side, forward; 31 | c3mat4 mtx; 32 | c3f distance; 33 | c3f fov; 34 | } c3cam_t, *c3cam_p; 35 | 36 | /******************************* set_distance() ***********/ 37 | /* This readjusts the distance from the eye to the lookat */ 38 | /* (changing the eye point in the process) */ 39 | /* The lookat point is unaffected */ 40 | void 41 | c3cam_set_distance( 42 | c3cam_p c, 43 | const c3f new_distance); 44 | 45 | /******************************* set_up() ***************/ 46 | void 47 | c3cam_set_upv( 48 | c3cam_p c, 49 | const c3vec3 new_up); 50 | void 51 | c3cam_set_upf( 52 | c3cam_p c, 53 | const c3f x, 54 | const c3f y, 55 | const c3f z); 56 | 57 | /******************************* set_eye() ***************/ 58 | void 59 | c3cam_set_eyev( 60 | c3cam_p c, 61 | const c3vec3 new_eye); 62 | void 63 | c3cam_set_eyef( 64 | c3cam_p c, 65 | const c3f x, 66 | const c3f y, 67 | const c3f z); 68 | 69 | /******************************* set_lookat() ***************/ 70 | void 71 | c3cam_set_lookatv( 72 | c3cam_p c, 73 | const c3vec3 new_lookat); 74 | void 75 | c3cam_set_lookatf( 76 | c3cam_p c, 77 | const c3f x, 78 | const c3f y, 79 | const c3f z); 80 | 81 | /******************************* roll() *****************/ 82 | /* Rotates about the forward vector */ 83 | /* eye and lookat remain unchanged */ 84 | void 85 | c3cam_roll( 86 | c3cam_p c, 87 | const c3f angle); 88 | 89 | /******************************* eye_yaw() *********************/ 90 | /* Rotates the eye about the lookat point, using the up vector */ 91 | /* Lookat is unaffected */ 92 | void 93 | c3cam_eye_yaw( 94 | c3cam_p c, 95 | const c3f angle); 96 | 97 | /******************************* eye_yaw_abs() ******************/ 98 | /* Rotates the eye about the lookat point, with a specific axis */ 99 | /* Lookat is unaffected */ 100 | void 101 | c3cam_eye_yaw_abs( 102 | c3cam_p c, 103 | const c3f angle, 104 | const c3vec3 axis); 105 | 106 | /******************************* eye_pitch() ************/ 107 | /* Rotates the eye about the side vector */ 108 | /* Lookat is unaffected */ 109 | void 110 | c3cam_eye_pitch( 111 | c3cam_p c, 112 | const c3f angle); 113 | 114 | /******************************* lookat_yaw()************/ 115 | /* This assumes the up vector is correct. */ 116 | /* Rotates the lookat about the side vector */ 117 | /* Eye point is unaffected */ 118 | void 119 | c3cam_lookat_yaw( 120 | c3cam_p c, 121 | const c3f angle); 122 | 123 | /******************************* lookat_pitch() *********/ 124 | /* Rotates the lookat point about the side vector */ 125 | /* This assumes the side vector is correct. */ 126 | /* Eye point is unaffected */ 127 | void 128 | c3cam_lookat_pitch( 129 | c3cam_p c, 130 | const c3f angle); 131 | 132 | /******************************* reset_up() ******************/ 133 | /* Resets the up vector to a specified axis (0=X, 1=Y, 2=Z) */ 134 | /* Also sets the eye point level with the lookat point, */ 135 | /* along the specified axis */ 136 | void 137 | c3cam_reset_up_axis( 138 | c3cam_p c, 139 | const int axis_num); 140 | void 141 | c3cam_reset_up( 142 | c3cam_p c); 143 | 144 | /******************************* move() ********************/ 145 | /* Moves a specified distance in the forward, side, and up */ 146 | /* directions. This function does NOT move by world */ 147 | /* coordinates. To move by world coords, use the move_abs */ 148 | /* function. */ 149 | void 150 | c3cam_movef( 151 | c3cam_p c, 152 | const c3f side_move, 153 | const c3f up_move, 154 | const c3f forw_move); 155 | void 156 | c3cam_movev( 157 | c3cam_p c, 158 | const c3vec3 v); /* A vector version of the above command */ 159 | 160 | /******************************* move_by_eye() ***********/ 161 | /* Sets the eye point, AND moves the lookat point by the */ 162 | /* same amount as the eye is moved. */ 163 | void 164 | c3cam_move_by_eye( 165 | c3cam_p c, 166 | const c3vec3 new_eye); 167 | 168 | /******************************* move_by_lookat() *********/ 169 | /* Sets the lookat point, AND moves the eye point by the */ 170 | /* same amount as the lookat is moved. */ 171 | void 172 | c3cam_move_by_lookat( 173 | c3cam_p c, 174 | const c3vec3 new_lookat); 175 | 176 | /******************************* move_abs() *****************/ 177 | /* Move the eye and lookat in world coordinates */ 178 | void 179 | c3cam_move_abs( 180 | c3cam_p c, 181 | const c3vec3 v); 182 | 183 | /****************************** rot_about_eye() ************/ 184 | /* Rotates the lookat point about the eye, based on a 4x4 */ 185 | /* (pure) rotation matrix */ 186 | void 187 | c3cam_rot_about_eye( 188 | c3cam_p c, 189 | const c3mat4p rot); 190 | 191 | /****************************** rot_about_lookat() ************/ 192 | /* Rotates the lookat point about the lookat, based on a 4x4 */ 193 | /* (pure) rotation matrix */ 194 | void 195 | c3cam_rot_about_lookat( 196 | c3cam_p c, 197 | const c3mat4p rot); 198 | 199 | /******************************* make_mtx() *************/ 200 | /* Constructs a 4x4 matrix - used by load_to_openGL() */ 201 | void 202 | c3cam_update_matrix( 203 | c3cam_p c); 204 | 205 | /******************************* load_to_openGL() ********/ 206 | /* Sets the OpenGL modelview matrix based on the current */ 207 | /* camera coordinates */ 208 | //void c3cam_load_to_openGL(); 209 | 210 | /******************************* load_to_openGL_noident() ******/ 211 | /* Multiplies the current camera matrix by the existing openGL */ 212 | /* modelview matrix. This is same as above function, but */ 213 | /* does not set the OpenGL matrix to identity first */ 214 | //void c3cam_load_to_openGL_noident(); 215 | 216 | /******************************* reset() ****************/ 217 | /* Resets the parameters of this class */ 218 | void 219 | c3cam_reset( 220 | c3cam_p c); 221 | 222 | /******************************* c3cam_t() ************/ 223 | /* Constructor */ 224 | c3cam_p 225 | c3cam_new(); 226 | 227 | void 228 | c3cam_init( 229 | c3cam_p c); 230 | /******************************* update() ****************/ 231 | /* updates the view params. Call this after making */ 232 | /* direct changes to the vectors or points of this class */ 233 | void c3cam_update( 234 | c3cam_p c); 235 | 236 | #endif /* __C3VIEW_H___ */ 237 | -------------------------------------------------------------------------------- /src/c3config-darwin.h: -------------------------------------------------------------------------------- 1 | #ifndef __C3_CONFIG__ 2 | #define __C3_CONFIG__ 3 | #define CONFIG_C3_VERSION "0.1.1" 4 | #define CONFIG_C3_PLATFORM "darwin" 5 | // #define CONFIG_C3_CAIRO 1 6 | #endif 7 | -------------------------------------------------------------------------------- /src/c3config-linux.h: -------------------------------------------------------------------------------- 1 | #ifndef __C3_CONFIG__ 2 | #define __C3_CONFIG__ 3 | #define CONFIG_C3_VERSION "0.1.1" 4 | #define CONFIG_C3_PLATFORM "linux" 5 | #define CONFIG_C3_CAIRO 1 6 | #endif 7 | -------------------------------------------------------------------------------- /src/c3config.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3config.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #ifndef __C3_CONFIG_MAIN_H_ 23 | #define __C3_CONFIG_MAIN_H_ 24 | 25 | #if __APPLE__ 26 | #include "c3config-darwin.h" 27 | #elif __linux__ 28 | #include "c3config-linux.h" 29 | #else 30 | #error No target platform detected, tweak the makefile 31 | #endif 32 | 33 | #endif // __C3_CONFIG_MAIN_H_ 34 | -------------------------------------------------------------------------------- /src/c3context.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3context.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include "c3context.h" 24 | #include "c3object.h" 25 | #include "c3light.h" 26 | #include "c3driver_context.h" 27 | 28 | c3context_p 29 | c3context_new( 30 | int w, 31 | int h) 32 | { 33 | c3context_p res = malloc(sizeof(*res)); 34 | return c3context_init(res, w, h); 35 | } 36 | 37 | c3context_p 38 | c3context_init( 39 | c3context_p c, 40 | int w, 41 | int h) 42 | { 43 | memset(c, 0, sizeof(*c)); 44 | 45 | c3context_view_t v = { 46 | .type = C3_CONTEXT_VIEW_EYE, 47 | .size = c3vec2f(w, h), 48 | .dirty = 1, 49 | .index = c->views.count, 50 | }; 51 | c3cam_init(&v.cam); 52 | c3context_view_array_add(&c->views, v); 53 | c->root = c3object_new(NULL); 54 | c->root->context = c; 55 | 56 | return c; 57 | } 58 | 59 | void 60 | c3context_dispose( 61 | c3context_p c) 62 | { 63 | c3object_dispose(c->root); 64 | for (int i = 0; i < c->views.count; i++) 65 | c3geometry_array_free(&c->views.e[i].projected); 66 | free(c); 67 | } 68 | 69 | static c3context_view_p qsort_view; 70 | 71 | void 72 | c3_bbox_vertices( 73 | c3bbox_t * b, 74 | c3vec3 out[8]) 75 | { 76 | out[0] = c3vec3f(b->min.x, b->min.y, b->min.z); 77 | out[1] = c3vec3f(b->min.x, b->min.y, b->max.z); 78 | out[2] = c3vec3f(b->max.x, b->min.y, b->min.z); 79 | out[3] = c3vec3f(b->max.x, b->min.y, b->max.z); 80 | out[4] = c3vec3f(b->max.x, b->max.y, b->min.z); 81 | out[5] = c3vec3f(b->max.x, b->max.y, b->max.z); 82 | out[6] = c3vec3f(b->min.x, b->max.y, b->min.z); 83 | out[7] = c3vec3f(b->min.x, b->max.y, b->max.z); 84 | } 85 | 86 | static void 87 | _c3_minmax_distance2( 88 | c3vec3 * in, 89 | int count, 90 | c3vec3 pt, 91 | c3f * min, c3f * max) 92 | { 93 | for (int i = 0; i < count; i++) { 94 | c3f d = c3vec3_length2(c3vec3_sub(in[i], pt)); 95 | if (i == 0 || d < *min) 96 | *min = d; 97 | if (i == 0 || d > *max) 98 | *max = d; 99 | } 100 | } 101 | 102 | /* 103 | * Computes the distance from the 'eye' of the camera, sort by this value 104 | */ 105 | static int 106 | _c3_z_sorter( 107 | const void *_p1, 108 | const void *_p2) 109 | { 110 | c3geometry_p g1 = *(c3geometry_p*)_p1; 111 | c3geometry_p g2 = *(c3geometry_p*)_p2; 112 | c3cam_p cam = &qsort_view->cam; 113 | 114 | c3vec3 v1[8], v2[8]; 115 | c3_bbox_vertices(&g1->wbbox, v1); 116 | c3_bbox_vertices(&g2->wbbox, v2); 117 | 118 | c3f d1min, d1max; 119 | c3f d2min, d2max; 120 | 121 | _c3_minmax_distance2(v1, 8, cam->eye, &d1min, &d1max); 122 | _c3_minmax_distance2(v2, 8, cam->eye, &d2min, &d2max); 123 | 124 | if (d1max > qsort_view->z.max) qsort_view->z.max = d1max; 125 | if (d1min < qsort_view->z.min) qsort_view->z.min = d1min; 126 | if (d2max > qsort_view->z.max) qsort_view->z.max = d2max; 127 | if (d2min < qsort_view->z.min) qsort_view->z.min = d2min; 128 | /* 129 | * make sure transparent items are drawn after everyone else 130 | */ 131 | if (g1->mat.color.n[3] < 1) 132 | d1min -= 100000.0; 133 | if (g2->mat.color.n[3] < 1) 134 | d2min -= 100000.0; 135 | if (g1->type.type == C3_LIGHT_TYPE) 136 | d1min = -200000 + (int)((intptr_t)((c3light_p)g1)->light_id); 137 | if (g2->type.type == C3_LIGHT_TYPE) 138 | d2min = -200000 + (int)((intptr_t)((c3light_p)g2)->light_id); 139 | 140 | return d1min < d2min ? -1 : d1min > d2min ? 1 : 0; 141 | } 142 | 143 | int 144 | c3context_project( 145 | c3context_p c) 146 | { 147 | if (!c->root) 148 | return 0; 149 | int res = 0; 150 | /* 151 | * if the root object is dirty, all the views are also 152 | * dirty since the geometry has changed 153 | */ 154 | if (c->root->dirty) { 155 | for (int ci = 0; ci < c->views.count; ci++) 156 | c->views.e[ci].dirty = 1; 157 | c3mat4 m = identity3D(); 158 | c3object_project(c->root, &m); 159 | res++; 160 | } 161 | 162 | /* 163 | * if the current view is dirty, gather all the geometry 164 | * and Z sort it in a basic way 165 | */ 166 | c3context_view_p v = qsort_view = c3context_view_get(c); 167 | if (v->dirty) { 168 | res++; 169 | 170 | c3geometry_array_p array = &c3context_view_get(c)->projected; 171 | c3geometry_array_clear(array); 172 | c3object_get_geometry(c->root, array); 173 | 174 | v->z.min = 1000000000; 175 | v->z.max = -1000000000; 176 | 177 | qsort(v->projected.e, 178 | v->projected.count, sizeof(v->projected.e[0]), 179 | _c3_z_sorter); 180 | v->z.min = sqrt(v->z.min) * 0.8f; 181 | v->z.max = sqrt(v->z.max); 182 | 183 | /* 184 | * Recalculate the perspective view using the new Z values 185 | */ 186 | if (v->cam.fov > 0) { 187 | c3cam_update_matrix(&v->cam); 188 | v->projection = perspective3D( 189 | v->cam.fov, 190 | v->size.x / v->size.y, 191 | v->z.min, v->z.max); 192 | } 193 | v->dirty = 0; 194 | } 195 | return res; 196 | } 197 | 198 | void 199 | c3context_draw( 200 | c3context_p c) 201 | { 202 | c3context_project(c); 203 | 204 | c3context_view_p v = c3context_view_get(c); 205 | 206 | C3_DRIVER(c, context_view_draw, v); 207 | 208 | c3geometry_array_p array = &v->projected; 209 | for (int gi = 0; gi < array->count; gi++) { 210 | c3geometry_p g = array->e[gi]; 211 | c3geometry_draw(g); 212 | } 213 | } 214 | 215 | -------------------------------------------------------------------------------- /src/c3context.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3context.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3CONTEXT_H___ 24 | #define __C3CONTEXT_H___ 25 | 26 | #include "c3algebra.h" 27 | #include "c3geometry.h" 28 | #include "c3pixels.h" 29 | #include "c3program.h" 30 | #include "c3camera.h" 31 | 32 | enum { 33 | C3_CONTEXT_VIEW_NONE = 0, 34 | C3_CONTEXT_VIEW_EYE, 35 | C3_CONTEXT_VIEW_LIGHT 36 | }; 37 | 38 | typedef struct c3context_view_t { 39 | int type : 4, // C3_CONTEXT_VIEW_EYE... 40 | dirty : 1, 41 | index : 4; // index in context array 42 | c3apiobject_t bid; // buffer id (fbo, texture...) 43 | c3vec2 size; // in pixels. for fbo/textures/window 44 | c3cam_t cam; 45 | c3mat4 projection; // projection matrix 46 | 47 | c3geometry_array_t projected; 48 | struct { 49 | c3f min, max; 50 | } z; 51 | } c3context_view_t, *c3context_view_p; 52 | 53 | DECLARE_C_ARRAY(c3context_view_t, c3context_view_array, 4); 54 | 55 | struct c3font_manager_t; 56 | 57 | //! c3context_t is a container for a 'scene' to be drawn 58 | /*! 59 | * A c3context_t holds a root object, a list of already cached projected 60 | * version of the geometry, and a driver that can be customized to draw it. 61 | * 62 | * This is a wrapper around a "top level object", the list of projected 63 | * geometries is kept, purged and resorted if the root object becomes 64 | * dirty 65 | */ 66 | typedef struct c3context_t { 67 | int current; 68 | c3context_view_array_t views; 69 | 70 | struct c3object_t * root; // root object 71 | 72 | c3pixels_array_t pixels; // pixels, textures... 73 | c3program_array_t programs; // fragment, vertex, geometry shaders 74 | 75 | const struct c3driver_context_t ** driver; 76 | 77 | struct c3font_manager_t * fonts; 78 | } c3context_t, *c3context_p; 79 | 80 | //! Allocates a new context of size w=width, h=height 81 | c3context_p 82 | c3context_new( 83 | int w, 84 | int h); 85 | 86 | //! Initializes a new context 'c' of size w=width, h=height 87 | c3context_p 88 | c3context_init( 89 | c3context_p c, 90 | int w, 91 | int h); 92 | 93 | //! Disposes the context, and everything underneath 94 | void 95 | c3context_dispose( 96 | c3context_p c); 97 | 98 | //! Reproject geometry for dirty objects 99 | int 100 | c3context_project( 101 | c3context_p c); 102 | //! Draws the context 103 | void 104 | c3context_draw( 105 | c3context_p c); 106 | 107 | IMPLEMENT_C_ARRAY(c3context_view_array); 108 | 109 | /* 110 | * Set and get the current view, this is done 111 | * before projecting and drawing 112 | */ 113 | static inline c3context_view_p 114 | c3context_view_get( 115 | c3context_p c ) 116 | { 117 | return &c->views.e[c->current]; 118 | } 119 | 120 | static inline c3context_view_p 121 | c3context_view_get_at( 122 | c3context_p c, 123 | int view) 124 | { 125 | if (view < c->views.count) 126 | return &c->views.e[view]; 127 | return NULL; 128 | } 129 | 130 | static inline void 131 | c3context_view_set( 132 | c3context_p c, 133 | int view) 134 | { 135 | if (view < c->views.count) 136 | c->current = view; 137 | } 138 | 139 | #endif /* __C3CONTEXT_H___ */ 140 | -------------------------------------------------------------------------------- /src/c3cube.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3cube.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include "c3geometry.h" 25 | #include "c3cube.h" 26 | 27 | 28 | c3geometry_p 29 | c3cube_add( 30 | c3geometry_p g, 31 | c3vec3 position, 32 | c3vec3 size, 33 | uint16_t flags, 34 | struct c3object_t * parent) 35 | { 36 | c3vec3 c = c3vec3_add(position, 37 | flags & C3CUBE_CENTER ? 38 | c3vec3f(-size.x/2,-size.y/2, size.z/2) : 39 | c3vec3f(0,0,0)); 40 | c3vec3 v[8] = { 41 | c, c3vec3_add(c, c3vec3f(size.x, 0, 0)), 42 | c3vec3_add(c, c3vec3f(size.x, size.y, 0)), c3vec3_add(c, c3vec3f(0, size.y, 0)), 43 | 44 | c3vec3_add(c, c3vec3f(0, 0, -size.z)), c3vec3_add(c, c3vec3f(size.x, 0, -size.z)), 45 | c3vec3_add(c, c3vec3f(size.x, size.y, -size.z)), c3vec3_add(c, c3vec3f(0, size.y, -size.z)), 46 | }; 47 | 48 | static const struct { 49 | c3f normal[3]; 50 | uint8_t i[6]; 51 | } face[6] = { 52 | { { 0, 0, 1 }, { 0, 1, 2, 2, 3, 0 }}, 53 | { { 0, -1, 0 }, { 0, 4, 5, 5, 1, 0 }}, 54 | { { 1, 0, 0 }, { 1, 5, 6, 6, 2, 1 }}, 55 | { { 0, 1, 0 }, { 2, 6, 7, 7, 3, 2 }}, 56 | { { -1, 0, 0 }, { 3, 7, 4, 4, 0, 3 }}, 57 | { { 0, 0, -1 }, { 4, 7, 6, 6, 5, 4 }}, 58 | }; 59 | // texture is Y flipped by default 60 | static const c3f tex[12] = { 61 | 0,1, 1,1, 1,0, 1,0, 0,0, 0,1 62 | }; 63 | 64 | for (int f = 0; f < 6; f++) if (flags & (1 << f)) { 65 | for (int i = 0; i < 6; i++) { 66 | c3vertex_array_add(&g->vertice, v[(int)face[f].i[i]]); 67 | c3vertex_array_add(&g->normals, *((c3vec3*)face[f].normal)); 68 | } 69 | c3tex_array_insert(&g->textures, g->textures.count, (c3vec2*)tex, 6); 70 | } 71 | g->dirty = 1; 72 | 73 | return g; 74 | } 75 | 76 | c3geometry_p 77 | c3cube_new( 78 | c3vec3 position, 79 | c3vec3 size, 80 | uint16_t flags, 81 | struct c3object_t * parent) 82 | { 83 | c3geometry_p g = c3geometry_new(c3geometry_type(C3_TRIANGLE_TYPE, 0), parent); 84 | 85 | c3cube_add(g, position, size, flags, parent); 86 | 87 | return g; 88 | } 89 | -------------------------------------------------------------------------------- /src/c3cube.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3cube.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3CUBE_H___ 24 | #define __C3CUBE_H___ 25 | 26 | #include "c3algebra.h" 27 | 28 | /* order of faces, and flags */ 29 | enum { 30 | C3CUBE_TOP_BIT = 0, 31 | C3CUBE_FRONT_BIT, 32 | C3CUBE_RIGHT_BIT, 33 | C3CUBE_BACK_BIT, 34 | C3CUBE_LEFT_BIT, 35 | C3CUBE_BOTTOM_BIT, 36 | 37 | C3CUBE_CENTER_BIT, 38 | 39 | C3CUBE_CENTER = (1 << C3CUBE_CENTER_BIT), 40 | C3CUBE_FACE_ALL = 0x3f, 41 | }; 42 | 43 | c3geometry_p 44 | c3cube_new( 45 | c3vec3 position, 46 | c3vec3 size, 47 | uint16_t flags, 48 | struct c3object_t * parent); 49 | 50 | c3geometry_p 51 | c3cube_add( 52 | c3geometry_p g, 53 | c3vec3 position, 54 | c3vec3 size, 55 | uint16_t flags, 56 | struct c3object_t * parent); 57 | 58 | #endif /* __C3CUBE_H___ */ 59 | -------------------------------------------------------------------------------- /src/c3driver.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3driver.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3DRIVER_H___ 24 | #define __C3DRIVER_H___ 25 | 26 | #define C3_DRIVER_CALL(__o, __callback, __args...) { \ 27 | if ((__o) && (__o)->driver) \ 28 | for (int _di = 0; (__o)->driver[_di]; _di++) \ 29 | if ((__o)->driver[_di]->__callback) { \ 30 | (__o)->driver[_di]->__callback(__o, (__o)->driver[_di], ##__args); \ 31 | break; \ 32 | } \ 33 | } 34 | #define C3_DRIVER(__o, __callback, __args...) \ 35 | C3_DRIVER_CALL(__o, __callback, ##__args) 36 | #define C3_DRIVER_INHERITED(__o, __driver, __callback, __args...) { \ 37 | if ((__o) && (__o)->driver) \ 38 | for (int _di = 0; (__o)->driver[_di]; _di++) \ 39 | if ((__o)->driver[_di] == __driver && (__o)->driver[_di+1]) { \ 40 | (__o)->driver[_di+1]->__callback(__o, (__o)->driver[_di+1], ##__args); \ 41 | break; \ 42 | } \ 43 | } 44 | #endif /* __C3DRIVER_H___ */ 45 | -------------------------------------------------------------------------------- /src/c3driver_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3driver_context.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3DRIVER_CONTEXT_H___ 24 | #define __C3DRIVER_CONTEXT_H___ 25 | 26 | #include "c3driver.h" 27 | 28 | struct c3context_t; 29 | struct c3driver_context_t; 30 | struct c3geometry_t; 31 | struct c3context_view_t; 32 | 33 | typedef struct c3driver_context_t { 34 | /* 35 | * Called when a geometry projection had changed in world view 36 | * can also be used to prepare resources like textures and so on 37 | */ 38 | void (*geometry_project)( 39 | struct c3context_t * c, 40 | const struct c3driver_context_t *d, 41 | struct c3geometry_t * g, 42 | union c3mat4 * mat); 43 | /* 44 | * Called to draw a geometry 45 | */ 46 | void (*geometry_draw)( 47 | struct c3context_t * c, 48 | const struct c3driver_context_t *d, 49 | struct c3geometry_t * g); 50 | 51 | /* 52 | * Called when starting to draw a context view(point) 53 | */ 54 | void (*context_view_draw)( 55 | struct c3context_t * c, 56 | const struct c3driver_context_t *d, 57 | struct c3context_view_t * ctx); 58 | 59 | /* 60 | * called when a geometry is disposed of, let the application 61 | * delete resources like textures etc 62 | */ 63 | void (*geometry_dispose)( 64 | struct c3context_t * c, 65 | const struct c3driver_context_t *d, 66 | struct c3geometry_t * g); 67 | } c3driver_context_t, *c3driver_context_p; 68 | 69 | #endif /* __C3DRIVER_CONTEXT_H___ */ 70 | -------------------------------------------------------------------------------- /src/c3driver_geometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3driver_geometry.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3DRIVER_GEOMETRY_H___ 24 | #define __C3DRIVER_GEOMETRY_H___ 25 | 26 | #include "c3driver.h" 27 | 28 | struct c3geometry_t; 29 | 30 | typedef struct c3driver_geometry_t { 31 | void (*dispose)( 32 | struct c3geometry_t * geometry, 33 | const struct c3driver_geometry_t *d); 34 | void (*project)( 35 | struct c3geometry_t * geometry, 36 | const struct c3driver_geometry_t *d, 37 | union c3mat4 * mat); 38 | void (*draw)( 39 | struct c3geometry_t * geometry, 40 | const struct c3driver_geometry_t *d); 41 | } c3driver_geometry_t, *c3driver_geometry_p; 42 | 43 | 44 | #endif /* __C3DRIVER_GEOMETRY_H___ */ 45 | -------------------------------------------------------------------------------- /src/c3driver_object.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3driver_object.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3DRIVER_OBJECT_H___ 24 | #define __C3DRIVER_OBJECT_H___ 25 | 26 | #include "c3driver.h" 27 | 28 | struct c3object_t; 29 | struct c3geometry_array_t; 30 | union c3mat4; 31 | 32 | typedef struct c3driver_object_t { 33 | /* 34 | * Delete any object related to this object, geometry etc 35 | * The object will still exist, just empty 36 | */ 37 | void (*clear)( 38 | struct c3object_t * object, 39 | const struct c3driver_object_t * d); 40 | /* 41 | * Dispose of the remaining memory for an object, detaches it 42 | * and frees remaining traces of it 43 | */ 44 | void (*dispose)( 45 | struct c3object_t * object, 46 | const struct c3driver_object_t * d); 47 | /* 48 | * Adds sub objects geometry and self geometry to array 'out' 49 | */ 50 | void (*get_geometry)( 51 | struct c3object_t * object, 52 | const struct c3driver_object_t * d, 53 | struct c3geometry_array_t * out); 54 | /* 55 | * Reproject geometry along matrix 'mat', applies our own 56 | * transform and call down the chain for sub-objects 57 | */ 58 | void (*project)( 59 | struct c3object_t * object, 60 | const struct c3driver_object_t * d, 61 | union c3mat4 * mat); 62 | } c3driver_object_t, *c3driver_object_p; 63 | 64 | 65 | #endif /* __C3DRIVER_OBJECT_H___ */ 66 | -------------------------------------------------------------------------------- /src/c3geometry.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3geometry.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include "c3object.h" 26 | #include "c3context.h" 27 | #include "c3driver_geometry.h" 28 | #include "c3driver_context.h" 29 | 30 | static void 31 | _c3geometry_dispose( 32 | c3geometry_p g, 33 | const struct c3driver_geometry_t *d) 34 | { 35 | /* 36 | * If we're still attached to an object, detach 37 | */ 38 | if (g->object) { 39 | for (int oi = 0; oi < g->object->geometry.count; oi++) 40 | if (g->object->geometry.e[oi] == g) { 41 | c3geometry_array_delete(&g->object->geometry, oi, 1); 42 | c3object_set_dirty(g->object, true); 43 | break; 44 | } 45 | g->object = NULL; 46 | } 47 | /* let the context driver have a chance to clear it's own stuff */ 48 | if (g->object && g->object->context) 49 | C3_DRIVER(g->object->context, geometry_dispose, g); 50 | str_free(g->name); 51 | c3vertex_array_free(&g->vertice); 52 | c3tex_array_free(&g->textures); 53 | c3colorf_array_free(&g->colorf); 54 | free(g); 55 | // C3_DRIVER_INHERITED(g, d, dispose); 56 | } 57 | 58 | static void 59 | _c3geometry_project( 60 | c3geometry_p g, 61 | const struct c3driver_geometry_t *d, 62 | c3mat4p m) 63 | { 64 | /* make sure there are actual elements in the array 65 | * if it had been purged, the element count might remain 66 | * but the array size is zero 67 | */ 68 | if (g->vertice.count && g->vertice.e) { 69 | for (int vi = 0; vi < g->vertice.count; vi++) { 70 | c3vec3 v = g->vertice.e[vi]; 71 | if (vi == 0) 72 | g->bbox.min = g->bbox.max = v; 73 | else { 74 | g->bbox.min = c3vec3_min(g->bbox.min, v); 75 | g->bbox.max = c3vec3_max(g->bbox.max, v); 76 | } 77 | } 78 | } 79 | /* else -- do not clear bbox on purged arrays */ 80 | 81 | g->wbbox.max = c3mat4_mulv3(m, g->bbox.max); 82 | g->wbbox.min = c3mat4_mulv3(m, g->bbox.min); 83 | 84 | if (g->object && g->object->context) 85 | C3_DRIVER(g->object->context, geometry_project, g, m); 86 | g->dirty = 0; 87 | // C3_DRIVER_INHERITED(g, d, project); 88 | } 89 | 90 | static void 91 | _c3geometry_draw( 92 | c3geometry_p g, 93 | const struct c3driver_geometry_t *d) 94 | { 95 | if (g->object && g->object->context) 96 | C3_DRIVER(g->object->context, geometry_draw, g); 97 | // C3_DRIVER_INHERITED(g, d, draw); 98 | } 99 | 100 | const c3driver_geometry_t c3geometry_driver = { 101 | .dispose = _c3geometry_dispose, 102 | .project = _c3geometry_project, 103 | .draw = _c3geometry_draw, 104 | }; 105 | 106 | c3geometry_p 107 | c3geometry_new( 108 | c3geometry_type_t type, 109 | c3object_p o /* = NULL */) 110 | { 111 | c3geometry_p res = malloc(sizeof(c3geometry_t)); 112 | return c3geometry_init(res, type, o); 113 | } 114 | 115 | c3geometry_p 116 | c3geometry_init( 117 | c3geometry_p g, 118 | c3geometry_type_t type, 119 | struct c3object_t * o /* = NULL */) 120 | { 121 | memset(g, 0, sizeof(*g)); 122 | static const c3driver_geometry_t * list[] = { 123 | &c3geometry_driver, NULL, 124 | }; 125 | g->driver = list; 126 | g->type = type; 127 | g->dirty = 1; 128 | if (o) 129 | c3object_add_geometry(o, g); 130 | return g; 131 | } 132 | 133 | c3driver_geometry_p 134 | c3geometry_get_custom( 135 | c3geometry_p g ) 136 | { 137 | if (g->custom) 138 | return (c3driver_geometry_p)g->driver[0]; 139 | int cnt = 0; 140 | for (int di = 0; g->driver[di]; di++) 141 | cnt++; 142 | c3driver_geometry_p * newd = malloc(sizeof(c3driver_geometry_p) * (cnt + 2)); 143 | memcpy(&newd[1], g->driver, (cnt + 1) * sizeof(c3driver_geometry_p)); 144 | newd[0] = malloc(sizeof(c3driver_geometry_t)); 145 | memset(newd[0], 0, sizeof(c3driver_geometry_t)); 146 | g->custom = 1; 147 | g->driver = (typeof(g->driver))newd; 148 | return newd[0]; 149 | } 150 | 151 | void 152 | c3geometry_dispose( 153 | c3geometry_p g) 154 | { 155 | C3_DRIVER(g, dispose); 156 | } 157 | 158 | void 159 | c3geometry_project( 160 | c3geometry_p g, 161 | c3mat4p m) 162 | { 163 | if (!g->dirty) 164 | return; 165 | C3_DRIVER(g, project, m); 166 | } 167 | 168 | void 169 | c3geometry_draw( 170 | c3geometry_p g ) 171 | { 172 | C3_DRIVER(g, draw); 173 | } 174 | 175 | void 176 | c3geometry_factor( 177 | c3geometry_p g, 178 | c3f tolerance, 179 | c3f normaltolerance) 180 | { 181 | printf("%s has %d/%d/%d vertices/normals/tex and %d indexes\n", __func__, 182 | g->vertice.count, g->normals.count, g->textures.count, 183 | g->indices.count); 184 | 185 | c3f tolerance2 = tolerance * tolerance; 186 | 187 | int in_index = g->indices.count; 188 | int vcount = in_index ? in_index : g->vertice.count; 189 | int input = 0; 190 | int output = 0; 191 | g->indices.count = 0; 192 | while (input < vcount) { 193 | int current = in_index ? g->indices.e[input] : input; 194 | c3vec3 v = g->vertice.e[current]; 195 | c3vec3 n = g->normals.count ? g->normals.e[current] : c3vec3f(0,0,0); 196 | c3vec3 np = c3vec3_polar(n); // normal in polar coord 197 | 198 | int oi = -1; 199 | for (int ci = 0; ci < output && oi == -1; ci++) 200 | if (c3vec3_length2(c3vec3_sub(g->vertice.e[ci], v)) < tolerance2) { 201 | if (g->normals.count) { 202 | c3vec3 nc = g->normals.e[ci]; 203 | c3vec3 pc = c3vec3_polar(nc); 204 | 205 | c3vec3 d = c3vec3_sub(np, pc); 206 | while (d.n[0] <= -M_PI) d.n[0] += (2*M_PI); 207 | while (d.n[1] <= -M_PI) d.n[1] += (2*M_PI); 208 | 209 | if (fabs(d.n[0]) < normaltolerance && 210 | fabs(d.n[1]) < normaltolerance) { 211 | oi = ci; 212 | // replace the compared normal with the 'merged' one 213 | // that should hopefully trim it to the right direction 214 | // somehow. Not perfect obviously 215 | g->normals.e[ci] = c3vec3_add(n, nc); 216 | } 217 | } else 218 | oi = ci; 219 | } 220 | if (oi == -1) { 221 | oi = output; 222 | g->vertice.e[output] = g->vertice.e[current]; 223 | if (g->textures.count) 224 | g->textures.e[output] = g->textures.e[current]; 225 | if (g->normals.count) 226 | g->normals.e[output] = n; 227 | if (g->colorf.count) 228 | g->colorf.e[output] = g->colorf.e[current]; 229 | output++; 230 | } 231 | c3indices_array_add(&g->indices, oi); 232 | input++; 233 | } 234 | g->vertice.count = output; 235 | c3vertex_array_realloc(&g->vertice, output); 236 | if (g->textures.count) { 237 | g->textures.count = output; 238 | c3tex_array_realloc(&g->textures, output); 239 | } 240 | if (g->normals.count) { 241 | g->normals.count = output; 242 | c3vertex_array_realloc(&g->normals, output); 243 | for (int ni = 0; ni < output; ni++) 244 | g->normals.e[ni] = c3vec3_normalize(g->normals.e[ni]); 245 | } 246 | if (g->colorf.count) { 247 | g->colorf.count = output; 248 | c3colorf_array_realloc(&g->colorf, output); 249 | } 250 | c3geometry_set_dirty(g, 1); 251 | 252 | printf("%s converted to %d vertices and %d indexes\n", __func__, 253 | g->vertice.count, g->indices.count); 254 | } 255 | 256 | void 257 | c3geometry_set_dirty( 258 | c3geometry_p g, 259 | int dirty ) 260 | { 261 | g->dirty = dirty; 262 | if (dirty && g->object) 263 | c3object_set_dirty(g->object, 1); 264 | } 265 | -------------------------------------------------------------------------------- /src/c3geometry.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3geometry.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | /* 23 | * c3geometry is a structure containing one set of vertices and various 24 | * bits related to it. Ultimately it contains a pre-cached projected 25 | * version of the vertices that the drawing code can use directly. 26 | * c3geometry is aways attached to a c3object as a parent. 27 | */ 28 | 29 | #ifndef __C3GEOMETRY_H___ 30 | #define __C3GEOMETRY_H___ 31 | 32 | #include "c3types.h" 33 | #include "c_utils.h" 34 | 35 | 36 | struct c3object_t; 37 | struct c3pixels_t; 38 | struct c3program_t; 39 | 40 | /* 41 | * Allow per-array storage of an extra buffer object 42 | * if 'mutable' is not set (default), the array can be clear()ed after 43 | * the buffer is bound. 44 | * If the array is mutable, setting the 'dirty' flag will signal 45 | * the rendering layer that it needs to update the buffer object 46 | */ 47 | typedef struct c3geometry_buffer_t { 48 | c3apiobject_t bid; // buffer object 49 | void * refCon; // reference constant for application use 50 | int mutable : 1, dirty : 1; 51 | } c3geometry_buffer_t, * c3geometry_buffer_p; 52 | 53 | DECLARE_C_ARRAY(c3vertex_t, c3vertex_array, 16, c3geometry_buffer_t buffer); 54 | DECLARE_C_ARRAY(c3tex_t, c3tex_array, 16, c3geometry_buffer_t buffer); 55 | DECLARE_C_ARRAY(c3colorf_t, c3colorf_array, 16, c3geometry_buffer_t buffer); 56 | DECLARE_C_ARRAY(c3index_t, c3indices_array, 16, c3geometry_buffer_t buffer); 57 | 58 | //! Geometry material. 59 | typedef struct c3material_t { 60 | c3colorf_t color; 61 | c3f shininess; 62 | struct c3pixels_t * texture; 63 | struct c3program_t * program; 64 | struct { 65 | uint32_t src, dst; 66 | } blend; 67 | } c3material_t; 68 | 69 | #define C3_TYPE(_a,_b,_c,_d) \ 70 | (((uint32_t)(_a)<<24)|((uint32_t)(_b)<<16)|((uint32_t)(_c)<<8)|(_d)) 71 | 72 | //! Generic geometry type 73 | enum { 74 | C3_RAW_TYPE = C3_TYPE('r','a','w','g'), 75 | C3_TRIANGLE_TYPE = C3_TYPE('t','r','i','a'), 76 | }; 77 | 78 | /*! 79 | * geometry type. 80 | * The type is used as non-opengl description of what the geometry 81 | * contains, like "texture", and the subtype can be used to store the 82 | * real format of the vertices. like GL_LINES etc 83 | */ 84 | typedef struct c3geometry_type_t { 85 | uint32_t type; // C3_RAW_TYPE etc 86 | c3apiobject_t subtype; // GL_LINES etc 87 | } c3geometry_type_t; 88 | 89 | /*! 90 | * Geometry object. Describes a set of vertices, texture coordinates, 91 | * normals, colors and material 92 | * The projection is not set here, a geometry is always attached to a 93 | * c3object that has the projection 94 | */ 95 | typedef struct c3geometry_t { 96 | c3geometry_type_t type; // geometry type 97 | int dirty : 1, 98 | debug : 1, 99 | custom : 1, // has a custom driver 100 | hidden : 8; // hidden from context_view, bitfield 101 | str_p name; // optional 102 | c3apiobject_t bid; // buffer id for opengl 103 | 104 | c3material_t mat; 105 | struct c3object_t * object; // parent object 106 | const struct c3driver_geometry_t ** driver; 107 | 108 | c3bbox_t bbox; // bounding box 109 | c3bbox_t wbbox; // world aligned bounding box 110 | c3vertex_array_t vertice; 111 | c3tex_array_t textures; // optional: texture coordinates 112 | c3vertex_array_t normals; // optional: vertex normals 113 | c3colorf_array_t colorf; // optional: vertex colors 114 | c3indices_array_t indices; // optional: vertex indices 115 | 116 | /* 117 | * Some shared attributes 118 | */ 119 | union { 120 | struct { 121 | float width; 122 | } line; 123 | }; 124 | } c3geometry_t, *c3geometry_p; 125 | 126 | DECLARE_C_ARRAY(c3geometry_p, c3geometry_array, 4); 127 | 128 | //! Allocates a new geometry, init it, and attached it to parent 'o' (optional) 129 | c3geometry_p 130 | c3geometry_new( 131 | c3geometry_type_t type, 132 | struct c3object_t * o /* = NULL */); 133 | //! Init an existing new geometry, and attached it to parent 'o' (optional) 134 | c3geometry_p 135 | c3geometry_init( 136 | c3geometry_p g, 137 | c3geometry_type_t type, 138 | struct c3object_t * o /* = NULL */); 139 | //! Disposes (via the driver interface) the geometry 140 | void 141 | c3geometry_dispose( 142 | c3geometry_p g); 143 | 144 | //! Prepares a geometry. 145 | /*! 146 | * The project phase is called only when the container object is 'dirty' 147 | * for example if it's projection has changed. 148 | * The project call is responsible for reprojecting the geometry and that 149 | * sort of things 150 | */ 151 | void 152 | c3geometry_project( 153 | c3geometry_p g, 154 | c3mat4p m); 155 | 156 | //! Draw the geometry 157 | /* 158 | * Called when drawing the context. Typicaly this calls the geometry 159 | * driver, which in turn will call the 'context' draw method, and the 160 | * application to draw this particular geometry 161 | */ 162 | void 163 | c3geometry_draw( 164 | c3geometry_p g ); 165 | 166 | //! Sets or clear geometry dirty bit 167 | /* 168 | * This will dirty parent objects if set to 1 169 | */ 170 | void 171 | c3geometry_set_dirty( 172 | c3geometry_p g, 173 | int dirty ); 174 | 175 | /* 176 | * if not present, create an index array, and collapses 177 | * the vertex array by removing vertices that are within 178 | * 'tolerance' (as a distance between vertices considered equals). 179 | * If the normals exists, they are also compared 180 | * to normaltolerance (in radian) and if both position and normals 181 | * are within tolerance, the vertices are collapsed and the normals 182 | * are averaged. 183 | * This code allows smooth rendering of STL files generated by 184 | * CAD programs that generate only triangle normals. 185 | */ 186 | void 187 | c3geometry_factor( 188 | c3geometry_p g, 189 | c3f tolerance, 190 | c3f normaltolerance); 191 | 192 | //! allocate (if not there) and return a custom driver for this geometry 193 | /*! 194 | * Geometries come with a default, read only driver stack.. It is a constant 195 | * global to save memory for each of the 'generic' object. 196 | * This call will duplicate that stack and allocate (if not there) a read/write 197 | * empty driver that the application can use to put their own, per object, 198 | * callback. For example you can add your own project() or draw() function 199 | * and have it called first 200 | */ 201 | struct c3driver_geometry_t * 202 | c3geometry_get_custom( 203 | c3geometry_p g ); 204 | 205 | IMPLEMENT_C_ARRAY(c3geometry_array); 206 | IMPLEMENT_C_ARRAY(c3vertex_array); 207 | IMPLEMENT_C_ARRAY(c3tex_array); 208 | IMPLEMENT_C_ARRAY(c3colorf_array); 209 | IMPLEMENT_C_ARRAY(c3indices_array); 210 | 211 | static inline c3geometry_type_t 212 | c3geometry_type(uint32_t type, int subtype) 213 | { 214 | c3geometry_type_t r;// = { .type = type, .subtype = subtype }; // older gcc <4.6 doesn't like this 215 | r.type = type; r.subtype = C3APIO(subtype); 216 | return r; 217 | } 218 | 219 | #endif /* __C3GEOMETRY_H___ */ 220 | -------------------------------------------------------------------------------- /src/c3light.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3light.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include 25 | #include "c3light.h" 26 | 27 | c3light_p 28 | c3light_new( 29 | struct c3object_t * o /* = NULL */) 30 | { 31 | c3light_p res = malloc(sizeof(*res)); 32 | return c3light_init(res, o); 33 | } 34 | 35 | c3light_p 36 | c3light_init( 37 | c3light_p l, 38 | struct c3object_t * o /* = NULL */) 39 | { 40 | memset(l, 0, sizeof(*l)); 41 | c3geometry_init(&l->geometry, 42 | c3geometry_type(C3_LIGHT_TYPE, 0), 43 | o); 44 | 45 | return l; 46 | } 47 | -------------------------------------------------------------------------------- /src/c3light.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3light.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3LIGHT_H___ 24 | #define __C3LIGHT_H___ 25 | 26 | #include "c3geometry.h" 27 | 28 | enum { 29 | C3_LIGHT_TYPE = C3_TYPE('l','i','g','h'), 30 | }; 31 | 32 | typedef struct c3light_t { 33 | c3geometry_t geometry; 34 | c3apiobject_t light_id; 35 | int context_view_index; 36 | c3vec4 position; 37 | c3vec3 direction; 38 | c3f fov; 39 | struct { 40 | c3colorf_t ambiant; 41 | c3colorf_t specular; 42 | } color; 43 | } c3light_t, *c3light_p; 44 | 45 | c3light_p 46 | c3light_new( 47 | struct c3object_t * o /* = NULL */); 48 | 49 | c3light_p 50 | c3light_init( 51 | c3light_p l, 52 | struct c3object_t * o /* = NULL */); 53 | 54 | #endif /* __C3LIGHT_H___ */ 55 | -------------------------------------------------------------------------------- /src/c3lines.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3lines.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c3object.h" 24 | #include "c3context.h" 25 | #include "c3driver_geometry.h" 26 | #include "c3lines.h" 27 | 28 | 29 | void 30 | c3lines_prepare( 31 | c3vertex_p vertices, // points A,B pairs 32 | size_t count, 33 | c3vertex_array_p v, // triangles 34 | c3tex_array_p tex, 35 | c3f lineWidth, 36 | c3mat4p m) 37 | { 38 | c3tex_array_clear(tex); 39 | c3vertex_array_clear(v); 40 | for (int l = 0; l < count; l += 2) { 41 | c3vec3 a = c3mat4_mulv3(m, vertices[l]); 42 | c3vec3 b = c3mat4_mulv3(m, vertices[l+1]); 43 | 44 | c3vec3 e = c3vec3_mulf(c3vec3_normalize(c3vec3_sub(b, a)), lineWidth); 45 | 46 | c3vec3 N = c3vec3f(-e.y, e.x, 0); 47 | c3vec3 S = c3vec3_minus(N); 48 | c3vec3 NE = c3vec3_add(N, e); 49 | c3vec3 NW = c3vec3_sub(N, e); 50 | c3vec3 SW = c3vec3_minus(NE); 51 | c3vec3 SE = c3vec3_minus(NW); 52 | #if 0 53 | c3vertex_array_add(v, c3vec3_add(a, SW)); 54 | c3vertex_array_add(v, c3vec3_add(a, NW)); 55 | c3vertex_array_add(v, c3vec3_add(a, S)); 56 | c3vertex_array_add(v, c3vec3_add(a, N)); 57 | c3vertex_array_add(v, c3vec3_add(b, S)); 58 | c3vertex_array_add(v, c3vec3_add(b, N)); 59 | c3vertex_array_add(v, c3vec3_add(b, SE)); 60 | c3vertex_array_add(v, c3vec3_add(b, NE)); 61 | #endif 62 | 63 | const float ts = 1; 64 | 65 | c3vertex_array_add(v, c3vec3_add(a, SW)); 66 | c3vertex_array_add(v, c3vec3_add(a, S)); 67 | c3vertex_array_add(v, c3vec3_add(a, NW)); 68 | c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 0 )); 69 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 70 | c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); 71 | 72 | c3vertex_array_add(v, c3vec3_add(a, S)); 73 | c3vertex_array_add(v, c3vec3_add(a, N)); 74 | c3vertex_array_add(v, c3vec3_add(a, NW)); 75 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 76 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 77 | c3tex_array_add(tex, c3vec2f(ts * 0 , ts * 1 )); 78 | 79 | c3vertex_array_add(v, c3vec3_add(a, N)); 80 | c3vertex_array_add(v, c3vec3_add(b, S)); 81 | c3vertex_array_add(v, c3vec3_add(b, N)); 82 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 83 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 84 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 85 | 86 | c3vertex_array_add(v, c3vec3_add(a, N)); 87 | c3vertex_array_add(v, c3vec3_add(a, S)); 88 | c3vertex_array_add(v, c3vec3_add(b, S)); 89 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 90 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 91 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 92 | 93 | c3vertex_array_add(v, c3vec3_add(b, N)); 94 | c3vertex_array_add(v, c3vec3_add(b, S)); 95 | c3vertex_array_add(v, c3vec3_add(b, SE)); 96 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 97 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 0 )); 98 | c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); 99 | 100 | c3vertex_array_add(v, c3vec3_add(b, N)); 101 | c3vertex_array_add(v, c3vec3_add(b, SE)); 102 | c3vertex_array_add(v, c3vec3_add(b, NE)); 103 | c3tex_array_add(tex, c3vec2f(ts * 0.5, ts * 1 )); 104 | c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 0 )); 105 | c3tex_array_add(tex, c3vec2f(ts * 1 , ts * 1 )); 106 | 107 | } 108 | } 109 | 110 | void 111 | c3lines_init( 112 | c3geometry_p g, 113 | c3vertex_p vertices, // points A,B pairs 114 | size_t count, 115 | c3f lineWidth) 116 | { 117 | c3mat4 i = identity3D(); 118 | c3lines_prepare(vertices, count, &g->vertice, &g->textures, lineWidth, &i); 119 | g->type.type = C3_LINES_TYPE; 120 | } 121 | 122 | #if 0 123 | static void 124 | _c3lines_project( 125 | c3geometry_p g, 126 | const struct c3driver_geometry_t *d, 127 | c3mat4p m) 128 | 129 | const c3driver_geometry_t c3lines_driver = { 130 | .project = _c3lines_project, 131 | }; 132 | 133 | const c3driver_geometry_t c3geometry_driver; 134 | 135 | c3geometry_set_lines( 136 | c3f lineWidth) 137 | { 138 | static const c3driver_geometry_t * list[] = { 139 | &c3lines_driver, &c3geometry_driver, NULL, 140 | }; 141 | } 142 | #endif 143 | -------------------------------------------------------------------------------- /src/c3lines.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3lines.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3LINES_H___ 24 | #define __C3LINES_H___ 25 | 26 | #include "c3geometry.h" 27 | 28 | enum { 29 | C3_LINES_TYPE = C3_TYPE('l','i','n','e'), 30 | }; 31 | /* 32 | * Takes an array of points A,B and split it into 'fat' lines around 33 | * lineWidth, generates an array of triangles and an array of corresponding 34 | * texture coordinates. Can also do a projection at the same time 35 | * TODO: Add array indices 36 | */ 37 | void 38 | c3lines_prepare( 39 | c3vertex_p vertices, // points A,B pairs 40 | size_t count, 41 | c3vertex_array_p v, // triangles 42 | c3tex_array_p tex, 43 | c3f lineWidth, 44 | c3mat4p m); 45 | 46 | void 47 | c3lines_init( 48 | c3geometry_p g, 49 | c3vertex_p vertices, // points A,B pairs 50 | size_t count, 51 | c3f lineWidth); 52 | 53 | #endif /* __C3LINES_H___ */ 54 | -------------------------------------------------------------------------------- /src/c3model_obj.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3model_obj.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include "c3algebra.h" 25 | #include "c3geometry.h" 26 | #include "c3object.h" 27 | #include "c3model_obj.h" 28 | 29 | struct c3object_t * 30 | c3obj_load( 31 | const char * filename, 32 | struct c3object_t * parent) 33 | { 34 | FILE *f = fopen(filename, "r"); 35 | if (!f) { 36 | perror(filename); 37 | return NULL; 38 | } 39 | 40 | c3object_p o = c3object_new(parent); 41 | c3geometry_p store = c3geometry_new(c3geometry_type(0, 0), NULL); 42 | c3geometry_p g = c3geometry_new(c3geometry_type(C3_TRIANGLE_TYPE, 0), o); 43 | 44 | o->name = str_new(filename); 45 | 46 | while (!feof(f)) { 47 | char line[256]; 48 | 49 | fgets(line, sizeof(line), f); 50 | 51 | int l = strlen(line); 52 | while (l && line[l-1] < ' ') 53 | line[--l] = 0; 54 | if (!l) 55 | continue; 56 | char * base = line; 57 | while (*base && *base <= ' ') 58 | base++; 59 | if (*base == '#') 60 | continue; 61 | l = strlen(base); 62 | 63 | char * keyword = strsep(&base, " "); 64 | 65 | if (!strcmp(keyword, "v") || !strcmp(keyword, "vn") || !strcmp(keyword, "vt")) { 66 | c3vec3 v; 67 | int ci = 0; 68 | char * cs; 69 | while ((cs = strsep(&base, " ")) != NULL && ci < 3) 70 | sscanf(cs, "%f", &v.n[ci++]); 71 | 72 | switch (keyword[1]) { 73 | case 0: 74 | c3vertex_array_add(&store->vertice, v); 75 | if (store->vertice.count == 0) 76 | g->bbox.min = g->bbox.max = v; 77 | else { 78 | g->bbox.min = c3vec3_min(g->bbox.min, v); 79 | g->bbox.max = c3vec3_max(g->bbox.max, v); 80 | } 81 | break; 82 | case 'n': 83 | c3vertex_array_add(&store->normals, v); 84 | break; 85 | case 't': 86 | c3tex_array_add(&store->textures, c3vec2f(v.x, v.y)); 87 | break; 88 | } 89 | } else if (!strcmp(keyword, "f")) { 90 | char * cs; 91 | while ((cs = strsep(&base, " ")) != NULL) { 92 | int vi, ti, ni; 93 | if (sscanf(cs, "%d/%d/%d", &vi, &ti, &ni) == 3) { 94 | c3vertex_array_add(&g->vertice, store->vertice.e[vi - 1]); 95 | c3tex_array_add(&g->textures, store->textures.e[ti - 1]); 96 | c3vertex_array_add(&g->normals, store->normals.e[ni]); 97 | } else if (sscanf(cs, "%d/%d", &vi,&ti) == 2) { 98 | c3vertex_array_add(&g->vertice, store->vertice.e[vi - 1]); 99 | c3tex_array_add(&g->textures, store->textures.e[ti - 1]); 100 | } else if (sscanf(cs, "%d//%d", &vi,&ni) == 2) { 101 | c3vertex_array_add(&g->vertice, store->vertice.e[vi - 1]); 102 | c3vertex_array_add(&g->normals, store->normals.e[ni]); 103 | } else if (*cs){ 104 | printf("%s: unknown facet format '%s'\n", filename, cs); 105 | } 106 | } 107 | } else if (!strcmp(keyword, "g")) { 108 | char * cs = strsep(&base, " "); 109 | g->name = str_new(cs); 110 | } else if (!strcmp(keyword, "o")) { 111 | char * cs = strsep(&base, " "); 112 | o->name = str_new(cs); 113 | } else { 114 | printf("%s %s unknpwn keyword '%s'\n", __func__, filename, keyword); 115 | } 116 | } 117 | fclose(f); 118 | c3geometry_dispose(store); 119 | 120 | printf("%s %s(%p) bbox = %.2f %.2f %.2f - %.2f %.2f %.2f\n", 121 | filename, 122 | g->name ? g->name->str : "?", g, 123 | g->bbox.min.x, g->bbox.min.y, g->bbox.min.z, 124 | g->bbox.max.x, g->bbox.max.y, g->bbox.max.z); 125 | return o; 126 | } 127 | -------------------------------------------------------------------------------- /src/c3model_obj.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3model_obj.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3MODEL_OBJ_H___ 24 | #define __C3MODEL_OBJ_H___ 25 | 26 | /* 27 | * Loads a OBJ file as a c3object with 28 | * a set of c3geometries with the triangles 29 | */ 30 | struct c3object_t * 31 | c3obj_load( 32 | const char * filename, 33 | struct c3object_t * parent); 34 | 35 | #endif /* __C3MODEL_OBJ_H___ */ 36 | -------------------------------------------------------------------------------- /src/c3model_stl.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3stl.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include "c3algebra.h" 24 | #include "c3geometry.h" 25 | #include "c3object.h" 26 | #include "c3model_stl.h" 27 | 28 | enum { 29 | vertex_None = -1, 30 | vertex_Vertex, 31 | vertex_Normal, 32 | }; 33 | 34 | static int 35 | _c3stl_read_vertex( 36 | char * vt, 37 | c3vec3 * out ) 38 | { 39 | int res = 1; 40 | char *l = vt; 41 | /*char * key =*/ strsep(&l, " \t"); 42 | char * x = strsep(&l, " \t"); 43 | char * y = strsep(&l, " \t"); 44 | char * z = strsep(&l, " \t"); 45 | 46 | if (x) sscanf(x, "%f", out->n); 47 | if (y) sscanf(y, "%f", out->n + 1); 48 | if (z) sscanf(z, "%f", out->n + 2); 49 | // printf("'%s' '%s' '%s' '%s' = %.2f %.2f %.2f\n", 50 | // key, x, y, z, out->n[0], out->n[1], out->n[2]); 51 | return res; 52 | } 53 | 54 | struct c3object_t * 55 | c3stl_load( 56 | const char * filename, 57 | c3object_p parent) 58 | { 59 | FILE *f = fopen(filename, "r"); 60 | if (!f) { 61 | perror(filename); 62 | return NULL; 63 | } 64 | 65 | c3object_p o = c3object_new(parent); 66 | c3geometry_p current_g = NULL; 67 | o->name = str_new(filename); 68 | 69 | int state = 0; 70 | while (!feof(f)) { 71 | char line[256]; 72 | 73 | fgets(line, sizeof(line), f); 74 | 75 | int l = strlen(line); 76 | while (l && line[l-1] < ' ') 77 | line[--l] = 0; 78 | if (!l) 79 | continue; 80 | char * keyword = line; 81 | while (*keyword && *keyword <= ' ') 82 | keyword++; 83 | l = strlen(keyword); 84 | // printf("%d>'%s'\n", state, keyword); 85 | 86 | switch (state) { 87 | case 0: // 88 | if (!strncmp(keyword, "solid ", 6)) { 89 | char * n = keyword + 6; 90 | current_g = c3geometry_new(c3geometry_type(C3_TRIANGLE_TYPE, 0), o); 91 | current_g->name = str_new(n); 92 | current_g->dirty = 1; 93 | state = 1; 94 | } 95 | break; 96 | case 1: // 97 | if (!strncmp(keyword, "facet ", 6)) { 98 | c3vec3 normal; 99 | _c3stl_read_vertex(keyword + 6, &normal); 100 | //normal = c3vec3_normalize(normal); 101 | c3vertex_array_add(¤t_g->normals, normal); 102 | c3vertex_array_add(¤t_g->normals, normal); 103 | c3vertex_array_add(¤t_g->normals, normal); 104 | state = 2; 105 | } else if (!strncmp(keyword, "endsolid ", 9)) 106 | state = 0; 107 | break; 108 | case 2: 109 | if (!strncmp(keyword, "outer loop", 10)) 110 | state = 3; 111 | else if (!strncmp(keyword, "endfacet", 8)) 112 | state = 1; 113 | break; 114 | case 3: 115 | if (!strncmp(keyword, "vertex ", 7)) { 116 | c3vec3 v; 117 | _c3stl_read_vertex(keyword, &v); 118 | c3vertex_array_add(¤t_g->vertice, v); 119 | current_g->bbox.min = c3vec3_min(current_g->bbox.min, v); 120 | current_g->bbox.max = c3vec3_max(current_g->bbox.max, v); 121 | 122 | // state = 3; 123 | } else if (!strncmp(keyword, "endloop", 7)) 124 | state = 2; 125 | break; 126 | } 127 | } 128 | printf("%s loaded %d geometries\n", filename, o->geometry.count); 129 | if (current_g) { 130 | c3geometry_p g = current_g; 131 | printf("%s(%p) bbox = %.2f %.2f %.2f - %.2f %.2f %.2f\n", 132 | g->name ? g->name->str : "?", g, 133 | g->bbox.min.x, g->bbox.min.y, g->bbox.min.z, 134 | g->bbox.max.x, g->bbox.max.y, g->bbox.max.z); 135 | } 136 | 137 | fclose(f); 138 | return o; 139 | } 140 | -------------------------------------------------------------------------------- /src/c3model_stl.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3stl.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3STL_H___ 24 | #define __C3STL_H___ 25 | 26 | /* 27 | * Loads an ASCII (TODO: Load STL Binary?) STL file as a c3object with 28 | * a set of c3geometries with the triangles 29 | */ 30 | struct c3object_t * 31 | c3stl_load( 32 | const char * filename, 33 | struct c3object_t * parent); 34 | 35 | #endif /* __C3STL_H___ */ 36 | -------------------------------------------------------------------------------- /src/c3object.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3object.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c3object.h" 24 | #include "c3context.h" 25 | #include "c3driver_object.h" 26 | 27 | void 28 | _c3object_clear( 29 | c3object_p o, 30 | const c3driver_object_t * d) 31 | { 32 | for (int oi = 0; oi < o->transform.count; oi++) { 33 | o->transform.e[oi]->object = NULL; 34 | c3transform_dispose(o->transform.e[oi]); 35 | } 36 | for (int oi = 0; oi < o->geometry.count; oi++) { 37 | o->geometry.e[oi]->object = NULL; // don't try to detach 38 | c3geometry_dispose(o->geometry.e[oi]); 39 | } 40 | for (int oi = 0; oi < o->objects.count; oi++) { 41 | o->objects.e[oi]->parent = NULL; // don't try to detach 42 | c3object_dispose(o->objects.e[oi]); 43 | } 44 | c3object_array_free(&o->objects); 45 | c3geometry_array_free(&o->geometry); 46 | c3transform_array_free(&o->transform); 47 | } 48 | 49 | void 50 | _c3object_dispose( 51 | c3object_p o, 52 | const c3driver_object_t * d) 53 | { 54 | if (o->parent) { 55 | for (int oi = 0; oi < o->parent->objects.count; oi++) 56 | if (o->parent->objects.e[oi] == o) { 57 | c3object_array_delete(&o->parent->objects, oi, 1); 58 | c3object_set_dirty(o->parent, true); 59 | break; 60 | } 61 | o->parent = NULL; 62 | } 63 | C3_DRIVER_INHERITED(o, d, dispose); 64 | free(o); 65 | } 66 | 67 | void 68 | _c3object_get_geometry( 69 | c3object_p o, 70 | const c3driver_object_t * d, 71 | c3geometry_array_p out) 72 | { 73 | // if this object is not visible in this view, exit 74 | // there will be no geometry, so no drawing 75 | uint16_t viewmask = (1 << o->context->current); 76 | if (o->hidden & viewmask) { 77 | return; 78 | } 79 | for (int oi = 0; oi < o->geometry.count; oi++) { 80 | c3geometry_p g = o->geometry.e[oi]; 81 | if (!(g->hidden & viewmask)) 82 | c3geometry_array_add(out, g); 83 | } 84 | for (int oi = 0; oi < o->objects.count; oi++) 85 | c3object_get_geometry(o->objects.e[oi], out); 86 | C3_DRIVER_INHERITED(o, d, get_geometry, out); 87 | } 88 | 89 | void 90 | _c3object_project( 91 | c3object_p o, 92 | const c3driver_object_t * d, 93 | c3mat4p m) 94 | { 95 | if (!o->dirty) 96 | return; 97 | c3mat4 p = *m; 98 | for (int pi = 0; pi < o->transform.count; pi++) { 99 | c3mat4 t = p; 100 | p = c3mat4_mul(&t, &o->transform.e[pi]->matrix); 101 | } 102 | o->world = p; 103 | 104 | for (int gi = 0; gi < o->geometry.count; gi++) { 105 | c3geometry_p g = o->geometry.e[gi]; 106 | c3geometry_project(g, &p); 107 | } 108 | for (int oi = 0; oi < o->objects.count; oi++) 109 | c3object_project(o->objects.e[oi], &p); 110 | o->dirty = false; 111 | C3_DRIVER_INHERITED(o, d, project, m); 112 | } 113 | 114 | const c3driver_object_t c3object_driver = { 115 | .clear = _c3object_clear, 116 | .dispose = _c3object_dispose, 117 | .get_geometry = _c3object_get_geometry, 118 | .project = _c3object_project, 119 | }; 120 | 121 | 122 | c3object_p 123 | c3object_init( 124 | c3object_p o /* = NULL */, 125 | c3object_p parent) 126 | { 127 | memset(o, 0, sizeof(*o)); 128 | o->parent = parent; 129 | static const c3driver_object_t * list[] = 130 | { &c3object_driver, NULL }; 131 | o->driver = list; 132 | if (parent) { 133 | c3object_array_add(&parent->objects, o); 134 | o->context = parent->context; 135 | } 136 | return o; 137 | } 138 | 139 | c3object_p 140 | c3object_new( 141 | c3object_p o /* = NULL */) 142 | { 143 | c3object_p res = malloc(sizeof(*o)); 144 | return c3object_init(res, o); 145 | } 146 | 147 | void 148 | c3object_clear( 149 | c3object_p o) 150 | { 151 | C3_DRIVER(o, clear); 152 | } 153 | 154 | void 155 | c3object_dispose( 156 | c3object_p o) 157 | { 158 | c3object_clear(o); 159 | C3_DRIVER(o, dispose); 160 | } 161 | 162 | void 163 | c3object_set_dirty( 164 | c3object_p o, 165 | bool dirty) 166 | { 167 | if (dirty) { 168 | // also mark all our geometry dirty 169 | for (int oi = 0; oi < o->geometry.count; oi++) 170 | if (o->geometry.e[oi]) 171 | o->geometry.e[oi]->dirty = 1; 172 | while (o) { 173 | o->dirty = true; 174 | o = o->parent; 175 | } 176 | } else { 177 | for (int oi = 0; oi < o->objects.count; oi++) 178 | if (o->objects.e[oi]->dirty) 179 | c3object_set_dirty(o->objects.e[oi], false); 180 | o->dirty = false; 181 | } 182 | } 183 | 184 | void 185 | c3object_add_object( 186 | c3object_p o, 187 | c3object_p sub) 188 | { 189 | if (sub->parent == o) 190 | return; 191 | if (sub->parent) { 192 | for (int oi = 0; oi < sub->parent->objects.count; oi++) { 193 | if (sub->parent->objects.e[oi] == sub) { 194 | c3object_array_delete(&sub->parent->objects, oi, 1); 195 | c3object_set_dirty(sub->parent, true); 196 | break; 197 | } 198 | } 199 | sub->parent = NULL; 200 | } 201 | sub->parent = o; 202 | if (o) { 203 | c3object_array_add(&o->objects, sub); 204 | c3object_set_dirty(o, true); 205 | } 206 | } 207 | 208 | void 209 | c3object_add_geometry( 210 | c3object_p o, 211 | c3geometry_p g) 212 | { 213 | if (g->object == o) 214 | return; 215 | if (g->object) { 216 | for (int oi = 0; oi < g->object->geometry.count; oi++) { 217 | if (g->object->geometry.e[oi] == g) { 218 | c3geometry_array_delete(&g->object->geometry, oi, 1); 219 | c3object_set_dirty(g->object, true); 220 | break; 221 | } 222 | } 223 | g->object = NULL; 224 | } 225 | g->object = o; 226 | if (o) { 227 | c3geometry_array_add(&o->geometry, g); 228 | c3object_set_dirty(o, true); 229 | } 230 | } 231 | 232 | void 233 | c3object_get_geometry( 234 | c3object_p o, 235 | c3geometry_array_p array ) 236 | { 237 | C3_DRIVER(o, get_geometry, array); 238 | } 239 | 240 | void 241 | c3object_project( 242 | c3object_p o, 243 | const c3mat4p m) 244 | { 245 | C3_DRIVER(o, project, m); 246 | } 247 | -------------------------------------------------------------------------------- /src/c3object.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3object.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3OBJECT_H___ 24 | #define __C3OBJECT_H___ 25 | 26 | #include 27 | #include "c3transform.h" 28 | #include "c3geometry.h" 29 | 30 | struct c3object_t; 31 | 32 | DECLARE_C_ARRAY(struct c3object_t*, c3object_array, 4); 33 | 34 | //! c3object is a container for child object, and geometry 35 | /*! 36 | * a c3object is a node in a c3object tree, it contains sub-objects and/or 37 | * geometry. It also contains it's own list of transform matrices, so can 38 | * be seen as a "anchor" that can be moved around and where you can 39 | * attach other objects or geometry. 40 | * 41 | * An object has a notion of 'dirty bit' -- something that signals that 42 | * something has changed and deserved reprojection. the dirty bit 43 | * is propagated upward when 1 (up to the root object) and downward when 0 44 | * (to allow clearing the bit on a subtree) 45 | */ 46 | typedef struct c3object_t { 47 | str_p name; //! optional name 48 | int dirty : 1, 49 | hidden : 8 /* hidden bit mask, related to c3context's views */; 50 | struct c3context_t * context; //! context this object is attached to 51 | struct c3object_t * parent; //! Parent object 52 | const struct c3driver_object_t ** driver; //! Driver stack 53 | 54 | c3mat4 world; // calculated world coordinates 55 | c3transform_array_t transform; 56 | c3object_array_t objects; //! child object list 57 | c3geometry_array_t geometry; //! Object geometri(es) 58 | } c3object_t, *c3object_p; 59 | 60 | //! Allocates and initialize an emty object, attaches it to parent 'o' 61 | c3object_p 62 | c3object_new( 63 | c3object_p o /* = NULL */); 64 | //! Disposes of everything under this object 65 | void 66 | c3object_dispose( 67 | c3object_p o); 68 | //! Clears every sub-object, geometry, and transform, but do not dispose of o 69 | void 70 | c3object_clear( 71 | c3object_p o); 72 | //! Initializes 'o' as a new object, attaches it to parent (optional) 73 | c3object_p 74 | c3object_init( 75 | c3object_p o, 76 | c3object_p parent /* = NULL */); 77 | //! sets the dirty bit for 'o' and related tree 78 | /*! 79 | * When dirty is 1, sets the dirty bit of this object and all the parent 80 | * objects up to the root object. 81 | * When dirty is 0, clear the dirty bit of this object, and all the 82 | * sub objects. 83 | */ 84 | void 85 | c3object_set_dirty( 86 | c3object_p o, 87 | bool dirty); 88 | //! Adds a new geometry g to object o 89 | void 90 | c3object_add_geometry( 91 | c3object_p o, 92 | c3geometry_p g); 93 | //! Adds a new sub-object sub to object o 94 | void 95 | c3object_add_object( 96 | c3object_p o, 97 | c3object_p sub); 98 | //! Adds a new transform matrix, initialized as identity 99 | c3transform_p 100 | c3object_add_transform( 101 | c3object_p o ); 102 | //! Iterates all the sub-objects and collects all the geometries 103 | /*! 104 | * This call iterates the sub-objects and collects all their 'projected' 105 | * geometry, and add them to the array 106 | */ 107 | void 108 | c3object_get_geometry( 109 | c3object_p o, 110 | c3geometry_array_p array ); 111 | //! Project object 'o' using it's own transformations, relative to matrix 'm' 112 | /*! 113 | * Multiply this objects transformation(s) to matrix 'm' and calls 114 | * reprojects the geometries using that matrix as an anchor. also call 115 | * recursively to sub-objects to follow the projection down. 116 | */ 117 | void 118 | c3object_project( 119 | c3object_p o, 120 | const c3mat4p m); 121 | 122 | IMPLEMENT_C_ARRAY(c3object_array); 123 | 124 | #endif /* __C3OBJECT_H___ */ 125 | -------------------------------------------------------------------------------- /src/c3pixels.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3pixels.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include "c3pixels.h" 25 | 26 | c3pixels_p 27 | c3pixels_new( 28 | uint32_t w, 29 | uint32_t h, 30 | int psize /* in bytes */, 31 | size_t row, 32 | void * base) 33 | { 34 | c3pixels_p p = malloc(sizeof(*p)); 35 | c3pixels_init(p, w, h, psize, row, base); 36 | p->alloc = 1; 37 | return p; 38 | } 39 | 40 | c3pixels_p 41 | c3pixels_init( 42 | c3pixels_p p, 43 | uint32_t w, 44 | uint32_t h, 45 | int psize /* in bytes */, 46 | size_t row, 47 | void * base) 48 | { 49 | memset (p, 0, sizeof(*p)); 50 | p->w = w; 51 | p->h = h; 52 | p->row = row; 53 | p->psize = psize; 54 | p->base = base; 55 | c3pixels_alloc(p); 56 | return p; 57 | } 58 | 59 | void 60 | c3pixels_dispose( 61 | c3pixels_p p ) 62 | { 63 | if (p->own && p->base) 64 | free(p->base); 65 | if (p->alloc) 66 | free(p); 67 | else 68 | memset(p, 0, sizeof(*p)); 69 | } 70 | 71 | void 72 | c3pixels_alloc( 73 | c3pixels_p p ) 74 | { 75 | if (p->base) 76 | return; 77 | p->base = malloc(p->row * p->h); 78 | p->own = p->base != NULL; 79 | } 80 | 81 | void 82 | c3pixels_purge( 83 | c3pixels_p p ) 84 | { 85 | if (!p->base) 86 | return; 87 | if (p->own) 88 | free(p->base); 89 | p->own = 0; 90 | p->base = NULL; 91 | } 92 | 93 | void 94 | c3pixels_zero( 95 | c3pixels_p p) 96 | { 97 | if (!p->base) 98 | return; 99 | memset(p->base, 0, p->h * p->row); 100 | } 101 | -------------------------------------------------------------------------------- /src/c3pixels.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3pixels.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3PIXELS_H___ 24 | #define __C3PIXELS_H___ 25 | 26 | #include "c3types.h" 27 | #include "c_utils.h" 28 | 29 | //! for format hint 30 | enum { 31 | C3PIXEL_ARGB = 0, 32 | C3PIXEL_RGB, 33 | C3PIXEL_LUMINANCE, 34 | C3PIXEL_ALPHA, 35 | }; 36 | 37 | typedef struct c3pixels_t { 38 | str_p name; // optional 39 | uint32_t w, h; // width & height in pixels 40 | size_t row; // size of one row in bytes 41 | void * base; // base address 42 | 43 | union { 44 | struct { 45 | uint32_t own : 1, // is the base our own to delete 46 | alloc : 1, // is the c3pixels_p our own to delete 47 | dirty : 1, // pixels have been changed 48 | psize : 4, // pixel size in byte 49 | rectangle : 1, // texture coordinates are 0...width not 0...1 50 | trace : 1, // debug 51 | mutable : 1, // should the texture be purged 52 | format : 8; // not used internally 53 | }; 54 | uint32_t flags; 55 | }; 56 | c3apiobject_t texture; 57 | int refCount; // TODO: Implement reference counting ? 58 | } c3pixels_t, *c3pixels_p; 59 | 60 | DECLARE_C_ARRAY(c3pixels_p, c3pixels_array, 4); 61 | 62 | //! Allocates a new c3pixels, also allocates the pixels if row == NULL 63 | c3pixels_p 64 | c3pixels_new( 65 | uint32_t w, 66 | uint32_t h, 67 | int psize /* in bytes */, 68 | size_t row, 69 | void * base); 70 | 71 | //! Initializes p, also allocates the pixels if row == NULL 72 | c3pixels_p 73 | c3pixels_init( 74 | c3pixels_p p, 75 | uint32_t w, 76 | uint32_t h, 77 | int psize /* in bytes */, 78 | size_t row, 79 | void * base); 80 | 81 | //! Dispose of the pixels, and potentially p if it was allocated with c3pixels_new 82 | void 83 | c3pixels_dispose( 84 | c3pixels_p p ); 85 | 86 | //! Disposes of the pixels, only 87 | void 88 | c3pixels_purge( 89 | c3pixels_p p ); 90 | 91 | //! (Re)allocate pixels if pixels had been purged 92 | void 93 | c3pixels_alloc( 94 | c3pixels_p p ); 95 | 96 | //! Get a pixel address 97 | static inline void * 98 | c3pixels_get( 99 | c3pixels_p p, 100 | int x, int y) 101 | { 102 | return ((uint8_t*)p->base) + (y * p->row) + (x * p->psize); 103 | } 104 | 105 | //! Zeroes the pixels 106 | void 107 | c3pixels_zero( 108 | c3pixels_p p); 109 | 110 | IMPLEMENT_C_ARRAY(c3pixels_array); 111 | 112 | #endif /* __C3PIXELS_H___ */ 113 | -------------------------------------------------------------------------------- /src/c3program.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3program.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "c3program.h" 31 | 32 | c3program_p 33 | c3program_new( 34 | const char * name, 35 | const char ** uniforms ) 36 | { 37 | c3program_p p = malloc(sizeof(*p)); 38 | memset(p, 0, sizeof(*p)); 39 | p->name = str_new(name); 40 | 41 | /* Allow specifying uniform names to make sure they are in 42 | * the specified order in the array, this allow direct indexing 43 | * instead of doign string lookup 44 | */ 45 | if (uniforms) { 46 | for (int ui = 0; uniforms[ui]; ui++) { 47 | c3program_param_t pa = { 48 | .name = str_new(uniforms[ui]), 49 | .program = p, 50 | .index = p->params.count, 51 | }; 52 | c3program_param_array_add(&p->params, pa); 53 | } 54 | } 55 | return p; 56 | } 57 | 58 | void 59 | c3program_dispose( 60 | c3program_p p) 61 | { 62 | c3program_purge(p); 63 | for (int pi = 0; pi < p->params.count; pi++) { 64 | c3program_param_p pa = &p->params.e[pi]; 65 | str_free(pa->name); 66 | } 67 | c3program_param_array_free(&p->params); 68 | str_free(p->name); 69 | str_free(p->log); 70 | free(p); 71 | } 72 | 73 | void 74 | c3program_purge( 75 | c3program_p p) 76 | { 77 | for (int si = 0; si < p->shaders.count; si++) { 78 | c3shader_p s = &p->shaders.e[si]; 79 | str_free(s->name); 80 | str_free(s->shader); 81 | } 82 | c3shader_array_free(&p->shaders); 83 | } 84 | 85 | c3program_param_p 86 | c3program_locate_param( 87 | c3program_p p, 88 | const char * name ) 89 | { 90 | for (int pi = 0; pi < p->params.count; pi++) 91 | if (!strcmp(p->params.e[pi].name->str, name)) 92 | return &p->params.e[pi]; 93 | return NULL; 94 | } 95 | 96 | int 97 | c3program_load_shader( 98 | c3program_p p, 99 | uint32_t type, 100 | const char * header, 101 | const char * filename, 102 | uint16_t flags) 103 | { 104 | struct stat st; 105 | str_p pgm = NULL; 106 | int fd = -1; 107 | 108 | if (stat(filename, &st)) 109 | goto error; 110 | fd = open(filename, O_RDONLY); 111 | if (fd == -1) 112 | goto error; 113 | 114 | int hlen = header ? strlen(header) : 0; 115 | pgm = str_alloc(st.st_size + hlen); 116 | if (header) 117 | strcpy(pgm->str, header); 118 | 119 | if (read(fd, pgm->str + hlen, st.st_size) != st.st_size) 120 | goto error; 121 | close(fd); 122 | pgm->str[pgm->len] = 0; // zero terminate it 123 | 124 | c3shader_t s = { 125 | .type = type, 126 | .name = str_new(filename), 127 | .shader = pgm, 128 | }; 129 | c3shader_array_add(&p->shaders, s); 130 | 131 | if (flags & C3_PROGRAM_LOAD_UNIFORM) { 132 | char * cur = pgm->str; 133 | char * l; 134 | 135 | while ((l = strsep(&cur, "\r\n")) != NULL) { 136 | while (*l && *l <= ' ') 137 | l++; 138 | str_p line = str_new(l); 139 | if (cur) // fix the endline after strsep 140 | *(cur-1) = '\n'; 141 | if (strncmp(line->str, "uniform", 7)) 142 | continue; 143 | // printf("UNI: %s\n", line->str); 144 | 145 | char * sep = line->str; 146 | char * uniform = strsep(&sep, " \t"); 147 | char * unitype = strsep(&sep, " \t"); 148 | char * uniname = strsep(&sep, " \t=;"); 149 | /* 150 | * found a parameter, extract it's type & name 151 | */ 152 | if (uniform && unitype && uniname) { 153 | // trim semicolons etc 154 | char *cl = uniname; 155 | while (isalpha(*cl) || *cl == '_' || isdigit(*cl)) 156 | cl++; 157 | *cl = 0; 158 | str_p name = str_new(uniname); 159 | for (int pi = 0; pi < p->params.count && uniform; pi++) 160 | if (!str_cmp(name, p->params.e[pi].name)) { 161 | if (!p->params.e[pi].type) 162 | p->params.e[pi].type = str_new(unitype); 163 | uniform = NULL; // already there 164 | } 165 | if (uniform) { 166 | c3program_param_t pa = { 167 | .type = str_new(unitype), 168 | .name = name, 169 | .program = p, 170 | .index = p->params.count, 171 | }; 172 | c3program_param_array_add(&p->params, pa); 173 | if (p->verbose) 174 | printf("%s %s: new parameter '%s' '%s'\n", __func__, 175 | p->name->str, unitype, uniname); 176 | } else 177 | str_free(name); 178 | } 179 | str_free(line); 180 | } 181 | } 182 | return p->shaders.count - 1; 183 | 184 | error: 185 | if (fd != -1) 186 | close(fd); 187 | if (pgm) 188 | str_free(pgm); 189 | fprintf(stderr, "%s: %s: %s\n", __func__, filename, strerror(errno)); 190 | return -1; 191 | 192 | } 193 | -------------------------------------------------------------------------------- /src/c3program.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3program.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3PROGRAM_H___ 24 | #define __C3PROGRAM_H___ 25 | 26 | #include "c3types.h" 27 | #include "c_utils.h" 28 | 29 | typedef struct c3shader_t { 30 | c3apiobject_t sid; // shader id 31 | uint32_t type; 32 | str_p name; 33 | str_p shader; 34 | } c3shader_t, *c3shader_p; 35 | 36 | DECLARE_C_ARRAY(c3shader_t, c3shader_array, 4); 37 | 38 | typedef struct c3program_param_t { 39 | struct c3program_t * program; 40 | int index; // index number in paramerer array 41 | c3apiobject_t pid; // parameter id 42 | str_p type; 43 | str_p name; 44 | } c3program_param_t, *c3program_param_p; 45 | 46 | DECLARE_C_ARRAY(c3program_param_t, c3program_param_array, 4); 47 | 48 | typedef struct c3program_t { 49 | c3apiobject_t pid; // program id 50 | int verbose : 1; 51 | str_p name; 52 | c3shader_array_t shaders; 53 | c3program_param_array_t params; 54 | str_p log; // if an error occurs 55 | } c3program_t, *c3program_p; 56 | 57 | DECLARE_C_ARRAY(c3program_p, c3program_array, 4); 58 | 59 | //! Allocates a new, empty program 60 | /* if 'uniforms' is non null it is a NULL terminated array of 61 | * uniform names to pre-add to the uniform array in the specified 62 | * order. 63 | * This make sure they are in the specified order in the array, 64 | * to allow direct indexing instead of doing string lookup by name 65 | */ 66 | c3program_p 67 | c3program_new( 68 | const char * name, 69 | const char ** uniforms /* optional */); 70 | 71 | //! disposes of a c3program memory 72 | void 73 | c3program_dispose( 74 | c3program_p p); 75 | 76 | //! purge deletes the shader storage, but keep the program and parameters 77 | void 78 | c3program_purge( 79 | c3program_p p); 80 | 81 | enum { 82 | C3_PROGRAM_LOAD_UNIFORM = (1 << 0), 83 | }; 84 | 85 | int 86 | c3program_load_shader( 87 | c3program_p p, 88 | uint32_t type, 89 | const char * header, 90 | const char * filename, 91 | uint16_t flags); 92 | 93 | c3program_param_p 94 | c3program_locate_param( 95 | c3program_p p, 96 | const char * name ); 97 | 98 | IMPLEMENT_C_ARRAY(c3program_param_array); 99 | IMPLEMENT_C_ARRAY(c3shader_array); 100 | IMPLEMENT_C_ARRAY(c3program_array); 101 | 102 | #endif /* __C3PROGRAM_H___ */ 103 | -------------------------------------------------------------------------------- /src/c3quaternion.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3quaternion.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | #include 23 | #include "c3quaternion.h" 24 | 25 | #ifndef DEG2RAD 26 | #define DEG2RAD(x) ((x)/180.0*M_PI) 27 | #define RAD2DEG(x) ((x)/M_PI*180.0) 28 | #endif 29 | #ifndef FUDGE 30 | #define FUDGE .00001 31 | #endif 32 | 33 | c3quat 34 | c3quat_new() 35 | { 36 | return c3quat_identity(); 37 | } 38 | 39 | /************************************************* c3quat_identity() *****/ 40 | /* Returns quaternion identity element */ 41 | 42 | c3quat 43 | c3quat_identity() 44 | { 45 | return c3quat_vec3( c3vec3f( 0.0, 0.0, 0.0 ), 1.0 ); 46 | } 47 | 48 | c3quat 49 | c3quatf( 50 | const c3f x, 51 | const c3f y, 52 | const c3f z, 53 | const c3f w) 54 | { 55 | c3quat q = { .v = c3vec3f(x,y,z), .s = w }; 56 | return q; 57 | } 58 | 59 | c3quat 60 | c3quat_vec3( 61 | const c3vec3 v, 62 | const c3f s) 63 | { 64 | c3quat q = { .v = v, .s = s }; 65 | return q; 66 | } 67 | 68 | c3quat 69 | c3quat_vec4( 70 | const c3vec4 v) 71 | { 72 | c3quat q = { .v = c3vec3f(v.n[0], v.n[1], v.n[2]), .s = v.n[3] }; 73 | return q; 74 | } 75 | 76 | c3quat 77 | c3quat_double( 78 | const double *d) 79 | { 80 | c3quat q; 81 | q.v.n[0] = (c3f) d[0]; 82 | q.v.n[1] = (c3f) d[1]; 83 | q.v.n[2] = (c3f) d[2]; 84 | q.s = (c3f) d[3]; 85 | return q; 86 | } 87 | 88 | 89 | c3quat 90 | c3quat_add( 91 | const c3quat a, 92 | const c3quat b) 93 | { 94 | return c3quat_vec3(c3vec3_add(a.v, b.v), a.s + b.s ); 95 | } 96 | 97 | c3quat 98 | c3quat_sub( 99 | const c3quat a, 100 | const c3quat b) 101 | { 102 | return c3quat_vec3(c3vec3_sub(a.v, b.v), a.s - b.s ); 103 | } 104 | 105 | c3quat 106 | c3quat_minus( 107 | const c3quat a ) 108 | { 109 | return c3quat_vec3(c3vec3_minus(a.v), -a.s); 110 | } 111 | 112 | c3quat 113 | c3quat_mul( 114 | const c3quat a, 115 | const c3quat b) 116 | { 117 | // return c3quat( a.s*b.s - a.v*b.v, a.s*b.v + b.s*a.v + a.v^b.v ); 118 | return c3quat_vec3( 119 | c3vec3_add(c3vec3_mulf(b.v, a.s), c3vec3_add(c3vec3_mulf(a.v, b.s), c3vec3_cross(a.v, b.v))), 120 | (a.s * b.s) - c3vec3_dot(a.v, b.v)); 121 | } 122 | 123 | c3quat 124 | c3quat_mulf( const c3quat a, const c3f t) 125 | { 126 | return c3quat_vec3(c3vec3_mulf(a.v, t), a.s * t ); 127 | } 128 | 129 | c3mat4 130 | c3quat_to_mat4( 131 | const c3quat a ) 132 | { 133 | c3f xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz; 134 | 135 | c3f t = 2.0f / (c3vec3_dot(a.v, a.v) + (a.s * a.s)); 136 | 137 | xs = a.v.n[VX]*t; ys = a.v.n[VY]*t; zs = a.v.n[VZ]*t; 138 | wx = a.s*xs; wy = a.s*ys; wz = a.s*zs; 139 | xx = a.v.n[VX]*xs; xy = a.v.n[VX]*ys; xz = a.v.n[VX]*zs; 140 | yy = a.v.n[VY]*ys; yz = a.v.n[VY]*zs; zz = a.v.n[VZ]*zs; 141 | 142 | c3mat4 m = c3mat4_vec4( 143 | c3vec4f(1.0f-(yy+zz), xy+wz, xz-wy, 0.0f), 144 | c3vec4f(xy-wz, 1.0f-(xx+zz), yz+wx, 0.0f), 145 | c3vec4f(xz+wy, yz-wx, 1.0f-(xx+yy), 0.0f), 146 | c3vec4f(0.0f, 0.0f, 0.0f, 1.0f )); 147 | 148 | return m; 149 | } 150 | 151 | 152 | /************************************************ quat_slerp() ********/ 153 | /* Quaternion spherical interpolation */ 154 | 155 | c3quat 156 | quat_slerp( 157 | const c3quat from, 158 | const c3quat to, 159 | c3f t) 160 | { 161 | c3quat to1; 162 | c3f omega, cosom, sinom, scale0, scale1; 163 | 164 | /* calculate cosine */ 165 | cosom = c3vec3_dot(from.v, to.v) + from.s + to.s; 166 | 167 | /* Adjust signs (if necessary) */ 168 | if (cosom < 0.0) { 169 | cosom = -cosom; 170 | to1 = c3quat_minus(to); 171 | } else { 172 | to1 = to; 173 | } 174 | 175 | /* Calculate coefficients */ 176 | if ((1.0 - cosom) > FUDGE ) { 177 | /* standard case (slerp) */ 178 | omega = (c3f) acos( cosom ); 179 | sinom = (c3f) sin( omega ); 180 | scale0 = (c3f) sin((1.0 - t) * omega) / sinom; 181 | scale1 = (c3f) sin(t * omega) / sinom; 182 | } else { 183 | /* 'from' and 'to' are very close - just do linear interpolation */ 184 | scale0 = 1.0f - t; 185 | scale1 = t; 186 | } 187 | 188 | return c3quat_add(c3quat_mulf(from, scale0), c3quat_mulf(to1, scale1)); 189 | } 190 | 191 | /********************************************** set_angle() ************/ 192 | /* set rot angle (degrees) */ 193 | 194 | c3quatp 195 | c3quat_set_angle( 196 | c3quatp a, 197 | c3f f) 198 | { 199 | c3vec3 axis = c3quat_get_axis(a); 200 | 201 | a->s = (c3f) cos( DEG2RAD( f ) / 2.0 ); 202 | 203 | a->v = c3vec3_mulf(axis, (c3f) sin(DEG2RAD(f) / 2.0)); 204 | return a; 205 | } 206 | 207 | /********************************************** scale_angle() ************/ 208 | /* scale rot angle (degrees) */ 209 | 210 | c3quatp 211 | c3quat_scale_angle( 212 | c3quatp a, 213 | c3f f) 214 | { 215 | return c3quat_set_angle(a, f * c3quat_get_angle(a) ); 216 | } 217 | 218 | /********************************************** get_angle() ************/ 219 | /* get rot angle (degrees). Assumes s is between -1 and 1 */ 220 | 221 | c3f 222 | c3quat_get_angle( 223 | const c3quatp a) 224 | { 225 | return (c3f) RAD2DEG( 2.0 * acos( a->s ) ); 226 | } 227 | 228 | /********************************************* get_axis() **************/ 229 | 230 | c3vec3 231 | c3quat_get_axis( 232 | c3quatp a) 233 | { 234 | c3f scale = (c3f) sin( acos( a->s ) ); 235 | 236 | if ( scale < FUDGE && scale > -FUDGE ) 237 | return c3vec3f( 0.0, 0.0, 0.0 ); 238 | else 239 | return c3vec3_divf(a->v, scale); 240 | } 241 | 242 | /******************************************* c3quat_print() ************/ 243 | #if 0 244 | void c3quat_print(FILE *dest, const char *name) const 245 | { 246 | fprintf( dest, "%s: v:<%3.2f %3.2f %3.2f> s:%3.2f\n", 247 | name, v[0], v[1], v[2], s ); 248 | } 249 | #endif 250 | -------------------------------------------------------------------------------- /src/c3quaternion.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3quaternion.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3QUATERNION_H___ 24 | #define __C3QUATERNION_H___ 25 | 26 | #include 27 | #include "c3algebra.h" 28 | 29 | typedef struct c3quat { 30 | c3vec3 v; /* vector component */ 31 | c3f s; /* scalar component */ 32 | } c3quat, *c3quatp; 33 | 34 | c3quat 35 | c3quat_new(); 36 | c3quat 37 | c3quat_identity(); 38 | 39 | c3quat 40 | c3quatf( 41 | const c3f x, 42 | const c3f y, 43 | const c3f z, 44 | const c3f w); 45 | c3quat 46 | c3quat_vec3( 47 | const c3vec3 v, 48 | const c3f s); 49 | c3quat 50 | c3quat_vec4( 51 | const c3vec4 v); 52 | 53 | c3quat 54 | c3quat_double( 55 | const double *d); 56 | 57 | c3quat 58 | c3quat_add( 59 | const c3quat a, 60 | const c3quat b); 61 | c3quat 62 | c3quat_sub( 63 | const c3quat a, 64 | const c3quat b); 65 | c3quat 66 | c3quat_minus( 67 | const c3quat a ); 68 | 69 | c3quat 70 | c3quat_mul( 71 | const c3quat a, 72 | const c3quat b); 73 | 74 | c3mat4 75 | c3quat_to_mat4( 76 | const c3quat a ); 77 | 78 | c3quatp 79 | c3quat_set_angle( 80 | c3quatp a, 81 | c3f f); 82 | c3quatp 83 | c3quat_scale_angle( 84 | c3quatp a, 85 | c3f f); 86 | c3f 87 | c3quat_get_angle( 88 | const c3quatp a); 89 | c3vec3 90 | c3quat_get_axis( 91 | c3quatp a); 92 | 93 | #endif /* __C3QUATERNION_H___ */ 94 | -------------------------------------------------------------------------------- /src/c3sphere.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3sphere.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include "c3geometry.h" 25 | #include "c3sphere.h" 26 | 27 | c3geometry_p 28 | c3sphere_uv( 29 | struct c3object_t * parent, 30 | c3vec3 center, 31 | c3f radius, 32 | int rings, 33 | int sectors ) 34 | { 35 | float const R = 1. / (float) (rings - 1); 36 | float const S = 1. / (float) (sectors - 1); 37 | 38 | c3geometry_p g = c3geometry_new(c3geometry_type(C3_SPHERE_TYPE, 0), parent); 39 | 40 | c3vertex_array_realloc(&g->vertice, rings * sectors); 41 | c3vertex_array_realloc(&g->normals, rings * sectors); 42 | c3tex_array_realloc(&g->textures, rings * sectors); 43 | c3indices_array_realloc(&g->indices, rings * sectors * 6); 44 | 45 | for (int r = 0; r < rings; r++) 46 | for (int s = 0; s < sectors; s++) { 47 | float const y = sin(-M_PI_2 + M_PI * r * R); 48 | float const x = cos(2 * M_PI * s * S) * sin(M_PI * r * R); 49 | float const z = sin(2 * M_PI * s * S) * sin(M_PI * r * R); 50 | 51 | c3tex_array_add(&g->textures, c3vec2f(s * S, r * R)); 52 | c3vertex_array_add(&g->vertice, 53 | c3vec3_add(center, c3vec3f(x * radius, y * radius, z * radius))); 54 | c3vertex_array_add(&g->normals, c3vec3_normalize(c3vec3f(x, y, z))); 55 | } 56 | 57 | for (int r = 0; r < rings - 1; r++) 58 | for (int s = 0; s < sectors - 1; s++) { 59 | uint16_t i[6] = { 60 | r * sectors + (s + 1), r * sectors + s, (r + 1) * sectors + (s + 1), 61 | (r + 1) * sectors + (s + 1), r * sectors + s, (r + 1) * sectors + s, 62 | }; 63 | c3indices_array_insert(&g->indices, g->indices.count, i, 6); 64 | } 65 | return g; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/c3sphere.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3sphere.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3SPHERE_H___ 24 | #define __C3SPHERE_H___ 25 | 26 | #include "c3algebra.h" 27 | 28 | enum { 29 | C3_SPHERE_TYPE = C3_TYPE('s','p','h','e'), 30 | }; 31 | 32 | struct c3geometry_t * 33 | c3sphere_uv( 34 | struct c3object_t * parent, 35 | c3vec3 center, 36 | c3f radius, 37 | int rings, 38 | int sectors ); 39 | 40 | #endif /* __C3SPHERE_H___ */ 41 | -------------------------------------------------------------------------------- /src/c3texture.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3texture.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include 24 | #include "c3texture.h" 25 | #include "c3driver_geometry.h" 26 | 27 | void 28 | _c3texture_dispose( 29 | c3geometry_p g, 30 | const c3driver_geometry_t * d) 31 | { 32 | // c3texture_p t = (c3texture_p)g; 33 | C3_DRIVER_INHERITED(g, d, dispose); 34 | } 35 | 36 | void 37 | _c3texture_project( 38 | c3geometry_p g, 39 | const c3driver_geometry_t * d, 40 | c3mat4p m) 41 | { 42 | c3texture_p t = (c3texture_p)g; 43 | c3pixels_p p = t->geometry.mat.texture; 44 | if (!p) { 45 | C3_DRIVER_INHERITED(g, d, project, m); 46 | return; 47 | } 48 | c3vec2 qs = c3vec2f( 49 | t->size.x > 0 ? t->size.x : p->w, 50 | t->size.y > 0 ? t->size.y : p->h); 51 | c3vec3 v[4] = { 52 | c3vec3f(0, 0, 0), c3vec3f(qs.x, 0, 0), 53 | c3vec3f(qs.x, qs.y, 0), c3vec3f(0, qs.y, 0) 54 | }; 55 | c3vertex_array_clear(&g->vertice); 56 | c3vertex_array_realloc(&g->vertice, 4); 57 | c3vertex_array_insert(&g->vertice, 0, v, 4); 58 | 59 | c3f tw = p->rectangle ? p->w : 1.0, 60 | th = p->rectangle ? p->h : 1.0; 61 | c3vec2 ti[4] = { 62 | c3vec2f(0, th), c3vec2f(tw, th), 63 | c3vec2f(tw, 0), c3vec2f(0, 0) 64 | }; 65 | if (p->trace) 66 | printf("%s size %.0fx%.0f tex %.0fx%.0f\n", __func__, qs.x, qs.y, tw, th); 67 | c3tex_array_clear(&t->geometry.textures); 68 | c3tex_array_realloc(&t->geometry.textures, 4); 69 | c3tex_array_insert(&t->geometry.textures, 0, ti, 4); 70 | 71 | C3_DRIVER_INHERITED(g, d, project, m); 72 | } 73 | 74 | const c3driver_geometry_t c3texture_driver = { 75 | .dispose = _c3texture_dispose, 76 | .project = _c3texture_project, 77 | }; 78 | extern const c3driver_geometry_t c3geometry_driver; 79 | 80 | c3texture_p 81 | c3texture_new( 82 | struct c3object_t * o /* = NULL */) 83 | { 84 | c3texture_p res = malloc(sizeof(*res)); 85 | return c3texture_init(res, o); 86 | } 87 | 88 | c3texture_p 89 | c3texture_init( 90 | c3texture_p t, 91 | struct c3object_t * o /* = NULL */) 92 | { 93 | memset(t, 0, sizeof(*t)); 94 | c3geometry_init(&t->geometry, 95 | c3geometry_type(C3_TEXTURE_TYPE, 0 /* GL_TRIANGLE_FAN */), 96 | o); 97 | static const c3driver_geometry_t * list[] = { 98 | &c3texture_driver, &c3geometry_driver, NULL, 99 | }; 100 | t->geometry.driver = list; 101 | 102 | return t; 103 | } 104 | 105 | void 106 | c3texture_resize( 107 | c3texture_p t, 108 | c3vec2 size ) 109 | { 110 | t->size = size; 111 | c3geometry_set_dirty(&t->geometry, 1); 112 | } 113 | -------------------------------------------------------------------------------- /src/c3texture.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3texture.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3TEXTURE_H___ 24 | #define __C3TEXTURE_H___ 25 | 26 | #include "c3geometry.h" 27 | #include "c3pixels.h" 28 | 29 | enum { 30 | C3_TEXTURE_TYPE = C3_TYPE('t','e','x','u'), 31 | }; 32 | 33 | typedef struct c3texture_t { 34 | c3geometry_t geometry; 35 | c3vec2 size; // quad size 36 | } c3texture_t, *c3texture_p; 37 | 38 | c3texture_p 39 | c3texture_new( 40 | struct c3object_t * parent /* = NULL */); 41 | c3texture_p 42 | c3texture_init( 43 | c3texture_p t, 44 | struct c3object_t * parent /* = NULL */); 45 | void 46 | c3texture_resize( 47 | c3texture_p t, 48 | c3vec2 size ); 49 | 50 | #endif /* __C3TEXTURE_H___ */ 51 | -------------------------------------------------------------------------------- /src/c3transform.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3transform.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c3object.h" 24 | 25 | c3transform_p 26 | c3transform_new( 27 | c3object_p o ) 28 | { 29 | c3transform_p res = malloc(sizeof(*res)); 30 | res->matrix = identity3D(); 31 | res->object = o; 32 | res->name = NULL; 33 | c3transform_array_add(&o->transform, res); 34 | return res; 35 | } 36 | 37 | void 38 | c3transform_dispose( 39 | c3transform_p t ) 40 | { 41 | if (t->object) { 42 | for (int oi = 0; oi < t->object->transform.count; oi++) 43 | if (t->object->transform.e[oi] == t) { 44 | c3transform_array_delete(&t->object->transform, oi, 1); 45 | c3object_set_dirty(t->object, true); 46 | break; 47 | } 48 | t->object = NULL; 49 | } 50 | str_free(t->name); 51 | free(t); 52 | } 53 | 54 | void 55 | c3transform_set( 56 | c3transform_p t, 57 | const c3mat4p m ) 58 | { 59 | if (c3mat4_equal(m, &t->matrix)) 60 | return; 61 | t->matrix = *m; 62 | c3object_set_dirty(t->object, true); 63 | } 64 | -------------------------------------------------------------------------------- /src/c3transform.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3transform.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3TRANSFORM_H___ 24 | #define __C3TRANSFORM_H___ 25 | 26 | #include "c3algebra.h" 27 | #include "c_utils.h" 28 | 29 | typedef struct c3transform_t { 30 | str_p name; 31 | struct c3object_t * object; 32 | c3mat4 matrix; 33 | } c3transform_t, *c3transform_p; 34 | 35 | c3transform_p 36 | c3transform_new( 37 | struct c3object_t * o ); 38 | void 39 | c3transform_set( 40 | c3transform_p t, 41 | c3mat4p m ); 42 | void 43 | c3transform_dispose( 44 | c3transform_p t ); 45 | 46 | DECLARE_C_ARRAY(c3transform_p, c3transform_array, 4); 47 | IMPLEMENT_C_ARRAY(c3transform_array); 48 | 49 | #endif /* __C3TRANSFORM_H___ */ 50 | -------------------------------------------------------------------------------- /src/c3types.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3types.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3TYPES_H___ 24 | #define __C3TYPES_H___ 25 | 26 | #include 27 | #include "c3algebra.h" 28 | 29 | typedef c3vec3 c3vertex_t, *c3vertex_p; 30 | typedef c3vec4 c3colorf_t, *c3colorf_p; 31 | typedef c3vec2 c3tex_t, *c3tex_p; 32 | typedef uint16_t c3index_t, *c3index_p; 33 | 34 | /* this type is used to store an API object (texture id etc 35 | * it is made to force a cast in most cases as OpenGL uses integers 36 | * for object ids 37 | */ 38 | typedef void * c3apiobject_t; 39 | 40 | #define C3APIO_INT(__v) (int)(((intptr_t)(__v))) 41 | #define C3APIO(__v) (c3apiobject_t)(((intptr_t)(__v))) 42 | 43 | //! Bounding box 44 | typedef struct c3bbox_t { 45 | c3vec3 min, max; 46 | } c3bbox_t; 47 | 48 | #endif /* __C3TYPES_H___ */ 49 | -------------------------------------------------------------------------------- /src/c_array.h: -------------------------------------------------------------------------------- 1 | /* 2 | c_array.h 3 | 4 | Copyright 2012 Michel Pollet 5 | 6 | This file is part of gcodepp. 7 | 8 | gcodepp is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | gcodepp is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with gcodepp. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C_ARRAY_H___ 24 | #define __C_ARRAY_H___ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifndef C_ARRAY_INLINE 31 | #define C_ARRAY_INLINE inline 32 | #endif 33 | #ifndef C_ARRAY_SIZE_TYPE 34 | #define C_ARRAY_SIZE_TYPE uint32_t 35 | #endif 36 | 37 | #define DECLARE_C_ARRAY(__type, __name, __page, __args...) \ 38 | enum { __name##_page_size = __page }; \ 39 | typedef __type __name##_element_t; \ 40 | typedef C_ARRAY_SIZE_TYPE __name##_count_t; \ 41 | typedef struct __name##_t {\ 42 | volatile __name##_count_t count;\ 43 | volatile __name##_count_t size;\ 44 | __name##_element_t * e;\ 45 | __args ;\ 46 | } __name##_t, *__name##_p; 47 | 48 | #define C_ARRAY_NULL { 0, 0, NULL } 49 | 50 | #define IMPLEMENT_C_ARRAY(__name) \ 51 | static const __name##_t __name##_zero = C_ARRAY_NULL; \ 52 | static C_ARRAY_INLINE \ 53 | void __name##_free(\ 54 | __name##_p a) \ 55 | {\ 56 | if (!a) return;\ 57 | if (a->e) free(a->e);\ 58 | a->count = a->size = 0;\ 59 | a->e = NULL;\ 60 | }\ 61 | static C_ARRAY_INLINE \ 62 | void __name##_clear(\ 63 | __name##_p a) \ 64 | {\ 65 | if (!a) return;\ 66 | a->count = 0;\ 67 | }\ 68 | static C_ARRAY_INLINE \ 69 | void __name##_realloc(\ 70 | __name##_p a, __name##_count_t size) \ 71 | {\ 72 | if (!a || a->size == size) return; \ 73 | if (size == 0) { if (a->e) free(a->e); a->e = NULL; } \ 74 | else a->e = realloc(a->e, size * sizeof(__name##_element_t));\ 75 | a->size = size; \ 76 | }\ 77 | static C_ARRAY_INLINE \ 78 | void __name##_trim(\ 79 | __name##_p a) \ 80 | {\ 81 | if (!a) return;\ 82 | __name##_count_t n = a->count + __name##_page_size;\ 83 | n -= (n % __name##_page_size);\ 84 | if (n != a->size)\ 85 | __name##_realloc(a, n);\ 86 | }\ 87 | static C_ARRAY_INLINE \ 88 | __name##_element_t * __name##_get_ptr(\ 89 | __name##_p a, __name##_count_t index) \ 90 | {\ 91 | if (!a) return NULL;\ 92 | if (index > a->count) index = a->count;\ 93 | return index < a->count ? a->e + index : NULL;\ 94 | }\ 95 | static C_ARRAY_INLINE \ 96 | __name##_count_t __name##_add(\ 97 | __name##_p a, __name##_element_t e) \ 98 | {\ 99 | if (!a) return 0;\ 100 | if (a->count + 1 >= a->size)\ 101 | __name##_realloc(a, a->size + __name##_page_size);\ 102 | a->e[a->count++] = e;\ 103 | return a->count;\ 104 | }\ 105 | static C_ARRAY_INLINE \ 106 | __name##_count_t __name##_insert(\ 107 | __name##_p a, __name##_count_t index, \ 108 | __name##_element_t * e, __name##_count_t count) \ 109 | {\ 110 | if (!a) return 0;\ 111 | if (index > a->count) index = a->count;\ 112 | if (a->count + count >= a->size) \ 113 | __name##_realloc(a, (((a->count + count) / __name##_page_size)+1) * __name##_page_size);\ 114 | if (index < a->count)\ 115 | memmove(&a->e[index + count], &a->e[index], \ 116 | (a->count - index + count) * sizeof(__name##_element_t));\ 117 | memmove(&a->e[index], e, count * sizeof(__name##_element_t));\ 118 | a->count += count;\ 119 | return a->count;\ 120 | }\ 121 | static C_ARRAY_INLINE \ 122 | __name##_count_t __name##_delete(\ 123 | __name##_p a, __name##_count_t index, __name##_count_t count) \ 124 | {\ 125 | if (!a) return 0;\ 126 | if (index > a->count) index = a->count;\ 127 | if (index + count > a->count) \ 128 | count = a->count - index;\ 129 | if (count && a->count - index) { \ 130 | memmove(&a->e[index], &a->e[index + count], \ 131 | (a->count - index - count) * sizeof(__name##_element_t));\ 132 | }\ 133 | a->count -= count;\ 134 | return a->count;\ 135 | } 136 | 137 | #endif /* __C_ARRAY_H___ */ 138 | -------------------------------------------------------------------------------- /src/c_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | c_utils.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | libc3 is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | libc3 is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with libc3. If not, see . 20 | */ 21 | 22 | 23 | #include "c_utils.h" 24 | 25 | void 26 | str_hash_init(str_hash_p h) 27 | { 28 | memset(h, 0, sizeof(*h)); 29 | } 30 | 31 | void 32 | str_hash_add( 33 | str_hash_p h, 34 | str_p k, 35 | void * v) 36 | { 37 | uint16_t hv = str_hash(k); 38 | hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; 39 | int inserti = bin->count; 40 | 41 | for (int i = 0; i < bin->count; i++) 42 | if (bin->e[i].key->hash >= hv) { 43 | inserti = i; 44 | break; 45 | } 46 | str_hashval_t n = { .key = str_dup(k), .val = v }; 47 | hashval_array_insert(bin, inserti, &n, 1); 48 | return; 49 | } 50 | 51 | void * 52 | str_hash_lookup( 53 | str_hash_p h, 54 | str_p k ) 55 | { 56 | uint16_t hv = str_hash(k); 57 | hashval_array_p bin = &h->bin[hv & (STR_HASH_SIZE-1)]; 58 | 59 | for (int i = 0; i < bin->count; i++) { 60 | uint16_t h = bin->e[i].key->hash; 61 | if (h == hv && !str_cmp(k, bin->e[i].key)) 62 | return bin->e[i].val; 63 | else if (h > hv) 64 | break; 65 | } 66 | return NULL; 67 | } 68 | -------------------------------------------------------------------------------- /src/c_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | c_utils.h 3 | 4 | Copyright 2008-11 Michel Pollet 5 | 6 | This program cross examines a root filesystem, loads all the elf 7 | files it can find, see what other library they load and then 8 | find the orphans. In then remove the orphans as "user" for it's 9 | dependencies and continues removing until everything has at least 10 | one user, OR is a program itself (ie, not a shared library) 11 | 12 | cross_linker is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU General Public License as published by 14 | the Free Software Foundation, either version 3 of the License, or 15 | (at your option) any later version. 16 | 17 | cross_linker is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU General Public License for more details. 21 | 22 | You should have received a copy of the GNU General Public License 23 | along with cross_linker. If not, see . 24 | */ 25 | 26 | #ifndef __C_UTILS_H__ 27 | #define __C_UTILS_H__ 28 | 29 | #ifndef NO_ALLOCA 30 | #include 31 | #endif 32 | #include "c_array.h" 33 | 34 | /******************************************************************** 35 | * CRC16 36 | ********************************************************************/ 37 | 38 | static uint8_t _crc16_lh[16] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 39 | 0x70, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1 }; 40 | static uint8_t _crc16_ll[16] = { 0x00, 0x21, 0x42, 0x63, 0x84, 0xA5, 0xC6, 41 | 0xE7, 0x08, 0x29, 0x4A, 0x6B, 0x8C, 0xAD, 0xCE, 0xEF }; 42 | 43 | static uint16_t crc16_u4(uint16_t crc, uint8_t val) 44 | { 45 | uint8_t h = crc >> 8, l = crc & 0xff; 46 | uint8_t t = (h >> 4) ^ val; 47 | 48 | // Shift the CRC Register left 4 bits 49 | h = (h << 4) | (l >> 4); 50 | l = l << 4; 51 | // Do the table lookups and XOR the result into the CRC Tables 52 | h = h ^ _crc16_lh[t]; 53 | l = l ^ _crc16_ll[t]; 54 | return (h << 8) | l; 55 | } 56 | 57 | static uint16_t crc16_update(uint16_t crc, uint8_t val) 58 | { 59 | crc = crc16_u4(crc, val >> 4); // High nibble first 60 | crc = crc16_u4(crc, val & 0x0F); // Low nibble 61 | return crc; 62 | } 63 | 64 | static uint16_t crc16_string(char * str) 65 | { 66 | uint16_t crc = 0xffff; 67 | while (*str) 68 | crc = crc16_update(crc, *str++); 69 | return crc; 70 | } 71 | 72 | /******************************************************************** 73 | * Hashed strings 74 | ********************************************************************/ 75 | 76 | #include 77 | typedef struct str_t { 78 | uint32_t hash : 16, rom : 1, len : 15; 79 | char str[0]; 80 | } str_t, *str_p; 81 | 82 | static inline str_p str_alloc(size_t len) 83 | { 84 | str_p r = (str_p)malloc(sizeof(*r) + len + 1); 85 | r->rom = r->hash = 0; r->len = len; 86 | return r; 87 | } 88 | static inline str_p str_new_i(const char *s, void * (*_alloc)(size_t)) 89 | { 90 | int l = s ? strlen(s) : 0; 91 | str_p r = (str_p)_alloc(sizeof(*r) + l + 1); 92 | r->hash = 0; r->len = l; 93 | if (s) 94 | strcpy(r->str, s); 95 | return r; 96 | } 97 | static inline void str_free(str_p s) 98 | { 99 | if (s && !s->rom) 100 | free(s); 101 | } 102 | static inline str_p str_new(const char *s) 103 | { 104 | return str_new_i(s, malloc); 105 | } 106 | static inline str_p str_dup(const str_p s) 107 | { 108 | size_t l = sizeof(*s) + s->len + 1; 109 | str_p r = (str_p)malloc(l); 110 | memcpy(r, s, l); 111 | return r; 112 | } 113 | #ifndef NO_ALLOCA 114 | static inline str_p str_anew(const char *s) 115 | { 116 | str_p r = str_new_i(s, alloca); 117 | r->rom = 1; 118 | return r; 119 | } 120 | static inline str_p str_adup(const str_p s) 121 | { 122 | size_t l = sizeof(*s) + s->len + 1; 123 | str_p r = (str_p)alloca(l); 124 | memcpy(r, s, l); 125 | r->rom = 1; 126 | return r; 127 | } 128 | #endif 129 | static inline uint16_t str_hash(str_p s) 130 | { 131 | if (!s->hash) s->hash = crc16_string(s->str); 132 | return s->hash; 133 | } 134 | static inline int str_cmp(str_p s1, str_p s2) 135 | { 136 | if (s1 == s2) return 1; 137 | if (s1->len != s2->len) return 1; 138 | str_hash(s1); 139 | str_hash(s2); 140 | return s1->hash == s2->hash ? strcmp(s1->str, s2->str) : 1; 141 | } 142 | 143 | /******************************************************************** 144 | * Hash table of strings. Key/value pair 145 | ********************************************************************/ 146 | 147 | typedef struct str_hashval_t { 148 | str_p key; 149 | void * val; 150 | } str_hashval_t; 151 | 152 | DECLARE_C_ARRAY(str_hashval_t, hashval_array, 16); 153 | IMPLEMENT_C_ARRAY(hashval_array); 154 | 155 | #ifndef STR_HASH_SIZE 156 | #define STR_HASH_SIZE 512 // use 9 bits of the 16 of the CRC 157 | #endif 158 | /* uses bins to store the strings as per their hash values */ 159 | typedef struct str_hash_t { 160 | hashval_array_t bin[STR_HASH_SIZE]; 161 | } str_hash_t, *str_hash_p; 162 | 163 | void 164 | str_hash_init( 165 | str_hash_p h); 166 | void 167 | str_hash_add( 168 | str_hash_p h, 169 | str_p k, 170 | void * v); 171 | 172 | void * 173 | str_hash_lookup( 174 | str_hash_p h, 175 | str_p k ); 176 | 177 | #endif /* __C_UTILS_H__ */ 178 | -------------------------------------------------------------------------------- /srcgl/c3gl.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3gl.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of simavr. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | #if __APPLE__ 23 | #define GL_GLEXT_PROTOTYPES 24 | #include 25 | #include 26 | #include 27 | #else 28 | #define GL_GLEXT_PROTOTYPES 29 | #include 30 | #include 31 | #include 32 | #endif 33 | #include 34 | 35 | 36 | #include "c3.h" 37 | #include "c3lines.h" 38 | #include "c3sphere.h" 39 | #include "c3light.h" 40 | #include "c3program.h" 41 | 42 | #include "c3driver_context.h" 43 | 44 | #include "c3gl.h" 45 | 46 | #define GLCHECK(_w) {_w; dumpError(#_w);} 47 | 48 | static int dumpError(const char * what) 49 | { 50 | GLenum e; 51 | int count = 0; 52 | while ((e = glGetError()) != GL_NO_ERROR) { 53 | printf("%s: %s\n", what, gluErrorString(e)); 54 | count++; 55 | } 56 | return count; 57 | } 58 | 59 | int 60 | c3gl_program_load( 61 | c3program_p p) 62 | { 63 | if (!p || p->pid || p->log) 64 | return -1; 65 | 66 | if (p->verbose) 67 | printf("%s loading %s\n", __func__, p->name->str); 68 | for (int si = 0; si < p->shaders.count && !p->log; si++) { 69 | c3shader_p s = &p->shaders.e[si]; 70 | 71 | if (p->verbose) 72 | printf("%s compiling shader %s\n", __func__, s->name->str); 73 | 74 | s->sid = C3APIO(glCreateShader(s->type)); 75 | const GLchar * pgm = s->shader->str; 76 | glShaderSource(C3APIO_INT(s->sid), 1, &pgm, NULL); 77 | 78 | glCompileShader(C3APIO_INT(s->sid)); 79 | 80 | GLint status; 81 | glGetShaderiv(C3APIO_INT(s->sid), GL_COMPILE_STATUS, &status); 82 | 83 | if (status != GL_FALSE) 84 | continue; 85 | 86 | GLint infoLogLength; 87 | glGetShaderiv(C3APIO_INT(s->sid), GL_INFO_LOG_LENGTH, &infoLogLength); 88 | 89 | p->log = str_alloc(infoLogLength); 90 | glGetShaderInfoLog(C3APIO_INT(s->sid), infoLogLength, NULL, p->log->str); 91 | 92 | fprintf(stderr, "%s compile %s: %s\n", __func__, s->name->str, p->log->str); 93 | break; 94 | } 95 | if (p->log) 96 | return -1; 97 | p->pid = C3APIO(glCreateProgram()); 98 | 99 | for (int si = 0; si < p->shaders.count && !p->log; si++) { 100 | c3shader_p s = &p->shaders.e[si]; 101 | 102 | glAttachShader(C3APIO_INT(p->pid), C3APIO_INT(s->sid)); 103 | } 104 | glLinkProgram(C3APIO_INT(p->pid)); 105 | 106 | GLint status; 107 | glGetProgramiv(C3APIO_INT(p->pid), GL_LINK_STATUS, &status); 108 | 109 | for (int si = 0; si < p->shaders.count && !p->log; si++) { 110 | c3shader_p s = &p->shaders.e[si]; 111 | 112 | glDetachShader(C3APIO_INT(p->pid), C3APIO_INT(s->sid)); 113 | glDeleteShader(C3APIO_INT(s->sid)); 114 | s->sid = 0; 115 | } 116 | 117 | if (status == GL_FALSE) { 118 | GLint infoLogLength; 119 | glGetProgramiv(C3APIO_INT(p->pid), GL_INFO_LOG_LENGTH, &infoLogLength); 120 | 121 | p->log = str_alloc(infoLogLength); 122 | 123 | glGetProgramInfoLog(C3APIO_INT(p->pid), infoLogLength, NULL, p->log->str); 124 | fprintf(stderr, "%s link %s: %s\n", __func__, p->name->str, p->log->str); 125 | 126 | goto error; 127 | } 128 | for (int pi = 0; pi < p->params.count; pi++) { 129 | c3program_param_p pa = &p->params.e[pi]; 130 | pa->pid = C3APIO(glGetUniformLocation(C3APIO_INT(p->pid), pa->name->str)); 131 | if (pa->pid == (c3apiobject_t)-1) { 132 | fprintf(stderr, "%s %s: parameter '%s' not found\n", 133 | __func__, p->name->str, pa->name->str); 134 | } else 135 | if (p->verbose) 136 | printf("%s %s load parameter [%d]'%s'=%d\n", __func__, 137 | p->name->str, pi, pa->name->str, 138 | C3APIO_INT(pa->pid)); 139 | } 140 | 141 | c3program_purge(p); 142 | return 0; 143 | error: 144 | c3program_purge(p); 145 | if (p->pid) 146 | glDeleteProgram(C3APIO_INT(p->pid)); 147 | p->pid = 0; 148 | return -1; 149 | } 150 | 151 | static void 152 | _c3_load_pixels( 153 | c3pixels_p pix) 154 | { 155 | GLuint mode = pix->rectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; 156 | if (!pix->texture) { 157 | pix->dirty = 1; 158 | GLuint texID = 0; 159 | GLCHECK(glEnable(mode)); 160 | 161 | glGenTextures(1, &texID); 162 | // if (pix->trace) 163 | printf("%s Creating texture %s %dx%d (id %d)\n", 164 | __func__, pix->name ? pix->name->str : "", pix->w, pix->h, texID); 165 | GLCHECK(glBindTexture(mode, texID)); 166 | glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 167 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 168 | glPixelStorei(GL_UNPACK_ROW_LENGTH, pix->row / pix->psize); 169 | GLCHECK(glTexParameteri(mode, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 170 | GLCHECK(glTexParameteri(mode, GL_TEXTURE_MIN_FILTER, 171 | pix->rectangle ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR)); 172 | // GLCHECK(glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)); 173 | // GLCHECK(glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)); 174 | // GLCHECK(glTexParameteri(mode, GL_TEXTURE_WRAP_S, GL_CLAMP)); 175 | // GLCHECK(glTexParameteri(mode, GL_TEXTURE_WRAP_T, GL_CLAMP)); 176 | if (!pix->rectangle) 177 | GLCHECK(glTexParameteri(mode, GL_GENERATE_MIPMAP, GL_TRUE)); 178 | #if 1 179 | GLfloat fLargest; 180 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); 181 | //printf("fLargest = %f\n", fLargest); 182 | GLCHECK(glTexParameterf(mode, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest)); 183 | #endif 184 | if (!pix->rectangle) 185 | GLCHECK(glGenerateMipmap(mode)); 186 | 187 | pix->texture = C3APIO(texID); 188 | pix->dirty = 1; 189 | } 190 | if (pix->dirty) { 191 | pix->dirty = 0; 192 | if (pix->base) { 193 | GLCHECK(glBindTexture(mode, C3APIO_INT(pix->texture))); 194 | static const struct { 195 | int gltype; 196 | int glsub; 197 | } map[] = { 198 | [C3PIXEL_ARGB] = { .gltype = GL_RGBA8, .glsub = GL_RGBA, }, 199 | [C3PIXEL_RGB] = { .gltype = GL_RGB8, .glsub = GL_RGB,}, 200 | [C3PIXEL_LUMINANCE] = { .gltype = GL_LUMINANCE, .glsub = GL_LUMINANCE,}, 201 | [C3PIXEL_ALPHA] = { .gltype = GL_ALPHA, .glsub = GL_ALPHA,}, 202 | }; 203 | 204 | glTexImage2D(mode, 0, 205 | map[pix->format].gltype, 206 | pix->w, pix->h, 0, 207 | map[pix->format].glsub, 208 | GL_UNSIGNED_BYTE, 209 | pix->base); 210 | dumpError("glTexImage2D"); 211 | if (!pix->rectangle) 212 | GLCHECK(glGenerateMipmap(mode)); 213 | if (!pix->mutable) 214 | c3pixels_purge(pix); 215 | } 216 | } 217 | } 218 | 219 | static void 220 | _c3_create_buffer( 221 | GLuint name, 222 | GLuint bufferType, 223 | void * data, 224 | size_t dataSize, 225 | GLuint * out) 226 | { 227 | glGenBuffers(1, out); 228 | 229 | GLCHECK(glBindBuffer(GL_ARRAY_BUFFER, *out)); 230 | GLCHECK(glBufferData(GL_ARRAY_BUFFER, 231 | dataSize, 232 | data, 233 | bufferType)); 234 | GLCHECK(glEnableClientState(name)); 235 | } 236 | 237 | static void 238 | _c3_load_vbo( 239 | c3geometry_p g) 240 | { 241 | if (!g->vertice.count) 242 | return ; 243 | if (!g->bid) { 244 | GLuint vao; 245 | glGenVertexArrays(1, &vao); 246 | g->bid = C3APIO(vao); 247 | } 248 | glBindVertexArray(C3APIO_INT(g->bid)); 249 | 250 | /* 251 | * Use 'realloc' on the array as it frees the data, but leaves 'count' 252 | * unchanged. We neec that for the vertices and the indexes, the others 253 | * can have a straight free() 254 | */ 255 | if (!g->vertice.buffer.bid && g->vertice.count) { 256 | GLuint bid; 257 | 258 | _c3_create_buffer(GL_VERTEX_ARRAY, 259 | g->vertice.buffer.mutable ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, 260 | g->vertice.e, g->vertice.count * sizeof(g->vertice.e[0]), 261 | &bid); 262 | glVertexPointer(3, GL_FLOAT, 0, (void*)0); 263 | g->vertice.buffer.bid = C3APIO(bid); 264 | if (!g->vertice.buffer.mutable && !g->debug) 265 | c3vertex_array_realloc(&g->vertice, 0); 266 | g->vertice.buffer.dirty = 0; 267 | } 268 | if (!g->textures.buffer.bid && g->textures.count) { 269 | GLuint bid; 270 | 271 | _c3_create_buffer(GL_TEXTURE_COORD_ARRAY, 272 | g->textures.buffer.mutable ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, 273 | g->textures.e, g->textures.count * sizeof(g->textures.e[0]), 274 | &bid); 275 | glTexCoordPointer(2, GL_FLOAT, 0, (void*)0); 276 | g->textures.buffer.bid = C3APIO(bid); 277 | if (!g->textures.buffer.mutable && !g->debug) 278 | c3tex_array_free(&g->textures); 279 | g->textures.buffer.dirty = 0; 280 | } 281 | if (!g->normals.buffer.bid && g->normals.count) { 282 | GLuint bid; 283 | 284 | _c3_create_buffer(GL_NORMAL_ARRAY, 285 | g->normals.buffer.mutable ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, 286 | g->normals.e, g->normals.count * sizeof(g->normals.e[0]), 287 | &bid); 288 | glNormalPointer(GL_FLOAT, 0, (void*) 0); 289 | g->normals.buffer.bid = C3APIO(bid); 290 | if (!g->normals.buffer.mutable && !g->debug) 291 | c3vertex_array_free(&g->normals); 292 | g->normals.buffer.dirty = 0; 293 | } 294 | if (!g->colorf.buffer.bid && g->colorf.count) { 295 | GLuint bid; 296 | 297 | _c3_create_buffer(GL_COLOR_ARRAY, 298 | g->colorf.buffer.mutable ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW, 299 | g->colorf.e, g->colorf.count * sizeof(g->colorf.e[0]), 300 | &bid); 301 | glColorPointer(4, GL_FLOAT, 0, (void*) 0); 302 | g->colorf.buffer.bid = C3APIO(bid); 303 | if (!g->colorf.buffer.mutable && !g->debug) 304 | c3colorf_array_free(&g->colorf); 305 | g->colorf.buffer.dirty = 0; 306 | } 307 | if (!g->indices.buffer.bid && g->indices.count) { 308 | GLuint bid; 309 | glGenBuffers(1, &bid); 310 | 311 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bid); 312 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, 313 | g->indices.count * sizeof(g->indices.e[0]), 314 | g->indices.e, 315 | g->indices.buffer.mutable ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); 316 | g->indices.buffer.bid = C3APIO(bid); 317 | if (!g->indices.buffer.mutable && !g->debug) 318 | c3indices_array_realloc(&g->indices, 0); 319 | g->indices.buffer.dirty = 0; 320 | } 321 | } 322 | 323 | static void 324 | _c3_geometry_project( 325 | c3context_p c, 326 | const struct c3driver_context_t * d, 327 | c3geometry_p g, 328 | c3mat4p m) 329 | { 330 | if (g->mat.texture) 331 | _c3_load_pixels(g->mat.texture); 332 | if (g->mat.program) 333 | c3gl_program_load(g->mat.program); 334 | 335 | switch(g->type.type) { 336 | case C3_SPHERE_TYPE: 337 | case C3_TRIANGLE_TYPE: 338 | case C3_LINES_TYPE: 339 | g->type.subtype = (c3apiobject_t)GL_TRIANGLES; 340 | break; 341 | case C3_TEXTURE_TYPE: { 342 | if (g->mat.texture) 343 | g->type.subtype = (c3apiobject_t)GL_TRIANGLE_FAN; 344 | } break; 345 | case C3_LIGHT_TYPE: { 346 | c3light_p l = (c3light_p)g; 347 | GLuint lid = GL_LIGHT0 + C3APIO_INT(l->light_id); 348 | if (l->color.specular.w > 0) 349 | glLightfv(lid, GL_SPECULAR, l->color.specular.n); 350 | if (l->color.ambiant.w > 0) 351 | glLightfv(lid, GL_AMBIENT, l->color.ambiant.n); 352 | } break; 353 | default: 354 | g->type.subtype = (c3apiobject_t)GL_TRIANGLES; 355 | break; 356 | } 357 | 358 | _c3_load_vbo(g); 359 | // _c3_update_vbo(g); 360 | 361 | glBindVertexArray(0); 362 | C3_DRIVER_INHERITED(c, d, geometry_project, g, m); 363 | } 364 | 365 | void // TODO cleanup 366 | c3_bbox_vertices( 367 | c3bbox_t * b, 368 | c3vec3 out[8]); 369 | 370 | /* 371 | * This id the meta function that draws a c3geometry. It looks for normals, 372 | * indices, textures and so on and call the glDrawArrays 373 | */ 374 | static void 375 | _c3_geometry_draw( 376 | c3context_p c, 377 | const struct c3driver_context_t *d, 378 | c3geometry_p g ) 379 | { 380 | c3mat4 eye = c3mat4_mul( 381 | &c3context_view_get(g->object->context)->cam.mtx, 382 | &g->object->world ); 383 | glLoadMatrixf(eye.n); 384 | 385 | #if 0 386 | if (g->name) 387 | printf("%s draw %s\n", __func__, g->name->str); 388 | else 389 | printf("%s draw %p\n", __func__, g); 390 | #endif 391 | glMaterialfv(GL_FRONT, GL_SHININESS, &g->mat.shininess); 392 | 393 | switch(g->type.type) { 394 | case C3_LIGHT_TYPE: { 395 | c3light_p l = (c3light_p)g; 396 | GLuint lid = GL_LIGHT0 + C3APIO_INT(l->light_id); 397 | glLightfv(lid, GL_POSITION, l->position.n); 398 | if (c3context_view_get(c)->type != C3_CONTEXT_VIEW_LIGHT) 399 | glEnable(lid); 400 | else 401 | glDisable(lid); 402 | } break; 403 | } 404 | if (!g->bid) { 405 | C3_DRIVER_INHERITED(c, d, geometry_draw, g); 406 | return; 407 | } 408 | glColor4fv(g->mat.color.n); 409 | dumpError("glColor"); 410 | 411 | GLCHECK(glBindVertexArray(C3APIO_INT(g->bid))); 412 | 413 | //glDisable(GL_TEXTURE_2D); 414 | if (g->mat.texture) { 415 | GLuint mode = g->mat.texture->rectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; 416 | glEnable(mode); 417 | if (g->mat.texture->trace) 418 | printf("%s view %d uses texture %s(%d) (%d tex)\n", 419 | __func__, c->current, g->mat.texture->name->str, 420 | C3APIO_INT(g->mat.texture->texture), 421 | g->textures.count); 422 | // printf("tex mode %d texture %d\n", g->mat.mode, g->mat.texture); 423 | dumpError("glEnable texture"); 424 | glBindTexture(mode, C3APIO_INT(g->mat.texture->texture)); 425 | dumpError("glBindTexture"); 426 | } 427 | if (g->mat.program) 428 | GLCHECK(glUseProgram(C3APIO_INT(g->mat.program->pid))); 429 | 430 | if (g->indices.buffer.bid) { 431 | GLCHECK(glDrawElements(C3APIO_INT(g->type.subtype), 432 | g->indices.count, GL_UNSIGNED_SHORT, 433 | (void*)NULL /*g->indices.e*/)); 434 | } else { 435 | glDrawArrays(C3APIO_INT(g->type.subtype), 0, g->vertice.count); 436 | } 437 | glBindVertexArray(0); 438 | 439 | if (g->mat.texture) 440 | glDisable(g->mat.texture->rectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D); 441 | if (g->mat.program) 442 | glUseProgram(0); 443 | 444 | if (g->debug) { 445 | if (g->normals.count) { 446 | for (int i = 0; i < g->vertice.count; i++) { 447 | c3vec3 o = g->vertice.e[i]; 448 | glBegin(GL_LINES); 449 | glColor4f(0.0,0.0,1.0,1.0); 450 | glVertex3fv(o.n); 451 | o = c3vec3_add(o, g->normals.e[i]); 452 | glColor4f(1.0,0.0,0.0,1.0); 453 | glVertex3fv(o.n); 454 | glEnd(); 455 | } 456 | } 457 | } 458 | if (0) { // debug bounding boxes 459 | c3vec3 v[8]; 460 | c3_bbox_vertices(&g->bbox, v); 461 | glColor4f(0.0,0.0,1.0,1.0); 462 | glPointSize(5); 463 | glBegin(GL_POINTS); 464 | for (int i = 0; i < 8; i++) { 465 | glVertex3fv(v[i].n); 466 | } 467 | glEnd(); 468 | } 469 | C3_DRIVER_INHERITED(c, d, geometry_draw, g); 470 | } 471 | 472 | const c3driver_context_t c3context_driver = { 473 | .geometry_project = _c3_geometry_project, 474 | .geometry_draw = _c3_geometry_draw, 475 | }; 476 | 477 | const struct c3driver_context_t * 478 | c3gl_getdriver() 479 | { 480 | return &c3context_driver; 481 | } 482 | -------------------------------------------------------------------------------- /srcgl/c3gl.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3gl.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of simavr. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3GL_H___ 24 | #define __C3GL_H___ 25 | 26 | const struct c3driver_context_t * 27 | c3gl_getdriver(); 28 | 29 | int 30 | c3gl_program_load( 31 | c3program_p p); 32 | 33 | #endif /* __C3GL_H___ */ 34 | -------------------------------------------------------------------------------- /srcgl/c3gl_fbo.c: -------------------------------------------------------------------------------- 1 | /* 2 | c3gl_fbo.c 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | #if __APPLE__ 23 | #define GL_GLEXT_PROTOTYPES 24 | #include 25 | #include 26 | #include 27 | #else 28 | #define GL_GLEXT_PROTOTYPES 29 | #include 30 | #include 31 | #include 32 | #endif 33 | #include 34 | #include 35 | 36 | #include "c3gl_fbo.h" 37 | 38 | 39 | #define GLCHECK(_w) {_w; dumpError(#_w);} 40 | static int dumpError(const char * what) 41 | { 42 | GLenum e; 43 | int count = 0; 44 | while ((e = glGetError()) != GL_NO_ERROR) { 45 | printf("%s: %s\n", what, gluErrorString(e)); 46 | count++; 47 | } 48 | return count; 49 | } 50 | 51 | int 52 | c3gl_fbo_create( 53 | c3gl_fbo_p b, 54 | c3vec2 size, 55 | uint32_t flags ) 56 | { 57 | memset(b, 0, sizeof(*b)); 58 | b->size = size; 59 | b->flags = flags; 60 | 61 | /* Texture */ 62 | GLCHECK(glActiveTexture(GL_TEXTURE0)); 63 | 64 | if (b->flags & (1 << C3GL_FBO_COLOR)) { 65 | GLuint tex; 66 | glGenTextures(1, &tex); 67 | glBindTexture(GL_TEXTURE_2D, tex); 68 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 69 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 70 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 71 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 72 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 73 | b->size.x, b->size.y, 0, 74 | GL_RGBA, GL_UNSIGNED_BYTE, NULL); 75 | glBindTexture(GL_TEXTURE_2D, 0); 76 | b->buffers[C3GL_FBO_COLOR].bid = C3APIO(tex); 77 | } 78 | 79 | /* Depth buffer */ 80 | if (b->flags & (1 << C3GL_FBO_DEPTH)) { 81 | GLuint rbo_depth; 82 | GLCHECK(glGenRenderbuffers(1, &rbo_depth)); 83 | glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth); 84 | GLCHECK(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 85 | b->size.x, b->size.y)); 86 | glBindRenderbuffer(GL_RENDERBUFFER, 0); 87 | b->buffers[C3GL_FBO_DEPTH].bid = C3APIO(rbo_depth); 88 | } 89 | 90 | if (b->flags & (1 << C3GL_FBO_DEPTH_TEX)) { 91 | GLuint depthTextureId; 92 | glGenTextures(1, &depthTextureId); 93 | glBindTexture(GL_TEXTURE_2D, depthTextureId); 94 | 95 | // does not make sense for depth texture. However, 96 | // next tutorial shows usage of GL_LINEAR and PCF. Using GL_NEAREST 97 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 98 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 99 | 100 | // Remove artefact on the edges of the shadowmap 101 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); 102 | glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); 103 | 104 | // This is to allow usage of shadow2DProj function in the shader 105 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); 106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); 107 | glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); 108 | // to debug depth buffer 109 | //glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ); 110 | //glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE ); 111 | // No need to force GL_DEPTH_COMPONENT24, drivers usually give you the max precision if available 112 | glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 113 | b->size.x, b->size.y, 114 | 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); 115 | glBindTexture(GL_TEXTURE_2D, 0); 116 | b->buffers[C3GL_FBO_DEPTH_TEX].bid = C3APIO(depthTextureId); 117 | } 118 | 119 | /* Framebuffer to link everything together */ 120 | GLuint fbo; 121 | GLCHECK(glGenFramebuffers(1, &fbo)); 122 | glBindFramebuffer(GL_FRAMEBUFFER, fbo); 123 | 124 | if (b->flags & (1 << C3GL_FBO_COLOR)) { 125 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 126 | GL_TEXTURE_2D, C3APIO_INT(b->buffers[C3GL_FBO_COLOR].bid), 0); 127 | // Set the list of draw buffers. 128 | GLenum DrawBuffers[2] = { GL_COLOR_ATTACHMENT0 }; 129 | glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers 130 | } else { 131 | glDrawBuffers(0, NULL); // "1" is the size of DrawBuffers 132 | glDrawBuffer(GL_NONE); 133 | glReadBuffer(GL_NONE); 134 | } 135 | 136 | if (b->flags & (1 << C3GL_FBO_DEPTH)) 137 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 138 | GL_RENDERBUFFER, C3APIO_INT(b->buffers[C3GL_FBO_DEPTH].bid)); 139 | 140 | if (b->flags & (1 << C3GL_FBO_DEPTH_TEX)) 141 | // attach the texture to FBO depth attachment point 142 | glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, 143 | GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 144 | C3APIO_INT(b->buffers[C3GL_FBO_DEPTH_TEX].bid), 0); 145 | 146 | b->fbo = C3APIO(fbo); 147 | 148 | GLenum status; 149 | if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) 150 | != GL_FRAMEBUFFER_COMPLETE) { 151 | fprintf(stderr, "%s: glCheckFramebufferStatus: error %d", __func__, (int)status); 152 | return -1 ; 153 | } 154 | 155 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 156 | return 0; 157 | } 158 | 159 | void 160 | c3gl_fbo_resize( 161 | c3gl_fbo_p b, 162 | c3vec2 size) 163 | { 164 | b->size = size; 165 | // Rescale FBO and RBO as well 166 | if (b->flags & (1 << C3GL_FBO_COLOR)) { 167 | glBindTexture(GL_TEXTURE_2D, C3APIO_INT(b->buffers[C3GL_FBO_COLOR].bid)); 168 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 169 | b->size.x, b->size.y, 0, 170 | GL_RGBA, GL_UNSIGNED_BYTE, NULL); 171 | glBindTexture(GL_TEXTURE_2D, 0); 172 | } 173 | 174 | if (b->flags & (1 << C3GL_FBO_DEPTH)) { 175 | glBindRenderbuffer(GL_RENDERBUFFER, C3APIO_INT(b->buffers[C3GL_FBO_DEPTH].bid)); 176 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 177 | b->size.x, b->size.y); 178 | glBindRenderbuffer(GL_RENDERBUFFER, 0); 179 | } 180 | } 181 | 182 | void 183 | c3gl_fbo_dispose( 184 | c3gl_fbo_p b ) 185 | { 186 | /* free_resources */ 187 | if (b->flags & (1 << C3GL_FBO_DEPTH)) { 188 | GLuint bid = C3APIO_INT(b->buffers[C3GL_FBO_DEPTH].bid); 189 | glDeleteRenderbuffers(1, &bid); 190 | } 191 | if (b->flags & (1 << C3GL_FBO_COLOR)) { 192 | GLuint bid = C3APIO_INT(b->buffers[C3GL_FBO_COLOR].bid); 193 | glDeleteTextures(1, &bid); 194 | } 195 | GLuint fbo = C3APIO_INT(b->fbo); 196 | glDeleteFramebuffers(1, &fbo); 197 | memset(b, 0, sizeof(*b)); 198 | } 199 | 200 | -------------------------------------------------------------------------------- /srcgl/c3gl_fbo.h: -------------------------------------------------------------------------------- 1 | /* 2 | c3gl_fbo.h 3 | 4 | Copyright 2008-2012 Michel Pollet 5 | 6 | This file is part of libc3. 7 | 8 | simavr is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | simavr is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with simavr. If not, see . 20 | */ 21 | 22 | 23 | #ifndef __C3GL_FBO_H___ 24 | #define __C3GL_FBO_H___ 25 | 26 | #include "c3types.h" 27 | 28 | enum { 29 | C3GL_FBO_COLOR = 0, 30 | C3GL_FBO_DEPTH, 31 | C3GL_FBO_DEPTH_TEX, 32 | C3GL_FBO_MAX, 33 | }; 34 | 35 | typedef struct c3gl_fbo_t { 36 | c3vec2 size; 37 | uint32_t flags; 38 | c3apiobject_t fbo; 39 | struct { 40 | c3apiobject_t bid; 41 | // ... ? 42 | } buffers[8]; 43 | } c3gl_fbo_t, *c3gl_fbo_p; 44 | 45 | 46 | int 47 | c3gl_fbo_create( 48 | c3gl_fbo_p b, 49 | c3vec2 size, 50 | uint32_t flags ); 51 | void 52 | c3gl_fbo_resize( 53 | c3gl_fbo_p b, 54 | c3vec2 size); 55 | void 56 | c3gl_fbo_dispose( 57 | c3gl_fbo_p b ); 58 | 59 | #endif /* __C3GL_FBO_H___ */ 60 | --------------------------------------------------------------------------------