├── Makefile ├── README.md ├── TODO.md ├── examples ├── chiptest.c ├── invaders.c ├── phystest.c ├── simple.c └── sprites.c ├── include ├── input.h ├── keys.h ├── lodepng.h ├── obj.h └── support.h ├── kazmath ├── README ├── aabb2.c ├── aabb2.h ├── aabb3.c ├── aabb3.h ├── kazmath.h ├── mat3.c ├── mat3.h ├── mat4.c ├── mat4.h ├── plane.c ├── plane.h ├── quaternion.c ├── quaternion.h ├── ray2.c ├── ray2.h ├── ray3.c ├── ray3.h ├── utility.c ├── utility.h ├── vec2.c ├── vec2.h ├── vec3.c ├── vec3.h ├── vec4.c └── vec4.h ├── lib └── .dummy ├── o └── .dummy ├── resources ├── models │ ├── alien.gbo │ ├── cube.gbo │ ├── ground.gbo │ ├── ship.gbo │ ├── shot.gbo │ └── sphere.gbo ├── shaders │ ├── glprint.frag │ ├── glprint.vert │ ├── particle.frag │ ├── particle.vert │ ├── sprite.frag │ ├── sprite.vert │ ├── textured.frag │ └── textured.vert └── textures │ ├── alien.png │ ├── ball.png │ ├── bigfont.png │ ├── biplane.png │ ├── cloud.png │ ├── dice.png │ ├── explosion.png │ ├── font.png │ ├── jupiter.png │ ├── shipv2.png │ ├── shot.png │ ├── swirl.png │ └── triplane.png ├── src ├── input.c ├── lodepng.c ├── obj.c └── support.c └── tools ├── fontexturer ├── build.xml ├── readme.txt └── src │ └── com │ └── logiklabs │ └── fontexturer │ ├── FontCellRenderer.java │ ├── Fontexturer.java │ └── PreviewPanel.java └── obj2opengl ├── LICENSE.txt ├── alien.obj ├── blend ├── alien.blend ├── cube.blend ├── ground.blend ├── shot.blend └── sphere.blend ├── builder.c ├── cube.obj ├── gbotest.c ├── ground.obj ├── makeGBO.sh ├── obj2opengl.pl ├── readme.txt ├── ship.obj ├── shot.obj └── sphere.obj /Makefile: -------------------------------------------------------------------------------- 1 | 2 | FLAGS= -g -c -std=gnu99 -Iinclude -Ikazmath 3 | LIBS=-lX11 -lEGL -lGLESv2 -lm 4 | 5 | 6 | # ok.... find all src/*.c replace all .c with .o then replace src\ with o\ - ...and breath 7 | # this is the framework itself without samples 8 | OBJ=$(shell find src/*.c | sed 's/\(.*\.\)c/\1o/g' | sed 's/src\//o\//g') 9 | 10 | #kazmath 11 | KAZ=$(shell find kazmath/*.c | sed 's/\(.*\.\)c/\1o/g' | sed 's/kazmath\/kazmath\//o\//g') 12 | 13 | all: invaders simple sprites 14 | 15 | test: 16 | echo $(KAZ) 17 | 18 | lib/libkazmath.a: $(KAZ) 19 | ar -cvq lib/libkazmath.a $(KAZ) 20 | 21 | kazmath/%.o: kazmath/%.c 22 | gcc $(FLAGS) $< -o $@ 23 | 24 | 25 | invaders: $(OBJ) o/invaders.o lib/libkazmath.a 26 | gcc $^ -o invaders $(LIBS) 27 | 28 | o/invaders.o: examples/invaders.c 29 | gcc $(FLAGS) $< -o $@ 30 | 31 | simple: $(OBJ) o/simple.o lib/libkazmath.a 32 | gcc $^ -o simple $(LIBS) 33 | 34 | o/simple.o: examples/simple.c 35 | gcc $(FLAGS) $< -o $@ 36 | 37 | phystest: $(OBJ) o/phystest.o lib/libkazmath.a 38 | gcc $^ -o phystest $(LIBS) ../ode/ode/src/.libs/libode.a -lstdc++ -lpthread 39 | 40 | o/phystest.o: examples/phystest.c 41 | gcc $(FLAGS) -I../ode/include $< -o $@ 42 | 43 | sprites: $(OBJ) o/sprites.o lib/libkazmath.a 44 | gcc $^ -o sprites $(LIBS) 45 | 46 | o/sprites.o: examples/sprites.c 47 | gcc $(FLAGS) $< -o $@ 48 | 49 | chiptest: $(OBJ) o/chiptest.o lib/libkazmath.a 50 | # gcc $^ -o chiptest $(LIBS) ../Chipmunk-6.1.1/src/libchipmunk.a 51 | # gcc $^ -o chiptest $(LIBS) ../Chipmunk-Physics/src/libchipmunk.a 52 | # gcc $^ -o chiptest $(LIBS) ../Chipmunk-7.0.1/src/libchipmunk.a 53 | gcc $^ -o chiptest $(LIBS) ../Chipmunk-7.0.2/src/libchipmunk.a 54 | 55 | o/chiptest.o: examples/chiptest.c 56 | # gcc $(FLAGS) -I../Chipmunk-6.1.1/include/chipmunk/ $< -o $@ 57 | # gcc $(FLAGS) -I../Chipmunk-Physics/include/chipmunk/ $< -o $@ 58 | # gcc $(FLAGS) -I../Chipmunk-7.0.1/include/chipmunk/ $< -o $@ 59 | gcc $(FLAGS) -I../Chipmunk-7.0.2/include/chipmunk/ $< -o $@ 60 | 61 | 62 | # used to create object files from all in src directory 63 | o/%.o: src/%.c 64 | gcc $(FLAGS) $< -o $@ 65 | 66 | 67 | 68 | 69 | # makes the code look nice! 70 | indent: 71 | astyle src/*.c include/*.h example/*.c 72 | 73 | 74 | # deletes all intermediate object files and all compiled 75 | # executables and automatic source backup files 76 | clean: 77 | rm -f o/*.o 78 | rm -f *~ 79 | rm -f src/*~ 80 | rm -f include/*~ 81 | rm -f examples/*~ 82 | rm -f resources/shaders/*~ 83 | 84 | clean-examples: 85 | rm -f invaders 86 | rm -f simple 87 | rm -f phystest 88 | rm -f sprites 89 | rm -f chiptest 90 | 91 | clean-all: clean clean-examples 92 | rm -f kazmath/*.o 93 | rm -f lib/libkazmath.a 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gles2framework 2 | 3 | ### a simple framework for OpenGLES 2.0 written in C 4 | 5 | *** Brief API notes at the end of the readme *** 6 | 7 | intended to help learning and tutorial writing 8 | 9 | Currently supports XORG (linux) Desktop using mesa GLES2.0 libs or various embedded 10 | platforms such as Allwinner A20 11 | 12 | dependencies, libEGL, libGLES (2.0), libode (0.15.2) for phystest, Chipmunk-7.0.2 for chiptest 13 | 14 | pkg-config, build-esentials and development libraries must be installed to compile the framework 15 | 16 | 17 | 18 | ##### raw mouse, keyboard and joystick on some embedded platforms 19 | 20 | When not using xwindows (ie via ssh) input including keyboard is now done entirely via 21 | the kernel evdev interface. 22 | 23 | you (might) need some udev rules 24 | 25 | make a file called /etc/udev/rules.d/99-evdev.rules (as root) it should contain the following 26 | 27 | KERNEL=="event*", NAME="input/%k", MODE="0640", GROUP="evdev" 28 | KERNEL=="mouse*", NAME="input/%k", MODE="0640", GROUP="evdev" 29 | KERNEL=="js*", NAME="input/%k", MODE="0640", GROUP="evdev" 30 | 31 | you need to add an new group and add your user account to the group (as root) 32 | 33 | groupadd evdev 34 | usermod -a -G evdev your_user_name 35 | 36 | you'll need to log out and back in again 37 | 38 | You can now run your programs from ssh and it will only use the targets attached 39 | usb keyboard rather than being confused with the ssh console 40 | 41 | editing files via ssh (sftp enabled editor) and compiling with a ssh console is the recommended 42 | way of developing with this framework if running with a small LCD and you have old tired eyes... 43 | 44 | 45 | ### file structure for external libraries 46 | 47 | some examples rely on external libraries they should be extracted and compiled in the same 48 | directory that you are working on the frame work like this: 49 | 50 | Chipmunk-7.0.2 gles2framework ode-0.16 51 | 52 | 53 | 54 | ### phystest (ode example) 55 | 56 | the rather hacky ODE example is only really for advanced users... 57 | (install Debian package version v0.11sp-dev (single precision package) 58 | 59 | If you want some of the extra bits of libODE (trimesh vs cylinder collisions - and other luxuries) then 60 | you can always compile ODE from source, see the ODE website for details 61 | 62 | suggested compile configuration for ODE 63 | 64 | ./configure --enable-libccd --with-box-cylinder=libccd --with-drawstuff=none --disable-demos 65 | 66 | this should by default provide trimesh collider etc as a static library 67 | 68 | 69 | ### chiptest (Chipmonk physics example) 70 | 71 | a quick example showing some balls falling on some invisible slopes, niether the sprites or the 72 | position of the slopes are scaled depending on the display size, so the sample will look 73 | different on different platforms and is a good example of why you should use scaled sizes! 74 | 75 | You only need compile a static library (the demos still use a *very* out of date 76 | version of GLFW (version 2 not actually avalible in a number of distros)) 77 | 78 | easiest way to bully cmake into working is just to remame the cmake file in the demo sub directory 79 | 80 | mv demo/CMakeLists.txt demo/CMakeLists.txt.xxx 81 | 82 | Once you have done this you can run make so the chipmunk library is available for the chiptest example 83 | 84 | 85 | ## Project structure 86 | 87 | | |description| 88 | |------------|--------------------------------------------------------------| 89 | |-include|source code include files| 90 | |-kazmath|source code and docs for the kazmath library| 91 | |-lib|kazmath compiled as static lib goes here. Other libs may follow. The framework may become a library| 92 | |-o|somewhere to put intermediate binary objects| 93 | |-src|source code for the framework| 94 | |-tools|a tool to package up 3d shapes and one to make 2d bitmap fonts| 95 | |-resources|holds textures, shaders and binary 3d models for the samples| 96 | |-examples|example code showing use of the framework| 97 | |Makefile|tells the compiler how to build the examples| 98 | |README.md|this file!| 99 | |TODO.md|aide memoire, ideas and inspiration for future development| 100 | 101 | #### kazmath 102 | there is no need to seperatly compile the kazmath library for your platform kazmath sources are now 103 | automatically compiled into a static library 104 | 105 | All though the source is unchanged I have deleted everthing except the C source 106 | the full distribution of kazmath is available at https://github.com/Kazade/kazmath 107 | 108 | 109 | #### obj2opengl 110 | 111 | In order to create code from OBJ files use this script, ensure you set the output file name to 112 | something like shape.c 113 | 114 | you will have to manually make shape.h it should look something like this 115 | 116 | extern float shapeVerts[]; 117 | extern float shapeTexCoords[]; 118 | extern float shapeNormals[]; 119 | extern unsigned int shapeNumVerts; 120 | 121 | in addition you will have to add a rule in the Makefile 122 | 123 | this method is depricated you should use a GBO instead... 124 | 125 | 126 | ### makeGBO script 127 | 128 | This is a binary file format, a kind of compiled OBJ file which can be used instead of embedding 129 | your objects in the executable (which can be wasteful in terms of ram) Once the object data is 130 | passed to the GPU the loaded data its based on is freed from memory... 131 | 132 | To make a gbo (Gles Binary Object) file place your wavefront object into the same directory, if 133 | for example the shape is called alien.obj then execute ./makeGBO.sh alien - note the lack of the 134 | file extension it will output alien.gbo which you can then copy to your resources directory - 135 | see loadObj command detailed below. makeGBO.sh relies on obj2opengl which must be in the same 136 | directory, it also needs at least the build esentials if going on another (artists) machine. 137 | 138 | ## support routines 139 | _____ 140 | 141 | __int loadPNG(const char *filename);__ 142 | 143 | loads a specified png file returning a GLES texture handle 144 | 145 | _____ 146 | 147 | __int makeContext();__ 148 | __int makeContextXY(int x, int y);__ 149 | 150 | creates a native window and sets up a GLES context within it 151 | makeContextXY takes dimesions for the window, giving -1,-1 will 152 | put the context in fullscreen mode, you can the use getDisplayWidth() / 153 | getDisplayHeight() to resize things according to this resolution if 154 | needed. 155 | 156 | _____ 157 | 158 | __void closeContext();__ 159 | 160 | closes GLES context and window 161 | 162 | _____ 163 | 164 | __GLuint create\_shader(const char *filename, GLenum type);__ 165 | 166 | returns a GLES shader handle from a file you must specify what type of shader it is either 167 | GL\_VERTEX\_SHADER or GL\_FRAGMENT\_SHADER 168 | 169 | _____ 170 | 171 | __GLuint getShaderLocation(int type, GLuint prog, const char *name);__ 172 | 173 | given a type of shaderAttrib or shaderUniform, a shader program handle and a name for the attrib 174 | or uniform it returns a location handle 175 | 176 | _____ 177 | 178 | __void initGlPrint(int w, int h);__ 179 | 180 | This initialises the resources used by the glPrintf you must supply the windows width and height 181 | 182 | _____ 183 | 184 | __font_t* createFont(const char* tpath,uint cbase,float tHeight,float tLines, int fWidth, int fHeight);__ 185 | 186 | tpath is the full path and of the texture for this font, cbase is the ascii code of the first character 187 | tHeight is the height in pixels of the texture, tLines specifies the number of lines in total the texture 188 | contains (I think there is a bug with this!) fWidth and fHeight are the width and height a character 189 | 190 | TODO freeFont to release a fonts resources... 191 | _____ 192 | 193 | __void glPrintf(float x, float y, font_t fnt, const char *fmt, ...);__ 194 | 195 | this behaves exactly like a normal printf except for the first two parameters which specify the starting coordinate 196 | you must specify a previously created font structure to print with 197 | 198 | _____ 199 | 200 | __void swapBuffers();__ 201 | 202 | In order isolate egl and native window handles use this routine instead of eglSwapBuffers 203 | _____ 204 | 205 | __int setSwapInterval(int);__ 206 | 207 | The number of frames EGL should wait before swapBuffers actually swaps the buffer, this freqently does 208 | nothing on many EGL implementations however... 209 | _____ 210 | 211 | __void doEvents();__ 212 | 213 | this should be called once a frame to update the key down boolean array and the mouse information 214 | 215 | _____ 216 | 217 | __int* getMouse();__ 218 | 219 | this returns a pointer to an array of 3 ints the first 2 are the x and y mouse position the 3rd int 220 | is a bit field reflecting the state of the mouse buttons 221 | 222 | _____ 223 | 224 | __bool* getKeys();__ 225 | 226 | this is an array of 256 bools, while a key is held down the coresponding bool is true, key values are defined in keys.h 227 | 228 | _____ 229 | 230 | *** deprecated may be removed in later version *** 231 | 232 | __int createObj(struct obj\_t *obj, int numVerts, float verts[], float txVert[], float norms[], char *vertShader, char *fragShader);__ 233 | 234 | pass an empty obj_t struct, the number of vertices and arrays of verts, texture coordinates and 235 | normals, finally you need to specify the file names for the vert and frag shaders 236 | 237 | _____ 238 | 239 | *** deprecated may be removed in later version *** 240 | 241 | __int createObjCopyShader(struct obj\_t *obj, int numVerts, float verts[], float txVert[], float norms[], struct obj\_t *sdrobj);__ 242 | 243 | this allows you to initialise a obj shape but using an existing obj's shader. 244 | 245 | _____ 246 | 247 | __void drawObj(struct obj\_t *obj, kmMat4 * combined, kmMat4 * mv, kmVec3 lightDir, kmVec3 viewDir);__ 248 | 249 | this draws an obj, you need to supply a combined model, view and projection matrices as well as a 250 | combined model, view matrix for the lighting, light and view direction vectors are also needed for 251 | lighting 252 | 253 | _____ 254 | 255 | __int getDisplayWidth();__ 256 | 257 | __int getDisplayHeight();__ 258 | 259 | returns full screen width and height, for now when not on Raspberry PI the "screen" is fixed to a 260 | 640x480 window 261 | 262 | _____ 263 | 264 | __int loadObj(struct obj\_t *obj,const char *objFile, char *vert, char *frag);__ 265 | 266 | __int loadObjCopyShader(struct obj\_t *obj,const char *objFile, struct obj\_t *sdrobj);__ 267 | 268 | these are basically the same as their createObj counterparts except the OBJ is loaded from a 269 | compiled binary wavefront object instead of from embedded data. 270 | 271 | _____ 272 | 273 | __void initSprite(int w, int h);__ 274 | 275 | __void drawSprite(float x, float y, float w, float h, float a, int tex);__ 276 | 277 | like glPrinf the sprite subsystem must be initialised before use, pass the dimensions of the screen. 278 | 279 | when drawing a sprite you specify where you want it (x & y) the size of the sprite (w & h) the rotation (a) and which texture to use (tex) 280 | 281 | _____ 282 | 283 | __void setMouseRelative(bool mode);__ 284 | 285 | if mode is true the mouse will report relative position changes only, this is handy for mouse 286 | look where you dont want the mouse constrained by the window. By default absolute mouse position 287 | is reported 288 | 289 | _____ 290 | 291 | __struct joystick\_t *getJoystick(int j);__ 292 | 293 | __void updateJoystick(struct joystick\_t *js);__ 294 | 295 | __void releaseJoystick(struct joystick\_t *js);__ 296 | 297 | to get a pointer to a joystick call getJoystick with the index of the joystick 0-7 298 | call this once only 299 | 300 | once a frame call updateJoystick you will then have (in the joystick structure) 301 | 302 | js->axis[0..7] upto 8 axes per joystick (signed short) 303 | js->buttons long - each bit represents a button 304 | 305 | when finished with a joystick you should call releaseJoystick to close its file 306 | handle and free the structures memory. 307 | 308 | _____ 309 | 310 | 311 | __void initPointClouds(const char* vertS, const char* fragS, float pntSize);__ 312 | 313 | __struct pointCloud\_t* createPointCloud(int size);__ 314 | 315 | __void drawPointCloud(struct pointCloud\_t* pntC,kmMat4* m);__ 316 | 317 | __void freePointCloud(struct pointCloud\_t* pntC);__ 318 | 319 | 320 | initPointClouds is used initialise the common shader used by the point clouds and set the size 321 | of the individual points (this can be changed on the fly later by changing a shader uniform) 322 | 323 | createPointCloud reserves space for the position and velocity components of each individual 324 | point in a cloud 325 | 326 | when drawing a point cloud you must pass the combined model/view/projection matrix in 327 | a similar manner to drawing obj shapes, note you must update the individual point positions 328 | optionally using the supplied velocity value for each point 329 | 330 | While it is ok to keep a point cloud around without drawing it for later use. 331 | When the resources used by the cloud need to be released call freePoint cloud 332 | this frees the point cloud structure itself and the associated points data 333 | 334 | _____ 335 | 336 | __void reProjectGlPrint(int w, int h)__ 337 | __void reProjectSprites(int w, int h)__ 338 | 339 | When glfw calls your window resize callback you should run these functions 340 | if you are using the apropriate facilities to inform them of the screen 341 | changes 342 | ___ 343 | 344 | __void resizePointCloudSprites(float s)__ 345 | 346 | This allows you to change the size of the point sprite's used - you would 347 | usually do this in the screen resize callback. 348 | 349 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | I would very much welcome people contacting me with ideas for this document. 2 | 3 | # Features to be added 4 | 5 | * shaders used by glprint etc should be released on exit (probably in 6 | closeContext) - we need to know what the user initialised 7 | 8 | * makeBestSellingFPSgame() function 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/chiptest.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include // usleep 6 | 7 | #include // matrix manipulation routines 8 | 9 | #include "support.h" // support routines 10 | #include "keys.h" // defines key indexes for key down boolean array 11 | #include "input.h" 12 | 13 | #include 14 | 15 | /* 16 | * 17 | * demostration of using chipmunk physics with 2d sprites 18 | * 19 | */ 20 | 21 | void render(); // func prototype 22 | 23 | // textures 24 | GLuint cloudTex,ballTex; 25 | float centreX,centreY,cloudW,cloudH; 26 | 27 | 28 | cpSpace *space; 29 | cpShape *ground,*ground2,*ground3; 30 | 31 | 32 | struct ball_t { 33 | cpShape *ballShape; 34 | cpBody *ballBody; 35 | }; 36 | 37 | #define max_balls 120 38 | 39 | struct ball_t balls[max_balls]; 40 | 41 | 42 | 43 | // matrices and combo matrices 44 | kmMat4 model, view, projection, mvp, vp, mv; 45 | 46 | int frame = 0; 47 | 48 | bool *keys; 49 | 50 | 51 | struct cloud_t { 52 | float x,y,w,h,v; 53 | }; 54 | 55 | #define max_clouds 20 56 | 57 | struct cloud_t clouds[max_clouds]; 58 | 59 | font_t *font1; 60 | 61 | int main() 62 | { 63 | 64 | 65 | // creates a window and GLES context 66 | if (makeContextXY(640,480) != 0) 67 | exit(-1); 68 | 69 | // all the shaders have at least texture unit 0 active so 70 | // activate it now and leave it active 71 | glActiveTexture(GL_TEXTURE0); 72 | 73 | cloudTex = loadPNG("resources/textures/cloud.png"); 74 | ballTex = loadPNG("resources/textures/ball.png"); 75 | 76 | 77 | glViewport(0, 0, getDisplayWidth(), getDisplayHeight()); 78 | 79 | // initialises glprint's matrix, shader and texture 80 | initGlPrint(getDisplayWidth(), getDisplayHeight()); 81 | font1=createFont("resources/textures/font.png",0,256,16,16,16); 82 | 83 | initSprite(getDisplayWidth(), getDisplayHeight()); 84 | 85 | centreX=((float)getDisplayWidth())/2.0; 86 | centreY=((float)getDisplayHeight())/2.0; 87 | cloudW=centreX/8.f; 88 | cloudH=centreY/8.f; // optional! scale sprite to screen 89 | 90 | for (int i=0; icentreY*2){ 170 | cpFloat x = rand_range(100,centreX*4); // ?? 171 | cpBodySetPosition(balls[i].ballBody, cpv(x, 0)); 172 | //?? cpBodyResetForces(balls[i].ballBody); 173 | cpBodySetForce(balls[i].ballBody, cpvzero); 174 | cpBodySetVelocity(balls[i].ballBody, cpv(0,0)); 175 | } 176 | } 177 | 178 | render(); // the render loop 179 | 180 | usleep(16000); // no need to run cpu/gpu full tilt 181 | 182 | } 183 | 184 | // we should really deallocate chipmonk stuff here 185 | // but we'll do the naughty and let the OS do it.... 186 | 187 | closeContext(); // tidy up 188 | 189 | return 0; 190 | } 191 | 192 | void render() 193 | { 194 | 195 | float rad; // radians of rotation based on frame counter 196 | 197 | // clear the colour (drawing) and depth sort back (offscreen) buffers 198 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 199 | 200 | // count the frame and base a rotation on it. 201 | frame++; 202 | rad = frame * (0.0175f); 203 | 204 | for (int i=0; i 9 | #include 10 | 11 | #include // matrix manipulation routines 12 | 13 | #include "support.h" // support routines 14 | #include "keys.h" // defines key indexes for key down boolean array 15 | #include "obj.h" // loading and displaying wavefront OBJ derived shapes 16 | #include "input.h" 17 | 18 | #include // usleep 19 | 20 | #include 21 | 22 | #include 23 | 24 | #define numObj 64 // 32 boxes, 32 spheres 25 | // TODO make a physics object struct with pointer to visual 26 | // geom and body id... 27 | dBodyID obj[numObj]; 28 | dGeomID geoms[numObj]; 29 | 30 | dWorldID world; 31 | dSpaceID space; 32 | dJointGroupID contactgroup; 33 | 34 | static void 35 | setTransform(const float pos[3], const float R[12], GLfloat * matrix) 36 | { 37 | matrix[0] = R[0]; 38 | matrix[1] = R[4]; 39 | matrix[2] = R[8]; 40 | matrix[3] = 0; 41 | matrix[4] = R[1]; 42 | matrix[5] = R[5]; 43 | matrix[6] = R[9]; 44 | matrix[7] = 0; 45 | matrix[8] = R[2]; 46 | matrix[9] = R[6]; 47 | matrix[10] = R[10]; 48 | matrix[11] = 0; 49 | matrix[12] = pos[0]; 50 | matrix[13] = pos[1]; 51 | matrix[14] = pos[2]; 52 | matrix[15] = 1; 53 | } 54 | 55 | #define MAX_CONTACTS 8 56 | 57 | static void nearCallback(void *data, dGeomID o1, dGeomID o2) 58 | { 59 | int i; 60 | // if (o1->body && o2->body) return; 61 | 62 | // exit without doing anything if the two bodies are connected by a joint 63 | dBodyID b1 = dGeomGetBody(o1); 64 | dBodyID b2 = dGeomGetBody(o2); 65 | if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) 66 | return; 67 | 68 | dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box 69 | for (i = 0; i < MAX_CONTACTS; i++) { 70 | contact[i].surface.mode = dContactBounce;// | dContactSoftCFM; 71 | contact[i].surface.mu = dInfinity; 72 | contact[i].surface.mu2 = 0; 73 | contact[i].surface.bounce = 0.4; 74 | contact[i].surface.bounce_vel = 0.4; 75 | //contact[i].surface.soft_cfm = 0.1; 76 | } 77 | int numc = dCollide(o1, o2, MAX_CONTACTS, &contact[0].geom, 78 | sizeof(dContact)); 79 | if (numc) { 80 | dMatrix3 RI; 81 | dRSetIdentity(RI); 82 | for (i = 0; i < numc; i++) { 83 | dJointID c = 84 | dJointCreateContact(world, contactgroup, contact + i); 85 | dJointAttach(c, b1, b2); 86 | } 87 | } 88 | 89 | } 90 | 91 | struct coll_t { 92 | int numVerts; 93 | float *verts; 94 | }; 95 | 96 | struct coll_t loadCollisionObj(const char *objFile) 97 | { 98 | FILE *pFile; 99 | struct coll_t r; 100 | r.numVerts = 0; 101 | r.verts = NULL; 102 | pFile = fopen(objFile, "rb"); 103 | if (pFile == NULL) { 104 | printf("Cant find open model - %s\n", objFile); 105 | return r; 106 | } 107 | unsigned int magic; 108 | int NumVerts; 109 | 110 | fread(&magic, 1, sizeof(unsigned int), pFile); 111 | if (magic != 0x614f4247) { 112 | printf("Does not appear to be a version 'a' GBO file\n"); 113 | return r; 114 | } 115 | fread(&NumVerts, 1, sizeof(unsigned int), pFile); 116 | 117 | float *Verts = malloc(sizeof(float) * 3 * NumVerts); 118 | fread(Verts, 1, sizeof(float) * 3 * NumVerts, pFile); 119 | 120 | r.numVerts = NumVerts; 121 | r.verts = Verts; 122 | return r; 123 | } 124 | 125 | 126 | 127 | void render(); // func prototype 128 | 129 | // obj shape textures 130 | GLuint cubeTex, groundTex,ballTex; 131 | font_t *font1; 132 | 133 | // structures holding various pointers and handles for obj shapes 134 | struct obj_t cubeObj, groundObj,ballObj; 135 | struct coll_t groundColl; 136 | dGeomID groundGeom; 137 | dTriMeshDataID triData; 138 | 139 | // matrices and combo matrices 140 | kmMat4 model, view, projection, mvp, vp, mv; 141 | kmVec3 lightDir; 142 | kmVec3 pEye, pCenter, pUp; // "camera" vectors 143 | // from position , target position and up direction 144 | 145 | int frame = 0; 146 | float *pos, *rot; 147 | bool *keys; 148 | struct timeval start,end; 149 | unsigned long elapsed; 150 | 151 | int main() 152 | { 153 | 154 | lightDir.x=.25; 155 | lightDir.y=.75; 156 | lightDir.z=-.25; 157 | kmVec3Normalize(&lightDir,&lightDir); 158 | 159 | // creates a window and GLES context 160 | if (makeContextXY(-1,-1) != 0) // -1,-1 for fullscreen 161 | exit(-1); 162 | 163 | // all the shaders have at least texture unit 0 active so 164 | // activate it now and leave it active 165 | glActiveTexture(GL_TEXTURE0); 166 | 167 | // The obj shapes and their textures are loaded 168 | cubeTex = loadPNG("resources/textures/dice.png"); 169 | 170 | loadObj(&cubeObj,"resources/models/cube.gbo", 171 | "resources/shaders/textured.vert", 172 | "resources/shaders/textured.frag"); 173 | 174 | groundTex = loadPNG("resources/textures/swirl.png"); 175 | loadObjCopyShader(&groundObj, "resources/models/ground.gbo", 176 | &cubeObj); 177 | 178 | ballTex = loadPNG("resources/textures/jupiter.png"); 179 | loadObjCopyShader(&ballObj, "resources/models/sphere.gbo", 180 | &cubeObj); 181 | 182 | 183 | kmMat4Identity(&view); 184 | 185 | pEye.x = 0; 186 | pEye.y = 14; 187 | pEye.z = 30; 188 | pCenter.x = 0; 189 | pCenter.y = 5; 190 | pCenter.z = 0; 191 | pUp.x = 0; 192 | pUp.y = 1; 193 | pUp.z = 0; 194 | 195 | kmMat4LookAt(&view, &pEye, &pCenter, &pUp); 196 | 197 | // projection matrix, as distance increases 198 | // the way the model is drawn is effected 199 | kmMat4Identity(&projection); 200 | kmMat4PerspectiveProjection(&projection, 45, 201 | (float) getDisplayWidth() / 202 | getDisplayHeight(), 0.1, 1000); 203 | 204 | glViewport(0, 0, getDisplayWidth(), getDisplayHeight()); 205 | 206 | // these two matrices are pre combined for use with each model render 207 | // the view and projection 208 | kmMat4Assign(&vp, &projection); 209 | kmMat4Multiply(&vp, &vp, &view); 210 | 211 | // initialises glprint's matrix, shader and texture 212 | initGlPrint(getDisplayWidth(), getDisplayHeight()); 213 | font1=createFont("resources/textures/font.png",0,256,16,16,16); 214 | // we don't want to draw the back of triangles 215 | // the blending is set up for glprint but disabled 216 | // while not in use 217 | glCullFace(GL_BACK); 218 | glEnable(GL_CULL_FACE); 219 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 220 | glDisable(GL_BLEND); 221 | glEnable(GL_DEPTH_TEST); 222 | glClearColor(0, 0.5, 1, 1); 223 | 224 | // count each frame 225 | int num_frames = 0; 226 | 227 | // set to true to leave main loop 228 | bool quit = false; 229 | 230 | // get a pointer to the key down array 231 | keys = getKeys(); 232 | 233 | 234 | dInitODE2(0); 235 | world = dWorldCreate(); 236 | space = dHashSpaceCreate(0); 237 | contactgroup = dJointGroupCreate(0); 238 | dWorldSetGravity(world, 0, -9.8, 0); 239 | dWorldSetCFM(world, 1e-5); 240 | //dCreatePlane (space,0,1,0,0); 241 | 242 | dMatrix3 R; 243 | dMass m; 244 | dMassSetZero(&m); 245 | //dMassSetBox(&m, 20, 0.5, 0.5, 0.5); 246 | for (int i = 0; i < numObj; i++) { 247 | obj[i] = dBodyCreate(world); 248 | if (i 15 | #include 16 | #include 17 | #include // usleep 18 | 19 | #include // matrix manipulation routines 20 | 21 | 22 | unsigned int cubeNumVerts = 36; 23 | 24 | float cubeVerts[] = { 25 | // f 1/1/1 2/2/1 3/3/1 26 | 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 27 | // f 1/1/1 3/3/1 4/4/1 28 | 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 29 | // f 5/5/2 8/6/2 7/7/2 30 | 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 31 | // f 5/5/2 7/7/2 6/8/2 32 | 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 33 | // f 1/9/3 5/10/3 6/11/3 34 | 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 35 | // f 1/9/3 6/11/3 2/12/3 36 | 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 37 | // f 2/13/4 6/14/4 7/15/4 38 | 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 39 | // f 2/13/4 7/15/4 3/16/4 40 | 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 41 | // f 3/17/5 7/18/5 8/19/5 42 | -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 43 | // f 3/17/5 8/19/5 4/20/5 44 | -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 45 | // f 5/21/6 1/22/6 4/23/6 46 | 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 47 | // f 5/21/6 4/23/6 8/24/6 48 | 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, 49 | }; 50 | 51 | float cubeNormals[] = { 52 | // f 1/1/1 2/2/1 3/3/1 53 | 0, -1, 0, 0, -1, 0, 0, -1, 0, 54 | // f 1/1/1 3/3/1 4/4/1 55 | 0, -1, 0, 0, -1, 0, 0, -1, 0, 56 | // f 5/5/2 8/6/2 7/7/2 57 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 58 | // f 5/5/2 7/7/2 6/8/2 59 | 0, 1, 0, 0, 1, 0, 0, 1, 0, 60 | // f 1/9/3 5/10/3 6/11/3 61 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 62 | // f 1/9/3 6/11/3 2/12/3 63 | 1, 0, 0, 1, 0, 0, 1, 0, 0, 64 | // f 2/13/4 6/14/4 7/15/4 65 | 0, 0, 1, 0, 0, 1, 0, 0, 1, 66 | // f 2/13/4 7/15/4 3/16/4 67 | 0, 0, 1, 0, 0, 1, 0, 0, 1, 68 | // f 3/17/5 7/18/5 8/19/5 69 | -1, 0, 0, -1, 0, 0, -1, 0, 0, 70 | // f 3/17/5 8/19/5 4/20/5 71 | -1, 0, 0, -1, 0, 0, -1, 0, 0, 72 | // f 5/21/6 1/22/6 4/23/6 73 | 0, 0, -1, 0, 0, -1, 0, 0, -1, 74 | // f 5/21/6 4/23/6 8/24/6 75 | 0, 0, -1, 0, 0, -1, 0, 0, -1, 76 | }; 77 | 78 | float cubeTexCoords[] = { 79 | // f 1/1/1 2/2/1 3/3/1 80 | 0.338526, 0.661474, 0.663522, 0.661474, 0.663522, 0.336478, 81 | // f 1/1/1 3/3/1 4/4/1 82 | 0.338526, 0.661474, 0.663522, 0.336478, 0.338526, 0.336478, 83 | // f 5/5/2 8/6/2 7/7/2 84 | 0.005288, 0.994712, 0.329713, 0.994712, 0.329713, 0.670287, 85 | // f 5/5/2 7/7/2 6/8/2 86 | 0.005288, 0.994712, 0.329713, 0.670287, 0.005288, 0.670287, 87 | // f 1/9/3 5/10/3 6/11/3 88 | 0.993727, 0.337651, 0.670272, 0.337651, 0.670272, 0.661106, 89 | // f 1/9/3 6/11/3 2/12/3 90 | 0.993727, 0.337651, 0.670272, 0.661106, 0.993727, 0.661106, 91 | // f 2/13/4 6/14/4 7/15/4 92 | 0.337449, 0.995051, 0.663207, 0.995051, 0.663338, 0.669686, 93 | // f 2/13/4 7/15/4 3/16/4 94 | 0.337449, 0.995051, 0.663338, 0.669686, 0.337711, 0.669162, 95 | // f 3/17/5 7/18/5 8/19/5 96 | 0.004502, 0.663184, 0.331568, 0.663184, 0.331568, 0.336118, 97 | // f 3/17/5 8/19/5 4/20/5 98 | 0.004502, 0.663184, 0.331568, 0.336118, 0.004408, 0.336118, 99 | // f 5/21/6 1/22/6 4/23/6 100 | 0.338744, 0.329745, 0.664703, 0.329745, 0.664703, 0.004606, 101 | // f 5/21/6 4/23/6 8/24/6 102 | 0.338744, 0.329745, 0.664703, 0.004606, 0.338744, 0.004606, 103 | }; 104 | 105 | 106 | 107 | 108 | void render(); // func prototype 109 | 110 | // obj shape textures 111 | GLuint cubeTex,ballTex; 112 | 113 | // structures holding various pointers and handles for obj shapes 114 | struct obj_t cubeObj,ballObj; 115 | 116 | // matrices and combo matrices 117 | kmMat4 model, view, projection, mvp, vp, mv; 118 | 119 | int frame = 0; 120 | kmVec3 lightDir, viewDir; // vectors for shader lighting 121 | kmVec3 pEye, pCenter, pUp; // "camera" vectors 122 | // from position , target position and up direction 123 | 124 | float camAng,lightAng; 125 | 126 | bool *keys; 127 | int *mouse; 128 | struct joystick_t *joy1; 129 | 130 | font_t *font1,*font2; 131 | 132 | int main() 133 | { 134 | 135 | 136 | // creates a window and GLES context 137 | if (makeContext() != 0) 138 | exit(-1); 139 | 140 | // all the shaders have at least texture unit 0 active so 141 | // activate it now and leave it active 142 | glActiveTexture(GL_TEXTURE0); 143 | 144 | // The obj shapes and their textures are loaded 145 | // directly from embedded data in the executable 146 | cubeTex = loadPNG("resources/textures/dice.png"); 147 | createObj(&cubeObj, cubeNumVerts, cubeVerts, cubeTexCoords, cubeNormals, 148 | "resources/shaders/textured.vert", "resources/shaders/textured.frag"); 149 | 150 | // embedding data can waste precious ram, loading from disk is more efficient 151 | // no redundant data left when verts transfered to GPU 152 | loadObjCopyShader(&ballObj,"resources/models/sphere.gbo",&cubeObj); 153 | ballTex = loadPNG("resources/textures/jupiter.png"); 154 | 155 | kmMat4Identity(&view); 156 | 157 | pEye.x = 0; 158 | pEye.y = 0; 159 | pEye.z = 5; 160 | pCenter.x = 0; 161 | pCenter.y = 0; 162 | pCenter.z = 0; 163 | pUp.x = 0; 164 | pUp.y = 1; 165 | pUp.z = 0; 166 | 167 | kmVec3Subtract(&viewDir,&pEye,&pCenter); 168 | kmVec3Normalize(&viewDir,&viewDir); 169 | 170 | kmMat4LookAt(&view, &pEye, &pCenter, &pUp); 171 | 172 | // these two matrices are pre combined for use with each model render 173 | // the view and projection 174 | kmMat4Assign(&vp, &projection); 175 | kmMat4Multiply(&vp, &vp, &view); 176 | 177 | // projection matrix, as distance increases 178 | // the way the model is drawn is effected 179 | kmMat4Identity(&projection); 180 | kmMat4PerspectiveProjection(&projection, 45, 181 | (float)getDisplayWidth() / getDisplayHeight(), 0.1, 10); 182 | 183 | glViewport(0, 0, getDisplayWidth(), getDisplayHeight()); 184 | 185 | // initialises glprint's matrix, shader and texture 186 | initGlPrint(getDisplayWidth(), getDisplayHeight()); 187 | 188 | font1=createFont("resources/textures/font.png",0,256,16,16,16); 189 | font2=createFont("resources/textures/bigfont.png",32,512,9.5,32,48); 190 | 191 | // we don't want to draw the back of triangles 192 | // the blending is set up for glprint but disabled 193 | // while not in use 194 | glCullFace(GL_BACK); 195 | glEnable(GL_CULL_FACE); 196 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 197 | glDisable(GL_BLEND); 198 | glEnable(GL_DEPTH_TEST); 199 | glClearColor(0, 0.5, 1, 1); 200 | 201 | // count each frame 202 | int num_frames = 0; 203 | 204 | // set to true to leave main loop 205 | bool quit = false; 206 | 207 | // get a pointer to the key down array 208 | keys = getKeys(); 209 | mouse = getMouse(); 210 | joy1=getJoystick(0); 211 | //setMouseRelative(true); 212 | 213 | while (!quit) { // the main loop 214 | 215 | doEvents(); // update mouse and key arrays 216 | updateJoystick(joy1); 217 | 218 | if (keys[KEY_ESC]) 219 | quit = true; // exit if escape key pressed 220 | 221 | if (keys[KEY_A]) camAng=camAng+1; 222 | if (keys[KEY_S]) camAng=camAng-1; 223 | if (keys[KEY_W]) lightAng=lightAng+1; 224 | if (keys[KEY_Q]) lightAng=lightAng-1; 225 | 226 | render(); // the render loop 227 | 228 | usleep(16000); // no need to run cpu/gpu full tilt 229 | 230 | } 231 | 232 | closeContext(); // tidy up 233 | releaseJoystick(joy1); 234 | 235 | return 0; 236 | } 237 | 238 | int rmx,rmy; 239 | 240 | void render() 241 | { 242 | 243 | float rad; // radians of rotation based on frame counter 244 | kmMat4 tmpM; 245 | 246 | // clear the colour (drawing) and depth sort back (offscreen) buffers 247 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 248 | 249 | // count the frame and base a rotation on it. 250 | frame++; 251 | rad = frame * (0.0175f); 252 | 253 | // rotate the light direction depending on lightAng 254 | lightDir.x=cos(lightAng/10.); 255 | lightDir.z=-1; 256 | lightDir.y=sin(lightAng/10.); 257 | kmVec3Normalize(&lightDir,&lightDir); 258 | 259 | 260 | pEye.x=cos(camAng/10.)*7.; 261 | pEye.z=sin(camAng/10.)*7.; 262 | pEye.y=1; 263 | 264 | // recalculate the view direction vector used by lighting 265 | kmVec3Subtract(&viewDir,&pEye,&pCenter); 266 | kmVec3Normalize(&viewDir,&viewDir); 267 | 268 | // update view matrix for new cam position 269 | kmMat4LookAt(&view, &pEye, &pCenter, &pUp); 270 | 271 | // these two matrices are pre combined for use with each model render 272 | // the view and projection 273 | kmMat4Assign(&vp, &projection); 274 | kmMat4Multiply(&vp, &vp, &view); 275 | 276 | 277 | // first set the model matrix with the models position (translation) 278 | // and rotation 279 | // as translation and rotation use different parts of the matrix 280 | // we can do both to the same matrix without having to multiply 281 | // (combine) two seperate matrices 282 | kmMat4Identity(&model); 283 | kmMat4Translation(&model, 1, 0, 0); 284 | //kmMat4RotationPitchYawRoll(&model, rad, rad * 1.5, rad * 2); 285 | kmMat4RotationYawPitchRoll(&tmpM, rad * 1.5, rad, rad * 2); 286 | kmMat4Multiply(&model,&model,&tmpM); 287 | 288 | // copy the combined view/projection matrix to the mvp matrix 289 | // to "reset" it 290 | // and then combine with the model matrix 291 | kmMat4Assign(&mvp, &vp); 292 | kmMat4Multiply(&mvp, &mvp, &model); // model, view, projection combined matrix 293 | 294 | // combine the view and model matrices 295 | kmMat4Assign(&mv, &view); 296 | kmMat4Multiply(&mv, &mv, &model); // view, model matrix for lighting 297 | 298 | glBindTexture(GL_TEXTURE_2D, cubeTex); 299 | drawObj(&cubeObj, &mvp, &mv,lightDir,viewDir); 300 | 301 | // ---- 302 | 303 | kmMat4Identity(&model); 304 | kmMat4Translation(&model, -1, 0, 0); 305 | //kmMat4RotationPitchYawRoll(&model, 0 , -rad, 0); 306 | kmMat4RotationYawPitchRoll(&tmpM, 0, -rad, 0); 307 | kmMat4Multiply(&model,&model,&tmpM); 308 | 309 | kmMat4Assign(&mvp, &vp); 310 | kmMat4Multiply(&mvp, &mvp, &model); // model, view, projection combined matrix 311 | kmMat4Assign(&mv, &view); 312 | kmMat4Multiply(&mv, &mv, &model); // view, model matrix for lighting 313 | 314 | glBindTexture(GL_TEXTURE_2D, ballTex); 315 | drawObj(&ballObj, &mvp, &mv,lightDir,viewDir); 316 | 317 | // ---- 318 | 319 | 320 | // see printf documentation for the formatting of variables... 321 | glPrintf(24, 24, font2, "frame=%i", frame); 322 | 323 | glPrintf(100, 260, font1, "mouse %i %i %i", mouse[0],mouse[1],mouse[2]); 324 | 325 | glPrintf(100, 280, font1, "joystick %i,%i %i",joy1->axis[0],joy1->axis[1],joy1->buttons); 326 | 327 | 328 | glPrintf(100, 320, font2, "abcABCqrsQRS123"); 329 | //rmx+=mouse[0]; 330 | //rmy+=mouse[1]; 331 | //glPrintf(100, 280, "%i %i", rmx,rmy); 332 | 333 | // swap the front (visible) buffer for the back (offscreen) buffer 334 | swapBuffers(); 335 | 336 | } 337 | -------------------------------------------------------------------------------- /examples/sprites.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include // usleep 6 | 7 | #include // matrix manipulation routines 8 | 9 | #include "support.h" // support routines 10 | #include "keys.h" // defines key indexes for key down boolean array 11 | #include "input.h" 12 | 13 | /* 14 | * 15 | * demostration of 2d sprites 16 | * 17 | * 18 | * (my apologies to Klaus ;) ) 19 | */ 20 | 21 | void render(); // func prototype 22 | 23 | // textures 24 | GLuint cloudTex,biTex,triTex; 25 | float centreX,centreY,cloudW,cloudH,planeW,planeH; 26 | 27 | font_t *font1; 28 | 29 | // matrices and combo matrices 30 | kmMat4 model, view, projection, mvp, vp, mv; 31 | 32 | int frame = 0; 33 | 34 | bool *keys; 35 | 36 | 37 | struct cloud_t { 38 | float x,y,w,h,v; 39 | }; 40 | 41 | #define max_clouds 20 42 | 43 | struct cloud_t clouds[max_clouds]; 44 | 45 | 46 | //float rand_range(float min,float max) { 47 | // return min + (max - min) * ((float)rand() / RAND_MAX) / 2.0; 48 | //} 49 | 50 | int main() 51 | { 52 | 53 | 54 | // creates a window and GLES context 55 | if (makeContext() != 0) 56 | exit(-1); 57 | 58 | // all the shaders have at least texture unit 0 active so 59 | // activate it now and leave it active 60 | glActiveTexture(GL_TEXTURE0); 61 | 62 | cloudTex = loadPNG("resources/textures/cloud.png"); 63 | biTex = loadPNG("resources/textures/biplane.png"); 64 | triTex = loadPNG("resources/textures/triplane.png"); 65 | 66 | 67 | glViewport(0, 0, getDisplayWidth(), getDisplayHeight()); 68 | 69 | // initialises glprint's matrix, shader and texture 70 | initGlPrint(getDisplayWidth(), getDisplayHeight()); 71 | font1=createFont("resources/textures/font.png",0,256,16,16,16); 72 | initSprite(getDisplayWidth(), getDisplayHeight()); 73 | 74 | centreX=((float)getDisplayWidth())/2.0; 75 | centreY=((float)getDisplayHeight())/2.0; 76 | cloudW=centreX/8.f; 77 | cloudH=centreY/8.f; // optional! scale sprite to screen 78 | planeW=centreX/6.; 79 | planeH=planeW*.75; 80 | 81 | for (int i=0; i 3 | 4 | struct obj_t { 5 | GLuint vbo_vert, vbo_tex, vbo_norm; 6 | GLint vert_attrib, tex_attrib, norm_attrib; 7 | GLint mvp_uniform, mv_uniform, tex_uniform; 8 | GLint lightDir_uniform, viewDir_uniform; 9 | int num_verts; 10 | GLuint program; 11 | }; 12 | 13 | int createObj(struct obj_t *obj, int numVerts, float verts[], float txVert[], 14 | float norms[], char *vertShader, char *fragShader); 15 | int createObjCopyShader(struct obj_t *obj, int numVerts, float verts[], 16 | float txVert[], float norms[], struct obj_t *sdrobj); 17 | void drawObj(struct obj_t *obj, kmMat4 * combined, kmMat4 * mv, kmVec3 lightDir, kmVec3 viewDir); 18 | 19 | int loadObj(struct obj_t *obj,const char *objFile, char *vert, char *frag); 20 | int loadObjCopyShader(struct obj_t *obj,const char *objFile, struct obj_t *sdrobj); 21 | -------------------------------------------------------------------------------- /include/support.h: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include // close 9 | 10 | #ifndef GLchar 11 | #define GLchar char 12 | #endif 13 | 14 | enum shaderLocationType { shaderAttrib, shaderUniform }; 15 | GLuint getShaderLocation(int type, GLuint prog, const char *name); 16 | char *file_read(const char *filename); 17 | GLuint create_shader(const char *filename, GLenum type); 18 | void print_log(GLuint object); 19 | int loadPNG(const char *filename); 20 | int makeContext(); 21 | int makeContextXY(int x, int y); 22 | void closeContext(); 23 | void swapBuffers(); 24 | int setSwapInterval(int i); 25 | int getDisplayWidth(); 26 | int getDisplayHeight(); 27 | void initSprite(int w, int h); 28 | void drawSprite(float x, float y, float w, float h, float a, int tex); 29 | float rand_range(float min,float max); 30 | void reProjectGlPrint(int w,int h); 31 | void reProjectSprites(int w, int h); 32 | void resizePointCloudSprites(float s); 33 | struct timeval timeval_diff (struct timeval* x, struct timeval* y); 34 | 35 | struct pointCloud_t { 36 | int totalPoints; 37 | float *pos; 38 | float *vel; 39 | int vertBuf; 40 | float tick; 41 | }; 42 | 43 | void initPointClouds(const char* vertS, const char* fragS, float pntSize); 44 | struct pointCloud_t* createPointCloud(int size); 45 | void drawPointCloud(struct pointCloud_t* pntC,kmMat4* m); 46 | void freePointCloud(struct pointCloud_t* pntC); 47 | 48 | 49 | struct __fnt { 50 | unsigned int tex; 51 | unsigned int base; 52 | unsigned int vertBuf; 53 | unsigned int texBuf; 54 | float tHeight; 55 | float tLines; 56 | int fWidth; 57 | int fHeight; 58 | }; 59 | 60 | typedef struct __fnt font_t; 61 | 62 | font_t* createFont(const char* tpath,unsigned int cbase,float tHeight,float tLines, int fWidth, int fHeight); 63 | void initGlPrint(int w, int h); 64 | void glPrintf(float x, float y, font_t* fnt, const char *fmt, ...); 65 | 66 | 67 | -------------------------------------------------------------------------------- /kazmath/README: -------------------------------------------------------------------------------- 1 | Kazmath is a 3D math library aimed at game programming. It is released under the modified BSD license. 2 | 3 | Authors 4 | 5 | Luke Benstead 6 | Carsten Haubold 7 | 8 | License 9 | 10 | Copyright (c) 2008, Luke Benstead. 11 | All rights reserved. 12 | 13 | Redistribution and use in source and binary forms, with or without modification, 14 | are permitted provided that the following conditions are met: 15 | 16 | * Redistributions of source code must retain the above copyright notice, 17 | this list of conditions and the following disclaimer. 18 | * Redistributions in binary form must reproduce the above copyright notice, 19 | this list of conditions and the following disclaimer in the documentation 20 | and/or other materials provided with the distribution. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | -------------------------------------------------------------------------------- /kazmath/aabb2.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "aabb2.h" 27 | 28 | 29 | /** 30 | Initializes the AABB around a central point. If centre is NULL then the origin 31 | is used. Returns pBox. 32 | */ 33 | kmAABB2* kmAABB2Initialize( kmAABB2* pBox, const kmVec2* centre, const kmScalar width, const kmScalar height, const kmScalar depth) { 34 | if(!pBox) return 0; 35 | 36 | kmVec2 origin; 37 | kmVec2* point = centre ? (kmVec2*) centre : &origin; 38 | kmVec2Fill(&origin, .0f, .0f); 39 | 40 | pBox->min.x = point->x - (width / 2); 41 | pBox->min.y = point->y - (height / 2); 42 | 43 | pBox->max.x = point->x + (width / 2); 44 | pBox->max.y = point->y + (height / 2); 45 | 46 | return pBox; 47 | } 48 | 49 | /** 50 | * Makes sure that min corresponds to the minimum values and max 51 | * to the maximum 52 | */ 53 | kmAABB2* kmAABB2Sanitize(kmAABB2* pOut, const kmAABB2* pIn) 54 | { 55 | if( pIn->min.x <= pIn->max.x ){ 56 | pOut->min.x = pIn->min.x; 57 | pOut->max.x = pIn->max.x; 58 | }else{ 59 | pOut->min.x = pIn->max.x; 60 | pOut->max.x = pIn->min.x; 61 | } 62 | 63 | if( pIn->min.y <= pIn->max.y ){ 64 | pOut->min.y = pIn->min.y; 65 | pOut->max.y = pIn->max.y; 66 | }else{ 67 | pOut->min.y = pIn->max.y; 68 | pOut->max.y = pIn->min.y; 69 | } 70 | 71 | return pOut; 72 | } 73 | 74 | /** 75 | * Returns KM_TRUE if point is in the specified AABB, returns 76 | * KM_FALSE otherwise. 77 | */ 78 | int kmAABB2ContainsPoint(const kmAABB2* pBox, const kmVec2* pPoint) 79 | { 80 | if(pPoint->x >= pBox->min.x && pPoint->x <= pBox->max.x && 81 | pPoint->y >= pBox->min.y && pPoint->y <= pBox->max.y ) { 82 | return KM_TRUE; 83 | } 84 | 85 | return KM_FALSE; 86 | } 87 | 88 | /** 89 | * Assigns pIn to pOut, returns pOut. 90 | */ 91 | kmAABB2* kmAABB2Assign(kmAABB2* pOut, const kmAABB2* pIn) 92 | { 93 | kmVec2Assign(&pOut->min, &pIn->min); 94 | kmVec2Assign(&pOut->max, &pIn->max); 95 | return pOut; 96 | } 97 | 98 | kmAABB2* kmAABB2Translate( kmAABB2* pOut, const kmAABB2* pIn, const kmVec2 *translation ) 99 | { 100 | kmVec2Add( &(pOut->min), &(pIn->min), translation ); 101 | kmVec2Add( &(pOut->max), &(pIn->max), translation ); 102 | return pOut; 103 | } 104 | 105 | /** 106 | * Scales pIn by s, stores the resulting AABB in pOut. Returns pOut. 107 | * It modifies both points, so position of the box will be changed. Use 108 | * kmAABB2ScaleWithPivot to specify the origin of the scale. 109 | */ 110 | kmAABB2* kmAABB2Scale(kmAABB2* pOut, const kmAABB2* pIn, kmScalar s) 111 | { 112 | kmVec2Scale( &(pOut->max), &(pIn->max), s ); 113 | kmVec2Scale( &(pOut->min), &(pIn->min), s ); 114 | return pOut; 115 | } 116 | 117 | /** 118 | * Scales pIn by s, using pivot as the origin for the scale. 119 | */ 120 | kmAABB2* kmAABB2ScaleWithPivot( kmAABB2* pOut, const kmAABB2* pIn, const kmVec2 *pivot, kmScalar s ) 121 | { 122 | kmVec2 translate; 123 | translate.x = -pivot->x; 124 | translate.y = -pivot->y; 125 | 126 | kmAABB2Translate( pOut, pIn, &translate ); 127 | kmAABB2Scale( pOut, pIn, s ); 128 | kmAABB2Translate( pOut, pIn, pivot ); 129 | 130 | return pOut; 131 | } 132 | 133 | kmEnum kmAABB2ContainsAABB(const kmAABB2* container, const kmAABB2* to_check) { 134 | kmVec2 corners[4]; 135 | kmVec2Fill(&corners[0], to_check->min.x, to_check->min.y); 136 | kmVec2Fill(&corners[1], to_check->max.x, to_check->min.y); 137 | kmVec2Fill(&corners[2], to_check->max.x, to_check->max.y); 138 | kmVec2Fill(&corners[3], to_check->min.x, to_check->max.y); 139 | 140 | // since KM_TRUE equals 1 , we can count the number of contained points 141 | // by actually adding the results: 142 | int nContains = kmAABB2ContainsPoint( container, &corners[0] ) + 143 | kmAABB2ContainsPoint( container, &corners[1] ) + 144 | kmAABB2ContainsPoint( container, &corners[2] ) + 145 | kmAABB2ContainsPoint( container, &corners[3] ); 146 | 147 | if( nContains == 0 ){ 148 | return KM_CONTAINS_NONE; 149 | }else if( nContains < 4 ){ 150 | return KM_CONTAINS_PARTIAL; 151 | }else{ 152 | return KM_CONTAINS_ALL; 153 | } 154 | } 155 | 156 | kmScalar kmAABB2DiameterX(const kmAABB2* aabb) { 157 | return aabb->max.x - aabb->min.x; 158 | } 159 | 160 | kmScalar kmAABB2DiameterY(const kmAABB2* aabb) { 161 | return aabb->max.y - aabb->min.y; 162 | } 163 | 164 | kmVec2* kmAABB2Centre(const kmAABB2* aabb, kmVec2* pOut) { 165 | kmVec2Add(pOut, &aabb->min, &aabb->max); 166 | kmVec2Scale(pOut, pOut, 0.5); 167 | return pOut; 168 | } 169 | 170 | /** 171 | * @brief kmAABB2ExpandToContain 172 | * @param pOut - The resulting AABB 173 | * @param pIn - The original AABB 174 | * @param other - Another AABB that you want pIn expanded to contain 175 | * @return 176 | */ 177 | kmAABB2* kmAABB2ExpandToContain(kmAABB2* pOut, const kmAABB2* pIn, const kmAABB2* other) { 178 | kmAABB2 result; 179 | 180 | result.min.x = (pIn->min.x < other->min.x)?pIn->min.x:other->min.x; 181 | result.max.x = (pIn->max.x > other->max.x)?pIn->max.x:other->max.x; 182 | result.min.y = (pIn->min.y < other->min.y)?pIn->min.y:other->min.y; 183 | result.max.y = (pIn->max.y > other->max.y)?pIn->max.y:other->max.y; 184 | 185 | kmAABB2Assign(pOut, &result); 186 | 187 | return pOut; 188 | } -------------------------------------------------------------------------------- /kazmath/aabb2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef KAZMATH_AABB2D_H_INCLUDED 27 | #define KAZMATH_AABB2D_H_INCLUDED 28 | 29 | #include "vec2.h" 30 | #include "utility.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /** 37 | * A struture that represents an axis-aligned 38 | * bounding box. 39 | */ 40 | typedef struct kmAABB2 { 41 | kmVec2 min; /** The max corner of the box */ 42 | kmVec2 max; /** The min corner of the box */ 43 | } kmAABB2; 44 | 45 | 46 | kmAABB2* kmAABB2Initialize(kmAABB2* pBox, const kmVec2* centre, const kmScalar width, const kmScalar height, const kmScalar depth); 47 | kmAABB2* kmAABB2Sanitize(kmAABB2* pOut, const kmAABB2* pIn ); 48 | int kmAABB2ContainsPoint(const kmAABB2* pBox, const kmVec2* pPoint); 49 | kmAABB2* kmAABB2Assign(kmAABB2* pOut, const kmAABB2* pIn); 50 | kmAABB2* kmAABB2Translate(kmAABB2* pOut, const kmAABB2* pIn, const kmVec2 *translation ); 51 | kmAABB2* kmAABB2Scale(kmAABB2* pOut, const kmAABB2* pIn, kmScalar s); 52 | kmAABB2* kmAABB2ScaleWithPivot( kmAABB2* pOut, const kmAABB2* pIn, const kmVec2 *pivot, kmScalar s ); 53 | kmEnum kmAABB2ContainsAABB(const kmAABB2* container, const kmAABB2* to_check); 54 | kmScalar kmAABB2DiameterX(const kmAABB2* aabb); 55 | kmScalar kmAABB2DiameterY(const kmAABB2* aabb); 56 | kmVec2* kmAABB2Centre(const kmAABB2* aabb, kmVec2* pOut); 57 | kmAABB2* kmAABB2ExpandToContain(kmAABB2* pOut, const kmAABB2* pIn, const kmAABB2* other); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /kazmath/aabb3.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "aabb3.h" 27 | 28 | 29 | /** 30 | Initializes the AABB around a central point. If centre is NULL then the origin 31 | is used. Returns pBox. 32 | */ 33 | kmAABB3* kmAABB3Initialize(kmAABB3* pBox, const kmVec3* centre, const kmScalar width, const kmScalar height, const kmScalar depth) { 34 | if(!pBox) return 0; 35 | 36 | kmVec3 origin; 37 | kmVec3* point = centre ? (kmVec3*) centre : &origin; 38 | kmVec3Zero(&origin); 39 | 40 | pBox->min.x = point->x - (width / 2); 41 | pBox->min.y = point->y - (height / 2); 42 | pBox->min.z = point->z - (depth / 2); 43 | 44 | pBox->max.x = point->x + (width / 2); 45 | pBox->max.y = point->y + (height / 2); 46 | pBox->max.z = point->z + (depth / 2); 47 | 48 | return pBox; 49 | } 50 | 51 | /** 52 | * Returns KM_TRUE if point is in the specified AABB, returns 53 | * KM_FALSE otherwise. 54 | */ 55 | int kmAABB3ContainsPoint(const kmAABB3* pBox, const kmVec3* pPoint) 56 | { 57 | if(pPoint->x >= pBox->min.x && pPoint->x <= pBox->max.x && 58 | pPoint->y >= pBox->min.y && pPoint->y <= pBox->max.y && 59 | pPoint->z >= pBox->min.z && pPoint->z <= pBox->max.z) { 60 | return KM_TRUE; 61 | } 62 | 63 | return KM_FALSE; 64 | } 65 | 66 | /** 67 | * Assigns pIn to pOut, returns pOut. 68 | */ 69 | kmAABB3* kmAABB3Assign(kmAABB3* pOut, const kmAABB3* pIn) 70 | { 71 | kmVec3Assign(&pOut->min, &pIn->min); 72 | kmVec3Assign(&pOut->max, &pIn->max); 73 | return pOut; 74 | } 75 | 76 | /** 77 | * Scales pIn by s, stores the resulting AABB in pOut. Returns pOut 78 | */ 79 | kmAABB3* kmAABB3Scale(kmAABB3* pOut, const kmAABB3* pIn, kmScalar s) 80 | { 81 | assert(0 && "Not implemented"); 82 | return pOut; 83 | } 84 | 85 | kmBool kmAABB3IntersectsTriangle(kmAABB3* box, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3) { 86 | assert(0 && "Not implemented"); 87 | return KM_TRUE; 88 | } 89 | 90 | kmBool kmAABB3IntersectsAABB(const kmAABB3* box, const kmAABB3* other) { 91 | return kmAABB3ContainsAABB(box, other) != KM_CONTAINS_NONE; 92 | } 93 | 94 | kmEnum kmAABB3ContainsAABB(const kmAABB3* container, const kmAABB3* to_check) { 95 | kmVec3 corners[8]; 96 | kmEnum result = KM_CONTAINS_ALL; 97 | kmBool found = KM_FALSE; 98 | 99 | kmVec3Fill(&corners[0], to_check->min.x, to_check->min.y, to_check->min.z); 100 | kmVec3Fill(&corners[1], to_check->max.x, to_check->min.y, to_check->min.z); 101 | kmVec3Fill(&corners[2], to_check->max.x, to_check->max.y, to_check->min.z); 102 | kmVec3Fill(&corners[3], to_check->min.x, to_check->max.y, to_check->min.z); 103 | kmVec3Fill(&corners[4], to_check->min.x, to_check->min.y, to_check->max.z); 104 | kmVec3Fill(&corners[5], to_check->max.x, to_check->min.y, to_check->max.z); 105 | kmVec3Fill(&corners[6], to_check->max.x, to_check->max.y, to_check->max.z); 106 | kmVec3Fill(&corners[7], to_check->min.x, to_check->max.y, to_check->max.z); 107 | 108 | for(kmUchar i = 0; i < 8; ++i) { 109 | if(!kmAABB3ContainsPoint(container, &corners[i])) { 110 | result = KM_CONTAINS_PARTIAL; 111 | if(found) { 112 | /*If we previously found a corner that was within the container*/ 113 | /*We know that partial is the final result*/ 114 | return result; 115 | } 116 | } else { 117 | found = KM_TRUE; 118 | } 119 | } 120 | 121 | if(!found) { 122 | result = KM_CONTAINS_NONE; 123 | } 124 | 125 | return result; 126 | } 127 | 128 | kmScalar kmAABB3DiameterX(const kmAABB3* aabb) { 129 | return fabs(aabb->max.x - aabb->min.x); 130 | } 131 | 132 | kmScalar kmAABB3DiameterY(const kmAABB3* aabb) { 133 | return fabs(aabb->max.y - aabb->min.y); 134 | } 135 | 136 | kmScalar kmAABB3DiameterZ(const kmAABB3* aabb) { 137 | return fabs(aabb->max.z - aabb->min.z); 138 | } 139 | 140 | kmVec3* kmAABB3Centre(const kmAABB3* aabb, kmVec3* pOut) { 141 | kmVec3Add(pOut, &aabb->min, &aabb->max); 142 | kmVec3Scale(pOut, pOut, 0.5); 143 | return pOut; 144 | } 145 | 146 | /** 147 | * @brief kmAABB3ExpandToContain 148 | * @param pOut - The resulting AABB 149 | * @param pIn - The original AABB 150 | * @param other - Another AABB that you want pIn expanded to contain 151 | * @return 152 | */ 153 | kmAABB3* kmAABB3ExpandToContain(kmAABB3* pOut, const kmAABB3* pIn, const kmAABB3* other) { 154 | kmAABB3 result; 155 | 156 | result.min.x = (pIn->min.x < other->min.x)?pIn->min.x:other->min.x; 157 | result.max.x = (pIn->max.x > other->max.x)?pIn->max.x:other->max.x; 158 | result.min.y = (pIn->min.y < other->min.y)?pIn->min.y:other->min.y; 159 | result.max.y = (pIn->max.y > other->max.y)?pIn->max.y:other->max.y; 160 | result.min.z = (pIn->min.z < other->min.z)?pIn->min.z:other->min.z; 161 | result.max.z = (pIn->max.z > other->max.z)?pIn->max.z:other->max.z; 162 | 163 | kmAABB3Assign(pOut, &result); 164 | 165 | return pOut; 166 | } 167 | -------------------------------------------------------------------------------- /kazmath/aabb3.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef KAZMATH_AABB3D_H_INCLUDED 27 | #define KAZMATH_AABB3D_H_INCLUDED 28 | 29 | #include "vec3.h" 30 | #include "utility.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /** 37 | * A struture that represents an axis-aligned 38 | * bounding box. 39 | */ 40 | typedef struct kmAABB3 { 41 | kmVec3 min; /** The max corner of the box */ 42 | kmVec3 max; /** The min corner of the box */ 43 | } kmAABB3; 44 | 45 | 46 | kmAABB3* kmAABB3Initialize(kmAABB3* pBox, const kmVec3* centre, const kmScalar width, const kmScalar height, const kmScalar depth); 47 | int kmAABB3ContainsPoint(const kmAABB3* pBox, const kmVec3* pPoint); 48 | kmAABB3* kmAABB3Assign(kmAABB3* pOut, const kmAABB3* pIn); 49 | kmAABB3* kmAABB3Scale(kmAABB3* pOut, const kmAABB3* pIn, kmScalar s); 50 | kmBool kmAABB3IntersectsTriangle(kmAABB3* box, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3); 51 | kmBool kmAABB3IntersectsAABB(const kmAABB3* box, const kmAABB3* other); 52 | kmEnum kmAABB3ContainsAABB(const kmAABB3* container, const kmAABB3* to_check); 53 | kmScalar kmAABB3DiameterX(const kmAABB3* aabb); 54 | kmScalar kmAABB3DiameterY(const kmAABB3* aabb); 55 | kmScalar kmAABB3DiameterZ(const kmAABB3* aabb); 56 | kmVec3* kmAABB3Centre(const kmAABB3* aabb, kmVec3* pOut); 57 | kmAABB3* kmAABB3ExpandToContain(kmAABB3* pOut, const kmAABB3* pIn, const kmAABB3* other); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /kazmath/kazmath.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef KAZMATH_H_INCLUDED 27 | #define KAZMATH_H_INCLUDED 28 | 29 | #include "vec2.h" 30 | #include "vec3.h" 31 | #include "mat3.h" 32 | #include "mat4.h" 33 | #include "utility.h" 34 | #include "quaternion.h" 35 | #include "plane.h" 36 | #include "aabb2.h" 37 | #include "aabb3.h" 38 | #include "ray2.h" 39 | #include "ray3.h" 40 | 41 | #endif // KAZMATH_H_INCLUDED 42 | -------------------------------------------------------------------------------- /kazmath/mat3.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "utility.h" 31 | #include "vec3.h" 32 | #include "mat3.h" 33 | #include "mat4.h" 34 | #include "quaternion.h" 35 | 36 | kmMat3* kmMat3Fill(kmMat3* pOut, const kmScalar* pMat) 37 | { 38 | memcpy(pOut->mat, pMat, sizeof(kmScalar) * 9); 39 | return pOut; 40 | } 41 | 42 | /** Sets pOut to an identity matrix returns pOut*/ 43 | kmMat3* kmMat3Identity(kmMat3* pOut) 44 | { 45 | memset(pOut->mat, 0, sizeof(kmScalar) * 9); 46 | pOut->mat[0] = pOut->mat[4] = pOut->mat[8] = 1.0f; 47 | return pOut; 48 | } 49 | 50 | kmScalar kmMat3Determinant(const kmMat3* pIn) 51 | { 52 | kmScalar output; 53 | /* 54 | calculating the determinant following the rule of sarus, 55 | | 0 3 6 | 0 3 | 56 | m = | 1 4 7 | 1 4 | 57 | | 2 5 8 | 2 5 | 58 | now sum up the products of the diagonals going to the right (i.e. 0,4,8) 59 | and substract the products of the other diagonals (i.e. 2,4,6) 60 | */ 61 | 62 | output = pIn->mat[0] * pIn->mat[4] * pIn->mat[8] + pIn->mat[1] * pIn->mat[5] * pIn->mat[6] + pIn->mat[2] * pIn->mat[3] * pIn->mat[7]; 63 | output -= pIn->mat[2] * pIn->mat[4] * pIn->mat[6] + pIn->mat[0] * pIn->mat[5] * pIn->mat[7] + pIn->mat[1] * pIn->mat[3] * pIn->mat[8]; 64 | 65 | return output; 66 | } 67 | 68 | 69 | kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn) 70 | { 71 | pOut->mat[0] = pIn->mat[4] * pIn->mat[8] - pIn->mat[5] * pIn->mat[7]; 72 | pOut->mat[1] = pIn->mat[2] * pIn->mat[7] - pIn->mat[1] * pIn->mat[8]; 73 | pOut->mat[2] = pIn->mat[1] * pIn->mat[5] - pIn->mat[2] * pIn->mat[4]; 74 | pOut->mat[3] = pIn->mat[5] * pIn->mat[6] - pIn->mat[3] * pIn->mat[8]; 75 | pOut->mat[4] = pIn->mat[0] * pIn->mat[8] - pIn->mat[2] * pIn->mat[6]; 76 | pOut->mat[5] = pIn->mat[2] * pIn->mat[3] - pIn->mat[0] * pIn->mat[5]; 77 | pOut->mat[6] = pIn->mat[3] * pIn->mat[7] - pIn->mat[4] * pIn->mat[6]; 78 | pOut->mat[7] = pIn->mat[1] * pIn->mat[6] - pIn->mat[0] * pIn->mat[7]; 79 | pOut->mat[8] = pIn->mat[0] * pIn->mat[4] - pIn->mat[1] * pIn->mat[3]; 80 | 81 | return pOut; 82 | } 83 | 84 | kmMat3* kmMat3Inverse(kmMat3* pOut, const kmMat3* pM) 85 | { 86 | kmScalar determinate = kmMat3Determinant(pM); 87 | kmScalar detInv; 88 | kmMat3 adjugate; 89 | 90 | if(determinate == 0.0) 91 | { 92 | return NULL; 93 | } 94 | 95 | detInv = 1.0 / determinate; 96 | 97 | kmMat3Adjugate(&adjugate, pM); 98 | kmMat3MultiplyScalar(pOut, &adjugate, detInv); 99 | 100 | return pOut; 101 | } 102 | 103 | /** Returns true if pIn is an identity matrix */ 104 | kmBool kmMat3IsIdentity(const kmMat3* pIn) 105 | { 106 | static kmScalar identity [] = { 1.0f, 0.0f, 0.0f, 107 | 0.0f, 1.0f, 0.0f, 108 | 0.0f, 0.0f, 1.0f}; 109 | 110 | return (memcmp(identity, pIn->mat, sizeof(kmScalar) * 9) == 0); 111 | } 112 | 113 | /** Sets pOut to the transpose of pIn, returns pOut */ 114 | kmMat3* kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn) 115 | { 116 | kmScalar temp[9]; 117 | 118 | temp[0] = pIn->mat[0]; 119 | temp[1] = pIn->mat[3]; 120 | temp[2] = pIn->mat[6]; 121 | 122 | temp[3] = pIn->mat[1]; 123 | temp[4] = pIn->mat[4]; 124 | temp[5] = pIn->mat[7]; 125 | 126 | temp[6] = pIn->mat[2]; 127 | temp[7] = pIn->mat[5]; 128 | temp[8] = pIn->mat[8]; 129 | 130 | memcpy(&pOut->mat, temp, sizeof(kmScalar)*9); 131 | 132 | return pOut; 133 | } 134 | 135 | /* Multiplies pM1 with pM2, stores the result in pOut, returns pOut */ 136 | kmMat3* kmMat3MultiplyMat3(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2) 137 | { 138 | kmScalar mat[9]; 139 | 140 | const kmScalar *m1 = pM1->mat, *m2 = pM2->mat; 141 | 142 | mat[0] = m1[0] * m2[0] + m1[3] * m2[1] + m1[6] * m2[2]; 143 | mat[1] = m1[1] * m2[0] + m1[4] * m2[1] + m1[7] * m2[2]; 144 | mat[2] = m1[2] * m2[0] + m1[5] * m2[1] + m1[8] * m2[2]; 145 | 146 | mat[3] = m1[0] * m2[3] + m1[3] * m2[4] + m1[6] * m2[5]; 147 | mat[4] = m1[1] * m2[3] + m1[4] * m2[4] + m1[7] * m2[5]; 148 | mat[5] = m1[2] * m2[3] + m1[5] * m2[4] + m1[8] * m2[5]; 149 | 150 | mat[6] = m1[0] * m2[6] + m1[3] * m2[7] + m1[6] * m2[8]; 151 | mat[7] = m1[1] * m2[6] + m1[4] * m2[7] + m1[7] * m2[8]; 152 | mat[8] = m1[2] * m2[6] + m1[5] * m2[7] + m1[8] * m2[8]; 153 | 154 | memcpy(pOut->mat, mat, sizeof(kmScalar)*9); 155 | 156 | return pOut; 157 | } 158 | 159 | kmMat3* kmMat3MultiplyScalar(kmMat3* pOut, const kmMat3* pM, const kmScalar pFactor) 160 | { 161 | kmScalar mat[9]; 162 | int i; 163 | 164 | for(i = 0; i < 9; i++) 165 | { 166 | mat[i] = pM->mat[i] * pFactor; 167 | } 168 | 169 | memcpy(pOut->mat, mat, sizeof(kmScalar)*9); 170 | 171 | return pOut; 172 | } 173 | 174 | /** Assigns the value of pIn to pOut */ 175 | kmMat3* kmMat3AssignMat3(kmMat3* pOut, const kmMat3* pIn) 176 | { 177 | assert(pOut != pIn); /*You have tried to self-assign!!*/ 178 | 179 | memcpy(pOut->mat, pIn->mat, sizeof(kmScalar)*9); 180 | 181 | return pOut; 182 | } 183 | 184 | /** Returns true if the 2 matrices are equal (approximately) */ 185 | kmBool kmMat3AreEqual(const kmMat3* pMat1, const kmMat3* pMat2) 186 | { 187 | int i; 188 | if (pMat1 == pMat2) { 189 | return KM_TRUE; 190 | } 191 | 192 | for (i = 0; i < 9; ++i) { 193 | if(!kmAlmostEqual(pMat1->mat[i], pMat2->mat[i])) { 194 | return KM_FALSE; 195 | } 196 | } 197 | 198 | return KM_TRUE; 199 | } 200 | 201 | 202 | /** Builds a scaling matrix */ 203 | kmMat3* kmMat3FromScaling(kmMat3* pOut, const kmScalar x, const kmScalar y) 204 | { 205 | /* memset(pOut->mat, 0, sizeof(kmScalar) * 9);*/ 206 | kmMat3Identity(pOut); 207 | pOut->mat[0] = x; 208 | pOut->mat[4] = y; 209 | 210 | return pOut; 211 | } 212 | 213 | kmMat3* kmMat3FromTranslation(kmMat3* pOut, const kmScalar x, const kmScalar y) 214 | { 215 | /* memset(pOut->mat, 0, sizeof(kmScalar) * 9);*/ 216 | kmMat3Identity(pOut); 217 | pOut->mat[6] = x; 218 | pOut->mat[7] = y; 219 | /* pOut->mat[8] = 1.0;*/ 220 | 221 | return pOut; 222 | } 223 | 224 | 225 | kmMat3* kmMat3FromRotationQuaternion(kmMat3* pOut, const kmQuaternion* pIn) 226 | { 227 | if (!pIn || !pOut) { 228 | return NULL; 229 | } 230 | 231 | /* First row */ 232 | pOut->mat[0] = 1.0f - 2.0f * (pIn->y * pIn->y + pIn->z * pIn->z); 233 | pOut->mat[1] = 2.0f * (pIn->x * pIn->y - pIn->w * pIn->z); 234 | pOut->mat[2] = 2.0f * (pIn->x * pIn->z + pIn->w * pIn->y); 235 | 236 | /* Second row */ 237 | pOut->mat[3] = 2.0f * (pIn->x * pIn->y + pIn->w * pIn->z); 238 | pOut->mat[4] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->z * pIn->z); 239 | pOut->mat[5] = 2.0f * (pIn->y * pIn->z - pIn->w * pIn->x); 240 | 241 | /* Third row */ 242 | pOut->mat[6] = 2.0f * (pIn->x * pIn->z - pIn->w * pIn->y); 243 | pOut->mat[7] = 2.0f * (pIn->y * pIn->z + pIn->w * pIn->x); 244 | pOut->mat[8] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->y * pIn->y); 245 | 246 | return pOut; 247 | } 248 | 249 | kmMat3* kmMat3FromRotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians) 250 | { 251 | kmScalar rcos = cosf(radians); 252 | kmScalar rsin = sinf(radians); 253 | 254 | pOut->mat[0] = rcos + axis->x * axis->x * (1 - rcos); 255 | pOut->mat[1] = axis->z * rsin + axis->y * axis->x * (1 - rcos); 256 | pOut->mat[2] = -axis->y * rsin + axis->z * axis->x * (1 - rcos); 257 | 258 | pOut->mat[3] = -axis->z * rsin + axis->x * axis->y * (1 - rcos); 259 | pOut->mat[4] = rcos + axis->y * axis->y * (1 - rcos); 260 | pOut->mat[5] = axis->x * rsin + axis->z * axis->y * (1 - rcos); 261 | 262 | pOut->mat[6] = axis->y * rsin + axis->x * axis->z * (1 - rcos); 263 | pOut->mat[7] = -axis->x * rsin + axis->y * axis->z * (1 - rcos); 264 | pOut->mat[8] = rcos + axis->z * axis->z * (1 - rcos); 265 | 266 | return pOut; 267 | } 268 | 269 | kmMat3* kmMat3FromRotationAxisAngleInDegrees(kmMat3* pOut, const struct kmVec3* axis, const kmScalar degrees) { 270 | return kmMat3FromRotationAxisAngle(pOut, axis, kmDegreesToRadians(degrees)); 271 | } 272 | 273 | void kmMat3ExtractRotationAxisAngle(const kmMat3* pIn, kmVec3* pAxis, kmScalar* radians) 274 | { 275 | /*Surely not this easy?*/ 276 | kmQuaternion temp; 277 | kmQuaternionRotationMatrix(&temp, pIn); 278 | kmQuaternionToAxisAngle(&temp, pAxis, radians); 279 | } 280 | 281 | /** 282 | * Builds an X-axis rotation matrix and stores it in pOut, returns pOut 283 | */ 284 | kmMat3* kmMat3FromRotationX(kmMat3* pOut, const kmScalar radians) 285 | { 286 | /* 287 | | 1 0 0 | 288 | M = | 0 cos(A) -sin(A) | 289 | | 0 sin(A) cos(A) | 290 | 291 | */ 292 | 293 | pOut->mat[0] = 1.0f; 294 | pOut->mat[1] = 0.0f; 295 | pOut->mat[2] = 0.0f; 296 | 297 | pOut->mat[3] = 0.0f; 298 | pOut->mat[4] = cosf(radians); 299 | pOut->mat[5] = sinf(radians); 300 | 301 | pOut->mat[6] = 0.0f; 302 | pOut->mat[7] = -sinf(radians); 303 | pOut->mat[8] = cosf(radians); 304 | 305 | return pOut; 306 | } 307 | 308 | /** 309 | * Builds a rotation matrix using the rotation around the Y-axis 310 | * The result is stored in pOut, pOut is returned. 311 | */ 312 | kmMat3* kmMat3FromRotationY(kmMat3* pOut, const kmScalar radians) 313 | { 314 | /* 315 | | cos(A) 0 sin(A) | 316 | M = | 0 1 0 | 317 | | -sin(A) 0 cos(A) | 318 | */ 319 | 320 | pOut->mat[0] = cosf(radians); 321 | pOut->mat[1] = 0.0f; 322 | pOut->mat[2] = -sinf(radians); 323 | 324 | pOut->mat[3] = 0.0f; 325 | pOut->mat[4] = 1.0f; 326 | pOut->mat[5] = 0.0f; 327 | 328 | pOut->mat[6] = sinf(radians); 329 | pOut->mat[7] = 0.0f; 330 | pOut->mat[8] = cosf(radians); 331 | 332 | return pOut; 333 | } 334 | 335 | /** 336 | * Builds a rotation matrix around the Z-axis. The resulting 337 | * matrix is stored in pOut. pOut is returned. 338 | */ 339 | kmMat3* kmMat3FromRotationZ(kmMat3* pOut, const kmScalar radians) 340 | { 341 | /* 342 | | cos(A) -sin(A) 0 | 343 | M = | sin(A) cos(A) 0 | 344 | | 0 0 1 | 345 | */ 346 | 347 | pOut->mat[0] = cosf(radians); 348 | pOut->mat[1] =-sinf(radians); 349 | pOut->mat[2] = 0.0f; 350 | 351 | pOut->mat[3] = sinf(radians); 352 | pOut->mat[4] = cosf(radians); 353 | pOut->mat[5] = 0.0f; 354 | 355 | pOut->mat[6] = 0.0f; 356 | pOut->mat[7] = 0.0f; 357 | pOut->mat[8] = 1.0f; 358 | 359 | return pOut; 360 | } 361 | 362 | kmMat3* kmMat3FromRotationXInDegrees(kmMat3* pOut, const kmScalar degrees) { 363 | return kmMat3FromRotationX(pOut, kmDegreesToRadians(degrees)); 364 | } 365 | 366 | kmMat3* kmMat3FromRotationYInDegrees(kmMat3* pOut, const kmScalar degrees) { 367 | return kmMat3FromRotationY(pOut, kmDegreesToRadians(degrees)); 368 | } 369 | 370 | kmMat3* kmMat3FromRotationZInDegrees(kmMat3* pOut, const kmScalar degrees) { 371 | return kmMat3FromRotationZ(pOut, kmDegreesToRadians(degrees)); 372 | } 373 | 374 | kmVec3* kmMat3ExtractUpVec3(const kmMat3* pIn, kmVec3* pOut) { 375 | pOut->x = pIn->mat[3]; 376 | pOut->y = pIn->mat[4]; 377 | pOut->z = pIn->mat[5]; 378 | 379 | kmVec3Normalize(pOut, pOut); 380 | 381 | return pOut; 382 | } 383 | 384 | kmVec3* kmMat3ExtractRightVec3(const kmMat3* pIn, kmVec3* pOut) { 385 | pOut->x = pIn->mat[0]; 386 | pOut->y = pIn->mat[1]; 387 | pOut->z = pIn->mat[2]; 388 | 389 | kmVec3Normalize(pOut, pOut); 390 | 391 | return pOut; 392 | } 393 | 394 | kmVec3* kmMat3ExtractForwardVec3(const kmMat3* pIn, kmVec3* pOut) { 395 | pOut->x = pIn->mat[6]; 396 | pOut->y = pIn->mat[7]; 397 | pOut->z = pIn->mat[8]; 398 | 399 | kmVec3Normalize(pOut, pOut); 400 | 401 | return pOut; 402 | } 403 | 404 | kmMat3* kmMat3FromRotationLookAt(kmMat3* pOut, const kmVec3* pEye, 405 | const kmVec3* pCenter, const kmVec3* pUp) 406 | { 407 | kmVec3 f, up, s, u; 408 | 409 | kmVec3Subtract(&f, pCenter, pEye); 410 | kmVec3Normalize(&f, &f); 411 | 412 | kmVec3Assign(&up, pUp); 413 | kmVec3Normalize(&up, &up); 414 | 415 | kmVec3Cross(&s, &f, &up); 416 | kmVec3Normalize(&s, &s); 417 | 418 | kmVec3Cross(&u, &s, &f); 419 | kmVec3Normalize(&s, &s); 420 | 421 | pOut->mat[0] = s.x; 422 | pOut->mat[3] = s.y; 423 | pOut->mat[6] = s.z; 424 | 425 | pOut->mat[1] = u.x; 426 | pOut->mat[4] = u.y; 427 | pOut->mat[7] = u.z; 428 | 429 | pOut->mat[2] = -f.x; 430 | pOut->mat[5] = -f.y; 431 | pOut->mat[8] = -f.z; 432 | 433 | return pOut; 434 | } 435 | -------------------------------------------------------------------------------- /kazmath/mat3.h: -------------------------------------------------------------------------------- 1 | #ifndef HEADER_8E9D0ABA3C76B989 2 | #define HEADER_8E9D0ABA3C76B989 3 | 4 | /* 5 | Copyright (c) 2008, Luke Benstead. 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | 30 | #ifndef MAT3_H_INCLUDED 31 | #define MAT3_H_INCLUDED 32 | 33 | #include "utility.h" 34 | 35 | struct kmVec3; 36 | struct kmQuaternion; 37 | struct kmMat4; 38 | 39 | typedef struct kmMat3{ 40 | kmScalar mat[9]; 41 | } kmMat3; 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | kmMat3* kmMat3Fill(kmMat3* pOut, const kmScalar* pMat); 48 | kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn); 49 | kmMat3* kmMat3Identity(kmMat3* pOut); 50 | kmMat3* kmMat3Inverse(kmMat3* pOut, const kmMat3* pM); 51 | kmBool kmMat3IsIdentity(const kmMat3* pIn); 52 | kmMat3* kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn); 53 | kmScalar kmMat3Determinant(const kmMat3* pIn); 54 | kmBool kmMat3AreEqual(const kmMat3* pMat1, const kmMat3* pMat2); 55 | 56 | kmMat3* kmMat3AssignMat3(kmMat3* pOut, const kmMat3* pIn); 57 | 58 | kmMat3* kmMat3MultiplyMat3(kmMat3* pOut, const kmMat3* lhs, const kmMat3* rhs); 59 | kmMat3* kmMat3MultiplyScalar(kmMat3* pOut, const kmMat3* lhs, const kmScalar rhs); 60 | 61 | kmMat3* kmMat3FromRotationX(kmMat3* pOut, const kmScalar radians); 62 | kmMat3* kmMat3FromRotationY(kmMat3* pOut, const kmScalar radians); 63 | kmMat3* kmMat3FromRotationZ(kmMat3* pOut, const kmScalar radians); 64 | kmMat3* kmMat3FromRotationXInDegrees(kmMat3* pOut, const kmScalar degrees); 65 | kmMat3* kmMat3FromRotationYInDegrees(kmMat3* pOut, const kmScalar degrees); 66 | kmMat3* kmMat3FromRotationZInDegrees(kmMat3* pOut, const kmScalar degrees); 67 | kmMat3* kmMat3FromRotationQuaternion(kmMat3* pOut, const struct kmQuaternion* quaternion); 68 | kmMat3* kmMat3FromRotationLookAt(kmMat3* pOut, const struct kmVec3* pEye, const struct kmVec3* pCentre, const struct kmVec3* pUp); 69 | kmMat3* kmMat3FromScaling(kmMat3* pOut, const kmScalar x, const kmScalar y); 70 | kmMat3* kmMat3FromTranslation(kmMat3* pOut, const kmScalar x, const kmScalar y); 71 | kmMat3* kmMat3FromRotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, const kmScalar radians); 72 | kmMat3* kmMat3FromRotationAxisAngleInDegrees(kmMat3* pOut, const struct kmVec3* axis, const kmScalar degrees); 73 | 74 | void kmMat3ExtractRotationAxisAngle(const kmMat3* self, struct kmVec3* axis, kmScalar* radians); 75 | void kmMat3ExtractRotationAxisAngleInDegrees(const kmMat3* self, struct kmVec3* axis, kmScalar* degrees); 76 | 77 | struct kmVec3* kmMat3ExtractUpVec3(const kmMat3* self, struct kmVec3* pOut); 78 | struct kmVec3* kmMat3ExtractRightVec3(const kmMat3* self, struct kmVec3* pOut); 79 | struct kmVec3* kmMat3ExtractForwardVec3(const kmMat3* self, struct kmVec3* pOut); 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | #endif /* MAT3_H_INCLUDED */ 85 | 86 | 87 | #endif /* header guard */ 88 | -------------------------------------------------------------------------------- /kazmath/mat4.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef MAT4_H_INCLUDED 27 | #define MAT4_H_INCLUDED 28 | 29 | #include "utility.h" 30 | 31 | struct kmVec3; 32 | struct kmMat3; 33 | struct kmQuaternion; 34 | struct kmPlane; 35 | 36 | /* 37 | A 4x4 matrix 38 | 39 | | 0 4 8 12 | 40 | mat = | 1 5 9 13 | 41 | | 2 6 10 14 | 42 | | 3 7 11 15 | 43 | */ 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | typedef struct kmMat4 { 50 | kmScalar mat[16]; 51 | } kmMat4; 52 | 53 | kmMat4* kmMat4Fill(kmMat4* pOut, const kmScalar* pMat); 54 | 55 | 56 | kmMat4* kmMat4Identity(kmMat4* pOut); 57 | 58 | kmMat4* kmMat4Inverse(kmMat4* pOut, const kmMat4* pM); 59 | 60 | 61 | int kmMat4IsIdentity(const kmMat4* pIn); 62 | 63 | kmMat4* kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn); 64 | kmMat4* kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2); 65 | 66 | kmMat4* kmMat4Assign(kmMat4* pOut, const kmMat4* pIn); 67 | kmMat4* kmMat4AssignMat3(kmMat4* pOut, const struct kmMat3* pIn); 68 | 69 | int kmMat4AreEqual(const kmMat4* pM1, const kmMat4* pM2); 70 | 71 | kmMat4* kmMat4RotationX(kmMat4* pOut, const kmScalar radians); 72 | kmMat4* kmMat4RotationY(kmMat4* pOut, const kmScalar radians); 73 | kmMat4* kmMat4RotationZ(kmMat4* pOut, const kmScalar radians); 74 | kmMat4* kmMat4RotationYawPitchRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll); 75 | kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const struct kmQuaternion* pQ); 76 | kmMat4* kmMat4RotationTranslation(kmMat4* pOut, const struct kmMat3* rotation, const struct kmVec3* translation); 77 | kmMat4* kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z); 78 | kmMat4* kmMat4Translation(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z); 79 | 80 | struct kmVec3* kmMat4GetUpVec3(struct kmVec3* pOut, const kmMat4* pIn); 81 | struct kmVec3* kmMat4GetRightVec3(struct kmVec3* pOut, const kmMat4* pIn); 82 | struct kmVec3* kmMat4GetForwardVec3RH(struct kmVec3* pOut, const kmMat4* pIn); 83 | struct kmVec3* kmMat4GetForwardVec3LH(struct kmVec3* pOut, const kmMat4* pIn); 84 | 85 | kmMat4* kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY, kmScalar aspect, kmScalar zNear, kmScalar zFar); 86 | kmMat4* kmMat4OrthographicProjection(kmMat4* pOut, kmScalar left, kmScalar right, kmScalar bottom, kmScalar top, kmScalar nearVal, kmScalar farVal); 87 | kmMat4* kmMat4LookAt(kmMat4* pOut, const struct kmVec3* pEye, const struct kmVec3* pCenter, const struct kmVec3* pUp); 88 | 89 | kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const struct kmVec3* axis, kmScalar radians); 90 | struct kmMat3* kmMat4ExtractRotationMat3(const kmMat4* pIn, struct kmMat3* pOut); 91 | struct kmPlane* kmMat4ExtractPlane(struct kmPlane* pOut, const kmMat4* pIn, const kmEnum plane); 92 | struct kmVec3* kmMat4RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat4* pIn); 93 | struct kmVec3* kmMat4ExtractTranslationVec3(const kmMat4* pIn, struct kmVec3* pOut); 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | #endif /* MAT4_H_INCLUDED */ 98 | -------------------------------------------------------------------------------- /kazmath/plane.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "vec3.h" 30 | #include "vec4.h" 31 | #include "plane.h" 32 | #include "mat4.h" 33 | 34 | kmScalar kmPlaneDot(const kmPlane* pP, const kmVec4* pV) 35 | { 36 | /*a*x + b*y + c*z + d*w*/ 37 | 38 | return (pP->a * pV->x + 39 | pP->b * pV->y + 40 | pP->c * pV->z + 41 | pP->d * pV->w); 42 | } 43 | 44 | kmScalar kmPlaneDotCoord(const kmPlane* pP, const kmVec3* pV) 45 | { 46 | return (pP->a * pV->x + 47 | pP->b * pV->y + 48 | pP->c * pV->z + pP->d); 49 | } 50 | 51 | kmScalar kmPlaneDotNormal(const kmPlane* pP, const kmVec3* pV) 52 | { 53 | return (pP->a * pV->x + 54 | pP->b * pV->y + 55 | pP->c * pV->z); 56 | } 57 | 58 | kmPlane* kmPlaneFromNormalAndDistance(kmPlane* plane, const struct kmVec3* normal, const kmScalar dist) { 59 | plane->a = normal->x; 60 | plane->b = normal->y; 61 | plane->c = normal->z; 62 | plane->d = dist; 63 | 64 | return plane; 65 | } 66 | 67 | kmPlane* kmPlaneFromPointAndNormal(kmPlane* pOut, const kmVec3* pPoint, const kmVec3* pNormal) 68 | { 69 | /* 70 | Planea = Nx 71 | Planeb = Ny 72 | Planec = Nz 73 | Planed = −N⋅P 74 | */ 75 | 76 | 77 | pOut->a = pNormal->x; 78 | pOut->b = pNormal->y; 79 | pOut->c = pNormal->z; 80 | pOut->d = -kmVec3Dot(pNormal, pPoint); 81 | 82 | return pOut; 83 | } 84 | 85 | /** 86 | * Creates a plane from 3 points. The result is stored in pOut. 87 | * pOut is returned. 88 | */ 89 | kmPlane* kmPlaneFromPoints(kmPlane* pOut, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3) 90 | { 91 | /* 92 | v = (B − A) × (C − A) 93 | n = 1⁄|v| v 94 | Outa = nx 95 | Outb = ny 96 | Outc = nz 97 | Outd = −n⋅A 98 | */ 99 | 100 | kmVec3 n, v1, v2; 101 | kmVec3Subtract(&v1, p2, p1); /*Create the vectors for the 2 sides of the triangle*/ 102 | kmVec3Subtract(&v2, p3, p1); 103 | kmVec3Cross(&n, &v1, &v2); /*Use the cross product to get the normal*/ 104 | 105 | kmVec3Normalize(&n, &n); /*Normalize it and assign to pOut->m_N*/ 106 | 107 | pOut->a = n.x; 108 | pOut->b = n.y; 109 | pOut->c = n.z; 110 | pOut->d = kmVec3Dot(kmVec3Scale(&n, &n, -1.0), p1); 111 | 112 | return pOut; 113 | } 114 | 115 | /* Added by tlensing (http://icedcoffee-framework.org)*/ 116 | kmVec3* kmPlaneIntersectLine(kmVec3* pOut, const kmPlane* pP, const kmVec3* pV1, const kmVec3* pV2) 117 | { 118 | /* 119 | n = (Planea, Planeb, Planec) 120 | d = V − U 121 | Out = U − d⋅(Pd + n⋅U)⁄(d⋅n) [iff d⋅n ≠ 0] 122 | */ 123 | kmVec3 d; /* direction from V1 to V2*/ 124 | kmVec3Subtract(&d, pV2, pV1); /* Get the direction vector*/ 125 | 126 | kmVec3 n; /* plane normal*/ 127 | n.x = pP->a; 128 | n.y = pP->b; 129 | n.z = pP->c; 130 | kmVec3Normalize(&n, &n); 131 | 132 | kmScalar nt = -(n.x * pV1->x + n.y * pV1->y + n.z * pV1->z + pP->d); 133 | kmScalar dt = (n.x * d.x + n.y * d.y + n.z * d.z); 134 | 135 | if (fabs(dt) < kmEpsilon) { 136 | pOut = NULL; 137 | return pOut; /* line parallel or contained*/ 138 | } 139 | 140 | kmScalar t = nt/dt; 141 | pOut->x = pV1->x + d.x * t; 142 | pOut->y = pV1->y + d.y * t; 143 | pOut->z = pV1->z + d.z * t; 144 | 145 | return pOut; 146 | } 147 | 148 | kmPlane* kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP) 149 | { 150 | kmVec3 n; 151 | kmScalar l = 0; 152 | 153 | if (!pP->a && !pP->b && !pP->c) { 154 | pOut->a = pP->a; 155 | pOut->b = pP->b; 156 | pOut->c = pP->c; 157 | pOut->d = pP->d; 158 | return pOut; 159 | } 160 | 161 | n.x = pP->a; 162 | n.y = pP->b; 163 | n.z = pP->c; 164 | 165 | l = 1.0f / kmVec3Length(&n); /*Get 1/length*/ 166 | kmVec3Normalize(&n, &n); /*Normalize the vector and assign to pOut*/ 167 | 168 | pOut->a = n.x; 169 | pOut->b = n.y; 170 | pOut->c = n.z; 171 | 172 | pOut->d = pP->d * l; /*Scale the D value and assign to pOut*/ 173 | 174 | return pOut; 175 | } 176 | 177 | kmPlane* kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s) 178 | { 179 | assert(0 && "Not implemented"); 180 | return NULL; 181 | } 182 | 183 | /** 184 | * Returns POINT_INFRONT_OF_PLANE if pP is infront of pIn. Returns 185 | * POINT_BEHIND_PLANE if it is behind. Returns POINT_ON_PLANE otherwise 186 | */ 187 | KM_POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const kmVec3* pP) 188 | { 189 | /* This function will determine if a point is on, in front of, or behind*/ 190 | /* the plane. First we store the dot product of the plane and the point.*/ 191 | kmScalar distance = pIn->a * pP->x + pIn->b * pP->y + pIn->c * pP->z + pIn->d; 192 | 193 | /* Simply put if the dot product is greater than 0 then it is infront of it.*/ 194 | /* If it is less than 0 then it is behind it. And if it is 0 then it is on it.*/ 195 | if(distance > kmEpsilon) return POINT_INFRONT_OF_PLANE; 196 | if(distance < -kmEpsilon) return POINT_BEHIND_PLANE; 197 | 198 | return POINT_ON_PLANE; 199 | } 200 | 201 | kmPlane* kmPlaneExtractFromMat4(kmPlane* pOut, const struct kmMat4* pIn, kmInt row) { 202 | int scale = (row < 0) ? -1 : 1; 203 | row = abs(row) - 1; 204 | 205 | pOut->a = pIn->mat[3] + scale * pIn->mat[row]; 206 | pOut->b = pIn->mat[7] + scale * pIn->mat[row + 4]; 207 | pOut->c = pIn->mat[11] + scale * pIn->mat[row + 8]; 208 | pOut->d = pIn->mat[15] + scale * pIn->mat[row + 12]; 209 | 210 | return kmPlaneNormalize(pOut, pOut); 211 | } 212 | 213 | kmVec3* kmPlaneGetIntersection(kmVec3* pOut, const kmPlane* p1, const kmPlane* p2, const kmPlane* p3) { 214 | kmVec3 n1, n2, n3, cross; 215 | kmVec3 r1, r2, r3; 216 | double denom = 0; 217 | 218 | kmVec3Fill(&n1, p1->a, p1->b, p1->c); 219 | kmVec3Fill(&n2, p2->a, p2->b, p2->c); 220 | kmVec3Fill(&n3, p3->a, p3->b, p3->c); 221 | 222 | kmVec3Cross(&cross, &n2, &n3); 223 | 224 | denom = kmVec3Dot(&n1, &cross); 225 | 226 | if (kmAlmostEqual(denom, 0.0)) { 227 | return NULL; 228 | } 229 | 230 | kmVec3Cross(&r1, &n2, &n3); 231 | kmVec3Cross(&r2, &n3, &n1); 232 | kmVec3Cross(&r3, &n1, &n2); 233 | 234 | kmVec3Scale(&r1, &r1, -p1->d); 235 | kmVec3Scale(&r2, &r2, p2->d); 236 | kmVec3Scale(&r3, &r3, p3->d); 237 | 238 | kmVec3Subtract(pOut, &r1, &r2); 239 | kmVec3Subtract(pOut, pOut, &r3); 240 | kmVec3Scale(pOut, pOut, 1.0 / denom); 241 | 242 | /*p = -d1 * ( n2.Cross ( n3 ) ) – d2 * ( n3.Cross ( n1 ) ) – d3 * ( n1.Cross ( n2 ) ) / denom;*/ 243 | 244 | return pOut; 245 | } 246 | 247 | kmPlane* kmPlaneFill(kmPlane* plane, kmScalar a, kmScalar b, kmScalar c, kmScalar d) { 248 | plane->a = a; 249 | plane->b = b; 250 | plane->c = c; 251 | plane->d = d; 252 | 253 | return plane; 254 | } 255 | -------------------------------------------------------------------------------- /kazmath/plane.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef PLANE_H_INCLUDED 27 | #define PLANE_H_INCLUDED 28 | 29 | #define KM_PLANE_LEFT 0 30 | #define KM_PLANE_RIGHT 1 31 | #define KM_PLANE_BOTTOM 2 32 | #define KM_PLANE_TOP 3 33 | #define KM_PLANE_NEAR 4 34 | #define KM_PLANE_FAR 5 35 | 36 | #include "utility.h" 37 | 38 | struct kmVec3; 39 | struct kmVec4; 40 | struct kmMat4; 41 | 42 | typedef struct kmPlane { 43 | kmScalar a, b, c, d; 44 | } kmPlane; 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | typedef enum KM_POINT_CLASSIFICATION { 51 | POINT_BEHIND_PLANE = -1, 52 | POINT_ON_PLANE = 0, 53 | POINT_INFRONT_OF_PLANE = 1 54 | } KM_POINT_CLASSIFICATION; 55 | 56 | kmPlane* kmPlaneFill(kmPlane* plane, kmScalar a, kmScalar b, kmScalar c, kmScalar d); 57 | kmScalar kmPlaneDot(const kmPlane* pP, const struct kmVec4* pV); 58 | kmScalar kmPlaneDotCoord(const kmPlane* pP, const struct kmVec3* pV); 59 | kmScalar kmPlaneDotNormal(const kmPlane* pP, const struct kmVec3* pV); 60 | kmPlane* kmPlaneFromNormalAndDistance(kmPlane* plane, const struct kmVec3* normal, const kmScalar dist); 61 | kmPlane* kmPlaneFromPointAndNormal(kmPlane* pOut, const struct kmVec3* pPoint, const struct kmVec3* pNormal); 62 | kmPlane* kmPlaneFromPoints(kmPlane* pOut, const struct kmVec3* p1, const struct kmVec3* p2, const struct kmVec3* p3); 63 | struct kmVec3* kmPlaneIntersectLine(struct kmVec3* pOut, const kmPlane* pP, const struct kmVec3* pV1, const struct kmVec3* pV2); 64 | kmPlane* kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP); 65 | kmPlane* kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s); 66 | KM_POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const struct kmVec3* pP); /** Classifys a point against a plane */ 67 | 68 | kmPlane* kmPlaneExtractFromMat4(kmPlane* pOut, const struct kmMat4* pIn, kmInt row); 69 | struct kmVec3* kmPlaneGetIntersection(struct kmVec3* pOut, const kmPlane* p1, const kmPlane* p2, const kmPlane* p3); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* PLANE_H_INCLUDED */ 76 | -------------------------------------------------------------------------------- /kazmath/quaternion.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef QUATERNION_H_INCLUDED 27 | #define QUATERNION_H_INCLUDED 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "utility.h" 34 | 35 | struct kmMat4; 36 | struct kmMat3; 37 | struct kmVec3; 38 | 39 | typedef struct kmQuaternion { 40 | kmScalar x; 41 | kmScalar y; 42 | kmScalar z; 43 | kmScalar w; 44 | } kmQuaternion; 45 | 46 | int kmQuaternionAreEqual(const kmQuaternion* p1, const kmQuaternion* p2); 47 | kmQuaternion* kmQuaternionFill(kmQuaternion* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w); 48 | kmScalar kmQuaternionDot(const kmQuaternion* q1, const kmQuaternion* q2); /**< Returns the dot product of the 2 quaternions*/ 49 | 50 | kmQuaternion* kmQuaternionExp(kmQuaternion* pOut, const kmQuaternion* pIn); /**< Returns the exponential of the quaternion*/ 51 | 52 | /**< Makes the passed quaternion an identity quaternion*/ 53 | 54 | kmQuaternion* kmQuaternionIdentity(kmQuaternion* pOut); 55 | 56 | /**< Returns the inverse of the passed Quaternion*/ 57 | 58 | kmQuaternion* kmQuaternionInverse(kmQuaternion* pOut, const kmQuaternion* pIn); 59 | 60 | /**< Returns true if the quaternion is an identity quaternion*/ 61 | 62 | int kmQuaternionIsIdentity(const kmQuaternion* pIn); 63 | 64 | /**< Returns the length of the quaternion*/ 65 | 66 | kmScalar kmQuaternionLength(const kmQuaternion* pIn); 67 | 68 | /**< Returns the length of the quaternion squared (prevents a sqrt)*/ 69 | 70 | kmScalar kmQuaternionLengthSq(const kmQuaternion* pIn); 71 | 72 | /**< Returns the natural logarithm*/ 73 | 74 | kmQuaternion* kmQuaternionLn(kmQuaternion* pOut, const kmQuaternion* pIn); 75 | 76 | /**< Multiplies 2 quaternions together*/ 77 | 78 | kmQuaternion* kmQuaternionMultiply(kmQuaternion* pOut, const kmQuaternion* q1, const kmQuaternion* q2); 79 | 80 | /**< Normalizes a quaternion*/ 81 | 82 | kmQuaternion* kmQuaternionNormalize(kmQuaternion* pOut, const kmQuaternion* pIn); 83 | 84 | /**< Rotates a quaternion around an axis*/ 85 | 86 | kmQuaternion* kmQuaternionRotationAxisAngle(kmQuaternion* pOut, const struct kmVec3* pV, kmScalar angle); 87 | 88 | /**< Creates a quaternion from a rotation matrix*/ 89 | 90 | kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut, const struct kmMat3* pIn); 91 | 92 | /**< Create a quaternion from yaw, pitch and roll*/ 93 | 94 | kmQuaternion* kmQuaternionRotationPitchYawRoll(kmQuaternion* pOut, kmScalar pitch, kmScalar yaw, kmScalar roll); 95 | /**< Interpolate between 2 quaternions*/ 96 | kmQuaternion* kmQuaternionSlerp(kmQuaternion* pOut, const kmQuaternion* q1, const kmQuaternion* q2, kmScalar t); 97 | 98 | /**< Get the axis and angle of rotation from a quaternion*/ 99 | void kmQuaternionToAxisAngle(const kmQuaternion* pIn, struct kmVec3* pVector, kmScalar* pAngle); 100 | 101 | /**< Scale a quaternion*/ 102 | kmQuaternion* kmQuaternionScale(kmQuaternion* pOut, const kmQuaternion* pIn, kmScalar s); 103 | kmQuaternion* kmQuaternionAssign(kmQuaternion* pOut, const kmQuaternion* pIn); 104 | kmQuaternion* kmQuaternionAdd(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2); 105 | kmQuaternion* kmQuaternionSubtract(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2); 106 | 107 | kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const struct kmVec3* vec1, const struct kmVec3* vec2, const struct kmVec3* fallback); 108 | struct kmVec3* kmQuaternionMultiplyVec3(struct kmVec3* pOut, const kmQuaternion* q, const struct kmVec3* v); 109 | 110 | kmVec3* kmQuaternionGetUpVec3(kmVec3* pOut, const kmQuaternion* pIn); 111 | kmVec3* kmQuaternionGetRightVec3(kmVec3* pOut, const kmQuaternion* pIn); 112 | kmVec3* kmQuaternionGetForwardVec3RH(kmVec3* pOut, const kmQuaternion* pIn); 113 | kmVec3* kmQuaternionGetForwardVec3LH(kmVec3* pOut, const kmQuaternion* pIn); 114 | 115 | kmScalar kmQuaternionGetPitch(const kmQuaternion* q); 116 | kmScalar kmQuaternionGetYaw(const kmQuaternion* q); 117 | kmScalar kmQuaternionGetRoll(const kmQuaternion* q); 118 | 119 | kmQuaternion* kmQuaternionLookRotation(kmQuaternion* pOut, const kmVec3* direction, const kmVec3* up); 120 | kmQuaternion* kmQuaternionExtractRotationAroundAxis(const kmQuaternion* pIn, const kmVec3* axis, kmQuaternion* pOut); 121 | kmQuaternion* kmQuaternionBetweenVec3(kmQuaternion* pOut, const kmVec3* v1, const kmVec3* v2); 122 | 123 | #ifdef __cplusplus 124 | } 125 | #endif 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /kazmath/ray2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ray2.h" 4 | 5 | void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy) { 6 | ray->start.x = px; 7 | ray->start.y = py; 8 | ray->dir.x = vx; 9 | ray->dir.y = vy; 10 | } 11 | 12 | void kmRay2FillWithEndpoints( kmRay2 *ray, const kmVec2 *start, const kmVec2 *end ) { 13 | ray->start.x = start->x; 14 | ray->start.y = start->y; 15 | ray->dir.x = end->x - start->x; 16 | ray->dir.y = end->y - start->y; 17 | } 18 | 19 | 20 | /* 21 | Lines are defined by a pt and a vector. It outputs the vector multiply factor 22 | that gives the intersection point 23 | */ 24 | kmBool kmLine2WithLineIntersection(const kmVec2 *ptA, const kmVec2 *vecA, // first line 25 | const kmVec2 *ptB, const kmVec2 *vecB, // seconf line 26 | kmScalar *outTA, kmScalar *outTB, 27 | kmVec2 *outIntersection ) 28 | { 29 | kmScalar x1 = ptA->x; 30 | kmScalar y1 = ptA->y; 31 | kmScalar x2 = x1 + vecA->x; 32 | kmScalar y2 = y1 + vecA->y; 33 | kmScalar x3 = ptB->x; 34 | kmScalar y3 = ptB->y; 35 | kmScalar x4 = x3 + vecB->x; 36 | kmScalar y4 = y3 + vecB->y; 37 | 38 | kmScalar denom = (y4 -y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); 39 | 40 | /*If denom is zero, the lines are parallel*/ 41 | if(denom > -kmEpsilon && denom < kmEpsilon) { 42 | return KM_FALSE; 43 | } 44 | 45 | kmScalar ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; 46 | kmScalar ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; 47 | 48 | kmScalar x = x1 + ua * (x2 - x1); 49 | kmScalar y = y1 + ua * (y2 - y1); 50 | 51 | if( outTA ){ 52 | *outTA = ua; 53 | } 54 | if( outTB ){ 55 | *outTB = ub; 56 | } 57 | if( outIntersection ){ 58 | outIntersection->x = x; 59 | outIntersection->y = y; 60 | } 61 | return KM_TRUE; 62 | } 63 | 64 | kmBool kmSegment2WithSegmentIntersection( const kmRay2 *segmentA, const kmRay2 *segmentB, kmVec2 *intersection ) 65 | { 66 | kmScalar ua; 67 | kmScalar ub; 68 | kmVec2 pt; 69 | 70 | if( kmLine2WithLineIntersection( &(segmentA->start), &(segmentA->dir), 71 | &(segmentB->start), &(segmentB->start), 72 | &ua, &ub, &pt ) && 73 | (0.0 <= ua) && (ua <= 1.0) && (0.0 <= ub) && (ub <= 1.0)) { 74 | intersection->x = pt.x; 75 | intersection->y = pt.y; 76 | return KM_TRUE; 77 | } 78 | 79 | return KM_FALSE; 80 | } 81 | 82 | kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection) { 83 | 84 | kmScalar ua; 85 | kmScalar ub; 86 | kmVec2 pt; 87 | 88 | kmRay2 otherSegment; 89 | kmRay2FillWithEndpoints(&otherSegment, p1, p2); 90 | 91 | if( kmLine2WithLineIntersection( &(ray->start), &(ray->dir), 92 | &(otherSegment.start), &(otherSegment.dir), 93 | &ua, &ub, &pt ) && 94 | (0.0 <= ua) && (0.0 <= ub) && (ub <= 1.0)) { 95 | 96 | intersection->x = pt.x; 97 | intersection->y = pt.y; 98 | return KM_TRUE; 99 | } 100 | 101 | return KM_FALSE; 102 | } 103 | 104 | void calculate_line_normal(kmVec2 p1, kmVec2 p2, kmVec2 other_point, kmVec2* normal_out) { 105 | /* 106 | A = (3,4) 107 | B = (2,1) 108 | C = (1,3) 109 | 110 | AB = (2,1) - (3,4) = (-1,-3) 111 | AC = (1,3) - (3,4) = (-2,-1) 112 | N = n(AB) = (-3,1) 113 | D = dot(N,AC) = 6 + -1 = 5 114 | 115 | since D > 0: 116 | N = -N = (3,-1) 117 | */ 118 | 119 | kmVec2 edge, other_edge; 120 | kmVec2Subtract(&edge, &p2, &p1); 121 | kmVec2Subtract(&other_edge, &other_point, &p1); 122 | kmVec2Normalize(&edge, &edge); 123 | kmVec2Normalize(&other_edge, &other_edge); 124 | 125 | kmVec2 n; 126 | n.x = edge.y; 127 | n.y = -edge.x; 128 | 129 | kmScalar d = kmVec2Dot(&n, &other_edge); 130 | if(d > 0.0f) { 131 | n.x = -n.x; 132 | n.y = -n.y; 133 | } 134 | 135 | normal_out->x = n.x; 136 | normal_out->y = n.y; 137 | kmVec2Normalize(normal_out, normal_out); 138 | } 139 | 140 | kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out, kmScalar* distance_out) { 141 | kmVec2 intersect; 142 | kmVec2 final_intersect; 143 | kmVec2 normal; 144 | kmScalar distance = 10000.0f; 145 | kmBool intersected = KM_FALSE; 146 | 147 | if(kmRay2IntersectLineSegment(ray, p1, p2, &intersect)) { 148 | kmVec2 tmp; 149 | kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); 150 | kmVec2 this_normal; 151 | calculate_line_normal(*p1, *p2, *p3, &this_normal); 152 | if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { 153 | final_intersect.x = intersect.x; 154 | final_intersect.y = intersect.y; 155 | distance = this_distance; 156 | kmVec2Assign(&normal, &this_normal); 157 | intersected = KM_TRUE; 158 | } 159 | } 160 | 161 | if(kmRay2IntersectLineSegment(ray, p2, p3, &intersect)) { 162 | kmVec2 tmp; 163 | kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); 164 | 165 | kmVec2 this_normal; 166 | calculate_line_normal(*p2, *p3, *p1, &this_normal); 167 | 168 | if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { 169 | final_intersect.x = intersect.x; 170 | final_intersect.y = intersect.y; 171 | distance = this_distance; 172 | kmVec2Assign(&normal, &this_normal); 173 | intersected = KM_TRUE; 174 | } 175 | } 176 | 177 | if(kmRay2IntersectLineSegment(ray, p3, p1, &intersect)) { 178 | 179 | kmVec2 tmp; 180 | kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); 181 | 182 | kmVec2 this_normal; 183 | calculate_line_normal(*p3, *p1, *p2, &this_normal); 184 | if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { 185 | final_intersect.x = intersect.x; 186 | final_intersect.y = intersect.y; 187 | distance = this_distance; 188 | kmVec2Assign(&normal, &this_normal); 189 | intersected = KM_TRUE; 190 | } 191 | } 192 | 193 | if(intersected) { 194 | intersection->x = final_intersect.x; 195 | intersection->y = final_intersect.y; 196 | if(normal_out) { 197 | normal_out->x = normal.x; 198 | normal_out->y = normal.y; 199 | } 200 | if(distance) { 201 | *distance_out = distance; 202 | } 203 | } 204 | 205 | return intersected; 206 | } 207 | 208 | kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4, 209 | kmVec2* intersection, kmVec2* normal_out) { 210 | kmBool intersected = KM_FALSE; 211 | kmVec2 intersect, final_intersect, normal; 212 | kmScalar distance = 10000.0f; 213 | 214 | const kmVec2* points[4]; 215 | points[0] = p1; 216 | points[1] = p2; 217 | points[2] = p3; 218 | points[3] = p4; 219 | 220 | unsigned int i = 0; 221 | for(; i < 4; ++i) { 222 | const kmVec2* this_point = points[i]; 223 | const kmVec2* next_point = (i == 3) ? points[0] : points[i+1]; 224 | const kmVec2* other_point = (i == 3 || i == 0) ? points[1] : points[0]; 225 | 226 | if(kmRay2IntersectLineSegment(ray, this_point, next_point, &intersect)) { 227 | 228 | kmVec2 tmp; 229 | kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); 230 | 231 | kmVec2 this_normal; 232 | 233 | calculate_line_normal(*this_point, *next_point, *other_point, &this_normal); 234 | if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { 235 | kmVec2Assign(&final_intersect, &intersect); 236 | distance = this_distance; 237 | intersected = KM_TRUE; 238 | kmVec2Assign(&normal, &this_normal); 239 | } 240 | } 241 | } 242 | 243 | if(intersected) { 244 | intersection->x = final_intersect.x; 245 | intersection->y = final_intersect.y; 246 | if(normal_out) { 247 | normal_out->x = normal.x; 248 | normal_out->y = normal.y; 249 | } 250 | } 251 | 252 | return intersected; 253 | } 254 | 255 | kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection) { 256 | assert(0 && "Not implemented"); 257 | return KM_TRUE; 258 | } 259 | -------------------------------------------------------------------------------- /kazmath/ray2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef RAY_2_H 27 | #define RAY_2_H 28 | 29 | #include "utility.h" 30 | #include "vec2.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | typedef struct kmRay2 { 37 | kmVec2 start; 38 | kmVec2 dir; 39 | } kmRay2; 40 | 41 | void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy); 42 | void kmRay2FillWithEndpoints( kmRay2 *ray, const kmVec2 *start, const kmVec2 *end ); 43 | 44 | kmBool kmLine2WithLineIntersection(const kmVec2 *ptA, const kmVec2 *vecA, 45 | const kmVec2 *ptB, const kmVec2 *vecB, 46 | kmScalar *outTA, kmScalar *outTB, 47 | kmVec2 *outIntersection ); 48 | 49 | kmBool kmSegment2WithSegmentIntersection( const kmRay2 *segmentA, 50 | const kmRay2 *segmentB, 51 | kmVec2 *intersection ); 52 | 53 | kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection); 54 | kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out, kmScalar* distance); 55 | 56 | kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4, 57 | kmVec2* intersection, kmVec2* normal_out); 58 | 59 | kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection); 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /kazmath/ray3.c: -------------------------------------------------------------------------------- 1 | #include "plane.h" 2 | #include "ray3.h" 3 | 4 | kmRay3* kmRay3Fill(kmRay3* ray, kmScalar px, kmScalar py, kmScalar pz, kmScalar vx, kmScalar vy, kmScalar vz) { 5 | ray->start.x = px; 6 | ray->start.y = py; 7 | ray->start.z = pz; 8 | 9 | ray->dir.x = vx; 10 | ray->dir.y = vy; 11 | ray->dir.z = vz; 12 | 13 | return ray; 14 | } 15 | 16 | kmRay3* kmRay3FromPointAndDirection(kmRay3* ray, const kmVec3* point, const kmVec3* direction) { 17 | kmVec3Assign(&ray->start, point); 18 | kmVec3Assign(&ray->dir, direction); 19 | return ray; 20 | } 21 | 22 | kmBool kmRay3IntersectPlane(kmVec3* pOut, const kmRay3* ray, const kmPlane* plane) { 23 | /*t = - (A*org.x + B*org.y + C*org.z + D) / (A*dir.x + B*dir.y + C*dir.z )*/ 24 | 25 | kmScalar d = (plane->a * ray->dir.x + 26 | plane->b * ray->dir.y + 27 | plane->c * ray->dir.z); 28 | 29 | if(d == 0) 30 | { 31 | return KM_FALSE; 32 | } 33 | 34 | kmScalar t = -(plane->a * ray->start.x + 35 | plane->b * ray->start.y + 36 | plane->c * ray->start.z + plane->d) / d; 37 | 38 | if(t < 0) 39 | { 40 | return KM_FALSE; 41 | } 42 | 43 | kmVec3 scaled_dir; 44 | kmVec3Scale(&scaled_dir, &ray->dir, t); 45 | kmVec3Add(pOut, &ray->start, &scaled_dir); 46 | return KM_TRUE; 47 | } 48 | 49 | 50 | kmBool kmRay3IntersectTriangle(const kmRay3* ray, const kmVec3* v0, const kmVec3* v1, const kmVec3* v2, kmVec3* intersection, kmVec3* normal, kmScalar* distance) { 51 | kmVec3 e1, e2, pvec, tvec, qvec, dir; 52 | kmScalar det, inv_det, u, v, t; 53 | 54 | kmVec3Normalize(&dir, &ray->dir); 55 | 56 | kmVec3Subtract(&e1, v1, v0); 57 | kmVec3Subtract(&e2, v2, v0); 58 | 59 | kmVec3Cross(&pvec, &dir, &e2); 60 | det = kmVec3Dot(&e1, &pvec); 61 | 62 | // Backfacing, discard. 63 | if(det < kmEpsilon) { 64 | return KM_FALSE; 65 | } 66 | 67 | if(kmAlmostEqual(det, 0)) { 68 | return KM_FALSE; 69 | } 70 | 71 | inv_det = 1.0 / det; 72 | 73 | kmVec3Subtract(&tvec, &ray->start, v0); 74 | 75 | u = inv_det * kmVec3Dot(&tvec, &pvec); 76 | if(u < 0.0 || u > 1.0) { 77 | return KM_FALSE; 78 | } 79 | 80 | kmVec3Cross(&qvec, &tvec, &e1); 81 | v = inv_det * kmVec3Dot(&dir, &qvec); 82 | if(v < 0.0 || (u + v) > 1.0) { 83 | return KM_FALSE; 84 | } 85 | 86 | t = inv_det * kmVec3Dot(&e2, &qvec); 87 | if(t > kmEpsilon && (t*t) <= kmVec3LengthSq(&ray->dir)) { 88 | *distance = t; // Distance 89 | kmVec3Cross(normal, &e1, &e2); //Surface normal of collision 90 | kmVec3Normalize(normal, normal); 91 | kmVec3 scaled; 92 | kmVec3Normalize(&scaled, &dir); 93 | kmVec3Scale(&scaled, &scaled, *distance); 94 | kmVec3Add(intersection, &ray->start, &scaled); 95 | return KM_TRUE; 96 | } 97 | 98 | return KM_FALSE; 99 | } 100 | -------------------------------------------------------------------------------- /kazmath/ray3.h: -------------------------------------------------------------------------------- 1 | #ifndef RAY3_H 2 | #define RAY3_H 3 | 4 | #include "utility.h" 5 | #include "vec3.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | typedef struct kmRay3 { 12 | kmVec3 start; 13 | kmVec3 dir; 14 | } kmRay3; 15 | 16 | struct kmPlane; 17 | 18 | kmRay3* kmRay3Fill(kmRay3* ray, kmScalar px, kmScalar py, kmScalar pz, kmScalar vx, kmScalar vy, kmScalar vz); 19 | kmRay3* kmRay3FromPointAndDirection(kmRay3* ray, const kmVec3* point, const kmVec3* direction); 20 | kmBool kmRay3IntersectPlane(kmVec3* pOut, const kmRay3* ray, const struct kmPlane* plane); 21 | kmBool kmRay3IntersectTriangle(const kmRay3* ray, const kmVec3* v0, const kmVec3* v1, const kmVec3* v2, kmVec3* intersection, kmVec3* normal, kmScalar* distance); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* RAY3_H */ 28 | -------------------------------------------------------------------------------- /kazmath/utility.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "utility.h" 27 | 28 | /** 29 | * Returns the square of s (e.g. s*s) 30 | */ 31 | kmScalar kmSQR(kmScalar s) { 32 | return s*s; 33 | } 34 | 35 | /** 36 | * Returns degrees as radians. 37 | */ 38 | kmScalar kmDegreesToRadians(kmScalar degrees) { 39 | return degrees * kmPIOver180; 40 | } 41 | 42 | /** 43 | * Returns radians as degrees 44 | */ 45 | kmScalar kmRadiansToDegrees(kmScalar radians) { 46 | return radians * kmPIUnder180; 47 | } 48 | 49 | kmScalar kmMin(kmScalar lhs, kmScalar rhs) { 50 | return (lhs < rhs)? lhs : rhs; 51 | } 52 | 53 | kmScalar kmMax(kmScalar lhs, kmScalar rhs) { 54 | return (lhs > rhs)? lhs : rhs; 55 | } 56 | 57 | kmBool kmAlmostEqual(kmScalar lhs, kmScalar rhs) { 58 | return (fabs(lhs - rhs) <= kmEpsilon * fmax(1.0f, fmax(lhs, rhs))); 59 | } 60 | 61 | kmScalar kmClamp(kmScalar x, kmScalar min, kmScalar max) 62 | { 63 | return x < min ? min : (x > max ? max : x); 64 | } 65 | 66 | kmScalar kmLerp(kmScalar x, kmScalar y, kmScalar t ) 67 | { 68 | return x + t * ( y - x ); 69 | } 70 | -------------------------------------------------------------------------------- /kazmath/utility.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef UTILITY_H_INCLUDED 27 | #define UTILITY_H_INCLUDED 28 | 29 | #include 30 | #include 31 | 32 | #ifndef kmScalar 33 | #ifdef USE_DOUBLE_PRECISION 34 | #define kmScalar double 35 | #define kmEpsilon DBL_EPSILON 36 | #else 37 | #define kmScalar float 38 | #define kmEpsilon FLT_EPSILON 39 | #endif 40 | 41 | #endif 42 | 43 | #ifndef kmBool 44 | #define kmBool unsigned char 45 | #endif 46 | 47 | #ifndef kmUchar 48 | #define kmUchar unsigned char 49 | #endif 50 | 51 | #ifndef kmEnum 52 | #define kmEnum unsigned int 53 | #endif 54 | 55 | #ifndef kmUint 56 | #define kmUint unsigned int 57 | #endif 58 | 59 | #ifndef kmInt 60 | #define kmInt int 61 | #endif 62 | 63 | #ifndef KM_FALSE 64 | #define KM_FALSE 0 65 | #endif 66 | 67 | #ifndef KM_TRUE 68 | #define KM_TRUE 1 69 | #endif 70 | 71 | #define kmPI 3.14159265358979323846f 72 | #define kmPIOver180 (kmPI / 180.0f) 73 | #define kmPIUnder180 (180.0 / kmPI) 74 | 75 | #define KM_CONTAINS_NONE (kmEnum)0 76 | #define KM_CONTAINS_PARTIAL (kmEnum)1 77 | #define KM_CONTAINS_ALL (kmEnum)2 78 | 79 | #ifdef __cplusplus 80 | extern "C" { 81 | #endif 82 | 83 | extern kmScalar kmSQR(kmScalar s); 84 | extern kmScalar kmDegreesToRadians(kmScalar degrees); 85 | extern kmScalar kmRadiansToDegrees(kmScalar radians); 86 | 87 | extern kmScalar kmMin(kmScalar lhs, kmScalar rhs); 88 | extern kmScalar kmMax(kmScalar lhs, kmScalar rhs); 89 | extern kmBool kmAlmostEqual(kmScalar lhs, kmScalar rhs); 90 | 91 | extern kmScalar kmClamp(kmScalar x, kmScalar min, kmScalar max); 92 | extern kmScalar kmLerp(kmScalar x, kmScalar y, kmScalar factor); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif /* UTILITY_H_INCLUDED */ 99 | -------------------------------------------------------------------------------- /kazmath/vec2.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "mat3.h" 30 | #include "vec2.h" 31 | #include "utility.h" 32 | 33 | const kmVec2 KM_VEC2_POS_Y = { 0, 1 }; 34 | const kmVec2 KM_VEC2_NEG_Y = { 0, -1 }; 35 | const kmVec2 KM_VEC2_NEG_X = { -1, 0 }; 36 | const kmVec2 KM_VEC2_POS_X = { 1, 0 }; 37 | const kmVec2 KM_VEC2_ZERO = { 0, 0 }; 38 | 39 | kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y) 40 | { 41 | pOut->x = x; 42 | pOut->y = y; 43 | return pOut; 44 | } 45 | 46 | kmScalar kmVec2Length(const kmVec2* pIn) 47 | { 48 | return sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y)); 49 | } 50 | 51 | kmScalar kmVec2LengthSq(const kmVec2* pIn) 52 | { 53 | return kmSQR(pIn->x) + kmSQR(pIn->y); 54 | } 55 | 56 | kmVec2* kmVec2Lerp(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2, kmScalar t) { 57 | pOut->x = pV1->x + t * ( pV2->x - pV1->x ); 58 | pOut->y = pV1->y + t * ( pV2->y - pV1->y ); 59 | return pOut; 60 | } 61 | 62 | kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn) 63 | { 64 | if (!pIn->x && !pIn->y) 65 | return kmVec2Assign(pOut, pIn); 66 | 67 | kmScalar l = 1.0f / kmVec2Length(pIn); 68 | 69 | kmVec2 v; 70 | v.x = pIn->x * l; 71 | v.y = pIn->y * l; 72 | 73 | pOut->x = v.x; 74 | pOut->y = v.y; 75 | 76 | return pOut; 77 | } 78 | 79 | kmVec2* kmVec2Add(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2) 80 | { 81 | pOut->x = pV1->x + pV2->x; 82 | pOut->y = pV1->y + pV2->y; 83 | 84 | return pOut; 85 | } 86 | 87 | kmScalar kmVec2Dot(const kmVec2* pV1, const kmVec2* pV2) 88 | { 89 | return pV1->x * pV2->x + pV1->y * pV2->y; 90 | } 91 | 92 | kmScalar kmVec2Cross(const kmVec2* pV1, const kmVec2* pV2) 93 | { 94 | return pV1->x * pV2->y - pV1->y * pV2->x; 95 | } 96 | 97 | kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2) 98 | { 99 | pOut->x = pV1->x - pV2->x; 100 | pOut->y = pV1->y - pV2->y; 101 | 102 | return pOut; 103 | } 104 | 105 | kmVec2* kmVec2Mul( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ) { 106 | pOut->x = pV1->x * pV2->x; 107 | pOut->y = pV1->y * pV2->y; 108 | return pOut; 109 | } 110 | 111 | kmVec2* kmVec2Div( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ) { 112 | if ( pV2->x && pV2->y ){ 113 | pOut->x = pV1->x / pV2->x; 114 | pOut->y = pV1->y / pV2->y; 115 | } 116 | return pOut; 117 | } 118 | 119 | kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV, const kmMat3* pM) 120 | { 121 | kmVec2 v; 122 | 123 | v.x = pV->x * pM->mat[0] + pV->y * pM->mat[3] + pM->mat[6]; 124 | v.y = pV->x * pM->mat[1] + pV->y * pM->mat[4] + pM->mat[7]; 125 | 126 | pOut->x = v.x; 127 | pOut->y = v.y; 128 | 129 | return pOut; 130 | } 131 | 132 | kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const kmMat3* pM) 133 | { 134 | assert(0); 135 | return NULL; 136 | } 137 | 138 | kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s) 139 | { 140 | pOut->x = pIn->x * s; 141 | pOut->y = pIn->y * s; 142 | 143 | return pOut; 144 | } 145 | 146 | kmBool kmVec2AreEqual(const kmVec2* p1, const kmVec2* p2) 147 | { 148 | if((!kmAlmostEqual(p1->x, p2->x)) || (!kmAlmostEqual(p1->y, p2->y))) { 149 | return KM_FALSE; 150 | } 151 | 152 | return KM_TRUE; 153 | } 154 | 155 | /** 156 | * Assigns pIn to pOut. Returns pOut. If pIn and pOut are the same 157 | * then nothing happens but pOut is still returned 158 | */ 159 | kmVec2* kmVec2Assign(kmVec2* pOut, const kmVec2* pIn) { 160 | if (pOut == pIn) { 161 | return pOut; 162 | } 163 | 164 | pOut->x = pIn->x; 165 | pOut->y = pIn->y; 166 | 167 | return pOut; 168 | } 169 | 170 | /** 171 | * Rotates the point anticlockwise around a center 172 | * by an amount of degrees. 173 | * 174 | * Code ported from Irrlicht: http://irrlicht.sourceforge.net/ 175 | */ 176 | kmVec2* kmVec2RotateBy(kmVec2* pOut, const kmVec2* pIn, 177 | const kmScalar degrees, const kmVec2* center) 178 | { 179 | kmScalar x, y; 180 | const kmScalar radians = kmDegreesToRadians(degrees); 181 | const kmScalar cs = cosf(radians), sn = sinf(radians); 182 | 183 | pOut->x = pIn->x - center->x; 184 | pOut->y = pIn->y - center->y; 185 | 186 | x = pOut->x * cs - pOut->y * sn; 187 | y = pOut->x * sn + pOut->y * cs; 188 | 189 | pOut->x = x + center->x; 190 | pOut->y = y + center->y; 191 | 192 | return pOut; 193 | } 194 | 195 | /** 196 | * Returns the angle in degrees between the two vectors 197 | */ 198 | kmScalar kmVec2DegreesBetween(const kmVec2* v1, const kmVec2* v2) { 199 | if(kmVec2AreEqual(v1, v2)) { 200 | return 0.0; 201 | } 202 | 203 | kmVec2 t1, t2; 204 | kmVec2Normalize(&t1, v1); 205 | kmVec2Normalize(&t2, v2); 206 | 207 | kmScalar cross = kmVec2Cross(&t1, &t2); 208 | kmScalar dot = kmVec2Dot(&t1, &t2); 209 | 210 | /* 211 | * acos is only defined for -1 to 1. Outside the range we 212 | * get NaN even if that's just because of a floating point error 213 | * so we clamp to the -1 - 1 range 214 | */ 215 | 216 | if(dot > 1.0) dot = 1.0; 217 | if(dot < -1.0) dot = -1.0; 218 | 219 | return kmRadiansToDegrees(atan2(cross, dot)); 220 | } 221 | 222 | /** 223 | * Returns the distance between the two points 224 | */ 225 | kmScalar kmVec2DistanceBetween(const kmVec2* v1, const kmVec2* v2) { 226 | kmVec2 diff; 227 | kmVec2Subtract(&diff, v2, v1); 228 | return fabs(kmVec2Length(&diff)); 229 | } 230 | /** 231 | * Returns the point mid-way between two others 232 | */ 233 | kmVec2* kmVec2MidPointBetween(kmVec2* pOut, const kmVec2* v1, const kmVec2* v2) { 234 | kmVec2 sum; 235 | kmVec2Add(&sum, v1, v2); 236 | pOut->x = sum.x / 2.0f; 237 | pOut->y = sum.y / 2.0f; 238 | 239 | return pOut; 240 | } 241 | 242 | /** 243 | * Reflects a vector about a given surface normal. The surface normal is 244 | * assumed to be of unit length. 245 | */ 246 | kmVec2* kmVec2Reflect(kmVec2* pOut, const kmVec2* pIn, const kmVec2* normal) { 247 | kmVec2 tmp; 248 | kmVec2Scale(&tmp, normal, 2.0f * kmVec2Dot(pIn, normal)); 249 | kmVec2Subtract(pOut, pIn, &tmp); 250 | 251 | return pOut; 252 | } 253 | 254 | void kmVec2Swap(kmVec2* pA, kmVec2* pB) { 255 | kmScalar x = pA->x; 256 | kmScalar y = pA->y; 257 | pA->x = pB->x; 258 | pA->y = pB->y; 259 | pB->x = x; 260 | pB->y = y; 261 | } 262 | -------------------------------------------------------------------------------- /kazmath/vec2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef VEC2_H_INCLUDED 27 | #define VEC2_H_INCLUDED 28 | 29 | #include "utility.h" 30 | 31 | struct kmMat3; 32 | 33 | #pragma pack(push) /* push current alignment to stack */ 34 | #pragma pack(1) /* set alignment to 1 byte boundary */ 35 | typedef struct kmVec2 { 36 | kmScalar x; 37 | kmScalar y; 38 | } kmVec2; 39 | 40 | #pragma pack(pop) 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y); 47 | kmScalar kmVec2Length(const kmVec2* pIn); /**< Returns the length of the vector*/ 48 | kmScalar kmVec2LengthSq(const kmVec2* pIn); /**< Returns the square of the length of the vector*/ 49 | kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn); /**< Returns the vector passed in set to unit length*/ 50 | kmVec2* kmVec2Lerp(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2, kmScalar t); 51 | kmVec2* kmVec2Add(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); /**< Adds 2 vectors and returns the result*/ 52 | kmScalar kmVec2Dot(const kmVec2* pV1, const kmVec2* pV2); /** Returns the Dot product which is the cosine of the angle between the two vectors multiplied by their lengths */ 53 | kmScalar kmVec2Cross(const kmVec2* pV1, const kmVec2* pV2); 54 | kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); /**< Subtracts 2 vectors and returns the result*/ 55 | kmVec2* kmVec2Mul( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ); /**< Component-wise multiplication */ 56 | kmVec2* kmVec2Div( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ); /**< Component-wise division*/ 57 | kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV1, const struct kmMat3* pM); /** Transform the Vector */ 58 | kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const struct kmMat3* pM); /** 31 | #include "utility.h" 32 | 33 | struct kmMat4; 34 | struct kmMat3; 35 | struct kmPlane; 36 | 37 | typedef struct kmVec3 { 38 | kmScalar x; 39 | kmScalar y; 40 | kmScalar z; 41 | } kmVec3; 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z); 48 | kmScalar kmVec3Length(const kmVec3* pIn); /** Returns the length of the vector */ 49 | kmScalar kmVec3LengthSq(const kmVec3* pIn); /** Returns the square of the length of the vector */ 50 | kmVec3* kmVec3Lerp(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2, kmScalar t); 51 | kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn); /** Returns the vector passed in set to unit length */ 52 | kmVec3* kmVec3Cross(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Returns a vector perpendicular to 2 other vectors */ 53 | kmScalar kmVec3Dot(const kmVec3* pV1, const kmVec3* pV2); /** Returns the cosine of the angle between 2 vectors */ 54 | kmVec3* kmVec3Add(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Adds 2 vectors and returns the result */ 55 | kmVec3* kmVec3Subtract(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Subtracts 2 vectors and returns the result */ 56 | kmVec3* kmVec3Mul( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 ); 57 | kmVec3* kmVec3Div( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 ); 58 | 59 | kmVec3* kmVec3MultiplyMat3(kmVec3 *pOut, const kmVec3 *pV, const struct kmMat3* pM); 60 | kmVec3* kmVec3MultiplyMat4(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM); 61 | 62 | kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV1, const struct kmMat4* pM); /** Transforms a vector (assuming w=1) by a given matrix */ 63 | kmVec3* kmVec3TransformNormal(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);/**Transforms a 3D normal by a given matrix */ 64 | kmVec3* kmVec3TransformCoord(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM); /**Transforms a 3D vector by a given matrix, projecting the result back into w = 1. */ 65 | 66 | kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s); /** Scales a vector to length s */ 67 | kmBool kmVec3AreEqual(const kmVec3* p1, const kmVec3* p2); 68 | kmVec3* kmVec3InverseTransform(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM); 69 | kmVec3* kmVec3InverseTransformNormal(kmVec3* pOut, const kmVec3* pVect, const struct kmMat4* pM); 70 | kmVec3* kmVec3Assign(kmVec3* pOut, const kmVec3* pIn); 71 | kmVec3* kmVec3Zero(kmVec3* pOut); 72 | kmVec3* kmVec3GetHorizontalAngle(kmVec3* pOut, const kmVec3 *pIn); /** Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector. */ 73 | kmVec3* kmVec3RotationToDirection(kmVec3* pOut, const kmVec3* pIn, const kmVec3* forwards); /** Builds a direction vector from input vector. */ 74 | 75 | kmVec3* kmVec3ProjectOnToPlane(kmVec3* pOut, const kmVec3* point, const struct kmPlane* plane); 76 | kmVec3* kmVec3ProjectOnToVec3(const kmVec3* pIn, const kmVec3* other, kmVec3* projection); 77 | 78 | kmVec3* kmVec3Reflect(kmVec3* pOut, const kmVec3* pIn, const kmVec3* normal); /**< Reflects a vector about a given surface normal. The surface normal is assumed to be of unit length. */ 79 | 80 | void kmVec3Swap(kmVec3* a, kmVec3* b); 81 | void kmVec3OrthoNormalize(kmVec3* normal, kmVec3* tangent); 82 | 83 | extern const kmVec3 KM_VEC3_NEG_Z; 84 | extern const kmVec3 KM_VEC3_POS_Z; 85 | extern const kmVec3 KM_VEC3_POS_Y; 86 | extern const kmVec3 KM_VEC3_NEG_Y; 87 | extern const kmVec3 KM_VEC3_NEG_X; 88 | extern const kmVec3 KM_VEC3_POS_X; 89 | extern const kmVec3 KM_VEC3_ZERO; 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | #endif /* VEC3_H_INCLUDED */ 95 | -------------------------------------------------------------------------------- /kazmath/vec4.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | 27 | #include 28 | #include 29 | 30 | #include "utility.h" 31 | #include "vec4.h" 32 | #include "mat4.h" 33 | 34 | 35 | kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w) 36 | { 37 | pOut->x = x; 38 | pOut->y = y; 39 | pOut->z = z; 40 | pOut->w = w; 41 | return pOut; 42 | } 43 | 44 | 45 | /** Adds 2 4D vectors together. The result is store in pOut, the function returns*/ 46 | /** pOut so that it can be nested in another function.*/ 47 | kmVec4* kmVec4Add(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2) { 48 | pOut->x = pV1->x + pV2->x; 49 | pOut->y = pV1->y + pV2->y; 50 | pOut->z = pV1->z + pV2->z; 51 | pOut->w = pV1->w + pV2->w; 52 | 53 | return pOut; 54 | } 55 | 56 | /** Returns the dot product of 2 4D vectors*/ 57 | kmScalar kmVec4Dot(const kmVec4* pV1, const kmVec4* pV2) { 58 | return ( pV1->x * pV2->x 59 | + pV1->y * pV2->y 60 | + pV1->z * pV2->z 61 | + pV1->w * pV2->w ); 62 | } 63 | 64 | /** Returns the length of a 4D vector, this uses a sqrt so if the squared length will do use*/ 65 | /** kmVec4LengthSq*/ 66 | kmScalar kmVec4Length(const kmVec4* pIn) { 67 | return sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z) + kmSQR(pIn->w)); 68 | } 69 | 70 | /** Returns the length of the 4D vector squared.*/ 71 | kmScalar kmVec4LengthSq(const kmVec4* pIn) { 72 | return kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z) + kmSQR(pIn->w); 73 | } 74 | 75 | /** Returns the interpolation of 2 4D vectors based on t.*/ 76 | kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t) { 77 | pOut->x = pV1->x + t * ( pV2->x - pV1->x ); 78 | pOut->y = pV1->y + t * ( pV2->y - pV1->y ); 79 | pOut->z = pV1->z + t * ( pV2->z - pV1->z ); 80 | pOut->w = pV1->w + t * ( pV2->w - pV1->w ); 81 | return pOut; 82 | } 83 | 84 | /** Normalizes a 4D vector. The result is stored in pOut. pOut is returned*/ 85 | kmVec4* kmVec4Normalize(kmVec4* pOut, const kmVec4* pIn) { 86 | if (!pIn->x && !pIn->y && !pIn->z && !pIn->w){ 87 | return kmVec4Assign(pOut, pIn); 88 | } 89 | 90 | kmScalar l = 1.0f / kmVec4Length(pIn); 91 | pOut->x = pIn->x * l; 92 | pOut->y = pIn->y * l; 93 | pOut->z = pIn->z * l; 94 | pOut->w = pIn->w * l; 95 | 96 | return pOut; 97 | } 98 | 99 | /** Scales a vector to the required length. This performs a Normalize before multiplying by S.*/ 100 | kmVec4* kmVec4Scale(kmVec4* pOut, const kmVec4* pIn, const kmScalar s) { 101 | kmVec4Normalize(pOut, pIn); 102 | 103 | pOut->x *= s; 104 | pOut->y *= s; 105 | pOut->z *= s; 106 | pOut->w *= s; 107 | return pOut; 108 | } 109 | 110 | /** Subtracts one 4D pV2 from pV1. The result is stored in pOut. pOut is returned*/ 111 | kmVec4* kmVec4Subtract(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2) { 112 | pOut->x = pV1->x - pV2->x; 113 | pOut->y = pV1->y - pV2->y; 114 | pOut->z = pV1->z - pV2->z; 115 | pOut->w = pV1->w - pV2->w; 116 | 117 | return pOut; 118 | } 119 | 120 | kmVec4* kmVec4Mul( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ) { 121 | pOut->x = pV1->x * pV2->x; 122 | pOut->y = pV1->y * pV2->y; 123 | pOut->z = pV1->z * pV2->z; 124 | pOut->w = pV1->w * pV2->w; 125 | return pOut; 126 | } 127 | 128 | kmVec4* kmVec4Div( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ) { 129 | if ( pV2->x && pV2->y && pV2->z && pV2->w){ 130 | pOut->x = pV1->x / pV2->x; 131 | pOut->y = pV1->y / pV2->y; 132 | pOut->z = pV1->z / pV2->z; 133 | pOut->w = pV1->w / pV2->w; 134 | } 135 | return pOut; 136 | } 137 | 138 | /** Multiplies a 4D vector by a matrix, the result is stored in pOut, and pOut is returned.*/ 139 | kmVec4* kmVec4MultiplyMat4(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM) { 140 | pOut->x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8] + pV->w * pM->mat[12]; 141 | pOut->y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9] + pV->w * pM->mat[13]; 142 | pOut->z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10] + pV->w * pM->mat[14]; 143 | pOut->w = pV->x * pM->mat[3] + pV->y * pM->mat[7] + pV->z * pM->mat[11] + pV->w * pM->mat[15]; 144 | return pOut; 145 | } 146 | 147 | kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const kmMat4* pM) { 148 | return kmVec4MultiplyMat4(pOut, pV, pM); 149 | } 150 | 151 | /** Loops through an input array transforming each vec4 by the matrix.*/ 152 | kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride, 153 | const kmVec4* pV, unsigned int vStride, const kmMat4* pM, unsigned int count) { 154 | unsigned int i = 0; 155 | /*Go through all of the vectors*/ 156 | while (i < count) { 157 | const kmVec4* in = pV + (i * vStride); /*Get a pointer to the current input*/ 158 | kmVec4* out = pOut + (i * outStride); /*and the current output*/ 159 | kmVec4Transform(out, in, pM); /*Perform transform on it*/ 160 | ++i; 161 | } 162 | 163 | return pOut; 164 | } 165 | 166 | int kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2) { 167 | return ( 168 | (p1->x < p2->x + kmEpsilon && p1->x > p2->x - kmEpsilon) && 169 | (p1->y < p2->y + kmEpsilon && p1->y > p2->y - kmEpsilon) && 170 | (p1->z < p2->z + kmEpsilon && p1->z > p2->z - kmEpsilon) && 171 | (p1->w < p2->w + kmEpsilon && p1->w > p2->w - kmEpsilon) 172 | ); 173 | } 174 | 175 | kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn) { 176 | pOut->x = pIn->x; 177 | pOut->y = pIn->y; 178 | pOut->z = pIn->z; 179 | pOut->w = pIn->w; 180 | return pOut; 181 | } 182 | 183 | void kmVec4Swap(kmVec4* pA, kmVec4* pB) { 184 | kmScalar x = pA->x; pA->x = pB->x; pB->x = x; 185 | kmScalar y = pA->y; pA->y = pB->y; pB->y = y; 186 | kmScalar z = pA->z; pA->z = pB->z; pB->z = z; 187 | kmScalar w = pA->w; pA->w = pB->w; pB->w = w; 188 | } 189 | -------------------------------------------------------------------------------- /kazmath/vec4.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Luke Benstead. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef VEC4_H_INCLUDED 27 | #define VEC4_H_INCLUDED 28 | 29 | #include "utility.h" 30 | 31 | struct kmMat4; 32 | 33 | #pragma pack(push) /* push current alignment to stack */ 34 | #pragma pack(1) /* set alignment to 1 byte boundary */ 35 | 36 | typedef struct kmVec4 37 | { 38 | kmScalar x; 39 | kmScalar y; 40 | kmScalar z; 41 | kmScalar w; 42 | } kmVec4; 43 | 44 | #pragma pack(pop) 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w); 51 | kmVec4* kmVec4Add(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2); 52 | kmScalar kmVec4Dot(const kmVec4* pV1, const kmVec4* pV2); 53 | kmScalar kmVec4Length(const kmVec4* pIn); 54 | kmScalar kmVec4LengthSq(const kmVec4* pIn); 55 | kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t); 56 | kmVec4* kmVec4Normalize(kmVec4* pOut, const kmVec4* pIn); 57 | kmVec4* kmVec4Scale(kmVec4* pOut, const kmVec4* pIn, const kmScalar s); /**< Scales a vector to length s*/ 58 | kmVec4* kmVec4Subtract(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2); 59 | kmVec4* kmVec4Mul( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ); 60 | kmVec4* kmVec4Div( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ); 61 | 62 | kmVec4* kmVec4MultiplyMat4(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM); 63 | kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM); 64 | kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride, 65 | const kmVec4* pV, unsigned int vStride, const struct kmMat4* pM, unsigned int count); 66 | int kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2); 67 | 68 | kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn); 69 | void kmVec4Swap(kmVec4* pA, kmVec4* pB); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* VEC4_H_INCLUDED */ 76 | -------------------------------------------------------------------------------- /lib/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/lib/.dummy -------------------------------------------------------------------------------- /o/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/o/.dummy -------------------------------------------------------------------------------- /resources/models/alien.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/alien.gbo -------------------------------------------------------------------------------- /resources/models/cube.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/cube.gbo -------------------------------------------------------------------------------- /resources/models/ground.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/ground.gbo -------------------------------------------------------------------------------- /resources/models/ship.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/ship.gbo -------------------------------------------------------------------------------- /resources/models/shot.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/shot.gbo -------------------------------------------------------------------------------- /resources/models/sphere.gbo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/models/sphere.gbo -------------------------------------------------------------------------------- /resources/shaders/glprint.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D texture_uniform; 2 | uniform float cx,cy; 3 | varying vec2 v_frag_uv; 4 | 5 | 6 | void main() 7 | { 8 | float x=cx+v_frag_uv.x; 9 | float y=cy+v_frag_uv.y; 10 | gl_FragColor = texture2D(texture_uniform, vec2(x,y)); 11 | } 12 | -------------------------------------------------------------------------------- /resources/shaders/glprint.vert: -------------------------------------------------------------------------------- 1 | attribute vec3 vert_attrib; 2 | attribute vec2 uv_attrib; 3 | 4 | uniform mat4 opm_uniform; 5 | 6 | varying vec2 v_frag_uv; 7 | 8 | void main(void) { 9 | 10 | v_frag_uv = uv_attrib; 11 | gl_Position = opm_uniform * vec4(vert_attrib,1); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /resources/shaders/particle.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | void main() { 4 | gl_FragColor = texture2D(u_texture,gl_PointCoord); 5 | //gl_FragColor = vec4(1,1,1,0.5); 6 | } 7 | -------------------------------------------------------------------------------- /resources/shaders/particle.vert: -------------------------------------------------------------------------------- 1 | attribute vec3 vertex_attrib; 2 | 3 | uniform mat4 mvp_uniform; 4 | 5 | uniform float u_point_size; 6 | 7 | void main(void) { 8 | 9 | gl_PointSize = u_point_size; 10 | gl_Position = mvp_uniform * vec4(vertex_attrib,1); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /resources/shaders/sprite.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D texture_uniform; 2 | varying vec2 v_frag_uv; 3 | 4 | 5 | void main() 6 | { 7 | gl_FragColor = texture2D(texture_uniform, v_frag_uv); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /resources/shaders/sprite.vert: -------------------------------------------------------------------------------- 1 | attribute vec3 vert_attrib; 2 | attribute vec2 uv_attrib; 3 | 4 | uniform mat4 opm_uniform; 5 | uniform vec2 u_size; 6 | 7 | varying vec2 v_frag_uv; 8 | 9 | void main(void) { 10 | 11 | v_frag_uv = uv_attrib; 12 | vec4 vert_pos; 13 | vert_pos = vec4(vert_attrib,1); 14 | vert_pos.x = vert_pos.x * u_size.x; 15 | vert_pos.y = vert_pos.y * u_size.y; 16 | 17 | gl_Position = opm_uniform * vert_pos; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /resources/shaders/textured.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D u_texture; 2 | 3 | uniform vec3 u_lightDir; 4 | uniform vec3 u_viewDir; 5 | 6 | varying vec3 v_Position; 7 | varying vec3 v_Normal; 8 | varying vec2 v_frag_uv; 9 | 10 | 11 | void main() { 12 | vec4 baseColour = texture2D(u_texture,v_frag_uv); 13 | float nDOTl = dot(v_Normal,u_lightDir); 14 | vec3 reflect = (2.0 * v_Normal * nDOTl) - u_lightDir; 15 | float rDOTv = max(0.0, dot(reflect,u_viewDir)); 16 | 17 | // these three vec4's could be material uniforms. 18 | vec4 ambi = vec4(.7,.7,.7,0) * baseColour; 19 | vec4 diffu = vec4(.8,.8,.8,0) * nDOTl * baseColour; 20 | 21 | 22 | // spec strength (could be a material uniform) - TODO seems wrong? 23 | //vec4 specu = vec4(.9,.9,.9,0) * (rDOTv/99.);//pow(rDOTv,20); 24 | vec4 specu = vec4(.7,.7,.7,0) * pow(rDOTv,20.0); 25 | 26 | gl_FragColor = ambi + diffu + specu; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /resources/shaders/textured.vert: -------------------------------------------------------------------------------- 1 | attribute vec3 vertex_attrib; 2 | attribute vec2 uv_attrib; 3 | attribute vec3 norm_attrib; 4 | 5 | uniform mat4 mvp_uniform; 6 | uniform mat4 mv_uniform; 7 | 8 | varying vec2 v_frag_uv; 9 | varying vec3 v_Position; 10 | varying vec3 v_Normal; 11 | 12 | void main(void) { 13 | 14 | v_frag_uv = uv_attrib; 15 | 16 | v_Position = vec3(mv_uniform * vec4(vertex_attrib,0)); 17 | v_Normal = vec3(mv_uniform * vec4(norm_attrib, 0.0)); 18 | gl_Position = mvp_uniform * vec4(vertex_attrib,1); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /resources/textures/alien.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/alien.png -------------------------------------------------------------------------------- /resources/textures/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/ball.png -------------------------------------------------------------------------------- /resources/textures/bigfont.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/bigfont.png -------------------------------------------------------------------------------- /resources/textures/biplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/biplane.png -------------------------------------------------------------------------------- /resources/textures/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/cloud.png -------------------------------------------------------------------------------- /resources/textures/dice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/dice.png -------------------------------------------------------------------------------- /resources/textures/explosion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/explosion.png -------------------------------------------------------------------------------- /resources/textures/font.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/font.png -------------------------------------------------------------------------------- /resources/textures/jupiter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/jupiter.png -------------------------------------------------------------------------------- /resources/textures/shipv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/shipv2.png -------------------------------------------------------------------------------- /resources/textures/shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/shot.png -------------------------------------------------------------------------------- /resources/textures/swirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/swirl.png -------------------------------------------------------------------------------- /resources/textures/triplane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/resources/textures/triplane.png -------------------------------------------------------------------------------- /src/input.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // sprintf 3 | #include // malloc 4 | #include 5 | #include // open fcntl 6 | #include // read close 7 | #include 8 | 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | extern Display *__x_display; 15 | extern Window __eventWin; 16 | 17 | 18 | #include // scandir 19 | #include // strlen 20 | 21 | #include "input.h" 22 | 23 | 24 | 25 | bool __keys[256]; 26 | int __mouse[3]; 27 | bool __rel_mouse; 28 | 29 | int __key_fd=0; // defaults to 0 ie console 30 | 31 | 32 | 33 | 34 | void doEvents() 35 | { 36 | 37 | 38 | XEvent event; 39 | 40 | if(__rel_mouse) { 41 | __mouse[0]=0; 42 | __mouse[1]=0; 43 | } 44 | 45 | while (XEventsQueued(__x_display, QueuedAfterReading)) { 46 | XNextEvent(__x_display, &event); 47 | switch (event.type) { 48 | 49 | case KeyPress: 50 | __keys[event.xkey.keycode & 0xff] = true; 51 | //printf("key=%i\n",event.xkey.keycode & 0xff); 52 | break; 53 | 54 | case KeyRelease: 55 | __keys[event.xkey.keycode & 0xff] = false; 56 | break; 57 | 58 | case MotionNotify: 59 | if (__rel_mouse) { 60 | __mouse[0] = event.xbutton.x-(__display_width/2.0); 61 | __mouse[1] = event.xbutton.y-(__display_height/2.0); 62 | } else { 63 | __mouse[0] = event.xbutton.x; 64 | __mouse[1] = event.xbutton.y; 65 | } 66 | //printf("mouse %i,%i\n",__mouse[0],__mouse[1]); 67 | break; 68 | 69 | case ButtonPress: 70 | __mouse[2] = 71 | __mouse[2] | (int)pow(2, event.xbutton.button - 1); 72 | break; 73 | case ButtonRelease: 74 | __mouse[2] = 75 | __mouse[2] & (int)(255 - 76 | pow(2, 77 | event.xbutton.button - 1)); 78 | break; 79 | 80 | } 81 | 82 | if(__rel_mouse) { // rel mode test here 83 | 84 | XSelectInput(__x_display, __eventWin, NoEventMask); 85 | XWarpPointer(__x_display, None, __eventWin, 0, 0, 0, 0, __display_width/2.0, __display_height/2.0); 86 | XFlush(__x_display); 87 | XSelectInput(__x_display, __eventWin, ExposureMask | 88 | KeyPressMask | KeyReleaseMask | 89 | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); 90 | XFlush(__x_display); 91 | 92 | } 93 | } 94 | 95 | 96 | } 97 | 98 | void setMouseRelative(bool mode) { 99 | __rel_mouse=mode; 100 | } 101 | 102 | int *getMouse() 103 | { 104 | __rel_mouse=false; 105 | 106 | return &__mouse[0]; 107 | } 108 | 109 | static int __dsort (const struct dirent **a,const struct dirent **b) { 110 | return 1; // dummy sort 111 | } 112 | 113 | static int __dfilter(const struct dirent *d) { 114 | if (d->d_type==DT_DIR) return 0; 115 | int i=0; 116 | i=strlen(d->d_name)-1; 117 | //printf ("%i %c %c %c \n",d->d_type,d->d_name[i-2],d->d_name[i-1],d->d_name[i]); 118 | // allegedly usb keyboard symlink *always* ends kbd 119 | if (d->d_name[i-2]=='k' & d->d_name[i-1]=='b' & d->d_name[i]=='d' ) return 1; 120 | return 0; 121 | } 122 | 123 | 124 | 125 | bool *getKeys() 126 | { 127 | 128 | struct dirent **eps; 129 | int n; 130 | 131 | n = scandir ("/dev/input/by-path/", &eps, __dfilter, __dsort); 132 | // if (n >= 0) 133 | if(n >= 0 && eps != 0 && eps[0] != 0) { 134 | // only check 1st usb keyboard.... 135 | char fn[256]; 136 | sprintf(fn,"/dev/input/by-path/%s%c",eps[0]->d_name,0); // %c 0 to avoid embedded '\0' in format 137 | __key_fd=open(fn, O_RDONLY); 138 | printf("%i %s\n",__key_fd,fn); 139 | } 140 | 141 | if (__key_fd==-1) __key_fd=0; // on usb evdev failure default to console 142 | 143 | int flags; 144 | flags = fcntl(__key_fd, F_GETFL); 145 | flags |= O_NONBLOCK; 146 | fcntl(__key_fd, F_SETFL, flags); 147 | 148 | 149 | return &__keys[0]; 150 | } 151 | 152 | struct joystick_t *getJoystick(int j) { 153 | 154 | char devpath[20]; 155 | sprintf(devpath,"/dev/input/js%i%c",j,0); 156 | 157 | struct joystick_t *js=malloc(sizeof(struct joystick_t)); 158 | js->fd = open(devpath, O_RDONLY); 159 | if (js->fd < 0) { 160 | printf("joystick %i open failed\n",j); 161 | } else { 162 | // make none blocking 163 | int flags = fcntl(js->fd, F_GETFL); 164 | flags |= O_NONBLOCK; 165 | fcntl(js->fd, F_SETFL, flags); 166 | } 167 | js->buttons=0; 168 | return js; 169 | } 170 | 171 | void updateJoystick(struct joystick_t *js) { 172 | struct js_event jse; 173 | int jres; 174 | jres=read(js->fd,&jse,sizeof(struct js_event)); 175 | while(jres>=0) { 176 | jse.type &= ~JS_EVENT_INIT; // mask out synthetic event flag 177 | 178 | if (jse.type == JS_EVENT_AXIS) { 179 | if (jse.number<8) { 180 | js->axis[jse.number]=jse.value; 181 | } 182 | } 183 | 184 | if (jse.type == JS_EVENT_BUTTON) { 185 | 186 | if (jse.value==1) { 187 | js->buttons = js->buttons | 1<buttons = js->buttons & ~(1<fd,&jse,sizeof(struct js_event)); 195 | } 196 | 197 | } 198 | 199 | void releaseJoystick(struct joystick_t *js) { 200 | 201 | close(js->fd); 202 | free(js); 203 | 204 | } 205 | 206 | -------------------------------------------------------------------------------- /src/obj.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "obj.h" 6 | #include "support.h" 7 | 8 | /* each OBJ shader is expected to have at least these attribs and uniforms 9 | 10 | vertex_attrib vertex coordinates 11 | uv_attrib uv coordinates 12 | mvp_uniform combined model, view and projection matrix 13 | mv_uniform view, model matrix for lighting 14 | texture_uniform texture sampler 15 | 16 | other custom attribs/uniforms should be handled as a special case in the 17 | main code 18 | 19 | */ 20 | 21 | int loadObj(struct obj_t *obj,const char *objFile, char *vert, char *frag) 22 | { 23 | FILE *pFile; 24 | pFile = fopen( objFile , "rb" ); 25 | if (pFile==NULL) { 26 | printf("Cant find open model - %s\n",objFile); 27 | return false; 28 | } 29 | unsigned int magic; 30 | int NumVerts; 31 | 32 | fread (&magic,1, sizeof(unsigned int), pFile ); 33 | if (magic!=0x614f4247) { 34 | printf("Does not appear to be a version 'a' GBO file\n"); 35 | return false; 36 | } 37 | fread(&NumVerts,1,sizeof(unsigned int), pFile ); 38 | 39 | float* Verts = malloc(sizeof(float) * 3 * NumVerts); 40 | fread(Verts,1,sizeof(float) * 3 * NumVerts, pFile ); 41 | 42 | float* Norms = malloc(sizeof(float) * 3 * NumVerts); 43 | fread(Norms,1,sizeof(float) * 3 * NumVerts, pFile ); 44 | 45 | float* TexCoords = malloc(sizeof(float) * 2 * NumVerts); 46 | fread(TexCoords,1,sizeof(float) * 2 * NumVerts, pFile ); 47 | 48 | createObj(obj,NumVerts,Verts,TexCoords,Norms,vert,frag); 49 | 50 | free(TexCoords); 51 | free(Norms); 52 | free(Verts); 53 | 54 | return true; 55 | } 56 | 57 | int loadObjCopyShader(struct obj_t *obj,const char *objFile, struct obj_t *sdrobj) 58 | { 59 | FILE *pFile; 60 | pFile = fopen( objFile , "rb" ); 61 | if (pFile==NULL) { 62 | printf("Cant find open model - %s\n",objFile); 63 | return false; 64 | } 65 | unsigned int magic; 66 | int NumVerts; 67 | 68 | fread (&magic,1, sizeof(unsigned int), pFile ); 69 | if (magic!=0x614f4247) { 70 | printf("Does not appear to be a version 'a' GBO file\n"); 71 | return false; 72 | } 73 | fread(&NumVerts,1,sizeof(unsigned int), pFile ); 74 | 75 | float* Verts = malloc(sizeof(float) * 3 * NumVerts); 76 | fread(Verts,1,sizeof(float) * 3 * NumVerts, pFile ); 77 | 78 | float* Norms = malloc(sizeof(float) * 3 * NumVerts); 79 | fread(Norms,1,sizeof(float) * 3 * NumVerts, pFile ); 80 | 81 | float* TexCoords = malloc(sizeof(float) * 2 * NumVerts); 82 | fread(TexCoords,1,sizeof(float) * 2 * NumVerts, pFile ); 83 | 84 | createObjCopyShader(obj,NumVerts, Verts,TexCoords, 85 | Norms, sdrobj); 86 | 87 | free(TexCoords); 88 | free(Norms); 89 | free(Verts); 90 | 91 | return true; 92 | } 93 | 94 | 95 | int createObj(struct obj_t *obj, int numVerts, float *verts, float *txVert, 96 | float *norms, char *vertShader, char *fragShader) 97 | { 98 | obj->num_verts = numVerts; 99 | 100 | glGenBuffers(1, &obj->vbo_vert); 101 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_vert); 102 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * numVerts, verts, 103 | GL_STATIC_DRAW); 104 | 105 | glGenBuffers(1, &obj->vbo_tex); 106 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_tex); 107 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 2 * numVerts, txVert, 108 | GL_STATIC_DRAW); 109 | 110 | glGenBuffers(1, &obj->vbo_norm); 111 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_norm); 112 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * numVerts, norms, 113 | GL_STATIC_DRAW); 114 | 115 | GLint link_ok = GL_FALSE; 116 | 117 | GLuint vs, fs; 118 | if ((vs = create_shader(vertShader, GL_VERTEX_SHADER)) == 0) 119 | return 0; 120 | if ((fs = create_shader(fragShader, GL_FRAGMENT_SHADER)) == 0) 121 | return 0; 122 | 123 | obj->program = glCreateProgram(); 124 | glAttachShader(obj->program, vs); 125 | glAttachShader(obj->program, fs); 126 | glLinkProgram(obj->program); 127 | glGetProgramiv(obj->program, GL_LINK_STATUS, &link_ok); 128 | if (!link_ok) { 129 | printf("glLinkProgram:"); 130 | print_log(obj->program); 131 | return 0; 132 | } 133 | 134 | obj->vert_attrib = 135 | getShaderLocation(shaderAttrib, obj->program, "vertex_attrib"); 136 | obj->tex_attrib = 137 | getShaderLocation(shaderAttrib, obj->program, "uv_attrib"); 138 | obj->norm_attrib = 139 | getShaderLocation(shaderAttrib, obj->program, "norm_attrib"); 140 | obj->mvp_uniform = 141 | getShaderLocation(shaderUniform, obj->program, "mvp_uniform"); 142 | obj->mv_uniform = 143 | getShaderLocation(shaderUniform, obj->program, "mv_uniform"); 144 | obj->tex_uniform = 145 | getShaderLocation(shaderUniform, obj->program, "u_texture"); 146 | obj->lightDir_uniform = 147 | getShaderLocation(shaderUniform, obj->program, "u_lightDir"); 148 | obj->viewDir_uniform = 149 | getShaderLocation(shaderUniform, obj->program, "u_viewDir"); 150 | 151 | 152 | } 153 | 154 | /* 155 | * create an obj from supplied verts using an existing models shader 156 | */ 157 | int createObjCopyShader(struct obj_t *obj, int numVerts, float *verts, 158 | float *txVert, float *norms, struct obj_t *sdrobj) 159 | { 160 | obj->num_verts = numVerts; 161 | glGenBuffers(1, &obj->vbo_vert); 162 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_vert); 163 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * numVerts, verts, 164 | GL_STATIC_DRAW); 165 | 166 | glGenBuffers(1, &obj->vbo_tex); 167 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_tex); 168 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 2 * numVerts, txVert, 169 | GL_STATIC_DRAW); 170 | 171 | glGenBuffers(1, &obj->vbo_norm); 172 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_norm); 173 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * numVerts, norms, 174 | GL_STATIC_DRAW); 175 | 176 | obj->vert_attrib = sdrobj->vert_attrib; 177 | obj->tex_attrib = sdrobj->tex_attrib; 178 | obj->norm_attrib = sdrobj->norm_attrib; 179 | obj->mvp_uniform = sdrobj->mvp_uniform; 180 | obj->mv_uniform = sdrobj->mv_uniform; 181 | obj->tex_uniform = sdrobj->tex_uniform; 182 | obj->lightDir_uniform = sdrobj->lightDir_uniform; 183 | obj->viewDir_uniform = sdrobj->viewDir_uniform; 184 | obj->program = sdrobj->program; 185 | 186 | } 187 | 188 | void drawObj(struct obj_t *obj, kmMat4 * combined, kmMat4 * mv, kmVec3 lightDir, kmVec3 viewDir) 189 | { 190 | glUseProgram(obj->program); 191 | 192 | glUniformMatrix4fv(obj->mvp_uniform, 1, GL_FALSE, (GLfloat *) combined); 193 | glUniformMatrix4fv(obj->mv_uniform, 1, GL_FALSE, (GLfloat *) mv); 194 | 195 | glUniform1i(obj->tex_uniform, 0); 196 | 197 | glUniform3f(obj->viewDir_uniform,viewDir.x,viewDir.y,viewDir.z); 198 | glUniform3f(obj->lightDir_uniform,lightDir.x,lightDir.y,lightDir.z); 199 | 200 | glEnableVertexAttribArray(obj->vert_attrib); 201 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_vert); 202 | glVertexAttribPointer(obj->vert_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); 203 | 204 | glEnableVertexAttribArray(obj->norm_attrib); 205 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_norm); 206 | glVertexAttribPointer(obj->norm_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); 207 | 208 | glEnableVertexAttribArray(obj->tex_attrib); 209 | glBindBuffer(GL_ARRAY_BUFFER, obj->vbo_tex); 210 | glVertexAttribPointer(obj->tex_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0); 211 | 212 | glDrawArrays(GL_TRIANGLES, 0, obj->num_verts); 213 | 214 | glDisableVertexAttribArray(obj->tex_attrib); 215 | glDisableVertexAttribArray(obj->vert_attrib); 216 | glDisableVertexAttribArray(obj->norm_attrib); 217 | 218 | } 219 | -------------------------------------------------------------------------------- /tools/fontexturer/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ant build/run file 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 40 | 44 | 45 | 46 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /tools/fontexturer/readme.txt: -------------------------------------------------------------------------------- 1 | found @ 2 | http://www.java-gaming.org/index.php?topic=25937.0 3 | 4 | added ant build file... 5 | 6 | added start char so you can start from 32 ie space which is more useful... 7 | 8 | TODO add overide for char width... 9 | 10 | 11 | Still very much work in progress! (IE it sucks and blows at the same time!) 12 | -------------------------------------------------------------------------------- /tools/fontexturer/src/com/logiklabs/fontexturer/FontCellRenderer.java: -------------------------------------------------------------------------------- 1 | package com.logiklabs.fontexturer; 2 | 3 | import java.awt.Component; 4 | import java.awt.Font; 5 | 6 | import javax.swing.DefaultListCellRenderer; 7 | import javax.swing.JLabel; 8 | import javax.swing.JList; 9 | 10 | public class FontCellRenderer extends DefaultListCellRenderer { 11 | public Component getListCellRendererComponent(JList list, Object value, 12 | int index, boolean isSelected, boolean cellHasFocus) { 13 | JLabel label = (JLabel) super.getListCellRendererComponent(list, value, 14 | index, isSelected, cellHasFocus); 15 | String str = value.toString(); 16 | Font font = new Font(str, Font.PLAIN, 14); 17 | if(font.canDisplayUpTo(str) == -1) 18 | label.setFont(font); 19 | else 20 | label.setFont(new Font(label.getFont().getFontName(), Font.PLAIN, 14)); 21 | return label; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools/fontexturer/src/com/logiklabs/fontexturer/Fontexturer.java: -------------------------------------------------------------------------------- 1 | package com.logiklabs.fontexturer; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Dimension; 5 | import java.awt.GraphicsEnvironment; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.awt.GridLayout; 9 | 10 | import java.io.File; 11 | 12 | import javax.swing.*; 13 | import javax.swing.border.CompoundBorder; 14 | import javax.swing.border.EmptyBorder; 15 | import javax.swing.border.TitledBorder; 16 | import javax.swing.event.ChangeEvent; 17 | import javax.swing.event.ChangeListener; 18 | import javax.swing.filechooser.FileFilter; 19 | 20 | public class Fontexturer extends JFrame implements ActionListener, ChangeListener { 21 | private JComboBox fontCombo; 22 | private JSpinner fontSpinner,minSpinner; 23 | private PreviewPanel preview; 24 | private ButtonGroup bg2; 25 | 26 | public static void main(String[] args) { 27 | SwingUtilities.invokeLater(new Runnable() { 28 | public void run() { 29 | new Fontexturer().setVisible(true); 30 | } 31 | }); 32 | } 33 | 34 | public Fontexturer() { 35 | super("Fontexturer"); 36 | setDefaultCloseOperation(EXIT_ON_CLOSE); 37 | 38 | GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); 39 | String[] fonts = env.getAvailableFontFamilyNames(); 40 | 41 | fontCombo = new JComboBox(fonts); 42 | fontCombo.setSelectedItem("Times New Roman"); 43 | fontCombo.addActionListener(this); 44 | fontCombo.setRenderer(new FontCellRenderer()); 45 | 46 | preview = new PreviewPanel(); 47 | preview.setSideLength(256); 48 | add(preview, BorderLayout.CENTER); 49 | 50 | JPanel controls = new JPanel(); 51 | controls.setLayout( new GridLayout(0,2) ); 52 | controls.setPreferredSize(new Dimension(300, 300)); 53 | controls.setBorder(new CompoundBorder(new TitledBorder("Settings"), new EmptyBorder(8, 8, 8, 8))); 54 | controls.add(new JLabel("Font")); 55 | controls.add(fontCombo); 56 | 57 | JCheckBox bounds = new JCheckBox("Show glyph boundaries"); 58 | bounds.addActionListener(this); 59 | controls.add(new JLabel(".")); 60 | controls.add(bounds); 61 | controls.add(new JLabel("Texture Width")); 62 | JPanel jp = new JPanel(); 63 | ButtonGroup bg = new ButtonGroup(); 64 | jp.add(makeRadio("128", bg)); 65 | jp.add(makeRadio("256", bg)); 66 | jp.add(makeRadio("512", bg)); 67 | controls.add(jp); 68 | 69 | controls.add(new JLabel("Cell Width")); 70 | JPanel jp2 = new JPanel(); 71 | bg2 = new ButtonGroup(); 72 | jp2.add(makeRadio( "8",bg2)); 73 | jp2.add(makeRadio("16",bg2)); 74 | jp2.add(makeRadio("32",bg2)); 75 | controls.add(jp2); 76 | 77 | 78 | controls.add(new JLabel("Font Size")); 79 | fontSpinner = new JSpinner(new SpinnerNumberModel(13, 1, 100, 1)); 80 | fontSpinner.addChangeListener(this); 81 | controls.add(fontSpinner); 82 | 83 | controls.add(new JLabel("Start Char")); 84 | minSpinner = new JSpinner(new SpinnerNumberModel(0,0,128,1)); 85 | minSpinner.addChangeListener(this); 86 | controls.add(minSpinner); 87 | 88 | JButton save = new JButton("Save image..."); 89 | save.addActionListener(this); 90 | controls.add(save); 91 | 92 | add(controls, BorderLayout.EAST); 93 | 94 | pack(); 95 | setLocationRelativeTo(null); 96 | } 97 | 98 | private JRadioButton makeRadio(String text, ButtonGroup bg) { 99 | JRadioButton btn = new JRadioButton(text); 100 | btn.addActionListener(this); 101 | bg.add(btn); 102 | return btn; 103 | } 104 | 105 | private void showSaveDialog() { 106 | JFileChooser fc = new JFileChooser(System.getProperty("user.dir")); 107 | fc.setFileFilter(new FileFilter() { 108 | public boolean accept(File f) { 109 | String s = f.getName(); 110 | return f.isDirectory() || s.endsWith(".png"); 111 | } 112 | 113 | public String getDescription() { 114 | return "PNG files (*.png)"; 115 | } 116 | 117 | }); 118 | int res = fc.showSaveDialog(this); 119 | if (res != JFileChooser.APPROVE_OPTION) 120 | return; 121 | try { 122 | preview.save(fc.getSelectedFile(), "png"); 123 | } catch (Exception e) { 124 | e.printStackTrace(); 125 | } 126 | } 127 | 128 | public void actionPerformed(ActionEvent e) { 129 | 130 | 131 | //System.out.println(e.getSource()); 132 | if(e.getSource() instanceof JComboBox) { 133 | preview.setFontName((String) fontCombo.getSelectedItem()); 134 | } else { 135 | String cmd = e.getActionCommand(); 136 | if(cmd.equals("8") || cmd.equals("16") || cmd.equals("32")) // TODO use properly defined actions... 137 | preview.setBoxSize(Integer.parseInt(cmd)); 138 | if(cmd.equals("128") || cmd.equals("256") || cmd.equals("512")) 139 | preview.setSideLength(Integer.parseInt(cmd)); 140 | else if(cmd.equals("Show glyph boundaries")) 141 | preview.setShowBounds(((JCheckBox) e.getSource()).isSelected()); 142 | else if(cmd.equals("Save image...")) 143 | showSaveDialog(); 144 | } 145 | } 146 | 147 | public void stateChanged(ChangeEvent e) { 148 | if (e.getSource() == fontSpinner ) 149 | preview.setFontSize(((Integer) fontSpinner.getValue()).intValue()); 150 | 151 | if (e.getSource() == minSpinner ) 152 | preview.setMin(((Integer) minSpinner.getValue()).intValue()); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tools/fontexturer/src/com/logiklabs/fontexturer/PreviewPanel.java: -------------------------------------------------------------------------------- 1 | package com.logiklabs.fontexturer; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Color; 5 | import java.awt.Dimension; 6 | import java.awt.Font; 7 | import java.awt.Graphics; 8 | import java.awt.Graphics2D; 9 | import java.awt.RenderingHints; 10 | import java.awt.font.TextLayout; 11 | import java.awt.geom.Rectangle2D; 12 | import java.awt.image.BufferedImage; 13 | import java.io.File; 14 | import java.io.IOException; 15 | 16 | import javax.imageio.ImageIO; 17 | import javax.swing.JPanel; 18 | import javax.swing.border.CompoundBorder; 19 | import javax.swing.border.EmptyBorder; 20 | import javax.swing.border.TitledBorder; 21 | 22 | public class PreviewPanel extends JPanel { 23 | private static char MIN_CH = '\u0000'; 24 | private static final char MAX_CH = '\u00ff'; 25 | 26 | private static final Color CHECKER_COL = new Color(220, 220, 220); 27 | 28 | private String fontName; 29 | private int fontSize; 30 | private Font font; 31 | 32 | private BufferedImage fontImage; 33 | 34 | private int sideLength; 35 | 36 | private boolean showBounds; 37 | private int boxSize=16; 38 | private int charsPerRow; 39 | 40 | public PreviewPanel() { 41 | this("Times New Roman", 13); 42 | } 43 | 44 | public PreviewPanel(String n, int s) { 45 | super(new BorderLayout()); 46 | 47 | fontName = n; 48 | fontSize = s; 49 | font = new Font(fontName, Font.PLAIN, fontSize); 50 | 51 | setPreferredSize(new Dimension(524, 524)); 52 | setBorder(new CompoundBorder(new TitledBorder("Preview"), 53 | new EmptyBorder(8, 8, 8, 8))); 54 | } 55 | 56 | public void setMin(int m) { 57 | MIN_CH = (char) m; 58 | updatePreview(); 59 | } 60 | 61 | public void setBoxSize(int s) { 62 | boxSize=s; 63 | updatePreview(); 64 | } 65 | 66 | public void setSideLength(int l) { 67 | if (l <= 0 || (l & (l - 1)) != 0) 68 | throw new IllegalArgumentException("length is not a positive power of 2"); 69 | sideLength = l; 70 | updatePreview(); 71 | } 72 | 73 | public void setFontSize(int sz) { 74 | fontSize = sz; 75 | font = new Font(fontName, Font.PLAIN, sz); 76 | updatePreview(); 77 | } 78 | 79 | public void setFontName(String name) { 80 | fontName = name; 81 | font = new Font(name, Font.PLAIN, fontSize); 82 | updatePreview(); 83 | } 84 | 85 | public void setShowBounds(boolean b) { 86 | showBounds = b; 87 | updatePreview(); 88 | } 89 | 90 | private void updatePreview() { 91 | fontImage = new BufferedImage(sideLength, sideLength, BufferedImage.TYPE_INT_ARGB); 92 | Graphics g = fontImage.getGraphics(); 93 | //int n = sideLength / 16; 94 | int n = sideLength / boxSize; 95 | for(int y = 0; y < n; y++) { 96 | for(int x = 0; x < n; x++) { 97 | if ((x & 0x1) == 0 ^ (y & 0x1) == 0) 98 | g.setColor(CHECKER_COL); 99 | else 100 | g.setColor(Color.white); 101 | //g.fillRect(x * 16, y * 16, 16, 16); 102 | g.fillRect(x * boxSize, y * boxSize, boxSize, boxSize); 103 | } 104 | } 105 | 106 | drawCharacters(fontImage.getGraphics(), Color.black); 107 | repaint(); 108 | } 109 | 110 | private void drawCharacters(Graphics _g, Color col) { 111 | Graphics2D g = (Graphics2D) _g; 112 | g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 113 | RenderingHints.VALUE_ANTIALIAS_ON); 114 | g.setFont(font); 115 | 116 | //boxSize = g.getFontMetrics().getHeight(); 117 | 118 | int off = 0; 119 | charsPerRow = sideLength / boxSize; 120 | for (char k = MIN_CH; k <= MAX_CH; k++, off++) { 121 | TextLayout layout = new TextLayout(String.valueOf(k), font, 122 | g.getFontRenderContext()); 123 | Rectangle2D rect = layout.getBounds(); 124 | 125 | int x = (off % charsPerRow) * boxSize; 126 | int y = (off / charsPerRow) * boxSize; 127 | 128 | float cx = 1 - (float) rect.getX(); 129 | float cy = boxSize - g.getFontMetrics().getDescent() - 1; 130 | 131 | g.setColor(col); 132 | layout.draw(g, x + cx, y + cy); 133 | 134 | if(showBounds) { 135 | rect.setRect(x + cx + rect.getX(), y + cy + rect.getY(), 136 | rect.getWidth(), rect.getHeight()); 137 | g.setColor(Color.green); 138 | g.draw(rect); 139 | 140 | g.setColor(Color.red); 141 | g.drawRect(x, y, boxSize, boxSize); 142 | } 143 | } 144 | } 145 | 146 | public void paintComponent(Graphics g) { 147 | super.paintComponent(g); 148 | if(fontImage == null) 149 | return; 150 | 151 | int halfLength = sideLength / 2; 152 | int x = getWidth() / 2 - halfLength; 153 | int y = getHeight() / 2 - halfLength; 154 | 155 | g.drawImage(fontImage, x, y, this); 156 | g.drawString(charsPerRow + " characters per row, " + boxSize + " px per character", 5, getHeight() - 5); 157 | } 158 | 159 | public void save(File file, String fmt) throws IOException { 160 | BufferedImage buf = new BufferedImage(sideLength, sideLength, BufferedImage.TYPE_INT_ARGB); 161 | drawCharacters(buf.getGraphics(), Color.white); 162 | ImageIO.write(buf, fmt, file); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /tools/obj2opengl/alien.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.62 (sub 0) OBJ File: 'alien.blend' 2 | # www.blender.org 3 | o Cube 4 | v 0.096767 -0.060478 -0.156216 5 | v 0.060181 -0.056989 0.127172 6 | v 0.095116 0.061152 -0.159148 7 | v 0.060760 0.059826 0.117395 8 | v 0.141757 -0.062416 -0.000559 9 | v -0.000354 -0.065130 -0.171060 10 | v 0.095657 -0.003257 -0.173646 11 | v -0.000341 -0.061059 0.159416 12 | v 0.078829 -0.000000 0.158601 13 | v 0.147861 0.062910 0.002211 14 | v -0.000354 0.067967 -0.171057 15 | v -0.000342 0.065315 0.157787 16 | v -0.000360 -0.065130 -0.002133 17 | v -0.000360 0.116199 -0.002948 18 | v 0.143307 -0.002326 0.021429 19 | v -0.000360 -0.000000 0.169513 20 | v 0.325327 -0.060549 0.075369 21 | v 0.314602 0.002326 0.087833 22 | v 0.328853 0.061736 0.073249 23 | v 0.315313 0.059022 -0.044049 24 | v 0.299101 -0.000000 -0.098988 25 | v 0.315313 -0.059022 -0.051648 26 | v 0.451219 -0.060039 0.082648 27 | v 0.414229 -0.046374 0.020912 28 | v 0.409201 -0.000000 -0.018622 29 | v 0.414229 0.046374 0.028591 30 | v 0.448982 0.061057 0.088720 31 | v 0.458583 -0.000000 0.084984 32 | v 0.422124 -0.056989 0.190147 33 | v 0.449488 0.003256 0.227446 34 | v 0.433527 0.056989 0.190880 35 | v 0.369231 0.056989 0.191650 36 | v 0.358915 -0.056989 0.189338 37 | v 0.341251 -0.003257 0.227351 38 | v -0.000354 0.056989 -0.203247 39 | v -0.000354 -0.005427 -0.204492 40 | v -0.000341 -0.061059 -0.202624 41 | v 0.073080 0.061059 -0.200755 42 | v 0.076575 0.005427 -0.202001 43 | v 0.073080 -0.056989 -0.200755 44 | v -0.097938 -0.060478 -0.156216 45 | v -0.061319 -0.056989 0.127172 46 | v -0.096293 0.061152 -0.159148 47 | v -0.061898 0.059826 0.117395 48 | v -0.142946 -0.062416 -0.000559 49 | v -0.096871 -0.003257 -0.173646 50 | v -0.080006 -0.000000 0.158601 51 | v -0.149053 0.062910 0.002211 52 | v -0.144522 -0.002326 0.021429 53 | v -0.326541 -0.060549 0.075369 54 | v -0.315816 0.002326 0.087833 55 | v -0.330067 0.061736 0.073249 56 | v -0.316528 0.059022 -0.044049 57 | v -0.300315 -0.000000 -0.098988 58 | v -0.316527 -0.059022 -0.051648 59 | v -0.452433 -0.060039 0.082648 60 | v -0.415443 -0.046374 0.020912 61 | v -0.410415 -0.000000 -0.018622 62 | v -0.415443 0.046374 0.028591 63 | v -0.450196 0.061057 0.088720 64 | v -0.459798 -0.000000 0.084984 65 | v -0.423339 -0.056989 0.190147 66 | v -0.450702 0.003256 0.227446 67 | v -0.434741 0.056989 0.190880 68 | v -0.370445 0.056989 0.191650 69 | v -0.360129 -0.056989 0.189338 70 | v -0.342466 -0.003257 0.227351 71 | v -0.074218 0.061059 -0.200755 72 | v -0.077738 0.005427 -0.202001 73 | v -0.074218 -0.056989 -0.200755 74 | vt 0.090561 0.892464 75 | vt 0.174157 0.891088 76 | vt 0.094842 0.821840 77 | vt 0.172939 0.814538 78 | vt 0.096483 0.962022 79 | vt 0.174275 0.963137 80 | vt 0.134551 0.181984 81 | vt 0.093054 0.140788 82 | vt 0.132803 0.065133 83 | vt 0.092826 0.062505 84 | vt 0.060370 0.202184 85 | vt 0.031352 0.167756 86 | vt 0.856378 0.783846 87 | vt 0.951635 0.792874 88 | vt 0.937563 0.751867 89 | vt 0.898306 0.822877 90 | vt 0.870696 0.903274 91 | vt 0.915958 0.898560 92 | vt 0.526691 0.322537 93 | vt 0.525510 0.222589 94 | vt 0.451447 0.315879 95 | vt 0.559306 0.279725 96 | vt 0.502295 0.661977 97 | vt 0.400230 0.680695 98 | vt 0.434514 0.637616 99 | vt 0.421785 0.752370 100 | vt 0.449762 0.507762 101 | vt 0.369880 0.528127 102 | vt 0.596802 0.432059 103 | vt 0.525707 0.452068 104 | vt 0.318620 0.647258 105 | vt 0.628884 0.312836 106 | vt 0.665195 0.262923 107 | vt 0.284929 0.697461 108 | vt 0.270221 0.601360 109 | vt 0.202977 0.600637 110 | vt 0.752992 0.355188 111 | vt 0.679418 0.354341 112 | vt 0.728286 0.484672 113 | vt 0.825770 0.494597 114 | vt 0.229098 0.471568 115 | vt 0.140598 0.458843 116 | vt 0.340416 0.259880 117 | vt 0.628241 0.702049 118 | vt 0.532337 0.682687 119 | vt 0.420245 0.280740 120 | vt 0.473994 0.123879 121 | vt 0.564263 0.072726 122 | vt 0.541570 0.158676 123 | vt 0.498588 0.052036 124 | vt 0.407869 0.823655 125 | vt 0.386261 0.916516 126 | vt 0.494493 0.858016 127 | vt 0.461410 0.941823 128 | vt 0.660657 0.917221 129 | vt 0.325476 0.079487 130 | vt 0.000000 0.000000 131 | vt 0.000000 1.000000 132 | vt 1.000000 1.000000 133 | vt 1.000000 0.000000 134 | vn -0.506424 0.021882 -0.861965 135 | vn 0.000092 -0.006378 -0.999969 136 | vn -0.404859 -0.583056 -0.704337 137 | vn 0.000153 -0.679830 -0.733360 138 | vn -0.415815 0.602039 -0.681600 139 | vn 0.000000 0.571490 -0.820582 140 | vn -0.340098 -0.841639 -0.419446 141 | vn 0.000122 -0.997711 -0.067385 142 | vn -0.656545 -0.011628 -0.754173 143 | vn -0.414838 0.773644 -0.478927 144 | vn 0.000122 0.966308 -0.257271 145 | vn 0.364666 0.810907 0.457595 146 | vn -0.653371 -0.005890 0.756981 147 | vn 0.619343 -0.011872 0.784997 148 | vn -0.482040 0.778405 0.402112 149 | vn -0.414319 -0.805628 0.423383 150 | vn 0.419904 -0.802667 0.423536 151 | vn 0.740074 0.052919 0.670400 152 | vn 0.314615 -0.898282 0.306681 153 | vn 0.287393 0.912748 0.290231 154 | vn -0.712516 -0.686544 -0.144658 155 | vn -0.681204 0.713981 -0.161687 156 | vn -0.985290 0.006836 -0.170568 157 | vn -0.556536 -0.713095 -0.426252 158 | vn -0.731040 0.038575 -0.681204 159 | vn -0.544328 0.727042 -0.418439 160 | vn -0.301279 0.858852 -0.414167 161 | vn -0.488449 0.029267 -0.872066 162 | vn -0.313303 -0.839473 -0.443922 163 | vn -0.106510 -0.934721 0.338969 164 | vn -0.226661 0.889706 0.396222 165 | vn -0.409070 -0.021393 0.912229 166 | vn -0.550249 -0.597491 0.583239 167 | vn -0.143559 0.037935 0.988891 168 | vn -0.573931 0.031007 0.818293 169 | vn 0.001312 -0.680837 0.732414 170 | vn -0.585376 0.554918 0.591052 171 | vn 0.001495 0.595599 0.803247 172 | vn 0.000580 0.998932 0.045991 173 | vn 0.000031 -0.999847 0.016999 174 | vn 0.506912 0.021790 -0.861721 175 | vn 0.405438 -0.582781 -0.704215 176 | vn 0.416242 0.601825 -0.681539 177 | vn 0.340312 -0.841548 -0.419446 178 | vn 0.657094 -0.011597 -0.753716 179 | vn 0.415143 0.773461 -0.478896 180 | vn -0.364666 0.810907 0.457595 181 | vn -0.619343 -0.011872 0.784997 182 | vn 0.653371 -0.005890 0.756981 183 | vn 0.482040 0.778405 0.402112 184 | vn -0.419904 -0.802667 0.423536 185 | vn 0.414319 -0.805628 0.423383 186 | vn -0.740074 0.052919 0.670400 187 | vn -0.314615 -0.898282 0.306681 188 | vn -0.287393 0.912748 0.290231 189 | vn 0.712516 -0.686544 -0.144658 190 | vn 0.681204 0.713981 -0.161687 191 | vn 0.985290 0.006836 -0.170568 192 | vn 0.556536 -0.713095 -0.426252 193 | vn 0.731040 0.038575 -0.681204 194 | vn 0.544328 0.727042 -0.418439 195 | vn 0.301279 0.858852 -0.414167 196 | vn 0.488479 0.029267 -0.872066 197 | vn 0.313334 -0.839473 -0.443922 198 | vn 0.106510 -0.934721 0.338939 199 | vn 0.227058 0.889615 0.396222 200 | vn 0.354686 -0.033265 0.934385 201 | vn 0.413160 -0.784875 0.461745 202 | vn 0.574206 0.031007 0.818079 203 | vn 0.500961 0.696616 0.513535 204 | s 1 205 | f 69/1/1 36/2/2 70/3/3 206 | f 70/3/3 36/2/2 37/4/4 207 | f 68/5/5 35/6/6 69/1/1 208 | f 69/1/1 35/6/6 36/2/2 209 | f 41/7/7 70/8/3 6/9/8 210 | f 6/9/8 70/8/3 37/10/4 211 | f 46/11/9 70/8/3 41/7/7 212 | f 46/11/9 69/12/1 70/8/3 213 | f 43/13/10 69/14/1 46/15/9 214 | f 43/13/10 68/16/5 69/14/1 215 | f 11/17/11 68/16/5 43/13/10 216 | f 11/17/11 35/18/6 68/16/5 217 | f 65/19/12 63/20/13 67/21/14 218 | f 65/19/12 64/22/15 63/20/13 219 | f 67/23/14 62/24/16 66/25/17 220 | f 67/23/14 63/26/13 62/24/16 221 | f 51/27/18 66/25/17 50/28/19 222 | f 51/27/18 67/23/14 66/25/17 223 | f 52/29/20 65/19/12 51/30/18 224 | f 51/30/18 65/19/12 67/21/14 225 | f 50/28/19 62/24/16 56/31/21 226 | f 50/28/19 66/25/17 62/24/16 227 | f 60/32/22 65/19/12 52/29/20 228 | f 60/32/22 64/22/15 65/19/12 229 | f 61/33/23 64/22/15 60/32/22 230 | f 61/33/23 63/20/13 64/22/15 231 | f 56/31/21 62/24/16 61/34/23 232 | f 61/34/23 62/24/16 63/26/13 233 | f 57/35/24 61/34/23 58/36/25 234 | f 57/35/24 56/31/21 61/34/23 235 | f 58/37/25 61/33/23 59/38/26 236 | f 59/38/26 61/33/23 60/32/22 237 | f 53/39/27 59/38/26 52/29/20 238 | f 52/29/20 59/38/26 60/32/22 239 | f 54/40/28 58/37/25 53/39/27 240 | f 53/39/27 58/37/25 59/38/26 241 | f 55/41/29 58/36/25 54/42/28 242 | f 55/41/29 57/35/24 58/36/25 243 | f 50/28/19 57/35/24 55/41/29 244 | f 50/28/19 56/31/21 57/35/24 245 | f 45/43/30 55/41/29 41/7/7 246 | f 45/43/30 50/28/19 55/41/29 247 | f 41/7/7 54/42/28 46/11/9 248 | f 41/7/7 55/41/29 54/42/28 249 | f 46/15/9 54/40/28 43/13/10 250 | f 43/13/10 54/40/28 53/39/27 251 | f 43/13/10 53/39/27 48/44/31 252 | f 48/44/31 53/39/27 52/29/20 253 | f 48/44/31 51/30/18 49/45/32 254 | f 48/44/31 52/29/20 51/30/18 255 | f 49/46/32 50/28/19 45/43/30 256 | f 49/46/32 51/27/18 50/28/19 257 | f 42/47/33 16/48/34 47/49/35 258 | f 42/47/33 8/50/36 16/48/34 259 | f 47/51/35 16/52/34 44/53/37 260 | f 44/53/37 16/52/34 12/54/38 261 | f 45/43/30 42/47/33 49/46/32 262 | f 49/46/32 42/47/33 47/49/35 263 | f 49/45/32 44/53/37 48/44/31 264 | f 49/45/32 47/51/35 44/53/37 265 | f 48/44/31 44/53/37 14/55/39 266 | f 14/55/39 44/53/37 12/54/38 267 | f 43/13/10 14/55/39 11/17/11 268 | f 43/13/10 48/44/31 14/55/39 269 | f 41/7/7 13/56/40 45/43/30 270 | f 41/7/7 6/9/8 13/56/40 271 | f 45/43/30 13/56/40 42/47/33 272 | f 42/47/33 13/56/40 8/50/36 273 | f 39/1/41 40/3/42 36/2/2 274 | f 40/3/42 37/4/4 36/2/2 275 | f 38/5/43 39/1/41 35/6/6 276 | f 39/1/41 36/2/2 35/6/6 277 | f 1/7/44 6/9/8 40/8/42 278 | f 6/9/8 37/10/4 40/8/42 279 | f 7/11/45 1/7/44 40/8/42 280 | f 7/11/45 40/8/42 39/12/41 281 | f 3/13/46 7/15/45 39/14/41 282 | f 3/13/46 39/14/41 38/16/43 283 | f 11/17/11 3/13/46 38/16/43 284 | f 11/17/11 38/16/43 35/18/6 285 | f 32/19/47 34/21/48 30/20/49 286 | f 32/19/47 30/20/49 31/22/50 287 | f 34/23/48 33/25/51 29/24/52 288 | f 34/23/48 29/24/52 30/26/49 289 | f 18/27/53 17/28/54 33/25/51 290 | f 18/27/53 33/25/51 34/23/48 291 | f 19/29/55 18/30/53 32/19/47 292 | f 18/30/53 34/21/48 32/19/47 293 | f 17/28/54 23/31/56 29/24/52 294 | f 17/28/54 29/24/52 33/25/51 295 | f 27/32/57 19/29/55 32/19/47 296 | f 27/32/57 32/19/47 31/22/50 297 | f 28/33/58 27/32/57 31/22/50 298 | f 28/33/58 31/22/50 30/20/49 299 | f 23/31/56 28/34/58 29/24/52 300 | f 28/34/58 30/26/49 29/24/52 301 | f 24/35/59 25/36/60 28/34/58 302 | f 24/35/59 28/34/58 23/31/56 303 | f 25/37/60 26/38/61 28/33/58 304 | f 26/38/61 27/32/57 28/33/58 305 | f 20/39/62 19/29/55 26/38/61 306 | f 19/29/55 27/32/57 26/38/61 307 | f 21/40/63 20/39/62 25/37/60 308 | f 20/39/62 26/38/61 25/37/60 309 | f 22/41/64 21/42/63 25/36/60 310 | f 22/41/64 25/36/60 24/35/59 311 | f 17/28/54 22/41/64 24/35/59 312 | f 17/28/54 24/35/59 23/31/56 313 | f 5/43/65 1/7/44 22/41/64 314 | f 5/43/65 22/41/64 17/28/54 315 | f 1/7/44 7/11/45 21/42/63 316 | f 1/7/44 21/42/63 22/41/64 317 | f 7/15/45 3/13/46 21/40/63 318 | f 3/13/46 20/39/62 21/40/63 319 | f 3/13/46 10/44/66 20/39/62 320 | f 10/44/66 19/29/55 20/39/62 321 | f 10/44/66 15/45/67 18/30/53 322 | f 10/44/66 18/30/53 19/29/55 323 | f 15/46/67 5/43/65 17/28/54 324 | f 15/46/67 17/28/54 18/27/53 325 | f 2/47/68 9/49/69 16/48/34 326 | f 2/47/68 16/48/34 8/50/36 327 | f 9/51/69 4/53/70 16/52/34 328 | f 4/53/70 12/54/38 16/52/34 329 | f 5/43/65 15/46/67 2/47/68 330 | f 15/46/67 9/49/69 2/47/68 331 | f 15/45/67 10/44/66 4/53/70 332 | f 15/45/67 4/53/70 9/51/69 333 | f 10/44/66 14/55/39 4/53/70 334 | f 14/55/39 12/54/38 4/53/70 335 | f 3/13/46 11/17/11 14/55/39 336 | f 3/13/46 14/55/39 10/44/66 337 | f 1/7/44 5/43/65 13/56/40 338 | f 1/7/44 13/56/40 6/9/8 339 | f 5/43/65 2/47/68 13/56/40 340 | f 2/47/68 8/50/36 13/56/40 341 | f 16/57/34 44/58/37 49/59/32 42/60/33 342 | -------------------------------------------------------------------------------- /tools/obj2opengl/blend/alien.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/tools/obj2opengl/blend/alien.blend -------------------------------------------------------------------------------- /tools/obj2opengl/blend/cube.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/tools/obj2opengl/blend/cube.blend -------------------------------------------------------------------------------- /tools/obj2opengl/blend/ground.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/tools/obj2opengl/blend/ground.blend -------------------------------------------------------------------------------- /tools/obj2opengl/blend/shot.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/tools/obj2opengl/blend/shot.blend -------------------------------------------------------------------------------- /tools/obj2opengl/blend/sphere.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chriscamacho/gles2framework/63527d7f4749a98ecaf825dc3cb102457503b3ad/tools/obj2opengl/blend/sphere.blend -------------------------------------------------------------------------------- /tools/obj2opengl/builder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "OBJ.h" 5 | 6 | int main (int argc, char *argv[]) 7 | { 8 | 9 | if (argc!=2) exit(-1); 10 | 11 | //OBJNumVerts 12 | //OBJVerts 13 | //OBJNormals 14 | //OBJTexCoords 15 | 16 | // printf("%s\n",argv[1]); 17 | 18 | unsigned int magic; 19 | magic=0x614F4247; // GBOa in little endian - initial version "a" 20 | 21 | FILE *pFile; 22 | pFile = fopen ( argv[1] , "wb" ); 23 | fwrite (&magic , 1 , sizeof(unsigned int) , pFile ); 24 | fwrite (&OBJNumVerts , 1 , sizeof(unsigned int) , pFile ); 25 | fwrite (OBJVerts , 1 , sizeof(float) * 3 * OBJNumVerts, pFile ); 26 | fwrite (OBJNormals , 1 , sizeof(float) * 3 * OBJNumVerts , pFile ); 27 | fwrite (OBJTexCoords , 1 , sizeof(float) * 2 * OBJNumVerts , pFile ); 28 | fclose(pFile); 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /tools/obj2opengl/cube.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.62 (sub 0) OBJ File: 'cube.blend' 2 | # www.blender.org 3 | o Cube_Cube.002 4 | v 0.5 -0.5 -0.5 5 | v 0.5 -0.5 0.5 6 | v -0.5 -0.5 0.5 7 | v -0.5 -0.5 -0.5 8 | v 0.5 0.5 -0.5 9 | v 0.5 0.5 0.5 10 | v -0.5 0.5 0.5 11 | v -0.5 0.5 -0.5 12 | vt 0.338526 0.338526 13 | vt 0.663522 0.338526 14 | vt 0.663522 0.663522 15 | vt 0.338526 0.663522 16 | vt 0.005288 0.005288 17 | vt 0.329713 0.005288 18 | vt 0.329713 0.329713 19 | vt 0.005288 0.329713 20 | vt 0.993727 0.662349 21 | vt 0.670272 0.662349 22 | vt 0.670272 0.338894 23 | vt 0.993727 0.338894 24 | vt 0.337449 0.004949 25 | vt 0.663207 0.004949 26 | vt 0.663338 0.330314 27 | vt 0.337711 0.330838 28 | vt 0.004502 0.336816 29 | vt 0.331568 0.336816 30 | vt 0.331568 0.663882 31 | vt 0.004408 0.663882 32 | vt 0.338744 0.670255 33 | vt 0.664703 0.670255 34 | vt 0.664703 0.995394 35 | vt 0.338744 0.995394 36 | vn 0.000000 -1.000000 0.000000 37 | vn 0.000000 1.000000 0.000000 38 | vn 1.000000 0.000000 0.000000 39 | vn -0.000000 -0.000000 1.000000 40 | vn -1.000000 -0.000000 -0.000000 41 | vn 0.000000 0.000000 -1.000000 42 | s off 43 | f 1/1/1 2/2/1 3/3/1 44 | f 1/1/1 3/3/1 4/4/1 45 | f 5/5/2 8/6/2 7/7/2 46 | f 5/5/2 7/7/2 6/8/2 47 | f 1/9/3 5/10/3 6/11/3 48 | f 1/9/3 6/11/3 2/12/3 49 | f 2/13/4 6/14/4 7/15/4 50 | f 2/13/4 7/15/4 3/16/4 51 | f 3/17/5 7/18/5 8/19/5 52 | f 3/17/5 8/19/5 4/20/5 53 | f 5/21/6 1/22/6 4/23/6 54 | f 5/21/6 4/23/6 8/24/6 55 | -------------------------------------------------------------------------------- /tools/obj2opengl/gbotest.c: -------------------------------------------------------------------------------- 1 | /* 2 | gcc -std=gnu99 gbotest.c -o gbotest 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main (int argc, char *argv[]) 9 | { 10 | if (argc!=2) { 11 | printf("please specify a GBO file\n"); 12 | return -1; 13 | } 14 | FILE *pFile; 15 | pFile = fopen( argv[1], "rb" ); 16 | 17 | unsigned int magic; 18 | int NumVerts; 19 | fread (&magic,1, sizeof(unsigned int), pFile ); 20 | if (magic!=0x614f4247) { 21 | printf("Does not appear to be a version 'a' GBO file\n"); 22 | return -2; 23 | } 24 | fread(&NumVerts,1,sizeof(unsigned int), pFile ); 25 | printf("Obj contains %i verts\n",NumVerts); 26 | 27 | float* Verts = malloc(sizeof(float) * 3 * NumVerts); 28 | fread(Verts,1,sizeof(float) * 3 * NumVerts, pFile ); 29 | for (int i=0; i< NumVerts*3; i=i+3) 30 | printf("%f\t%f\t%f\n",Verts[i],Verts[i+1],Verts[i+2]); 31 | free(Verts); 32 | 33 | printf("\nNormals\n"); 34 | float* Norms = malloc(sizeof(float) * 3 * NumVerts); 35 | fread(Norms,1,sizeof(float) * 3 * NumVerts, pFile ); 36 | for (int i=0; i< NumVerts*3; i=i+3) 37 | printf("%f\t%f\t%f\n",Norms[i],Norms[i+1],Norms[i+2]); 38 | free(Norms); 39 | 40 | printf("\nTexture coordinates\n"); 41 | float* TexCoords = malloc(sizeof(float) * 2 * NumVerts); 42 | fread(TexCoords,1,sizeof(float) * 2 * NumVerts, pFile ); 43 | for (int i=0; i< NumVerts*2; i=i+2) 44 | printf("%f\t%f\n",TexCoords[i],TexCoords[i+1]); 45 | free(TexCoords); 46 | 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tools/obj2opengl/makeGBO.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./obj2opengl.pl -noverbose -noScale -noMove -o OBJ.h $1.obj 4 | gcc builder.c -o builder 5 | ./builder $1.gbo 6 | 7 | -------------------------------------------------------------------------------- /tools/obj2opengl/readme.txt: -------------------------------------------------------------------------------- 1 | files for WIP wavefront to Gles Binary Obj convertor 2 | 3 | builder.c 4 | clean.sh 5 | makeGBO.sh 6 | 7 | 8 | files from obj2opengl script 9 | 10 | LICENSE.txt 11 | obj2opengl.pl 12 | 13 | to compile for example ship.obj 14 | 15 | ./makeGBO ship 16 | 17 | the compiled object will be called ship.gbo - copy this to your 18 | resources directory 19 | 20 | see README.md for loading gbo's 21 | 22 | -------------------------------------------------------------------------------- /tools/obj2opengl/shot.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.62 (sub 0) OBJ File: 'shot.blend' 2 | # www.blender.org 3 | o Cube 4 | v 0.070187 -0.054059 -0.053106 5 | v 0.070187 -0.054059 0.071893 6 | v -0.054813 -0.054059 0.071893 7 | v -0.054813 -0.054059 -0.053107 8 | v 0.070187 0.070941 -0.053106 9 | v 0.070187 0.070941 0.071894 10 | v -0.054813 0.070941 0.071893 11 | v -0.054813 0.070941 -0.053106 12 | v 0.007687 0.195941 0.009394 13 | v 0.195187 0.008441 0.009394 14 | v 0.007687 0.008441 0.196893 15 | v 0.007687 0.008441 -0.178107 16 | v -0.179813 0.008441 0.009393 17 | v 0.007687 -0.179059 0.009393 18 | vt 0.000000 1.000000 19 | vt 0.000000 0.000000 20 | vt 0.500000 0.500000 21 | vt 0.999999 0.000000 22 | vt 1.000000 1.000000 23 | vt 1.000000 0.000000 24 | vn -0.894427 0.447214 -0.000000 25 | vn -0.000000 0.447214 0.894427 26 | vn 0.000000 0.447214 -0.894427 27 | vn 0.894427 0.447214 0.000000 28 | vn 0.447214 0.894427 0.000000 29 | vn 0.447213 -0.000000 0.894427 30 | vn 0.447214 0.000000 -0.894427 31 | vn 0.447214 -0.894427 0.000000 32 | vn -0.000000 0.894427 0.447214 33 | vn -0.894427 0.000000 0.447213 34 | vn 0.894427 0.000000 0.447214 35 | vn -0.000000 -0.894427 0.447214 36 | vn 0.000000 0.894427 -0.447213 37 | vn -0.894427 0.000000 -0.447214 38 | vn 0.894427 -0.000000 -0.447213 39 | vn 0.000000 -0.894427 -0.447214 40 | vn -0.447214 0.894427 -0.000000 41 | vn -0.447213 0.000000 -0.894427 42 | vn -0.447214 0.000000 0.894427 43 | vn -0.447214 -0.894427 -0.000000 44 | vn -0.894427 -0.447214 -0.000000 45 | vn -0.000000 -0.447214 0.894427 46 | vn 0.000000 -0.447214 -0.894427 47 | vn 0.894427 -0.447214 0.000000 48 | s off 49 | f 8/1/1 7/2/1 9/3/1 50 | f 7/2/2 6/4/2 9/3/2 51 | f 5/5/3 8/1/3 9/3/3 52 | f 6/4/4 5/5/4 9/3/4 53 | f 5/5/5 6/1/5 10/3/5 54 | f 6/1/6 2/2/6 10/3/6 55 | f 1/6/7 5/5/7 10/3/7 56 | f 2/2/8 1/6/8 10/3/8 57 | f 6/5/9 7/1/9 11/3/9 58 | f 7/1/10 3/2/10 11/3/10 59 | f 2/6/11 6/5/11 11/3/11 60 | f 3/2/12 2/6/12 11/3/12 61 | f 8/2/13 5/6/13 12/3/13 62 | f 4/1/14 8/2/14 12/3/14 63 | f 5/6/15 1/5/15 12/3/15 64 | f 1/5/16 4/1/16 12/3/16 65 | f 7/1/17 8/2/17 13/3/17 66 | f 8/2/18 4/6/18 13/3/18 67 | f 3/5/19 7/1/19 13/3/19 68 | f 4/6/20 3/5/20 13/3/20 69 | f 3/2/21 4/6/21 14/3/21 70 | f 2/1/22 3/2/22 14/3/22 71 | f 4/6/23 1/5/23 14/3/23 72 | f 1/5/24 2/1/24 14/3/24 73 | --------------------------------------------------------------------------------