├── .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 << "" << n.tag << ">";
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 |