├── .github └── FUNDING.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── bunnygut.cpp ├── geometric.h ├── glutil.h ├── linalg.h ├── main.cpp ├── misc.h ├── progmesh.cpp ├── progmesh.h ├── rabdata.cpp ├── rabdata.h └── winmain.cpp /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: dougbinks 2 | patreon: enkisoftware 3 | open_collective: # Replace with a single Open Collective username 4 | ko_fi: # Replace with a single Ko-fi username 5 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 6 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 7 | liberapay: # Replace with a single Liberapay username 8 | issuehunt: # Replace with a single IssueHunt username 9 | otechie: # Replace with a single Otechie username 10 | custom: https://www.enkisoftware.com/avoyd 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "glfw"] 2 | path = glfw 3 | url = https://github.com/glfw/glfw 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required( VERSION 2.8 ) 2 | 3 | project( BunnyLOD ) 4 | 5 | find_package( OpenGL REQUIRED ) 6 | 7 | include_directories( "glfw/include" ) 8 | include_directories( ${OPENGL_INCLUDE_DIRS} ) 9 | 10 | set( GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW lib only" ) 11 | set( GLFW_BUILD_TESTS OFF CACHE BOOL "GLFW lib only" ) 12 | set( GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW lib only" ) 13 | set( GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" ) 14 | 15 | add_subdirectory( glfw ) 16 | 17 | if( WIN32 ) 18 | SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup" ) 19 | endif() 20 | if( UNIX ) 21 | SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14" ) 22 | endif() 23 | if( APPLE ) 24 | SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) 25 | endif() 26 | 27 | set( BunnyLOD-SRC 28 | main.cpp 29 | bunnygut.cpp 30 | progmesh.cpp 31 | progmesh.h 32 | rabdata.cpp 33 | rabdata.h 34 | linalg.h 35 | glutil.h 36 | geometric.h 37 | misc.h 38 | ) 39 | 40 | 41 | add_executable( BunnyLOD ${BunnyLOD-SRC} ) 42 | target_link_libraries( BunnyLOD ${OPENGL_LIBRARIES} glfw ${GLFW_LIBRARIES} ) 43 | if( MSVC ) 44 | if(${CMAKE_VERSION} VERSION_LESS "3.6.0") 45 | message( "\n\t[ WARNING ]\n\n\tCMake version lower than 3.6.\n\n\t - Please update CMake and rerun; OR\n\t - Manually set 'BunnyLOD' as StartUp Project in Visual Studio.\n" ) 46 | else() 47 | set_property( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT BunnyLOD ) 48 | endif() 49 | endif() 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Stan Melax 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Original code: https://github.com/melax/sandbox/tree/master/bunnylod 2 | 3 | More information & article link: http://www.melax.com/polychop 4 | 5 | Polygon Reduction Demo 6 | By Stan Melax (c) 1998 7 | http://www.melax.com 8 | 9 | Mouse dragging spins the rabbit. 10 | 11 | August 2014: code style upgraded to be more consistent with graphics/gamdev conventions 12 | 13 | MIT Licensed as per https://github.com/melax/sandbox/blob/master/LICENSE 14 | 15 | # BunnyLOD Cross Platform Port 16 | May 2020: Cross platform port using GLFW and CMake by Doug Binks 17 | 18 | I have made sufficient and minimal changes to Stan Melax's code to get it running with GLFW on Windows, OSX and Linux. 19 | 20 | The main interesting code is in [progmesh.h](https://github.com/dougbinks/BunnyLOD/blob/master/progmesh.h) and [progmesh.cpp](https://github.com/dougbinks/BunnyLOD/blob/master/progmesh.cpp). 21 | 22 | The code requires a C++14 compatible compiler. Visual Studio on Windows, Clang on OSX and GCC on Linux tested. 23 | 24 | ![BunnyLOD screenshot](https://github.com/dougbinks/images/blob/master/BunnyLOD.jpg?raw=true) 25 | 26 | ## Getting the code 27 | 28 | The easiest way to get hold of the starter code is to run the following command using a shell you can run git from: 29 | 30 | ``` 31 | git clone --recursive https://github.com/dougbinks/BunnyLOD 32 | ``` 33 | 34 | If you are on Windows you can download git from [git-scm.com/download/win](https://git-scm.com/download/win) and use the right click menu in Windows File Explorer to "Git Bash here" and then run git commands. 35 | 36 | This will create the directory _GLFW-CMake-starter_ and get the latest source code, using the ```--recursive``` option to download the GLFW code which is included in the repository as a submodule. If you want to run further git commands from the command line you'll need to cd into the directory: 37 | 38 | ``` 39 | cd BunnyLOD 40 | ``` 41 | 42 | Alternatively you can use a git GUI program such as [Fork](https://git-fork.com/) to get the code. Most of these will automatically download the git submodules. 43 | 44 | If you download the code from GitHub via the "Download ZIP" approach, you'll also need to download GLFW into the _glfw_ folder. The correct version can be found by clicking on the _glfw_ folder you see on the [front page of the _BunnyLOD_ GitHub repository](https://github.com/dougbinks/BunnyLOD). 45 | 46 | ## Using CMake to create the project 47 | 48 | From a command prompt in the `BunnyLOD` directory: 49 | 1. `mkdir build` 50 | 1. `cd build` 51 | 1. `cmake ..` 52 | 1. Either run `make all` or for Visual Studio open `BunnyLOD.sln` 53 | 54 | ## Also see 55 | 56 | [BGFX](https://github.com/bkaradzic/bgfx) example 42-bunnlod by [cloudwu](https://github.com/cloudwu): 57 | https://bkaradzic.github.io/bgfx/examples.html#bunnylod 58 | ![BGFX example 42-bunnlod screenshot](https://github.com/bkaradzic/bgfx/raw/master/examples/42-bunnylod/screenshot.png) 59 | 60 | This port to render with the [BGFX GFX API](https://github.com/bkaradzic/bgfx) also adds a [Dear ImGui UI](https://github.com/ocornut/imgui) and the code is converted to C. 61 | 62 | -------------------------------------------------------------------------------- /bunnygut.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Polygon Reduction Demo by Stan Melax (c) 1998 3 | * Permission to use any of this code wherever you want is granted.. 4 | * Although, please do acknowledge authorship if appropriate. 5 | * 6 | * This module initializes the bunny model data and calls 7 | * the polygon reduction routine. At each frame the RenderModel() 8 | * routine is called to draw the model. This module also 9 | * animates the parameters (such as number of vertices to 10 | * use) to show the model at various levels of detail. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #pragma warning(disable : 4244) 19 | 20 | #include "progmesh.h" 21 | #include "rabdata.h" 22 | #include "glutil.h" 23 | #include "geometric.h" 24 | 25 | int render_num; // number of vertices to draw with 26 | float lodbase=0.5f; // the fraction of vertices used to morph toward 27 | float morph=1.0f; // where to render between 2 levels of detail 28 | std::vector vert; // global Array of vertices 29 | std::vector tri; // global Array of triangles 30 | std::vector collapse_map; // to which neighbor each vertex collapses 31 | int renderpolycount=0; // polygons rendered in the current frame 32 | float3 model_position; // position of bunny 33 | float4 model_orientation(0,0,0,1); // orientation of bunny 34 | 35 | // Note that the use of the Map() function and the collapse_map 36 | // Array isn't part of the polygon reduction algorithm. 37 | // We just set up this system here in this module 38 | // so that we could retrieve the model at any desired vertex count. 39 | // Therefore if this part of the program confuses you, then 40 | // dont worry about it. It might help to look over the progmesh.cpp 41 | // module first. 42 | 43 | // Map() 44 | // 45 | // When the model is rendered using a maximum of mx vertices 46 | // then it is vertices 0 through mx-1 that are used. 47 | // We are able to do this because the vertex Array 48 | // gets sorted according to the collapse order. 49 | // The Map() routine takes a vertex number 'a' and the 50 | // maximum number of vertices 'mx' and returns the 51 | // appropriate vertex in the range 0 to mx-1. 52 | // When 'a' is greater than 'mx' the Map() routine 53 | // follows the chain of edge collapses until a vertex 54 | // within the limit is reached. 55 | // An example to make this clear: assume there is 56 | // a triangle with vertices 1, 3 and 12. But when 57 | // rendering the model we limit ourselves to 10 vertices. 58 | // In that case we find out how vertex 12 was removed 59 | // by the polygon reduction algorithm. i.e. which 60 | // edge was collapsed. Lets say that vertex 12 was collapsed 61 | // to vertex number 7. This number would have been stored 62 | // in the collapse_map array (i.e. collapse_map[12]==7). 63 | // Since vertex 7 is in range (less than max of 10) we 64 | // will want to render the triangle 1,3,7. 65 | // Pretend now that we want to limit ourselves to 5 vertices. 66 | // and vertex 7 was collapsed to vertex 3 67 | // (i.e. collapse_map[7]==3). Then triangle 1,3,12 would now be 68 | // triangle 1,3,3. i.e. this polygon was removed by the 69 | // progressive mesh polygon reduction algorithm by the time 70 | // it had gotten down to 5 vertices. 71 | // No need to draw a one dimensional polygon. :-) 72 | int Map(int a,int mx) { 73 | if(mx<=0) return 0; 74 | while(a>=mx) { 75 | a=collapse_map[a]; 76 | } 77 | return a; 78 | } 79 | 80 | void DrawModelTriangles() { 81 | assert(collapse_map.size()); 82 | renderpolycount=0; 83 | for (unsigned int i = 0; i &permutation) { 118 | // rearrange the vertex Array 119 | std::vector temp_Array; 120 | unsigned int i; 121 | assert(permutation.size() == vert.size()); 122 | for (i = 0; i permutation; 157 | GetRabbitData(); 158 | 159 | ProgressiveMesh(vert,tri,collapse_map,permutation); 160 | 161 | PermuteVertices(permutation); 162 | model_position = float3(0,0,-3); 163 | float4 yaw = QuatFromAxisAngle(float3(0, 1, 0), -3.14f / 4); // 45 degrees 164 | float4 pitch = QuatFromAxisAngle(float3(1, 0, 0), 3.14f / 12); // 15 degrees 165 | model_orientation = qmul(pitch,yaw); 166 | } 167 | 168 | void StatusDraw() { 169 | // Draw a slider type widget looking thing 170 | // to show portion of vertices being used 171 | float b = (float)render_num / (float)vert.size(); 172 | float a = b*(lodbase ); 173 | glDisable(GL_LIGHTING); 174 | glMatrixMode( GL_PROJECTION ); 175 | glPushMatrix(); 176 | glLoadIdentity(); 177 | glOrtho(-0.15,15,-0.1,1.1,-0.1,100); 178 | glMatrixMode( GL_MODELVIEW ); 179 | 180 | glPushMatrix(); 181 | glLoadIdentity(); 182 | glBegin(GL_POLYGON); 183 | glColor3f(1,0,0); 184 | glVertex2f(0,0); 185 | glVertex2f(1,0); 186 | glVertex2f(1,a); 187 | glVertex2f(0,a); 188 | glEnd(); 189 | glBegin(GL_POLYGON); 190 | glColor3f(1,0,0); 191 | glVertex2f(0,a); 192 | glVertex2f(morph,a); 193 | glVertex2f(morph,b); 194 | glVertex2f(0,b); 195 | glEnd(); 196 | glBegin(GL_POLYGON); 197 | glColor3f(0,0,1); 198 | glVertex2f(morph,a); 199 | glVertex2f(1,a); 200 | glVertex2f(1,b); 201 | glVertex2f(morph,b); 202 | glEnd(); 203 | glBegin(GL_POLYGON); 204 | glColor3f(0,0,1); 205 | glVertex2f(0,b); 206 | glVertex2f(1,b); 207 | glVertex2f(1,1); 208 | glVertex2f(0,1); 209 | glEnd(); 210 | glPopMatrix(); 211 | glMatrixMode( GL_PROJECTION ); 212 | glPopMatrix(); 213 | glMatrixMode( GL_MODELVIEW ); 214 | } 215 | 216 | /* 217 | * The following is just a quick hack to animate 218 | * the object through various polygon reduced versions. 219 | */ 220 | struct keyframethings { 221 | float t; // timestamp 222 | float n; // portion of vertices used to start 223 | float dn; // rate of change in "n" 224 | float m; // morph value 225 | float dm; // rate of change in "m" 226 | } keys[]={ 227 | {0 ,1 ,0 ,1, 0}, 228 | {2 ,1 ,-1,1, 0}, 229 | {10,0 ,1 ,1, 0}, 230 | {18,1 ,0 ,1, 0}, 231 | {20,1 ,0 ,1,-1}, 232 | {24,0.5 ,0 ,1, 0}, 233 | {26,0.5 ,0 ,1,-1}, 234 | {30,0.25,0 ,1, 0}, 235 | {32,0.25,0 ,1,-1}, 236 | {36,0.125,0,1, 0}, 237 | {38,0.25,0 ,0, 1}, 238 | {42,0.5 ,0 ,0, 1}, 239 | {46,1 ,0 ,0, 1}, 240 | {50,1 ,0 ,1, 0}, 241 | }; 242 | void AnimateParameters( float DeltaT ) { 243 | static float time=0; // global time - used for animation 244 | time+=DeltaT; 245 | if(time>=50) time=0; // repeat cycle every so many seconds 246 | int k=0; 247 | while(time>keys[k+1].t) { 248 | k++; 249 | } 250 | float interp = (time-keys[k].t)/(keys[k+1].t-keys[k].t); 251 | render_num = vert.size()*(keys[k].n + interp*keys[k].dn); 252 | morph = keys[k].m + interp*keys[k].dm; 253 | morph = (morph>1.0f) ? 1.0f : morph; // clamp value 254 | if (render_num> (int) vert.size()) render_num = (int)vert.size(); 255 | if(render_num<0 ) render_num=0; 256 | } 257 | 258 | char *RenderModel( float DeltaT ) { 259 | AnimateParameters(DeltaT); 260 | 261 | glEnable(GL_LIGHTING); 262 | glEnable(GL_LIGHT0); 263 | glColor3f(1,1,1); 264 | glPushMatrix(); 265 | glMultMatrixf(Pose(model_position, model_orientation).matrix()); 266 | DrawModelTriangles(); 267 | StatusDraw(); 268 | glPopMatrix(); 269 | 270 | static char buf[256]; 271 | snprintf(buf,sizeof(buf),"Polys: %d Vertices: %d ",renderpolycount,render_num); 272 | if(morph<1.0) { 273 | snprintf(buf+strlen(buf),256-strlen(buf),"<-> %d morph: %4.2f ", 274 | (int)(lodbase *render_num),morph); 275 | } 276 | return buf; 277 | } 278 | 279 | -------------------------------------------------------------------------------- /geometric.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Collection of useful 3d geometric routines such as projections, intersection, etc. 4 | // 5 | // note: still doing some reorg to make naming more consistent and pick the best and minimal set of routines here 6 | // 7 | 8 | #pragma once 9 | #ifndef GEOMETRIC_H 10 | #define GEOMETRIC_H 11 | 12 | #include // for std::max_element() used by maxdir and supportmap funcs 13 | #include // for std::numeric_limits used by Extents() 14 | #include 15 | #include // since we define some << and >> stream io operators 16 | #include 17 | #include 18 | 19 | #include "linalg.h" 20 | using namespace linalg::aliases; // usual defined aliases (int3,float3,float4x4 etc.) in the global namespace 21 | #include "misc.h" // for my std::transform wrapper Transform that creates and returns by value 22 | // still reorganizing little geometry functions, putting these here for now: 23 | 24 | 25 | struct rect_iteration // nice programming convenience, but adds some loop overhead the compiler doesn't see through 26 | { 27 | struct iterator 28 | { 29 | int2 coord; int dims_x; 30 | int2 operator * () const { return coord; } 31 | bool operator != (const iterator & r) const { return coord.y != r.coord.y; } 32 | void operator ++ () { coord.y += !(++coord.x %= dims_x); } 33 | }; 34 | 35 | int2 dims; 36 | rect_iteration(const int2 & dims) : dims(dims) {} 37 | iterator begin() const { return{ { 0,0 }, dims.x }; } 38 | iterator end() const { return{ { 0,dims.y }, dims.x }; } 39 | }; 40 | struct vol_iteration 41 | { 42 | struct iterator 43 | { 44 | int3 coord; int2 dims; 45 | int3 operator * () const { return coord; } 46 | bool operator != (const iterator & r) const { return coord.z != r.coord.z; } 47 | void operator ++ () { coord.z += ((coord.y += !(++coord.x %= dims.x)) == dims.y); coord.y %= dims.y; } 48 | }; 49 | 50 | int3 dims; 51 | vol_iteration(const int3 & dims) : dims(dims) {} 52 | iterator begin() const { return{ { 0,0,0 }, dims.xy() }; } 53 | iterator end() const { return{ { 0,0,dims.z }, dims.xy() }; } 54 | }; 55 | 56 | inline int2 asint2(const float2 &v) { return{ (int )v.x, (int )v.y }; } 57 | inline float2 asfloat2(const int2 &v) { return{ (float)v.x, (float)v.y }; } 58 | 59 | inline float3 safenormalize(const float3 &v) { return (v == float3(0, 0, 0)) ? float3(0, 0, 1) : normalize(v); } 60 | 61 | // template T clamp(T a, const T mn = T(0), const T mx = T(1)) { return std::min(std::max(a, mn), mx); } // templating this messed up the within_range and clamp for linalg types 62 | inline int clamp(int a, const int mn = int (0), const int mx = int (1)) { return std::min(std::max(a, mn), mx); } 63 | inline float clamp(float a, const float mn = float(0), const float mx = float(1)) { return std::min(std::max(a, mn), mx); } 64 | 65 | template bool within_range(const linalg::vec & v, const linalg::vec & mn, const linalg::vec & mx) { return v == linalg::clamp(v, mn, mx); } 66 | 67 | 68 | inline float4 quatfrommat(const float3x3 &m) 69 | { 70 | float magw = m[0][0] + m[1][1] + m[2][2]; 71 | float magxy; 72 | float magzw; 73 | float3 pre; 74 | float3 prexy; 75 | float3 prezw; 76 | 77 | bool wvsz = magw > m[2][2]; 78 | magzw = wvsz ? magw : m[2][2]; 79 | prezw = wvsz ? float3(1, 1, 1) : float3(-1, -1, 1); 80 | auto postzw = wvsz ? float4(0, 0, 0, 1) : float4(0, 0, 1, 0); 81 | 82 | bool xvsy = m[0][0] > m[1][1]; 83 | magxy = xvsy ? m[0][0] : m[1][1]; 84 | prexy = xvsy ? float3(1, -1, -1) : float3(-1, 1, -1); 85 | auto postxy = xvsy ? float4(1, 0, 0, 0) : float4(0, 1, 0, 0); 86 | 87 | bool zwvsxy = magzw > magxy; 88 | pre = zwvsxy ? prezw : prexy; 89 | auto post = zwvsxy ? postzw : postxy; 90 | 91 | float t = pre.x * m[0][0] + pre.y * m[1][1] + pre.z * m[2][2] + 1; 92 | float s = 1 / sqrt(t) / 2; 93 | float4 qp 94 | { 95 | (pre.y * m[1][2] - pre.z * m[2][1]) * s, 96 | (pre.z * m[2][0] - pre.x * m[0][2]) * s, 97 | (pre.x * m[0][1] - pre.y * m[1][0]) * s, 98 | t * s 99 | }; 100 | return qmul(qp, post); 101 | } 102 | 103 | inline float4 QuatFromAxisAngle(const float3 & axis, float angle) { return {axis*std::sin(angle/2), std::cos(angle/2)}; } 104 | inline float4x4 MatrixFromRotation(const float4 & rotationQuat) { return {{qxdir(rotationQuat),0}, {qydir(rotationQuat),0}, {qzdir(rotationQuat),0}, {0,0,0,1}}; } 105 | inline float4x4 MatrixFromTranslation(const float3 & translationVec) { return {{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {translationVec,1}}; } 106 | inline float4x4 MatrixFromRotationTranslation(const float4 & rotationQuat, const float3 & translationVec) { return {{qxdir(rotationQuat),0}, {qydir(rotationQuat),0}, {qzdir(rotationQuat),0}, {translationVec,1}}; } 107 | inline float4x4 MatrixFromProjectionFrustum(float l, float r, float b, float t, float n, float f) { return {{2*n/(r-l),0,0,0}, {0,2*n/(t-b),0,0}, {(r+l)/(r-l),(t+b)/(t-b),-(f+n)/(f-n),-1}, {0,0,-2*f*n/(f-n),0}}; } 108 | inline float4x4 MatrixFromVfovAspect(float vfov, float aspect, float n, float f) { float y = n*std::tan(vfov/2), x=y*aspect; return MatrixFromProjectionFrustum(-x,x,-y,y,n,f); } 109 | inline float4x4 MatrixFromLookVector(const float3 & fwd, const float3 & up) { auto f = normalize(fwd), s = normalize(cross(f, up)), u = cross(s, f); return {{s.x,u.x,-f.x,0},{s.y,u.y,-f.y,0},{s.z,u.z,-f.z,0},{0,0,0,1}}; } 110 | inline float4x4 MatrixFromLookAt(const float3 & eye, const float3 & center, const float3 & up) { return mul(MatrixFromLookVector(center - eye, up), MatrixFromTranslation(-eye)); } 111 | 112 | struct Pose // Value type representing a rigid transformation consisting of a translation and rotation component 113 | { 114 | float3 position; 115 | float4 orientation; 116 | 117 | Pose(const float3 & p, const float4 & q) : position(p), orientation(q) {} 118 | Pose() : Pose({ 0, 0, 0 }, { 0, 0, 0, 1 }) {} 119 | 120 | Pose inverse() const { auto q = qconj(orientation); return{ qrot(q, -position), q }; } 121 | float4x4 matrix() const { return MatrixFromRotationTranslation(orientation, position); } 122 | 123 | float3 operator * (const float3 & point) const { return position + qrot(orientation, point); } 124 | Pose operator * (const Pose & pose) const { return{ *this * pose.position, qmul(orientation, pose.orientation) }; } 125 | float4 TransformPlane(const float4 &p) { float3 n = qrot(orientation, p.xyz()); return float4(n, p.w - dot(position, n)); } 126 | }; 127 | 128 | namespace linalg 129 | { 130 | // Implement stream operators for vector types, and specifically interpret byte-sized integers as integers instead of characters 131 | template std::ostream & operator << (std::ostream & out, const vec< T, M> & v) { for (int i = 0; i < M; ++i) out << (i ? " " : "") << v[i]; return out; } 132 | template< int M> std::ostream & operator << (std::ostream & out, const vec< int8_t, M> & v) { for (int i = 0; i < M; ++i) out << (i ? " " : "") << (int)v[i]; return out; } 133 | template< int M> std::ostream & operator << (std::ostream & out, const vec & v) { for (int i = 0; i < M; ++i) out << (i ? " " : "") << (int)v[i]; return out; } 134 | template std::istream & operator >> (std::istream & in, vec< T, M> & v) { for (int i = 0; i < M; ++i) in >> v[i]; return in; } 135 | template< int M> std::istream & operator >> (std::istream & in, vec< int8_t, M> & v) { for (int i = 0, x; i < M; ++i) if (in >> x) v[i] = (int8_t)x; return in; } 136 | template< int M> std::istream & operator >> (std::istream & in, vec & v) { for (int i = 0, x; i < M; ++i) if (in >> x) v[i] = (uint8_t)x; return in; } 137 | } 138 | 139 | inline std::ostream & operator << (std::ostream & out, const Pose& p) { return out << p.position << " " << p.orientation; } 140 | inline std::istream & operator >> (std::istream & in, Pose& p) { return in >> p.position >> p.orientation; } 141 | 142 | 143 | inline float3 PlaneLineIntersection(const float3 &n, const float d, const float3 &p0, const float3 &p1) // returns the point where the line p0-p2 intersects the plane n&d 144 | { 145 | float3 dif = p1 - p0; 146 | float dn = dot(n, dif); 147 | float t = -(d + dot(n, p0)) / dn; 148 | return p0 + (dif*t); 149 | } 150 | inline float3 PlaneLineIntersection(const float4 &plane, const float3 &p0, const float3 &p1) { return PlaneLineIntersection(plane.xyz(), plane.w, p0, p1); } // returns the point where the line p0-p2 intersects the plane n&d 151 | 152 | 153 | 154 | inline float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a) 155 | { 156 | // project point a on segment [p0,p1] 157 | float3 d = p1 - p0; 158 | float t = dot(d, (a - p0)) / dot(d, d); 159 | return t; 160 | } 161 | inline float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a) { return p0 + (p1 - p0) * LineProjectTime(p0, p1, a); } 162 | 163 | inline float3 gradient(const float3 &v0, const float3 &v1, const float3 &v2, 164 | const float t0, const float t1, const float t2) { 165 | float3 e0 = v1 - v0; 166 | float3 e1 = v2 - v0; 167 | float d0 = t1 - t0; 168 | float d1 = t2 - t0; 169 | float3 pd = e1*d0 - e0*d1; 170 | if (pd == float3(0, 0, 0)){ 171 | return float3(0, 0, 1); 172 | } 173 | pd = normalize(pd); 174 | if (fabsf(d0)>fabsf(d1)) { 175 | e0 = e0 + pd * -dot(pd, e0); 176 | e0 = e0 * (1.0f / d0); 177 | return e0 * (1.0f / dot(e0, e0));; 178 | } 179 | // else 180 | //assert(fabsf(d0) <= fabsf(d1)); 181 | e1 = e1 + pd * -dot(pd, e1); 182 | e1 = e1 * (1.0f / d1); 183 | return e1 * (1.0f / dot(e1, e1)); 184 | } 185 | 186 | inline float3 BaryCentric(const float3 &v0, const float3 &v1, const float3 &v2, float3 s) 187 | { 188 | float3x3 m(v0, v1, v2); 189 | if (determinant(m) == 0) 190 | { 191 | int k = (length(v1 - v2)>length(v0 - v2)) ? 1 : 0; 192 | float t = LineProjectTime(v2, m[k], s); 193 | return float3((1 - k)*t, k*t, 1 - t); 194 | } 195 | return mul(inverse(m), s); 196 | } 197 | inline bool tri_interior(const float3& v0, const float3& v1, const float3& v2, const float3& d) 198 | { 199 | float3 b = BaryCentric(v0, v1, v2, d); 200 | return (b.x >= 0.0f && b.y >= 0.0f && b.z >= 0.0f); 201 | } 202 | 203 | inline float3 ProjectOntoPlane(const float4 &plane, const float3 &v) { return v - plane.xyz()*dot(plane, float4( v, 1 )); } 204 | 205 | inline float3 PlaneProjectOf(const float3 &v0, const float3 &v1, const float3 &v2, const float3 &point) 206 | { 207 | float3 cp = cross(v2 - v0, v2 - v1); 208 | float dtcpm = -dot(cp, v0); 209 | float cpm2 = dot(cp, cp); 210 | if (cpm2 == 0.0f) 211 | { 212 | return LineProject(v0, (length(v1 - v0)>length(v2 - v0)) ? v1 : v2, point); 213 | } 214 | return point - cp * (dot(cp, point) + dtcpm) / cpm2; 215 | } 216 | 217 | 218 | 219 | inline int maxdir(const float3 *p, int count, const float3 &dir) // returns index 220 | { 221 | assert(count > 0); 222 | if (count == 0) 223 | return -1; 224 | return (int)( std::max_element(p, p + count, [dir](const float3 &a, const float3 &b){return dot(a, dir) < dot(b, dir); }) - p ); 225 | } 226 | inline int maxdir_index(const std::vector &points, const float3 &dir) // returns index 227 | { 228 | return maxdir(points.data(), (int)points.size(), dir); 229 | } 230 | inline float3 maxdir_value(const std::vector &points, const float3 &dir) // returns index 231 | { 232 | return points[maxdir_index(points, dir)]; 233 | } 234 | 235 | inline float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2) // normal of the triangle with vertex positions v0, v1, and v2 236 | { 237 | float3 cp = cross(v1 - v0, v2 - v1); 238 | float m = length(cp); 239 | if (m == 0) return float3(0, 0, 1); 240 | return cp*(1.0f / m); 241 | } 242 | 243 | inline float4 plane_of(const float3 &v0, const float3 &v1, const float3 &v2) // plane of triangle with vertex positions v0, v1, and v2 244 | { 245 | auto n = TriNormal(v0, v1, v2); 246 | return{ n, -dot(n,v0) }; 247 | } 248 | inline float4 PolyPlane(const std::vector& verts) 249 | { 250 | float4 p(0, 0, 0, 0); 251 | float3 c(0, 0, 0); 252 | for (const auto &v : verts) 253 | c += v*(1.0f / verts.size()); 254 | for (unsigned int i = 0; i < verts.size(); i++) 255 | p.xyz() += cross(verts[i] - c, verts[(i + 1) % verts.size()] - c); 256 | if (p == float4(0, 0, 0, 0)) 257 | return p; 258 | p.xyz() = normalize(p.xyz()); 259 | p.w = -dot(c, p.xyz()); 260 | return p; 261 | } 262 | struct HitInfo { bool hit; float3 impact; float3 normal; operator bool(){ return hit; }; }; 263 | 264 | inline HitInfo PolyHitCheck(const std::vector& verts, const float4 &plane, const float3 &v0, const float3 &v1) 265 | { 266 | float d0 = dot(float4(v0, 1), plane); 267 | float d1 = dot(float4(v1, 1), plane); 268 | HitInfo hitinfo = { ((d0 > 0) && (d1 < 0)), { 0, 0, 0 }, { 0, 0, 0 } }; // if segment crosses into plane 269 | hitinfo.normal = plane.xyz(); 270 | hitinfo.impact = v0 + (v1 - v0)* d0 / (d0 - d1); // if both points on plane this will be 0/0, if parallel you might get infinity 271 | for (unsigned int i = 0; hitinfo&& i < verts.size(); i++) 272 | hitinfo.hit = hitinfo && (determinant(float3x3(verts[(i + 1) % verts.size()] - v0, verts[i] - v0, v1 - v0)) >= 0); // use v0,v1 winding instead of impact to prevent mesh edge tunneling 273 | return hitinfo; 274 | } 275 | inline HitInfo PolyHitCheck(const std::vector& verts, const float3 &v0, const float3 &v1) { return PolyHitCheck(verts, PolyPlane(verts), v0, v1); } 276 | 277 | inline HitInfo ConvexHitCheck(const std::vector& planes, float3 v0, const float3 &v1_) 278 | { 279 | float3 v1 = v1_; 280 | float3 n; 281 | for (auto plane : planes) 282 | { 283 | float d0 = dot(float4(v0, 1), plane); 284 | float d1 = dot(float4(v1, 1), plane); 285 | if (d0 >= 0 && d1>=0) // segment above plane 286 | return{ false, v1_, { 0, 0, 0 } }; // hitinfo; 287 | if (d0 <= 0 && d1<=0 ) 288 | continue; // start and end point under plane 289 | auto c = v0 + (v1 - v0)* d0 / (d0 - d1); 290 | if (d0 >= 0) 291 | { 292 | n = plane.xyz(); 293 | v0 = c; 294 | } 295 | else 296 | v1 = c; 297 | } 298 | return{ true, v0, n }; 299 | } 300 | inline HitInfo ConvexHitCheck(const std::vector& planes, const Pose &pose, float3 v0, const float3 &v1) 301 | { 302 | auto h = ConvexHitCheck(planes, pose.inverse()*v0, pose.inverse()*v1); 303 | return { h.hit, pose*h.impact, qrot(pose.orientation, h.normal) }; 304 | } 305 | 306 | inline int argmax(const float a[], int count) // returns index 307 | { 308 | if (count == 0) return -1; 309 | return (int)( std::max_element(a,a+count)-a ); 310 | } 311 | 312 | // still in the process of rearranging basic math and geom routines, putting these here for now... 313 | 314 | inline float3 Orth(const float3& v) 315 | { 316 | float3 absv = abs(v); 317 | float3 u(1, 1, 1); 318 | u[argmax(&absv[0], 3)] = 0.0f; 319 | return normalize(cross(u, v)); 320 | } 321 | inline float4 quat_from_to(const float3 &v0_, const float3 &v1_) // shortest arc quat from game programming gems 1 section 2.10 322 | { 323 | auto v0 = normalize(v0_); // Comment these two lines out if you know its not needed. 324 | auto v1 = normalize(v1_); // If vector is already unit length then why do it again? 325 | auto c = cross(v0, v1); 326 | auto d = dot(v0, v1); 327 | if (d <= -1.0f) { float3 a = Orth(v0); return float4(a.x, a.y, a.z, 0); } // 180 about any orthogonal axis 328 | auto s = sqrtf((1 + d) * 2); 329 | return{ c.x / s, c.y / s, c.z / s, s / 2.0f }; 330 | } 331 | 332 | 333 | inline float4 VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir1, const float3 &dir2) 334 | { 335 | // Simple track ball functionality to spin stuf on the screen. 336 | // cop center of projection cor center of rotation 337 | // dir1 old mouse direction dir2 new mouse direction 338 | // Pretend there is a sphere around cor. Take rotation 339 | // between apprx points where dir1 and dir2 intersect sphere. 340 | float3 nrml = cor - cop; // compute plane 341 | float fudgefactor = 1.0f / (length(nrml) * 0.25f); // since trackball proportional to distance from cop 342 | nrml = normalize(nrml); 343 | float dist = -dot(nrml, cor); 344 | float3 u = ( PlaneLineIntersection(nrml, dist, cop, cop + dir1) - cor) * fudgefactor; 345 | float m = length(u); 346 | u = (m > 1) ? u / m : u - (nrml * sqrtf(1 - m*m)); 347 | float3 v = ( PlaneLineIntersection(nrml, dist, cop, cop + dir2) - cor) * fudgefactor; 348 | m = length(v); 349 | v = (m>1) ? v / m : v - (nrml * sqrtf(1 - m*m)); 350 | return quat_from_to(u, v); 351 | } 352 | 353 | 354 | 355 | template 356 | inline std::pair, linalg::vec > Extents(const std::vector > &verts) 357 | { 358 | linalg::vec bmin(std::numeric_limits::max()), bmax(std::numeric_limits::lowest()); 359 | for (auto v : verts) 360 | { 361 | bmin = min(bmin, v); 362 | bmax = max(bmax, v); 363 | } 364 | return std::make_pair(bmin, bmax); // typical useage: std::tie(mymin,mymax) = Extents(myverts); 365 | } 366 | 367 | inline float Volume(const float3 *vertices, const int3 *tris, const int count) 368 | { 369 | // count is the number of triangles (tris) 370 | float volume = 0; 371 | for (int i = 0; iom.y&&om.x>om.z) ? 0 : (om.y>om.z) ? 1 : 2; // index of largest element of offdiag 446 | int k1 = (k + 1) % 3; 447 | int k2 = (k + 2) % 3; 448 | if (offdiag[k] == 0.0f) break; // diagonal already 449 | float thet = (D[k2][k2] - D[k1][k1]) / (2.0f*offdiag[k]); 450 | float sgn = (thet>0.0f) ? 1.0f : -1.0f; 451 | thet *= sgn; // make it positive 452 | float t = sgn / (thet + ((thet<1.E6f) ? sqrtf(thet*thet + 1.0f) : thet)); // sign(T)/(|T|+sqrt(T^2+1)) 453 | float c = 1.0f / sqrtf(t*t + 1.0f); // c= 1/(t^2+1) , t=s/c 454 | if (c == 1.0f) break; // no room for improvement - reached machine precision. 455 | float4 jr(0, 0, 0, 0); // jacobi rotation for this iteration. 456 | jr[k] = sgn*sqrtf((1.0f - c) / 2.0f); // using 1/2 angle identity sin(a/2) = sqrt((1-cos(a))/2) 457 | jr[k] *= -1.0f; // note we want a final result semantic that takes D to A, not A to D 458 | jr.w = sqrtf(1.0f - (jr[k] * jr[k])); 459 | if (jr.w == 1.0f) break; // reached limits of floating point precision 460 | q = qmul(q, jr); 461 | q = normalize(q); 462 | } 463 | float h = 1.0f/sqrtf(2.0f); // M_SQRT2 464 | auto e = [&q, &A]() {return Diagonal(mul(transpose(qmat(q)), A, qmat(q))); }; // current ordering of eigenvals of q 465 | q = (e().x < e().z) ? qmul(q, float4( 0, h, 0, h )) : q; 466 | q = (e().y < e().z) ? qmul(q, float4( h, 0, 0, h )) : q; 467 | q = (e().x < e().y) ? qmul(q, float4( 0, 0, h, h )) : q; // size order z,y,x so xy spans a planeish spread 468 | q = (qzdir(q).z < 0) ? qmul(q, float4( 1, 0, 0, 0 )) : q; 469 | q = (qydir(q).y < 0) ? qmul(q, float4( 0, 0, 1, 0 )) : q; 470 | q = (q.w < 0) ? -q : q; 471 | auto M = mul(transpose(qmat(q)), A, qmat(q)); // to test result 472 | return q; 473 | } 474 | 475 | inline float Diagonalizer(const float2x2 &m) // returns angle that rotates m into diagonal matrix d where d01==d10==0 and d00>d11 (the eigenvalues) 476 | { 477 | float d = m.y.y - m.x.x; 478 | return atan2f(d + sqrtf(d*d + 4.0f*m.x.y*m.y.x), 2.0f * m.x.y); 479 | } 480 | 481 | inline void PlaneTranslate(float4 & plane, const float3 & translation) { plane.w -= dot(plane.xyz(), translation); } 482 | inline void PlaneRotate(float4 & plane, const float4 & rotation) { plane.xyz() = qrot(rotation, plane.xyz()); } 483 | inline void PlaneScale(float4 & plane, const float3 & scaling) { plane.xyz() = plane.xyz() / scaling; plane /= length(plane.xyz()); } 484 | inline void PlaneScale(float4 & plane, float scaling) { plane.w *= scaling; } 485 | 486 | inline std::vector boxedges() { std::vector a; for (int i = 0; i<8; i++) for (int j = 0; j DeIndex(const std::vector &v, const std::vector &t) { return Transform(t, [&v](int2 t) {return float3x2(v[t[0]], v[t[1]] );}); } // return 3x2 is pair of vertices m[0] and m[1]. eg line segment 490 | inline std::vector DeIndex(const std::vector &v, const std::vector &t) { return Transform(t, [&v](int3 t) {return float3x3(v[t[0]], v[t[1]],v[t[2]]);}); } // return 3x3 is pair of vertices m[0] and m[1]. eg triangle 491 | 492 | inline std::pair PrincipalAxes(const std::vector &points) // returns principal axes as a pose and population's variance along pose's local x,y,z 493 | { 494 | float3 com(0, 0, 0); 495 | float3x3 cov; 496 | for (auto p : points) 497 | com += p; 498 | com /= (float)points.size(); 499 | for (auto p : points) 500 | cov += outerprod(p - com, p - com); 501 | cov /= (float)points.size(); 502 | auto q = Diagonalizer(cov); 503 | return std::make_pair({ com, q }, Diagonal(mul(transpose(qmat(q)), cov, qmat(q)))); 504 | } 505 | 506 | 507 | 508 | #endif //GEOMETRIC_H 509 | -------------------------------------------------------------------------------- /glutil.h: -------------------------------------------------------------------------------- 1 | // 2 | // glwin.h 3 | // 4 | // minimal opengl on windows framework for writing small opengl test apps 5 | // all in one header file. No extra downloads, installs, cmake, .DLLs, .LIBs. etc... 6 | // 7 | // try not to use that 16 bit wchar. 8 | // 9 | 10 | // 11 | // bitmap font code from the OpenGL red book example programs the copyright from that sample is: 12 | // (c) Copyright 1993, Silicon Graphics, Inc. 1993-1995 Microsoft Corporation ALL RIGHTS RESERVED 13 | // 14 | // 15 | 16 | #pragma once 17 | #ifndef GLWIN_H 18 | #define GLWIN_H 19 | 20 | #include 21 | #include 22 | 23 | 24 | #include 25 | #include // For va_list, va_start, ... 26 | #include // For vsnprintf 27 | #include 28 | #include "linalg.h" 29 | using namespace linalg::aliases; 30 | 31 | class GLUtil 32 | { 33 | 34 | GLuint fontOffset; 35 | void MakeRasterFont(void) 36 | { 37 | GLubyte rasters[][13] = { // bitmap font code from the OpenGL red book example 38 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 39 | {0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 40 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36}, 41 | {0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00}, 42 | {0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18}, 43 | {0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70}, 44 | {0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38}, 45 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e}, 46 | {0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c}, 47 | {0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30}, 48 | {0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00}, 49 | {0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00}, 50 | {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 51 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, 52 | {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 53 | {0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03}, 54 | {0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c}, 55 | {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18}, 56 | {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e}, 57 | {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e}, 58 | {0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c}, 59 | {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, 60 | {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, 61 | {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff}, 62 | {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, 63 | {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e}, 64 | {0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00}, 65 | {0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00}, 66 | {0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06}, 67 | {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, 68 | {0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60}, 69 | {0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e}, 70 | {0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00}, 71 | {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18}, 72 | {0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, 73 | {0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, 74 | {0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc}, 75 | {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff}, 76 | {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff}, 77 | {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, 78 | {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, 79 | {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e}, 80 | {0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}, 81 | {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3}, 82 | {0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, 83 | {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3}, 84 | {0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3}, 85 | {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e}, 86 | {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, 87 | {0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c}, 88 | {0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe}, 89 | {0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e}, 90 | {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff}, 91 | {0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, 92 | {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, 93 | {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3}, 94 | {0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, 95 | {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3}, 96 | {0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff}, 97 | {0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c}, 98 | {0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60}, 99 | {0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c}, 100 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, 101 | {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 102 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70}, 103 | {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, 104 | {0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}, 105 | {0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, 106 | {0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03}, 107 | {0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, 108 | {0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, 109 | {0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00}, 110 | {0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0}, 111 | {0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, 112 | {0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00}, 113 | {0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0}, 114 | {0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78}, 115 | {0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00}, 116 | {0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00}, 117 | {0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00}, 118 | {0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00}, 119 | {0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00}, 120 | {0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00}, 121 | {0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00}, 122 | {0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00}, 123 | {0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00}, 124 | {0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, 125 | {0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00}, 126 | {0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, 127 | {0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00}, 128 | {0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00}, 129 | {0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, 130 | {0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 131 | {0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0}, 132 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00} 133 | }; 134 | GLuint i; 135 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 136 | 137 | fontOffset = glGenLists (128); 138 | for (i = 32; i < 127; i++) { 139 | glNewList(i+fontOffset, GL_COMPILE); 140 | glBitmap(8, 13, 0.0, 2.0, 10.0, 0.0, rasters[i-32]); 141 | glEndList(); 142 | } 143 | } 144 | 145 | void SpitLetters(const char *s) 146 | { 147 | glPushAttrib (GL_LIST_BIT); 148 | glListBase(fontOffset); 149 | glCallLists((GLsizei)strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s); 150 | glPopAttrib (); 151 | } 152 | 153 | void PrintString(const char *s,const float2 &p) { 154 | if(!s) return; 155 | glPushAttrib(GL_LIGHTING_BIT|GL_DEPTH_BUFFER_BIT|GL_TEXTURE_BIT); 156 | glDisable(GL_TEXTURE_2D); 157 | glDisable(GL_LIGHTING); 158 | glDisable(GL_DEPTH_TEST); 159 | glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); 160 | glMatrixMode(GL_PROJECTION); 161 | glPushMatrix(); 162 | glLoadIdentity(); 163 | glOrtho (0.0, 1.0, 0.0, 1.0, -1.0, 1.0); 164 | glRasterPos2f(p.x,p.y); 165 | SpitLetters(s); 166 | glRasterPos2f(0,0); 167 | glPopMatrix(); 168 | glMatrixMode(GL_MODELVIEW); glPopMatrix(); 169 | glPopAttrib(); 170 | } 171 | public: 172 | const int2 font_char_dims = { 10,14 }; 173 | void PrintString(int2 cp, const char *s, ...) 174 | { 175 | va_list args; 176 | va_start(args, s); 177 | char buffer[1024]; 178 | vsnprintf(buffer, sizeof(buffer), s, args); 179 | va_end(args); 180 | int2x2 viewport; // current viewport settings [[x y][w h]] 181 | glGetIntegerv(GL_VIEWPORT, (GLint*)&viewport); 182 | int rows = std::max(1,viewport[1].y/font_char_dims.y) ; 183 | int cols = viewport[1].x/font_char_dims.x ; 184 | if(cp.y>=rows){ cp.y=rows-1;} 185 | if(cp.y<0) { cp.y+= rows;} // caller gives a negative y 186 | if(cp.y<0) { cp.y = 0;} // caller gives a too much negative y 187 | if(cp.x<0) { cp.x = cols+cp.x-(int)strlen(s)+1;} 188 | if (cp.x + (int)strlen(s)>cols) { cp.x = cols - (int)strlen(s); } 189 | if (cp.x<0) { cp.x = 0; } 190 | cp.y=rows-1-cp.y; // invert y so row 0 is at the top and -1 is at the bottom 191 | PrintString(buffer,float2((float)cp.x,(float)cp.y)/float2((float)cols, (float)rows)); 192 | } 193 | 194 | GLUtil() 195 | { 196 | MakeRasterFont(); 197 | } 198 | ~GLUtil() 199 | { 200 | } 201 | 202 | }; 203 | 204 | inline void glVertex3fv (const float3 &v) { glVertex3fv(&v.x); } 205 | inline void glNormal3fv (const float3 &v) { glNormal3fv(&v.x); } 206 | inline void glTexCoord2fv(const float2 &v) { glTexCoord2fv(&v.x); } 207 | inline void glColor3fv (const float3 &c) { glColor3fv(&c.x); } 208 | inline void glColor4fv (const float4 &c) { glColor4fv(&c.x); } 209 | inline void glTranslatefv(const float3 &v) { glTranslatef(v.x,v.y,v.z);} 210 | inline void glMultMatrixf(const float4x4 &m) { glMultMatrixf(&m.x.x); } 211 | inline void glPerspective(float fovy, float aspect, float n, float f) { double y = n*std::tan(fovy / 2 * acos(-1) / 180), x = y*aspect; glFrustum(-x, x, -y, y, n, f); } 212 | 213 | 214 | #endif // GLWIN_H 215 | 216 | 217 | -------------------------------------------------------------------------------- /linalg.h: -------------------------------------------------------------------------------- 1 | // linalg.h - v2.0 - Single-header public domain linear algebra library 2 | // 3 | // The intent of this library is to provide the bulk of the functionality 4 | // you need to write programs that frequently use small, fixed-size vectors 5 | // and matrices, in domains such as computational geometry or computer 6 | // graphics. It strives for terse, readable source code. 7 | // 8 | // The original author of this software is Sterling Orsten, and its permanent 9 | // home is . If you find this software 10 | // useful, an acknowledgement in your source text and/or product documentation 11 | // is appreciated, but not required. 12 | // 13 | // The author acknowledges significant insights and contributions by: 14 | // Stan Melax 15 | // Dimitri Diakopoulos 16 | 17 | 18 | 19 | // This is free and unencumbered software released into the public domain. 20 | // 21 | // Anyone is free to copy, modify, publish, use, compile, sell, or 22 | // distribute this software, either in source code form or as a compiled 23 | // binary, for any purpose, commercial or non-commercial, and by any 24 | // means. 25 | // 26 | // In jurisdictions that recognize copyright laws, the author or authors 27 | // of this software dedicate any and all copyright interest in the 28 | // software to the public domain. We make this dedication for the benefit 29 | // of the public at large and to the detriment of our heirs and 30 | // successors. We intend this dedication to be an overt act of 31 | // relinquishment in perpetuity of all present and future rights to this 32 | // software under copyright law. 33 | // 34 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 35 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 36 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 37 | // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 38 | // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 39 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 40 | // OTHER DEALINGS IN THE SOFTWARE. 41 | // 42 | // For more information, please refer to 43 | 44 | 45 | 46 | #pragma once 47 | #ifndef LINALG_H 48 | #define LINALG_H 49 | 50 | #include // For various unary math functions, such as std::sqrt 51 | #include // For implementing namespace linalg::aliases 52 | #include // For std::array, used in the relational operator overloads 53 | 54 | namespace linalg 55 | { 56 | // Small, fixed-length vector type, consisting of exactly M elements of type T, and presumed to be a column-vector unless otherwise noted 57 | template struct vec; 58 | template struct vec 59 | { 60 | T x,y; 61 | vec() : x(), y() {} 62 | vec(T x, T y) : x(x), y(y) {} 63 | explicit vec(T s) : x(s), y(s) {} 64 | explicit vec(const T * p) : vec(p[0], p[1]) {} 65 | template explicit vec(const vec & v) : vec(static_cast(v.x), static_cast(v.y)) {} 66 | const T & operator[] (int i) const { return (&x)[i]; } 67 | T & operator[] (int i) { return (&x)[i]; } 68 | }; 69 | template struct vec 70 | { 71 | T x,y,z; 72 | vec() : x(), y(), z() {} 73 | vec(T x, T y, T z) : x(x), y(y), z(z) {} 74 | explicit vec(T s) : x(s), y(s), z(s) {} 75 | explicit vec(const T * p) : vec(p[0], p[1], p[2]) {} 76 | template explicit vec(const vec & v) : vec(static_cast(v.x), static_cast(v.y), static_cast(v.z)) {} 77 | vec(const vec & xy, T z) : vec(xy.x, xy.y, z) {} 78 | const T & operator[] (int i) const { return (&x)[i]; } 79 | T & operator[] (int i) { return (&x)[i]; } 80 | const vec & xy() const { return *reinterpret_cast *>(this); } 81 | vec & xy() { return *reinterpret_cast *>(this); } 82 | }; 83 | template struct vec 84 | { 85 | T x,y,z,w; 86 | vec() : x(), y(), z(), w() {} 87 | vec(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} 88 | explicit vec(T s) : x(s), y(s), z(s), w(s) {} 89 | explicit vec(const T * p) : vec(p[0], p[1], p[2], p[3]) {} 90 | template explicit vec(const vec & v) : vec(static_cast(v.x), static_cast(v.y), static_cast(v.z), static_cast(v.w)) {} 91 | vec(const vec & xyz, T w) : vec(xyz.x, xyz.y, xyz.z, w) {} 92 | const T & operator[] (int i) const { return (&x)[i]; } 93 | T & operator[] (int i) { return (&x)[i]; } 94 | const vec & xy() const { return *reinterpret_cast *>(this); } 95 | vec & xy() { return *reinterpret_cast *>(this); } 96 | const vec & xyz() const { return *reinterpret_cast *>(this); } 97 | vec & xyz() { return *reinterpret_cast *>(this); } 98 | }; 99 | 100 | // Small, fixed-size matrix type, consisting of exactly M rows and N columns of type T, stored in column-major order. 101 | template struct mat; 102 | template struct mat 103 | { 104 | typedef vec V; 105 | V x,y; 106 | mat() : x(), y() {} 107 | mat(V x, V y) : x(x), y(y) {} 108 | explicit mat(T s) : x(s), y(s) {} 109 | explicit mat(const T * p) : x(p+M*0), y(p+M*1) {} 110 | template explicit mat(const mat & m) : mat(V(m.x), V(m.y)) {} 111 | vec row(int i) const { return {x[i], y[i]}; } 112 | const V & operator[] (int j) const { return (&x)[j]; } 113 | V & operator[] (int j) { return (&x)[j]; } 114 | }; 115 | template struct mat 116 | { 117 | typedef vec V; 118 | V x,y,z; 119 | mat() : x(), y(), z() {} 120 | mat(V x, V y, V z) : x(x), y(y), z(z) {} 121 | explicit mat(T s) : x(s), y(s), z(s) {} 122 | explicit mat(const T * p) : x(p+M*0), y(p+M*1), z(p+M*2) {} 123 | template explicit mat(const mat & m) : mat(V(m.x), V(m.y), V(m.z)) {} 124 | vec row(int i) const { return {x[i], y[i], z[i]}; } 125 | const V & operator[] (int j) const { return (&x)[j]; } 126 | V & operator[] (int j) { return (&x)[j]; } 127 | }; 128 | template struct mat 129 | { 130 | typedef vec V; 131 | V x,y,z,w; 132 | mat() : x(), y(), z(), w() {} 133 | mat(V x, V y, V z, V w) : x(x), y(y), z(z), w(w) {} 134 | explicit mat(T s) : x(s), y(s), z(s), w(s) {} 135 | explicit mat(const T * p) : x(p+M*0), y(p+M*1), z(p+M*2), w(p+M*3) {} 136 | template explicit mat(const mat & m) : mat(V(m.x), V(m.y), V(m.z), V(m.w)) {} 137 | vec row(int i) const { return {x[i], y[i], z[i], w[i]}; } 138 | const V & operator[] (int j) const { return (&x)[j]; } 139 | V & operator[] (int j) { return (&x)[j]; } 140 | }; 141 | 142 | // Type traits for a binary operation involving linear algebra types, used for SFINAE on templated functions and operator overloads 143 | template struct traits {}; 144 | template struct traits, vec> { typedef T scalar; typedef vec result; typedef vec bool_result; typedef vec arith_result; typedef std::array compare_as; }; 145 | template struct traits, T > { typedef T scalar; typedef vec result; typedef vec bool_result; typedef vec arith_result; }; 146 | template struct traits> { typedef T scalar; typedef vec result; typedef vec bool_result; typedef vec arith_result; }; 147 | template struct traits, mat> { typedef T scalar; typedef mat result; typedef mat bool_result; typedef mat arith_result; typedef std::array compare_as; }; 148 | template struct traits, T > { typedef T scalar; typedef mat result; typedef mat bool_result; typedef mat arith_result; }; 149 | template struct traits> { typedef T scalar; typedef mat result; typedef mat bool_result; typedef mat arith_result; }; 150 | template using scalar_t = typename traits::scalar; // Underlying scalar type when performing elementwise operations 151 | template using result_t = typename traits::result; // Result of calling a function on linear algebra types 152 | template using bool_result_t = typename traits::bool_result; // Result of a comparison or unary not operation on linear algebra types 153 | template using arith_result_t = typename traits::arith_result; // Result of an arithmetic operation on linear algebra types (accounts for integer promotion) 154 | 155 | // Produce a scalar by applying f(T,T) -> T to adjacent pairs of elements from vector a in left-to-right order (matching the associativity of arithmetic and logical operators) 156 | template T fold(const vec & a, F f) { return f(a.x,a.y); } 157 | template T fold(const vec & a, F f) { return f(f(a.x,a.y),a.z); } 158 | template T fold(const vec & a, F f) { return f(f(f(a.x,a.y),a.z),a.w); } 159 | 160 | // Produce a vector/matrix by applying f(T,T) to corresponding pairs of elements from vectors/matrix a and b 161 | template auto zip(const vec & a, const vec & b, F f) -> vec { return {f(a.x,b.x), f(a.y,b.y)}; } 162 | template auto zip(const vec & a, const vec & b, F f) -> vec { return {f(a.x,b.x), f(a.y,b.y), f(a.z,b.z)}; } 163 | template auto zip(const vec & a, const vec & b, F f) -> vec { return {f(a.x,b.x), f(a.y,b.y), f(a.z,b.z), f(a.w,b.w)}; } 164 | template auto zip(const vec & a, T b, F f) -> vec { return zip(a, vec(b), f); } 165 | template auto zip( T a, const vec & b, F f) -> vec { return zip(vec(a), b, f); } 166 | template auto zip(const mat & a, const mat & b, F f) -> mat { return {zip(a.x,b.x,f), zip(a.y,b.y,f)}; } 167 | template auto zip(const mat & a, const mat & b, F f) -> mat { return {zip(a.x,b.x,f), zip(a.y,b.y,f), zip(a.z,b.z,f)}; } 168 | template auto zip(const mat & a, const mat & b, F f) -> mat { return {zip(a.x,b.x,f), zip(a.y,b.y,f), zip(a.z,b.z,f), zip(a.w,b.w,f)}; } 169 | template auto zip(const mat & a, T b, F f) -> mat { return zip(a, mat(b), f); } 170 | template auto zip( T a, const mat & b, F f) -> mat { return zip(mat(a), b, f); } 171 | 172 | // Produce a vector/matrix by applying f(T) to elements from vector/matrix a 173 | template auto map(const vec & a, F f) -> vec { return zip(a, a, [f](T l, T) { return f(l); }); } 174 | template auto map(const mat & a, F f) -> mat { return zip(a, a, [f](T l, T) { return f(l); }); } 175 | 176 | // Relational operators are defined to compare the elements of two vectors or matrices lexicographically, in column-major order 177 | template::compare_as> bool operator == (const A & a, const A & b) { return reinterpret_cast(a) == reinterpret_cast(b); } 178 | template::compare_as> bool operator != (const A & a, const A & b) { return reinterpret_cast(a) != reinterpret_cast(b); } 179 | template::compare_as> bool operator < (const A & a, const A & b) { return reinterpret_cast(a) < reinterpret_cast(b); } 180 | template::compare_as> bool operator > (const A & a, const A & b) { return reinterpret_cast(a) > reinterpret_cast(b); } 181 | template::compare_as> bool operator <= (const A & a, const A & b) { return reinterpret_cast(a) <= reinterpret_cast(b); } 182 | template::compare_as> bool operator >= (const A & a, const A & b) { return reinterpret_cast(a) >= reinterpret_cast(b); } 183 | 184 | // Functions for coalescing scalar values 185 | template bool any (const vec & a) { return fold(a, [](bool l, bool r) { return l || r; }); } 186 | template bool all (const vec & a) { return fold(a, [](bool l, bool r) { return l && r; }); } 187 | template T sum (const vec & a) { return fold(a, [](T l, T r) { return l + r; }); } 188 | template T product(const vec & a) { return fold(a, [](T l, T r) { return l * r; }); } 189 | template int argmin (const vec & a) { int j=0; for(int i=1; i int argmax (const vec & a) { int j=0; for(int i=1; i a[j]) j = i; return j; } 191 | template T minelem(const vec & a) { return a[argmin(a)]; } 192 | template T maxelem(const vec & a) { return a[argmax(a)]; } 193 | 194 | // Overloads for unary operators on vectors are implemented in terms of elementwise application of the operator 195 | template arith_result_t operator + (const A & a) { return map(a, [](scalar_t l) { return +l; }); } 196 | template arith_result_t operator - (const A & a) { return map(a, [](scalar_t l) { return -l; }); } 197 | template arith_result_t operator ~ (const A & a) { return map(a, [](scalar_t l) { return ~l; }); } 198 | template bool_result_t operator ! (const A & a) { return map(a, [](scalar_t l) { return !l; }); } 199 | 200 | // Mirror the set of unary scalar math functions to apply elementwise to vectors 201 | template result_t abs (const A & a) { return map(a, [](scalar_t l) { return std::abs (l); }); } 202 | template result_t floor(const A & a) { return map(a, [](scalar_t l) { return std::floor(l); }); } 203 | template result_t ceil (const A & a) { return map(a, [](scalar_t l) { return std::ceil (l); }); } 204 | template result_t exp (const A & a) { return map(a, [](scalar_t l) { return std::exp (l); }); } 205 | template result_t log (const A & a) { return map(a, [](scalar_t l) { return std::log (l); }); } 206 | template result_t log10(const A & a) { return map(a, [](scalar_t l) { return std::log10(l); }); } 207 | template result_t sqrt (const A & a) { return map(a, [](scalar_t l) { return std::sqrt (l); }); } 208 | template result_t sin (const A & a) { return map(a, [](scalar_t l) { return std::sin (l); }); } 209 | template result_t cos (const A & a) { return map(a, [](scalar_t l) { return std::cos (l); }); } 210 | template result_t tan (const A & a) { return map(a, [](scalar_t l) { return std::tan (l); }); } 211 | template result_t asin (const A & a) { return map(a, [](scalar_t l) { return std::asin (l); }); } 212 | template result_t acos (const A & a) { return map(a, [](scalar_t l) { return std::acos (l); }); } 213 | template result_t atan (const A & a) { return map(a, [](scalar_t l) { return std::atan (l); }); } 214 | template result_t sinh (const A & a) { return map(a, [](scalar_t l) { return std::sinh (l); }); } 215 | template result_t cosh (const A & a) { return map(a, [](scalar_t l) { return std::cosh (l); }); } 216 | template result_t tanh (const A & a) { return map(a, [](scalar_t l) { return std::tanh (l); }); } 217 | template result_t round(const A & a) { return map(a, [](scalar_t l) { return std::round(l); }); } 218 | 219 | // Overloads for vector op vector are implemented in terms of elementwise application of the operator, followed by casting back to the original type (integer promotion is suppressed) 220 | template arith_result_t operator + (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l + r; }); } 221 | template arith_result_t operator - (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l - r; }); } 222 | template arith_result_t operator * (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l * r; }); } 223 | template arith_result_t operator / (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l / r; }); } 224 | template arith_result_t operator % (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l % r; }); } 225 | template arith_result_t operator | (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l | r; }); } 226 | template arith_result_t operator ^ (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l ^ r; }); } 227 | template arith_result_t operator & (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l & r; }); } 228 | template arith_result_t operator << (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l << r; }); } 229 | template arith_result_t operator >> (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l >> r; }); } 230 | 231 | // Overloads for assignment operators are implemented trivially 232 | template result_t & operator += (A & a, const B & b) { return a = a + b; } 233 | template result_t & operator -= (A & a, const B & b) { return a = a - b; } 234 | template result_t & operator *= (A & a, const B & b) { return a = a * b; } 235 | template result_t & operator /= (A & a, const B & b) { return a = a / b; } 236 | template result_t & operator %= (A & a, const B & b) { return a = a % b; } 237 | template result_t & operator |= (A & a, const B & b) { return a = a | b; } 238 | template result_t & operator ^= (A & a, const B & b) { return a = a ^ b; } 239 | template result_t & operator &= (A & a, const B & b) { return a = a & b; } 240 | template result_t & operator <<= (A & a, const B & b) { return a = a << b; } 241 | template result_t & operator >>= (A & a, const B & b) { return a = a >> b; } 242 | 243 | // Mirror the set of binary scalar math functions to apply elementwise to vectors 244 | template result_t min (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l < r ? l : r; }); } 245 | template result_t max (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l > r ? l : r; }); } 246 | template result_t fmod (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return std::fmod (l, r); }); } 247 | template result_t pow (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return std::pow (l, r); }); } 248 | template result_t atan2(const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return std::atan2(l, r); }); } 249 | template result_t clamp(const A & a, const B & b, const B & c) { return min(max(a,b),c); } // TODO: Revisit 250 | 251 | // Functions for componentwise application of equivalence and relational operators 252 | template bool_result_t equal (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l == r; }); } 253 | template bool_result_t nequal (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l != r; }); } 254 | template bool_result_t less (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l < r; }); } 255 | template bool_result_t greater(const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l > r; }); } 256 | template bool_result_t lequal (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l <= r; }); } 257 | template bool_result_t gequal (const A & a, const B & b) { return zip(a, b, [](scalar_t l, scalar_t r) { return l >= r; }); } 258 | 259 | // Support for vector algebra 260 | template T cross (const vec & a, const vec & b) { return a.x*b.y-a.y*b.x; } 261 | template vec cross (const vec & a, const vec & b) { return {a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x}; } 262 | template T dot (const vec & a, const vec & b) { return sum(a*b); } 263 | template T length2 (const vec & a) { return dot(a,a); } 264 | template T length (const vec & a) { return std::sqrt(length2(a)); } 265 | template vec normalize(const vec & a) { return a / length(a); } 266 | template T distance2(const vec & a, const vec & b) { return length2(b-a); } 267 | template T distance (const vec & a, const vec & b) { return length(b-a); } 268 | template T uangle (const vec & a, const vec & b) { T d=dot(a,b); return d > 1 ? 0 : std::acos(d < -1 ? -1 : d); } 269 | template vec lerp (const vec & a, const vec & b, T t) { return a*(1-t) + b*t; } 270 | template vec nlerp (const vec & a, const vec & b, T t) { return normalize(lerp(a,b,t)); } 271 | template vec slerp (const vec & a, const vec & b, T t) { T th=uangle(a,b); return th == 0 ? a : a*(std::sin(th*(1-t))/std::sin(th)) + b*(std::sin(th*t)/std::sin(th)); } 272 | template mat outerprod(const vec & a, const vec & b) { return {a*b.x, a*b.y}; } 273 | template mat outerprod(const vec & a, const vec & b) { return {a*b.x, a*b.y, a*b.z}; } 274 | template mat outerprod(const vec & a, const vec & b) { return {a*b.x, a*b.y, a*b.z, a*b.w}; } 275 | 276 | // Support for quaternion algebra using 4D vectors, representing xi + yj + zk + w 277 | template vec qconj(const vec & q) { return {-q.x,-q.y,-q.z,q.w}; } 278 | template vec qinv (const vec & q) { return qconj(q)/length2(q); } 279 | template vec qmul (const vec & a, const vec & b) { return {a.x*b.w+a.w*b.x+a.y*b.z-a.z*b.y, a.y*b.w+a.w*b.y+a.z*b.x-a.x*b.z, a.z*b.w+a.w*b.z+a.x*b.y-a.y*b.x, a.w*b.w-a.x*b.x-a.y*b.y-a.z*b.z}; } 280 | template vec qmul(const vec & a, R... r) { return qmul(a, qmul(r...)); } 281 | // TODO: qexp, qlog 282 | 283 | // Support for 3D spatial rotations using quaternions, via qmul(qmul(q, v), qconj(q)) 284 | template vec qxdir (const vec & q) { return {q.w*q.w+q.x*q.x-q.y*q.y-q.z*q.z, (q.x*q.y+q.z*q.w)*2, (q.z*q.x-q.y*q.w)*2}; } 285 | template vec qydir (const vec & q) { return {(q.x*q.y-q.z*q.w)*2, q.w*q.w-q.x*q.x+q.y*q.y-q.z*q.z, (q.y*q.z+q.x*q.w)*2}; } 286 | template vec qzdir (const vec & q) { return {(q.z*q.x+q.y*q.w)*2, (q.y*q.z-q.x*q.w)*2, q.w*q.w-q.x*q.x-q.y*q.y+q.z*q.z}; } 287 | template mat qmat (const vec & q) { return {qxdir(q), qydir(q), qzdir(q)}; } 288 | template vec qrot (const vec & q, const vec & v) { return qxdir(q)*v.x + qydir(q)*v.y + qzdir(q)*v.z; } 289 | template T qangle(const vec & q) { return std::acos(q.w)*2; } 290 | template vec qaxis (const vec & q) { return normalize(q.xyz()); } 291 | template vec qnlerp(const vec & a, const vec & b, T t) { return nlerp(a, dot(a,b) < 0 ? -b : b, t); } 292 | template vec qslerp(const vec & a, const vec & b, T t) { return slerp(a, dot(a,b) < 0 ? -b : b, t); } 293 | 294 | // Support for matrix algebra 295 | template vec mul(const mat & a, const vec & b) { return a.x*b.x + a.y*b.y; } 296 | template vec mul(const mat & a, const vec & b) { return a.x*b.x + a.y*b.y + a.z*b.z; } 297 | template vec mul(const mat & a, const vec & b) { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; } 298 | template mat mul(const mat & a, const mat & b) { return {mul(a,b.x), mul(a,b.y)}; } 299 | template mat mul(const mat & a, const mat & b) { return {mul(a,b.x), mul(a,b.y), mul(a,b.z)}; } 300 | template mat mul(const mat & a, const mat & b) { return {mul(a,b.x), mul(a,b.y), mul(a,b.z), mul(a,b.w)}; } 301 | #if _MSC_VER >= 1910 302 | template constexpr auto mul(const mat & a, R... r) { return mul(a, mul(r...)); } 303 | #else 304 | template constexpr auto mul(const mat & a, R... r) -> decltype(mul(a, mul(r...))) { return mul(a, mul(r...)); } 305 | #endif 306 | template mat transpose(const mat & m) { return {m.row(0), m.row(1)}; } 307 | template mat transpose(const mat & m) { return {m.row(0), m.row(1), m.row(2)}; } 308 | template mat transpose(const mat & m) { return {m.row(0), m.row(1), m.row(2), m.row(3)}; } 309 | template mat adjugate(const mat & a) { return {{a.y.y, -a.x.y}, {-a.y.x, a.x.x}}; } 310 | template mat adjugate(const mat & a) { return {{a.y.y*a.z.z - a.z.y*a.y.z, a.z.y*a.x.z - a.x.y*a.z.z, a.x.y*a.y.z - a.y.y*a.x.z}, 311 | {a.y.z*a.z.x - a.z.z*a.y.x, a.z.z*a.x.x - a.x.z*a.z.x, a.x.z*a.y.x - a.y.z*a.x.x}, 312 | {a.y.x*a.z.y - a.z.x*a.y.y, a.z.x*a.x.y - a.x.x*a.z.y, a.x.x*a.y.y - a.y.x*a.x.y}}; } 313 | template mat adjugate(const mat & a) { return {{a.y.y*a.z.z*a.w.w + a.w.y*a.y.z*a.z.w + a.z.y*a.w.z*a.y.w - a.y.y*a.w.z*a.z.w - a.z.y*a.y.z*a.w.w - a.w.y*a.z.z*a.y.w, 314 | a.x.y*a.w.z*a.z.w + a.z.y*a.x.z*a.w.w + a.w.y*a.z.z*a.x.w - a.w.y*a.x.z*a.z.w - a.z.y*a.w.z*a.x.w - a.x.y*a.z.z*a.w.w, 315 | a.x.y*a.y.z*a.w.w + a.w.y*a.x.z*a.y.w + a.y.y*a.w.z*a.x.w - a.x.y*a.w.z*a.y.w - a.y.y*a.x.z*a.w.w - a.w.y*a.y.z*a.x.w, 316 | a.x.y*a.z.z*a.y.w + a.y.y*a.x.z*a.z.w + a.z.y*a.y.z*a.x.w - a.x.y*a.y.z*a.z.w - a.z.y*a.x.z*a.y.w - a.y.y*a.z.z*a.x.w}, 317 | {a.y.z*a.w.w*a.z.x + a.z.z*a.y.w*a.w.x + a.w.z*a.z.w*a.y.x - a.y.z*a.z.w*a.w.x - a.w.z*a.y.w*a.z.x - a.z.z*a.w.w*a.y.x, 318 | a.x.z*a.z.w*a.w.x + a.w.z*a.x.w*a.z.x + a.z.z*a.w.w*a.x.x - a.x.z*a.w.w*a.z.x - a.z.z*a.x.w*a.w.x - a.w.z*a.z.w*a.x.x, 319 | a.x.z*a.w.w*a.y.x + a.y.z*a.x.w*a.w.x + a.w.z*a.y.w*a.x.x - a.x.z*a.y.w*a.w.x - a.w.z*a.x.w*a.y.x - a.y.z*a.w.w*a.x.x, 320 | a.x.z*a.y.w*a.z.x + a.z.z*a.x.w*a.y.x + a.y.z*a.z.w*a.x.x - a.x.z*a.z.w*a.y.x - a.y.z*a.x.w*a.z.x - a.z.z*a.y.w*a.x.x}, 321 | {a.y.w*a.z.x*a.w.y + a.w.w*a.y.x*a.z.y + a.z.w*a.w.x*a.y.y - a.y.w*a.w.x*a.z.y - a.z.w*a.y.x*a.w.y - a.w.w*a.z.x*a.y.y, 322 | a.x.w*a.w.x*a.z.y + a.z.w*a.x.x*a.w.y + a.w.w*a.z.x*a.x.y - a.x.w*a.z.x*a.w.y - a.w.w*a.x.x*a.z.y - a.z.w*a.w.x*a.x.y, 323 | a.x.w*a.y.x*a.w.y + a.w.w*a.x.x*a.y.y + a.y.w*a.w.x*a.x.y - a.x.w*a.w.x*a.y.y - a.y.w*a.x.x*a.w.y - a.w.w*a.y.x*a.x.y, 324 | a.x.w*a.z.x*a.y.y + a.y.w*a.x.x*a.z.y + a.z.w*a.y.x*a.x.y - a.x.w*a.y.x*a.z.y - a.z.w*a.x.x*a.y.y - a.y.w*a.z.x*a.x.y}, 325 | {a.y.x*a.w.y*a.z.z + a.z.x*a.y.y*a.w.z + a.w.x*a.z.y*a.y.z - a.y.x*a.z.y*a.w.z - a.w.x*a.y.y*a.z.z - a.z.x*a.w.y*a.y.z, 326 | a.x.x*a.z.y*a.w.z + a.w.x*a.x.y*a.z.z + a.z.x*a.w.y*a.x.z - a.x.x*a.w.y*a.z.z - a.z.x*a.x.y*a.w.z - a.w.x*a.z.y*a.x.z, 327 | a.x.x*a.w.y*a.y.z + a.y.x*a.x.y*a.w.z + a.w.x*a.y.y*a.x.z - a.x.x*a.y.y*a.w.z - a.w.x*a.x.y*a.y.z - a.y.x*a.w.y*a.x.z, 328 | a.x.x*a.y.y*a.z.z + a.z.x*a.x.y*a.y.z + a.y.x*a.z.y*a.x.z - a.x.x*a.z.y*a.y.z - a.y.x*a.x.y*a.z.z - a.z.x*a.y.y*a.x.z}}; } 329 | template T determinant(const mat & a) { return a.x.x*a.y.y - a.x.y*a.y.x; } 330 | template T determinant(const mat & a) { return a.x.x*(a.y.y*a.z.z - a.z.y*a.y.z) + a.x.y*(a.y.z*a.z.x - a.z.z*a.y.x) + a.x.z*(a.y.x*a.z.y - a.z.x*a.y.y); } 331 | template T determinant(const mat & a) { return a.x.x*(a.y.y*a.z.z*a.w.w + a.w.y*a.y.z*a.z.w + a.z.y*a.w.z*a.y.w - a.y.y*a.w.z*a.z.w - a.z.y*a.y.z*a.w.w - a.w.y*a.z.z*a.y.w) 332 | + a.x.y*(a.y.z*a.w.w*a.z.x + a.z.z*a.y.w*a.w.x + a.w.z*a.z.w*a.y.x - a.y.z*a.z.w*a.w.x - a.w.z*a.y.w*a.z.x - a.z.z*a.w.w*a.y.x) 333 | + a.x.z*(a.y.w*a.z.x*a.w.y + a.w.w*a.y.x*a.z.y + a.z.w*a.w.x*a.y.y - a.y.w*a.w.x*a.z.y - a.z.w*a.y.x*a.w.y - a.w.w*a.z.x*a.y.y) 334 | + a.x.w*(a.y.x*a.w.y*a.z.z + a.z.x*a.y.y*a.w.z + a.w.x*a.z.y*a.y.z - a.y.x*a.z.y*a.w.z - a.w.x*a.y.y*a.z.z - a.z.x*a.w.y*a.y.z); } 335 | template mat inverse(const mat & a) { return adjugate(a)/determinant(a); } 336 | 337 | // Vectors and matrices can be used as ranges 338 | template T * begin( vec & a) { return &a[0]; } 339 | template const T * begin(const vec & a) { return &a[0]; } 340 | template T * end ( vec & a) { return begin(a) + M; } 341 | template const T * end (const vec & a) { return begin(a) + M; } 342 | template vec * begin( mat & a) { return &a[0]; } 343 | template const vec * begin(const mat & a) { return &a[0]; } 344 | template vec * end ( mat & a) { return begin(a) + N; } 345 | template const vec * end (const mat & a) { return begin(a) + N; } 346 | 347 | // Factory functions for 3D spatial transformations (will possibly be removed or changed in a future version) 348 | template vec rotation_quat (const vec & axis, T angle) { return {axis*std::sin(angle/2), std::cos(angle/2)}; } 349 | template mat translation_matrix(const vec & translation) { return {{1,0,0,0},{0,1,0,0},{0,0,1,0},{translation,1}}; } 350 | template mat rotation_matrix (const vec & rotation) { return {{qxdir(rotation),0}, {qydir(rotation),0}, {qzdir(rotation),0}, {0,0,0,1}}; } 351 | template mat pose_matrix (const vec & q, const vec & p) { return {{qxdir(q),0}, {qydir(q),0}, {qzdir(q),0}, {p,1}}; } 352 | template mat frustum_matrix (T l, T r, T b, T t, T n, T f) { return {{2*n/(r-l),0,0,0}, {0,2*n/(t-b),0,0}, {(r+l)/(r-l),(t+b)/(t-b),-(f+n)/(f-n),-1}, {0,0,-2*f*n/(f-n),0}}; } 353 | template mat perspective_matrix(T fovy, T aspect, T n, T f) { T y = n*std::tan(fovy/2), x=y*aspect; return frustum_matrix(-x,x,-y,y,n,f); } 354 | 355 | // Provide typedefs for common element types and vector/matrix sizes 356 | namespace aliases 357 | { 358 | typedef vec bool2; typedef vec byte2; typedef vec short2; typedef vec ushort2; 359 | typedef vec bool3; typedef vec byte3; typedef vec short3; typedef vec ushort3; 360 | typedef vec bool4; typedef vec byte4; typedef vec short4; typedef vec ushort4; 361 | typedef vec int2; typedef vec uint2; typedef vec float2; typedef vec double2; 362 | typedef vec int3; typedef vec uint3; typedef vec float3; typedef vec double3; 363 | typedef vec int4; typedef vec uint4; typedef vec float4; typedef vec double4; 364 | typedef mat bool2x2; typedef mat int2x2; typedef mat float2x2; typedef mat double2x2; 365 | typedef mat bool2x3; typedef mat int2x3; typedef mat float2x3; typedef mat double2x3; 366 | typedef mat bool2x4; typedef mat int2x4; typedef mat float2x4; typedef mat double2x4; 367 | typedef mat bool3x2; typedef mat int3x2; typedef mat float3x2; typedef mat double3x2; 368 | typedef mat bool3x3; typedef mat int3x3; typedef mat float3x3; typedef mat double3x3; 369 | typedef mat bool3x4; typedef mat int3x4; typedef mat float3x4; typedef mat double3x4; 370 | typedef mat bool4x2; typedef mat int4x2; typedef mat float4x2; typedef mat double4x2; 371 | typedef mat bool4x3; typedef mat int4x3; typedef mat float4x3; typedef mat double4x3; 372 | typedef mat bool4x4; typedef mat int4x4; typedef mat float4x4; typedef mat double4x4; 373 | } 374 | } 375 | 376 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "glutil.h" 4 | #include "geometric.h" 5 | 6 | // Functions and Variables from bunny module 7 | extern void InitModel(); 8 | extern char * RenderModel( float DeltaT ); 9 | extern float3 model_position; // position of bunny 10 | extern float4 model_orientation; // orientation of bunny 11 | 12 | 13 | 14 | int main(void) 15 | { 16 | GLFWwindow* window; 17 | 18 | /* Initialize the library */ 19 | if (!glfwInit()) 20 | return -1; 21 | 22 | /* Create a windowed mode window and its OpenGL context */ 23 | window = glfwCreateWindow(640, 480, "BunnyLOD", NULL, NULL); 24 | if (!window) 25 | { 26 | glfwTerminate(); 27 | return -1; 28 | } 29 | 30 | /* Make the window's context current */ 31 | glfwMakeContextCurrent(window); 32 | glClearColor( 0.4f, 0.3f, 0.4f, 0.0f ); 33 | 34 | double lastFrameTime = glfwGetTime(); 35 | 36 | InitModel(); // initializes some data structures and does progressive mesh polygon reduction algorithm 37 | GLUtil glUtil; 38 | 39 | glEnable(GL_CULL_FACE); 40 | glEnable(GL_DEPTH_TEST); 41 | 42 | float3 MouseVectorOld; 43 | const float ViewAngle = 60.f; 44 | 45 | 46 | /* Loop until the user closes the window */ 47 | while (!glfwWindowShouldClose(window)) 48 | { 49 | double currTime = glfwGetTime(); 50 | float deltaT = (float)( currTime - lastFrameTime ); 51 | lastFrameTime = currTime; 52 | 53 | int width, height; 54 | glfwGetFramebufferSize(window,&width,&height); 55 | float2 res = { (float)width,(float)height }; 56 | float3 MouseVector; 57 | 58 | // ComputeMouseVector 59 | double mouseposx, mouseposy; 60 | glfwGetCursorPos(window,&mouseposx,&mouseposy); 61 | float spread = (float)tan(ViewAngle / 2 * 3.14 / 180); 62 | float y = spread * ((res.y - (float)mouseposy) - res.y / 2.0f) / (res.y / 2.0f); 63 | float x = spread * ((float)mouseposx - res.x / 2.0f) / (res.y / 2.0f); 64 | MouseVector = normalize(float3(x, y, -1)); 65 | if( glfwGetMouseButton(window,0) ) 66 | { 67 | model_orientation=qmul(VirtualTrackBall(float3(0,0,0),model_position,MouseVectorOld,MouseVector),model_orientation); 68 | } 69 | MouseVectorOld = MouseVector; 70 | 71 | 72 | /* Render here */ 73 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 74 | 75 | glViewport(0, 0, width, height); 76 | glMatrixMode(GL_PROJECTION); 77 | glLoadIdentity(); 78 | glPerspective(ViewAngle, (float)width/height, 0.1f, 50.0f); 79 | glMatrixMode(GL_MODELVIEW); 80 | glLoadIdentity(); 81 | 82 | 83 | glPushMatrix(); 84 | glLoadIdentity(); 85 | // camera at default (zero) position and orientation 86 | char * s=RenderModel( deltaT ); 87 | 88 | glLoadIdentity(); 89 | glColor3f(1,1,0); 90 | glUtil.PrintString({ 0, -2 },s); // print returned status string from rendermodel() current vert and tri count 91 | glUtil.PrintString({ 5, 1 },"Demo by Stan Melax (c)1998"); 92 | glUtil.PrintString({ 5, 2 },"Model by Viewpoint Datalabs (c)1996"); 93 | glUtil.PrintString({ 0, -1 }, "FPS: %5.2f ", 1.0f/deltaT); 94 | 95 | 96 | glPopMatrix(); 97 | 98 | /* Swap front and back buffers */ 99 | glfwSwapBuffers(window); 100 | 101 | /* Poll for and process events */ 102 | glfwPollEvents(); 103 | } 104 | 105 | glfwTerminate(); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /misc.h: -------------------------------------------------------------------------------- 1 | // 2 | // Common convenience routines not yet sure about convention or where it goes. 3 | // Rather than copy-paste code between projects, better to move into this file. 4 | // Stuff in this file should generally only depend on standard library. 5 | // So graphics stuff would go in misc_gl.h instead. 6 | // 7 | 8 | #pragma once 9 | #ifndef SANDBOX_MISC_H 10 | #define SANDBOX_MISC_H 11 | 12 | //----------------------- 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | // some misc convenience functions 22 | template auto Transform(std::vector &src, F f) { std::vector> dst;dst.reserve(src.size()); std::transform(src.begin(), src.end(), std::back_inserter(dst), f); return dst; } 23 | template auto Transform(const std::vector &src, F f) { std::vector> dst;dst.reserve(src.size()); std::transform(src.begin(), src.end(), std::back_inserter(dst), f); return dst; } 24 | template std::vector & Append(std::vector &a, const T& t) { a.push_back(t); return a; } 25 | template std::vector & Append(std::vector &a, T&& t) { a.push_back(std::move(t)); return a; } 26 | template std::vector & Append(std::vector &a, const std::vector &b) { a.insert(a.end(), b.begin(), b.end()); return a; } 27 | template std::vector & Append(std::vector &a, std::vector &&b) { for(auto &e:b) a.push_back(std::move(e)); return a; } 28 | template std::vector Addresses( std::vector &a) { return Transform(a, [](T &t)->T* {return &t; }); } 29 | template std::vector Addresses(const std::vector &a) { return Transform(a, [](T &t)->T* {return &t; }); } 30 | 31 | 32 | // fixme: basepathname and fileprefix are just two attempts to implemement the same thing 33 | 34 | inline std::string basepathname(std::string fname) { return std::string(fname.begin(), fname.begin() + fname.find_last_of('.')); } // FIXME stl string newb not sure if correct if no '.' exists 35 | inline bool fileexists(std::string filename) { std::ifstream i(filename, std::ifstream::in); return i.is_open(); } 36 | inline std::string filesuffix(std::string fname) { std::string s(fname.begin() + fname.find_last_of('.'), fname.end()); return (s.find('/') == std::string::npos && s.find('\\') == std::string::npos) ? s : ""; } 37 | 38 | inline const char* strstp(const char *s, char c) { const char* p = NULL; while (*s) { if (*s == c) p = s; s++; } return p?p:s; } // pointer to last c in string s or end of string if not found 39 | inline std::string fileprefix(const char *filename) { return std::string(filename, strstp(filename, '.')); } 40 | inline std::string fileprefix(std::string filename) { return fileprefix(filename.c_str()); } 41 | 42 | inline std::string freefilename(std::string prefix, std::string suffix) // find next unused file in sequence 43 | { 44 | int fid = 0; 45 | auto fnaming_convention = [prefix, suffix](int fid) { return prefix + std::to_string(fid) + suffix; }; 46 | while (fileexists(fnaming_convention(fid).c_str())) 47 | fid++; 48 | return fnaming_convention(fid); 49 | } 50 | 51 | 52 | 53 | inline std::vector split(std::string line, std::string delimeter = " ", size_t minlength = 1) // move to misc.h 54 | { 55 | std::vector tokens; 56 | size_t pos = 0; 57 | while ((pos = line.find(delimeter)) != std::string::npos) 58 | { 59 | auto token = line.substr(0, pos); 60 | line.erase(0, pos + delimeter.length()); 61 | if (token.length()>= minlength) 62 | tokens.push_back(token); 63 | } 64 | if (line.length()>=minlength) 65 | tokens.push_back(line); 66 | return tokens; 67 | } 68 | 69 | 70 | template 71 | inline std::vector ArrayImport(std::string str) 72 | { 73 | std::vector a; 74 | std::istringstream s(str); 75 | T e; 76 | while (((s >> e), s.good())) 77 | { 78 | a.push_back(e); 79 | s.ignore(16, '\n'); 80 | } 81 | return a; 82 | } 83 | 84 | // ToString() - convenience class/function for using << overloads to generate strings inline within a single expression 85 | // Example Usage: return ToString() << "test" << my_vec3 << " more " << my_float_var << " and so on"; 86 | // or: set_thermometer_gui_string( ToString() << (temperature*9/5+32) ); 87 | struct ToString 88 | { 89 | std::ostringstream o; 90 | std::string str() { return o.str(); } 91 | operator std::string() { return o.str(); } 92 | templateToString &operator<<(const T &t) { o << t; return *this; } 93 | }; 94 | 95 | // StringTo and FromString - convenience class/function for using >> overloads to convert from strings inline within a single expression 96 | // f(StringTo("6 7 8")); // if f() is overloaded specify type with StringTo<>() 97 | // g(FromString("9")); // works if g isn't overloaded such as it takes a float 98 | // 99 | template inline T StringTo(std::string s) { T v; std::istringstream i(std::move(s)); i >> v; return v; } 100 | 101 | struct FromString 102 | { 103 | const std::string &s; 104 | FromString(const std::string &s) :s(s) {} 105 | template operator T () { return StringTo(s); } 106 | operator std::string() { return s; } 107 | }; 108 | 109 | 110 | template void visit_fields(T&t, F f) { t.visit_fields(f); } 111 | 112 | template inline typename std::enable_if::type 113 | visit_fields(std::tuple ¶ms, F f) 114 | {} 115 | 116 | template inline typename std::enable_if< I < sizeof...(TS), void>::type 117 | visit_fields(std::tuple ¶ms, F f) 118 | { 119 | f(std::get(params), std::get(params)); 120 | visit_fields(params, f); 121 | } 122 | 123 | 124 | 125 | #endif // SANDBOX_MISC_H 126 | 127 | -------------------------------------------------------------------------------- /progmesh.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Progressive Mesh type Polygon Reduction Algorithm 3 | * by Stan Melax (c) 1998 4 | * Permission to use any of this code wherever you want is granted.. 5 | * Although, please do acknowledge authorship if appropriate. 6 | * 7 | * See the header file progmesh.h for a description of this module 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "progmesh.h" 19 | 20 | template int Contains(const std::vector & c, const T & t){ return (int)std::count(begin(c), end(c), t); } 21 | template int IndexOf(const std::vector & c, const T & v) { return (int)( std::find(begin(c), end(c), v) - begin(c) ); } // Note: Not presently called 22 | template T & Add(std::vector & c, T t) { c.push_back(t); return c.back(); } 23 | template T Pop(std::vector & c) { auto val = std::move(c.back()); c.pop_back(); return val; } 24 | template void AddUnique(std::vector & c, T t) { if (!Contains(c, t)) c.push_back(t); } 25 | template void Remove(std::vector & c, T t) { auto it = std::find(begin(c), end(c), t); assert(it != end(c)); c.erase(it); assert(!Contains(c, t)); } 26 | 27 | 28 | /* 29 | * For the polygon reduction algorithm we use data structures 30 | * that contain a little bit more information than the usual 31 | * indexed face set type of data structure. 32 | * From a vertex we wish to be able to quickly get the 33 | * neighboring faces and vertices. 34 | */ 35 | class Triangle; 36 | class Vertex; 37 | 38 | class Triangle { 39 | public: 40 | Vertex * vertex[3]; // the 3 points that make this tri 41 | float3 normal; // unit vector othogonal to this face 42 | Triangle(Vertex *v0,Vertex *v1,Vertex *v2); 43 | ~Triangle(); 44 | void ComputeNormal(); 45 | void ReplaceVertex(Vertex *vold,Vertex *vnew); 46 | int HasVertex(Vertex *v); 47 | }; 48 | class Vertex { 49 | public: 50 | float3 position; // location of point in euclidean space 51 | int id; // place of vertex in original Array 52 | std::vector neighbor; // adjacent vertices 53 | std::vector face; // adjacent triangles 54 | float objdist; // cached cost of collapsing edge 55 | Vertex * collapse; // candidate vertex for collapse 56 | Vertex(float3 v,int _id); 57 | ~Vertex(); 58 | void RemoveIfNonNeighbor(Vertex *n); 59 | }; 60 | std::vector vertices; 61 | std::vector triangles; 62 | 63 | 64 | Triangle::Triangle(Vertex *v0,Vertex *v1,Vertex *v2){ 65 | assert(v0!=v1 && v1!=v2 && v2!=v0); 66 | vertex[0]=v0; 67 | vertex[1]=v1; 68 | vertex[2]=v2; 69 | ComputeNormal(); 70 | triangles.push_back(this); 71 | for(int i=0;i<3;i++) { 72 | vertex[i]->face.push_back(this); 73 | for(int j=0;j<3;j++) if(i!=j) { 74 | AddUnique(vertex[i]->neighbor, vertex[j]); 75 | } 76 | } 77 | } 78 | Triangle::~Triangle(){ 79 | Remove(triangles,this); 80 | for(int i=0;i<3;i++) { 81 | if(vertex[i]) Remove(vertex[i]->face,this); 82 | } 83 | for (int i = 0; i<3; i++) { 84 | int i2 = (i+1)%3; 85 | if(!vertex[i] || !vertex[i2]) continue; 86 | vertex[i ]->RemoveIfNonNeighbor(vertex[i2]); 87 | vertex[i2]->RemoveIfNonNeighbor(vertex[i ]); 88 | } 89 | } 90 | int Triangle::HasVertex(Vertex *v) { 91 | return (v==vertex[0] ||v==vertex[1] || v==vertex[2]); 92 | } 93 | void Triangle::ComputeNormal() 94 | { 95 | float3 v0=vertex[0]->position; 96 | float3 v1=vertex[1]->position; 97 | float3 v2=vertex[2]->position; 98 | normal = cross(v1-v0,v2-v1); 99 | if(length(normal)==0)return; 100 | normal = normalize(normal); 101 | } 102 | 103 | void Triangle::ReplaceVertex(Vertex *vold,Vertex *vnew) 104 | { 105 | assert(vold && vnew); 106 | assert(vold==vertex[0] || vold==vertex[1] || vold==vertex[2]); 107 | assert(vnew!=vertex[0] && vnew!=vertex[1] && vnew!=vertex[2]); 108 | if(vold==vertex[0]){ 109 | vertex[0]=vnew; 110 | } 111 | else if(vold==vertex[1]){ 112 | vertex[1]=vnew; 113 | } 114 | else { 115 | assert(vold==vertex[2]); 116 | vertex[2]=vnew; 117 | } 118 | Remove(vold->face,this); 119 | assert(!Contains(vnew->face,this)); 120 | vnew->face.push_back(this); 121 | for (int i = 0; i<3; i++) { 122 | vold->RemoveIfNonNeighbor(vertex[i]); 123 | vertex[i]->RemoveIfNonNeighbor(vold); 124 | } 125 | for (int i = 0; i<3; i++) { 126 | assert(Contains(vertex[i]->face,this)==1); 127 | for(int j=0;j<3;j++) if(i!=j) { 128 | AddUnique(vertex[i]->neighbor,vertex[j]); 129 | } 130 | } 131 | ComputeNormal(); 132 | } 133 | 134 | Vertex::Vertex(float3 v,int _id) { 135 | position =v; 136 | id=_id; 137 | vertices.push_back(this); 138 | } 139 | 140 | Vertex::~Vertex(){ 141 | assert(face.size() == 0); 142 | while(neighbor.size()) { 143 | Remove(neighbor[0]->neighbor,this); 144 | Remove(neighbor,neighbor[0]); 145 | } 146 | Remove(vertices,this); 147 | } 148 | void Vertex::RemoveIfNonNeighbor(Vertex *n) { 149 | // removes n from neighbor Array if n isn't a neighbor. 150 | if(!Contains(neighbor,n)) return; 151 | for (unsigned int i = 0; iHasVertex(n)) return; 153 | } 154 | Remove(neighbor,n); 155 | } 156 | 157 | 158 | float ComputeEdgeCollapseCost(Vertex *u,Vertex *v) { 159 | // if we collapse edge uv by moving u to v then how 160 | // much different will the model change, i.e. how much "error". 161 | // Texture, vertex normal, and border vertex code was removed 162 | // to keep this demo as simple as possible. 163 | // The method of determining cost was designed in order 164 | // to exploit small and coplanar regions for 165 | // effective polygon reduction. 166 | // Is is possible to add some checks here to see if "folds" 167 | // would be generated. i.e. normal of a remaining face gets 168 | // flipped. I never seemed to run into this problem and 169 | // therefore never added code to detect this case. 170 | float edgelength = length(v->position - u->position); 171 | float curvature=0; 172 | 173 | // find the "sides" triangles that are on the edge uv 174 | std::vector sides; 175 | for (unsigned int i = 0; iface.size(); i++) { 176 | if(u->face[i]->HasVertex(v)){ 177 | sides.push_back(u->face[i]); 178 | } 179 | } 180 | // use the triangle facing most away from the sides 181 | // to determine our curvature term 182 | for (unsigned int i = 0; iface.size(); i++) { 183 | float mincurv=1; // curve for face i and closer side to it 184 | for (unsigned int j = 0; jface[i]->normal , sides[j]->normal); // use dot product of face normals. 186 | mincurv = std::min(mincurv,(1-dotprod)/2.0f); 187 | } 188 | curvature = std::max(curvature, mincurv); 189 | } 190 | // the more coplanar the lower the curvature term 191 | return edgelength * curvature; 192 | } 193 | 194 | void ComputeEdgeCostAtVertex(Vertex *v) { 195 | // compute the edge collapse cost for all edges that start 196 | // from vertex v. Since we are only interested in reducing 197 | // the object by selecting the min cost edge at each step, we 198 | // only cache the cost of the least cost edge at this vertex 199 | // (in member variable collapse) as well as the value of the 200 | // cost (in member variable objdist). 201 | if (v->neighbor.size() == 0) { 202 | // v doesn't have neighbors so it costs nothing to collapse 203 | v->collapse=NULL; 204 | v->objdist=-0.01f; 205 | return; 206 | } 207 | v->objdist = 1000000; 208 | v->collapse=NULL; 209 | // search all neighboring edges for "least cost" edge 210 | for (unsigned int i = 0; ineighbor.size(); i++) { 211 | float dist; 212 | dist = ComputeEdgeCollapseCost(v,v->neighbor[i]); 213 | if(distobjdist) { 214 | v->collapse=v->neighbor[i]; // candidate for edge collapse 215 | v->objdist=dist; // cost of the collapse 216 | } 217 | } 218 | } 219 | void ComputeAllEdgeCollapseCosts() { 220 | // For all the edges, compute the difference it would make 221 | // to the model if it was collapsed. The least of these 222 | // per vertex is cached in each vertex object. 223 | for (unsigned int i = 0; itmp; 238 | // make tmp a Array of all the neighbors of u 239 | for (unsigned int i = 0; ineighbor.size(); i++) { 240 | tmp.push_back(u->neighbor[i]); 241 | } 242 | // delete triangles on edge uv: 243 | { 244 | auto i = u->face.size(); 245 | while (i--) { 246 | if (u->face[i]->HasVertex(v)) { 247 | delete(u->face[i]); 248 | } 249 | } 250 | } 251 | // update remaining triangles to have v instead of u 252 | { 253 | auto i = u->face.size(); 254 | while (i--) { 255 | u->face[i]->ReplaceVertex(u, v); 256 | } 257 | } 258 | delete u; 259 | // recompute the edge collapse costs for neighboring vertices 260 | for (unsigned int i = 0; i &vert){ 266 | for (unsigned int i = 0; i &tri){ 271 | for (unsigned int i = 0; iobjdist < mn->objdist) { 289 | mn = vertices[i]; 290 | } 291 | } 292 | return mn; 293 | } 294 | 295 | void ProgressiveMesh(std::vector &vert, std::vector &tri, 296 | std::vector &map, std::vector &permutation) 297 | { 298 | AddVertex(vert); // put input data into our data structures 299 | AddFaces(tri); 300 | ComputeAllEdgeCollapseCosts(); // cache all edge collapse costs 301 | permutation.resize(vertices.size()); // allocate space 302 | map.resize(vertices.size()); // allocate space 303 | // reduce the object down to nothing: 304 | size_t sizeofVerts = vertices.size(); 305 | while (vertices.size() ) { 306 | // get the next vertex to collapse 307 | Vertex *mn = MinimumCostEdge(); 308 | // keep track of this vertex, i.e. the collapse ordering 309 | permutation[mn->id] = (int)vertices.size() - 1; 310 | // keep track of vertex to which we collapse to 311 | map[vertices.size() - 1] = (mn->collapse) ? mn->collapse->id : -1; 312 | // Collapse this edge 313 | Collapse(mn,mn->collapse); 314 | } 315 | // reorder the map Array based on the collapse ordering 316 | for (unsigned int i = 0; i 22 | #include "linalg.h" 23 | using namespace linalg::aliases; 24 | class tridata { 25 | public: 26 | int v[3]; // indices to vertex Array 27 | // texture and vertex normal info removed for this demo 28 | }; 29 | 30 | void ProgressiveMesh(std::vector &vert, std::vector &tri, 31 | std::vector &map, std::vector &permutation); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /rabdata.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright 1996, Viewpoint Datalabs Int'l, www.viewpoint.com, 1-800-DATASET */ 2 | /* 3 | # Usage Rights: You (the user) may use this model to help build cool personal 4 | # vrml worlds, but please give us credit when you do ("3D model provided by 5 | # Viewpoint Datalabs, www,viewpoint.com"). Please don't sell it or use it to 6 | # make money indirectly. Don't redistribute it or put it on a web site except 7 | # as a part of your personal, non-commerical vrml world. If you want to do a 8 | # commercial project, give us a call at 1-800-DATASET or visit www.viewpoint.com 9 | # and we'll help you obtain the rights to do so. 10 | */ 11 | 12 | /* 13 | * Note that this data was put directly into the program 14 | * to provide a demo program on the net that people could 15 | * just run without having to fetch datafiles. 16 | * i.e. more convienent for the user this way 17 | */ 18 | 19 | #include "rabdata.h" 20 | 21 | #pragma warning(disable : 4305) 22 | #pragma warning(disable : 4136) 23 | 24 | float rabbit_vertices[RABBIT_VERTEX_NUM][3]={ 25 | {-0.334392f,0.133007f,0.062259f}, 26 | {-0.350189f,0.150354f,-0.147769f}, 27 | {-0.234201f,0.343811f,-0.174307f}, 28 | {-0.200259f,0.285207f,0.093749f}, 29 | {0.003520f,0.475208f,-0.159365f}, 30 | {0.001856f,0.419203f,0.098582f}, 31 | {-0.252802f,0.093666f,0.237538f}, 32 | {-0.162901f,0.237984f,0.206905f}, 33 | {0.000865f,0.318141f,0.235370f}, 34 | {-0.414624f,0.164083f,-0.278254f}, 35 | {-0.262213f,0.357334f,-0.293246f}, 36 | {0.004628f,0.482694f,-0.338626f}, 37 | {-0.402162f,0.133528f,-0.443247f}, 38 | {-0.243781f,0.324275f,-0.436763f}, 39 | {0.005293f,0.437592f,-0.458332f}, 40 | {-0.339884f,-0.041150f,-0.668211f}, 41 | {-0.248382f,0.255825f,-0.627493f}, 42 | {0.006261f,0.376103f,-0.631506f}, 43 | {-0.216201f,-0.126776f,-0.886936f}, 44 | {-0.171075f,0.011544f,-0.881386f}, 45 | {-0.181074f,0.098223f,-0.814779f}, 46 | {-0.119891f,0.218786f,-0.760153f}, 47 | {-0.078895f,0.276780f,-0.739281f}, 48 | {0.006801f,0.310959f,-0.735661f}, 49 | {-0.168842f,0.102387f,-0.920381f}, 50 | {-0.104072f,0.177278f,-0.952530f}, 51 | {-0.129704f,0.211848f,-0.836678f}, 52 | {-0.099875f,0.310931f,-0.799381f}, 53 | {0.007237f,0.361687f,-0.794439f}, 54 | {-0.077913f,0.258753f,-0.921640f}, 55 | {0.007957f,0.282241f,-0.931680f}, 56 | {-0.252222f,-0.550401f,-0.557810f}, 57 | {-0.267633f,-0.603419f,-0.655209f}, 58 | {-0.446838f,-0.118517f,-0.466159f}, 59 | {-0.459488f,-0.093017f,-0.311341f}, 60 | {-0.370645f,-0.100108f,-0.159454f}, 61 | {-0.371984f,-0.091991f,-0.011044f}, 62 | {-0.328945f,-0.098269f,0.088659f}, 63 | {-0.282452f,-0.018862f,0.311501f}, 64 | {-0.352403f,-0.131341f,0.144902f}, 65 | {-0.364126f,-0.200299f,0.202388f}, 66 | {-0.283965f,-0.231869f,0.023668f}, 67 | {-0.298943f,-0.155218f,0.369716f}, 68 | {-0.293787f,-0.121856f,0.419097f}, 69 | {-0.290163f,-0.290797f,0.107824f}, 70 | {-0.264165f,-0.272849f,0.036347f}, 71 | {-0.228567f,-0.372573f,0.290309f}, 72 | {-0.190431f,-0.286997f,0.421917f}, 73 | {-0.191039f,-0.240973f,0.507118f}, 74 | {-0.287272f,-0.276431f,-0.065444f}, 75 | {-0.295675f,-0.280818f,-0.174200f}, 76 | {-0.399537f,-0.313131f,-0.376167f}, 77 | {-0.392666f,-0.488581f,-0.427494f}, 78 | {-0.331669f,-0.570185f,-0.466054f}, 79 | {-0.282290f,-0.618140f,-0.589220f}, 80 | {-0.374238f,-0.594882f,-0.323298f}, 81 | {-0.381071f,-0.629723f,-0.350777f}, 82 | {-0.382112f,-0.624060f,-0.221577f}, 83 | {-0.272701f,-0.566522f,0.259157f}, 84 | {-0.256702f,-0.663406f,0.286079f}, 85 | {-0.280948f,-0.428359f,0.055790f}, 86 | {-0.184974f,-0.508894f,0.326265f}, 87 | {-0.279971f,-0.526918f,0.395319f}, 88 | {-0.282599f,-0.663393f,0.412411f}, 89 | {-0.188329f,-0.475093f,0.417954f}, 90 | {-0.263384f,-0.663396f,0.466604f}, 91 | {-0.209063f,-0.663393f,0.509344f}, 92 | {-0.002044f,-0.319624f,0.553078f}, 93 | {-0.001266f,-0.371260f,0.413296f}, 94 | {-0.219753f,-0.339762f,-0.040921f}, 95 | {-0.256986f,-0.282511f,-0.006349f}, 96 | {-0.271706f,-0.260881f,0.001764f}, 97 | {-0.091191f,-0.419184f,-0.045912f}, 98 | {-0.114944f,-0.429752f,-0.124739f}, 99 | {-0.113970f,-0.382987f,-0.188540f}, 100 | {-0.243012f,-0.464942f,-0.242850f}, 101 | {-0.314815f,-0.505402f,-0.324768f}, 102 | {0.002774f,-0.437526f,-0.262766f}, 103 | {-0.072625f,-0.417748f,-0.221440f}, 104 | {-0.160112f,-0.476932f,-0.293450f}, 105 | {0.003859f,-0.453425f,-0.443916f}, 106 | {-0.120363f,-0.581567f,-0.438689f}, 107 | {-0.091499f,-0.584191f,-0.294511f}, 108 | {-0.116469f,-0.599861f,-0.188308f}, 109 | {-0.208032f,-0.513640f,-0.134649f}, 110 | {-0.235749f,-0.610017f,-0.040939f}, 111 | {-0.344916f,-0.622487f,-0.085380f}, 112 | {-0.336401f,-0.531864f,-0.212298f}, 113 | {0.001961f,-0.459550f,-0.135547f}, 114 | {-0.058296f,-0.430536f,-0.043440f}, 115 | {0.001378f,-0.449511f,-0.037762f}, 116 | {-0.130135f,-0.510222f,0.079144f}, 117 | {0.000142f,-0.477549f,0.157064f}, 118 | {-0.114284f,-0.453206f,0.304397f}, 119 | {-0.000592f,-0.443558f,0.285401f}, 120 | {-0.056215f,-0.663402f,0.326073f}, 121 | {-0.026248f,-0.568010f,0.273318f}, 122 | {-0.049261f,-0.531064f,0.389854f}, 123 | {-0.127096f,-0.663398f,0.479316f}, 124 | {-0.058384f,-0.663401f,0.372891f}, 125 | {-0.303961f,0.054199f,0.625921f}, 126 | {-0.268594f,0.193403f,0.502766f}, 127 | {-0.277159f,0.126123f,0.443289f}, 128 | {-0.287605f,-0.005722f,0.531844f}, 129 | {-0.231396f,-0.121289f,0.587387f}, 130 | {-0.253475f,-0.081797f,0.756541f}, 131 | {-0.195164f,-0.137969f,0.728011f}, 132 | {-0.167673f,-0.156573f,0.609388f}, 133 | {-0.145917f,-0.169029f,0.697600f}, 134 | {-0.077776f,-0.214247f,0.622586f}, 135 | {-0.076873f,-0.214971f,0.696301f}, 136 | {-0.002341f,-0.233135f,0.622859f}, 137 | {-0.002730f,-0.213526f,0.691267f}, 138 | {-0.003136f,-0.192628f,0.762731f}, 139 | {-0.056136f,-0.201222f,0.763806f}, 140 | {-0.114589f,-0.166192f,0.770723f}, 141 | {-0.155145f,-0.129632f,0.791738f}, 142 | {-0.183611f,-0.058705f,0.847012f}, 143 | {-0.165562f,0.001980f,0.833386f}, 144 | {-0.220084f,0.019914f,0.768935f}, 145 | {-0.255730f,0.090306f,0.670782f}, 146 | {-0.255594f,0.113833f,0.663389f}, 147 | {-0.226380f,0.212655f,0.617740f}, 148 | {-0.003367f,-0.195342f,0.799680f}, 149 | {-0.029743f,-0.210508f,0.827180f}, 150 | {-0.003818f,-0.194783f,0.873636f}, 151 | {-0.004116f,-0.157907f,0.931268f}, 152 | {-0.031280f,-0.184555f,0.889476f}, 153 | {-0.059885f,-0.184448f,0.841330f}, 154 | {-0.135333f,-0.164332f,0.878200f}, 155 | {-0.085574f,-0.170948f,0.925547f}, 156 | {-0.163833f,-0.094170f,0.897114f}, 157 | {-0.138444f,-0.104250f,0.945975f}, 158 | {-0.083497f,-0.084934f,0.979607f}, 159 | {-0.004433f,-0.146642f,0.985872f}, 160 | {-0.150715f,0.032650f,0.884111f}, 161 | {-0.135892f,-0.035520f,0.945455f}, 162 | {-0.070612f,0.036849f,0.975733f}, 163 | {-0.004458f,-0.042526f,1.015670f}, 164 | {-0.004249f,0.046042f,1.003240f}, 165 | {-0.086969f,0.133224f,0.947633f}, 166 | {-0.003873f,0.161605f,0.970499f}, 167 | {-0.125544f,0.140012f,0.917678f}, 168 | {-0.125651f,0.250246f,0.857602f}, 169 | {-0.003127f,0.284070f,0.878870f}, 170 | {-0.159174f,0.125726f,0.888878f}, 171 | {-0.183807f,0.196970f,0.844480f}, 172 | {-0.159890f,0.291736f,0.732480f}, 173 | {-0.199495f,0.207230f,0.779864f}, 174 | {-0.206182f,0.164608f,0.693257f}, 175 | {-0.186315f,0.160689f,0.817193f}, 176 | {-0.192827f,0.166706f,0.782271f}, 177 | {-0.175112f,0.110008f,0.860621f}, 178 | {-0.161022f,0.057420f,0.855111f}, 179 | {-0.172319f,0.036155f,0.816189f}, 180 | {-0.190318f,0.064083f,0.760605f}, 181 | {-0.195072f,0.129179f,0.731104f}, 182 | {-0.203126f,0.410287f,0.680536f}, 183 | {-0.216677f,0.309274f,0.642272f}, 184 | {-0.241515f,0.311485f,0.587832f}, 185 | {-0.002209f,0.366663f,0.749413f}, 186 | {-0.088230f,0.396265f,0.678635f}, 187 | {-0.170147f,0.109517f,0.840784f}, 188 | {-0.160521f,0.067766f,0.830650f}, 189 | {-0.181546f,0.139805f,0.812146f}, 190 | {-0.180495f,0.148568f,0.776087f}, 191 | {-0.180255f,0.129125f,0.744192f}, 192 | {-0.186298f,0.078308f,0.769352f}, 193 | {-0.167622f,0.060539f,0.806675f}, 194 | {-0.189876f,0.102760f,0.802582f}, 195 | {-0.108340f,0.455446f,0.657174f}, 196 | {-0.241585f,0.527592f,0.669296f}, 197 | {-0.265676f,0.513366f,0.634594f}, 198 | {-0.203073f,0.478550f,0.581526f}, 199 | {-0.266772f,0.642330f,0.602061f}, 200 | {-0.216961f,0.564846f,0.535435f}, 201 | {-0.202210f,0.525495f,0.475944f}, 202 | {-0.193888f,0.467925f,0.520606f}, 203 | {-0.265837f,0.757267f,0.500933f}, 204 | {-0.240306f,0.653440f,0.463215f}, 205 | {-0.309239f,0.776868f,0.304726f}, 206 | {-0.271009f,0.683094f,0.382018f}, 207 | {-0.312111f,0.671099f,0.286687f}, 208 | {-0.268791f,0.624342f,0.377231f}, 209 | {-0.302457f,0.533996f,0.360289f}, 210 | {-0.263656f,0.529310f,0.412564f}, 211 | {-0.282311f,0.415167f,0.447666f}, 212 | {-0.239201f,0.442096f,0.495604f}, 213 | {-0.220043f,0.569026f,0.445877f}, 214 | {-0.001263f,0.395631f,0.602029f}, 215 | {-0.057345f,0.442535f,0.572224f}, 216 | {-0.088927f,0.506333f,0.529106f}, 217 | {-0.125738f,0.535076f,0.612913f}, 218 | {-0.126251f,0.577170f,0.483159f}, 219 | {-0.149594f,0.611520f,0.557731f}, 220 | {-0.163188f,0.660791f,0.491080f}, 221 | {-0.172482f,0.663387f,0.415416f}, 222 | {-0.160464f,0.591710f,0.370659f}, 223 | {-0.156445f,0.536396f,0.378302f}, 224 | {-0.136496f,0.444358f,0.425226f}, 225 | {-0.095564f,0.373768f,0.473659f}, 226 | {-0.104146f,0.315912f,0.498104f}, 227 | {-0.000496f,0.384194f,0.473817f}, 228 | {-0.000183f,0.297770f,0.401486f}, 229 | {-0.129042f,0.270145f,0.434495f}, 230 | {0.000100f,0.272963f,0.349138f}, 231 | {-0.113060f,0.236984f,0.385554f}, 232 | {0.007260f,0.016311f,-0.883396f}, 233 | {0.007865f,0.122104f,-0.956137f}, 234 | {-0.032842f,0.115282f,-0.953252f}, 235 | {-0.089115f,0.108449f,-0.950317f}, 236 | {-0.047440f,0.014729f,-0.882756f}, 237 | {-0.104458f,0.013137f,-0.882070f}, 238 | {-0.086439f,-0.584866f,-0.608343f}, 239 | {-0.115026f,-0.662605f,-0.436732f}, 240 | {-0.071683f,-0.665372f,-0.606385f}, 241 | {-0.257884f,-0.665381f,-0.658052f}, 242 | {-0.272542f,-0.665381f,-0.592063f}, 243 | {-0.371322f,-0.665382f,-0.353620f}, 244 | {-0.372362f,-0.665381f,-0.224420f}, 245 | {-0.335166f,-0.665380f,-0.078623f}, 246 | {-0.225999f,-0.665375f,-0.038981f}, 247 | {-0.106719f,-0.665374f,-0.186351f}, 248 | {-0.081749f,-0.665372f,-0.292554f}, 249 | {0.006943f,-0.091505f,-0.858354f}, 250 | {0.006117f,-0.280985f,-0.769967f}, 251 | {0.004495f,-0.502360f,-0.559799f}, 252 | {-0.198638f,-0.302135f,-0.845816f}, 253 | {-0.237395f,-0.542544f,-0.587188f}, 254 | {-0.270001f,-0.279489f,-0.669861f}, 255 | {-0.134547f,-0.119852f,-0.959004f}, 256 | {-0.052088f,-0.122463f,-0.944549f}, 257 | {-0.124463f,-0.293508f,-0.899566f}, 258 | {-0.047616f,-0.289643f,-0.879292f}, 259 | {-0.168595f,-0.529132f,-0.654931f}, 260 | {-0.099793f,-0.515719f,-0.645873f}, 261 | {-0.186168f,-0.605282f,-0.724690f}, 262 | {-0.112970f,-0.583097f,-0.707469f}, 263 | {-0.108152f,-0.665375f,-0.700408f}, 264 | {-0.183019f,-0.665378f,-0.717630f}, 265 | {-0.349529f,-0.334459f,-0.511985f}, 266 | {-0.141182f,-0.437705f,-0.798194f}, 267 | {-0.212670f,-0.448725f,-0.737447f}, 268 | {-0.261111f,-0.414945f,-0.613835f}, 269 | {-0.077364f,-0.431480f,-0.778113f}, 270 | {0.005174f,-0.425277f,-0.651592f}, 271 | {0.089236f,-0.431732f,-0.777093f}, 272 | {0.271006f,-0.415749f,-0.610577f}, 273 | {0.223981f,-0.449384f,-0.734774f}, 274 | {0.153275f,-0.438150f,-0.796391f}, 275 | {0.358414f,-0.335529f,-0.507649f}, 276 | {0.193434f,-0.665946f,-0.715325f}, 277 | {0.118363f,-0.665717f,-0.699021f}, 278 | {0.123515f,-0.583454f,-0.706020f}, 279 | {0.196851f,-0.605860f,-0.722345f}, 280 | {0.109788f,-0.516035f,-0.644590f}, 281 | {0.178656f,-0.529656f,-0.652804f}, 282 | {0.061157f,-0.289807f,-0.878626f}, 283 | {0.138234f,-0.293905f,-0.897958f}, 284 | {0.066933f,-0.122643f,-0.943820f}, 285 | {0.149571f,-0.120281f,-0.957264f}, 286 | {0.280989f,-0.280321f,-0.666487f}, 287 | {0.246581f,-0.543275f,-0.584224f}, 288 | {0.211720f,-0.302754f,-0.843303f}, 289 | {0.086966f,-0.665627f,-0.291520f}, 290 | {0.110634f,-0.665702f,-0.185021f}, 291 | {0.228099f,-0.666061f,-0.036201f}, 292 | {0.337743f,-0.666396f,-0.074503f}, 293 | {0.376722f,-0.666513f,-0.219833f}, 294 | {0.377265f,-0.666513f,-0.349036f}, 295 | {0.281411f,-0.666217f,-0.588670f}, 296 | {0.267564f,-0.666174f,-0.654834f}, 297 | {0.080745f,-0.665602f,-0.605452f}, 298 | {0.122016f,-0.662963f,-0.435280f}, 299 | {0.095767f,-0.585141f,-0.607228f}, 300 | {0.118944f,0.012799f,-0.880702f}, 301 | {0.061944f,0.014564f,-0.882086f}, 302 | {0.104725f,0.108156f,-0.949130f}, 303 | {0.048513f,0.115159f,-0.952753f}, 304 | {0.112696f,0.236643f,0.386937f}, 305 | {0.128177f,0.269757f,0.436071f}, 306 | {0.102643f,0.315600f,0.499370f}, 307 | {0.094535f,0.373481f,0.474824f}, 308 | {0.136270f,0.443946f,0.426895f}, 309 | {0.157071f,0.535923f,0.380222f}, 310 | {0.161350f,0.591224f,0.372630f}, 311 | {0.173035f,0.662865f,0.417531f}, 312 | {0.162808f,0.660299f,0.493077f}, 313 | {0.148250f,0.611070f,0.559555f}, 314 | {0.125719f,0.576790f,0.484702f}, 315 | {0.123489f,0.534699f,0.614440f}, 316 | {0.087621f,0.506066f,0.530188f}, 317 | {0.055321f,0.442365f,0.572915f}, 318 | {0.219936f,0.568361f,0.448571f}, 319 | {0.238099f,0.441375f,0.498528f}, 320 | {0.281711f,0.414315f,0.451121f}, 321 | {0.263833f,0.528513f,0.415794f}, 322 | {0.303284f,0.533081f,0.363998f}, 323 | {0.269687f,0.623528f,0.380528f}, 324 | {0.314255f,0.670153f,0.290524f}, 325 | {0.272023f,0.682273f,0.385343f}, 326 | {0.311480f,0.775931f,0.308527f}, 327 | {0.240239f,0.652714f,0.466159f}, 328 | {0.265619f,0.756464f,0.504187f}, 329 | {0.192562f,0.467341f,0.522972f}, 330 | {0.201605f,0.524885f,0.478417f}, 331 | {0.215743f,0.564193f,0.538084f}, 332 | {0.264969f,0.641527f,0.605317f}, 333 | {0.201031f,0.477940f,0.584002f}, 334 | {0.263086f,0.512567f,0.637832f}, 335 | {0.238615f,0.526867f,0.672237f}, 336 | {0.105309f,0.455123f,0.658482f}, 337 | {0.183993f,0.102195f,0.804872f}, 338 | {0.161563f,0.060042f,0.808692f}, 339 | {0.180748f,0.077754f,0.771600f}, 340 | {0.175168f,0.128588f,0.746368f}, 341 | {0.175075f,0.148030f,0.778264f}, 342 | {0.175658f,0.139265f,0.814333f}, 343 | {0.154191f,0.067291f,0.832578f}, 344 | {0.163818f,0.109013f,0.842830f}, 345 | {0.084760f,0.396004f,0.679695f}, 346 | {0.238888f,0.310760f,0.590775f}, 347 | {0.213380f,0.308625f,0.644905f}, 348 | {0.199666f,0.409678f,0.683003f}, 349 | {0.190143f,0.128597f,0.733463f}, 350 | {0.184833f,0.063516f,0.762902f}, 351 | {0.166070f,0.035644f,0.818261f}, 352 | {0.154361f,0.056943f,0.857042f}, 353 | {0.168542f,0.109489f,0.862725f}, 354 | {0.187387f,0.166131f,0.784599f}, 355 | {0.180428f,0.160135f,0.819438f}, 356 | {0.201823f,0.163991f,0.695756f}, 357 | {0.194206f,0.206635f,0.782275f}, 358 | {0.155438f,0.291260f,0.734412f}, 359 | {0.177696f,0.196424f,0.846693f}, 360 | {0.152305f,0.125256f,0.890786f}, 361 | {0.119546f,0.249876f,0.859104f}, 362 | {0.118369f,0.139643f,0.919173f}, 363 | {0.079410f,0.132973f,0.948652f}, 364 | {0.062419f,0.036648f,0.976547f}, 365 | {0.127847f,-0.035919f,0.947070f}, 366 | {0.143624f,0.032206f,0.885913f}, 367 | {0.074888f,-0.085173f,0.980577f}, 368 | {0.130184f,-0.104656f,0.947620f}, 369 | {0.156201f,-0.094653f,0.899074f}, 370 | {0.077366f,-0.171194f,0.926545f}, 371 | {0.127722f,-0.164729f,0.879810f}, 372 | {0.052670f,-0.184618f,0.842019f}, 373 | {0.023477f,-0.184638f,0.889811f}, 374 | {0.022626f,-0.210587f,0.827500f}, 375 | {0.223089f,0.211976f,0.620493f}, 376 | {0.251444f,0.113067f,0.666494f}, 377 | {0.251419f,0.089540f,0.673887f}, 378 | {0.214360f,0.019258f,0.771595f}, 379 | {0.158999f,0.001490f,0.835374f}, 380 | {0.176696f,-0.059249f,0.849218f}, 381 | {0.148696f,-0.130091f,0.793599f}, 382 | {0.108290f,-0.166528f,0.772088f}, 383 | {0.049820f,-0.201382f,0.764454f}, 384 | {0.071341f,-0.215195f,0.697209f}, 385 | {0.073148f,-0.214475f,0.623510f}, 386 | {0.140502f,-0.169461f,0.699354f}, 387 | {0.163374f,-0.157073f,0.611416f}, 388 | {0.189466f,-0.138550f,0.730366f}, 389 | {0.247593f,-0.082554f,0.759610f}, 390 | {0.227468f,-0.121982f,0.590197f}, 391 | {0.284702f,-0.006586f,0.535347f}, 392 | {0.275741f,0.125287f,0.446676f}, 393 | {0.266650f,0.192594f,0.506044f}, 394 | {0.300086f,0.053287f,0.629620f}, 395 | {0.055450f,-0.663935f,0.375065f}, 396 | {0.122854f,-0.664138f,0.482323f}, 397 | {0.046520f,-0.531571f,0.391918f}, 398 | {0.024824f,-0.568450f,0.275106f}, 399 | {0.053855f,-0.663931f,0.328224f}, 400 | {0.112829f,-0.453549f,0.305788f}, 401 | {0.131265f,-0.510617f,0.080746f}, 402 | {0.061174f,-0.430716f,-0.042710f}, 403 | {0.341019f,-0.532887f,-0.208150f}, 404 | {0.347705f,-0.623533f,-0.081139f}, 405 | {0.238040f,-0.610732f,-0.038037f}, 406 | {0.211764f,-0.514274f,-0.132078f}, 407 | {0.120605f,-0.600219f,-0.186856f}, 408 | {0.096985f,-0.584476f,-0.293357f}, 409 | {0.127621f,-0.581941f,-0.437170f}, 410 | {0.165902f,-0.477425f,-0.291453f}, 411 | {0.077720f,-0.417975f,-0.220519f}, 412 | {0.320892f,-0.506363f,-0.320874f}, 413 | {0.248214f,-0.465684f,-0.239842f}, 414 | {0.118764f,-0.383338f,-0.187114f}, 415 | {0.118816f,-0.430106f,-0.123307f}, 416 | {0.094131f,-0.419464f,-0.044777f}, 417 | {0.274526f,-0.261706f,0.005110f}, 418 | {0.259842f,-0.283292f,-0.003185f}, 419 | {0.222861f,-0.340431f,-0.038210f}, 420 | {0.204445f,-0.664380f,0.513353f}, 421 | {0.259286f,-0.664547f,0.471281f}, 422 | {0.185402f,-0.476020f,0.421718f}, 423 | {0.279163f,-0.664604f,0.417328f}, 424 | {0.277157f,-0.528122f,0.400208f}, 425 | {0.183069f,-0.509812f,0.329995f}, 426 | {0.282599f,-0.429210f,0.059242f}, 427 | {0.254816f,-0.664541f,0.290687f}, 428 | {0.271436f,-0.567707f,0.263966f}, 429 | {0.386561f,-0.625221f,-0.216870f}, 430 | {0.387086f,-0.630883f,-0.346073f}, 431 | {0.380021f,-0.596021f,-0.318679f}, 432 | {0.291269f,-0.619007f,-0.585707f}, 433 | {0.339280f,-0.571198f,-0.461946f}, 434 | {0.400045f,-0.489778f,-0.422640f}, 435 | {0.406817f,-0.314349f,-0.371230f}, 436 | {0.300588f,-0.281718f,-0.170549f}, 437 | {0.290866f,-0.277304f,-0.061905f}, 438 | {0.187735f,-0.241545f,0.509437f}, 439 | {0.188032f,-0.287569f,0.424234f}, 440 | {0.227520f,-0.373262f,0.293102f}, 441 | {0.266526f,-0.273650f,0.039597f}, 442 | {0.291592f,-0.291676f,0.111386f}, 443 | {0.291914f,-0.122741f,0.422683f}, 444 | {0.297574f,-0.156119f,0.373368f}, 445 | {0.286603f,-0.232731f,0.027162f}, 446 | {0.364663f,-0.201399f,0.206850f}, 447 | {0.353855f,-0.132408f,0.149228f}, 448 | {0.282208f,-0.019715f,0.314960f}, 449 | {0.331187f,-0.099266f,0.092701f}, 450 | {0.375463f,-0.093120f,-0.006467f}, 451 | {0.375917f,-0.101236f,-0.154882f}, 452 | {0.466635f,-0.094416f,-0.305669f}, 453 | {0.455805f,-0.119881f,-0.460632f}, 454 | {0.277465f,-0.604242f,-0.651871f}, 455 | {0.261022f,-0.551176f,-0.554667f}, 456 | {0.093627f,0.258494f,-0.920589f}, 457 | {0.114248f,0.310608f,-0.798070f}, 458 | {0.144232f,0.211434f,-0.835001f}, 459 | {0.119916f,0.176940f,-0.951159f}, 460 | {0.184061f,0.101854f,-0.918220f}, 461 | {0.092431f,0.276521f,-0.738231f}, 462 | {0.133504f,0.218403f,-0.758602f}, 463 | {0.194987f,0.097655f,-0.812476f}, 464 | {0.185542f,0.011005f,-0.879202f}, 465 | {0.230315f,-0.127450f,-0.884202f}, 466 | {0.260471f,0.255056f,-0.624378f}, 467 | {0.351567f,-0.042194f,-0.663976f}, 468 | {0.253742f,0.323524f,-0.433716f}, 469 | {0.411612f,0.132299f,-0.438264f}, 470 | {0.270513f,0.356530f,-0.289984f}, 471 | {0.422146f,0.162819f,-0.273130f}, 472 | {0.164724f,0.237490f,0.208912f}, 473 | {0.253806f,0.092900f,0.240640f}, 474 | {0.203608f,0.284597f,0.096223f}, 475 | {0.241006f,0.343093f,-0.171396f}, 476 | {0.356076f,0.149288f,-0.143443f}, 477 | {0.337656f,0.131992f,0.066374f} 478 | }; 479 | int rabbit_triangles[RABBIT_TRIANGLE_NUM][3]={ 480 | {126,134,133}, 481 | {342,138,134}, 482 | {133,134,138}, 483 | {126,342,134}, 484 | {312,316,317}, 485 | {169,163,162}, 486 | {312,317,319}, 487 | {312,319,318}, 488 | {169,162,164}, 489 | {169,168,163}, 490 | {312,314,315}, 491 | {169,164,165}, 492 | {169,167,168}, 493 | {312,315,316}, 494 | {312,313,314}, 495 | {169,165,166}, 496 | {169,166,167}, 497 | {312,318,313}, 498 | {308,304,305}, 499 | {308,305,306}, 500 | {179,181,188}, 501 | {177,173,175}, 502 | {177,175,176}, 503 | {302,293,300}, 504 | {322,294,304}, 505 | {188,176,175}, 506 | {188,175,179}, 507 | {158,177,187}, 508 | {305,293,302}, 509 | {305,302,306}, 510 | {322,304,308}, 511 | {188,181,183}, 512 | {158,173,177}, 513 | {293,298,300}, 514 | {304,294,296}, 515 | {304,296,305}, 516 | {185,176,188}, 517 | {185,188,183}, 518 | {187,177,176}, 519 | {187,176,185}, 520 | {305,296,298}, 521 | {305,298,293}, 522 | {436,432, 28}, 523 | {436, 28, 23}, 524 | {434,278,431}, 525 | { 30,208,209}, 526 | { 30,209, 29}, 527 | { 19, 20, 24}, 528 | {208,207,211}, 529 | {208,211,209}, 530 | { 19,210,212}, 531 | {433,434,431}, 532 | {433,431,432}, 533 | {433,432,436}, 534 | {436,437,433}, 535 | {277,275,276}, 536 | {277,276,278}, 537 | {209,210, 25}, 538 | { 21, 26, 24}, 539 | { 21, 24, 20}, 540 | { 25, 26, 27}, 541 | { 25, 27, 29}, 542 | {435,439,277}, 543 | {439,275,277}, 544 | {432,431, 30}, 545 | {432, 30, 28}, 546 | {433,437,438}, 547 | {433,438,435}, 548 | {434,277,278}, 549 | { 24, 25,210}, 550 | { 24, 26, 25}, 551 | { 29, 27, 28}, 552 | { 29, 28, 30}, 553 | { 19, 24,210}, 554 | {208, 30,431}, 555 | {208,431,278}, 556 | {435,434,433}, 557 | {435,277,434}, 558 | { 25, 29,209}, 559 | { 27, 22, 23}, 560 | { 27, 23, 28}, 561 | { 26, 22, 27}, 562 | { 26, 21, 22}, 563 | {212,210,209}, 564 | {212,209,211}, 565 | {207,208,278}, 566 | {207,278,276}, 567 | {439,435,438}, 568 | { 12, 9, 10}, 569 | { 12, 10, 13}, 570 | { 2, 3, 5}, 571 | { 2, 5, 4}, 572 | { 16, 13, 14}, 573 | { 16, 14, 17}, 574 | { 22, 21, 16}, 575 | { 13, 10, 11}, 576 | { 13, 11, 14}, 577 | { 1, 0, 3}, 578 | { 1, 3, 2}, 579 | { 15, 12, 16}, 580 | { 19, 18, 15}, 581 | { 19, 15, 16}, 582 | { 19, 16, 20}, 583 | { 9, 1, 2}, 584 | { 9, 2, 10}, 585 | { 3, 7, 8}, 586 | { 3, 8, 5}, 587 | { 16, 17, 23}, 588 | { 16, 23, 22}, 589 | { 21, 20, 16}, 590 | { 10, 2, 4}, 591 | { 10, 4, 11}, 592 | { 0, 6, 7}, 593 | { 0, 7, 3}, 594 | { 12, 13, 16}, 595 | {451,446,445}, 596 | {451,445,450}, 597 | {442,440,439}, 598 | {442,439,438}, 599 | {442,438,441}, 600 | {421,420,422}, 601 | {412,411,426}, 602 | {412,426,425}, 603 | {408,405,407}, 604 | {413, 67, 68}, 605 | {413, 68,414}, 606 | {391,390,412}, 607 | { 80,384,386}, 608 | {404,406,378}, 609 | {390,391,377}, 610 | {390,377, 88}, 611 | {400,415,375}, 612 | {398,396,395}, 613 | {398,395,371}, 614 | {398,371,370}, 615 | {112,359,358}, 616 | {112,358,113}, 617 | {351,352,369}, 618 | {125,349,348}, 619 | {345,343,342}, 620 | {342,340,339}, 621 | {341,335,337}, 622 | {328,341,327}, 623 | {331,323,333}, 624 | {331,322,323}, 625 | {327,318,319}, 626 | {327,319,328}, 627 | {315,314,324}, 628 | {302,300,301}, 629 | {302,301,303}, 630 | {320,311,292}, 631 | {285,284,289}, 632 | {310,307,288}, 633 | {310,288,290}, 634 | {321,350,281}, 635 | {321,281,282}, 636 | {423,448,367}, 637 | {272,273,384}, 638 | {272,384,274}, 639 | {264,265,382}, 640 | {264,382,383}, 641 | {440,442,261}, 642 | {440,261,263}, 643 | {252,253,254}, 644 | {252,254,251}, 645 | {262,256,249}, 646 | {262,249,248}, 647 | {228,243,242}, 648 | {228, 31,243}, 649 | {213,215,238}, 650 | {213,238,237}, 651 | { 19,212,230}, 652 | {224,225,233}, 653 | {224,233,231}, 654 | {217,218, 56}, 655 | {217, 56, 54}, 656 | {217,216,239}, 657 | {217,239,238}, 658 | {217,238,215}, 659 | {218,217,215}, 660 | {218,215,214}, 661 | { 6,102,206}, 662 | {186,199,200}, 663 | {197,182,180}, 664 | {170,171,157}, 665 | {201,200,189}, 666 | {170,190,191}, 667 | {170,191,192}, 668 | {175,174,178}, 669 | {175,178,179}, 670 | {168,167,155}, 671 | {122,149,158}, 672 | {122,158,159}, 673 | {135,153,154}, 674 | {135,154,118}, 675 | {143,140,141}, 676 | {143,141,144}, 677 | {132,133,136}, 678 | {130,126,133}, 679 | {124,125,127}, 680 | {122,101,100}, 681 | {122,100,121}, 682 | {110,108,107}, 683 | {110,107,109}, 684 | { 98, 99, 97}, 685 | { 98, 97, 64}, 686 | { 98, 64, 66}, 687 | { 87, 55, 57}, 688 | { 83, 82, 79}, 689 | { 83, 79, 84}, 690 | { 78, 74, 50}, 691 | { 49, 71, 41}, 692 | { 49, 41, 37}, 693 | { 49, 37, 36}, 694 | { 58, 44, 60}, 695 | { 60, 59, 58}, 696 | { 51, 34, 33}, 697 | { 39, 40, 42}, 698 | { 39, 42, 38}, 699 | {243,240, 33}, 700 | {243, 33,229}, 701 | { 39, 38, 6}, 702 | { 44, 46, 40}, 703 | { 55, 56, 57}, 704 | { 64, 62, 65}, 705 | { 64, 65, 66}, 706 | { 41, 71, 45}, 707 | { 75, 50, 51}, 708 | { 81, 79, 82}, 709 | { 77, 88, 73}, 710 | { 93, 92, 94}, 711 | { 68, 47, 46}, 712 | { 96, 97, 99}, 713 | { 96, 99, 95}, 714 | {110,109,111}, 715 | {111,112,110}, 716 | {114,113,123}, 717 | {114,123,124}, 718 | {132,131,129}, 719 | {133,137,136}, 720 | {135,142,145}, 721 | {145,152,135}, 722 | {149,147,157}, 723 | {157,158,149}, 724 | {164,150,151}, 725 | {153,163,168}, 726 | {153,168,154}, 727 | {185,183,182}, 728 | {185,182,184}, 729 | {161,189,190}, 730 | {200,199,191}, 731 | {200,191,190}, 732 | {180,178,195}, 733 | {180,195,196}, 734 | {102,101,204}, 735 | {102,204,206}, 736 | { 43, 48,104}, 737 | { 43,104,103}, 738 | {216,217, 54}, 739 | {216, 54, 32}, 740 | {207,224,231}, 741 | {230,212,211}, 742 | {230,211,231}, 743 | {227,232,241}, 744 | {227,241,242}, 745 | {235,234,241}, 746 | {235,241,244}, 747 | {430,248,247}, 748 | {272,274,253}, 749 | {272,253,252}, 750 | {439,260,275}, 751 | {225,224,259}, 752 | {225,259,257}, 753 | {269,270,407}, 754 | {269,407,405}, 755 | {270,269,273}, 756 | {270,273,272}, 757 | {273,269,268}, 758 | {273,268,267}, 759 | {273,267,266}, 760 | {273,266,265}, 761 | {273,265,264}, 762 | {448,279,367}, 763 | {281,350,368}, 764 | {285,286,301}, 765 | {290,323,310}, 766 | {290,311,323}, 767 | {282,281,189}, 768 | {292,311,290}, 769 | {292,290,291}, 770 | {307,306,302}, 771 | {307,302,303}, 772 | {316,315,324}, 773 | {316,324,329}, 774 | {331,351,350}, 775 | {330,334,335}, 776 | {330,335,328}, 777 | {341,337,338}, 778 | {344,355,354}, 779 | {346,345,348}, 780 | {346,348,347}, 781 | {364,369,352}, 782 | {364,352,353}, 783 | {365,363,361}, 784 | {365,361,362}, 785 | {376,401,402}, 786 | {373,372,397}, 787 | {373,397,400}, 788 | {376, 92,377}, 789 | {381,378,387}, 790 | {381,387,385}, 791 | {386, 77, 80}, 792 | {390,389,412}, 793 | {416,417,401}, 794 | {403,417,415}, 795 | {408,429,430}, 796 | {419,423,418}, 797 | {427,428,444}, 798 | {427,444,446}, 799 | {437,436,441}, 800 | {450,445, 11}, 801 | {450, 11, 4}, 802 | {447,449, 5}, 803 | {447, 5, 8}, 804 | {441,438,437}, 805 | {425,426,451}, 806 | {425,451,452}, 807 | {417,421,415}, 808 | {408,407,429}, 809 | {399,403,400}, 810 | {399,400,397}, 811 | {394,393,416}, 812 | {389,411,412}, 813 | {386,383,385}, 814 | {408,387,378}, 815 | {408,378,406}, 816 | {377,391,376}, 817 | { 94,375,415}, 818 | {372,373,374}, 819 | {372,374,370}, 820 | {359,111,360}, 821 | {359,112,111}, 822 | {113,358,349}, 823 | {113,349,123}, 824 | {346,343,345}, 825 | {343,340,342}, 826 | {338,336,144}, 827 | {338,144,141}, 828 | {327,341,354}, 829 | {327,354,326}, 830 | {331,350,321}, 831 | {331,321,322}, 832 | {314,313,326}, 833 | {314,326,325}, 834 | {300,298,299}, 835 | {300,299,301}, 836 | {288,287,289}, 837 | {189,292,282}, 838 | {287,288,303}, 839 | {284,285,297}, 840 | {368,280,281}, 841 | {448,447,279}, 842 | {274,226,255}, 843 | {267,268,404}, 844 | {267,404,379}, 845 | {429,262,430}, 846 | {439,440,260}, 847 | {257,258,249}, 848 | {257,249,246}, 849 | {430,262,248}, 850 | {234,228,242}, 851 | {234,242,241}, 852 | {237,238,239}, 853 | {237,239,236}, 854 | { 15, 18,227}, 855 | { 15,227,229}, 856 | {222,223, 82}, 857 | {222, 82, 83}, 858 | {214,215,213}, 859 | {214,213, 81}, 860 | { 38,102, 6}, 861 | {122,159,200}, 862 | {122,200,201}, 863 | {174,171,192}, 864 | {174,192,194}, 865 | {197,193,198}, 866 | {190,170,161}, 867 | {181,179,178}, 868 | {181,178,180}, 869 | {166,156,155}, 870 | {163,153,152}, 871 | {163,152,162}, 872 | {120,156,149}, 873 | {120,149,121}, 874 | {152,153,135}, 875 | {140,143,142}, 876 | {135,131,132}, 877 | {135,132,136}, 878 | {130,129,128}, 879 | {130,128,127}, 880 | {100,105,119}, 881 | {100,119,120}, 882 | {106,104,107}, 883 | {106,107,108}, 884 | { 91, 95, 59}, 885 | { 93, 94, 68}, 886 | { 91, 89, 92}, 887 | { 76, 53, 55}, 888 | { 76, 55, 87}, 889 | { 81, 78, 79}, 890 | { 74, 73, 49}, 891 | { 69, 60, 45}, 892 | { 58, 62, 64}, 893 | { 58, 64, 61}, 894 | { 53, 31, 32}, 895 | { 32, 54, 53}, 896 | { 42, 43, 38}, 897 | { 35, 36, 0}, 898 | { 35, 0, 1}, 899 | { 34, 35, 1}, 900 | { 34, 1, 9}, 901 | { 44, 40, 41}, 902 | { 44, 41, 45}, 903 | { 33,240, 51}, 904 | { 63, 62, 58}, 905 | { 63, 58, 59}, 906 | { 45, 71, 70}, 907 | { 76, 75, 51}, 908 | { 76, 51, 52}, 909 | { 86, 85, 84}, 910 | { 86, 84, 87}, 911 | { 89, 72, 73}, 912 | { 89, 73, 88}, 913 | { 91, 92, 96}, 914 | { 91, 96, 95}, 915 | { 72, 91, 60}, 916 | { 72, 60, 69}, 917 | {104,106,105}, 918 | {119,105,117}, 919 | {119,117,118}, 920 | {124,127,128}, 921 | {117,116,129}, 922 | {117,129,131}, 923 | {118,117,131}, 924 | {135,140,142}, 925 | {146,150,152}, 926 | {146,152,145}, 927 | {149,122,121}, 928 | {166,165,151}, 929 | {166,151,156}, 930 | {158,172,173}, 931 | {161,160,189}, 932 | {199,198,193}, 933 | {199,193,191}, 934 | {204,201,202}, 935 | {178,174,194}, 936 | {200,159,186}, 937 | {109, 48, 67}, 938 | { 48,107,104}, 939 | {216, 32,236}, 940 | {216,236,239}, 941 | {223,214, 81}, 942 | {223, 81, 82}, 943 | { 33, 12, 15}, 944 | { 32,228,234}, 945 | { 32,234,236}, 946 | {240, 31, 52}, 947 | {256,255,246}, 948 | {256,246,249}, 949 | {258,263,248}, 950 | {258,248,249}, 951 | {275,260,259}, 952 | {275,259,276}, 953 | {207,276,259}, 954 | {270,271,429}, 955 | {270,429,407}, 956 | {413,418,366}, 957 | {413,366,365}, 958 | {368,367,279}, 959 | {368,279,280}, 960 | {303,301,286}, 961 | {303,286,287}, 962 | {283,282,292}, 963 | {283,292,291}, 964 | {320,292,189}, 965 | {298,296,297}, 966 | {298,297,299}, 967 | {318,327,326}, 968 | {318,326,313}, 969 | {329,330,317}, 970 | {336,333,320}, 971 | {326,354,353}, 972 | {334,332,333}, 973 | {334,333,336}, 974 | {342,339,139}, 975 | {342,139,138}, 976 | {345,342,126}, 977 | {347,357,356}, 978 | {369,368,351}, 979 | {363,356,357}, 980 | {363,357,361}, 981 | {366,367,368}, 982 | {366,368,369}, 983 | {375,373,400}, 984 | { 92, 90,377}, 985 | {409,387,408}, 986 | {386,385,387}, 987 | {386,387,388}, 988 | {412,394,391}, 989 | {396,398,399}, 990 | {408,406,405}, 991 | {415,421,419}, 992 | {415,419,414}, 993 | {425,452,448}, 994 | {425,448,424}, 995 | {444,441,443}, 996 | {448,452,449}, 997 | {448,449,447}, 998 | {446,444,443}, 999 | {446,443,445}, 1000 | {250,247,261}, 1001 | {250,261,428}, 1002 | {421,422,423}, 1003 | {421,423,419}, 1004 | {427,410,250}, 1005 | {417,403,401}, 1006 | {403,402,401}, 1007 | {420,392,412}, 1008 | {420,412,425}, 1009 | {420,425,424}, 1010 | {386,411,389}, 1011 | {383,382,381}, 1012 | {383,381,385}, 1013 | {378,379,404}, 1014 | {372,371,395}, 1015 | {372,395,397}, 1016 | {371,372,370}, 1017 | {361,359,360}, 1018 | {361,360,362}, 1019 | {368,350,351}, 1020 | {349,347,348}, 1021 | {356,355,344}, 1022 | {356,344,346}, 1023 | {344,341,340}, 1024 | {344,340,343}, 1025 | {338,337,336}, 1026 | {328,335,341}, 1027 | {324,352,351}, 1028 | {324,351,331}, 1029 | {320,144,336}, 1030 | {314,325,324}, 1031 | {322,308,309}, 1032 | {310,309,307}, 1033 | {287,286,289}, 1034 | {203,280,279}, 1035 | {203,279,205}, 1036 | {297,295,283}, 1037 | {297,283,284}, 1038 | {447,205,279}, 1039 | {274,384, 80}, 1040 | {274, 80,226}, 1041 | {266,267,379}, 1042 | {266,379,380}, 1043 | {225,257,246}, 1044 | {225,246,245}, 1045 | {256,254,253}, 1046 | {256,253,255}, 1047 | {430,247,250}, 1048 | {226,235,244}, 1049 | {226,244,245}, 1050 | {232,233,244}, 1051 | {232,244,241}, 1052 | {230, 18, 19}, 1053 | { 32, 31,228}, 1054 | {219,220, 86}, 1055 | {219, 86, 57}, 1056 | {226,213,235}, 1057 | {206, 7, 6}, 1058 | {122,201,101}, 1059 | {201,204,101}, 1060 | {180,196,197}, 1061 | {170,192,171}, 1062 | {200,190,189}, 1063 | {194,193,195}, 1064 | {183,181,180}, 1065 | {183,180,182}, 1066 | {155,154,168}, 1067 | {149,156,151}, 1068 | {149,151,148}, 1069 | {155,156,120}, 1070 | {145,142,143}, 1071 | {145,143,146}, 1072 | {136,137,140}, 1073 | {133,132,130}, 1074 | {128,129,116}, 1075 | {100,120,121}, 1076 | {110,112,113}, 1077 | {110,113,114}, 1078 | { 66, 65, 63}, 1079 | { 66, 63, 99}, 1080 | { 66, 99, 98}, 1081 | { 96, 46, 61}, 1082 | { 89, 88, 90}, 1083 | { 86, 87, 57}, 1084 | { 80, 78, 81}, 1085 | { 72, 69, 49}, 1086 | { 67, 48, 47}, 1087 | { 67, 47, 68}, 1088 | { 56, 55, 53}, 1089 | { 50, 49, 36}, 1090 | { 50, 36, 35}, 1091 | { 40, 39, 41}, 1092 | {242,243,229}, 1093 | {242,229,227}, 1094 | { 6, 37, 39}, 1095 | { 42, 47, 48}, 1096 | { 42, 48, 43}, 1097 | { 61, 46, 44}, 1098 | { 45, 70, 69}, 1099 | { 69, 70, 71}, 1100 | { 69, 71, 49}, 1101 | { 74, 78, 77}, 1102 | { 83, 84, 85}, 1103 | { 73, 74, 77}, 1104 | { 93, 96, 92}, 1105 | { 68, 46, 93}, 1106 | { 95, 99, 63}, 1107 | { 95, 63, 59}, 1108 | {115,108,110}, 1109 | {115,110,114}, 1110 | {125,126,127}, 1111 | {129,130,132}, 1112 | {137,133,138}, 1113 | {137,138,139}, 1114 | {148,146,143}, 1115 | {148,143,147}, 1116 | {119,118,154}, 1117 | {161,147,143}, 1118 | {165,164,151}, 1119 | {158,157,171}, 1120 | {158,171,172}, 1121 | {159,158,187}, 1122 | {159,187,186}, 1123 | {194,192,191}, 1124 | {194,191,193}, 1125 | {189,202,201}, 1126 | {182,197,184}, 1127 | {205, 8, 7}, 1128 | { 48,109,107}, 1129 | {218,219, 57}, 1130 | {218, 57, 56}, 1131 | {207,231,211}, 1132 | {232,230,231}, 1133 | {232,231,233}, 1134 | { 53, 52, 31}, 1135 | {388,411,386}, 1136 | {409,430,250}, 1137 | {262,429,254}, 1138 | {262,254,256}, 1139 | {442,444,428}, 1140 | {273,264,383}, 1141 | {273,383,384}, 1142 | {429,271,251}, 1143 | {429,251,254}, 1144 | {413,365,362}, 1145 | { 67,413,360}, 1146 | {282,283,295}, 1147 | {285,301,299}, 1148 | {202,281,280}, 1149 | {284,283,291}, 1150 | {284,291,289}, 1151 | {320,189,160}, 1152 | {308,306,307}, 1153 | {307,309,308}, 1154 | {319,317,330}, 1155 | {319,330,328}, 1156 | {353,352,324}, 1157 | {332,331,333}, 1158 | {340,341,338}, 1159 | {354,341,344}, 1160 | {349,358,357}, 1161 | {349,357,347}, 1162 | {364,355,356}, 1163 | {364,356,363}, 1164 | {364,365,366}, 1165 | {364,366,369}, 1166 | {374,376,402}, 1167 | {375, 92,373}, 1168 | { 77,389,390}, 1169 | {382,380,381}, 1170 | {389, 77,386}, 1171 | {393,394,412}, 1172 | {393,412,392}, 1173 | {401,394,416}, 1174 | {415,400,403}, 1175 | {411,410,427}, 1176 | {411,427,426}, 1177 | {422,420,424}, 1178 | {247,248,263}, 1179 | {247,263,261}, 1180 | {445,443, 14}, 1181 | {445, 14, 11}, 1182 | {449,450, 4}, 1183 | {449, 4, 5}, 1184 | {443,441, 17}, 1185 | {443, 17, 14}, 1186 | {436, 23, 17}, 1187 | {436, 17,441}, 1188 | {424,448,422}, 1189 | {448,423,422}, 1190 | {414,419,418}, 1191 | {414,418,413}, 1192 | {406,404,405}, 1193 | {399,397,395}, 1194 | {399,395,396}, 1195 | {420,416,392}, 1196 | {388,410,411}, 1197 | {386,384,383}, 1198 | {390, 88, 77}, 1199 | {375, 94, 92}, 1200 | {415,414, 68}, 1201 | {415, 68, 94}, 1202 | {370,374,402}, 1203 | {370,402,398}, 1204 | {361,357,358}, 1205 | {361,358,359}, 1206 | {125,348,126}, 1207 | {346,344,343}, 1208 | {340,338,339}, 1209 | {337,335,334}, 1210 | {337,334,336}, 1211 | {325,353,324}, 1212 | {324,331,332}, 1213 | {324,332,329}, 1214 | {323,322,309}, 1215 | {323,309,310}, 1216 | {294,295,297}, 1217 | {294,297,296}, 1218 | {289,286,285}, 1219 | {202,280,203}, 1220 | {288,307,303}, 1221 | {282,295,321}, 1222 | { 67,360,111}, 1223 | {418,423,367}, 1224 | {418,367,366}, 1225 | {272,252,251}, 1226 | {272,251,271}, 1227 | {272,271,270}, 1228 | {255,253,274}, 1229 | {265,266,380}, 1230 | {265,380,382}, 1231 | {442,428,261}, 1232 | {440,263,258}, 1233 | {440,258,260}, 1234 | {409,250,410}, 1235 | {255,226,245}, 1236 | {255,245,246}, 1237 | { 31,240,243}, 1238 | {236,234,235}, 1239 | {236,235,237}, 1240 | {233,225,245}, 1241 | {233,245,244}, 1242 | {220,221, 85}, 1243 | {220, 85, 86}, 1244 | { 81,213,226}, 1245 | { 81,226, 80}, 1246 | { 7,206,205}, 1247 | {186,184,198}, 1248 | {186,198,199}, 1249 | {204,203,205}, 1250 | {204,205,206}, 1251 | {195,193,196}, 1252 | {171,174,172}, 1253 | {173,174,175}, 1254 | {173,172,174}, 1255 | {155,167,166}, 1256 | {160,161,143}, 1257 | {160,143,144}, 1258 | {119,154,155}, 1259 | {148,151,150}, 1260 | {148,150,146}, 1261 | {140,137,139}, 1262 | {140,139,141}, 1263 | {127,126,130}, 1264 | {114,124,128}, 1265 | {114,128,115}, 1266 | {117,105,106}, 1267 | {117,106,116}, 1268 | {104,105,100}, 1269 | {104,100,103}, 1270 | { 59, 60, 91}, 1271 | { 97, 96, 61}, 1272 | { 97, 61, 64}, 1273 | { 91, 72, 89}, 1274 | { 87, 84, 79}, 1275 | { 87, 79, 76}, 1276 | { 78, 80, 77}, 1277 | { 49, 50, 74}, 1278 | { 60, 44, 45}, 1279 | { 61, 44, 58}, 1280 | { 51, 50, 35}, 1281 | { 51, 35, 34}, 1282 | { 39, 37, 41}, 1283 | { 33, 34, 9}, 1284 | { 33, 9, 12}, 1285 | { 0, 36, 37}, 1286 | { 0, 37, 6}, 1287 | { 40, 46, 47}, 1288 | { 40, 47, 42}, 1289 | { 53, 54, 56}, 1290 | { 65, 62, 63}, 1291 | { 72, 49, 73}, 1292 | { 79, 78, 75}, 1293 | { 79, 75, 76}, 1294 | { 52, 53, 76}, 1295 | { 92, 89, 90}, 1296 | { 96, 93, 46}, 1297 | {102,103,100}, 1298 | {102,100,101}, 1299 | {116,106,108}, 1300 | {116,108,115}, 1301 | {123,125,124}, 1302 | {116,115,128}, 1303 | {118,131,135}, 1304 | {140,135,136}, 1305 | {148,147,149}, 1306 | {120,119,155}, 1307 | {164,162,152}, 1308 | {164,152,150}, 1309 | {157,147,161}, 1310 | {157,161,170}, 1311 | {186,187,185}, 1312 | {186,185,184}, 1313 | {193,197,196}, 1314 | {202,203,204}, 1315 | {194,195,178}, 1316 | {198,184,197}, 1317 | { 67,111,109}, 1318 | { 38, 43,103}, 1319 | { 38,103,102}, 1320 | {214,223,222}, 1321 | {214,222,221}, 1322 | {214,221,220}, 1323 | {214,220,219}, 1324 | {214,219,218}, 1325 | {213,237,235}, 1326 | {221,222, 83}, 1327 | {221, 83, 85}, 1328 | { 15,229, 33}, 1329 | {227, 18,230}, 1330 | {227,230,232}, 1331 | { 52, 51,240}, 1332 | { 75, 78, 50}, 1333 | {408,430,409}, 1334 | {260,258,257}, 1335 | {260,257,259}, 1336 | {224,207,259}, 1337 | {268,269,405}, 1338 | {268,405,404}, 1339 | {413,362,360}, 1340 | {447, 8,205}, 1341 | {299,297,285}, 1342 | {189,281,202}, 1343 | {290,288,289}, 1344 | {290,289,291}, 1345 | {322,321,295}, 1346 | {322,295,294}, 1347 | {333,323,311}, 1348 | {333,311,320}, 1349 | {317,316,329}, 1350 | {320,160,144}, 1351 | {353,325,326}, 1352 | {329,332,334}, 1353 | {329,334,330}, 1354 | {339,338,141}, 1355 | {339,141,139}, 1356 | {348,345,126}, 1357 | {347,356,346}, 1358 | {123,349,125}, 1359 | {364,353,354}, 1360 | {364,354,355}, 1361 | {365,364,363}, 1362 | {376,391,394}, 1363 | {376,394,401}, 1364 | { 92,376,374}, 1365 | { 92,374,373}, 1366 | {377, 90, 88}, 1367 | {380,379,378}, 1368 | {380,378,381}, 1369 | {388,387,409}, 1370 | {388,409,410}, 1371 | {416,393,392}, 1372 | {399,398,402}, 1373 | {399,402,403}, 1374 | {250,428,427}, 1375 | {421,417,416}, 1376 | {421,416,420}, 1377 | {426,427,446}, 1378 | {426,446,451}, 1379 | {444,442,441}, 1380 | {452,451,450}, 1381 | {452,450,449} 1382 | }; 1383 | -------------------------------------------------------------------------------- /rabdata.h: -------------------------------------------------------------------------------- 1 | /* Copyright 1996, Viewpoint Datalabs Int'l, www.viewpoint.com, 1-800-DATASET */ 2 | /* 3 | # Usage Rights: You (the user) may use this model to help build cool personal 4 | # vrml worlds, but please give us credit when you do ("3D model provided by 5 | # Viewpoint Datalabs, www,viewpoint.com"). Please don't sell it or use it to 6 | # make money indirectly. Don't redistribute it or put it on a web site except 7 | # as a part of your personal, non-commerical vrml world. If you want to do a 8 | # commercial project, give us a call at 1-800-DATASET or visit www.viewpoint.com 9 | # and we'll help you obtain the rights to do so. 10 | */ 11 | 12 | /* 13 | * Note that this data was put directly into the program 14 | * to provide a demo program on the net that people could 15 | * just run without having to fetch datafiles. 16 | * i.e. more convienent for the user this way 17 | */ 18 | 19 | 20 | #ifndef RABBIT_DATA_H 21 | #define RABBIT_DATA_H 22 | 23 | #define RABBIT_VERTEX_NUM (453) 24 | #define RABBIT_TRIANGLE_NUM (902) 25 | 26 | extern float rabbit_vertices[RABBIT_VERTEX_NUM][3]; 27 | extern int rabbit_triangles[RABBIT_TRIANGLE_NUM][3]; 28 | 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /winmain.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Polygon Reduction Demo by Stan Melax (c) 1998 4 | * Permission to use any of this code wherever you want is granted.. 5 | * Although, please do acknowledge authorship if appropriate. 6 | * 7 | * This module contains the window setup code, mouse input, timing 8 | * routines, and that sort of stuff. The interesting modules 9 | * to see are bunnygut.cpp and progmesh.cpp. 10 | * 11 | * The windows 95 specific code for this application was taken from 12 | * an example of processing mouse events in an OpenGL program using 13 | * the Win32 API from the www.opengl.org web site. 14 | * 15 | * Under Project->Settings, Link Options, General Category 16 | * Add: 17 | * Opengl32.lib glu32.lib winmm.lib 18 | * to the Object/Library Modules 19 | * 20 | * You will need have OpenGL libs and include files to compile this 21 | * Go to the www.opengl.org web site if you need help with this. 22 | */ 23 | 24 | // 2014 update, just inlined the needed vector things in the vecmatquat_minimal.h file. 25 | // original code was from 1998 and wasn't using the best conventions. 26 | // For example, quaternions are xyzw now, not rxyz. 27 | 28 | 29 | #define NOMINMAX 30 | #include /* must include this before GL/gl.h */ 31 | #include /* OpenGL header file */ 32 | #include /* OpenGL utilities header file */ 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #pragma comment(lib,"winmm.lib") // for the timing functions fps deltat 39 | 40 | #include "../include/glwin.h" // a minimial opengl on windows wrapper, just a header, no lib/dll. 41 | 42 | // Functions and Variables from bunny module 43 | extern void InitModel(); 44 | extern char * RenderModel(); 45 | extern float3 model_position; // position of bunny 46 | extern float4 model_orientation; // orientation of bunny 47 | 48 | // Global Variables 49 | float DeltaT = 0.1f; 50 | float FPS; 51 | 52 | 53 | 54 | 55 | 56 | 57 | void CalcFPSDeltaT() 58 | { 59 | static int timeinit=0; 60 | static int start,start2,current,last; 61 | static int frame=0, frame2=0; 62 | if(!timeinit){ 63 | frame=0; 64 | start=timeGetTime(); 65 | timeinit=1; 66 | } 67 | frame++; 68 | frame2++; 69 | current=timeGetTime(); // found in winmm.lib 70 | double dif=(double)(current-start)/CLOCKS_PER_SEC; 71 | double rv = (dif)? (double)frame/(double)dif:-1.0; 72 | if(dif>2.0 && frame >10) { 73 | start = start2; 74 | frame = frame2; 75 | start2 = timeGetTime(); 76 | frame2 = 0; 77 | } 78 | DeltaT = (float)(current-last)/CLOCKS_PER_SEC; 79 | if(current==last) { 80 | DeltaT = 0.1f / CLOCKS_PER_SEC; // it just cant be 0 81 | } 82 | // if(DeltaT>1.0) DeltaT=1.0; 83 | FPS = (float)rv; 84 | last = current; 85 | } 86 | 87 | 88 | 89 | 90 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, 91 | LPSTR lpszCmdLine, int nCmdShow) 92 | { 93 | 94 | InitModel(); // initializes some data structures and does progressive mesh polygon reduction algorithm 95 | 96 | GLWin glwin("bunnylod by Stan Melax"); 97 | float3 MouseVectorOld; 98 | 99 | while (glwin.WindowUp()) 100 | { 101 | 102 | if(glwin.MouseState) 103 | model_orientation=qmul(VirtualTrackBall(float3(0,0,0),model_position,MouseVectorOld,glwin.MouseVector),model_orientation); 104 | 105 | MouseVectorOld = glwin.MouseVector; 106 | CalcFPSDeltaT(); 107 | 108 | // main drawing loop 109 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 110 | glPushMatrix(); 111 | glLoadIdentity(); 112 | // camera at default (zero) position and orientation 113 | char * s=RenderModel(); 114 | 115 | glLoadIdentity(); 116 | glColor3f(1,1,0); 117 | glwin.PrintString({ 0, -2 },s); // print returned status string from rendermodel() current vert and tri count 118 | glwin.PrintString({ 5, 1 },"Demo by Stan Melax (c)1998"); 119 | glwin.PrintString({ 5, 2 },"Model by Viewpoint Datalabs (c)1996"); 120 | glwin.PrintString({ 0, -1 }, "FPS: %5.2f ", FPS); 121 | 122 | glPopMatrix(); 123 | glFlush(); 124 | glwin.SwapBuffers(); 125 | } 126 | return 0; 127 | } 128 | --------------------------------------------------------------------------------