├── .gitignore ├── LICENSE ├── README.md ├── bunnylod ├── README ├── bunnygut.cpp ├── bunnylod.vcxproj ├── progmesh.cpp ├── progmesh.h ├── rabdata.cpp ├── rabdata.h └── winmain.cpp ├── clothsimd ├── clothsimd.cpp └── clothsimd.vcxproj ├── derp ├── derp.cpp └── derp.vcxproj ├── include ├── bmp.h ├── cnn.h ├── dxshaders.h ├── dxwin.h ├── geometric.h ├── gjk.h ├── glwin.h ├── html_reflect.h ├── hull.h ├── json.h ├── linalg.h ├── mesh.h ├── minixml.h ├── misc.h ├── misc_gl.h ├── misc_image.h ├── misc_json.h ├── mswin.h ├── physics.h ├── tcpsocket.h └── wingmesh.h ├── jointdrive ├── jointdrive.cpp └── jointdrive.vcxproj ├── ploidfit ├── ploidfit.cpp └── ploidfit.vcxproj ├── remove_temp_files.sh ├── sandbox.sln ├── test_reflect ├── test_reflect.cpp └── test_reflect.vcxproj ├── testbool ├── playtest.cpp └── testbool.vcxproj ├── testbsp ├── bsp.cpp ├── bsp.h ├── bspcollide.cpp ├── bspmerge.cpp ├── face.cpp ├── testbsp.cpp └── testbsp.vcxproj ├── testcloth ├── springnet.h ├── testcloth.cpp └── testcloth.vcxproj ├── testcnn ├── testcnn.cpp └── testcnn.vcxproj ├── testcov ├── testcov.cpp └── testcov.vcxproj ├── testdx ├── testdx.cpp └── testdx.vcxproj ├── testgjk ├── testgjk.cpp └── testgjk.vcxproj ├── testhull ├── testhull.cpp └── testhull.vcxproj ├── testicp ├── geo6.h ├── testicp.cpp └── testicp.vcxproj ├── testphys ├── physics.cpp ├── testphys.cpp └── testphys.vcxproj ├── testrig ├── default_hand.chr ├── readme.txt ├── testrig.cpp └── testrig.vcxproj ├── testsubdiv ├── EntireBody.obj ├── testsubdiv.cpp └── testsubdiv.vcxproj ├── testtrack ├── testtrack.cpp └── testtrack.vcxproj └── voxblob ├── legacy_voxblob.vcxproj └── limcubes.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | *_Debug.exe 3 | *_Debug.ilk 4 | *_Debug.pdb 5 | 6 | Release/ 7 | *_Release.exe 8 | *_Release.ilk 9 | *_Release.pdb 10 | 11 | /ipch/ 12 | /packages/ 13 | /*.opensdf 14 | /*.sdf 15 | /*.suo -------------------------------------------------------------------------------- /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 | sandbox 2 | ======= 3 | 4 | sandbox for various 3d math, geometry, graphics and physics code 5 | -------------------------------------------------------------------------------- /bunnylod/README: -------------------------------------------------------------------------------- 1 | 2 | Polygon Reduction Demo 3 | By Stan Melax (c) 1998 4 | http://www.melax.com 5 | 6 | The PC executable bunnylod.exe should run 7 | on a standard PC. 8 | Just run it and enjoy. 9 | Mouse dragging spins the rabbit. 10 | 11 | 12 | August 2014: code style upgraded to be more consistent with graphics/gamdev conventions 13 | 14 | -------------------------------------------------------------------------------- /bunnylod/bunnylod.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | {106A176D-E273-B8BE-82CE-C8F4451D705E} 17 | legacy_bunnylod 18 | 19 | 20 | 21 | Application 22 | false 23 | v140 24 | 25 | 26 | Application 27 | false 28 | v140 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | $(ProjectDir)\ 44 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 45 | $(ProjectName)_$(Configuration) 46 | 47 | 48 | $(ProjectDir)\ 49 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 50 | $(ProjectName)_$(Configuration) 51 | 52 | 53 | 54 | MultiThreaded 55 | OnlyExplicitInline 56 | true 57 | true 58 | MaxSpeed 59 | true 60 | Level3 61 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 62 | 63 | 64 | true 65 | NDEBUG;%(PreprocessorDefinitions) 66 | .\Release\bunnylod.tlb 67 | true 68 | NUL 69 | Win32 70 | 71 | 72 | 0x0409 73 | NDEBUG;%(PreprocessorDefinitions) 74 | 75 | 76 | true 77 | .\Release\bunnylod.bsc 78 | 79 | 80 | true 81 | Windows 82 | 83 | 84 | 85 | 86 | 87 | true 88 | _DEBUG;%(PreprocessorDefinitions) 89 | .\Debug\bunnylod.tlb 90 | true 91 | NUL 92 | Win32 93 | 94 | 95 | 0x0409 96 | _DEBUG;%(PreprocessorDefinitions) 97 | 98 | 99 | true 100 | .\Debug\bunnylod.bsc 101 | 102 | 103 | true 104 | true 105 | Windows 106 | false 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /bunnylod/progmesh.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Progressive Mesh type Polygon Reduction Algorithm 3 | * by Stan Melax (c) 1998 4 | * 5 | * The function ProgressiveMesh() takes a model in an "indexed face 6 | * set" sort of way. i.e. Array of vertices and Array of triangles. 7 | * The function then does the polygon reduction algorithm 8 | * internally and reduces the model all the way down to 0 9 | * vertices and then returns the order in which the 10 | * vertices are collapsed and to which neighbor each vertex 11 | * is collapsed to. More specifically the returned "permutation" 12 | * indicates how to reorder your vertices so you can render 13 | * an object by using the first n vertices (for the n 14 | * vertex version). After permuting your vertices, the 15 | * map Array indicates to which vertex each vertex is collapsed to. 16 | */ 17 | 18 | #ifndef PROGRESSIVE_MESH_H 19 | #define PROGRESSIVE_MESH_H 20 | 21 | #include "../include/linalg.h" // typical 3D math routines following hlsl style for the most part 22 | using namespace linalg::aliases; 23 | #include 24 | 25 | class tridata { 26 | public: 27 | int v[3]; // indices to vertex Array 28 | // texture and vertex normal info removed for this demo 29 | }; 30 | 31 | void ProgressiveMesh(std::vector &vert, std::vector &tri, 32 | std::vector &map, std::vector &permutation); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /bunnylod/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 | -------------------------------------------------------------------------------- /bunnylod/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/linalg.h" // typical 3D math routines following hlsl style for the most part 41 | using namespace linalg::aliases; 42 | #include "../include/geometric.h" 43 | #include "../include/glwin.h" // a minimial opengl on windows wrapper, just a header, no lib/dll. 44 | 45 | // Functions and Variables from bunny module 46 | extern void InitModel(); 47 | extern char * RenderModel(); 48 | extern float3 model_position; // position of bunny 49 | extern float4 model_orientation; // orientation of bunny 50 | 51 | // Global Variables 52 | float DeltaT = 0.1f; 53 | float FPS; 54 | 55 | 56 | 57 | 58 | 59 | 60 | void CalcFPSDeltaT() 61 | { 62 | static int timeinit=0; 63 | static int start,start2,current,last; 64 | static int frame=0, frame2=0; 65 | if(!timeinit){ 66 | frame=0; 67 | start=timeGetTime(); 68 | timeinit=1; 69 | } 70 | frame++; 71 | frame2++; 72 | current=timeGetTime(); // found in winmm.lib 73 | double dif=(double)(current-start)/CLOCKS_PER_SEC; 74 | double rv = (dif)? (double)frame/(double)dif:-1.0; 75 | if(dif>2.0 && frame >10) { 76 | start = start2; 77 | frame = frame2; 78 | start2 = timeGetTime(); 79 | frame2 = 0; 80 | } 81 | DeltaT = (float)(current-last)/CLOCKS_PER_SEC; 82 | if(current==last) { 83 | DeltaT = 0.1f / CLOCKS_PER_SEC; // it just cant be 0 84 | } 85 | // if(DeltaT>1.0) DeltaT=1.0; 86 | FPS = (float)rv; 87 | last = current; 88 | } 89 | 90 | 91 | 92 | 93 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, 94 | LPSTR lpszCmdLine, int nCmdShow) 95 | { 96 | 97 | InitModel(); // initializes some data structures and does progressive mesh polygon reduction algorithm 98 | 99 | GLWin glwin("bunnylod by Stan Melax"); 100 | float3 MouseVectorOld; 101 | 102 | while (glwin.WindowUp()) 103 | { 104 | 105 | if(glwin.MouseState) 106 | model_orientation=qmul(VirtualTrackBall(float3(0,0,0),model_position,MouseVectorOld,glwin.MouseVector),model_orientation); 107 | 108 | MouseVectorOld = glwin.MouseVector; 109 | CalcFPSDeltaT(); 110 | 111 | // main drawing loop 112 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 113 | glPushMatrix(); 114 | glLoadIdentity(); 115 | // camera at default (zero) position and orientation 116 | char * s=RenderModel(); 117 | 118 | glLoadIdentity(); 119 | glColor3f(1,1,0); 120 | glwin.PrintString({ 0, -2 },s); // print returned status string from rendermodel() current vert and tri count 121 | glwin.PrintString({ 5, 1 },"Demo by Stan Melax (c)1998"); 122 | glwin.PrintString({ 5, 2 },"Model by Viewpoint Datalabs (c)1996"); 123 | glwin.PrintString({ 0, -1 }, "FPS: %5.2f ", FPS); 124 | 125 | glPopMatrix(); 126 | glFlush(); 127 | glwin.SwapBuffers(); 128 | } 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /derp/derp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // DERP: Dual quaternion intERPolation 3 | // 4 | // A minimal demo illustrating screw-motion pose interpolation using dual quaternion math 5 | // left mouse moves the camera or, if selected, changes the orientation of one of the two endpoints. 6 | // 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Minimal c++11 implementation of dual quaternion as style agnostic as possible. 16 | // Assumes there is a float4 struct defined the obvious xyzw way and usual support quat functions. 17 | // This implementation just uses 4x2 matrix where the second ([1]) column is the dual part. 18 | // Feel free to convert to your own design/style preferences and struct names. 19 | // The Pose class is just a position,orientation (vec3,quat) pair defined the obvious way. 20 | // The functions dqmake/dqpose convert Pose to/from dual quat representation. 21 | // 22 | float4x2 dqmul(const float4x2 &a, float4x2 &b) { return{ qmul(a[0], b[0]), qmul(a[0], b[1]) + qmul(a[1], b[0]) }; } 23 | float4x2 dqnorm(const float4x2 &d) { return d / length(d[0]); } // normalize based on non-dual part only 24 | float4x2 dqmake(const Pose &p) { return dqmul(float4x2({ 0, 0, 0, 1 }, float4(p.position / 2.0f, 0)), float4x2(p.orientation, { 0, 0, 0, 0 })); } 25 | Pose dqpose(const float4x2 &d) { return{ qmul(d[1], qconj(d[0])).xyz()*2.0f, d[0] }; } 26 | float4x2 dqinterp(const float4x2 &d0, const float4x2 &d1, float t) { return dqnorm(d0*(1 - t) + d1*t); } // normalized lerp 27 | Pose dqinterp(const Pose &p0,const Pose &p1,float t) { return dqpose(dqinterp(dqmake(p0),dqmake(dot(p0.orientation,p1.orientation)<0?Pose(p1.position,-p1.orientation):p1),t)); } 28 | 29 | // some typical opengl drawing support routines 30 | // 31 | void glGridxy(float r, float3 c = { 0, 1, 0 }) 32 | { 33 | glColor3fv(c); 34 | glBegin(GL_LINES); 35 | glColor3fv({ 0.25f, 0.25f, 0.25f }); 36 | for (float t = -4; t <= 4; t += 1.0f) 37 | { 38 | glVertex3fv(float3(t, -4.0f, 0)*r / 4.0f); glVertex3fv(float3(t, 4.0f, 0)*r / 4.0f); 39 | glVertex3fv(float3(-4.0f, t, 0)*r / 4.0f); glVertex3fv(float3(4.0f, t, 0)*r / 4.0f); 40 | } 41 | glEnd(); 42 | } 43 | 44 | void glAxis() 45 | { 46 | glPushAttrib(GL_ALL_ATTRIB_BITS); 47 | glLineWidth(3.0f); 48 | glBegin(GL_LINES); 49 | for (int i : {0, 1, 2}) 50 | { 51 | float3 v(0, 0, 0); 52 | v[i] = 1.0f; 53 | glColor3fv(v); 54 | glVertex3fv({ 0, 0, 0 }); 55 | glVertex3fv(v); 56 | } 57 | glEnd(); 58 | glPopAttrib(); 59 | } 60 | 61 | void glcolorbox(const float3 &r, const Pose &p) // p = { { 0, 0, 0 }, { 0, 0, 0, 1 } }) 62 | { 63 | glPushMatrix(); 64 | glMultMatrixf(p.matrix()); 65 | glBegin(GL_QUADS); 66 | for (int m : {0, 1}) for (int i : {0, 1, 2}) 67 | { 68 | int i1 = (i + 1 + m) % 3; 69 | int i2 = (i + 2 - m) % 3; 70 | float3 u, v, w; 71 | u[i1] = r[i1]; 72 | v[i2] = r[i2]; 73 | w[i] = (m) ? -1.0f : 1.0f; 74 | float3 a((float)m, (float)m, (float)m); 75 | a[i] = 1-a[i]; 76 | glColor3fv(a); 77 | glNormal3fv(w); 78 | float2 corners[] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { 1.0f, 1.0f }, { -1.0f, 1.0f } }; // ccw order 79 | for (float2 t : corners) 80 | glTexCoord2fv(t), glVertex3fv(w*r[i] + u*t.x + v*t.y); 81 | } 82 | glEnd(); 83 | glPopMatrix(); 84 | } 85 | 86 | int main(int argc, char *argv[]) try 87 | { 88 | std::cout << "DerpDemo\n"; 89 | Pose camera = { { 0, 0, 8 }, { 0, 0, 0, 1 } }; 90 | bool showaxis = true; 91 | float3 focuspoint(0, 0, 0); 92 | float4 model_orientation(0, 0, 0, 1); 93 | Pose p0 = { { -3, 0, 0 }, { 0, 0, 0, 1 } }; 94 | Pose p1 = { { 3, 0, 0 }, { 0, 0, sqrtf(0.5f),sqrtf(0.5f) } }; 95 | float dt = 0.01f, t = 0; 96 | Pose *selected = NULL; 97 | std::vector planes = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { -1, 0, 0, 0 }, { 0, -1, 0, 0 }, { 0, 0, -1, 0 } }; 98 | for (auto &p : planes) 99 | p.w = -0.25f; 100 | 101 | GLWin glwin("DERP: Dual quaternion intERPolation"); 102 | glwin.keyboardfunc = [&](int key, int, int) 103 | { 104 | showaxis = key == 'a' != showaxis; 105 | }; 106 | while (glwin.WindowUp()) 107 | { 108 | t = t + dt; // advance our global time t is in 0..1 109 | if (t > 1.0f) 110 | t = 0.0f; 111 | 112 | Pose pt = dqinterp(p0,p1,t); // And here we show our dual quaterion usage 113 | 114 | // some extras to help visualize the axis of rotation, not the best math to get the result, but oh well 115 | float4 aq = qmul(dot(p0.orientation, p1.orientation) < 0 ? -p1.orientation : p1.orientation, qconj(p0.orientation)); 116 | float3 axis = normalize(aq.xyz()*(aq.w < 0 ? -1.0f : 1.0f)); // direction of the axis of rotation 117 | float3 axisp = cross(axis, p1.position - p0.position) / 2.0f * sqrtf(1/dot(aq.xyz(),aq.xyz())-1); // origin projected onto the axis of rotation 118 | // user interaction: 119 | float3 ray = qrot(camera.orientation, normalize(glwin.MouseVector)); // for mouse selection 120 | float3 v1 = camera.position + ray*100.0f; 121 | if (!glwin.MouseState) // note that we figure out what is being selected only when the mouse is up 122 | { 123 | selected = NULL; 124 | for (Pose *p : { &p0, &p1 }) 125 | { 126 | if (auto h = ConvexHitCheck(planes, *p, camera.position, v1)) 127 | { 128 | selected = p; 129 | v1 = h.impact; 130 | } 131 | } 132 | } 133 | else // if (glwin.MouseState) 134 | { 135 | if (selected) 136 | selected->orientation = qmul(VirtualTrackBall(camera.position, selected->position, qrot(camera.orientation, glwin.OldMouseVector), qrot(camera.orientation, glwin.MouseVector)), selected->orientation); 137 | else 138 | camera.orientation = qmul(camera.orientation, qconj(VirtualTrackBall(float3(0, 0, 1), float3(0, 0, 0), glwin.OldMouseVector, glwin.MouseVector))); // equation is non-typical we are orbiting the camera, not rotating the object 139 | } 140 | camera.position = focuspoint + qzdir(camera.orientation)*length(camera.position - focuspoint); 141 | camera.position -= focuspoint; 142 | camera.position *= powf(1.1f, (float)glwin.mousewheel); 143 | camera.position += focuspoint; 144 | 145 | // Render the scene 146 | glPushAttrib(GL_ALL_ATTRIB_BITS); 147 | glViewport(0, 0, glwin.res.x, glwin.res.y); // Set up the viewport 148 | glClearColor(0.1f, 0.1f, 0.15f, 1); 149 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 150 | glMatrixMode(GL_PROJECTION); 151 | glPushMatrix(); glLoadIdentity(); 152 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.25, 250); 153 | glMatrixMode(GL_MODELVIEW); 154 | glPushMatrix(); glLoadIdentity(); 155 | glMultMatrixf(camera.inverse().matrix()); 156 | 157 | glDisable(GL_LIGHTING); 158 | glAxis(); 159 | glGridxy(4.0f); 160 | if (showaxis) 161 | { 162 | glPushAttrib(GL_ALL_ATTRIB_BITS); 163 | glLineWidth(3.0f); 164 | glBegin(GL_LINES); 165 | glColor3f(1, 1, 1); 166 | for (auto p : { p0.position, p1.position, pt.position ,axisp}) 167 | glVertex3fv(p - axis*0.5f), glVertex3fv(p + axis*0.5f); // note the comma 168 | glEnd(); 169 | glPopAttrib(); 170 | glColor3f(1, 1, 0); 171 | glBegin(GL_LINES); 172 | glVertex3fv(axisp + axis*dot(axis, p0.position)), glVertex3fv(axisp + axis*dot(axis, p1.position)); 173 | glVertex3fv(axisp + axis*dot(axis, p0.position)), glVertex3fv(p0.position); 174 | glVertex3fv(axisp + axis*dot(axis, p1.position)), glVertex3fv(p1.position); 175 | glVertex3fv(axisp + axis*dot(axis, pt.position)), glVertex3fv(pt.position); 176 | glEnd(); 177 | } 178 | 179 | glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); 180 | for (auto p : { p0, p1, pt }) 181 | glcolorbox(float3(0.25f), p); 182 | 183 | glPopMatrix(); //should be currently in modelview mode 184 | glMatrixMode(GL_PROJECTION); 185 | glPopMatrix(); 186 | glMatrixMode(GL_MODELVIEW); 187 | glPopAttrib();// Restore state 188 | 189 | glwin.PrintString({ 0, 0 }, "ESC to quit."); 190 | glwin.PrintString({ 0, 1 }, "'a' show axis (%s)", showaxis ? "on" : "off"); 191 | glwin.PrintString({ 0, 2 }, "%selected: %s", glwin.MouseState?"S":"s", (selected) ? ((selected==&p0)?"box0":"box1") : "none"); 192 | glwin.SwapBuffers(); 193 | } 194 | std::cout << "\n"; 195 | return 0; 196 | } 197 | catch (std::exception e) 198 | { 199 | std::cerr << e.what() << "\n"; 200 | } 201 | -------------------------------------------------------------------------------- /derp/derp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {BF4023E5-46A2-45FD-B616-E63AA17BF631} 15 | Win32Proj 16 | testdq 17 | derp 18 | 19 | 20 | 21 | Application 22 | true 23 | v140 24 | NotSet 25 | 26 | 27 | Application 28 | false 29 | v140 30 | true 31 | NotSet 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 48 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 49 | 50 | 51 | false 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 55 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 56 | 57 | 58 | 59 | 60 | 61 | Level3 62 | Disabled 63 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 64 | 65 | 66 | Console 67 | true 68 | 69 | 70 | 71 | 72 | Level3 73 | 74 | 75 | MaxSpeed 76 | true 77 | true 78 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 79 | 80 | 81 | Console 82 | true 83 | true 84 | true 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /include/bmp.h: -------------------------------------------------------------------------------- 1 | // 2 | // minimal bmp support that only handles 24 bit color images 3 | // 4 | 5 | #ifndef BMP_FILE_FORMAT_H 6 | #define BMP_FILE_FORMAT_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "geometric.h" 15 | #include "misc.h" 16 | 17 | inline std::vector monotorgb(const std::vector &src) 18 | { 19 | std::vector dst(src.size()); 20 | std::transform(src.begin(), src.end(), dst.begin(), [](unsigned char c){return byte3(c, c, c); }); 21 | return dst; 22 | } 23 | inline std::vector shorttorgb_r(const std::vector &src) 24 | { 25 | std::vector dst(src.size()); 26 | // this color ramp is a bit of a hack right now, just trying to visualize output for sanity check object at about 50cm away. 27 | auto map = [](unsigned short c){return (c==0)?byte3(0,0,0): byte3(c > 512 ? 0 : std::min(255, 512 - c), c > 512 ? 0 : std::min(255, (512 - c)*2), c > 768 ? 0 : std::min(255, (768 - c)/2)); }; 28 | std::transform(src.begin(), src.end(), dst.begin(),map); 29 | return dst; 30 | } 31 | 32 | struct BMPHeader{ 33 | // char bm[2]; // not part of struct due to 4 byte alignment of the int members 34 | int filesize; // 54 + dim.x * dim.y * (bpp/8) 35 | int whatever = 0; // 4 bytes can be 0000 36 | int start = 54; // 54 37 | int dib_header_size = 40; // 40 size of remainder of this struct, which is same as windows.h -> wingdi.h -> BITMAPINFOHEADER or struct tagBITMAPINFOHEADER 38 | int2 dim; // w,h width,height negative height means the origin is in the upper left 39 | short color_planes = 1; // 1 40 | short bpp = 24; // 24 bits per pixel 41 | int pixarraycomp = 0; // 0 compression flag BI_RGB in wingdi.h 42 | int imagesizebytes; // w*h*bpp/8 or filesize-54 43 | int pix_per_meter_x = 0; // 2835 or 0 44 | int pix_per_meter_y = 0; // 2835 or 0 45 | int palettesize = 0; // 0 46 | int colors_important= 0; // 0 47 | BMPHeader(){}; 48 | BMPHeader(int2 dim) :dim(dim), imagesizebytes(abs(product(dim)) * 24 / 8), filesize(abs(product(dim)) * 24 / 8 + 54){} 49 | }; 50 | static_assert(sizeof(BMPHeader) == 54 - 2, "incorrect header size"); 51 | 52 | struct BMPImage 53 | { 54 | int2 dim; // w,h 55 | std::vector image; 56 | operator std::pair() { return std::pair(image.data(), dim); } 57 | }; 58 | template inline std::vector & FlipV(std::vector &image, int2 dim) // ugh 59 | { 60 | for (int y = 0; y < dim.y / 2; y++) for (int x = 0; x < dim.x; x++) 61 | std::swap(image[y*dim.x + x], image[(dim.y - 1 - y)*dim.x + x]); 62 | return image; 63 | } 64 | 65 | 66 | inline BMPImage BMPRead(const char *filename) 67 | { 68 | std::ifstream file(filename, std::ios::binary); 69 | if (!file.is_open()) 70 | throw(std::exception((std::string("BMPRead failed to open: ") + filename).c_str())); 71 | char bm[2]; // "BM" 72 | file.read(bm, 2); 73 | BMPHeader header; 74 | file.read((char*)&header, sizeof(header)); 75 | std::vector image(header.imagesizebytes/3); 76 | file.read((char*)image.data(), header.imagesizebytes); 77 | for (auto &pixel: image) 78 | std::swap(pixel.x,pixel.z); // bgr to rgb 79 | if (header.dim.y < 0) 80 | FlipV(image, header.dim *= int2{ 1,-1 }); 81 | return { header.dim, image }; 82 | } 83 | 84 | inline void BMPWrite(const char *filename, std::vector image, int2 dim) // pass image by value since we need to swap bytes 85 | { 86 | std::ofstream file(filename, std::ios::binary | std::ios::trunc ); 87 | if (!file.is_open()) 88 | throw(std::exception("unable to open a file for binary write")); 89 | file.write("BM", 2); 90 | BMPHeader header(dim); 91 | file.write(reinterpret_cast(&header), sizeof(header)); 92 | for (auto &pixel : image) 93 | std::swap(pixel.x, pixel.z); // rgb to bgr 94 | file.write(reinterpret_cast(image.data()), header.imagesizebytes); 95 | file.close(); 96 | } 97 | 98 | 99 | inline std::vector ShortToRGB(const std::vector &src, std::function f) 100 | { 101 | auto ColorEncode = [&f](unsigned short s) ->byte3 { 102 | return byte3(f(s), 103 | (s & 1) >> 0 | (s & 4) >> 1 | (s & 16) >> 2 | (s & 64 ) >> 3 | (s & 256) >> 4 | (s & 1024) >> 5 | (s & 4096) >> 6 | (s & 16384) >> 7 , 104 | (s & 2) >> 1 | (s & 8) >> 2 | (s & 32) >> 3 | (s & 128) >> 4 | (s & 512) >> 5 | (s & 2048) >> 6 | (s & 8192) >> 7 | (s & 32768) >> 8 105 | //reinterpret_cast(&s)[0], reinterpret_cast(&s)[1] 106 | ); 107 | }; 108 | std::vector image(src.size()); 109 | for (unsigned int i = 0; i < src.size(); i++) 110 | { 111 | image[i] = ColorEncode(src[i]); 112 | } 113 | return image; 114 | } 115 | inline void BMPFromShortR(const char *filename, const std::vector &src, int2 dim, std::function f = [](short s)->unsigned char{return (s >= 512) ? 0 : 255 - ((s >> 1) & 255); }) 116 | { 117 | BMPWrite(filename, FlipV(ShortToRGB(src, f),dim), dim); 118 | } 119 | inline void BMPFromShortC(const char *filename, const std::vector &src, int2 dim, std::function f = [](short s)->unsigned char{return (s >= 1024) ? 255 : ((s >> 2) & 255); }) 120 | { 121 | BMPWrite(filename, FlipV(ShortToRGB(src, f),dim), dim); 122 | } 123 | 124 | inline std::vector RGBToShort(const std::vector &src,int2 dim) 125 | { 126 | std::vector data(src.size()); 127 | auto ColorDecode = [](byte3 c) -> unsigned short{ 128 | unsigned short r = 0; 129 | for (int i = 0; i < 8; i++) 130 | { 131 | r |= (c.y&(1 << i)) << i; 132 | r |= (c.z&(1 << i)) << (i+1); 133 | } 134 | return r; // c.y + (c.z << 8); 135 | }; 136 | for (unsigned int i = 0; i < src.size(); i++) 137 | { 138 | data[i] = ColorDecode(src[i]); 139 | } 140 | FlipV(data, dim); 141 | return data; 142 | } 143 | 144 | 145 | 146 | 147 | 148 | #endif // BMP_FILE_FORMAT_H 149 | -------------------------------------------------------------------------------- /include/dxshaders.h: -------------------------------------------------------------------------------- 1 | // 2 | // inlined hlsl shaders. see dxwin.h 3 | // 4 | 5 | const char *dxshaders = R"EFFECTFILE( 6 | 7 | float4 qconj(float4 q) 8 | { 9 | return float4(-q.x,-q.y,-q.z,q.w); 10 | } 11 | 12 | float4 qmul(float4 a, float4 b) 13 | { 14 | float4 c; 15 | c.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z; 16 | c.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y; 17 | c.y = a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x; 18 | c.z = a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w; 19 | return c; 20 | } 21 | 22 | 23 | float3 qrot( float4 q, float3 v ) 24 | { 25 | return qmul(qmul(q,float4(v,0)), float4(-q.x,-q.y,-q.z,q.w)).xyz; 26 | } 27 | 28 | struct Vertex 29 | { 30 | float3 position : POSITION; 31 | float4 orientation : TEXCOORD1; 32 | float2 texcoord : TEXCOORD0; 33 | }; 34 | 35 | struct Fragment 36 | { 37 | float4 screenpos : SV_POSITION; 38 | float2 texcoord : TEXCOORD0; 39 | float3 position : TEXCOORD6; 40 | // float4 orientation : TEXCOORD7; 41 | float3 tangent : TEXCOORD3; 42 | float3 binormal : TEXCOORD4; 43 | float3 normal : TEXCOORD5; 44 | }; 45 | 46 | cbuffer ConstantBuffer : register( b0 ) 47 | { 48 | float4 hack; 49 | matrix Projection; 50 | float3 camerap; float unusedc; // extra float for 128bit padding 51 | float4 cameraq; 52 | float3 meshp; float unusedm; 53 | float4 meshq; 54 | } 55 | 56 | 57 | 58 | Texture2D txDiffuse : register( t0 ); 59 | Texture2D txNMap : register( t1 ); 60 | SamplerState samLinear : register( s0 ); 61 | 62 | 63 | //-------------------------------------------------------------------------------------- 64 | // Vertex Shader 65 | //-------------------------------------------------------------------------------------- 66 | //Fragment VS(Vertex v) 67 | Fragment VS( Vertex v ) //: SV_POSITION 68 | { 69 | Fragment foo = (Fragment)0; 70 | //out.position = meshp + qrot(meshq,v.position); 71 | //out.screenpos = mul(float4( mul(qrot(qconj(cameraq,out.position))-camerap,1),Projection); 72 | // out.screenpos = mul(float4(v.position,1),Projection); 73 | // return out.screenpos; 74 | float3 pw = meshp.xyz + qrot(meshq,v.position.xyz) ; 75 | foo.position = pw; // world space position 76 | float4 pc = float4(qrot(qconj(cameraq),pw-camerap) ,1); 77 | foo.screenpos = mul(pc,Projection); 78 | foo.texcoord = v.texcoord; 79 | float4 sq = qmul(meshq,v.orientation); 80 | foo.normal = qrot(sq,float3(0,0,1)); 81 | foo.tangent = qrot(sq,float3(1,0,0)); 82 | foo.binormal = qrot(sq,float3(0,1,0)); 83 | return foo; 84 | // return mul(p,Projection); 85 | } 86 | 87 | //-------------------------------------------------------------------------------------- 88 | // Pixel Shader 89 | //-------------------------------------------------------------------------------------- 90 | float4 PS( Fragment v) : SV_Target 91 | { 92 | float parallaxscale = 0.2; // was 0.06 93 | 94 | // return hack /* txDiffuse.Sample( samLinear,v.texcoord) */ * txNMap.Sample( samLinear,v.texcoord).w ; // float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 95 | float height = txNMap.Sample( samLinear,v.texcoord).w * parallaxscale - parallaxscale/2.0f; 96 | float3x3 m = float3x3(normalize(v.tangent),normalize(v.binormal),normalize(v.normal)); 97 | float2 offset = height * mul(m,normalize(camerap-v.position)) ; // rotate eye vector into tangent space 98 | 99 | float3 nl = normalize(txNMap.Sample( samLinear,v.texcoord+offset).xyz - float3(0.5,0.5,0.5)); 100 | float3 nw = mul(nl,m); 101 | //return float4(nl*0.5+float3(0.5,0.5,0.5),1.0); 102 | // return hack * dot(nw ,qrot(cameraq,float3(0,0,1)) ) ; // float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 103 | // return dot(nw ,qrot(cameraq,float3(-.5,.5,.5)) ) ; // float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 104 | // return dot(nw ,normalize(float3(-1,-2,1)) ) ; // float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 105 | //return txNMap.Sample( samLinear,v.texcoord).zzzz; 106 | //return float4(0.5+offset.x*100,0.5+offset.y*100,parallaxscale*100,1); 107 | return hack * (0.75+0.25*txDiffuse.Sample( samLinear,v.texcoord+offset)) * dot(nw ,normalize(float3(-1,-2,1)) ) ; // float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 108 | } 109 | 110 | )EFFECTFILE"; 111 | -------------------------------------------------------------------------------- /include/minixml.h: -------------------------------------------------------------------------------- 1 | // 2 | // a small xml parser 3 | // doesn't fully meet spec 4 | // 5 | 6 | #ifndef SANDBOX_MINI_XML_PARSE_H 7 | #define SANDBOX_MINI_XML_PARSE_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | class xmlNode 20 | { 21 | public: 22 | class Attribute 23 | { 24 | public: 25 | std::string key; 26 | std::string value; 27 | }; 28 | std::string tag; 29 | std::vector attributes; 30 | std::vector children; 31 | std::string body; 32 | xmlNode * haschild(const char *s) { for (unsigned int i = 0; i < children.size(); i++)if (s == children[i].tag)return &children[i]; return NULL; } 33 | const xmlNode * haschild(const char *s) const { for (unsigned int i = 0; i < children.size(); i++)if (s == children[i].tag)return &children[i]; return NULL; } 34 | xmlNode & child(const char *s) { if (auto c=haschild(s)) return *c; children.push_back(xmlNode(s)); return children.back(); } 35 | const xmlNode & child(const char *s) const { if (auto c=haschild(s)) return *c; throw(std::exception((std::string("xml tree missing expected node ")+s+" in "+tag).c_str())); } 36 | Attribute * hasAttribute(const char *s) { auto iter = std::find_if(attributes.begin(), attributes.end(), [s](Attribute&a){return s == a.key; }); return (iter != attributes.end()) ? &*iter : NULL; } 37 | const Attribute *hasAttribute(const char *s)const { for(unsigned int i=0;ivalue; attributes.push_back({s,""}); return attributes.back().value; } 39 | std::string attribute(const char *s)const { auto a = hasAttribute(s); return (a) ? a->value : ""; } 40 | xmlNode & operator<<(Attribute a) { attributes.push_back(a); return *this;} 41 | xmlNode & operator<<(xmlNode c) { children.push_back(c); return *this;} 42 | xmlNode(const char *_tag):tag(_tag){} 43 | xmlNode(){} 44 | //xmlNode(const xmlNode &a) = delete; 45 | ~xmlNode(){} 46 | }; 47 | 48 | inline int IsOneOf (const char e, const char *p ) { while (*p) if (*p++ == e) return 1; return 0; } 49 | inline const char *SkipChars (const char *s, const char *delimeter) { while (*s && IsOneOf(*s, delimeter)){ s++; } return s; } 50 | inline const char *SkipToChars(const char *s, const char *tokens ) { while (*s && !IsOneOf(*s, tokens )){ s++; } return s; } 51 | 52 | inline std::string NextToken(const char *&s) 53 | { 54 | const char *t; 55 | std::string token(""); 56 | s = SkipChars(s, " \t\n\r"); 57 | t = s; 58 | if (!*s) 59 | { 60 | token = ""; 61 | return token; 62 | } 63 | if (*t == '\"') 64 | { 65 | s = t = t + 1; 66 | s = SkipToChars(s, "\""); 67 | token = std::string(std::string(t, s)); 68 | if (*s) s++; 69 | return token; 70 | } 71 | if (IsOneOf(*t, "<>!?=/")) 72 | { 73 | s++; 74 | token = std::string(t, t + 1); 75 | return token; 76 | } 77 | s = SkipToChars(s, "<>!?=/ \r\t\n"); 78 | token = std::string(t, s); 79 | s = SkipChars(s, " \t\n\r"); 80 | return token; 81 | } 82 | 83 | inline xmlNode XMLParse(const char *&s) 84 | { 85 | std::string token; 86 | while (token != "<" || IsOneOf(*s, "!?")) 87 | { 88 | token=NextToken(s); 89 | assert(*s); 90 | } 91 | xmlNode elem(NextToken(s).c_str()); 92 | while (*s && (token=NextToken(s)) != ">" && token != "/") 93 | { 94 | std::string &newval = elem.attribute(token.c_str()); 95 | token = NextToken(s); 96 | assert(token == "="); 97 | newval = NextToken(s).c_str(); 98 | } 99 | if (token == "/") 100 | { 101 | token = NextToken(s); 102 | assert(token == ">"); 103 | return elem; // no children 104 | } 105 | assert(token == ">"); 106 | const char *t = SkipChars(s, " \t\n\r");; 107 | token = NextToken(s); 108 | while (token != "<" || *s != '/') 109 | { 110 | if (token == "<") 111 | { 112 | s = t;// rewind a bit 113 | elem.children.push_back(XMLParse(s)); 114 | t = SkipChars(s, " \t\n\r");; 115 | token = NextToken(s); 116 | } 117 | else 118 | { 119 | 120 | s = SkipToChars(s, "<"); 121 | elem.body = elem.body + std::string(t, s); 122 | t = s; 123 | token = NextToken(s); 124 | } 125 | } 126 | assert(*s == '/'); 127 | token = NextToken(s); 128 | token = NextToken(s); 129 | assert(token == elem.tag); 130 | token = NextToken(s); 131 | assert(token == ">"); 132 | return elem; 133 | } 134 | 135 | 136 | inline xmlNode XMLParseFile(const char *filename) 137 | { 138 | if (!filename || !*filename) return NULL; 139 | std::ifstream file(filename, std::ios::binary|std::ios::ate); 140 | if (!file.is_open()) 141 | throw(std::exception((std::string("File Not Found: ") + filename).c_str())); 142 | auto len = file.tellg(); 143 | file.seekg(0, std::ios::beg); 144 | std::string mem((size_t)len+1,'\0'); 145 | file.read(&mem[0], len); 146 | file.close(); 147 | const char *s = mem.data(); 148 | return XMLParse(s); 149 | } 150 | 151 | 152 | inline void XMLSaveFile(const xmlNode &elem, FILE *fp) 153 | { 154 | static int depth = 0; 155 | int singleline = (elem.children.size() == 0 && elem.body.size()<60); 156 | auto indent = [fp](){for (int i = 0; i < depth; i++) fprintf(fp, " "); }; 157 | indent(); 158 | fprintf(fp, "<%s", (const char*)elem.tag.c_str()); 159 | for (unsigned int i = 0; i" : ">\n"); 163 | depth += 2; 164 | for (unsigned int i = 0; i\n", (const char*)elem.tag.c_str()); 174 | } 175 | inline void XMLSaveFile(const xmlNode &elem, const char *filename) 176 | { 177 | FILE *fp=NULL; 178 | fopen_s(&fp, filename, "w"); 179 | assert(fp); 180 | if (&elem != NULL) 181 | XMLSaveFile(elem, fp); 182 | fclose(fp); 183 | } 184 | 185 | 186 | std::ostream& operator<<(std::ostream &os, const xmlNode &n) 187 | { 188 | os << "<" << n.tag << " "; 189 | for (auto &h : n.attributes) 190 | os << h.key << "=\"" << h.value << "\" "; 191 | os << ">"; 192 | for (auto &c : n.children) 193 | os << c; 194 | os << n.body; 195 | os << ""; 196 | return os; 197 | } 198 | 199 | 200 | 201 | #endif // SANDBOX_MINI_XML_PARSE_H 202 | -------------------------------------------------------------------------------- /include/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 | #include 21 | 22 | // some misc convenience functions 23 | 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; } 24 | 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; } 25 | template std::vector & Append(std::vector &a, const T& t) { a.push_back(t); return a; } 26 | template std::vector & Append(std::vector &a, T&& t) { a.push_back(std::move(t)); return a; } 27 | template std::vector & Append(std::vector &a, const std::vector &b) { a.insert(a.end(), b.begin(), b.end()); return a; } 28 | template std::vector & Append(std::vector &a, std::vector &&b) { for(auto &e:b) a.push_back(std::move(e)); return a; } 29 | template std::vector Addresses( std::vector &a) { return Transform(a, [](T &t)->T* {return &t; }); } 30 | template std::vector Addresses(const std::vector &a) { return Transform(a, [](T &t)->T* {return &t; }); } 31 | 32 | 33 | // fixme: basepathname and fileprefix are just two attempts to implemement the same thing 34 | 35 | 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 36 | inline bool fileexists(std::string filename) { std::ifstream i(filename, std::ifstream::in); return i.is_open(); } 37 | 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 : ""; } 38 | 39 | 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 40 | inline std::string fileprefix(const char *filename) { return std::string(filename, strstp(filename, '.')); } 41 | inline std::string fileprefix(std::string filename) { return fileprefix(filename.c_str()); } 42 | 43 | inline std::string freefilename(std::string prefix, std::string suffix) // find next unused file in sequence 44 | { 45 | int fid = 0; 46 | auto fnaming_convention = [prefix, suffix](int fid) { return prefix + std::to_string(fid) + suffix; }; 47 | while (fileexists(fnaming_convention(fid).c_str())) 48 | fid++; 49 | return fnaming_convention(fid); 50 | } 51 | 52 | 53 | 54 | inline std::vector split(std::string line, std::string delimeter = " ", size_t minlength = 1) // move to misc.h 55 | { 56 | std::vector tokens; 57 | size_t pos = 0; 58 | while ((pos = line.find(delimeter)) != std::string::npos) 59 | { 60 | auto token = line.substr(0, pos); 61 | line.erase(0, pos + delimeter.length()); 62 | if (token.length()>= minlength) 63 | tokens.push_back(token); 64 | } 65 | if (line.length()>=minlength) 66 | tokens.push_back(line); 67 | return tokens; 68 | } 69 | 70 | 71 | template 72 | inline std::vector ArrayImport(std::string str) 73 | { 74 | std::vector a; 75 | std::istringstream s(str); 76 | T e; 77 | while (((s >> e), s.good())) 78 | { 79 | a.push_back(e); 80 | s.ignore(16, '\n'); 81 | } 82 | return a; 83 | } 84 | 85 | // ToString() - convenience class/function for using << overloads to generate strings inline within a single expression 86 | // Example Usage: return ToString() << "test" << my_vec3 << " more " << my_float_var << " and so on"; 87 | // or: set_thermometer_gui_string( ToString() << (temperature*9/5+32) ); 88 | struct ToString 89 | { 90 | std::ostringstream o; 91 | std::string str() { return o.str(); } 92 | operator std::string() { return o.str(); } 93 | templateToString &operator<<(const T &t) { o << t; return *this; } 94 | }; 95 | 96 | // StringTo and FromString - convenience class/function for using >> overloads to convert from strings inline within a single expression 97 | // f(StringTo("6 7 8")); // if f() is overloaded specify type with StringTo<>() 98 | // g(FromString("9")); // works if g isn't overloaded such as it takes a float 99 | // 100 | template inline T StringTo(std::string s) { T v; std::istringstream i(std::move(s)); i >> v; return v; } 101 | 102 | struct FromString 103 | { 104 | const std::string &s; 105 | FromString(const std::string &s) :s(s) {} 106 | template operator T () { return StringTo(s); } 107 | operator std::string() { return s; } 108 | }; 109 | 110 | 111 | template void visit_fields(T&t, F f) { t.visit_fields(f); } 112 | 113 | template inline typename std::enable_if::type 114 | visit_fields(std::tuple ¶ms, F f) 115 | {} 116 | 117 | template inline typename std::enable_if< I < sizeof...(TS), void>::type 118 | visit_fields(std::tuple ¶ms, F f) 119 | { 120 | f(std::get(params), std::get(params)); 121 | visit_fields(params, f); 122 | } 123 | 124 | 125 | 126 | #endif // SANDBOX_MISC_H 127 | 128 | -------------------------------------------------------------------------------- /include/misc_json.h: -------------------------------------------------------------------------------- 1 | // 2 | // misc files are temporary home for convenience routines not yet sure about convention or where it goes. 3 | // json support code for our linalg types 4 | // 5 | 6 | 7 | #pragma once 8 | #ifndef SANDBOX_MISC_JSON_H 9 | #define SANDBOX_MISC_JSON_H 10 | 11 | //----------------------- 12 | 13 | #include "json.h" 14 | #include "geometric.h" 15 | 16 | 17 | 18 | // Serialize vectors and matrices as JSON arrays 19 | template json::value to_json(const linalg::vec & vec) { return json::array{to_json(vec.x), to_json(vec.y)}; } 20 | template json::value to_json(const linalg::vec & vec) { return json::array{to_json(vec.x), to_json(vec.y), to_json(vec.z)}; } 21 | template json::value to_json(const linalg::vec & vec) { return json::array{to_json(vec.x), to_json(vec.y), to_json(vec.z), to_json(vec.w)}; } 22 | template json::value to_json(const linalg::mat & mat) { return json::array{to_json(mat.x), to_json(mat.y)}; } 23 | template json::value to_json(const linalg::mat & mat) { return json::array{to_json(mat.x), to_json(mat.y), to_json(mat.z)}; } 24 | template json::value to_json(const linalg::mat & mat) { return json::array{to_json(mat.x), to_json(mat.y), to_json(mat.z), to_json(mat.w)}; } 25 | 26 | template void from_json(linalg::vec & vec, const json::value & val) { from_json(vec.x, val[0]); from_json(vec.y, val[1]); } 27 | template void from_json(linalg::vec & vec, const json::value & val) { from_json(vec.x, val[0]); from_json(vec.y, val[1]); from_json(vec.z, val[2]); } 28 | template void from_json(linalg::vec & vec, const json::value & val) { from_json(vec.x, val[0]); from_json(vec.y, val[1]); from_json(vec.z, val[2]); from_json(vec.w, val[3]); } 29 | template void from_json(linalg::mat & mat, const json::value & val) { from_json(mat.x, val[0]); from_json(mat.y, val[1]); } 30 | template void from_json(linalg::mat & mat, const json::value & val) { from_json(mat.x, val[0]); from_json(mat.y, val[1]); from_json(mat.z, val[2]); } 31 | template void from_json(linalg::mat & mat, const json::value & val) { from_json(mat.x, val[0]); from_json(mat.y, val[1]); from_json(mat.z, val[2]); from_json(mat.w, val[3]); } 32 | 33 | json::value to_json(const Pose &pose) { auto &p = pose.position; auto &o = pose.orientation; return json::array{to_json(p.x), to_json(p.y), to_json(p.z), to_json(o.x), to_json(o.y), to_json(o.z), to_json(o.w)}; } 34 | void from_json(Pose &pose, const json::value & val) { for (auto i : { 0,1,2 }) from_json(pose.position[i], val[i]); for (auto i : { 0,1,2,3 }) from_json(pose.orientation[i], val[3 + i]); } 35 | 36 | 37 | 38 | #endif // SANDBOX_MISC_JSON_H 39 | 40 | -------------------------------------------------------------------------------- /include/mswin.h: -------------------------------------------------------------------------------- 1 | // 2 | // mswin.h 3 | // 4 | // Create and setup of a Window for a typical MS Windows application intended for user interaction. 5 | // This file contains the OS specific common window setup and callback functionality. 6 | // This file does not include any of the opengl or directx graphics library setup, just the win32 parts. 7 | // see glwin.h or dxwin.h for subclasses that do this. 8 | // 9 | // 10 | 11 | #ifndef SANDBOX_MSWIN_H 12 | #define SANDBOX_MSWIN_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define NOMINMAX 20 | #include 21 | 22 | #include 23 | #include // For va_list, va_start, ... 24 | #include // For vsnprintf 25 | 26 | #include "geometric.h" 27 | 28 | #define VERIFY (assert(0),throw(std::exception((std::string(__FILE__) + ":" + std::to_string(__LINE__)).c_str())),1) 29 | 30 | 31 | class MSWin // parent class for DXWin and GLWin, abstract class for the common 3D usages and win32 gui calls support(separated from any dx or opengl) 32 | { 33 | public: 34 | HWND hWnd; 35 | int2 res; 36 | int mousewheel; // if and how much its been rolled up/down this frame 37 | int2 mousepos; 38 | int2 mousepos_previous; 39 | float2 dmouse = { 0,0 }; 40 | float3 MouseVector; // 3D direction mouse points 41 | float3 OldMouseVector; 42 | int MouseState; // true iff left button down 43 | float ViewAngle; 44 | bool downevent; 45 | bool centermouse = false; 46 | bool centered_last_frame = false; 47 | bool focus = true; 48 | 49 | RECT window_inset; // the extra pixels windows needs for its borders on windowed windows. 50 | std::function keyboardfunc; 51 | std::function preshutdown = []() {}; 52 | std::function reshape = [](int,int) {}; 53 | 54 | float aspect_ratio() { return (float)res.x / (float)res.y; } 55 | void ComputeMouseVector() 56 | { 57 | OldMouseVector = MouseVector; 58 | float spread = (float)tan(ViewAngle / 2 * 3.14 / 180); 59 | float y = spread * ((res.y - mousepos.y) - res.y / 2.0f) / (res.y / 2.0f); 60 | float x = spread * (mousepos.x - res.x / 2.0f) / (res.y / 2.0f); 61 | MouseVector = normalize(float3(x, y, -1)); 62 | } 63 | MSWin(const char *title, int2 res) :res(res), mousepos(0, 0), MouseState(0), mousewheel(0), ViewAngle(60.0f), reshape([this](int x, int y) {this->res = { x,y }; })//, keyboardfunc([](int, int, int){}) 64 | { 65 | } 66 | // virtual LONG WINAPI MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0; // since we override 67 | 68 | void CreateMSWindow(const char* title, int2 res, int2 win_position = { 100,100 }) 69 | { 70 | WNDCLASSA wc; // force non-unicode16 version using 'A' suffix 71 | wc.style = CS_OWNDC; 72 | wc.lpfnWndProc = (WNDPROC)MsgProcG; // the global winproc 73 | wc.cbClsExtra = 0; 74 | wc.cbWndExtra = 0; 75 | wc.hInstance = GetModuleHandleA(NULL); // hInstance; 76 | wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); 77 | wc.hCursor = LoadCursor(NULL, IDC_ARROW); 78 | wc.hbrBackground = NULL; 79 | wc.lpszMenuName = NULL; 80 | wc.lpszClassName = "SANDBOX"; 81 | 82 | if (!RegisterClassA(&wc)) 83 | throw("RegisterClassA() failed: Cannot register window class."); // supposedly should only register the window class once 84 | 85 | SetRect(&window_inset, 0, 0, 0, 0); 86 | AdjustWindowRect(&window_inset, WS_OVERLAPPEDWINDOW, 0); 87 | this->hWnd = CreateWindowA("SANDBOX", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 88 | //rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 89 | win_position.x + window_inset.left, win_position.y + window_inset.top, res.x + window_inset.right - window_inset.left, res.y + window_inset.bottom - window_inset.top, 90 | NULL, NULL, wc.hInstance, this); // force non-unicode16 non-wchar version of Windows's CreateWindow 91 | 92 | if (hWnd == NULL) 93 | throw("CreateWindow() failed: Cannot create a window."); 94 | } 95 | 96 | static LRESULT WINAPI MsgProcG(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 97 | { 98 | if (msg == WM_NCCREATE) 99 | SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)(reinterpret_cast(lParam)->lpCreateParams)); // grab my pointer passed into createwindow 100 | auto w = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); 101 | return (w) ? w->MsgProc(hWnd, msg, wParam, lParam) : DefWindowProc(hWnd, msg, wParam, lParam); 102 | } 103 | 104 | LONG WINAPI MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 105 | { 106 | auto fixnbits = [](int d) { return (d & 1 << 15) ? d - (1 << 16) : d; }; 107 | auto take_mouse_position_from_lparam = [lParam, fixnbits]() ->int2 { return int2(fixnbits(LOWORD(lParam)), fixnbits(HIWORD(lParam))); }; 108 | switch (uMsg) { 109 | case WM_CHAR: 110 | switch (wParam) { 111 | case 27: /* ESC key */ 112 | if (preshutdown) 113 | preshutdown(); 114 | PostQuitMessage(0); 115 | break; 116 | } 117 | if (keyboardfunc) 118 | keyboardfunc(wParam, mousepos.x, mousepos.y); // to match glut's api, add the x and y. 119 | return 0; 120 | 121 | case WM_LBUTTONDOWN: 122 | SetCapture(hWnd); // set the capture to get mouse moves outside window 123 | mousepos_previous = mousepos = take_mouse_position_from_lparam(); 124 | ComputeMouseVector(); 125 | OldMouseVector = MouseVector; // for touch devices to avoid unwanted snappings 126 | downevent = 1; 127 | MouseState = 1; 128 | return 0; 129 | 130 | case WM_LBUTTONUP: 131 | mousepos = take_mouse_position_from_lparam(); 132 | ComputeMouseVector(); 133 | MouseState = 0; 134 | ReleaseCapture(); 135 | return 0; 136 | 137 | case WM_MOUSEMOVE: 138 | mousepos = take_mouse_position_from_lparam(); 139 | ComputeMouseVector(); 140 | return 0; 141 | case WM_MOUSEWHEEL: 142 | //shiftdown = (wParam&MK_SHIFT) ? 1 : 0; ctrldown = (wParam&MK_CONTROL) ? 1 : 0; 143 | mousewheel += GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA; 144 | return 0; 145 | case WM_SIZE: 146 | if(reshape) 147 | reshape(LOWORD(lParam), HIWORD(lParam)); 148 | PostMessage(hWnd, WM_PAINT, 0, 0); 149 | return 0; 150 | case WM_SETFOCUS: 151 | focus = 1; 152 | break; 153 | case WM_KILLFOCUS: 154 | focus = 0; 155 | break; 156 | case WM_CLOSE: 157 | if (preshutdown) 158 | preshutdown(); 159 | PostQuitMessage(0); 160 | return 0; 161 | } 162 | return DefWindowProc(hWnd, uMsg, wParam, lParam); 163 | } 164 | 165 | 166 | bool WindowUp() 167 | { 168 | dmouse = { 0,0 }; // only used if mouse is being centered each frame 169 | downevent = 0; 170 | mousewheel = 0; // reset to 0 each frame 171 | mousepos_previous = mousepos; 172 | OldMouseVector = MouseVector; 173 | MSG msg; // Windows message 174 | while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) { 175 | if (GetMessage(&msg, hWnd, 0, 0)) { 176 | TranslateMessage(&msg); 177 | DispatchMessage(&msg); 178 | } 179 | else 180 | { 181 | if (preshutdown) 182 | preshutdown(); 183 | return false; 184 | } 185 | } 186 | 187 | if (centermouse && focus) { 188 | RECT rect; 189 | RECT crect; 190 | POINT pt; 191 | GetWindowRect(hWnd, &rect); 192 | GetClientRect(hWnd, &crect); 193 | GetCursorPos(&pt); 194 | if (1) // (windowed) 195 | { 196 | rect.left -= window_inset.left; // todo: look into the function: ScreenToClient(hwnd,point) 197 | rect.top -= window_inset.top; 198 | } 199 | if (centered_last_frame) 200 | { 201 | dmouse.x = (float)(pt.x - rect.left - (res.x / 2)) / (res.x / 2.0f); 202 | dmouse.y = -(float)(pt.y - rect.top - (res.y / 2)) / (res.y / 2.0f); 203 | } 204 | else 205 | dmouse = { 0,0 }; 206 | SetCursorPos(res.x / 2 + rect.left, res.y / 2 + rect.top); 207 | MouseVector = float3(0, 0, -1); 208 | centered_last_frame = 1; 209 | } 210 | else 211 | { 212 | centered_last_frame = 0; 213 | } 214 | 215 | return true; 216 | } 217 | 218 | }; 219 | 220 | // see dxwin.h for usage such as: 221 | // class DXWin : public MSWin 222 | 223 | 224 | #endif //SANDBOX_MSWIN_H 225 | -------------------------------------------------------------------------------- /jointdrive/jointdrive.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // JointDrive - sample showing powered ragdoll rigidbody physics 3 | // 4 | // Animation influences the angular drive which is the desired relative orientation of two jointed bodies. 5 | // The physics simulation tries to put the rigidbodies in the desired pose by applying up to the allowable torque on a joint. 6 | // This sample uses a generated circular animation for the upper limbs to follow the path of a cone. 7 | // Typically one would use interpolated animation keyframe to set the joint drive. 8 | // 9 | // this sample is a stripped down reimplementation from original spider seen in Teeter 2007 (http://melax.github.io/minigames/) 10 | // 11 | 12 | #include 13 | #include 14 | #include // to quickly make a box 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | // a simple 6 legged creature with boxes for bones 21 | // note that typing numbers in code is the absolute worst way to create content. 22 | // 23 | float3 bodysizes[] = { // box radius 24 | { 0.25f, 0.50f, 0.10f }, // torso 25 | { 0.25f, 0.05f, 0.05f }, // limb upper bones 26 | { 0.25f, 0.05f, 0.05f }, 27 | { 0.25f, 0.05f, 0.05f }, 28 | { 0.25f, 0.05f, 0.05f }, 29 | { 0.25f, 0.05f, 0.05f }, 30 | { 0.25f, 0.05f, 0.05f }, 31 | { 0.05f, 0.05f, 0.25f }, // limb lower bones 32 | { 0.05f, 0.05f, 0.25f }, 33 | { 0.05f, 0.05f, 0.25f }, 34 | { 0.05f, 0.05f, 0.25f }, 35 | { 0.05f, 0.05f, 0.25f }, 36 | { 0.05f, 0.05f, 0.25f }, 37 | }; 38 | struct 39 | { 40 | int b0, b1; // body0 and body1 (parent and child) indices 41 | float a; // multiplier to generated animation 42 | float3 p0, p1; // attachment points 43 | } joints[]= 44 | { 45 | { 0, 1, 0.2f, { 0.25f, -0.5f, 0 }, { -0.25f, 0, 0 } }, // attach upper limbs to torso 46 | { 0, 2, -0.2f, { 0.25f, 0.0f, 0 }, { -0.25f, 0, 0 } }, 47 | { 0, 3, 0.2f, { 0.25f, 0.5f, 0 }, { -0.25f, 0, 0 } }, 48 | { 0, 4, 0.2f, { -0.25f, -0.5f, 0 }, { 0.25f, 0, 0 } }, 49 | { 0, 5, -0.2f, { -0.25f, 0.0f, 0 }, { 0.25f, 0, 0 } }, 50 | { 0, 6, 0.2f, { -0.25f, 0.5f, 0 }, { 0.25f, 0, 0 } }, 51 | { 1, 7, 0.0f, { 0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, // attaches lower limb to corresponding upper limb 52 | { 2, 8, 0.0f, { 0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, 53 | { 3, 9, 0.0f, { 0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, 54 | { 4, 10, 0.0f, { -0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, 55 | { 5, 11, 0.0f, { -0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, 56 | { 6, 12, 0.0f, { -0.25f, 0, 0 } ,{ 0, 0 ,0.25f } }, 57 | }; 58 | 59 | 60 | std::vector genboxverts(float3 r){std::vector verts; for (auto z : { -1.0f, 1.0f }) for (auto y : { -1.0f, 1.0f }) for (auto x : { -1.0f, 1.0f }) verts.push_back(float3(x,y,z)*r); return verts;} 61 | 62 | int main(int argc, const char *argv[]) try 63 | { 64 | std::vector rbs; 65 | for (auto const &b : bodysizes) 66 | { 67 | auto verts = genboxverts(b); 68 | auto tris = calchull(verts, 8); 69 | rbs.push_back(RigidBody({ Shape(verts, tris) }, float3(0, 0, 0))); 70 | } 71 | rbscalemass(&rbs[0], 5.0f); // make torso heavier than limb bones 72 | rbs[0].position.z = 1.0f; // lift a meter off the ground. 73 | DXWin mywin("Joint Drive - powered rag doll model", { 800,600 }); 74 | std::vector meshes; 75 | for (auto &rb : rbs) 76 | { 77 | meshes.push_back(MeshSmoothish(rb.shapes[0].verts, rb.shapes[0].tris)); // 1 shape each is known 78 | rb.damping = 0.8f; //rb.gravscale = 0; 79 | } 80 | for (auto &joint : joints) 81 | { 82 | rbs[joint.b0].ignore.push_back(&rbs[joint.b1]); 83 | rbs[joint.b1].ignore.push_back(&rbs[joint.b0]); 84 | rbs[joint.b1].position = rbs[joint.b0].pose() * joint.p0 - qrot(rbs[joint.b1].orientation,joint.p1); 85 | } 86 | 87 | WingMesh ground_wm = WingMeshBox({ -5, -5, -2.0f }, { 5, 5, -1.0f }); 88 | auto ground = MeshFlatShadeTex(ground_wm.verts, WingMeshTris(ground_wm)); 89 | ground.hack = { 0.25f, 0.75f, 0.25f, 1 }; 90 | 91 | Pose camera = { { 0, -8, 0 }, normalize(float4(0.9f, 0, 0, 1)) }; // where we view the rendered scene from. 92 | float time = 0; // our global clock, used to generate the circular animation for upper limbs to follow 93 | float torquelimit = 38.0f; // how much torque we let each joint apply each frame 94 | 95 | while (mywin.WindowUp()) 96 | { 97 | time += 0.06f; 98 | 99 | std::vector angulars; 100 | std::vector linears; 101 | for (auto const &joint : joints) 102 | { 103 | Append(linears, ConstrainPositionNailed(&rbs[joint.b0], joint.p0, &rbs[joint.b1], joint.p1)); 104 | Append(angulars, ConstrainAngularDrive(&rbs[joint.b0], &rbs[joint.b1], (float4(0, joint.a*cos(time), joint.a*sin(time), sqrt(1.0f - joint.a*joint.a))), torquelimit)); 105 | } 106 | PhysicsUpdate(Addresses(rbs), linears, angulars, { &ground_wm.verts }); 107 | 108 | for (unsigned int i = 0; i < rbs.size(); i++) 109 | meshes[i].pose = rbs[i].pose(); 110 | 111 | mywin.RenderScene(camera, Append(Addresses(meshes), std::vector({ &ground }))); 112 | } 113 | return 0; 114 | } 115 | catch (std::exception e) 116 | { 117 | MessageBoxA(GetActiveWindow(), e.what(), "FAIL", 0); 118 | return -1; 119 | } 120 | 121 | 122 | -------------------------------------------------------------------------------- /jointdrive/jointdrive.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {1468EA6D-654B-4C8B-8442-1D123601C08D} 21 | Win32Proj 22 | jointdrive 23 | 24 | 25 | 26 | Application 27 | true 28 | v140 29 | NotSet 30 | 31 | 32 | Application 33 | false 34 | v140 35 | true 36 | NotSet 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | true 50 | $(ProjectDir)\ 51 | $(ProjectName)_$(Configuration) 52 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 53 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 54 | 55 | 56 | false 57 | $(ProjectDir)\ 58 | $(ProjectName)_$(Configuration) 59 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 60 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 61 | 62 | 63 | 64 | 65 | 66 | Level3 67 | Disabled 68 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 69 | 70 | 71 | Console 72 | true 73 | 74 | 75 | 76 | 77 | Level3 78 | 79 | 80 | MaxSpeed 81 | true 82 | true 83 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 84 | 85 | 86 | Console 87 | true 88 | true 89 | true 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /ploidfit/ploidfit.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {1FC1901A-F611-4B9E-8A34-60409E14FCA0} 23 | ploidfit 24 | 25 | 26 | 27 | Application 28 | true 29 | v140 30 | NotSet 31 | 32 | 33 | Application 34 | false 35 | v140 36 | true 37 | NotSet 38 | 39 | 40 | Application 41 | true 42 | v140 43 | MultiByte 44 | 45 | 46 | Application 47 | false 48 | v140 49 | true 50 | MultiByte 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 72 | $(ProjectDir)\ 73 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 74 | $(ProjectName)_$(Configuration) 75 | 76 | 77 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 78 | $(ProjectDir)\ 79 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 80 | $(ProjectName)_$(Configuration) 81 | 82 | 83 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 84 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 85 | $(ProjectName)_$(Configuration)_$(Platform) 86 | $(ProjectDir)\ 87 | 88 | 89 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 90 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 91 | $(ProjectName)_$(Configuration)_$(Platform) 92 | $(ProjectDir)\ 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | true 99 | 100 | 101 | true 102 | 103 | 104 | 105 | 106 | Level3 107 | Disabled 108 | true 109 | 110 | 111 | true 112 | 113 | 114 | 115 | 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | true 121 | 122 | 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | MaxSpeed 132 | true 133 | true 134 | true 135 | 136 | 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /remove_temp_files.sh: -------------------------------------------------------------------------------- 1 | rm -r obj/ 2 | rm */*.pdb 3 | rm */*.ipdb 4 | rm */*.iobj 5 | rm */*.ilk 6 | rm */*.filters 7 | rm */*.user 8 | rm *.sdf 9 | 10 | 11 | -------------------------------------------------------------------------------- /test_reflect/test_reflect.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // test html reflection - browser html form based gui 3 | // 4 | // no debugger? no gui? no problem! 5 | // rather than integrating a scripting language, command console, or adding gui elements to a small 6 | // opengl program, all various tweakable parameters and data is put in a single tuple and 7 | // exposed through a generated html form based web page. 8 | // this exploits the same unobtrusive visit_fields() mechanism used for json serialization and sterling's other 9 | // gui component generation system. 10 | // the program opens up a socket, effectively becoming a web server, 11 | // and listens for requests and reacts accordingly. 12 | // from the browser it is possible to modify various runtime settings including exposed data for 13 | // objects in the application (in this case a simple 2D polygon object). 14 | // 15 | 16 | #define NOMINMAX 17 | #include 18 | #include 19 | 20 | #include "../include/misc_image.h" 21 | #include "../include/geometric.h" 22 | #include "../include/html_reflect.h" 23 | 24 | #include "../include/json.h" 25 | #include "../include/misc_json.h" 26 | #include "../include/glwin.h" // in order to provide some simple example visuals that can be tweaked in html-form 27 | 28 | template void visit_fields(int3 &v, F f) { f("x", v.x); f("y", v.y); f("z", v.z); } 29 | template void visit_fields(float3 &v, F f) { f("x", v.x); f("y", v.y); f("z", v.z); } 30 | template void visit_fields(float2 &v, F f) { f("x", v.x); f("y", v.y); } 31 | template void visit_fields(int2 &v, F f) { f("x", v.x); f("y", v.y); } 32 | struct RuntimeParams 33 | { 34 | bool continue_execution; 35 | int connections_seen, frame_id; 36 | std::string helpstring; 37 | }; 38 | template void visit_fields(RuntimeParams &s, F f) 39 | { 40 | f("continue_execution", s.continue_execution); 41 | f("connections_seen" , s.connections_seen ); 42 | f("frame_id", s.frame_id); 43 | f("helpstring", s.helpstring); 44 | } 45 | 46 | struct PolygonObject 47 | { 48 | std::vector verts; // just positions 49 | float3 color; 50 | float spin; 51 | float angle; 52 | template void visit_fields(F f) { f("verts", verts); f("color", color);f("spin", spin), f("angle",angle );} 53 | }; 54 | 55 | 56 | 57 | struct // anonymous has to be global struct since local struct/class cant have member templates in msvc2015 58 | { 59 | float red, green, blue; 60 | template void visit_fields(F f) { f("red", red);f("green", green);f("blue", blue); } 61 | } clear_color = { 0.0f,0.0f, 0.25f}; 62 | 63 | struct AnotherTestStruct // just to show some more examples of reflection 64 | { 65 | float a, b; 66 | int3 v; 67 | std::vector nums; 68 | struct { int c, d; template void visit_fields(F f) { f("c", c);f("d", d); } } nested_member; 69 | template void visit_fields(F f) { f("a", a); f("b", b, float2(0, 1)); f("v", v); f("nums", nums); f("nested_member", nested_member); } 70 | } more_test_cases = { 13,17,{ 97,98,99 } ,{ 9,8,7,6 } ,{1024,1025 }}; 71 | 72 | 73 | int main(int argc, char *argv[]) try 74 | { 75 | 76 | Image image({ 256,256 }); 77 | for (auto p : rect_iteration(image.dim())) 78 | image.pixel(p) = byte3(p.x, p.y, 128); 79 | SOCKET sock = start_server(12345); 80 | 81 | PolygonObject my_polygon = { { { -0.4f, -0.3f, 0.0f },{ 0.4f, -0.3f, 0.0f },{ 0.0f, 0.5f, 0.0f } },{ 1.0f,0.0f,0.0f } , 0.1f,0.0f }; 82 | RuntimeParams runtime_settings = { true,0,0, "tweak various runtime parameters from your browser!"}; 83 | bool use_meta_refresh = false; 84 | int3 test_int3 = { 100,200,300 }; 85 | bool extra_bool = false; 86 | int extra_int = 202; 87 | auto unused = std::tie(extra_bool, "extra_bool", extra_int, "extra_int", test_int3, "test_int3", more_test_cases,"more_test_cases"); 88 | auto all_my_params = std::tie(runtime_settings, "runtime_settings" , clear_color, "clear_color" , my_polygon,"my_polygon" , use_meta_refresh,"use_meta_refresh", unused,"unused" ); 89 | 90 | GLWin glwin("enter url http://localhost:12345 in your browser"); 91 | std::cout << "open up a browser and enter URL: http://localhost:12345/ " << std::endl; 92 | 93 | while (runtime_settings.continue_execution && glwin.WindowUp()) 94 | { 95 | runtime_settings.connections_seen+= 96 | reflection_service(sock,all_my_params,[&image,&glwin](SOCKET socket, std::string command) 97 | { 98 | if (command == "pic") 99 | { 100 | http_reply_image(socket, image); 101 | return true; 102 | } 103 | else if (command == "screenshot") 104 | { 105 | Image cimage(glwin.res); 106 | glReadPixels(0, 0, glwin.res.x, glwin.res.y, GL_RGB, GL_UNSIGNED_BYTE, cimage.raster.data()); 107 | FlipV(cimage.raster, cimage.dim()); 108 | http_reply_image(socket, cimage); 109 | return true; 110 | } 111 | return false; 112 | }); 113 | glClearColor(clear_color.red,clear_color.green,clear_color.blue,0.0); 114 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 115 | glPushAttrib(GL_ALL_ATTRIB_BITS); 116 | glMatrixMode(GL_PROJECTION); 117 | glPushMatrix(); 118 | glLoadIdentity(); 119 | glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 120 | glMatrixMode(GL_MODELVIEW); 121 | glPushMatrix(); 122 | glLoadIdentity(); 123 | 124 | // animate and update our 'game' object: 125 | glRotatef(my_polygon.angle += my_polygon.spin, 0, 0, 1); 126 | glBegin(GL_TRIANGLES); 127 | glColor3fv(my_polygon.color); 128 | for(auto &p:my_polygon.verts) 129 | glVertex3fv(p); 130 | glEnd(); 131 | 132 | glMatrixMode(GL_PROJECTION); 133 | glPopMatrix(); 134 | glMatrixMode(GL_MODELVIEW); 135 | glPopMatrix(); 136 | glColor3f(1, 1, 0.5f); 137 | glwin.PrintString({ 0,0 }, "%s", runtime_settings.helpstring.c_str()); 138 | glPopAttrib(); 139 | glwin.SwapBuffers(); 140 | 141 | runtime_settings.frame_id++; 142 | } 143 | } 144 | catch (const char *c) 145 | { 146 | MessageBox(GetActiveWindow(), "FAIL", c, 0); 147 | } 148 | catch (std::exception e) 149 | { 150 | MessageBox(GetActiveWindow(), "FAIL", e.what(), 0); 151 | } 152 | -------------------------------------------------------------------------------- /test_reflect/test_reflect.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {865E19A4-105C-4011-9EBD-14189B26FBEA} 23 | Win32Proj 24 | test_reflect 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | NotSet 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | NotSet 39 | 40 | 41 | Application 42 | true 43 | v140 44 | NotSet 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | NotSet 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | false 73 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 74 | $(ProjectName)_$(Configuration)_$(Platform) 75 | $(ProjectDir) 76 | 77 | 78 | true 79 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 80 | $(ProjectName)_$(Configuration)_$(Platform) 81 | $(ProjectDir) 82 | 83 | 84 | true 85 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 86 | $(ProjectName)_$(Configuration)_$(Platform) 87 | $(ProjectDir) 88 | 89 | 90 | false 91 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 92 | $(ProjectName)_$(Configuration)_$(Platform) 93 | $(ProjectDir) 94 | 95 | 96 | 97 | Level3 98 | 99 | 100 | MaxSpeed 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | 105 | 106 | Console 107 | true 108 | true 109 | 110 | 111 | 112 | 113 | 114 | 115 | Level3 116 | Disabled 117 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | 119 | 120 | Console 121 | 122 | 123 | 124 | 125 | 126 | 127 | Level3 128 | Disabled 129 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | 131 | 132 | Console 133 | 134 | 135 | 136 | 137 | Level3 138 | 139 | 140 | MaxSpeed 141 | true 142 | true 143 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 144 | 145 | 146 | Console 147 | true 148 | true 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /testbool/testbool.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {145BBE4D-EA4A-4903-81BB-50F63606A36B} 23 | testbool 24 | 25 | 26 | 27 | Application 28 | true 29 | v140 30 | NotSet 31 | 32 | 33 | Application 34 | false 35 | v140 36 | true 37 | NotSet 38 | 39 | 40 | Application 41 | true 42 | v140 43 | NotSet 44 | 45 | 46 | Application 47 | false 48 | v140 49 | true 50 | NotSet 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | $(ProjectDir)\ 72 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 73 | $(ProjectName)_$(Configuration) 74 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 75 | 76 | 77 | $(ProjectDir)\ 78 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 79 | $(ProjectName)_$(Configuration) 80 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 81 | 82 | 83 | $(ProjectDir)\ 84 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 85 | $(ProjectName)_$(Configuration)_$(Platform) 86 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 87 | 88 | 89 | $(ProjectDir)\ 90 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 91 | $(ProjectName)_$(Configuration)_$(Platform) 92 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 93 | 94 | 95 | 96 | Level3 97 | Disabled 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | true 106 | 107 | 108 | 109 | 110 | Level3 111 | MaxSpeed 112 | true 113 | true 114 | true 115 | 116 | 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | true 128 | 129 | 130 | true 131 | true 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /testbsp/testbsp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {CBFA606C-2813-4FAB-AC18-F3F830FADEDD} 15 | Win32Proj 16 | testbsp 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectName)_$(Configuration) 46 | $(ProjectDir)\ 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectName)_$(Configuration) 53 | $(ProjectDir)\ 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /testcloth/testcloth.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // testcloth - small sample using point-mass spring system 3 | // 4 | // The spring network is force based and uses implicit integration to handle stiff springs. 5 | // See springnet.h for additional information. 6 | // 7 | // debug build might be a bit slow. Use release when possible. 8 | // 9 | 10 | #include 11 | #include // std::max_element 12 | #include // std::tolower 13 | 14 | // in project properties, add "../include" to the vc++ directories include path 15 | #include "springnet.h" 16 | #include "glwin.h" // minimal opengl for windows setup wrapper 17 | 18 | bool g_wireframe = 0; 19 | 20 | 21 | void InitTex() // create a checkerboard texture 22 | { 23 | const int imagedim = 16; 24 | byte3 checker_image[imagedim * imagedim]; 25 | for (int y = 0; y < imagedim; y++) 26 | for (int x = 0; x < imagedim; x++) 27 | checker_image[y * imagedim + x] = ((x + y) % 2) ? byte3(0, 255, 255) : byte3(0, 127, 127); 28 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 29 | glEnable(GL_TEXTURE_2D); 30 | glBindTexture(GL_TEXTURE_2D, 0); 31 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 32 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 33 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // use nearest to see actual uninterpolated image pixels 34 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 35 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imagedim, imagedim, 0, GL_RGB, GL_UNSIGNED_BYTE, checker_image); 36 | } 37 | 38 | 39 | void OnKeyboard(unsigned char key, int x, int y) 40 | { 41 | switch (std::tolower(key)) 42 | { 43 | case ' ': 44 | break; 45 | case 27: // ESC 46 | case 'q': 47 | exit(0); 48 | break; 49 | case 'w': 50 | g_wireframe = !g_wireframe; 51 | break; 52 | default: 53 | std::cout << "unassigned key (" << (int)key << "): '" << key << "'\n"; 54 | break; 55 | } 56 | } 57 | 58 | 59 | 60 | // int main(int argc, char *argv[]) 61 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,LPSTR lpszCmdLine, int nCmdShow) 62 | { 63 | SpringNetwork cloth = SpringNetworkCreateRectangular(17, 17, 1.0f); 64 | for (auto &v : cloth.X) v.z -= 1.75f; // put cloth object at 0,0,-1.5 region, view/camera will be at origin. 65 | cloth.gravity = float3(0, -10.0f, 0); // normally i perfer z-up for any environment or "world" space. 66 | cloth.dt = 0.033f; // speed it up a bit (regardless of fps, each frame advances cloth 1/30th of a second instead of just 1/60th). 67 | GLWin glwin("TestCloth sample"); 68 | glwin.keyboardfunc = OnKeyboard; 69 | InitTex(); // just initializes a checkerboard default texture 70 | int selection = 0; // index of currently selected point 71 | while (glwin.WindowUp()) 72 | { 73 | int point_to_unpin = -1; // if we temporarily move pin a point, we have to unpin it later after simulation. 74 | if (!glwin.MouseState) // on mouse drag 75 | { 76 | float3 v = glwin.MouseVector; // assumes camera at 0,0,0 looking down -z axis 77 | selection = std::max_element(cloth.X.begin(), cloth.X.end(), [&v](const float3&a, const float3&b)->bool{return dot(v, normalize(a)) < dot(v, normalize(b)); })- cloth.X.begin(); 78 | } 79 | else 80 | { 81 | if (!cloth.PointStatusSet(selection, -1)) 82 | cloth.PointStatusSet((point_to_unpin = selection), 1); 83 | const float3 &v = glwin.MouseVector; 84 | cloth.X[selection] = v * (dot(v, cloth.X[selection]) / dot(v, v) *(1.0f + glwin.mousewheel*0.1f)); 85 | } 86 | 87 | cloth.Simulate(); 88 | 89 | if(point_to_unpin >=0) 90 | cloth.PointStatusSet(point_to_unpin, 0); 91 | 92 | glPushAttrib(GL_ALL_ATTRIB_BITS); 93 | glViewport(0, 0, glwin.res.x,glwin.res.y); // Set up the viewport 94 | glClearColor(0.1f, 0.1f, 0.15f, 1); 95 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 96 | 97 | glMatrixMode(GL_PROJECTION); 98 | glPushMatrix(); 99 | glLoadIdentity(); 100 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.01, 10); 101 | 102 | glMatrixMode(GL_MODELVIEW); 103 | glPushMatrix(); 104 | gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); 105 | 106 | glEnable(GL_DEPTH_TEST); 107 | glDisable(GL_TEXTURE_2D); 108 | glPointSize(3); 109 | glBegin(GL_POINTS); 110 | for (unsigned int i = 0; i < cloth.X.size(); i++ ) 111 | glColor3f((i==selection)?1.0f:0 , 1, 0.5f), glVertex3fv(cloth.X[i]); 112 | glEnd(); 113 | 114 | if (g_wireframe) 115 | { 116 | glBegin(GL_LINES); 117 | SpringNetworkDrawSprings(&cloth, [](const float3 &a, const float3 &b, const float3 &c){glColor3fv(c); glVertex3fv(a); glVertex3fv(b); }); 118 | glColor3f(1, 0, 0); 119 | glEnd(); 120 | } 121 | else 122 | { 123 | glEnable(GL_TEXTURE_2D); 124 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 125 | glEnable(GL_POLYGON_OFFSET_FILL); 126 | glPolygonOffset(1., 1. / (float)0x10000); 127 | glEnable(GL_LIGHTING); 128 | glEnable(GL_LIGHT0); 129 | glColor3f(0.5f, 0.5f, 0.5f); 130 | glBegin(GL_QUADS); 131 | for (auto const & q: cloth.quads) 132 | { 133 | for (int c = 0; c <4; c++) 134 | glTexCoord2f(q[c]%17/16.0f,q[c]/17/16.0f),glNormal3fv(cloth.N[q[c]]), glVertex3fv(cloth.X[q[c]]); 135 | } 136 | glEnd(); 137 | } 138 | 139 | // Restore state 140 | glPopMatrix(); //should be currently in modelview mode 141 | glMatrixMode(GL_PROJECTION); 142 | glPopMatrix(); 143 | glPopAttrib(); 144 | glMatrixMode(GL_MODELVIEW); 145 | 146 | glwin.PrintString({ 0, 0 }, "Press ESC to quit. w toggles wireframe. "); 147 | glwin.PrintString({ 0, 1 }, "Use left mouse motion and wheel to move points."); 148 | glwin.PrintString({ 0, 2 }, "(w)ireframe %s vert selected %d", ((g_wireframe) ? "ON " : "OFF"), selection); 149 | # ifdef _DEBUG 150 | glwin.PrintString({ 2, -1 }, "Running DEBUG Version. Performance may be SLoooow.", 2, -1); 151 | # endif 152 | glwin.SwapBuffers(); 153 | } 154 | std::cout << "\n"; 155 | return 0; 156 | } 157 | 158 | -------------------------------------------------------------------------------- /testcloth/testcloth.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {000A15B7-0000-0000-0000-000000000000} 15 | Win32Proj 16 | testcloth 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /testcnn/testcnn.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // testcnn minimal program to ensure the neural network code works. 3 | // 4 | // I didn't want to bloat this repo with data files, so please download the four mnist data files and place in this directory. 5 | // look for names "train-images-idx3-ubyte". Easy to find. try the main site: http://yann.lecun.com/exdb/mnist/ 6 | // There are many copies on the internet including a handful of other github repos for example: https://github.com/wichtounet/mnist.git . 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include // for messagebox if an error is thrown 16 | 17 | // the mnist dataset is the standard nn benchmark and extensively studied. 18 | // A good test to ensure any cnn code is behaving as expected. 19 | // There's not much point writing a general purpose parser that properly 20 | // decodes the other-byte-ordered header part to extract count,width,height 21 | // for the idx{1,3} format when there are only 2 files on the planet using this format that even matter. 22 | // so i just seek to the start position, and read the well known data 28x28x60000 block in uchar format. 23 | // 24 | std::vector> mnist_read_images(std::string filename,int count) 25 | { 26 | std::ifstream in(filename, std::istream::binary); 27 | if (!in.is_open()) throw("unable to open mnist dataset, please download this if you haven't already"); 28 | in.seekg(16); 29 | std::vector buf(count * 28 * 28); 30 | in.read((char*) buf.data(), buf.size()); 31 | auto buff = Transform(buf, [](unsigned char s) {return s / 255.0f;}); 32 | std::vector> images(count); 33 | for (int i = 0;i < count;i++) 34 | images[i] = std::vector(buff.data() + i * 28 * 28, buff.data() + (i + 1) * 28 * 28); 35 | return images; 36 | } 37 | std::vector> mnist_read_labels(std::string filename, int count) 38 | { 39 | std::ifstream in(filename, std::istream::binary); 40 | if (!in.is_open()) throw("unable to open mnist dataset, please download this if you haven't already"); 41 | in.seekg(8); 42 | std::vector buf(count ); 43 | in.read((char*)buf.data(), buf.size()); 44 | std::vector> labels(count); 45 | for (int i = 0;i < count;i++) 46 | { 47 | labels[i] = std::vector(10, 0.0f); 48 | labels[i][buf[i]] = 1.0f; 49 | } 50 | return labels; 51 | } 52 | int minst_best(std::vector &v) { assert(v.size() == 10); int best = 0; for (int j = 0;j < 10;j++) if (v[j]>v[best]) best = j; return best; } 53 | 54 | class progress_report 55 | { 56 | typedef std::chrono::high_resolution_clock clock; 57 | const char * msg; int n, pct; clock::time_point t0; 58 | public: 59 | progress_report(const char * msg, int n) : msg(msg), n(n), pct(), t0(clock::now()) { std::cout << msg << "... 0%"; } 60 | void update(int i) 61 | { 62 | const int new_pct = (i+1)*100/n; 63 | if(new_pct == pct) return; 64 | pct = new_pct; 65 | std::cout << '\r' << msg << "... " << pct << "%"; 66 | if(pct == 100) std::cout << " in " << std::chrono::duration(clock::now() - t0).count() << " seconds" << std::endl; 67 | } 68 | }; 69 | 70 | void mnist() 71 | { 72 | std::cout << "mnist\n"; 73 | std::cout << "be patient this may take minutes.\n"; 74 | # ifdef _DEBUG 75 | std::cout << "Suggest you use 'Release' mode instead of 'Debug'.\n"; 76 | # endif 77 | std::cout << "should get close to 99% correctness\n"; 78 | auto train_in = mnist_read_images("train-images-idx3-ubyte", 60000); 79 | auto train_lb = mnist_read_labels("train-labels-idx1-ubyte", 60000); 80 | auto test_in = mnist_read_images("t10k-images-idx3-ubyte" , 10000); 81 | auto test_lb = mnist_read_labels("t10k-labels-idx1-ubyte" , 10000); 82 | 83 | // I just used a typical cnn setup here. 84 | // Feel free to try other configurations 85 | 86 | CNN cnn({}); 87 | cnn.layers.push_back(new CNN::LConv({ 28,28,1 }, { 5,5,1,16 }, { 24,24,16 })); 88 | cnn.layers.push_back(new CNN::LActivation(24 * 24 * 16)); 89 | cnn.layers.push_back(new CNN::LMaxPool({ 24,24,16 })); 90 | cnn.layers.push_back(new CNN::LMaxPool({ 12,12,16 })); 91 | cnn.layers.push_back(new CNN::LConv({ 6,6,16 }, { 3,3,16,64 }, { 4,4,64 })); 92 | cnn.layers.push_back(new CNN::LActivation(4 * 4 * 64)); 93 | //cnn.layers.push_back(new CNN::LMaxPool({ 8,8,256 })); 94 | cnn.layers.push_back(new CNN::LFull(4 * 4 * 64, 64)); 95 | cnn.layers.push_back(new CNN::LActivation(64)); 96 | cnn.layers.push_back(new CNN::LFull(64, 10)); 97 | cnn.Init(); 98 | 99 | 100 | for (int e = 0; e < 20;e++) // each training epoch does an initial test followed by backprop on all 60K samples. 101 | { 102 | auto p = progress_report("Evaluating", 10000); 103 | int correct = 0; 104 | for (int i = 0;i < 10000;i++) 105 | { 106 | correct += (minst_best(cnn.Eval(test_in[i])) == minst_best(test_lb[i])); 107 | p.update(i); 108 | } 109 | std::cout << correct << " of 10000 correct\n"; 110 | 111 | p = progress_report("Training", 60000); 112 | for (int i = 0;i < 60000;i++) 113 | { 114 | cnn.Train(train_in[i], train_lb[i]); 115 | p.update(i); 116 | } 117 | } 118 | } 119 | 120 | void xor() 121 | { 122 | // typical exclusive-or test for NN: 123 | struct { 124 | std::vector input,labels; 125 | } trainset[4] = { // a,b, a^b 126 | {{ 0, 0},{ 0} }, 127 | {{ 1, 0},{ 1} }, 128 | {{ 0, 1},{ 1} }, 129 | {{ 1, 1},{ 0} }, 130 | }; 131 | CNN nn({ 2, 2, 1 }); // simple constructor takes input, hidden(s), and output. So builds two fully interconnected layers with tanh activation layers following them 132 | std::cout << "epoch mse\n--------------------\n"; 133 | for (int i = 0; i <= (1 << 20); i++) 134 | { 135 | float sse = 0.0f; // sum of square error in this case 136 | for (auto s : trainset) 137 | sse += nn.Train(s.input, s.labels); 138 | if (0 == (i&(i - 1))) // if power of 2 139 | std::cout << i << " " << sse << "\n"; 140 | } 141 | std::cout << "\n"; 142 | } 143 | 144 | void junk() 145 | { 146 | CNN::LConv cl({ 5,5,1 }, { 3,3,1,2 }, { 3,3,2 }); 147 | CNN cnn({}); 148 | cnn.layers.push_back(&cl); 149 | cnn.Init(); 150 | std::ifstream("deleteme.txt") >> cl; 151 | std::cout << "weights initial: " << cl; 152 | std::cout << "\n\n"; 153 | std::vector in(25); 154 | for (int i = 0; i < 25; i++)in[i] = (float)i; 155 | std::vector expected(18, 0.0f); 156 | auto out = cl.forward(in); 157 | std::cout << "output \n"; 158 | for (auto y : out) 159 | std::cout << y << " "; 160 | std::cout << "\n\n"; 161 | cnn.Train(in, expected); 162 | std::cout << "weights now: " << cl; 163 | std::cout << "\n\n"; 164 | 165 | for (auto v : vol_iteration({ 2,2,2 })) 166 | std::cout << v << "\n"; 167 | std::cout << "\n"; 168 | } 169 | 170 | int main(int argc, char *argv[]) try 171 | { 172 | //xor(); 173 | mnist(); 174 | 175 | std::cout << "\n"; 176 | return 0; 177 | 178 | 179 | } 180 | catch (const char *c) 181 | { 182 | std::cerr << "Program aborted: " << c << "\n"; 183 | MessageBox(GetActiveWindow(), c, "FAIL", 0); 184 | } 185 | catch (std::exception e) 186 | { 187 | std::cerr << "Program aborted: " << e.what() << "\n"; 188 | MessageBox(GetActiveWindow(), e.what(), "FAIL", 0); 189 | } 190 | -------------------------------------------------------------------------------- /testcnn/testcnn.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A158D5D9-3085-423B-86B4-A05327ED431D} 15 | Win32Proj 16 | cnn 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectName)_$(Configuration) 46 | $(ProjectDir)\ 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectName)_$(Configuration) 53 | $(ProjectDir)\ 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 63 | 64 | 65 | Console 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 78 | 79 | 80 | Console 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /testcov/testcov.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // 3D Covariance and Principal Axes 3 | // 4 | // various applications of this. 5 | // Not shown here, but one practical example of this is whole object tracking of an unknown model based on depth camera data. 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | 19 | 20 | std::default_random_engine random_number_generator; 21 | float3 vrand() // output range is from -1 to 1 22 | { 23 | auto r = [](){return std::uniform_real(-1.0f, 1.0f)(random_number_generator); }; 24 | return{ r(), r(), r() }; 25 | } 26 | float3 vrand(const float3 &scale) { return scale* vrand(); } 27 | 28 | 29 | std::vector RandomPointCloud(float3 range = float3(1.0f, 0.5f, 0.25f), int n = 30) 30 | { 31 | Pose randpose({ 1, 1, 1 }, normalize(float4(vrand(), 1.0f))); 32 | std::vector points(n); 33 | std::transform(points.begin(), points.end(), points.begin(), [&randpose, &range](const float3)->float3 {return randpose * (range*vrand()); }); // note this multiplication here not associative since scale 'range' is componentwise float3 instead of a matrix 34 | return points; 35 | } 36 | 37 | 38 | void glAxis() 39 | { 40 | glPushAttrib(GL_ALL_ATTRIB_BITS); 41 | glLineWidth(3.0f); 42 | glBegin(GL_LINES); 43 | for (int i : {0, 1, 2}) 44 | { 45 | float3 v(0, 0, 0); 46 | v[i] = 1.0f; 47 | glColor3fv(v); 48 | glVertex3fv({ 0, 0, 0 }); 49 | glVertex3fv(v); 50 | } 51 | glEnd(); 52 | glPopAttrib(); 53 | } 54 | void glAxis(const Pose &pose) 55 | { 56 | glPushMatrix(); 57 | glMultMatrixf(pose.matrix()); 58 | glAxis(); 59 | glPopMatrix(); 60 | } 61 | 62 | std::vector gridtriangulation(int2 tess) 63 | { 64 | std::vector tris; 65 | for (int y = 0; y < tess.y - 1; y++) for (int x = 0; x < tess.x - 1; x++) 66 | { 67 | tris.push_back({ (y + 1)* tess.x + x + 0, (y + 0)* tess.x + x + 0, (y + 0)* tess.x + x + 1 }); 68 | tris.push_back({ (y + 0)* tess.x + x + 1, (y + 1)* tess.x + x + 1, (y + 1)* tess.x + x + 0 }); // note the {2,0} edge is the one that cuts across the quad 69 | } 70 | return tris; 71 | } 72 | Mesh sphere(int2 tess) 73 | { 74 | std::vector verts; 75 | for (int y = 0; y < tess.y ; y++) for (int x = 0; x < tess.x; x++) 76 | { 77 | float lat = 3.14159f * (y /(tess.y - 1.0f) - 0.5f); 78 | float lng = 3.14159f * 2.0f * x / (tess.x - 1.0f); 79 | float3 p(cos(lat)*cos(lng), cos(lat)*sin(lng), sin(lat)); 80 | float3 u(-sin(lng), cos(lng), 0); 81 | verts.push_back({ p, quatfrommat({ u, cross(p, u), p }), { x / (tess.x - 1.0f), y / (tess.y - 1.0f) } }); 82 | } 83 | return{ verts, gridtriangulation(tess), Pose(), "", { 1, 1, 1, 1 } }; 84 | } 85 | 86 | Mesh scale(Mesh m, float3 r) 87 | { 88 | auto stretch = [&r](Vertex v)->Vertex 89 | { 90 | float3 n = qzdir(v.orientation)/ r; 91 | float3 u = qxdir(v.orientation)/ r; 92 | return{ v.position* r, quatfrommat({ u, cross(n, u), n }), v.texcoord }; 93 | }; 94 | std::transform(m.verts.begin(), m.verts.end(), m.verts.begin(), stretch); 95 | return m; 96 | } 97 | Mesh ellipse(float3 r) 98 | { 99 | return scale(sphere({ 23, 17 }), r); 100 | } 101 | 102 | bool show_ellipsoid_normals = false; // just to make sure my mesh scale worked ok 103 | inline void glellipsoid(const float3 &r) // wire mesh version 104 | { 105 | auto e = ellipse(r); 106 | glBegin(GL_LINES); 107 | glColor3f(0.5f, 0.5f, 0.5f); 108 | for (auto t : e.tris) for (auto i : { 0, 1, 1, 2 }) // just draw first 2 edges since {0,2} is the diagonal that cuts across the quad 109 | glVertex3fv(e.verts[t[i]].position); 110 | glColor3f(0.0f, 0.5f, 0.5f); 111 | for (auto p : e.verts) for (auto n : { 0.0f, 0.02f }) if (show_ellipsoid_normals) // just for debugging 112 | glVertex3fv(p.position + qzdir(p.orientation)*n); 113 | glEnd(); 114 | } 115 | inline void glellipsoid(const float3 &r,const Pose &pose) { glPushMatrix(); glMultMatrixf(pose.matrix()); glellipsoid(r); glPopMatrix(); } 116 | 117 | 118 | 119 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) try 120 | { 121 | std::cout << "TestCov\n"; 122 | Pose camera = { { 0, 0, 6 }, { 0, 0, 0, 1 } }; 123 | float3 focuspoint(0, 0, 0); 124 | float3 mousevec_prev; 125 | float4 model_orientation(0, 0, 0, 1); 126 | float dt = 0.01f, t = 0; 127 | float3 *selected = NULL; 128 | float boxr = 0.025f; 129 | std::vector planes = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { -1, 0, 0, 0 }, { 0, -1, 0, 0 }, { 0, 0, -1, 0 } }; 130 | for (auto &p : planes) 131 | p.w = -boxr; 132 | std::vector points = RandomPointCloud(); 133 | 134 | GLWin glwin("Point Cloud Covariance"); 135 | glwin.keyboardfunc = [&](int key, int, int) 136 | { 137 | show_ellipsoid_normals = key == 'n' != show_ellipsoid_normals; 138 | if (key == ' ') 139 | points = RandomPointCloud(); 140 | }; 141 | while (glwin.WindowUp()) 142 | { 143 | t = t + dt; // advance our global time t is in 0..1 144 | if (t > 1.0f) 145 | t = 0.0f; 146 | 147 | // user interaction: 148 | float3 ray = qrot(camera.orientation, normalize(glwin.MouseVector)); // for mouse selection 149 | float3 v1 = camera.position + ray*100.0f; 150 | if (!glwin.MouseState) // note that we figure out what is being selected only when the mouse is up 151 | { 152 | selected = NULL; 153 | for (float3 &p : points) 154 | { 155 | if (auto h = ConvexHitCheck(planes, Pose(p, { 0, 0, 0, 1 }), camera.position, v1)) 156 | { 157 | selected = &p; 158 | v1 = h.impact; 159 | } 160 | } 161 | } 162 | else // if (glwin.MouseState) 163 | { 164 | if (!selected) 165 | camera.orientation = qmul(camera.orientation, qconj(VirtualTrackBall(float3(0, 0, 1), float3(0, 0, 0), glwin.OldMouseVector, glwin.MouseVector))); // equation is non-typical we are orbiting the camera, not rotating the object 166 | else 167 | { 168 | *selected += (qrot(camera.orientation, glwin.MouseVector) - qrot(camera.orientation, glwin.OldMouseVector)) * length(*selected-camera.position); 169 | *selected = camera.position + (*selected - camera.position) * powf(1.1f, (float)glwin.mousewheel); 170 | glwin.mousewheel = 0; 171 | } 172 | } 173 | camera.position = focuspoint + qzdir(camera.orientation)*length(camera.position - focuspoint); 174 | camera.position -= focuspoint; 175 | camera.position *= powf(1.1f, (float)glwin.mousewheel); 176 | camera.position += focuspoint; 177 | mousevec_prev = glwin.MouseVector; 178 | 179 | // Render the scene 180 | glPushAttrib(GL_ALL_ATTRIB_BITS); 181 | glViewport(0, 0, glwin.res.x, glwin.res.y); // Set up the viewport 182 | glClearColor(0.1f, 0.1f, 0.15f, 1); 183 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 184 | glMatrixMode(GL_PROJECTION); 185 | glPushMatrix(); glLoadIdentity(); 186 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.25, 250); 187 | glMatrixMode(GL_MODELVIEW); 188 | glPushMatrix(); glLoadIdentity(); 189 | glMultMatrixf(camera.inverse().matrix()); 190 | 191 | glDisable(GL_LIGHTING); 192 | glAxis(); 193 | glGridxy(4.0f); 194 | 195 | Pose pa; 196 | float3 va; 197 | std::tie(pa,va) = PrincipalAxes(points); 198 | focuspoint = pa.position; 199 | 200 | auto s2 = sqrt(va)*2.0f; // 2 * standard deviation 201 | glellipsoid(s2, pa); 202 | 203 | glPushMatrix(); glMultMatrixf(pa.matrix()); 204 | glScalef(s2.x, s2.y, s2.z); 205 | glAxis(); 206 | glScalef(-1, -1, -1); 207 | glAxis(); 208 | glPopMatrix(); 209 | 210 | glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); 211 | for(auto &p:points) 212 | glcolorbox(float3(selected==&p?boxr*1.5f:boxr), { p, pa.orientation }); 213 | 214 | glPopMatrix(); //should be currently in modelview mode 215 | glMatrixMode(GL_PROJECTION); 216 | glPopMatrix(); 217 | glMatrixMode(GL_MODELVIEW); 218 | glPopAttrib();// Restore state 219 | 220 | glwin.PrintString({ 0, 0 }, "ESC to quit. Space for new pointcloud."); 221 | glwin.PrintString({ 0, 1 }, (!selected) ? ((glwin.MouseState)?"rotate cloud":"") : "%s: %d", glwin.MouseState ? "moving" : "selected", selected - points.data()); 222 | if (show_ellipsoid_normals) 223 | glwin.PrintString({ 0, 3 }, "[n] to disable useless showing of vertex normals."); 224 | glwin.SwapBuffers(); 225 | } 226 | std::cout << "\n"; 227 | return 0; 228 | } 229 | catch (std::exception e) 230 | { 231 | MessageBoxA(GetActiveWindow(), e.what(), "FAIL", 0); 232 | return -1; 233 | } 234 | -------------------------------------------------------------------------------- /testcov/testcov.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {3259EC6C-4F5C-4CB6-A6BB-D29099CA2E0F} 15 | Win32Proj 16 | testcov 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | $(ProjectDir)\ 45 | $(ProjectName)_$(Configuration) 46 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | $(ProjectDir)\ 52 | $(ProjectName)_$(Configuration) 53 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /testdx/testdx.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "linalg.h" 3 | #include "mesh.h" 4 | #include "dxwin.h" 5 | 6 | #include "wingmesh.h" 7 | 8 | 9 | Mesh MeshFlatShadeTex(const WingMesh &m) // procedurally generate normals and texture coords mesh 10 | { 11 | return MeshFlatShadeTex(m.verts, WingMeshTris(m)); 12 | } 13 | 14 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) try // int main(int argc, char *argv[]) 15 | { 16 | DXWin dxwin("simple test of d3d render window"); 17 | 18 | WingMesh cube_wm = WingMeshCube(1.0f); 19 | WingMesh oct_wm = WingMeshDual(cube_wm, 1.4f); 20 | auto cube_mesh = MeshFlatShadeTex(cube_wm); 21 | auto oct_mesh = MeshFlatShadeTex(oct_wm); 22 | int frame = 0; 23 | bool stereo = 0; 24 | dxwin.keyboardfunc = [&](int key, int, int) 25 | { 26 | stereo = key == 's' != stereo; 27 | }; 28 | while (dxwin.WindowUp()) 29 | { 30 | frame++; 31 | float c[] = { 0.5f, 0.6f, 1.0f, 1.0f }; 32 | frame++; 33 | 34 | cube_mesh.hack = { 0.5f + 0.5f*sinf(frame*0.0002f), 1, 1, 1 }; 35 | cube_mesh.pose.orientation = { 0, 0, sinf(frame*0.0001f), cosf(frame*0.0001f) }; 36 | 37 | oct_mesh.pose = { { -2.5f, 6.3f, -0.25f }, { 0, 0, -sinf(frame*0.0001f), cosf(frame*0.0001f) } }; 38 | oct_mesh.hack = { 1, 0, 1, 1 }; 39 | 40 | (dxwin.*(stereo ? &DXWin::RenderStereo : &DXWin::RenderScene))({ { 0, -3, 2 }, normalize(float4(1, 0, 0, 2)) }, { &cube_mesh, &oct_mesh }); 41 | } 42 | } 43 | catch (const char *c) 44 | { 45 | MessageBox(GetActiveWindow(), "FAIL", c, 0); 46 | } 47 | catch (std::exception e) 48 | { 49 | MessageBox(GetActiveWindow(), "FAIL", e.what(), 0); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /testdx/testdx.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {11E44195-631D-4757-88BA-59146671D9EC} 15 | Win32Proj 16 | testdx 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /testgjk/testgjk.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A15B7BD9-DC89-4553-80E6-5140731C804C} 15 | Win32Proj 16 | testgjk 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /testhull/testhull.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include // std::tolower 5 | #include 6 | #include 7 | // in project properties, add "../include" to the vc++ directories include path 8 | 9 | #include "linalg.h" 10 | using namespace linalg::aliases; // float3, int2, float3x3 etc 11 | 12 | #include "glwin.h" // minimal opengl for windows setup wrapper 13 | #include "hull.h" 14 | 15 | 16 | std::vector g_verts; 17 | std::vector g_tris; 18 | int g_vlimit = 64; 19 | int g_cloudsize = 20; 20 | 21 | inline float randf(){ return static_cast(rand()) / static_cast(RAND_MAX); } 22 | 23 | float3 vrand(){ return {randf(),randf(),randf()}; } 24 | 25 | void Init() // creates a random point cloud and generates initial hull for it. 26 | { 27 | g_vlimit = 64; 28 | g_verts.resize(0); 29 | for (int i = 0; i < g_cloudsize; i++) 30 | g_verts.push_back(vrand() - float3(0.5f, 0.5f, 0.5f)); 31 | g_tris = ::calchull(g_verts, g_vlimit); 32 | g_vlimit = 0; 33 | for (auto t : g_tris) 34 | g_vlimit = std::max(g_vlimit, 1+ maxelem(t)); 35 | } 36 | 37 | 38 | void OnKeyboard(unsigned char key, int x, int y) 39 | { 40 | switch (std::tolower(key)) 41 | { 42 | case ' ': 43 | Init(); 44 | break; 45 | case 27: // ESC 46 | case 'q': 47 | exit(0); 48 | break; 49 | case 'w': 50 | case 's': 51 | g_vlimit+=(key=='s')?-1:1; g_vlimit = std::max(4, g_vlimit); // same point cloud, just change the max allowable number of verts to use 52 | g_tris = ::calchull(g_verts, g_vlimit); 53 | break; 54 | default: 55 | std::cout << "unassigned key (" << (int)key << "): '" << key << "'\n"; 56 | break; 57 | } 58 | } 59 | 60 | 61 | 62 | int main(int argc, char *argv[]) 63 | { 64 | std::cout << "TestMath\n"; 65 | 66 | Init(); 67 | 68 | GLWin glwin("TestHull sample"); 69 | glwin.keyboardfunc = OnKeyboard; 70 | float3 mousevec_prev; 71 | float4 model_orientation(0, 0, 0, 1); 72 | while (glwin.WindowUp()) 73 | { 74 | if (glwin.MouseState) // on mouse drag 75 | { 76 | model_orientation = qmul(VirtualTrackBall(float3(0, 0, 2), float3(0,0,0), mousevec_prev, glwin.MouseVector), model_orientation); 77 | } 78 | mousevec_prev = glwin.MouseVector; 79 | 80 | if (glwin.mousewheel) // lets also support mouse wheel to increase/decrease number of points used to generate hull 81 | { 82 | g_vlimit += glwin.mousewheel; g_vlimit = std::max(4, g_vlimit); 83 | g_tris = ::calchull(g_verts, g_vlimit); 84 | } 85 | 86 | 87 | glPushAttrib(GL_ALL_ATTRIB_BITS); 88 | 89 | // Set up the viewport 90 | glViewport(0, 0, glwin.res.x,glwin.res.y); 91 | glClearColor(0.1f, 0.1f, 0.15f, 1); 92 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 93 | 94 | glMatrixMode(GL_PROJECTION); 95 | glPushMatrix(); 96 | glLoadIdentity(); 97 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.01, 10); 98 | 99 | glMatrixMode(GL_MODELVIEW); 100 | glPushMatrix(); 101 | gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0); 102 | 103 | float4x4 R = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; 104 | R[0].xyz() = qxdir(model_orientation); R[1].xyz() = qydir(model_orientation); R[2].xyz() = qzdir(model_orientation); 105 | glMultMatrixf(R); 106 | 107 | glEnable(GL_DEPTH_TEST); 108 | 109 | glDisable(GL_BLEND); 110 | glPointSize(4); 111 | glBegin(GL_POINTS); 112 | glColor3f(0, 1, 0); 113 | for (auto &v : g_verts) 114 | { 115 | glColor3fv((&v - g_verts.data() < g_vlimit) ? float3(0.75, 1, 0) : float3(0.75, 0, 0)); 116 | glVertex3fv(v); 117 | } 118 | glEnd(); 119 | 120 | glEnable(GL_CULL_FACE); 121 | glEnable(GL_BLEND); 122 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 123 | glEnable(GL_LIGHTING); 124 | glEnable(GL_LIGHT0); 125 | glBegin(GL_TRIANGLES); 126 | glColor4f(1, 1, 1, 0.25f); 127 | for (auto t : g_tris) 128 | { 129 | glNormal3fv(TriNormal(g_verts[t[0]], g_verts[t[1]], g_verts[t[2]])); 130 | for (int j = 0; j < 3; j++) 131 | glVertex3fv(g_verts[t[j]]); 132 | } 133 | glEnd(); 134 | 135 | 136 | // Restore state 137 | glPopMatrix(); //should be currently in modelview mode 138 | glMatrixMode(GL_PROJECTION); 139 | glPopMatrix(); 140 | glPopAttrib(); 141 | glMatrixMode(GL_MODELVIEW); 142 | 143 | glwin.PrintString({ 5, 0 },"Press q to quit. Spacebar new pointcloud."); 144 | glwin.PrintString({ 5, 1 }, "w,s or mwheel to increase/decrease vlimit. "); 145 | glwin.PrintString({ 5, 2 }, "vlimit %d tris %d", g_vlimit, g_tris.size()); 146 | 147 | glwin.SwapBuffers(); 148 | } 149 | 150 | 151 | std::cout << "\n"; 152 | return 0; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /testhull/testhull.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {0000E173-0000-0000-0000-000000000000} 15 | Win32Proj 16 | testmath 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ..\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86); 46 | $(ProjectDir)\ 47 | $(ProjectName)_$(Configuration) 48 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 49 | 50 | 51 | false 52 | ..\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 53 | $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86); 54 | $(ProjectDir)\ 55 | $(ProjectName)_$(Configuration) 56 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 57 | 58 | 59 | 60 | 61 | 62 | Level3 63 | Disabled 64 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 65 | 66 | 67 | Console 68 | true 69 | 70 | 71 | 72 | 73 | Level3 74 | 75 | 76 | MaxSpeed 77 | true 78 | true 79 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 80 | 81 | 82 | Console 83 | true 84 | true 85 | true 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /testicp/testicp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // 4 | 5 | #include "../include/glwin.h" 6 | #include "../include/misc_gl.h" 7 | #include "geo6.h" 8 | 9 | #include "../include/wingmesh.h" 10 | 11 | 12 | int main(int argc, char *argv[]) try 13 | { 14 | GLWin glwin("test_icp"); 15 | 16 | 17 | Pose camera({ 0,0,3.0f }, { 0,0,0,1 }); 18 | 19 | float radius = 0.5f; 20 | auto box = WingMeshBox(float3(radius)); 21 | Pose bpose = { { 0.02f,0,0 },QuatFromAxisAngle({ 0,1,0 },0.242f) }; 22 | auto bmesh = MeshFlatShadeTex(box.verts, box.GenerateTris()); 23 | 24 | bool editmode = false; 25 | glwin.keyboardfunc = [&](int key, int, int) 26 | { 27 | editmode = key == 'e' != editmode; 28 | std::cout << "editmode " << editmode << std::endl; 29 | }; 30 | 31 | while (glwin.WindowUp()) 32 | { 33 | if (glwin.MouseState) 34 | { 35 | if (editmode) 36 | { 37 | auto dq = camera.orientation*quat_from_to(glwin.OldMouseVector, glwin.MouseVector); 38 | bpose.orientation = normalize(qmul(bpose.orientation, dq)); 39 | 40 | } 41 | else 42 | { 43 | auto dmouse = (glwin.mousepos - glwin.mousepos_previous); 44 | camera = Pose({ 0,0,0 }, QuatFromAxisAngle(qydir(camera.orientation), -dmouse.x*3.14f / 180.0f)) * camera; 45 | camera = Pose({ 0,0,0 }, QuatFromAxisAngle(qxdir(camera.orientation), -dmouse.y*3.14f / 180.0f)) * camera; 46 | camera.orientation = normalize(camera.orientation); 47 | } 48 | } 49 | camera.position *= powf(1.1f, (float)glwin.mousewheel); 50 | 51 | 52 | glPushAttrib(GL_ALL_ATTRIB_BITS); 53 | glViewport(0, 0, glwin.res.x, glwin.res.y); 54 | glClearColor(0.1f, 0.1f, 0.15f, 1); 55 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 56 | 57 | 58 | 59 | bmesh.pose = bpose; 60 | std::vector points; 61 | std::vector correspondences; 62 | for (float2 p(-radius + 0.1f);p.y < radius;p.y += 0.1f) for (p.x = -radius + 0.1f;p.x < radius;p.x += 0.1f) for (int i : {0, 1, 2}) for (int sign : {-1, 1}) 63 | { 64 | float3 normal(0.0f); normal[i] = 1.0f * sign; 65 | float3 v; v[i] = radius*sign; v[(i + 1) % 3] = p.x;v[(i + 2) % 3] = p.y; 66 | correspondences.push_back({ v,bpose.TransformPlane(float4{ normal,-radius }) }); 67 | } 68 | 69 | auto dpose = ICP(correspondences); 70 | 71 | auto drawpoints = ColorVerts(Transform(correspondences, [&](icp_correspondence c) {return dpose*c.point;}), { 1,0,0 }); 72 | 73 | std::vector lines; 74 | for (auto c : correspondences) 75 | lines.push_back(SegmentPC(c.point, c.point + c.plane.xyz()*-dot(c.plane, float4(c.point, 1.0f)), { 0,1,0,1 })); 76 | 77 | { 78 | render_scene scene(camera, { &bmesh }, lines, drawpoints); 79 | glPushMatrix(); 80 | glMultMatrixf(dpose.matrix()); 81 | glwirebox(float3(-radius), float3(radius)); 82 | glPopMatrix(); 83 | glColor3f(0, 1.0f,0); 84 | glwirebox(float3(-radius), float3(radius)); 85 | glColor3f(0, 0, 1.0f); 86 | glMultMatrixf(bpose.matrix()); 87 | glwirebox(float3(-radius), float3(radius)); 88 | } 89 | glPopAttrib(); 90 | glwin.SwapBuffers(); 91 | } 92 | return 0; 93 | } 94 | catch (const char *c) 95 | { 96 | std::cerr << c << std::endl; 97 | MessageBox(GetActiveWindow(), c, "FAIL", 0); 98 | } 99 | catch (std::exception e) 100 | { 101 | std::cerr << e.what() << std::endl; 102 | MessageBox(GetActiveWindow(), e.what(), "FAIL", 0); 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /testicp/testicp.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {D02BEFCD-FED1-4597-9484-51D41C9D446F} 23 | Win32Proj 24 | test_icp 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | NotSet 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | NotSet 39 | 40 | 41 | Application 42 | true 43 | v140 44 | NotSet 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | NotSet 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | true 73 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 74 | $(ProjectName)_$(Configuration)_$(Platform) 75 | $(ProjectDir)\ 76 | 77 | 78 | true 79 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 80 | $(ProjectName)_$(Configuration)_$(Platform) 81 | $(ProjectDir)\ 82 | 83 | 84 | false 85 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 86 | $(ProjectName)_$(Configuration)_$(Platform) 87 | $(ProjectDir)\ 88 | 89 | 90 | false 91 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 92 | $(ProjectName)_$(Configuration)_$(Platform) 93 | $(ProjectDir)\ 94 | 95 | 96 | 97 | 98 | 99 | Level3 100 | Disabled 101 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 102 | 103 | 104 | Console 105 | true 106 | 107 | 108 | 109 | 110 | 111 | 112 | Level3 113 | Disabled 114 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 115 | 116 | 117 | Console 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | 125 | 126 | MaxSpeed 127 | true 128 | true 129 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | 131 | 132 | Console 133 | true 134 | true 135 | true 136 | 137 | 138 | 139 | 140 | Level3 141 | 142 | 143 | MaxSpeed 144 | true 145 | true 146 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /testphys/physics.cpp: -------------------------------------------------------------------------------- 1 | 2 | #error("unused file") 3 | 4 | #include "physics.h" 5 | #include "gjk.h" 6 | 7 | 8 | 9 | /* 10 | Spring *CreateSpring(RigidBody *a,float3 av,RigidBody *b,float3 bv,float k) { 11 | Spring *s = new Spring(); 12 | s->bodyA = a; 13 | s->anchorA = av; 14 | s->bodyB = b; 15 | s->anchorB = bv; 16 | s->k = k; 17 | if(a)a->springs.push_back(s); 18 | if(b)b->springs.push_back(s); 19 | return s; 20 | } 21 | void DeleteSpring(Spring *s) { 22 | if (s->bodyA && Contains(s->bodyA->springs,s)) { 23 | Remove(s->bodyA->springs, s); 24 | } 25 | if (s->bodyB && Contains(s->bodyB->springs,s)) { 26 | Remove(s->bodyB->springs, s); 27 | } 28 | delete s; 29 | } 30 | */ 31 | //float springk=12.56f; // spring constant position - default to about half a second for unit mass weight 32 | //float springr=1.0f; // spring constant rotation 33 | 34 | //EXPORTVAR(springk); 35 | //EXPORTVAR(physics_damping); 36 | //float3 SpringForce(State &s,const float3 &home,float mass) { 37 | // return (home-s.position)*springk + // spring part 38 | // (s.momentum/mass)* (-sqrtf(4 * mass * springk) * physics_damping); // physics_damping part 39 | //} 40 | 41 | //int AddSpringForces(RigidBody *rba,const State &state,float3 *force,float3 *torque) 42 | //{ 43 | // 44 | // return 1; 45 | //} 46 | 47 | 48 | 49 | //-- retained mode API -- 50 | 51 | //std::vector Angulars; 52 | //std::vector Linears; 53 | // 54 | // 55 | //void addlimitlinearaxis(RigidBody *rb0,const float3 &p0,RigidBody *rb1,const float3 &p1,const float3 &axisw,float minforce,float maxforce) 56 | //{ 57 | // Linears.push_back( limitlinearaxis(rb0,p0,rb1,p1,axisw, minforce, maxforce) ); 58 | //} 59 | //void addlimitlinearaxisflow(RigidBody *rb0,const float3 &p0,RigidBody *rb1,const float3 &p1,const float3 &axisw,float minforce,float maxforce) 60 | //{ 61 | // Linears.push_back(limitlinearaxis(rb0, p0, rb1, p1, axisw, minforce, maxforce)); 62 | // LimitLinear &lim=Linears.back(); 63 | // lim.targetspeednobias=lim.targetspeed; 64 | //} 65 | //void createnail(RigidBody *rb0,const float3 &p0,RigidBody *rb1,const float3 &p1) 66 | //{ 67 | // float maxforce = FLT_MAX; 68 | // addlimitlinearaxis(rb0,p0,rb1,p1,float3(1,0,0),-maxforce,maxforce); 69 | // addlimitlinearaxis(rb0,p0,rb1,p1,float3(0,1,0),-maxforce,maxforce); 70 | // addlimitlinearaxis(rb0,p0,rb1,p1,float3(0,0,1),-maxforce,maxforce); 71 | // //return createnail(Linears,rb0,p0,rb1,p1); 72 | //} 73 | //void createdrive(RigidBody *rb0,RigidBody *rb1,float4 target,float maxtorque) 74 | //{ 75 | // return createdrive(Angulars,rb0,rb1,target,maxtorque); 76 | //} 77 | //void createangularlimits(RigidBody *rb0,RigidBody *rb1, const float4 &_jointframe, const float3& _jointlimitmin, const float3& _jointlimitmax) 78 | //{ 79 | // createangularlimits(Angulars,rb0,rb1,_jointframe,_jointlimitmin,_jointlimitmax); 80 | //} 81 | //void createconelimit(RigidBody* rb0,const float3 &n0,RigidBody* rb1,const float3 &n1,float limitangle_degrees) // a hinge is a cone with 0 limitangle 82 | //{ 83 | // Angulars.push_back(conelimit(rb0, n0, rb1, n1, limitangle_degrees)); 84 | //} 85 | // 86 | //void PhysicsUpdate(std::vector &rigidbodies,const std::vector *> &wgeom) 87 | //{ 88 | // //GetEnvBSPs(area_bsps); 89 | // PhysicsUpdate(rigidbodies,Linears,Angulars,wgeom); 90 | // Linears.clear(); 91 | // Angulars.clear(); 92 | //} 93 | // 94 | // -------------------------------------------------------------------------------- /testphys/testphys.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // a quick sample testing the physics code 3 | // create some boxes, let them drop. 4 | // SPACE key starts the simulation. 5 | // 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include // std::tolower 12 | #include // For va_list, va_start, ... 13 | #include // For vsnprintf 14 | #include 15 | 16 | // in project properties, add "../include" to the vc++ directories include path 17 | #include "linalg.h" 18 | using namespace linalg::aliases; // float3, int2, float3x3 etc 19 | 20 | #include "glwin.h" // minimal opengl for windows setup wrapper 21 | #include "hull.h" 22 | #include "gjk.h" 23 | #include "wingmesh.h" 24 | #include "physics.h" 25 | 26 | 27 | 28 | float g_pitch, g_yaw; 29 | bool g_simulate = 0; 30 | 31 | 32 | 33 | void InitTex() // create a checkerboard texture 34 | { 35 | const int imagedim = 16; 36 | byte3 checker_image[imagedim * imagedim]; 37 | for (int y = 0; y < imagedim; y++) for (int x = 0; x < imagedim; x++) 38 | checker_image[y * imagedim + x] = ((x/4 + y/4) % 2) ? byte3(191, 255, 255) : byte3(63, 127, 127); 39 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 40 | glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); 41 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 42 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 43 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imagedim, imagedim, 0, GL_RGB, GL_UNSIGNED_BYTE, checker_image); 44 | } 45 | 46 | void gldraw(const std::vector &verts, const std::vector &tris) 47 | { 48 | glBegin(GL_TRIANGLES); 49 | glColor4f(1, 1, 1, 0.25f); 50 | for (auto t : tris) 51 | { 52 | auto n = TriNormal(verts[t[0]], verts[t[1]], verts[t[2]]); 53 | glNormal3fv(n); auto vn = abs(n); 54 | int k = argmax(&vn.x, 3); 55 | for (int j = 0; j < 3; j++) 56 | { 57 | const auto &v = verts[t[j]]; 58 | glTexCoord2f(v[(k + 1) % 3], v[(k + 2) % 3]); 59 | glVertex3fv(v); 60 | } 61 | } 62 | glEnd(); 63 | } 64 | void wmwire(const WingMesh &m) 65 | { 66 | glBegin(GL_LINES); 67 | for (auto e : m.edges) 68 | { 69 | glVertex3fv(m.verts[e.v]); 70 | glVertex3fv(m.verts[m.edges[e.next].v]); 71 | } 72 | glEnd(); 73 | } 74 | void wmdraw(const WingMesh &m) 75 | { 76 | gldraw(m.verts, m.GenerateTris()); 77 | } 78 | 79 | void rbdraw(const RigidBody *rb) 80 | { 81 | glPushMatrix(); 82 | glMultMatrixf(MatrixFromRotationTranslation(rb->orientation, rb->position)); 83 | for (const auto &s : rb->shapes) 84 | gldraw(s.verts, s.tris); 85 | glPopMatrix(); 86 | } 87 | 88 | 89 | 90 | Shape AsShape(const WingMesh &m) { return Shape(m.verts, m.GenerateTris()); } 91 | 92 | 93 | int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,LPSTR lpszCmdLine, int nCmdShow) // int main(int argc, char *argv[]) 94 | { 95 | std::cout << "Test Physics\n"; 96 | 97 | std::vector rigidbodies; 98 | rigidbodies.push_back(new RigidBody({ AsShape(WingMeshCube(1.1f)) }, { 1.5f, 0.0f, 1.5f })); 99 | rigidbodies.push_back(new RigidBody({ AsShape(WingMeshCube(1.1f)) }, { -1.5f, 0.0f, 1.5f })); 100 | rigidbodies.back()->orientation = normalize(float4(0.1f, 0.01f, 0.3f, 1.0f)); 101 | auto seesaw = new RigidBody({ AsShape(WingMeshBox( { 3, 0.5f, 0.1f })) }, { 0, -2.5, 0.25f }); 102 | rigidbodies.push_back(seesaw); 103 | rigidbodies.push_back( new RigidBody({ AsShape(WingMeshCube(0.25f)) }, seesaw->position_start + float3( 2.5f, 0, 0.4f))); 104 | rigidbodies.push_back( new RigidBody({ AsShape(WingMeshCube(0.50f)) }, seesaw->position_start + float3(-2.5f, 0, 5.0f))); 105 | rbscalemass(rigidbodies.back(), 4.0f); 106 | rigidbodies.push_back(new RigidBody({ AsShape(WingMeshBox({1,0.2f,0.2f})),AsShape(WingMeshBox({0.2f,1,0.2f})),AsShape(WingMeshBox({0.2f,0.2f,1})) }, { -1.5f, 0.5f, 7.5f })); 107 | for (float z = 5.5f; z < 14.0f; z += 3.0f) 108 | rigidbodies.push_back(new RigidBody({ AsShape(WingMeshCube(0.5f)) }, { 0.0f, 0.0f, z })); 109 | for (float z = 15.0f; z < 20.0f; z += 3.0f) 110 | rigidbodies.push_back(new RigidBody({ AsShape(WingMeshDual(WingMeshCube(0.5f), 0.65f)) }, { 2.0f, -1.0f, z })); 111 | 112 | WingMesh world_slab = WingMeshBox({ -10, -10, -5 }, { 10, 10, -2 }); // world_geometry 113 | 114 | 115 | 116 | GLWin glwin("TestPhys sample"); 117 | glwin.ViewAngle = 60.0f; 118 | 119 | glwin.keyboardfunc = [&](unsigned char key, int x, int y)->void 120 | { 121 | switch (std::tolower(key)) 122 | { 123 | case ' ': 124 | g_simulate = !g_simulate; 125 | break; 126 | case 'q': case 27: // ESC 127 | exit(0); break; 128 | case 'r': 129 | for (auto &rb : rigidbodies) 130 | { 131 | rb->position = rb->position_start; 132 | //rb->orientation = rb->orientation_start; // when commented out this provides some variation 133 | rb->linear_momentum = float3(0, 0, 0); 134 | rb->angular_momentum = float3(0, 0, 0); 135 | } 136 | seesaw->orientation = { 0, 0, 0, 1 }; 137 | break; 138 | default: 139 | std::cout << "unassigned key (" << (int)key << "): '" << key << "'\n"; 140 | break; 141 | } 142 | }; 143 | 144 | InitTex(); 145 | 146 | while (glwin.WindowUp()) 147 | { 148 | if (glwin.MouseState) // on mouse drag 149 | { 150 | g_yaw += (glwin.mousepos.x - glwin.mousepos_previous.x) * 0.3f; // poor man's trackball 151 | g_pitch += (glwin.mousepos.y - glwin.mousepos_previous.y) * 0.3f; 152 | } 153 | 154 | if (g_simulate) 155 | { 156 | std::vector angulars; 157 | std::vector linears; 158 | Append(linears , ConstrainPositionNailed(NULL, seesaw->position_start, seesaw, { 0, 0, 0 })); 159 | Append(angulars, ConstrainAngularRange(NULL, seesaw, { 0, 0, 0, 1 }, { 0, -20, 0 }, { 0, 20, 0 })); 160 | PhysicsUpdate(rigidbodies, linears, angulars, { &world_slab.verts }); 161 | } 162 | 163 | 164 | glPushAttrib(GL_ALL_ATTRIB_BITS); 165 | glViewport(0, 0, glwin.res.x,glwin.res.y); // Set up the viewport 166 | glClearColor(0.1f, 0.1f, 0.15f, 1); 167 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 168 | glEnable(GL_DEPTH_TEST); 169 | 170 | // Set up matrices 171 | glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); 172 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.01, 50); 173 | 174 | glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); 175 | gluLookAt(0, -8, 5, 0, 0, 0, 0, 0, 1); 176 | glRotatef(g_pitch, 1, 0, 0); 177 | glRotatef(g_yaw, 0, 0, 1); 178 | 179 | wmdraw(world_slab); // world_geometry 180 | 181 | glEnable(GL_POLYGON_OFFSET_FILL); 182 | glPolygonOffset(1., 1. / (float)0x10000); 183 | glEnable(GL_LIGHTING); 184 | glEnable(GL_LIGHT0); 185 | glEnable(GL_TEXTURE_2D); 186 | glColor3f(0.5f, 0.5f, 0.5f); 187 | for (auto &rb : rigidbodies) 188 | rbdraw(rb); 189 | 190 | 191 | glPopAttrib(); // Restore state 192 | glMatrixMode(GL_PROJECTION); glPopMatrix(); 193 | glMatrixMode(GL_MODELVIEW); glPopMatrix(); 194 | 195 | glwin.PrintString({ 5, 0 },"ESC/q quits. SPACE to simulate. r to restart"); 196 | glwin.PrintString({ 5, 1 }, "simulation %s", (g_simulate) ? "ON" : "OFF"); 197 | glwin.SwapBuffers(); 198 | } 199 | 200 | std::cout << "\n"; 201 | return 0; 202 | } 203 | 204 | -------------------------------------------------------------------------------- /testphys/testphys.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A15C7BE9-DC39-4523-81E7-5150741C814C} 15 | Win32Proj 16 | testgjk 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ..\include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /testrig/readme.txt: -------------------------------------------------------------------------------- 1 | this hand model was publicly available: 2 | downloadable from https://raw.githubusercontent.com/IntelPerceptual/UnityPXC/master/UnityPluginTest/default_hand.chr 3 | 4 | 5 | -------------------------------------------------------------------------------- /testrig/testrig.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // An example of loading and simulating a rigged model consisting of a collection of rigidbodies and some joints connecting them. 3 | // left mouse and mwheel can select and move individual rigidbodies using on-the-fly positional constraints. 4 | // 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include // just so i can quickly make a box 15 | #include 16 | #include 17 | 18 | 19 | 20 | 21 | struct Joint 22 | { 23 | int rbi0 ; 24 | int rbi1 ; 25 | float3 p0; 26 | float3 p1; 27 | float3 jointlimitmin; 28 | float3 jointlimitmax; 29 | }; 30 | 31 | std::vector Planes(const std::vector &verts, const std::vector &tris) { std::vector planes; for (auto &t : tris) planes.push_back(PolyPlane({verts[t[0]],verts[t[1]],verts[t[2]] })); return planes; } 32 | 33 | int main(int argc, const char *argv[]) try 34 | { 35 | bool showskin = false; 36 | 37 | std::vector joints; 38 | std::vector rbs; 39 | std::map rbindex; 40 | auto xml = XMLParseFile("./default_hand.chr"); // replace string with whatever model you want to test. uses xml variation of John Ratcliff's easy mesh (ezm) file format. 41 | auto const &skx = xml.child("model").child("skeleton"); 42 | for (auto const &b : skx.children) 43 | { 44 | rbindex[b.attribute("name")] = rbs.size(); 45 | auto verts = ArrayImport(b.child("verts").body); 46 | auto tris = calchull(verts, verts.size()); 47 | float3 pos = StringTo(b.attribute("position")); 48 | int parent = (b.hasAttribute("parent")) ? (int)rbindex[b.attribute("parent")] : -1; 49 | rbs.push_back(RigidBody({ Shape(verts,tris) }, pos + ((parent>=0)?rbs[parent].position-rbs[parent].com:float3(0,0,0)))); 50 | if (parent>=0) 51 | joints.push_back({ parent, (int)rbs.size() - 1, pos, float3(0,0,0), StringTo(b.child("jointlimitmin").body), StringTo(b.child("jointlimitmax").body) }); 52 | } 53 | rbscalemass(&rbs[0], 3.0f); 54 | rbscalemass(&rbs[1], 5.0f); 55 | 56 | Mesh skin; 57 | skin.hack = { 1,1,1,1 }; 58 | std::vector sverts = ArrayImport(xml.child("model").child("mesh").child("vertexbuffer").body); 59 | //for (auto &s : sverts) { s.orientation = qmul(s.orientation, float4(1, 0, 0, 0)); s.texcoord = { s.position.x,s.position.y }; } // trying to make not everything black 60 | skin.tris = ArrayImport(xml.child("model").child("mesh").child("indexbuffer").body); 61 | auto basepose = Transform(rbs, [](const RigidBody &rb) {return Pose(rb.PositionUser(), rb.orientation); }); 62 | 63 | 64 | std::vector meshes; 65 | for (auto &rb : rbs) 66 | { 67 | meshes.push_back(MeshSmoothish(rb.shapes[0].verts, rb.shapes[0].tris)); // 1 shape each is known 68 | rb.damping = 0.8f; 69 | //rb.gravscale = 0; 70 | } 71 | for (auto &joint : joints) 72 | { 73 | rbs[joint.rbi0].ignore.push_back(&rbs[joint.rbi1]); 74 | rbs[joint.rbi1].ignore.push_back(&rbs[joint.rbi0]); 75 | joint.p0 -= rbs[joint.rbi0].com; 76 | joint.p1 -= rbs[joint.rbi1].com; 77 | } 78 | for (auto &ja : joints) for (auto &jb : joints) if (ja.rbi0 == jb.rbi0 && ja.rbi1 != jb.rbi1) // ignore siblings 79 | { 80 | rbs[ja.rbi1].ignore.push_back(&rbs[jb.rbi1]); 81 | rbs[jb.rbi1].ignore.push_back(&rbs[ja.rbi1]); 82 | } 83 | for (auto &ja : joints) for (auto &jb : joints) if (ja.rbi1 == jb.rbi0 ) // ignore grandparents 84 | { 85 | rbs[ja.rbi0].ignore.push_back(&rbs[jb.rbi1]); 86 | rbs[jb.rbi1].ignore.push_back(&rbs[ja.rbi0]); 87 | } 88 | 89 | std::vector groundpoints = { { -5.0f, -5.0f, -5.0f }, { 5.0f, -5.0f, -5.0f }, { 5.0f, 10.0f, -5.0f }, { -5.0f, 10.0f, -5.0f }, { -5.0f, -5.0f, -10.0f }, { 5.0f, -5.0f, -10.0f }, { 5.0f, 10.0f, -10.0f }, { -5.0f, 10.0f, -10.0f } }; 90 | Mesh ground = MeshSmoothish(groundpoints, { { 0, 1, 2 }, { 2, 3,0 } }); 91 | ground.hack = { 1, 1, 0 ,1}; 92 | WingMesh cube_wm = WingMeshCube(0.025f); 93 | auto mesh_cube = MeshFlatShadeTex(cube_wm.verts, WingMeshTris(cube_wm)); 94 | mesh_cube.hack = { 0, 1, 0, 1 }; 95 | 96 | Pose camera = { { 0, -10, 0 }, normalize(float4(1, 0, 0, 1)) }; 97 | RigidBody *selected = NULL; 98 | float3 spoint=camera * float3(0,0,-10); 99 | float3 rbpoint; 100 | 101 | struct Pin{ float3 w; RigidBody* rb; float3 p; }; 102 | std::vector pins; 103 | 104 | DXWin mywin("DX testing articulated rigged model"); 105 | mywin.keyboardfunc = [&](int key, int, int) 106 | { 107 | showskin = key == 's' != showskin; 108 | if (key == 'g') for (auto &rb : rbs) rb.gravscale = 1.0f - rb.gravscale; 109 | if (key == 'p' && selected) 110 | Append(pins, { spoint, selected, rbpoint }); 111 | }; 112 | 113 | while (mywin.WindowUp()) 114 | { 115 | float3 ray = qrot(camera.orientation, normalize(mywin.MouseVector)); 116 | if (!selected) 117 | { 118 | for (auto &rb : rbs) 119 | { 120 | float3 v1 = camera.position + ray*100.0f; 121 | if (auto h=ConvexHitCheck(Planes(rb.shapes[0].verts, rb.shapes[0].tris),rb.pose(),camera.position,v1)) 122 | { 123 | v1 = h.impact; 124 | selected = &rb; 125 | spoint = h.impact; 126 | rbpoint = rb.pose().inverse()*h.impact; 127 | } 128 | } 129 | } 130 | spoint = camera.position + ray * length(spoint - camera.position)*powf(1.025f, (float)mywin.mousewheel); 131 | mesh_cube.pose.position = spoint; 132 | if (!mywin.MouseState) 133 | selected = NULL; 134 | 135 | std::vector angulars; 136 | std::vector linears; 137 | for (auto const &joint : joints) 138 | { 139 | Append(linears, ConstrainPositionNailed(&rbs[joint.rbi0], joint.p0, &rbs[joint.rbi1], joint.p1)); 140 | Append(angulars, ConstrainAngularRange(&rbs[joint.rbi0], &rbs[joint.rbi1], { 0, 0, 0, 1 }, joint.jointlimitmin, joint.jointlimitmax)); 141 | } 142 | if (selected) 143 | Append(linears, ConstrainPositionNailed(NULL, spoint, selected, rbpoint)); 144 | for(auto &p:pins) 145 | Append(linears, ConstrainPositionNailed(NULL, p.w,p.rb,p.p)); 146 | PhysicsUpdate(Addresses(rbs), linears, angulars, { &groundpoints }); 147 | 148 | { 149 | //auto deltapose = Transform(rbs, [](const RigidBody &rb) {return Pose(); });// Pose(rb.PositionUser(), rb.orientation) * Pose(rb.position_start - rb.com, { 0,0,0,1 }).inverse(); }); 150 | auto deltapose = Transform(rbs, [](const RigidBody &rb) {return Pose(rb.PositionUser(), rb.orientation) * Pose(rb.position_start - rb.com, { 0,0,0,1 }).inverse(); }); 151 | skin.verts = Skin(sverts, deltapose); 152 | } 153 | 154 | for (unsigned int i = 0; i < rbs.size(); i++) 155 | { 156 | meshes[i].pose = rbs[i].pose(); 157 | } 158 | 159 | mywin.RenderScene(camera, (showskin) ? std::vector{ &ground, &skin, &mesh_cube } : Append(Addresses(meshes), std::vector({ &ground, &mesh_cube }))); 160 | } 161 | } 162 | catch (std::exception e) 163 | { 164 | MessageBoxA(GetActiveWindow(), e.what(), "FAIL", 0); 165 | return -1; 166 | } 167 | 168 | 169 | -------------------------------------------------------------------------------- /testrig/testrig.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {6D8B8BF8-699D-41F4-8577-2CF859A5F240} 15 | Win32Proj 16 | testrig 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 45 | $(ProjectDir) 46 | $(ProjectName)_$(Configuration) 47 | ..\include;../LibOVR/Include;../LibOVR/Src;$(VC_IncludePath);$(WindowsSDK_IncludePath); 48 | 49 | 50 | false 51 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 52 | $(ProjectDir) 53 | $(ProjectName)_$(Configuration) 54 | ..\include;../LibOVR/Include;../LibOVR/Src;$(VC_IncludePath);$(WindowsSDK_IncludePath); 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 63 | 64 | 65 | Console 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 78 | 79 | 80 | Console 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /testsubdiv/testsubdiv.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // testing a subd idea 3 | // 4 | 5 | #include 6 | #include 7 | #include // std::tolower 8 | #include 9 | #include 10 | // in project properties, add "../include" to the vc++ directories include path 11 | 12 | #include "geometric.h" 13 | #include "glwin.h" // minimal opengl for windows setup wrapper 14 | #include "misc_gl.h" 15 | #include "wingmesh.h" 16 | #include "minixml.h" 17 | #include "misc.h" 18 | 19 | void wmwire(const WingMesh &m) 20 | { 21 | glBegin(GL_LINES); 22 | for (auto e : m.edges) 23 | { 24 | glVertex3fv(m.verts[e.v]); 25 | glVertex3fv(m.verts[m.edges[e.next].v]); 26 | } 27 | glEnd(); 28 | } 29 | void wmdraw(const WingMesh &m) 30 | { 31 | gldraw(m.verts, m.GenerateTris()); 32 | } 33 | 34 | 35 | WingMesh WingMeshLoad(const char *filename) 36 | { 37 | WingMesh wm; 38 | std::ifstream filein(filename); 39 | if (!filein.is_open()) 40 | throw "unable to open file"; 41 | std::string line; 42 | while (std::getline(filein, line)) 43 | { 44 | auto tokens = split(line); 45 | if (!tokens.size()) 46 | continue; 47 | auto head = tokens.front(); 48 | tokens.erase(tokens.begin()); 49 | if (head == "v") 50 | { 51 | line.erase(0, 1); 52 | wm.verts.push_back(StringTo(line)*0.1f); 53 | continue; 54 | } 55 | if (head == "f") 56 | { 57 | std::vector vids; 58 | for(auto &token:tokens) 59 | vids.push_back(StringTo(split(token,"/")[0]) - 1); // ugg obj index from one instead of zero 60 | int base = wm.edges.size(); 61 | std::vector fverts; 62 | for (int i = 0; i < (int)vids.size(); i++) 63 | { 64 | int inext = (i + 1) % vids.size(); 65 | int iprev = (i + vids.size()-1) % vids.size(); 66 | wm.edges.push_back(WingMesh::HalfEdge(base + i, vids[i], -1, base + inext, base + iprev, wm.faces.size())); 67 | fverts.push_back(wm.verts[vids[i]]); 68 | } 69 | wm.faces.push_back(PolyPlane(fverts)); 70 | continue; 71 | } 72 | } 73 | wm.LinkMesh(); 74 | wm.InitBackLists(); 75 | return wm; 76 | } 77 | 78 | float3 *HitCheckPoint(std::vector &points,const float3 &v0,float3 v1,float box_radius) // typically used for vertex selection 79 | { 80 | float3 *point_hit = NULL; 81 | float w = -box_radius; 82 | std::vector planes = { { 1, 0, 0, w },{ 0, 1, 0, w },{ 0, 0, 1, w },{ -1, 0, 0, w },{ 0, -1, 0, w },{ 0, 0, -1, w } }; 83 | for (float3 &p : points) 84 | { 85 | if (auto h = ConvexHitCheck(planes, Pose(p, { 0, 0, 0, 1 }), v0, v1)) 86 | { 87 | point_hit = &p; 88 | v1 = h.impact; 89 | } 90 | } 91 | return point_hit; 92 | } 93 | 94 | 95 | int main(int argc, char *argv[]) 96 | { 97 | std::cout << "Test...\n"; 98 | auto body = WingMeshLoad("EntireBody.obj"); 99 | 100 | //auto box = WingMeshSubDiv(WingMeshSubDiv(WingMeshCube(0.5f))); 101 | float3 *selected = NULL; 102 | float3 *operand = NULL; // for any two point operations 103 | GLWin glwin("Test CatmullClark"); 104 | glwin.keyboardfunc = [&](int key, int, int) 105 | { 106 | switch (std::tolower(key)) 107 | { 108 | case ' ': 109 | break; 110 | case 27: // ESC 111 | case 'q': 112 | exit(0); 113 | break; 114 | case 'e': 115 | { 116 | if (operand == selected) 117 | { 118 | operand = NULL; // de-select 119 | break; 120 | } 121 | if (!operand || !selected) 122 | { 123 | operand = selected; 124 | break; 125 | } 126 | body.TryToggleEdge(operand - body.verts.data(), selected - body.verts.data()); 127 | operand = NULL; 128 | selected = NULL; 129 | break; 130 | } 131 | default: 132 | std::cout << "unassigned key (" << (int)key << "): '" << key << "'\n"; 133 | break; 134 | } 135 | 136 | }; 137 | 138 | float3 mousevec_prev; 139 | float camdist = 2.0f; 140 | Pose camera({ 0,0,camdist }, { 0, 0, 0, 1 }); 141 | float boxr = 0.002f; 142 | 143 | while (glwin.WindowUp()) 144 | { 145 | if (!glwin.MouseState) 146 | { 147 | selected = HitCheckPoint(body.verts, camera.position, camera*(glwin.MouseVector*100.0f), boxr); 148 | } 149 | else if (selected) 150 | { 151 | *selected += (qrot(camera.orientation, glwin.MouseVector) - qrot(camera.orientation, glwin.OldMouseVector)) * length(*selected - camera.position); 152 | *selected = camera.position + (*selected - camera.position) * powf(1.1f, (float)glwin.mousewheel); 153 | glwin.mousewheel = 0; 154 | } 155 | else // on mouse drag 156 | { 157 | camera.orientation = qmul(camera.orientation,qconj(VirtualTrackBall(float3(0, 0, 2), float3(0, 0, 0), mousevec_prev, glwin.MouseVector))); 158 | camera.position = qzdir(camera.orientation)*camdist; 159 | camdist *= pow(1.1f, (float)glwin.mousewheel); 160 | glwin.mousewheel = 0; 161 | } 162 | mousevec_prev = glwin.MouseVector; 163 | 164 | auto body1 = WingMeshSubDiv(body); 165 | auto body2 = WingMeshSubDiv(body1); 166 | 167 | 168 | glPushAttrib(GL_ALL_ATTRIB_BITS); 169 | 170 | // Set up the viewport 171 | glViewport(0, 0, glwin.res.x, glwin.res.y); 172 | glClearColor(0.1f, 0.1f, 0.15f, 1); 173 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 174 | 175 | glMatrixMode(GL_PROJECTION); 176 | glPushMatrix(); 177 | glLoadIdentity(); 178 | gluPerspective(glwin.ViewAngle, (double)glwin.aspect_ratio(), 0.01, 10); 179 | 180 | glMatrixMode(GL_MODELVIEW); 181 | glPushMatrix(); 182 | glMultMatrixf(camera.inverse().matrix()); 183 | 184 | glEnable(GL_DEPTH_TEST); 185 | 186 | 187 | glDisable(GL_BLEND); 188 | for (auto &p : body.verts) 189 | glcolorbox(float3((&p==operand||&p==selected)?2.0f:1.0f)*boxr, Pose(p, { 0,0,0,1 })); 190 | if (operand) 191 | { 192 | glBegin(GL_LINES); 193 | glColor3f(1, 1, 1); 194 | glVertex3fv(*operand); 195 | glVertex3fv(camera*(glwin.MouseVector*length(*operand - camera.position))); 196 | glEnd(); 197 | } 198 | glColor3f(0, 1, 1); 199 | glEnable(GL_CULL_FACE); 200 | //glEnable(GL_LIGHTING); 201 | glEnable(GL_LIGHT0); 202 | wmwire(body ); 203 | glTranslatef(0.3f,0,0 ); 204 | wmwire(body1); 205 | glTranslatef( 0.3f,0,0); 206 | wmwire(body2); 207 | 208 | 209 | // Restore state 210 | glMatrixMode(GL_PROJECTION); 211 | glPopMatrix(); 212 | glMatrixMode(GL_MODELVIEW); 213 | glPopMatrix(); //should be currently in modelview mode 214 | glPopAttrib(); 215 | 216 | glwin.PrintString({ 0, 0 }, "Press ESC to quit."); 217 | if (selected) glwin.PrintString({ 0, 1 }, "vertex current: %d", (int)(selected - body.verts.data())); 218 | if (operand ) glwin.PrintString({ 0, 2 }, "vertex operand: %d", (int)(operand - body.verts.data())); 219 | glwin.SwapBuffers(); 220 | } 221 | 222 | 223 | std::cout << "\n"; 224 | return 0; 225 | } 226 | 227 | -------------------------------------------------------------------------------- /testtrack/testtrack.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {5AEBE621-C990-408D-B1C3-062CC3FEADC8} 15 | Win32Proj 16 | testtrack 17 | 18 | 19 | 20 | Application 21 | true 22 | v140 23 | NotSet 24 | 25 | 26 | Application 27 | false 28 | v140 29 | true 30 | NotSet 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 45 | $(ProjectDir)\ 46 | $(ProjectName)_$(Configuration) 47 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 48 | 49 | 50 | false 51 | ../include;$(VC_IncludePath);$(WindowsSDK_IncludePath); 52 | $(ProjectDir)\ 53 | $(ProjectName)_$(Configuration) 54 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)\ 55 | 56 | 57 | 58 | 59 | 60 | Level3 61 | Disabled 62 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 63 | 64 | 65 | Windows 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MaxSpeed 75 | true 76 | true 77 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 78 | 79 | 80 | Windows 81 | true 82 | true 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /voxblob/legacy_voxblob.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {8955E4E8-C047-436B-9125-916D3653BA8F} 23 | voxblob 24 | legacy_voxblob 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | NotSet 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | NotSet 39 | 40 | 41 | Application 42 | true 43 | v140 44 | NotSet 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | NotSet 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | $(ProjectDir)\ 73 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 74 | $(ProjectName)_$(Configuration) 75 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 76 | 77 | 78 | $(ProjectDir)\ 79 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 80 | $(ProjectName)_$(Configuration) 81 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 82 | 83 | 84 | $(ProjectDir)\ 85 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 86 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 87 | $(ProjectName)_$(Configuration)_$(Platform) 88 | 89 | 90 | $(ProjectDir)\ 91 | $(SolutionDir)\obj\$(ProjectName)\$(Configuration)_$(Platform)\ 92 | ../include/;$(VC_IncludePath);$(WindowsSDK_IncludePath); 93 | $(ProjectName)_$(Configuration)_$(Platform) 94 | 95 | 96 | 97 | Level3 98 | Disabled 99 | true 100 | 101 | 102 | 103 | 104 | Level3 105 | Disabled 106 | true 107 | 108 | 109 | 110 | 111 | Level3 112 | MaxSpeed 113 | true 114 | true 115 | true 116 | 117 | 118 | true 119 | true 120 | 121 | 122 | 123 | 124 | Level3 125 | MaxSpeed 126 | true 127 | true 128 | true 129 | 130 | 131 | true 132 | true 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | --------------------------------------------------------------------------------