├── LICENSE.txt ├── Makefile ├── README.md ├── core ├── Makefile ├── aabbtree.cpp ├── aabbtree.h ├── core.cpp ├── core.h ├── core.props ├── core.sln ├── core.vcproj ├── core.vcxproj ├── core.vcxproj.filters ├── hashgrid.cpp ├── hashgrid.h ├── log.cpp ├── log.h ├── mat22.h ├── mat33.h ├── mat44.h ├── maths.cpp ├── maths.h ├── memory.cpp ├── memory.h ├── mesh.cpp ├── mesh.h ├── meshuv.cpp ├── meshuv.h ├── perlin.cpp ├── perlin.h ├── pfm.cpp ├── pfm.h ├── platform.cpp ├── platform.h ├── png.cpp ├── png.h ├── point3.h ├── radix.cpp ├── radix.h ├── sdf.cpp ├── sdf.h ├── shader.cpp ├── shader.h ├── skylight.cpp ├── skylight.h ├── tga.cpp ├── tga.h ├── threadgroup.cpp ├── threadgroup.h ├── threading.cpp ├── threading.h ├── threadinglinux.h ├── threadingwin32.h ├── types.h ├── vec2.h ├── vec3.h ├── vec4.h ├── voxelize.cpp └── voxelize.h ├── data ├── beach.pfm ├── happy.obj └── teapot.obj ├── external ├── glew │ ├── LICENSE.txt │ ├── bin │ │ └── glew32.dll │ ├── include │ │ └── GL │ │ │ ├── glew.h │ │ │ └── wglew.h │ └── lib │ │ ├── glew32.lib │ │ └── glew32s.lib ├── glut │ ├── glut.dll │ ├── glut.h │ ├── glut.lib │ ├── glut32.dll │ └── glut32.lib └── stb_image │ └── stb_image.c └── projects ├── cloth ├── cloth.sln ├── cloth.vcxproj └── main.cpp ├── dew ├── Dew.sln ├── Dew.vcxproj ├── Makefile ├── can.obj ├── dew ├── dew.exe ├── dialog.mm ├── drawing001.bvh ├── drawing002.bvh ├── main.cpp ├── readme.txt ├── shaders.h ├── tag.cpp └── tag.h ├── empty ├── empty.sln ├── empty.vcxproj └── main.cpp ├── fem ├── armadillo.tga ├── bunny.tga ├── cg.h ├── donut1.tga ├── donut2.tga ├── fem.cpp ├── fem.h ├── fem.nb ├── fem.sln ├── fem.vcxproj ├── integrators.nb ├── main.cpp ├── makefile ├── mesher.cpp ├── mesher.h ├── meshing.pdf ├── meshing.tex └── vencode.sh ├── fog ├── data │ ├── common.glsl │ ├── pointlight.glsl │ ├── simplevertex.glsl │ └── spotlight.glsl ├── fogvolumes.sln ├── fogvolumes.vcxproj └── main.cpp ├── gi ├── gi.sln ├── gi.suo ├── gi.vcproj ├── gi_shot1.jpg ├── gi_shot2.jpg ├── illuminate.fp ├── illuminate.vp ├── illuminationsim.cpp ├── illuminationsim.h └── main.cpp ├── granular2d ├── armadillo.tga ├── bunny.tga ├── granular2d.sln ├── granular2d.vcxproj ├── main.cpp ├── makefile ├── solve.cu ├── solve.h ├── solveConstraint.cpp ├── solveImpulse.cpp ├── solvePBD.cpp └── sort.cu ├── granular3d ├── armadillo.ply ├── bunny.ply ├── granular.sln ├── granular.vcxproj ├── main.cpp ├── shaders.cpp ├── shaders.h ├── solve.cpp ├── solve.cu ├── solve.h └── sort.cu ├── mathematica └── capsulecollision.nb ├── metaballs └── main.cpp ├── nanoray ├── camera.cpp ├── camera.h ├── examples.cpp ├── integrators.cpp ├── integrators.h ├── lights.cpp ├── lights.h ├── main.cpp ├── makefile ├── material.cpp ├── materials.h ├── metaballs.cpp ├── metaballs.h ├── nanoray.sln ├── nanoray.vcproj ├── nanoray.vcxproj ├── nanoray.vcxproj.filters ├── primitives.cpp ├── primitives.h ├── rendercl.cpp ├── rendercl.h ├── renderjob.cl ├── renderjob.cpp ├── renderjob.h ├── renderspu.cpp ├── renderspu.h ├── scene.h ├── textures.cpp ├── textures.h └── todo.txt ├── pbd ├── dump.txt ├── main.cpp ├── makefile ├── pbd.pdf ├── pbd.sln └── pbd.vcxproj ├── probeview └── main.cpp ├── quadric ├── main.cpp ├── makefile ├── quadric ├── quadric.bib ├── quadric.pdf └── quadric.tex ├── rigidbody └── main.cpp ├── sh ├── Makefile ├── main.cpp ├── sh.cpp ├── sh.h ├── sh.nb ├── sh.sln └── sh.vcxproj ├── smoke ├── blackbody.cpp ├── blackbody.h ├── fluid ├── fluid.sln ├── fluid.vcproj ├── fluid.vcxproj ├── fluid.vcxproj.filters ├── fluid2d.cpp ├── fluid3d.cpp ├── grid3d.h ├── raymarchshadowps.glsl ├── raymarchvolumeps.glsl ├── raymarchvolumeps.glsl_opt ├── raymarchvolumevs.glsl ├── vencode.bat └── vencode.sh ├── springs ├── cg.h ├── implicitsprings.pdf ├── implicitsprings.tex ├── main.cpp ├── makefile ├── springs.sln └── springs.vcxproj ├── surfel ├── main.cpp ├── surfel.sln └── surfel.vcxproj └── voxelize ├── main.cpp ├── makefile ├── voxelize.sln └── voxelize.vcxproj /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Miles Macklin 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CTAGS = ctags --fields=+l --c-kinds=+p --c++-kinds=+p 2 | 3 | FILES = core/*.h 4 | FILES += external/glut/glut.h 5 | FILES += /Library/Frameworks/CUDA.framework/Versions/A/Headers/*.h 6 | FILES += /usr/local/cuda/include/cuda_runtime_api.h 7 | FILES += /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers/gl.h 8 | 9 | tags: $(FILES) Makefile 10 | $(CTAGS) $(FILES) 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sandbox 2 | ======= 3 | 4 | Graphics and physics research, snippets, demos. Some are described here: 5 | 6 | http://blog.mmacklin.com 7 | 8 | Directories: 9 | 10 | core/ - shared foundation code, math lib, etc 11 | projects/ 12 | cloth/ - implementation of Cornell CS5643 assignment two (the spaghetti factory) 13 | dew/ - prototype for live motion captured graffiti demo 14 | empty/ - base for a project 15 | fem/ - co-rotational finite element demo with fracture 16 | fog/ - analytic integration of inscattering from a point light 17 | gi/ - real-time point based illumination implementation 18 | granular2d/ - granular materials in CUDA 19 | granular3d/ - granular materials in CUDA 20 | mathematica/ - misc notebooks 21 | metaballs/ - old 2d metaballs effect 22 | nanoray/ - path tracer I wrote while reading PBRT 23 | probeview/ - app to view Debevec format HDR light probes 24 | rigidbody/ - unfinished LCP rigid body solver 25 | sh/ - glossy reflections using spherical harmonics 26 | smoke/ - implementation of Fedkiw's Visual Simulation of Smoke, vortex particles and black-body rendering 27 | springs/ - implicit spring solver 28 | external/ 29 | 30 | 31 | -------------------------------------------------------------------------------- /core/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | AR = ar 4 | 5 | CFLAGS = -g -Wall -I.. -D_DEBUG 6 | ARFLAGS = cq 7 | 8 | TARGET = core.a 9 | SOURCES = $(wildcard *.cpp) 10 | HEADERS = $(wildcard *.h) 11 | 12 | OBJECTS = $(SOURCES:.cpp=.o) 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) Makefile 17 | $(AR) $(ARFLAGS) $(TARGET) $(OBJECTS) 18 | 19 | clean: 20 | -rm -f $(OBJECTS) 21 | -rm -f $(TARGET) 22 | 23 | %.o: %.cpp $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o $@ $< 25 | 26 | run: $(TARGET) 27 | ./$(TARGET) 28 | 29 | .PHONY : all clean 30 | -------------------------------------------------------------------------------- /core/aabbtree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core.h" 4 | #include "maths.h" 5 | 6 | #include 7 | 8 | class AABBTree 9 | { 10 | AABBTree(const AABBTree&); 11 | AABBTree& operator=(const AABBTree&); 12 | 13 | public: 14 | 15 | AABBTree(const Point3* vertices, uint32_t numVerts, const uint32_t* indices, uint32_t numFaces); 16 | 17 | bool TraceRaySlow(const Point3& start, const Vector3& dir, float& outT, float& u, float& v, float& w, float& faceSign, uint32_t& faceIndex) const; 18 | bool TraceRay(const Point3& start, const Vector3& dir, float& outT, float& u, float& v, float& w, float& faceSign, uint32_t& faceIndex) const; 19 | 20 | void DebugDraw(); 21 | 22 | Vector3 GetCenter() const { return (m_nodes[0].m_minExtents+m_nodes[0].m_maxExtents)*0.5f; } 23 | Vector3 GetMinExtents() const { return m_nodes[0].m_minExtents; } 24 | Vector3 GetMaxExtents() const { return m_nodes[0].m_maxExtents; } 25 | 26 | #if _WIN32 27 | // stats (reset each trace) 28 | static uint32_t GetTraceDepth() { return s_traceDepth; } 29 | #endif 30 | 31 | private: 32 | 33 | void DebugDrawRecursive(uint32_t nodeIndex, uint32_t depth); 34 | 35 | struct Node 36 | { 37 | Node() 38 | : m_numFaces(0) 39 | , m_faces(NULL) 40 | , m_minExtents(0.0f) 41 | , m_maxExtents(0.0f) 42 | { 43 | } 44 | 45 | union 46 | { 47 | uint32_t m_children; 48 | uint32_t m_numFaces; 49 | }; 50 | 51 | uint32_t* m_faces; 52 | Vector3 m_minExtents; 53 | Vector3 m_maxExtents; 54 | }; 55 | 56 | 57 | struct Bounds 58 | { 59 | Bounds() : m_min(0.0f), m_max(0.0f) 60 | { 61 | } 62 | 63 | Bounds(const Vector3& min, const Vector3& max) : m_min(min), m_max(max) 64 | { 65 | } 66 | 67 | inline float GetVolume() const 68 | { 69 | Vector3 e = m_max-m_min; 70 | return (e.x*e.y*e.z); 71 | } 72 | 73 | inline float GetSurfaceArea() const 74 | { 75 | Vector3 e = m_max-m_min; 76 | return 2.0f*(e.x*e.y + e.x*e.z + e.y*e.z); 77 | } 78 | 79 | inline void Union(const Bounds& b) 80 | { 81 | m_min = Min(m_min, b.m_min); 82 | m_max = Max(m_max, b.m_max); 83 | } 84 | 85 | Vector3 m_min; 86 | Vector3 m_max; 87 | }; 88 | 89 | typedef std::vector IndexArray; 90 | typedef std::vector PositionArray; 91 | typedef std::vector NodeArray; 92 | typedef std::vector FaceArray; 93 | typedef std::vector FaceBoundsArray; 94 | 95 | // partition the objects and return the number of objects in the lower partition 96 | uint32_t PartitionMedian(Node& n, uint32_t* faces, uint32_t numFaces); 97 | uint32_t PartitionSAH(Node& n, uint32_t* faces, uint32_t numFaces); 98 | 99 | void Build(); 100 | void BuildRecursive(uint32_t nodeIndex, uint32_t* faces, uint32_t numFaces); 101 | void TraceRecursive(uint32_t nodeIndex, const Point3& start, const Vector3& dir, float& outT, float& u, float& v, float& w, float& faceSign, uint32_t& faceIndex) const; 102 | 103 | void CalculateFaceBounds(uint32_t* faces, uint32_t numFaces, Vector3& outMinExtents, Vector3& outMaxExtents); 104 | uint32_t GetNumFaces() const { return m_numFaces; } 105 | uint32_t GetNumNodes() const { return m_nodes.size(); } 106 | 107 | // track the next free node 108 | uint32_t m_freeNode; 109 | 110 | const Point3* m_vertices; 111 | const uint32_t m_numVerts; 112 | 113 | const uint32_t* m_indices; 114 | const uint32_t m_numFaces; 115 | 116 | FaceArray m_faces; 117 | NodeArray m_nodes; 118 | FaceBoundsArray m_faceBounds; 119 | 120 | // stats 121 | uint32_t m_treeDepth; 122 | uint32_t m_innerNodes; 123 | uint32_t m_leafNodes; 124 | 125 | #if _WIN32 126 | _declspec (thread) static uint32_t s_traceDepth; 127 | #endif 128 | }; 129 | -------------------------------------------------------------------------------- /core/core.cpp: -------------------------------------------------------------------------------- 1 | #include "core.h" 2 | 3 | -------------------------------------------------------------------------------- /core/core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define Super __super 4 | 5 | // basically just a collection of macros and types 6 | #ifndef UNUSED 7 | #define UNUSED(x) (void)x; 8 | #endif 9 | 10 | #define NOMINMAX 11 | 12 | #if !PLATFORM_OPENCL 13 | #include 14 | #endif 15 | 16 | #include "types.h" 17 | 18 | #if !PLATFORM_SPU && !PLATFORM_OPENCL 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | // disable some warnings 27 | #if _WIN32 28 | #pragma warning(disable: 4996) // secure io 29 | #pragma warning(disable: 4100) // unreferenced param 30 | #pragma warning(disable: 4324) // structure was padded due to __declspec(align()) 31 | #endif 32 | 33 | // alignment helpers 34 | #define DEFAULT_ALIGNMENT 16 35 | 36 | #if PLATFORM_LINUX 37 | #define ALIGN_N(x) 38 | #define ENDALIGN_N(x) __attribute__ ((aligned (x))) 39 | #else 40 | #define ALIGN_N(x) __declspec(align(x)) 41 | #define END_ALIGN_N(x) 42 | #endif 43 | 44 | #define ALIGN ALIGN_N(DEFAULT_ALIGNMENT) 45 | #define END_ALIGN END_ALIGN_N(DEFAULT_ALIGNMENT) 46 | 47 | inline bool IsPowerOfTwo(int n) 48 | { 49 | return (n&(n-1))==0; 50 | } 51 | 52 | // align a ptr to a power of tow 53 | template 54 | inline T* AlignPtr(T* p, uint32_t alignment) 55 | { 56 | assert(IsPowerOfTwo(alignment)); 57 | 58 | // cast to safe ptr type 59 | uintptr_t up = reinterpret_cast(p); 60 | return (T*)((up+(alignment-1)) & ~(alignment-1)); 61 | }; 62 | 63 | // align an unsigned value to a power of two 64 | inline uint32_t Align(uint32_t val, uint32_t alignment) 65 | { 66 | assert(IsPowerOfTwo(alignment)); 67 | 68 | return (val+(alignment-1))& ~(alignment-1); 69 | } 70 | 71 | inline bool IsAligned(void* p, uint32_t alignment) 72 | { 73 | return (((uintptr_t)p) & (alignment-1)) == 0; 74 | } 75 | 76 | // Endian helpers 77 | template 78 | T ByteSwap(const T& val) 79 | { 80 | T copy = val; 81 | uint8_t* p = reinterpret_cast(©); 82 | 83 | std::reverse(p, p+sizeof(T)); 84 | 85 | return copy; 86 | } 87 | 88 | #ifndef LITTLE_ENDIAN 89 | #define LITTLE_ENDIAN WIN32 90 | #endif 91 | 92 | #ifndef BIG_ENDIAN 93 | #define BIG_ENDIAN PLATFORM_PS3 || PLATFORM_SPU 94 | #endif 95 | 96 | #if BIG_ENDIAN 97 | #define ToLittleEndian(x) ByteSwap(x) 98 | #else 99 | #define ToLittleEndian(x) x 100 | #endif 101 | 102 | //#include "platform.h" 103 | 104 | //#define sizeof_array(x) (sizeof(x)/sizeof(*x)) 105 | template 106 | size_t sizeof_array(const T (&)[N]) 107 | { 108 | return N; 109 | } 110 | 111 | // functor designed for use in the stl 112 | template 113 | class free_ptr : public std::unary_function 114 | { 115 | public: 116 | 117 | void operator()(const T* ptr) 118 | { 119 | delete ptr; 120 | } 121 | }; 122 | 123 | #if WIN32 124 | #define ThreadLocal _declspec(thread) 125 | #else 126 | #define ThreadLocal __thread 127 | #endif 128 | 129 | 130 | #if !WIN32 131 | #define stricmp strcasecmp 132 | #define strincmp strncasecmp 133 | #endif 134 | -------------------------------------------------------------------------------- /core/core.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | ..\External\freeglut-2.6.0\lib 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /core/core.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 14 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 15 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /core/hashgrid.cpp: -------------------------------------------------------------------------------- 1 | #include "hashgrid.h" 2 | 3 | // test 4 | HashGrid gTestGrid; -------------------------------------------------------------------------------- /core/log.cpp: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | 3 | #include "threading.h" 4 | #include "platform.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | Log Log::Info; 14 | Log Log::Warn; 15 | Log Log::Error; 16 | 17 | void Log::RegisterListener(LogListener* l) 18 | { 19 | std::vector::iterator iter = std::find(mListeners.begin(), mListeners.end(), l); 20 | 21 | if (iter == mListeners.end()) 22 | mListeners.push_back(l); 23 | 24 | } 25 | 26 | void Log::UnRegisterListener(LogListener* l) 27 | { 28 | std::vector::iterator iter = std::find(mListeners.begin(), mListeners.end(), l); 29 | 30 | if (iter != mListeners.end()) 31 | mListeners.erase(iter); 32 | } 33 | 34 | void Log::Flush(void) 35 | { 36 | // get string from string stream 37 | string d = m_stream.str(); 38 | 39 | // reset stream 40 | m_stream.str(""); 41 | 42 | // send to all listeners 43 | for (size_t i=0; i < mListeners.size(); i++) 44 | mListeners[i]->Output(d); 45 | 46 | // default output 47 | //std::cout << d.c_str(); 48 | } 49 | 50 | 51 | 52 | // log to file 53 | class LogFileListener : public LogListener 54 | { 55 | public: 56 | 57 | LogFileListener(const char* filename) 58 | { 59 | m_file = fopen(filename, "w"); 60 | //std::cout << "temp: " << GetTempDirectory() << std::endl; 61 | std::cout << filename << std::endl; 62 | assert(m_file); 63 | } 64 | 65 | virtual ~LogFileListener() 66 | { 67 | fclose(m_file); 68 | } 69 | 70 | virtual void Output(const string& msg) 71 | { 72 | CriticalSectionScopeLock lock(m_mutex); 73 | 74 | fwrite(msg.c_str(), msg.length(), 1, m_file); 75 | } 76 | 77 | CriticalSection m_mutex; 78 | FILE* m_file; 79 | }; 80 | 81 | #if WIN32 82 | 83 | #include 84 | 85 | 86 | // outputs to debugger console 87 | class LogDebugListener : public LogListener 88 | { 89 | public: 90 | 91 | virtual void Output(const string& msg) 92 | { 93 | OutputDebugString(msg.c_str()); 94 | std::cout << msg.c_str(); 95 | } 96 | }; 97 | 98 | #else 99 | // outputs to debugger console 100 | class LogDebugListener : public LogListener 101 | { 102 | public: 103 | 104 | virtual void Output(const string& msg) 105 | { 106 | std::cout << msg.c_str(); 107 | } 108 | }; 109 | 110 | #endif 111 | 112 | namespace 113 | { 114 | LogFileListener* gLogFileListener; 115 | LogDebugListener* gDebugListener; 116 | } 117 | 118 | // initialize default log listeners 119 | void Log::Init(const char* logFile) 120 | { 121 | gLogFileListener = new LogFileListener(logFile); 122 | gDebugListener = new LogDebugListener(); 123 | 124 | Log::Info.RegisterListener(gLogFileListener); 125 | Log::Warn.RegisterListener(gLogFileListener); 126 | Log::Error.RegisterListener(gLogFileListener); 127 | 128 | Log::Info.RegisterListener(gDebugListener); 129 | Log::Warn.RegisterListener(gDebugListener); 130 | Log::Error.RegisterListener(gDebugListener); 131 | } 132 | 133 | void Log::Shutdown() 134 | { 135 | Log::Info.UnRegisterListener(gLogFileListener); 136 | Log::Warn.UnRegisterListener(gLogFileListener); 137 | Log::Error.UnRegisterListener(gLogFileListener); 138 | 139 | Log::Info.UnRegisterListener(gDebugListener); 140 | Log::Warn.UnRegisterListener(gDebugListener); 141 | Log::Error.UnRegisterListener(gDebugListener); 142 | 143 | delete gLogFileListener; 144 | delete gDebugListener; 145 | } 146 | -------------------------------------------------------------------------------- /core/log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "types.h" 8 | 9 | class LogListener; 10 | 11 | class Log 12 | { 13 | public: 14 | 15 | Log() {}; 16 | virtual ~Log() {} 17 | 18 | //! register stream 19 | void RegisterListener(LogListener* l); 20 | void UnRegisterListener(LogListener* l); 21 | 22 | // handles std::endl which is used to mark termination of log messages 23 | //std::stringstream& operator<<(std::basic_ostream >& (*_Pfn)(std::basic_ostream >&)); 24 | std::stringstream& operator<<(std::basic_ostream >& (*_Pfn)(std::basic_ostream >&)) 25 | { 26 | _Pfn(m_stream); 27 | Flush(); 28 | 29 | return m_stream; 30 | } 31 | 32 | // logs any old thing it can convert to a string 33 | template 34 | Log& operator << (const T& v) 35 | { 36 | m_stream << v; 37 | return *this; 38 | } 39 | 40 | // create default loggers 41 | static void Init(const char* logFile="log.txt"); 42 | static void Shutdown(); 43 | 44 | // log sinks 45 | static Log Info; 46 | static Log Warn; 47 | static Log Error; 48 | 49 | private: 50 | 51 | void Flush(); 52 | 53 | // stringstream used for temp conversion 54 | std::stringstream m_stream; 55 | 56 | typedef std::vector ListenerArray; 57 | ListenerArray mListeners; 58 | 59 | }; 60 | 61 | // interface for listener classes 62 | class LogListener 63 | { 64 | public: 65 | 66 | virtual ~LogListener() {} 67 | virtual void Output(const std::string& msg)=0; 68 | 69 | private: 70 | 71 | 72 | }; 73 | -------------------------------------------------------------------------------- /core/mat22.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "maths.h" 4 | 5 | struct Matrix22 6 | { 7 | CUDA_CALLABLE Matrix22() {} 8 | CUDA_CALLABLE Matrix22(float a, float b, float c, float d) 9 | { 10 | cols[0] = Vec2(a, c); 11 | cols[1] = Vec2(b, d); 12 | } 13 | 14 | CUDA_CALLABLE Matrix22(const Vec2& c1, const Vec2& c2) 15 | { 16 | cols[0] = c1; 17 | cols[1] = c2; 18 | } 19 | 20 | CUDA_CALLABLE float operator()(int i, int j) const { return static_cast(cols[j])[i]; } 21 | CUDA_CALLABLE float& operator()(int i, int j) { return static_cast(cols[j])[i]; } 22 | 23 | Vec2 cols[2]; 24 | 25 | static inline Matrix22 Identity() { static const Matrix22 sIdentity(Vec2(1.0f, 0.0f), Vec2(0.0f, 1.0f)); return sIdentity; } 26 | }; 27 | 28 | CUDA_CALLABLE inline Matrix22 Multiply(float s, const Matrix22& m) 29 | { 30 | Matrix22 r = m; 31 | r.cols[0] *= s; 32 | r.cols[1] *= s; 33 | return r; 34 | } 35 | 36 | CUDA_CALLABLE inline Matrix22 Multiply(const Matrix22& a, const Matrix22& b) 37 | { 38 | Matrix22 r; 39 | r.cols[0] = a.cols[0]*b.cols[0].x + a.cols[1]*b.cols[0].y; 40 | r.cols[1] = a.cols[0]*b.cols[1].x + a.cols[1]*b.cols[1].y; 41 | return r; 42 | } 43 | 44 | CUDA_CALLABLE inline Matrix22 Add(const Matrix22& a, const Matrix22& b) 45 | { 46 | return Matrix22(a.cols[0]+b.cols[0], a.cols[1]+b.cols[1]); 47 | } 48 | 49 | CUDA_CALLABLE inline Vec2 Multiply(const Matrix22& a, const Vec2& x) 50 | { 51 | return a.cols[0]*x.x + a.cols[1]*x.y; 52 | } 53 | 54 | CUDA_CALLABLE inline Matrix22 operator*(float s, const Matrix22& a) { return Multiply(s, a); } 55 | CUDA_CALLABLE inline Matrix22 operator*(const Matrix22& a, float s) { return Multiply(s, a); } 56 | CUDA_CALLABLE inline Matrix22 operator*(const Matrix22& a, const Matrix22& b) { return Multiply(a, b); } 57 | CUDA_CALLABLE inline Matrix22 operator+(const Matrix22& a, const Matrix22& b) { return Add(a, b); } 58 | CUDA_CALLABLE inline Matrix22 operator-(const Matrix22& a, const Matrix22& b) { return Add(a, -1.0f*b); } 59 | CUDA_CALLABLE inline Matrix22& operator+=(Matrix22& a, const Matrix22& b) { a = a+b; return a; } 60 | CUDA_CALLABLE inline Matrix22& operator-=(Matrix22& a, const Matrix22& b) { a = a-b; return a; } 61 | CUDA_CALLABLE inline Matrix22& operator*=(Matrix22& a, float s) { a = a*s; return a; } 62 | CUDA_CALLABLE inline Vec2 operator*(const Matrix22& a, const Vec2& x) { return Multiply(a, x); } 63 | 64 | CUDA_CALLABLE inline float Determinant(const Matrix22& m) 65 | { 66 | return m(0,0)*m(1,1)-m(1,0)*m(0,1); 67 | } 68 | 69 | CUDA_CALLABLE inline Matrix22 Inverse(const Matrix22& m, float& det) 70 | { 71 | det = Determinant(m); 72 | 73 | if (fabsf(det) > FLT_EPSILON) 74 | { 75 | Matrix22 inv; 76 | inv(0,0) = m(1,1); 77 | inv(1,1) = m(0,0); 78 | inv(0,1) = -m(0,1); 79 | inv(1,0) = -m(1,0); 80 | 81 | return Multiply(1.0f/det, inv); 82 | } 83 | else 84 | { 85 | det = 0.0f; 86 | return m; 87 | } 88 | } 89 | 90 | CUDA_CALLABLE inline Matrix22 Transpose(const Matrix22& a) 91 | { 92 | Matrix22 r; 93 | r(0,0) = a(0,0); 94 | r(0,1) = a(1,0); 95 | r(1,0) = a(0,1); 96 | r(1,1) = a(1,1); 97 | return r; 98 | } 99 | 100 | CUDA_CALLABLE inline float Trace(const Matrix22& a) 101 | { 102 | return a(0,0)+a(1,1); 103 | } 104 | 105 | CUDA_CALLABLE inline Matrix22 RotationMatrix(float theta) 106 | { 107 | return Matrix22(Vec2(cosf(theta), sinf(theta)), Vec2(-sinf(theta), cosf(theta))); 108 | } 109 | 110 | // outer product of a and b, b is considered a row vector 111 | CUDA_CALLABLE inline Matrix22 Outer(const Vec2& a, const Vec2& b) 112 | { 113 | return Matrix22(a*b.x, a*b.y); 114 | } 115 | 116 | CUDA_CALLABLE inline Matrix22 QRDecomposition(const Matrix22& m) 117 | { 118 | Vec2 a = Normalize(m.cols[0]); 119 | Matrix22 q(a, PerpCCW(a)); 120 | 121 | return q; 122 | } 123 | 124 | CUDA_CALLABLE inline Matrix22 PolarDecomposition(const Matrix22& m) 125 | { 126 | /* 127 | //iterative method 128 | 129 | float det; 130 | Matrix22 q = m; 131 | 132 | for (int i=0; i < 4; ++i) 133 | { 134 | q = 0.5f*(q + Inverse(Transpose(q), det)); 135 | } 136 | */ 137 | 138 | Matrix22 q = m + Matrix22(m(1,1), -m(1,0), -m(0,1), m(0,0)); 139 | 140 | float s = Length(q.cols[0]); 141 | q.cols[0] /= s; 142 | q.cols[1] /= s; 143 | 144 | return q; 145 | } 146 | 147 | 148 | -------------------------------------------------------------------------------- /core/mat33.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "maths.h" 4 | 5 | struct Matrix33 6 | { 7 | CUDA_CALLABLE Matrix33() {} 8 | CUDA_CALLABLE Matrix33(const Vec3& c1, const Vec3& c2, const Vec3& c3) 9 | { 10 | cols[0] = c1; 11 | cols[1] = c2; 12 | cols[2] = c3; 13 | } 14 | 15 | CUDA_CALLABLE float operator()(int i, int j) const { return static_cast(cols[j])[i]; } 16 | CUDA_CALLABLE float& operator()(int i, int j) { return static_cast(cols[j])[i]; } 17 | 18 | Vec3 cols[3]; 19 | 20 | static inline Matrix33 Identity() { static const Matrix33 sIdentity(Vec3(1.0f, 0.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f), Vec3(0.0f, 0.0f, 1.0f)); return sIdentity; } 21 | }; 22 | 23 | CUDA_CALLABLE inline Matrix33 Multiply(float s, const Matrix33& m) 24 | { 25 | Matrix33 r = m; 26 | r.cols[0] *= s; 27 | r.cols[1] *= s; 28 | r.cols[2] *= s; 29 | return r; 30 | } 31 | 32 | CUDA_CALLABLE inline Vec3 Multiply(const Matrix33& a, const Vec3& x) 33 | { 34 | return a.cols[0]*x.x + a.cols[1]*x.y + a.cols[2]*x.z; 35 | } 36 | 37 | CUDA_CALLABLE inline Vec3 operator*(const Matrix33& a, const Vec3& x) { return Multiply(a, x); } 38 | 39 | CUDA_CALLABLE inline Matrix33 Multiply(const Matrix33& a, const Matrix33& b) 40 | { 41 | Matrix33 r; 42 | r.cols[0] = a*b.cols[0]; 43 | r.cols[1] = a*b.cols[1]; 44 | r.cols[2] = a*b.cols[2]; 45 | return r; 46 | } 47 | 48 | CUDA_CALLABLE inline Matrix33 Add(const Matrix33& a, const Matrix33& b) 49 | { 50 | return Matrix33(a.cols[0]+b.cols[0], a.cols[1]+b.cols[1], a.cols[2]+b.cols[2]); 51 | } 52 | 53 | CUDA_CALLABLE inline float Determinant(const Matrix33& m) 54 | { 55 | return Dot(m.cols[0], Cross(m.cols[1], m.cols[2])); 56 | } 57 | 58 | CUDA_CALLABLE inline Matrix33 Transpose(const Matrix33& a) 59 | { 60 | Matrix33 r; 61 | for (uint32_t i=0; i < 3; ++i) 62 | for(uint32_t j=0; j < 3; ++j) 63 | r(i, j) = a(j, i); 64 | 65 | return r; 66 | } 67 | 68 | CUDA_CALLABLE inline float Trace(const Matrix33& a) 69 | { 70 | return a(0,0)+a(1,1)+a(2,2); 71 | } 72 | 73 | CUDA_CALLABLE inline Matrix33 Outer(const Vec3& a, const Vec3& b) 74 | { 75 | return Matrix33(a*b.x, a*b.y, a*b.z); 76 | } 77 | 78 | CUDA_CALLABLE inline Matrix33 operator*(float s, const Matrix33& a) { return Multiply(s, a); } 79 | CUDA_CALLABLE inline Matrix33 operator*(const Matrix33& a, float s) { return Multiply(s, a); } 80 | CUDA_CALLABLE inline Matrix33 operator*(const Matrix33& a, const Matrix33& b) { return Multiply(a, b); } 81 | CUDA_CALLABLE inline Matrix33 operator+(const Matrix33& a, const Matrix33& b) { return Add(a, b); } 82 | CUDA_CALLABLE inline Matrix33 operator-(const Matrix33& a, const Matrix33& b) { return Add(a, -1.0f*b); } 83 | CUDA_CALLABLE inline Matrix33& operator+=(Matrix33& a, const Matrix33& b) { a = a+b; return a; } 84 | CUDA_CALLABLE inline Matrix33& operator-=(Matrix33& a, const Matrix33& b) { a = a-b; return a; } 85 | CUDA_CALLABLE inline Matrix33& operator*=(Matrix33& a, float s) { a.cols[0]*=s; a.cols[1]*=s; a.cols[2]*=s; return a; } 86 | 87 | 88 | -------------------------------------------------------------------------------- /core/maths.cpp: -------------------------------------------------------------------------------- 1 | #include "maths.h" 2 | 3 | uint32_t seed1; 4 | uint32_t seed2; 5 | 6 | void RandInit() 7 | { 8 | seed1 = 315645664; 9 | seed2 = seed1 ^ 0x13ab45fe; 10 | } 11 | 12 | static float s_identity[4][4] = { {1.0f, 0.0f, 0.0f, 0.0f}, 13 | {0.0f, 1.0f, 0.0f, 0.0f}, 14 | {0.0f, 0.0f, 1.0f, 0.0f}, 15 | {0.0f, 0.0f, 0.0f, 1.0f} }; 16 | 17 | template <> 18 | XMatrix44 XMatrix44::kIdentity(s_identity[0]); 19 | 20 | 21 | Colour::Colour(Colour::Preset p) 22 | { 23 | switch (p) 24 | { 25 | case kRed: 26 | *this = Colour(1.0f, 0.0f, 0.0f); 27 | break; 28 | case kGreen: 29 | *this = Colour(0.0f, 1.0f, 0.0f); 30 | break; 31 | case kBlue: 32 | *this = Colour(0.0f, 0.0f, 1.0f); 33 | break; 34 | case kWhite: 35 | *this = Colour(1.0f, 1.0f, 1.0f); 36 | break; 37 | case kBlack: 38 | *this = Colour(0.0f, 0.0f, 0.0f); 39 | break; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /core/memory.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/core/memory.cpp -------------------------------------------------------------------------------- /core/memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include 6 | 7 | inline void* AlignedMalloc(size_t size,int byteAlign) 8 | { 9 | void *mallocPtr = malloc(size + byteAlign + sizeof(void*)); 10 | size_t ptrInt = (size_t)mallocPtr; 11 | 12 | ptrInt = (ptrInt + byteAlign + sizeof(void*)) / byteAlign * byteAlign; 13 | *(((void**)ptrInt) - 1) = mallocPtr; 14 | 15 | return (void*)ptrInt; 16 | } 17 | 18 | inline void AlignedFree(void *ptr) 19 | { 20 | free(*(((void**)ptr) - 1)); 21 | } 22 | 23 | // temporary allocation storage, used to reduce load on crt malloc 24 | class MemoryArena 25 | { 26 | public: 27 | 28 | MemoryArena(const uint32_t sizeInBytes) 29 | { 30 | m_mem = (uint8_t*)AlignedMalloc(sizeInBytes, 16); 31 | m_size = sizeInBytes; 32 | m_head = m_mem; 33 | } 34 | 35 | ~MemoryArena() 36 | { 37 | AlignedFree(m_mem); 38 | } 39 | 40 | uint8_t* Allocate(uint32_t size) 41 | { 42 | if ((m_head+size)-m_mem > ptrdiff_t(m_size)) 43 | { 44 | assert(!"Arena ran out of memory"); 45 | return NULL; 46 | } 47 | 48 | uint8_t* p = m_head; 49 | m_head += size; 50 | 51 | return p; 52 | } 53 | 54 | void Reset() 55 | { 56 | m_head = m_mem; 57 | } 58 | 59 | uint8_t* m_mem; 60 | uint8_t* m_head; 61 | uint32_t m_size; 62 | }; 63 | 64 | // version of placement new to support usage as: new (MemArena) Type(); 65 | inline void* operator new (size_t s, MemoryArena& a) 66 | { 67 | return a.Allocate(s); 68 | } 69 | 70 | // not used but compiler will complain without it 71 | inline void operator delete(void*, MemoryArena&) 72 | { 73 | } 74 | -------------------------------------------------------------------------------- /core/mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "core.h" 6 | #include "maths.h" 7 | 8 | struct Mesh 9 | { 10 | void AddMesh(Mesh& m); 11 | 12 | uint32_t GetNumVertices() const { return m_positions.size(); } 13 | uint32_t GetNumFaces() const { return m_indices.size() / 3; } 14 | 15 | void DuplicateVertex(uint32_t i); 16 | 17 | void CalculateNormals(); 18 | void Transform(const Matrix44& m); 19 | 20 | void GetBounds(Vector3& minExtents, Vector3& maxExtents) const; 21 | 22 | std::vector m_positions; 23 | std::vector m_normals; 24 | std::vector m_texcoords[2]; 25 | std::vector m_colours; 26 | 27 | std::vector m_indices; 28 | }; 29 | 30 | // create mesh from file 31 | Mesh* ImportMeshFromObj(const char* path); 32 | Mesh* ImportMeshFromPly(const char* path); 33 | 34 | // create procedural primitives 35 | Mesh* CreateQuadMesh(float size, float y=0.0f); 36 | Mesh* CreateDiscMesh(float radius, uint32_t segments); 37 | 38 | // unwrap the mesh, 39 | void UvAtlas(Mesh* m); 40 | -------------------------------------------------------------------------------- /core/meshuv.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/core/meshuv.cpp -------------------------------------------------------------------------------- /core/perlin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | float Perlin1D(float x, int octaves, float persistence); 4 | float Perlin2D(float x, float y, int octaves, float persistence); 5 | float Perlin3D(float x, float y, float z, int octaves, float persistence); 6 | 7 | // periodic versions of the same function, inspired by the Renderman pnoise() functions 8 | float Perlin3DPeriodic(float x, float y, float z, int px, int py, int pz, int octaves, float persistence); 9 | -------------------------------------------------------------------------------- /core/pfm.cpp: -------------------------------------------------------------------------------- 1 | #include "pfm.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace 9 | { 10 | // RAII wrapper to handle file pointer clean up 11 | struct FilePointer 12 | { 13 | FilePointer(FILE* ptr) : p(ptr) {} 14 | ~FilePointer() { if (p) fclose(p); } 15 | 16 | operator FILE*() { return p; } 17 | 18 | FILE* p; 19 | }; 20 | } 21 | 22 | bool PfmLoad(const char* filename, PfmImage& image) 23 | { 24 | FilePointer f = fopen(filename, "rb"); 25 | if (!f) 26 | return false; 27 | 28 | memset(&image, 0, sizeof(PfmImage)); 29 | 30 | const uint32_t kBufSize = 1024; 31 | char buffer[kBufSize]; 32 | 33 | if (!fgets(buffer, kBufSize, f)) 34 | return false; 35 | 36 | if (strcmp(buffer, "PF\n") != 0) 37 | return false; 38 | 39 | if (!fgets(buffer, kBufSize, f)) 40 | return false; 41 | 42 | image.m_depth = 1; 43 | sscanf(buffer, "%d %d %d", &image.m_width, &image.m_height, &image.m_depth); 44 | 45 | if (!fgets(buffer, kBufSize, f)) 46 | return false; 47 | 48 | sscanf(buffer, "%f", &image.m_maxDepth); 49 | 50 | uint32_t dataStart = ftell(f); 51 | fseek(f, 0, SEEK_END); 52 | uint32_t dataEnd = ftell(f); 53 | fseek(f, dataStart, SEEK_SET); 54 | 55 | uint32_t dataSize = dataEnd-dataStart; 56 | 57 | // must be 4 byte aligned 58 | assert((dataSize&0x3) == 0); 59 | 60 | image.m_data = new float[dataSize/4]; 61 | 62 | if (fread(image.m_data, dataSize, 1, f) != 1) 63 | return false; 64 | 65 | return true; 66 | } 67 | 68 | void PfmSave(const char* filename, const PfmImage& image) 69 | { 70 | FILE* f = fopen(filename, "wb"); 71 | if (!f) 72 | return; 73 | 74 | fprintf(f, "PF\n"); 75 | if (image.m_depth > 1) 76 | fprintf(f, "%d %d %d\n", image.m_width, image.m_height, image.m_depth); 77 | else 78 | fprintf(f, "%d %d\n", image.m_width, image.m_height); 79 | 80 | fprintf(f, "%f\n", *std::max_element(image.m_data, image.m_data+(image.m_width*image.m_height*image.m_depth))); 81 | 82 | fwrite(image.m_data, image.m_width*image.m_height*image.m_depth*sizeof(float), 1, f); 83 | } 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /core/pfm.h: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | 3 | struct PfmImage 4 | { 5 | // set m_depth to 1 for standard pfm compatability, > 1 will act as a volume texture (non-standard) 6 | uint32_t m_width; 7 | uint32_t m_height; 8 | uint32_t m_depth; 9 | 10 | // optional 11 | float m_maxDepth; 12 | 13 | float* m_data; 14 | }; 15 | 16 | bool PfmLoad(const char* filename, PfmImage& image); 17 | void PfmSave(const char* filename, const PfmImage& image); 18 | -------------------------------------------------------------------------------- /core/platform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "log.h" 5 | 6 | #include 7 | #include 8 | 9 | // system functions 10 | double GetSeconds(); 11 | void Sleep(double seconds); 12 | 13 | // helper function to get exe path 14 | std::string GetExePath(); 15 | std::string GetWorkingDirectory(); 16 | 17 | // shows a file open dialog 18 | std::string FileOpenDialog(char *filter = "All Files (*.*)\0*.*\0"); 19 | 20 | // pulls out an option in the form option=value, must have no spaces 21 | template 22 | bool GetCmdLineArg(const char* arg, T& out, int argc, char* argv[]) 23 | { 24 | // iterate over all the arguments 25 | for (int i=0; i < argc; ++i) 26 | { 27 | const char* s1 = arg; 28 | const char* s2 = argv[i]; 29 | 30 | while (*s1 && *s2 && *s1 == *s2) 31 | { 32 | ++s1; 33 | ++s2; 34 | } 35 | 36 | // we've found the flag we're looking for 37 | if (*s1 == 0 && *s2 == '=') 38 | { 39 | ++s2; 40 | 41 | // build a string stream and output 42 | std::istringstream is(s2); 43 | if (is >> out) 44 | { 45 | return true; 46 | } 47 | else 48 | return false; 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | // return the full path to a file 55 | std::string ExpandPath(const char* path); 56 | // takes a full file path and returns just the folder (with trailing slash) 57 | std::string StripFilename(const char* path); 58 | // strips the path from a file name 59 | std::string StripPath(const char* path); 60 | // strips the extension from a path 61 | std::string StripExtension(const char* path); 62 | // returns the file extension (excluding period) 63 | std::string GetExtension(const char* path); 64 | // normalize path 65 | std::string NormalizePath(const char* path); 66 | 67 | // loads a file to a text string 68 | std::string LoadFileToString(const char* filename); 69 | // loads a file to a binary buffer (free using delete[]) 70 | uint8_t* LoadFileToBuffer(const char* filename, uint32_t* sizeRead=NULL); 71 | // save whole string to a file 72 | bool SaveStringToFile(const char* filename, const char* s); 73 | 74 | bool FileMove(const char* src, const char* dest); 75 | bool FileScan(const char* pattern, std::vector& files); 76 | 77 | // file system stuff 78 | const uint32_t kMaxPathLength = 2048; 79 | 80 | #ifdef WIN32 81 | 82 | // defined these explicitly because don't want to include windowsx.h 83 | #define GET_WPARAM(wp, lp) (wp) 84 | #define GET_LPARAM(wp, lp) (lp) 85 | 86 | #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) 87 | #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) 88 | 89 | #define vsnprintf _vsnprintf 90 | #define snprintf _snprintf 91 | #define vsnwprintf _vsnwprintf 92 | 93 | #if _MSC_VER >= 1400 //vc8.0 use new secure 94 | #define snwprintf _snwprintf_s 95 | #else 96 | #define snwprintf _snwprintf 97 | #endif // _MSC_VER 98 | 99 | #endif // WIN32 100 | 101 | #if PLATFORM_IOS 102 | inline std::string ExpandPath(const char* p) 103 | { 104 | NSString *imagePath = [NSString stringWithUTF8String:p]; 105 | NSString *fullPath = [[NSBundle mainBundle] pathForResource:[imagePath lastPathComponent] ofType:nil inDirectory:[imagePath stringByDeletingLastPathComponent]]; 106 | 107 | if (fullPath) 108 | { 109 | std::string s = [fullPath cStringUsingEncoding:1]; 110 | return s; 111 | } 112 | else 113 | { 114 | Log::Info << "Failed to map path for : " << p << std::endl; 115 | return std::string(""); 116 | } 117 | } 118 | inline std::string GetTempDirectory() 119 | { 120 | NSString* tmp = NSTemporaryDirectory(); 121 | std::string s = [tmp cStringUsingEncoding:1]; 122 | 123 | return s; 124 | } 125 | 126 | inline std::string DataPath(const char* p) 127 | { 128 | return ExpandPath((std::string("DataCooked/") + p).c_str()); 129 | } 130 | 131 | #else 132 | 133 | inline std::string ExpandPath(const char* p) 134 | { 135 | return p; 136 | } 137 | 138 | inline std::string DataPath(const char* p) 139 | { 140 | return ExpandPath((std::string("Data/") + p).c_str()); 141 | 142 | } 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /core/png.cpp: -------------------------------------------------------------------------------- 1 | #include "png.h" 2 | #include "log.h" 3 | 4 | #include 5 | 6 | #include "external/stb_image/stb_image.c" 7 | 8 | bool PngLoad(const char* filename, PngImage& image) 9 | { 10 | int x, y, c; 11 | 12 | uint8_t* data = stbi_png_load(filename, &x, &y, &c, 4); 13 | 14 | if (data) 15 | { 16 | int s = x*y; 17 | 18 | image.m_data = new uint32_t[s]; 19 | memcpy(image.m_data, data, s*4); 20 | 21 | image.m_width = (uint16)x; 22 | image.m_height = (uint16)y; 23 | 24 | stbi_image_free(data); 25 | 26 | Log::Info << "Loaded png " << filename << image.m_width << ", " << image.m_height << std::endl; 27 | return true; 28 | } 29 | else 30 | { 31 | Log::Info << "Could not find " << filename << " for loading" << std::endl; 32 | return false; 33 | } 34 | } 35 | 36 | #if 0 37 | 38 | bool PngLoad(const char* filename, PngImage& image) 39 | { 40 | png_structp png_ptr; 41 | png_infop info_ptr; 42 | //unsigned int sig_read = 0; 43 | png_uint_32 width, height; 44 | int bit_depth, color_type, interlace_type; 45 | FILE *fp; 46 | 47 | if ((fp = fopen(filename, "rb")) == NULL) 48 | return NULL; 49 | 50 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 51 | NULL, NULL, NULL); 52 | 53 | if (png_ptr == NULL) 54 | { 55 | fclose(fp); 56 | return NULL; 57 | } 58 | 59 | /* Allocate/initialize the memory for image information. REQUIRED. */ 60 | info_ptr = png_create_info_struct(png_ptr); 61 | if (info_ptr == NULL) 62 | { 63 | fclose(fp); 64 | png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); 65 | return false; 66 | } 67 | 68 | /* Set error handling if you are using the setjmp/longjmp method (this is 69 | * the normal method of doing things with libpng). REQUIRED unless you 70 | * set up your own error handlers in the png_create_read_struct() earlier. 71 | */ 72 | if (setjmp(png_ptr->jmpbuf)) 73 | { 74 | /* Free all of the memory associated with the png_ptr and info_ptr */ 75 | png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); 76 | fclose(fp); 77 | /* If we get here, we had a problem reading the file */ 78 | return false; 79 | } 80 | 81 | png_init_io(png_ptr, fp); 82 | png_read_info(png_ptr, info_ptr); 83 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 84 | &interlace_type, NULL, NULL); 85 | 86 | /* Add filler (or alpha) uint8_t (before/after each RGB triplet) */ 87 | png_set_expand(png_ptr); 88 | png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); 89 | //png_set_gray_1_2_4_to_8(png_ptr); 90 | png_set_palette_to_rgb(png_ptr); 91 | png_set_gray_to_rgb(png_ptr); 92 | 93 | //png_set_bgr(png_ptr); 94 | 95 | int aNumBytes = png_get_rowbytes(png_ptr, info_ptr) * height; 96 | 97 | uint32_t* aBits = new uint32_t[aNumBytes/4]; 98 | 99 | for (uint32_t i = 0; i < height; i++) 100 | { 101 | png_bytep anAddr = (png_bytep) &aBits[i*width]; 102 | png_read_rows(png_ptr, (png_bytepp) &anAddr, NULL, 1); 103 | } 104 | 105 | std::cout << filename << " " << width << " " << height << " : " << interlace_type << std::endl; 106 | 107 | image.m_data = (uint32_t*)aBits; 108 | image.m_width = (uint16)width; 109 | image.m_height = (uint16)height; 110 | 111 | return true; 112 | } 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /core/png.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | struct PngImage 6 | { 7 | uint16_t m_width; 8 | uint16_t m_height; 9 | 10 | // pixels are always assumed to be 32 bit 11 | uint32_t* m_data; 12 | }; 13 | 14 | bool PngLoad(const char* filename, PngImage& image); 15 | -------------------------------------------------------------------------------- /core/point3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "vec4.h" 6 | 7 | class Point3 8 | { 9 | public: 10 | 11 | Point3() : x(0), y(0), z(0) {} 12 | Point3(float a) : x(a), y(a), z(a) {} 13 | Point3(const float* p) : x(p[0]), y(p[1]), z(p[2]) {} 14 | Point3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) 15 | { 16 | Validate(); 17 | } 18 | 19 | explicit Point3(const Vec3& v) : x(v.x), y(v.y), z(v.z) {} 20 | 21 | operator float* () { return &x; } 22 | operator const float* () const { return &x; }; 23 | operator Vec4 () const { return Vec4(x, y, z, 1.0f); } 24 | 25 | void Set(float x_, float y_, float z_) { Validate(); x = x_; y = y_; z = z_;} 26 | 27 | Point3 operator * (float scale) const { Point3 r(*this); r *= scale; Validate(); return r; } 28 | Point3 operator / (float scale) const { Point3 r(*this); r /= scale; Validate(); return r; } 29 | Point3 operator + (const Vec3& v) const { Point3 r(*this); r += v; Validate(); return r; } 30 | Point3 operator - (const Vec3& v) const { Point3 r(*this); r -= v; Validate(); return r; } 31 | 32 | Point3& operator *=(float scale) {x *= scale; y *= scale; z*= scale; Validate(); return *this;} 33 | Point3& operator /=(float scale) {float s(1.0f/scale); x *= s; y *= s; z *= s; Validate(); return *this;} 34 | Point3& operator +=(const Vec3& v) {x += v.x; y += v.y; z += v.z; Validate(); return *this;} 35 | Point3& operator -=(const Vec3& v) {x -= v.x; y -= v.y; z -= v.z; Validate(); return *this;} 36 | 37 | bool operator != (const Point3& v) const { return (x != v.x || y != v.y || z != v.z); } 38 | 39 | // negate 40 | Point3 operator -() const { Validate(); return Point3(-x, -y, -z); } 41 | 42 | float x,y,z; 43 | 44 | void Validate() const 45 | { 46 | } 47 | }; 48 | 49 | // lhs scalar scale 50 | inline Point3 operator *(float lhs, const Point3& rhs) 51 | { 52 | Point3 r(rhs); 53 | r *= lhs; 54 | return r; 55 | } 56 | 57 | inline Vec3 operator-(const Point3& lhs, const Point3& rhs) 58 | { 59 | return Vec3(lhs.x-rhs.x,lhs.y-rhs.y, lhs.z-rhs.z); 60 | } 61 | 62 | inline Point3 operator+(const Point3& lhs, const Point3& rhs) 63 | { 64 | return Point3(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z); 65 | } 66 | 67 | inline bool operator==(const Point3& lhs, const Point3& rhs) 68 | { 69 | return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 70 | } 71 | 72 | inline std::ostream& operator << (std::ostream& s, const Point3& p) 73 | { 74 | return s << p.x << "," << p.y << "," << p.z; 75 | } 76 | 77 | // component wise min max functions 78 | inline Point3 Max(const Point3& a, const Point3& b) 79 | { 80 | return Point3(std::max(a.x, b.x), std::max(a.y, b.y), std::max(a.z, b.z)); 81 | } 82 | 83 | inline Point3 Min(const Point3& a, const Point3& b) 84 | { 85 | return Point3(std::min(a.x, b.x), std::min(a.y, b.y), std::min(a.z, b.z)); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /core/radix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Radix.cpp 3 | * Cloth 4 | * 5 | * Created by Miles Macklin on 6/04/11. 6 | * Copyright 2011 None. All rights reserved. 7 | * 8 | */ 9 | 10 | #include "radix.h" 11 | 12 | -------------------------------------------------------------------------------- /core/radix.h: -------------------------------------------------------------------------------- 1 | #include "core.h" 2 | 3 | void radix_sort(uint32_t* begin, uint32_t* end, uint32_t* auxBegin, uint32_t* auxEnd) 4 | { 5 | static uint32_t tables[2][1 << 16]; 6 | memset(tables, 0, sizeof(tables)); 7 | 8 | // build histograms 9 | for (Iter iter=begin; iter != end; ++iter) 10 | { 11 | const uint16_t low = (*iter) & 0xffff; 12 | const uint16_t high = (*iter) >> 16; 13 | 14 | ++tables[0][low]; 15 | ++tables[1][high]; 16 | } 17 | 18 | // convert histograms to offset tables in-place 19 | uint32_t offlow = 0; 20 | uint32_t offhigh = 0; 21 | 22 | for (uint32_t i=0; i < 65536; ++i) 23 | { 24 | const uint32_t newofflow = offlow + tables[0][i]; 25 | const uint32_t newoffhigh = offhigh + tables[1][i]; 26 | 27 | tables[0][i] = offlow; 28 | tables[1][i] = offhigh; 29 | 30 | offlow = newofflow; 31 | offhigh = newoffhigh; 32 | } 33 | 34 | // pass 1 - sort by low 16 bits 35 | for (uint32_t* iter=begin; iter != end; ++iter) 36 | { 37 | // lookup offset of input 38 | const uint32_t x = *iter; 39 | const uint32_t i = x & 0xffff; 40 | 41 | // find offset and increment 42 | const uint32_t offset = tables[0][i]++; 43 | 44 | auxBegin[offset] = x; 45 | } 46 | 47 | // pass 2 - sort by high 16 bits 48 | for (uint32_t* iter=auxBegin; iter != auxEnd; ++iter) 49 | { 50 | // lookup offset of input 51 | const uint32_t x = *iter; 52 | const uint32_t i = x >> 16; 53 | 54 | const uint32_t offset = tables[1][i]++; 55 | 56 | begin[offset] = x; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/sdf.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/core/sdf.cpp -------------------------------------------------------------------------------- /core/sdf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/core.h" 4 | #include "core/maths.h" 5 | 6 | // 2d and 3d signed distance field computation using fast marching method (FMM), output array 7 | // should be the same size as input, non-zero input pixels will have distance < 0.0f, resulting 8 | // distance is scaled by 1 / max(dimension) 9 | void MakeSDF(const uint32_t* input, uint32_t width, uint32_t height, float* output); 10 | void MakeSDF(const uint32_t* input, uint32_t width, uint32_t height, uint32_t depth, float* output); 11 | -------------------------------------------------------------------------------- /core/shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if _WIN32 4 | 5 | #include 6 | 7 | #if USE_FREEGLUT 8 | #include 9 | #else 10 | #include 11 | #endif 12 | 13 | #elif __APPLE__ 14 | #define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED 15 | #include 16 | #include 17 | #elif PLATFORM_IOS 18 | 19 | #if OGL1 20 | #import 21 | #import 22 | #import 23 | #else 24 | #import 25 | #import 26 | #endif 27 | 28 | #endif 29 | 30 | #include "core/maths.h" 31 | 32 | #define glVerify(x) {x; glAssert(#x, __LINE__, __FILE__);} 33 | void glAssert(const char* msg, long line, const char* file); 34 | 35 | GLuint CompileProgramFromFile(const char *vertexPath, const char *fragmentPath); 36 | GLuint CompileProgram(const char *vsource=NULL, const char *fsource=NULL, const char* gsource=NULL); 37 | GLuint CompileProgram(const char *vsource, const char* csource, const char* esource, const char* fsource); 38 | 39 | void DrawPlane(const Vec4& p, bool color=true); 40 | void DrawString(int x, int y, const char* s, ...); 41 | void DrawFrustum(const Matrix44& projToWorld); 42 | -------------------------------------------------------------------------------- /core/skylight.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/core/skylight.cpp -------------------------------------------------------------------------------- /core/skylight.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/maths.h" 4 | 5 | // implements Perez's model for sky luminance 6 | inline float SkyDistribution(float theta, float gamma, float a, float b, float c, float d, float e) 7 | { 8 | float cosGamma = cosf(gamma); 9 | float cosTheta = cosf(theta); 10 | 11 | return (1.0f + a*expf(b / cosTheta))*(1.0f + c*expf(d*gamma) + e*cosGamma*cosGamma); 12 | } 13 | 14 | inline float SkyLuminance(float theta, float gamma, float zenith, float sunTheta, float a, float b, float c, float d, float e) 15 | { 16 | float l = zenith * (SkyDistribution(theta, gamma, a, b, c, d, e) / SkyDistribution(0.0f, sunTheta, a, b, c, d, e)); 17 | return l; 18 | } 19 | 20 | inline float Lerp2(const float ab[2], float t) 21 | { 22 | return ab[0]*t + ab[1]; 23 | } 24 | 25 | inline Colour SkyLight(float theta, float phi, float sunTheta, float sunPhi, float t) 26 | { 27 | // need cosTheta > 0.0 28 | theta = Clamp(theta, 0.0f, kPi*0.5f-1.0e-6f); 29 | 30 | // calculate arc-length between sun and patch being calculated 31 | const float gamma = acosf(cosf(sunTheta)*cosf(theta) + sinf(sunTheta)*sinf(theta)*cosf(abs(phi-sunPhi))); 32 | 33 | const float xcoeff [5][2] = { { -0.0193f, -0.2592f }, 34 | { -0.0665f, 0.0008f }, 35 | { -0.0004f, 0.2125f }, 36 | { -0.0641f, -0.8989f }, 37 | { -0.0033f, 0.0452f } }; 38 | 39 | const float ycoeff [5][2] = { {-0.0167f, -0.2608f }, 40 | { -0.0950f, 0.0092f }, 41 | { -0.0079f, 0.2102f }, 42 | { -0.0441f, -1.6537f }, 43 | { -0.0109f, 0.0529f } }; 44 | 45 | const float Ycoeff [5][2] = { { 0.1787f, -1.4630f }, 46 | { -0.3554f, 0.4275f }, 47 | { -0.0227f, 5.3251f }, 48 | { 0.1206f, -2.5771f }, 49 | { -0.0670f, 0.3703f } }; 50 | 51 | const Matrix44 zxcoeff(0.00166f, -0.02903f, 0.11693f, 0.0f, 52 | -0.00375f, 0.06377f, -0.21196f, 0.0f, 53 | 0.00209f, -0.03202f, 0.06052f, 0.0f, 54 | 0.0f, 0.00394f, 0.25886f, 0.0f); 55 | 56 | const Matrix44 zycoeff(0.00275f, -0.04214f, 0.15346f, 0.0f, 57 | -0.00610f, 0.08970f, -0.26756f, 0.0f, 58 | 0.00317f, -0.04153f, 0.06670f, 0.0f, 59 | 0.0f, 0.00516f, 0.26688f, 0.0f); 60 | 61 | 62 | const Vec4 b(sunTheta*sunTheta*sunTheta, sunTheta*sunTheta, sunTheta, 1.0f); 63 | const Vec4 a(t*t, t, 1.0f, 0.0f); 64 | 65 | // calculate the zenith values for current turbidity and sun position 66 | const float zx = Dot3(a, zxcoeff*b); 67 | const float zy = Dot3(a, zycoeff*b); 68 | const float zY = (4.0453f * t - 4.9710f)*tanf((4.0f/9.0f - t/120.0f)*(kPi-2.0f*sunTheta)) - 0.2155f*t + 2.4192f; 69 | 70 | float x = SkyLuminance(theta, gamma, zx, sunTheta, Lerp2(xcoeff[0], t), 71 | Lerp2(xcoeff[1], t), 72 | Lerp2(xcoeff[2], t), 73 | Lerp2(xcoeff[3], t), 74 | Lerp2(xcoeff[4], t)); 75 | 76 | 77 | float y = SkyLuminance(theta, gamma, zy, sunTheta, Lerp2(ycoeff[0], t), 78 | Lerp2(ycoeff[1], t), 79 | Lerp2(ycoeff[2], t), 80 | Lerp2(ycoeff[3], t), 81 | Lerp2(ycoeff[4], t)); 82 | 83 | float Y = SkyLuminance(theta, gamma, zY, sunTheta, Lerp2(Ycoeff[0], t), 84 | Lerp2(Ycoeff[1], t), 85 | Lerp2(Ycoeff[2], t), 86 | Lerp2(Ycoeff[3], t), 87 | Lerp2(Ycoeff[4], t)); 88 | 89 | 90 | // convert Yxy to XYZ and then to RGB 91 | Colour XYZ = YxyToXYZ(Y, x, y); 92 | Colour RGB = XYZToLinear(XYZ.r, XYZ.g, XYZ.b); 93 | 94 | return RGB; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /core/tga.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include 6 | 7 | struct TgaImage 8 | { 9 | uint32_t SampleClamp(int x, int y) const 10 | { 11 | uint32_t ix = std::min(std::max(0, x), int(m_width-1)); 12 | uint32_t iy = std::min(std::max(0, y), int(m_height-1)); 13 | 14 | return m_data[iy*m_width + ix]; 15 | } 16 | 17 | uint16_t m_width; 18 | uint16_t m_height; 19 | 20 | // pixels are always assumed to be 32 bit 21 | uint32_t* m_data; 22 | }; 23 | 24 | bool TgaSave(const char* filename, const TgaImage& image, bool rle=false); 25 | bool TgaLoad(const char* filename, TgaImage& image); 26 | void TgaFree(const TgaImage& image); 27 | -------------------------------------------------------------------------------- /core/threadgroup.cpp: -------------------------------------------------------------------------------- 1 | #include "threadgroup.h" 2 | 3 | #include "platform.h" 4 | 5 | #include 6 | #include 7 | 8 | #include "memory.h" 9 | 10 | #if defined(_WIN32) 11 | 12 | using namespace std; 13 | 14 | // these two things should not be here 15 | _declspec(thread) MemoryArena* g_memArena; 16 | 17 | DWORD WINAPI ThreadPool::WorkerMain(void* data) 18 | { 19 | 20 | if (data == NULL) 21 | return 0; 22 | 23 | ThreadPool* pool = (ThreadPool*)(data); 24 | 25 | //double start = GetSeconds(); 26 | //uint32_t tasksExecuted = 0; 27 | 28 | // initialize tls 29 | g_memArena = new MemoryArena(128*1024); 30 | 31 | // pull task from thread pool 32 | for(;;) 33 | { 34 | Task t; 35 | t.m_func = NULL; 36 | 37 | { 38 | CriticalSectionScopeLock cs(pool->m_mutex); 39 | 40 | if (!pool->m_tasks.empty()) 41 | { 42 | t = pool->m_tasks.back(); 43 | pool->m_tasks.pop_back(); 44 | } 45 | else 46 | { 47 | //double totalTime = GetSeconds() - start; 48 | //cout << "Total worker time: " << totalTime << " Tasks: " << tasksExecuted << endl; 49 | 50 | // no tasks so return 51 | delete g_memArena; 52 | 53 | return 0; 54 | } 55 | } 56 | 57 | // execute job 58 | if (t.m_func) 59 | { 60 | t.m_func(t.m_param); 61 | 62 | //++tasksExecuted; 63 | } 64 | } 65 | 66 | delete g_memArena; 67 | 68 | return 0; 69 | } 70 | 71 | ThreadPool::ThreadPool() 72 | { 73 | } 74 | 75 | ThreadPool::~ThreadPool() 76 | { 77 | for (uint32_t i=0; i < m_threads.size(); ++i) 78 | { 79 | CloseHandle(m_threads[i]); 80 | } 81 | } 82 | 83 | void ThreadPool::AddTask(ThreadFunc func, void* param) 84 | { 85 | CriticalSectionScopeLock cs(m_mutex); 86 | 87 | Task t; 88 | t.m_func = func; 89 | t.m_param = param; 90 | 91 | m_tasks.push_back(t); 92 | } 93 | 94 | #include "maths.h" 95 | 96 | void ThreadPool::Run(uint32_t workerCount) 97 | { 98 | // create workers 99 | for(uint32_t i=0; i < workerCount; ++i) 100 | { 101 | HANDLE newThread = CreateThread(NULL, 0, WorkerMain, this, 0, NULL); 102 | if (newThread == NULL) 103 | { 104 | cout << "CreateThread failed with: " << GetLastError() << endl; 105 | return; 106 | } 107 | 108 | m_threads.push_back(newThread); 109 | } 110 | } 111 | 112 | void ThreadPool::Wait() 113 | { 114 | WaitForMultipleObjects(m_threads.size(), &m_threads[0], TRUE, INFINITE); 115 | } 116 | 117 | 118 | #if USE_PTHREADS 119 | 120 | void ThreadPool::AddWorker(ThreadFunc func, void* param) 121 | { 122 | pthread_t newThread; 123 | 124 | int retval = pthread_create(&newThread, NULL, WorkerMain, this); 125 | 126 | if (retval) 127 | { 128 | cerr << "Could not create pthread, error code: " << retval << endl; 129 | return; 130 | } 131 | 132 | m_threads.push_back(newThread); 133 | } 134 | 135 | void ThreadPool::Wait() 136 | { 137 | for (uint32_t i=0; i < m_threads.size(); ++i) 138 | { 139 | pthread_join(m_threads[i], NULL); 140 | } 141 | } 142 | 143 | #endif // USE_PTHREADS 144 | 145 | #endif // _WIN32 146 | -------------------------------------------------------------------------------- /core/threadgroup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "threading.h" 5 | 6 | #include 7 | 8 | #if defined(_WIN32) 9 | 10 | typedef uint32_t (*ThreadFunc)(void*); 11 | 12 | // very simple platform independent threading wrapper 13 | class ThreadPool 14 | { 15 | public: 16 | 17 | ThreadPool(); 18 | ~ThreadPool(); 19 | 20 | void AddTask(ThreadFunc function, void* param); 21 | 22 | void Run(uint32_t workerCount); 23 | void Wait(); 24 | 25 | uint32_t GetNumTasks() { return m_tasks.size(); } 26 | 27 | private: 28 | 29 | static DWORD WINAPI WorkerMain(void* data); 30 | 31 | void AddWorker(); 32 | 33 | struct Task 34 | { 35 | ThreadFunc m_func; 36 | void* m_param; 37 | }; 38 | 39 | CriticalSection m_mutex; 40 | 41 | std::vector m_tasks; 42 | std::vector m_threads; 43 | }; 44 | 45 | #endif //_WIN32 46 | -------------------------------------------------------------------------------- /core/threading.cpp: -------------------------------------------------------------------------------- 1 | #include "threading.h" 2 | 3 | #include 4 | 5 | #if USE_PTHREADS 6 | 7 | CriticalSection::CriticalSection() 8 | { 9 | int err = pthread_mutex_init(&m_semaphore, NULL); 10 | 11 | assert(err == 0); 12 | } 13 | 14 | CriticalSection::~CriticalSection() 15 | { 16 | pthread_mutex_destroy(&m_semaphore); 17 | } 18 | 19 | void CriticalSection::Enter() 20 | { 21 | pthread_mutex_lock(&m_semaphore); 22 | } 23 | 24 | void CriticalSection::Leave() 25 | { 26 | pthread_mutex_unlock(&m_semaphore); 27 | } 28 | 29 | #else 30 | 31 | CriticalSection::CriticalSection() 32 | { 33 | InitializeCriticalSection(&m_semaphore); 34 | } 35 | 36 | CriticalSection::~CriticalSection() 37 | { 38 | DeleteCriticalSection(&m_semaphore); 39 | } 40 | 41 | void CriticalSection::Enter() 42 | { 43 | EnterCriticalSection(&m_semaphore); 44 | } 45 | 46 | void CriticalSection::Leave() 47 | { 48 | LeaveCriticalSection(&m_semaphore); 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /core/threading.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if _WIN32 4 | #define NOMINMAX 5 | #include 6 | typedef CRITICAL_SECTION CriticalSectionHandle; 7 | #else 8 | #define USE_PTHREADS 1 9 | #include 10 | typedef pthread_mutex_t CriticalSectionHandle; 11 | #endif 12 | 13 | class CriticalSection 14 | { 15 | public: 16 | 17 | CriticalSection(); 18 | ~CriticalSection(); 19 | 20 | void Enter(); 21 | void Leave(); 22 | 23 | private: 24 | 25 | CriticalSectionHandle m_semaphore; 26 | }; 27 | 28 | 29 | 30 | // RAII style critical section lock 31 | class CriticalSectionScopeLock 32 | { 33 | CriticalSectionScopeLock& operator=(const CriticalSectionScopeLock&); 34 | 35 | public: 36 | 37 | CriticalSectionScopeLock(CriticalSection& cs) : m_cs(cs) 38 | { 39 | m_cs.Enter(); 40 | } 41 | 42 | ~CriticalSectionScopeLock() 43 | { 44 | m_cs.Leave(); 45 | } 46 | 47 | CriticalSection& m_cs; 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /core/threadinglinux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Thread 6 | { 7 | public: 8 | 9 | pthread_t m_handle; 10 | 11 | Thread(ThreadFunc func, void* param) 12 | { 13 | int retval = pthread_create(&m_handle, NULL, func, param); 14 | assert(retval); 15 | } 16 | }; 17 | 18 | void WaitForThreads(const Thread* threads, uint32_t n) 19 | { 20 | // just join all the threads 21 | for (uint32_t i=0; i < n; ++i) 22 | { 23 | pthread_join(threads[i], NULL); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /core/threadingwin32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Thread 4 | { 5 | public: 6 | 7 | Thread(ThreadFunc func, void* param) 8 | { 9 | m_handle = CreateThread(NULL, 0, func, param, 0, NULL); 10 | } 11 | 12 | HANDLE m_handle; 13 | } 14 | 15 | void WaitForThreads(Thread* threads, uint32_t n) 16 | { 17 | 18 | } -------------------------------------------------------------------------------- /core/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "stdint.h" 5 | 6 | 7 | -------------------------------------------------------------------------------- /core/vec2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(_WIN32) && !defined(__CUDACC__) 4 | #if defined(_DEBUG) 5 | 6 | #define VEC2_VALIDATE() { assert(_finite(x));\ 7 | assert(!_isnan(x));\ 8 | \ 9 | assert(_finite(y));\ 10 | assert(!_isnan(y));\ 11 | } 12 | #else 13 | 14 | #define VEC2_VALIDATE() {\ 15 | assert(isfinite(x));\ 16 | assert(isfinite(y)); }\ 17 | 18 | #endif // _WIN32 19 | 20 | #else 21 | #define VEC2_VALIDATE() 22 | #endif 23 | 24 | #ifdef _DEBUG 25 | #define FLOAT_VALIDATE(f) { assert(_finite(f)); assert(!_isnan(f)); } 26 | #else 27 | #define FLOAT_VALIDATE(f) 28 | #endif 29 | 30 | 31 | // vec2 32 | template 33 | class XVector2 34 | { 35 | public: 36 | 37 | typedef T value_type; 38 | 39 | CUDA_CALLABLE XVector2() : x(0.0f), y(0.0f) { VEC2_VALIDATE(); } 40 | CUDA_CALLABLE XVector2(T _x) : x(_x), y(_x) { VEC2_VALIDATE(); } 41 | CUDA_CALLABLE XVector2(T _x, T _y) : x(_x), y(_y) { VEC2_VALIDATE(); } 42 | CUDA_CALLABLE XVector2(const T* p) : x(p[0]), y(p[1]) {} 43 | 44 | template 45 | CUDA_CALLABLE explicit XVector2(const XVector2& v) : x(v.x), y(v.y) {} 46 | 47 | CUDA_CALLABLE operator T* () { return &x; } 48 | CUDA_CALLABLE operator const T* () const { return &x; }; 49 | 50 | CUDA_CALLABLE void Set(T x_, T y_) { VEC2_VALIDATE(); x = x_; y = y_; } 51 | 52 | CUDA_CALLABLE XVector2 operator * (T scale) const { XVector2 r(*this); r *= scale; VEC2_VALIDATE(); return r; } 53 | CUDA_CALLABLE XVector2 operator / (T scale) const { XVector2 r(*this); r /= scale; VEC2_VALIDATE(); return r; } 54 | CUDA_CALLABLE XVector2 operator + (const XVector2& v) const { XVector2 r(*this); r += v; VEC2_VALIDATE(); return r; } 55 | CUDA_CALLABLE XVector2 operator - (const XVector2& v) const { XVector2 r(*this); r -= v; VEC2_VALIDATE(); return r; } 56 | 57 | CUDA_CALLABLE XVector2& operator *=(T scale) {x *= scale; y *= scale; VEC2_VALIDATE(); return *this;} 58 | CUDA_CALLABLE XVector2& operator /=(T scale) {T s(1.0f/scale); x *= s; y *= s; VEC2_VALIDATE(); return *this;} 59 | CUDA_CALLABLE XVector2& operator +=(const XVector2& v) {x += v.x; y += v.y; VEC2_VALIDATE(); return *this;} 60 | CUDA_CALLABLE XVector2& operator -=(const XVector2& v) {x -= v.x; y -= v.y; VEC2_VALIDATE(); return *this;} 61 | 62 | CUDA_CALLABLE XVector2& operator *=(const XVector2& scale) {x *= scale.x; y *= scale.y; VEC2_VALIDATE(); return *this;} 63 | 64 | // negate 65 | CUDA_CALLABLE XVector2 operator -() const { VEC2_VALIDATE(); return XVector2(-x, -y); } 66 | 67 | // returns this vector 68 | CUDA_CALLABLE void Normalize() { *this /= Length(*this); } 69 | CUDA_CALLABLE void SafeNormalize(const XVector2& v=XVector2(0.0f,0.0f)) 70 | { 71 | T length = Length(*this); 72 | *this = (length==0.00001f)?v:(*this /= length); 73 | } 74 | 75 | T x; 76 | T y; 77 | }; 78 | 79 | typedef XVector2 Vec2; 80 | typedef XVector2 Vector2; 81 | 82 | // lhs scalar scale 83 | template 84 | CUDA_CALLABLE XVector2 operator *(T lhs, const XVector2& rhs) 85 | { 86 | XVector2 r(rhs); 87 | r *= lhs; 88 | return r; 89 | } 90 | 91 | template 92 | CUDA_CALLABLE XVector2 operator*(const XVector2& lhs, const XVector2& rhs) 93 | { 94 | XVector2 r(lhs); 95 | r *= rhs; 96 | return r; 97 | } 98 | 99 | template 100 | CUDA_CALLABLE bool operator==(const XVector2& lhs, const XVector2& rhs) 101 | { 102 | return (lhs.x == rhs.x && lhs.y == rhs.y); 103 | } 104 | 105 | 106 | template 107 | CUDA_CALLABLE T Dot(const XVector2& v1, const XVector2& v2) 108 | { 109 | return v1.x * v2.x + v1.y * v2.y; 110 | } 111 | 112 | // returns the ccw perpendicular vector 113 | template 114 | CUDA_CALLABLE XVector2 PerpCCW(const XVector2& v) 115 | { 116 | return XVector2(-v.y, v.x); 117 | } 118 | 119 | template 120 | CUDA_CALLABLE XVector2 PerpCW(const XVector2& v) 121 | { 122 | return XVector2(v.y, -v.x); 123 | } 124 | 125 | // component wise min max functions 126 | template 127 | CUDA_CALLABLE XVector2 Max(const XVector2& a, const XVector2& b) 128 | { 129 | return XVector2(Max(a.x, b.x), Max(a.y, b.y)); 130 | } 131 | 132 | template 133 | CUDA_CALLABLE XVector2 Min(const XVector2& a, const XVector2& b) 134 | { 135 | return XVector2(Min(a.x, b.x), Min(a.y, b.y)); 136 | } 137 | 138 | // 2d cross product, treat as if a and b are in the xy plane and return magnitude of z 139 | template 140 | CUDA_CALLABLE T Cross(const XVector2& a, const XVector2& b) 141 | { 142 | return (a.x*b.y - a.y*b.x); 143 | } 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /core/vec3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if 0 //_DEBUG 4 | #define VEC3_VALIDATE() { \ 5 | assert(_finite(x));\ 6 | assert(!_isnan(x));\ 7 | \ 8 | assert(_finite(y));\ 9 | assert(!_isnan(y));\ 10 | \ 11 | assert(_finite(z));\ 12 | assert(!_isnan(z));\ 13 | } 14 | #else 15 | #define VEC3_VALIDATE() 16 | #endif 17 | 18 | template 19 | class XVector3 20 | { 21 | public: 22 | 23 | typedef T value_type; 24 | 25 | CUDA_CALLABLE inline XVector3() : x(0), y(0), z(0) {} 26 | CUDA_CALLABLE inline XVector3(T a) : x(a), y(a), z(a) {} 27 | CUDA_CALLABLE inline XVector3(const T* p) : x(p[0]), y(p[1]), z(p[2]) {} 28 | CUDA_CALLABLE inline XVector3(T x_, T y_, T z_) : x(x_), y(y_), z(z_) 29 | { 30 | VEC3_VALIDATE(); 31 | } 32 | 33 | CUDA_CALLABLE inline operator T* () { return &x; } 34 | CUDA_CALLABLE inline operator const T* () const { return &x; }; 35 | 36 | CUDA_CALLABLE inline void Set(T x_, T y_, T z_) { VEC3_VALIDATE(); x = x_; y = y_; z = z_;} 37 | 38 | CUDA_CALLABLE inline XVector3 operator * (T scale) const { XVector3 r(*this); r *= scale; return r; VEC3_VALIDATE();} 39 | CUDA_CALLABLE inline XVector3 operator / (T scale) const { XVector3 r(*this); r /= scale; return r; VEC3_VALIDATE();} 40 | CUDA_CALLABLE inline XVector3 operator + (const XVector3& v) const { XVector3 r(*this); r += v; return r; VEC3_VALIDATE();} 41 | CUDA_CALLABLE inline XVector3 operator - (const XVector3& v) const { XVector3 r(*this); r -= v; return r; VEC3_VALIDATE();} 42 | CUDA_CALLABLE inline XVector3 operator /(const XVector3& v) const { XVector3 r(*this); r /= v; return r; VEC3_VALIDATE();} 43 | CUDA_CALLABLE inline XVector3 operator *(const XVector3& v) const { XVector3 r(*this); r *= v; return r; VEC3_VALIDATE();} 44 | 45 | CUDA_CALLABLE inline XVector3& operator *=(T scale) {x *= scale; y *= scale; z*= scale; VEC3_VALIDATE(); return *this;} 46 | CUDA_CALLABLE inline XVector3& operator /=(T scale) {T s(1.0f/scale); x *= s; y *= s; z *= s; VEC3_VALIDATE(); return *this;} 47 | CUDA_CALLABLE inline XVector3& operator +=(const XVector3& v) {x += v.x; y += v.y; z += v.z; VEC3_VALIDATE(); return *this;} 48 | CUDA_CALLABLE inline XVector3& operator -=(const XVector3& v) {x -= v.x; y -= v.y; z -= v.z; VEC3_VALIDATE(); return *this;} 49 | CUDA_CALLABLE inline XVector3& operator /=(const XVector3& v) {x /= v.x; y /= v.y; z /= v.z; VEC3_VALIDATE(); return *this; } 50 | CUDA_CALLABLE inline XVector3& operator *=(const XVector3& v) {x *= v.x; y *= v.y; z *= v.z; VEC3_VALIDATE(); return *this; } 51 | 52 | CUDA_CALLABLE inline bool operator != (const XVector3& v) const { return (x != v.x || y != v.y || z != v.z); } 53 | 54 | // negate 55 | CUDA_CALLABLE inline XVector3 operator -() const { VEC3_VALIDATE(); return XVector3(-x, -y, -z); } 56 | 57 | CUDA_CALLABLE void Validate() 58 | { 59 | VEC3_VALIDATE(); 60 | } 61 | 62 | T x,y,z; 63 | }; 64 | 65 | typedef XVector3 Vec3; 66 | typedef XVector3 Vector3; 67 | 68 | // lhs scalar scale 69 | template 70 | CUDA_CALLABLE XVector3 operator *(T lhs, const XVector3& rhs) 71 | { 72 | XVector3 r(rhs); 73 | r *= lhs; 74 | return r; 75 | } 76 | 77 | template 78 | CUDA_CALLABLE bool operator==(const XVector3& lhs, const XVector3& rhs) 79 | { 80 | return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 81 | } 82 | 83 | template 84 | CUDA_CALLABLE typename T::value_type Dot3(const T& v1, const T& v2) 85 | { 86 | return v1.x * v2.x + v1.y * v2.y + v1.z*v2.z; 87 | } 88 | 89 | CUDA_CALLABLE inline float Dot3(const float* v1, const float * v2) 90 | { 91 | return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; 92 | } 93 | 94 | 95 | template 96 | CUDA_CALLABLE inline T Dot(const XVector3& v1, const XVector3& v2) 97 | { 98 | return Dot3(v1, v2); 99 | } 100 | 101 | CUDA_CALLABLE inline Vec3 Cross(const Vec3& b, const Vec3& c) 102 | { 103 | return Vec3(b.y*c.z - b.z*c.y, 104 | b.z*c.x - b.x*c.z, 105 | b.x*c.y - b.y*c.x); 106 | } 107 | 108 | // component wise min max functions 109 | template 110 | CUDA_CALLABLE inline XVector3 Max(const XVector3& a, const XVector3& b) 111 | { 112 | return XVector3(Max(a.x, b.x), Max(a.y, b.y), Max(a.z, b.z)); 113 | } 114 | 115 | template 116 | CUDA_CALLABLE inline XVector3 Min(const XVector3& a, const XVector3& b) 117 | { 118 | return XVector3(Min(a.x, b.x), Min(a.y, b.y), Min(a.z, b.z)); 119 | } 120 | 121 | -------------------------------------------------------------------------------- /core/vec4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #if 0 //defined(_DEBUG) && defined(_WIN32) 6 | #define VEC4_VALIDATE() { \ 7 | assert(_finite(x));\ 8 | assert(!_isnan(x));\ 9 | \ 10 | assert(_finite(y));\ 11 | assert(!_isnan(y));\ 12 | \ 13 | assert(_finite(z));\ 14 | assert(!_isnan(z));\ 15 | \ 16 | assert(_finite(w));\ 17 | assert(!_isnan(w));\ 18 | } 19 | #else 20 | #define VEC4_VALIDATE() 21 | #endif 22 | 23 | template 24 | class XVector4 25 | { 26 | public: 27 | 28 | typedef T value_type; 29 | 30 | CUDA_CALLABLE XVector4() : x(0), y(0), z(0), w(0) {} 31 | CUDA_CALLABLE XVector4(T a) : x(a), y(a), z(a), w(a) {} 32 | CUDA_CALLABLE XVector4(const T* p) : x(p[0]), y(p[1]), z(p[2]), w(p[3]) {} 33 | CUDA_CALLABLE XVector4(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) 34 | { 35 | VEC4_VALIDATE(); 36 | } 37 | 38 | CUDA_CALLABLE operator T* () { return &x; } 39 | CUDA_CALLABLE operator const T* () const { return &x; }; 40 | 41 | CUDA_CALLABLE void Set(T x_, T y_, T z_, T w_) { VEC4_VALIDATE(); x = x_; y = y_; z = z_; w = w_; } 42 | 43 | CUDA_CALLABLE XVector4 operator * (T scale) const { XVector4 r(*this); r *= scale; VEC4_VALIDATE(); return r;} 44 | CUDA_CALLABLE XVector4 operator / (T scale) const { XVector4 r(*this); r /= scale; VEC4_VALIDATE(); return r; } 45 | CUDA_CALLABLE XVector4 operator + (const XVector4& v) const { XVector4 r(*this); r += v; VEC4_VALIDATE(); return r; } 46 | CUDA_CALLABLE XVector4 operator - (const XVector4& v) const { XVector4 r(*this); r -= v; VEC4_VALIDATE(); return r; } 47 | CUDA_CALLABLE XVector4 operator * (XVector4 scale) const { XVector4 r(*this); r *= scale; VEC4_VALIDATE(); return r; } 48 | 49 | CUDA_CALLABLE XVector4& operator *=(T scale) {x *= scale; y *= scale; z*= scale; w*= scale; VEC4_VALIDATE(); return *this;} 50 | CUDA_CALLABLE XVector4& operator /=(T scale) {T s(1.0f/scale); x *= s; y *= s; z *= s; w *=s; VEC4_VALIDATE(); return *this;} 51 | CUDA_CALLABLE XVector4& operator +=(const XVector4& v) {x += v.x; y += v.y; z += v.z; w += v.w; VEC4_VALIDATE(); return *this;} 52 | CUDA_CALLABLE XVector4& operator -=(const XVector4& v) {x -= v.x; y -= v.y; z -= v.z; w -= v.w; VEC4_VALIDATE(); return *this;} 53 | CUDA_CALLABLE XVector4& operator *=(const XVector4& v) {x *= v.x; y *= v.y; z *= v.z; w *= v.w; VEC4_VALIDATE(); return *this;} 54 | 55 | CUDA_CALLABLE bool operator != (const XVector4& v) const { return (x != v.x || y != v.y || z != v.z || w != v.w); } 56 | 57 | // negate 58 | CUDA_CALLABLE XVector4 operator -() const { VEC4_VALIDATE(); return XVector4(-x, -y, -z, -w); } 59 | 60 | T x,y,z,w; 61 | }; 62 | 63 | typedef XVector4 Vector4; 64 | typedef XVector4 Vec4; 65 | 66 | // lhs scalar scale 67 | template 68 | CUDA_CALLABLE XVector4 operator *(T lhs, const XVector4& rhs) 69 | { 70 | XVector4 r(rhs); 71 | r *= lhs; 72 | return r; 73 | } 74 | 75 | template 76 | CUDA_CALLABLE bool operator==(const XVector4& lhs, const XVector4& rhs) 77 | { 78 | return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /core/voxelize.cpp: -------------------------------------------------------------------------------- 1 | #include "core/aabbtree.h" 2 | #include "core/mesh.h" 3 | 4 | void Voxelize(const Mesh& mesh, uint32_t width, uint32_t height, uint32_t depth, uint32_t* volume, Vec3 minExtents, Vec3 maxExtents) 5 | { 6 | memset(volume, 0, sizeof(uint32_t)*width*height*depth); 7 | 8 | // build an aabb tree of the mesh 9 | AABBTree tree(&mesh.m_positions[0], mesh.m_positions.size(), &mesh.m_indices[0], mesh.m_indices.size()/3); 10 | 11 | // parity count method, single pass 12 | const Vec3 extents(maxExtents-minExtents); 13 | const Vec3 delta(extents.x/width, extents.y/height, extents.z/depth); 14 | const Vec3 offset(0.5f/width, 0.5f/height, 0.5f/depth); 15 | 16 | const float eps = 0.0000001f*extents.z; 17 | 18 | for (uint32_t x=0; x < width; ++x) 19 | { 20 | for (uint32_t y=0; y < height; ++y) 21 | { 22 | bool inside = false; 23 | 24 | //float sign = -1.0f; 25 | 26 | Vec3 rayDir = Vec3(0.0f, 0.0f, 1.0f); 27 | Vec3 rayStart = minExtents + Vec3(x*delta.x + offset.x, y*delta.y + offset.y, -0.0f*extents.z); // z-coord starts somewhat outside bounds 28 | 29 | uint32_t lastTri = uint32_t(-1); 30 | //while (z < depth) 31 | for (;;) 32 | { 33 | // calculate ray start 34 | float t, u, v, w, s; 35 | uint32_t tri; 36 | 37 | if (tree.TraceRay(Point3(rayStart), rayDir, t, u, v, w, s, tri)) 38 | //if (tree.TraceRaySlow(Point3(rayStart), rayDir, t, u, v, w, s, tri)) 39 | { 40 | //uint32_t i = mesh.m_indices[tri*3+0]; 41 | //uint32_t j = mesh.m_indices[tri*3+1]; 42 | //uint32_t k = mesh.m_indices[tri*3+2]; 43 | 44 | //Vec3 n = SafeNormalize(Cross(mesh.m_positions[j]-mesh.m_positions[i], mesh.m_positions[k]-mesh.m_positions[i]), Vec3(0.0f)); 45 | 46 | //if (fabsf(n.z) > 0.01f) 47 | { 48 | 49 | // calculate cell in which intersection occurred 50 | const float zpos = rayStart.z + t*rayDir.z; 51 | const float zhit = (zpos-minExtents.z)/delta.z; 52 | 53 | uint32_t z = uint32_t((rayStart.z-minExtents.z)/delta.z); 54 | uint32_t zend = std::min(uint32_t(zhit), depth-1); 55 | 56 | // must be true for termination 57 | //assert(zend >= z); 58 | //if (zend == z && zend < depth-1) 59 | // zend++; 60 | 61 | if (inside) 62 | { 63 | // march along column setting bits 64 | for (uint32_t k=z; k <= zend; ++k) 65 | volume[k*width*height + y*width + x] = uint32_t(-1); 66 | } 67 | 68 | inside = !inside; 69 | } 70 | 71 | //if (Sign(s) != sign) 72 | //inside = !inside; 73 | //sign = Sign(s); 74 | 75 | /* 76 | if (Sign(s) == sign) 77 | printf("Mesh not closed tri: %d lasttri: %d\n", tri, lastTri); 78 | sign = Sign(s); 79 | */ 80 | 81 | if (tri == lastTri) 82 | printf("Error self-intersect\n"); 83 | lastTri = tri; 84 | 85 | rayStart += rayDir*(t+eps); 86 | 87 | } 88 | else 89 | break; 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /core/voxelize.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Mesh; 4 | 5 | // voxelizes a mesh using a single pass parity algorithm 6 | void Voxelize(const Mesh& mesh, uint32_t width, uint32_t height, uint32_t depth, uint32_t* volume, Vec3 minExtents, Vec3 maxExtents); -------------------------------------------------------------------------------- /data/beach.pfm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/data/beach.pfm -------------------------------------------------------------------------------- /external/glew/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The OpenGL Extension Wrangler Library 2 | Copyright (C) 2002-2007, Milan Ikits 3 | Copyright (C) 2002-2007, Marcelo E. Magallon 4 | Copyright (C) 2002, Lev Povalahev 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | * The name of the author may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | Mesa 3-D graphics library 32 | Version: 7.0 33 | 34 | Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a 37 | copy of this software and associated documentation files (the "Software"), 38 | to deal in the Software without restriction, including without limitation 39 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 40 | and/or sell copies of the Software, and to permit persons to whom the 41 | Software is furnished to do so, subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included 44 | in all copies or substantial portions of the Software. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 47 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 49 | BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 50 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 51 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 | 53 | 54 | Copyright (c) 2007 The Khronos Group Inc. 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining a 57 | copy of this software and/or associated documentation files (the 58 | "Materials"), to deal in the Materials without restriction, including 59 | without limitation the rights to use, copy, modify, merge, publish, 60 | distribute, sublicense, and/or sell copies of the Materials, and to 61 | permit persons to whom the Materials are furnished to do so, subject to 62 | the following conditions: 63 | 64 | The above copyright notice and this permission notice shall be included 65 | in all copies or substantial portions of the Materials. 66 | 67 | THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 68 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 69 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 70 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 71 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 72 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 73 | MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 74 | -------------------------------------------------------------------------------- /external/glew/bin/glew32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glew/bin/glew32.dll -------------------------------------------------------------------------------- /external/glew/lib/glew32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glew/lib/glew32.lib -------------------------------------------------------------------------------- /external/glew/lib/glew32s.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glew/lib/glew32s.lib -------------------------------------------------------------------------------- /external/glut/glut.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glut/glut.dll -------------------------------------------------------------------------------- /external/glut/glut.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glut/glut.lib -------------------------------------------------------------------------------- /external/glut/glut32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glut/glut32.dll -------------------------------------------------------------------------------- /external/glut/glut32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/external/glut/glut32.lib -------------------------------------------------------------------------------- /projects/cloth/cloth.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cloth", "Cloth.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/cloth/cloth.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Surfel 17 | Cloth 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 54 | ../.. 55 | MultiThreadedDebug 56 | 57 | 58 | Console 59 | true 60 | ../../Core/Debug;../../External/glut;../../External/glew/lib 61 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | ../.. 74 | MultiThreaded 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | ../../Core/Release;../../External/glut;../../External/glew/lib 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /projects/dew/Dew.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dew", "Dew.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/dew/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -Wall -I"../.." 5 | LDFLAGS = -g -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = Dew 8 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../Core/maths.cpp ../../Core/tga.cpp ../../Core/mesh.cpp dialog.mm 9 | HEADERS = $(wildcard *.h) 10 | 11 | OBJECTS = $(SOURCES:.cpp=.o) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET): $(OBJECTS) Makefile 16 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 17 | 18 | clean: 19 | -rm -f $(OBJECTS) 20 | -rm -f $(TARGET) 21 | 22 | %.o: %.cpp $(HEADERS) 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | 25 | run: $(TARGET) 26 | ./$(TARGET) 27 | 28 | .PHONY : all clean 29 | -------------------------------------------------------------------------------- /projects/dew/dew: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/dew/dew -------------------------------------------------------------------------------- /projects/dew/dew.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/dew/dew.exe -------------------------------------------------------------------------------- /projects/dew/dialog.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #include 4 | #include "../../core/platform.h" 5 | 6 | using namespace std; 7 | 8 | string FileOpenDialog(char* filter) 9 | { 10 | NSOpenPanel *dialogOpen = [NSOpenPanel openPanel]; 11 | [dialogOpen setCanChooseFiles:YES]; 12 | [dialogOpen setCanChooseDirectories:NO]; 13 | [dialogOpen setAllowsMultipleSelection:NO]; 14 | 15 | NSMutableArray *typesArray = nil; 16 | 17 | NSString *directory = nil; 18 | int resultCode = [dialogOpen runModalForDirectory:directory file:nil types:typesArray]; 19 | 20 | if( resultCode == NSOKButton ) { 21 | NSString *result = [[dialogOpen filenames] objectAtIndex:0]; 22 | return StripPath(string( [result UTF8String] ).c_str()); 23 | } 24 | else 25 | return string(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /projects/dew/readme.txt: -------------------------------------------------------------------------------- 1 | 3D Graffiti 2 | ========================== 3 | 4 | This OpenGL demo app reads BVH motion capture data taken from a hand held 5 | controller and generates a triangle mesh from the path. Controller rotation data 6 | is read but is currently ignored as I found it didn't give results as good as the 7 | parallel transport method for constructing a reference frame along a path. 8 | A nice description of the paralle transport method is given in 9 | "Quaternion Gauss Maps and Optimal Framings of Curves and Surfaces (1998)", 10 | http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.50.8658). 11 | 12 | Lighting is performed using a third order spherical harmonic ambient 13 | term with a direct spot light and PCF filtered shadow mapping. The ambient 14 | SH coefficients are calculated from Paul Debevec's HDR "beach" light probe. 15 | 16 | The mesh is reconstructed from scratch each frame and nothing is 17 | optimised so I expect it could be made significantly faster. 18 | 19 | Controls 20 | -------- 21 | 22 | mouse - Rotate camera 23 | w,a,s,d - Translate camera 24 | 25 | 1 - Open Animation (.bvh) 26 | 2 - Open Mouse Track (.txt) 27 | 3 - Export mesh at current frame (creates dew.obj) 28 | 4 - Start/Stop Mouse Record (saves mouse clicks to control.txt) 29 | 30 | +/- Adjust Mouse track sync forward/back in time 31 | 32 | j - Speed up animation 33 | u - Slow down animation 34 | r - Rewind to beginning 35 | f - Fast forward to end 36 | space - Pause animation 37 | 38 | i - Increase path width 39 | k - Decrease path width 40 | o - Increase path thickness 41 | l - Decrease path thickness 42 | p - Increase the effect velocity has on path thickness 43 | ; - Decrease the effect velocity has on path thickness 44 | / - Cycle brushes 45 | 46 | h - Hide help text 47 | c - Hide can 48 | b - Show wirefame 49 | n - Show normals 50 | b - Toggle fullscreen 51 | -------------------------------------------------------------------------------- /projects/dew/shaders.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // spherical harmonic coefficients for the 'beach' light probe 4 | Vec3 gShDiffuse[] = 5 | { 6 | Vec3(1.51985, 1.53785, 1.56834), 7 | Vec3(-0.814902, -0.948101, -1.13014), 8 | Vec3(-0.443242, -0.441047, -0.421306), 9 | Vec3(1.16161, 1.07284, 0.881858), 10 | Vec3(-0.36858, -0.37136, -0.332637), 11 | Vec3(0.178697, 0.200577, 0.219209), 12 | Vec3(-0.0204381, -0.0136351, -0.00920174), 13 | Vec3(-0.349078, -0.292836, -0.214752), 14 | Vec3(0.399496, 0.334641, 0.219389), 15 | }; 16 | 17 | // vertex shader 18 | const char* vertexShader = STRINGIFY 19 | ( 20 | uniform mat4 lightTransform; 21 | uniform mat4 worldTransform; 22 | 23 | void main() 24 | { 25 | vec3 n = gl_Normal;//normalize(gl_Normal); 26 | 27 | gl_Position = gl_ModelViewProjectionMatrix*vec4(gl_Vertex.xyz, 1.0); 28 | gl_TexCoord[0] = worldTransform*vec4(n, 0.0); 29 | gl_TexCoord[1] = vec4(gl_Vertex.xyz, 1.0); 30 | gl_TexCoord[2] = lightTransform*vec4(gl_Vertex.xyz+n, 1.0); 31 | gl_TexCoord[3].xyz = gl_Color.xyz; 32 | } 33 | ); 34 | 35 | // pixel shader 36 | const char* fragmentShaderMain = STRINGIFY 37 | ( 38 | uniform vec3 shDiffuse[9]; 39 | uniform vec3 color; 40 | 41 | uniform vec3 lightDir; 42 | uniform vec3 lightPos; 43 | 44 | uniform sampler2DShadow shadowTex; 45 | uniform vec2 shadowTaps[12]; 46 | 47 | // evaluate spherical harmonic function 48 | vec3 shEval(vec3 dir, vec3 sh[9]) 49 | { 50 | // evaluate irradiance 51 | vec3 e = sh[0]; 52 | 53 | e += -dir.y*sh[1]; 54 | e += dir.z*sh[2]; 55 | e += -dir.x*sh[3]; 56 | 57 | e += dir.x*dir.y*sh[4]; 58 | e += -dir.y*dir.z*sh[5]; 59 | e += -dir.x*dir.z*sh[7]; 60 | 61 | e += (3.0*dir.z*dir.z-1.0)*sh[6]; 62 | e += (dir.x*dir.x - dir.y*dir.y)*sh[8]; 63 | 64 | return max(e, vec3(0.0)); 65 | } 66 | 67 | // sample shadow map 68 | float shadowSample() 69 | { 70 | vec3 pos = vec3(gl_TexCoord[2].xyz/gl_TexCoord[2].w); 71 | vec3 uvw = (pos.xyz*0.5)+vec3(0.5); 72 | 73 | // user clip 74 | if (uvw.x < 0.0 || uvw.x > 1.0) 75 | return 0.0; 76 | if (uvw.y < 0.0 || uvw.y > 1.0) 77 | return 0.0; 78 | 79 | float s = 0.0; 80 | float radius = 0.003; 81 | 82 | for (int i=0; i < 12; i++) 83 | { 84 | s += shadow2D(shadowTex, vec3(uvw.xy + shadowTaps[i]*radius, uvw.z)).r; 85 | } 86 | 87 | s /= 12.0; 88 | return s; 89 | } 90 | 91 | void main() 92 | { 93 | vec3 n = gl_TexCoord[0].xyz; 94 | vec3 shadePos = gl_TexCoord[1].xyz; 95 | vec3 eyePos = gl_ModelViewMatrixInverse[3].xyz; 96 | vec3 eyeDir = normalize(eyePos-shadePos); 97 | vec3 vcolor = gl_TexCoord[3].xyz; 98 | 99 | vec3 lightCol = vec3(1.0, 1.0, 1.0)*0.8; 100 | 101 | // SH-ambient 102 | float ambientExposure = 0.04; 103 | vec3 ambient = shEval(n, shDiffuse)*ambientExposure; 104 | 105 | // wrapped spot light 106 | float w = 0.1; 107 | float s = shadowSample(); 108 | vec3 direct = clamp((dot(n, -lightDir) + w) / (1.0 + w), 0.0, 1.0)*lightCol*smoothstep(0.9, 1.0, dot(lightDir, normalize(shadePos-lightPos))); 109 | 110 | vec3 l = (ambient + s*direct)*vcolor;//*(n*vec3(0.5) + vec3(0.5));//color; 111 | 112 | // convert from linear light space to SRGB 113 | gl_FragColor = vec4(pow(l, vec3(0.5)), 1.0); 114 | } 115 | ); 116 | 117 | // pixel shader 118 | const char* fragmentShaderDebug = STRINGIFY 119 | ( 120 | void main() 121 | { 122 | vec3 n = gl_TexCoord[0].xyz; 123 | gl_FragColor = vec4(n*0.5 + vec3(0.5), 1.0); 124 | } 125 | ); 126 | 127 | -------------------------------------------------------------------------------- /projects/dew/tag.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/dew/tag.cpp -------------------------------------------------------------------------------- /projects/empty/empty.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Upsample", "Upsample.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/empty/empty.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Surfel 17 | Upsample 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 54 | ../.. 55 | MultiThreadedDebug 56 | 57 | 58 | Console 59 | true 60 | ../../Core/Debug;../../External/glut;../../External/glew/lib 61 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | ../.. 74 | MultiThreaded 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | ../../Core/Release;../../External/glut;../../External/glew/lib 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /projects/empty/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "core/types.h" 4 | #include "core/shader.h" 5 | 6 | using namespace std; 7 | 8 | uint32_t g_screenWidth = 1280; 9 | uint32_t g_screenHeight = 720; 10 | 11 | void Init() 12 | { 13 | 14 | } 15 | 16 | void GLUTUpdate() 17 | { 18 | glViewport(0, 0, g_screenWidth, g_screenHeight); 19 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 20 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 21 | 22 | glMatrixMode(GL_PROJECTION); 23 | glLoadIdentity(); 24 | gluPerspective(45.0f, g_screenWidth/float(g_screenHeight), 0.01f, 1000.0f); 25 | 26 | glMatrixMode(GL_MODELVIEW); 27 | glLoadIdentity(); 28 | 29 | //gluLookAt(sin(g_angle)*2.0f, 0.4f, cos(g_angle)*2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); 30 | 31 | 32 | // flip 33 | glutSwapBuffers(); 34 | } 35 | 36 | void GLUTReshape(int width, int height) 37 | { 38 | } 39 | 40 | void GLUTArrowKeys(int key, int x, int y) 41 | { 42 | } 43 | 44 | void GLUTArrowKeysUp(int key, int x, int y) 45 | { 46 | } 47 | 48 | void GLUTKeyboardDown(unsigned char key, int x, int y) 49 | { 50 | switch (key) 51 | { 52 | case 'e': 53 | { 54 | break; 55 | } 56 | case 'q': 57 | case 27: 58 | exit(0); 59 | break; 60 | }; 61 | } 62 | 63 | void GLUTKeyboardUp(unsigned char key, int x, int y) 64 | { 65 | switch (key) 66 | { 67 | case 'e': 68 | { 69 | break; 70 | } 71 | case 'd': 72 | { 73 | break; 74 | } 75 | case ' ': 76 | { 77 | break; 78 | } 79 | } 80 | } 81 | 82 | static int lastx; 83 | static int lasty; 84 | 85 | void GLUTMouseFunc(int b, int state, int x, int y) 86 | { 87 | switch (state) 88 | { 89 | case GLUT_UP: 90 | { 91 | lastx = x; 92 | lasty = y; 93 | } 94 | case GLUT_DOWN: 95 | { 96 | lastx = x; 97 | lasty = y; 98 | } 99 | } 100 | } 101 | 102 | void GLUTMotionFunc(int x, int y) 103 | { 104 | int dx = x-lastx; 105 | int dy = y-lasty; 106 | 107 | lastx = x; 108 | lasty = y; 109 | 110 | } 111 | 112 | void GLUTPassiveMotionFunc(int x, int y) 113 | { 114 | int dx = x-lastx; 115 | int dy = y-lasty; 116 | 117 | lastx = x; 118 | lasty = y; 119 | 120 | } 121 | 122 | 123 | int main(int argc, char* argv[]) 124 | { 125 | // init gl 126 | glutInit(&argc, argv); 127 | glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH); 128 | 129 | glutInitWindowSize(g_screenWidth, g_screenHeight); 130 | glutCreateWindow("Empty"); 131 | glutPositionWindow(350, 100); 132 | 133 | #if WIN32 134 | glewInit(); 135 | #endif 136 | 137 | Init(); 138 | 139 | glutMouseFunc(GLUTMouseFunc); 140 | glutReshapeFunc(GLUTReshape); 141 | glutDisplayFunc(GLUTUpdate); 142 | glutKeyboardFunc(GLUTKeyboardDown); 143 | glutKeyboardUpFunc(GLUTKeyboardUp); 144 | glutIdleFunc(GLUTUpdate); 145 | glutSpecialFunc(GLUTArrowKeys); 146 | glutSpecialUpFunc(GLUTArrowKeysUp); 147 | glutMotionFunc(GLUTMotionFunc); 148 | glutPassiveMotionFunc(GLUTPassiveMotionFunc); 149 | 150 | glutMainLoop(); 151 | } 152 | 153 | -------------------------------------------------------------------------------- /projects/fem/armadillo.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/fem/armadillo.tga -------------------------------------------------------------------------------- /projects/fem/bunny.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/fem/bunny.tga -------------------------------------------------------------------------------- /projects/fem/cg.h: -------------------------------------------------------------------------------- 1 | #include "core/types.h" 2 | #include "core/maths.h" 3 | #include "mat22.h" 4 | 5 | #include 6 | 7 | 8 | typedef std::vector NodeRow; 9 | 10 | std::vector CgMul(const std::vector& A, const std::vector& x) 11 | { 12 | assert(A[0].size() == x.size()); 13 | 14 | std::vector b(A.size()); 15 | 16 | for (size_t i=0; i < A.size(); ++i) 17 | { 18 | for (size_t j=0; j < x.size(); ++j) 19 | { 20 | b[i] += A[i][j]*x[j]; 21 | } 22 | } 23 | 24 | return b; 25 | } 26 | 27 | std::vector CgMul(float c, const std::vector& x) 28 | { 29 | std::vector r(x.size()); 30 | 31 | for (size_t i=0; i < r.size(); ++i) 32 | r[i] = c*x[i]; 33 | 34 | return r; 35 | } 36 | 37 | std::vector CgAdd(const std::vector& a, const std::vector& b) 38 | { 39 | assert(a.size() == b.size()); 40 | 41 | std::vector c(a.size()); 42 | 43 | for (size_t i=0; i < a.size(); ++i) 44 | c[i] = a[i] + b[i]; 45 | 46 | return c; 47 | } 48 | 49 | std::vector CgSub(const std::vector& a, const std::vector& b) 50 | { 51 | assert(a.size() == b.size()); 52 | 53 | std::vector c(a.size()); 54 | 55 | for (size_t i=0; i < a.size(); ++i) 56 | c[i] = a[i] - b[i]; 57 | 58 | return c; 59 | } 60 | 61 | float CgDot(const std::vector& a, const std::vector& b) 62 | { 63 | assert(a.size() == b.size()); 64 | 65 | float d = 0.0f; 66 | 67 | for (size_t i=0; i < a.size(); ++i) 68 | { 69 | d += Dot(a[i], b[i]); 70 | } 71 | 72 | return d; 73 | } 74 | 75 | void CgDebug(const Matrix22& m) 76 | { 77 | printf("{ %f, %f }\n", m(0, 0), m(0, 1)); 78 | printf("{ %f, %f }\n", m(1, 0), m(1, 1)); 79 | } 80 | 81 | void CgDebug(const char* s, const std::vector& x) 82 | { 83 | for (size_t i=0; i < x.size(); ++i) 84 | printf("%s[%u] = {%f, %f}\n", s, uint32_t(i), x[i].x, x[i].y); 85 | } 86 | 87 | void CgDebug(const char* s, const std::vector& A) 88 | { 89 | for (size_t i=0; i < A.size(); ++i) 90 | { 91 | 92 | for (int r=0; r < 2; ++r) 93 | { 94 | for (size_t j=0; j < A[i].size(); ++j) 95 | { 96 | printf("%f, %f, ", A[i][j](r,0), A[i][j](r, 1)); 97 | } 98 | printf("\n"); 99 | } 100 | } 101 | } 102 | 103 | 104 | // returns x 105 | std::vector CgSolve(const std::vector& A, const std::vector& b, uint32_t imax, float e) 106 | { 107 | assert(A.size() == A[0].size()); 108 | 109 | uint32_t i=0; 110 | std::vector x(A[0].size()); 111 | std::vector r = CgSub(b, CgMul(A, x)); 112 | std::vector d = r; 113 | 114 | float sigmaNew = CgDot(r, r); 115 | //const float sigma0 = sigmaNew; 116 | 117 | assert(A.size() == A[0].size()); 118 | assert(x.size() == A.size()); 119 | assert(r.size() == A.size()); 120 | assert(d.size() == A.size()); 121 | 122 | //CgDebug("b", b); 123 | std::vector q; 124 | 125 | while (i < imax)// && sigmaNew > e*e*sigma0) 126 | { 127 | q = CgMul(A, d); 128 | 129 | // CgDebug("q", q); 130 | 131 | float a = sigmaNew / CgDot(d, q); 132 | x = CgAdd(x, CgMul(a,d)); 133 | 134 | // could reseed residual here to account for numerical inaccuracy 135 | r = CgSub(r, CgMul(a, q)); 136 | 137 | float sigmaOld = sigmaNew; 138 | if (sigmaOld <= 0.0001f) 139 | return x; 140 | sigmaNew = CgDot(r, r); 141 | 142 | //printf("%d %f\n", i, sigmaNew); 143 | 144 | float beta = sigmaNew / sigmaOld; 145 | 146 | d = CgAdd(r, CgMul(beta, d)); 147 | 148 | ++i; 149 | } 150 | 151 | return x; 152 | } 153 | 154 | 155 | -------------------------------------------------------------------------------- /projects/fem/donut1.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/fem/donut1.tga -------------------------------------------------------------------------------- /projects/fem/donut2.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/fem/donut2.tga -------------------------------------------------------------------------------- /projects/fem/fem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/types.h" 4 | #include "core/maths.h" 5 | #include "core/vec2.h" 6 | #include "core/mat22.h" 7 | 8 | namespace fem 9 | { 10 | 11 | struct Scene; 12 | 13 | struct Particle 14 | { 15 | Particle() {}; 16 | Particle(Vec2 x, float im) : p(x), invMass(im) {} 17 | 18 | Vec2 p; 19 | Vec2 v; 20 | Vec2 f; 21 | Vec2 c; 22 | float invMass; 23 | uint32_t index; 24 | }; 25 | 26 | struct Triangle 27 | { 28 | Triangle() {}; 29 | Triangle(int a, int b, int c) : i(a), j(b), k(c) {} 30 | 31 | uint32_t i, j, k; 32 | }; 33 | 34 | struct SceneParams 35 | { 36 | Vec2 mGravity; 37 | float mLameLambda; 38 | float mLameMu; 39 | float mYield; 40 | float mCreep; 41 | float mDamping; 42 | float mDrag; 43 | float mFriction; 44 | float mToughness; 45 | 46 | SceneParams() : 47 | mGravity(0.0f, -9.8f), 48 | mLameLambda(1000.0f), 49 | mLameMu(1000.0f), 50 | mYield(0.5f), 51 | mCreep(25.0f), 52 | mDamping(10.0f), 53 | mDrag(0.0f), 54 | mFriction(0.5f), 55 | mToughness(500.0f) {} 56 | 57 | }; 58 | 59 | Scene* CreateScene( 60 | const Particle* particles, uint32_t numParticles, 61 | const Triangle* elements, uint32_t numTriangles); 62 | 63 | void DestroyScene(Scene* sim); 64 | 65 | void SetParams(Scene* scene, SceneParams params); 66 | SceneParams GetParams(const Scene* scene); 67 | 68 | void SetParticles(Scene* sim, const Particle* src); 69 | void GetParticles(const Scene* sim, Particle* dest); 70 | uint32_t NumParticles(const Scene* sim); 71 | 72 | void GetTriangles(const Scene* sim, Triangle* dest); 73 | uint32_t NumTriangles(const Scene* sim); 74 | 75 | void SetPlanes(Scene* scene, const Vec3* planes, uint32_t n); 76 | 77 | void Update(Scene* sim, float dt); 78 | 79 | void DrawDebug(); 80 | 81 | } // namespace fem 82 | 83 | -------------------------------------------------------------------------------- /projects/fem/fem.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FEM", "FEM.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/fem/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -O3 -ffast-math -Wall -I"../.." -D_DEBUG 5 | LDFLAGS = -g -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = fem 8 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../core/maths.cpp ../../core/tga.cpp 9 | HEADERS = $(wildcard *.h) 10 | 11 | OBJECTS = $(SOURCES:.cpp=.o) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET): $(OBJECTS) 16 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 17 | 18 | clean: 19 | -rm -f $(OBJECTS) 20 | -rm -f $(TARGET) 21 | 22 | %.o: %.cpp $(HEADERS) makefile 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | 25 | run: $(TARGET) 26 | ./$(TARGET) 27 | 28 | .PHONY : all clean 29 | -------------------------------------------------------------------------------- /projects/fem/mesher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/maths.h" 4 | #include "core/tga.h" 5 | 6 | #include 7 | 8 | void TriangulateDelaunay(const Vec2* points, uint32_t numPoints, std::vector& outPoints, std::vector& outTris); 9 | void TriangulateVariational(const Vec2* points, uint32_t numPoints, const Vec2* bpoints, uint32_t numBPoints, uint32_t iterations, std::vector& outPoints, std::vector& outTris); 10 | 11 | void CreateDonut(std::vector& points, std::vector& indices, float inner, float outer, uint32_t segments); 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /projects/fem/meshing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/fem/meshing.pdf -------------------------------------------------------------------------------- /projects/fem/meshing.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | \usepackage{mathptmx} 3 | \usepackage[small,compact]{titlesec} 4 | \usepackage{geometry} % See geometry.pdf to learn the layout options. There are lots. 5 | \usepackage{url} 6 | \usepackage{hyperref} 7 | \usepackage{breakurl} 8 | \geometry{letterpaper} % ... or a4paper or a5paper or ... 9 | %\geometry{landscape} % Activate for for rotated page geometry 10 | \usepackage[parfill]{parskip} % Activate to begin paragraphs with an empty line rather than an indent 11 | \usepackage{graphicx} 12 | \usepackage{amssymb, amsmath} 13 | \usepackage{epstopdf} 14 | 15 | \DeclareGraphicsRule{.tif}{png}{.png}{`convert #1 `dirname #1`/`basename #1 .tif`.png} 16 | 17 | \title{Observations on Meshes} 18 | \author{Miles Macklin} 19 | %\date{} % Activate to display a given date or no date 20 | 21 | \begin{document} 22 | \maketitle 23 | 24 | \section{Motivation} 25 | 26 | Manifold meshes are important for many purposes including physical simulation. 27 | 28 | \includegraphics[width=100mm]{Figures.pdf} 29 | 30 | \subsection{Triangle Meshes} 31 | 32 | How to classify a vertex based on the number of incident faces and edges. 33 | 34 | Interior Vertex: $numEdges = numFaces$ 35 | 36 | Boundary Vertex: $numEdges = numFaces+1$ or $numEdgesOpen = 2$ 37 | s 38 | Otherwise vertex is singular. 39 | 40 | \subsection{Tetrahedral Meshes} 41 | 42 | There are analogous formulas for tetrahedral meshes, but I can't find them. 43 | 44 | Interior Vertex: $numFaces = 2*numTets$ 45 | 46 | Boundary Vertex: ???? 47 | 48 | \section {References} 49 | 50 | \begin{itemize} 51 | \item{[Gueziec et. al] - Converting Sets of Polygons to Manifold Surfaces by Cutting and Stitching - \url{(http://mesh.brown.edu/taubin/pdfs/gueziec-etal-vis98.pdf}} 52 | \end{itemize} 53 | \end{document} 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /projects/fem/vencode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ffmpeg -r 60 -f image2 -i ./dump/frame%d.tga -threads 0 -vcodec libx264 -vpre slow -crf 20 $1 3 | -------------------------------------------------------------------------------- /projects/fog/data/common.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | #define saturate(x) clamp(x, 0.0, 1.0) 4 | #define kPi 3.1415926535897 5 | 6 | vec3 LinearToSrgb(vec3 rgb) 7 | { 8 | return pow(rgb, vec3(1.0/2.2)); 9 | } 10 | 11 | vec3 SrgbToLinear(vec3 rgb) 12 | { 13 | return pow(rgb, vec3(2.2)); 14 | } 15 | 16 | float LinearToSrgb(float rgb) 17 | { 18 | return pow(rgb, float(1.0/2.2)); 19 | } 20 | 21 | float SrgbToLinear(float rgb) 22 | { 23 | return pow(rgb, float(2.2)); 24 | } 25 | 26 | vec3 ToneMap(vec3 rgb) 27 | { 28 | // simple Reinhard like tone mapping 29 | float l = dot(rgb, vec3(0.212671, 0.715160, 0.072169)); 30 | 31 | return rgb / (l + 1.0); 32 | } 33 | 34 | float CalculateShadowFactor(sampler2DShadow texDepth, vec3 uvw, const int samples) 35 | { 36 | // Poisson disc 37 | vec2 vTaps[12] = vec2[] (vec2(-0.326212,-0.40581),vec2(-0.840144,-0.07358), 38 | vec2(-0.695914,0.457137),vec2(-0.203345,0.620716), 39 | vec2(0.96234,-0.194983),vec2(0.473434,-0.480026), 40 | vec2(0.519456,0.767022),vec2(0.185461,-0.893124), 41 | vec2(0.507431,0.064425),vec2(0.89642,0.412458), 42 | vec2(-0.32194,-0.932615),vec2(-0.791559,-0.59771) ); 43 | 44 | float s = 0.0; 45 | float radius = 0.002; 46 | 47 | for (int i=0; i < 12; i++) 48 | { 49 | s += shadow2D(texDepth, vec3(uvw.xy + vTaps[i]*radius, uvw.z)).r; 50 | 51 | } 52 | 53 | s /= samples; 54 | 55 | return s; 56 | } 57 | 58 | void SolveQuadratic(float a, float b, float c, out float minT, out float maxT) 59 | { 60 | float discriminant = b*b - 4.0*a*c; 61 | 62 | if (discriminant < 0.0) 63 | { 64 | // no real solutions so return a degenerate result 65 | maxT = 0.0; 66 | minT = 0.0; 67 | return; 68 | } 69 | 70 | // numerical receipes 5.6 (this method ensures numerical accuracy is preserved) 71 | float t = -0.5 * (b + sign(b)*sqrt(discriminant)); 72 | float closestT = t / a; 73 | float furthestT = c / t; 74 | 75 | if (closestT > furthestT) 76 | { 77 | minT = furthestT; 78 | maxT = closestT; 79 | } 80 | else 81 | { 82 | minT = closestT; 83 | maxT = furthestT; 84 | } 85 | } 86 | 87 | /* 88 | float InScatter(vec3 start, vec3 dir, vec3 lightPos, float d) 89 | { 90 | // calculate quadratic coefficients a,b,c 91 | vec3 q = start - lightPos; 92 | 93 | float b = dot(dir, q); 94 | float c = dot(q, q); 95 | 96 | // evaluate integral 97 | float s = 1.0f / sqrt(c - b*b); 98 | 99 | float l = s * (atan( (d + b) * s) - atan( b*s )); 100 | 101 | return l; 102 | } 103 | */ 104 | 105 | float MiniMax3Atan(float x) 106 | { 107 | //return -0.0000120333 + 1.00712*x - 0.0954105*x*x - 0.130234*x*x*x; 108 | //return ((-0.130234*x - 0.0954105)*x + 1.00712)*x - 0.00001203333; // Horner form 109 | //return (-0.130234*x + 0.0954105)*x*x + (1.00712*x + 00001203333); // Erstin's form 110 | return x*(1.037907119-0.2525089558*x); 111 | } 112 | 113 | 114 | float fastatan(float x) 115 | { 116 | //return clamp(0.9974133042*x, -0.5*kPi, 0.5*kPi); 117 | //return kPi*0.5*x / (1.0+x); 118 | 119 | if (x < 1) 120 | return MiniMax3Atan(x); 121 | else 122 | return kPi*0.5 - MiniMax3Atan(1.0/x); 123 | 124 | //return atan(x); 125 | } 126 | 127 | 128 | 129 | float atanTaylor(float x) 130 | { 131 | return fastatan(x); 132 | } 133 | 134 | float InScatter(vec3 start, vec3 dir, vec3 lightPos, float d) 135 | { 136 | // calculate quadratic coefficients a,b,c 137 | vec3 q = start - lightPos; 138 | 139 | float b = dot(dir, q); 140 | float c = dot(q, q); 141 | 142 | // evaluate integral 143 | float s = 1.0 / (sqrt(c - b*b) + 0.00001); 144 | 145 | //float u = (d+b)*s; 146 | //float v = b*s; 147 | 148 | //float f = (u-v) / (abs(1.0+u*v) + 0.0001); 149 | 150 | float u = d*s; 151 | float v = b*s; 152 | 153 | float x = (1.0+(u+v)*v); 154 | float f = (u) / clamp(x, 0.0, x); 155 | 156 | float l = s * fastatan( f ); 157 | 158 | //float l = s * (atan(u) - atan(v )); 159 | //float l = s * fastatan(f); 160 | //float l = s * atanTaylor(f); 161 | //float l = s * pow(clamp(f/(kPi*0.5), 0.0, 1.0), 5.0)*kPi*0.5; 162 | 163 | return l; 164 | } 165 | 166 | 167 | 168 | // simple diffuse + blinn phong lighting model 169 | void Li(vec3 surfacePos, vec3 surfaceNormal, vec3 lightPos, vec3 eyePos, float specularPower, out float diffuse, out float specular) 170 | { 171 | vec3 l = lightPos-surfacePos; 172 | vec3 e = normalize(eyePos-surfacePos); 173 | 174 | float d = length(l); 175 | l /= d; 176 | 177 | // half vector 178 | vec3 h = normalize(e+l); 179 | 180 | diffuse = saturate(dot(surfaceNormal, l)) / (d*d); 181 | specular = pow(saturate(dot(h,surfaceNormal)), specularPower); 182 | } -------------------------------------------------------------------------------- /projects/fog/data/pointlight.glsl: -------------------------------------------------------------------------------- 1 | #include "common.glsl" 2 | 3 | uniform mat4 g_lightToWorld; 4 | uniform mat4 g_worldToLight; 5 | 6 | uniform vec4 g_lightPos; 7 | uniform vec4 g_lightCol; 8 | uniform float g_scatteringCoefficient; 9 | 10 | uniform sampler3D g_noiseTexture; 11 | 12 | void main() 13 | { 14 | vec3 surfacePos = gl_TexCoord[0].xyz; 15 | vec3 surfaceNormal = gl_TexCoord[1].xyz; 16 | vec3 cameraPos = gl_ModelViewMatrixInverse[3].xyz; 17 | vec3 lightPos = g_lightToWorld[3].xyz; 18 | 19 | //vec3 noise = texture3D(g_noiseTexture, 0.1*(surfacePos + (surfacePos-cameraPos)*0.5)).xyz; 20 | 21 | vec3 dir = surfacePos - cameraPos;// + noise; 22 | float l = length(dir); 23 | dir /= l; 24 | 25 | // calculate in-scattering contribution 26 | vec3 scatter = g_lightCol.xyz * vec3(0.2, 0.5, 0.8) * InScatter(cameraPos, dir, lightPos, l) * g_scatteringCoefficient; 27 | 28 | // calculate contribution from diffuse reflection 29 | float diffuse; 30 | float specular; 31 | 32 | float specularExponent = 15.0; 33 | float specularIntensity = 0.02; 34 | 35 | Li(surfacePos, surfaceNormal, lightPos, cameraPos, specularExponent, diffuse, specular); 36 | 37 | vec3 r = LinearToSrgb(g_lightCol.xyz * (diffuse + specular * specularIntensity) + scatter); 38 | 39 | gl_FragColor = vec4(r, 1.0); 40 | //gl_FragColor = vec4(texture3D( g_noiseTexture, surfacePos * 0.1).xyz, 1.0); 41 | } -------------------------------------------------------------------------------- /projects/fog/data/simplevertex.glsl: -------------------------------------------------------------------------------- 1 | #include "common.glsl" 2 | 3 | void main() 4 | { 5 | gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; 6 | gl_TexCoord[0] = gl_Vertex; 7 | gl_TexCoord[1].xyz = gl_Normal.xyz; 8 | gl_TexCoord[2].xy = gl_MultiTexCoord0.xy; 9 | } -------------------------------------------------------------------------------- /projects/fog/data/spotlight.glsl: -------------------------------------------------------------------------------- 1 | #include "common.glsl" 2 | 3 | uniform sampler2D g_texDiffuse; 4 | uniform sampler2D g_texNormal; 5 | uniform sampler2DShadow g_texDepth; 6 | uniform mat4 g_lightToWorld; 7 | uniform mat4 g_worldToLight; 8 | 9 | uniform vec4 g_lightPos; 10 | uniform vec4 g_lightCol; 11 | uniform float g_scatteringCoefficient; 12 | 13 | uniform sampler3D g_noiseTexture; 14 | 15 | void IntersectCone(vec3 rayOrigin, vec3 rayDir, mat4 invConeTransform, float aperture, float height, out float minT, out float maxT) 16 | { 17 | vec4 localOrigin = invConeTransform * vec4(rayOrigin, 1.0); 18 | vec4 localDir = invConeTransform * vec4(rayDir, 0.0); 19 | 20 | // could perform this on the cpu 21 | float tanTheta = tan(aperture); 22 | tanTheta *= tanTheta; 23 | 24 | float a = localDir.x*localDir.x + localDir.z*localDir.z - localDir.y*localDir.y*tanTheta; 25 | float b = 2.0*(localOrigin.x*localDir.x + localOrigin.z*localDir.z - localOrigin.y*localDir.y*tanTheta); 26 | float c = localOrigin.x*localOrigin.x + localOrigin.z*localOrigin.z - localOrigin.y*localOrigin.y*tanTheta; 27 | 28 | SolveQuadratic(a, b, c, minT, maxT); 29 | 30 | float y1 = localOrigin.y + localDir.y*minT; 31 | float y2 = localOrigin.y + localDir.y*maxT; 32 | 33 | // should be possible to simplify these branches if the compiler isn't already doing it 34 | 35 | if (y1 > 0.0 && y2 > 0.0) 36 | { 37 | // both intersections are in the reflected cone so return degenerate value 38 | minT = 0.0; 39 | maxT = -1.0; 40 | } 41 | else if (y1 > 0.0 && y2 < 0.0) 42 | { 43 | // closest t on the wrong side, furthest on the right side => ray enters volume but doesn't leave it (so set maxT arbitrarily large) 44 | minT = maxT; 45 | maxT = 10000.0; 46 | } 47 | else if (y1 < 0.0 && y2 > 0.0) 48 | { 49 | // closest t on the right side, largest on the wrong side => ray starts in volume and exits once 50 | maxT = minT; 51 | minT = 0.0; 52 | } 53 | } 54 | 55 | float SpotFalloff(vec3 surfacePos, float aperture, vec3 lightDir, vec3 lightPos) 56 | { 57 | vec3 l = lightPos-surfacePos; 58 | float d = length(l); 59 | l /= d; 60 | 61 | float a = saturate(1.0 - acos(saturate(dot(l, lightDir))) / aperture); 62 | 63 | return a; 64 | } 65 | 66 | void main() 67 | { 68 | vec3 surfacePos = gl_TexCoord[0].xyz; 69 | vec3 surfaceNormal = gl_TexCoord[1].xyz; 70 | vec3 cameraPos = gl_ModelViewMatrixInverse[3].xyz; 71 | vec3 lightPos = g_lightToWorld[3].xyz; 72 | vec3 lightDir = g_lightToWorld[1].xyz; 73 | 74 | vec3 dir = surfacePos - cameraPos; 75 | float l = length(dir); 76 | dir /= l; 77 | 78 | // hard-coded light shape 79 | float aperture = 0.4; 80 | float height = 30.0; 81 | float minT = 0.0; 82 | float maxT = 0.0; 83 | 84 | IntersectCone(cameraPos, dir, g_worldToLight, aperture, height, minT, maxT); 85 | 86 | // clamp bounds to scene geometry / camera 87 | maxT = clamp(maxT, 0.0, l); 88 | minT = max(0.0, minT); 89 | 90 | float t = max(0.0, maxT - minT); 91 | 92 | float innerMin = (minT + maxT)*0.5 - t * 0.6 * 0.5; 93 | 94 | //vec3 noise = texture3D(g_noiseTexture, 0.9*(cameraPos + (surfacePos-cameraPos)*0.1)).xyz; 95 | //dir = normalize(dir + noise); 96 | 97 | vec3 scatter = g_lightCol.xyz * vec3(0.2, 0.5, 0.8) * InScatter(cameraPos + dir*minT, dir, lightPos, t) * g_scatteringCoefficient; 98 | 99 | // calculate contribution from diffuse reflection 100 | float diffuse; 101 | float specular; 102 | float falloff = SpotFalloff(surfacePos, aperture, lightDir, lightPos); 103 | 104 | float specularExponent = 15.0; 105 | float specularIntensity = 0.02; 106 | 107 | Li(surfacePos, surfaceNormal, lightPos, cameraPos, specularExponent, diffuse, specular); 108 | 109 | vec3 r = LinearToSrgb(g_lightCol.xyz * (falloff * (diffuse + specular * specularIntensity)) + scatter); 110 | 111 | gl_FragColor = vec4(r, 1.0); 112 | 113 | } -------------------------------------------------------------------------------- /projects/fog/fogvolumes.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FogVolumes", "FogVolumes.vcxproj", "{2BB0ABBF-95C3-48A2-BDE3-1E2B78FA338D}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {2BB0ABBF-95C3-48A2-BDE3-1E2B78FA338D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {2BB0ABBF-95C3-48A2-BDE3-1E2B78FA338D}.Debug|Win32.Build.0 = Debug|Win32 19 | {2BB0ABBF-95C3-48A2-BDE3-1E2B78FA338D}.Release|Win32.ActiveCfg = Release|Win32 20 | {2BB0ABBF-95C3-48A2-BDE3-1E2B78FA338D}.Release|Win32.Build.0 = Release|Win32 21 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /projects/gi/gi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GI", "GI.vcxproj", "{B060D2BC-738B-4E39-B79F-7D6201393491}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shared", "..\Shared\Shared.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B060D2BC-738B-4E39-B79F-7D6201393491}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {B060D2BC-738B-4E39-B79F-7D6201393491}.Debug|Win32.Build.0 = Debug|Win32 16 | {B060D2BC-738B-4E39-B79F-7D6201393491}.Release|Win32.ActiveCfg = Release|Win32 17 | {B060D2BC-738B-4E39-B79F-7D6201393491}.Release|Win32.Build.0 = Release|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 21 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /projects/gi/gi.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/gi/gi.suo -------------------------------------------------------------------------------- /projects/gi/gi_shot1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/gi/gi_shot1.jpg -------------------------------------------------------------------------------- /projects/gi/gi_shot2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/gi/gi_shot2.jpg -------------------------------------------------------------------------------- /projects/gi/illuminate.fp: -------------------------------------------------------------------------------- 1 | 2 | uniform sampler2D texPosition; 3 | uniform sampler2D texNormal; 4 | uniform sampler2D texIrradiance; 5 | uniform sampler2D texAlbedo; 6 | uniform sampler2D texIndices; 7 | 8 | float kPi = 3.1415926535897932384626433832795; 9 | float kInvPi = 1.0f / kPi; 10 | 11 | float CalculateClippedArea(vec3 v, vec3 nr, vec3 ne, float a) 12 | { 13 | float r2 = abs(a) / kPi; 14 | float r = sqrt(r2); 15 | float h = max(dot(v, nr), 0.0); 16 | float d = h / (1.0-abs(dot(nr,ne))); 17 | 18 | //float c = sqrt(r2-d*d); 19 | float theta = 2.0*acos(clamp(d/r,0.0,1.0)); 20 | float stheta = sin(theta); 21 | 22 | float cseg = 0.5*r2*(theta-stheta); 23 | return abs(a)-cseg; 24 | //return a; 25 | } 26 | 27 | void main() 28 | { 29 | vec4 receiverPosition = texture2D(texPosition, gl_TexCoord[0].xy); 30 | 31 | //if(isnan(receiverPosition.x)) 32 | //discard; 33 | 34 | vec4 receiverNormal = texture2D(texNormal, gl_TexCoord[0].xy); 35 | vec4 receiverIrradiance = vec4(0.0); 36 | float receiverArea = receiverPosition.w; 37 | 38 | //gl_FragColor = receiverNormal; 39 | 40 | 41 | // if we are not a leaf surfel 42 | if (receiverNormal.w > 0.0) 43 | { 44 | // first child 45 | vec2 childIndex = texture2D(texIndices, gl_TexCoord[0].xy).zw; 46 | 47 | float totalArea = 0.0; 48 | 49 | // iterate over children gathering radiance 50 | int numChildren = int(receiverNormal.w); 51 | for (int i=0; i < numChildren; i++) 52 | { 53 | vec4 childPosition = texture2D(texPosition, childIndex); 54 | vec4 childIrradiance = texture2D(texIrradiance, childIndex); 55 | 56 | receiverIrradiance += childIrradiance*abs(childPosition.w); 57 | totalArea += abs(childPosition.w); 58 | 59 | // go to next emitter 60 | childIndex = texture2D(texIndices, childIndex).xy; 61 | } 62 | 63 | receiverIrradiance /= totalArea; 64 | } 65 | else 66 | { 67 | vec2 emitterIndex = vec2(0.0, 0.0); 68 | 69 | // have to double up the loops as there seems to be a 255 iteration limit per loop 70 | while (emitterIndex.y != 1.0) 71 | while (emitterIndex.y != 1.0) 72 | { 73 | vec4 emitterPosition = texture2D(texPosition, emitterIndex); 74 | vec4 emitterNext = texture2D(texIndices, emitterIndex); 75 | float emitterArea = emitterPosition.w; 76 | 77 | // vector to emitter 78 | vec3 v = emitterPosition.xyz - receiverPosition.xyz; 79 | float dSq = dot(v,v) + 1e-16; 80 | 81 | // if close enough then traverse children 82 | if (dSq < 4.0*-emitterArea*kInvPi) 83 | { 84 | emitterNext.xy = emitterNext.zw; 85 | emitterArea = 0.0; 86 | } 87 | 88 | vec4 emitterNormal = texture2D(texNormal, emitterIndex); 89 | vec4 emitterIrradiance = texture2D(texIrradiance, emitterIndex); 90 | vec4 emitterColour = texture2D(texAlbedo, emitterIndex); 91 | 92 | // calc form factor 93 | vec3 dir = v * inversesqrt(dSq); 94 | 95 | float area = abs(emitterArea); 96 | 97 | float ev = dot(dir,emitterNormal.xyz); 98 | float rv = dot(dir,receiverNormal.xyz); 99 | //float ff = abs((area*clamp(rv, 0.0, 1.0)*ev)/(kPi*dSq+area)); 100 | float ff = 2.0*kPi*abs(ev*clamp(rv,0.0, 1.0)*(1.0 - inversesqrt(1.0 + ( area / ( dSq*kPi ) ) ) ) ); 101 | 102 | // add bounced light and glow sources 103 | if (emitterColour.a > 0.0) 104 | { 105 | receiverIrradiance.xyz += ff*emitterColour.xyz*emitterColour.a; 106 | } 107 | else if (ev < 0.0) 108 | { 109 | receiverIrradiance.xyz += ff*(emitterColour.xyz*kInvPi*emitterIrradiance.xyz); 110 | } 111 | else 112 | { 113 | receiverIrradiance.xyz -= ff*emitterIrradiance.xyz*0.8f; 114 | } 115 | 116 | emitterIndex = emitterNext.xy; 117 | } 118 | } 119 | 120 | gl_FragColor = max(receiverIrradiance, vec4(0.0)); 121 | 122 | } 123 | 124 | 125 | -------------------------------------------------------------------------------- /projects/gi/illuminate.vp: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 4 | gl_TexCoord[0] = gl_MultiTexCoord0; 5 | } -------------------------------------------------------------------------------- /projects/gi/illuminationsim.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core.h" 4 | #include "mesh.h" 5 | 6 | struct Surfel 7 | { 8 | Surfel() : position(0.0f) 9 | , normal(0.0f) 10 | , area(0.0f) 11 | , colour(0.0f) 12 | , emissive(0.0f) 13 | , irradiance(0.0f) 14 | , next(0) 15 | , numChildren(0) 16 | , tri(0) 17 | , depth(0) 18 | { 19 | } 20 | 21 | Vec3 position; 22 | Vec3 normal; 23 | float area; 24 | 25 | Colour colour; // material colour 26 | Colour emissive; // material emission 27 | Colour irradiance; // current irradiance 28 | 29 | size_t next; // for traversal 30 | size_t numChildren; // number of children in cluster 31 | size_t tri; // the tri this surfel represents 32 | size_t depth; 33 | }; 34 | 35 | typedef std::vector SurfelArray; 36 | 37 | // helper class to manage tree nodes stored in a contiguous linear array 38 | template 39 | class TreeNode : public T 40 | { 41 | public: 42 | 43 | TreeNode() : childPtr(NULL) 44 | , firstChild(0) 45 | , parent(0) 46 | { 47 | 48 | } 49 | 50 | // returns a surfels children 51 | const TreeNode& GetChild(size_t i) const 52 | { 53 | assert(i < numChildren); 54 | return (this-firstChild)[i]; 55 | } 56 | 57 | TreeNode& GetChild(size_t i) 58 | { 59 | assert(i < numChildren); 60 | return (this-firstChild)[i]; 61 | } 62 | 63 | TreeNode* childPtr; // relative index to first child 64 | size_t firstChild; 65 | size_t parent; // parent of the surfel 66 | //size_t depth; // just for debug 67 | size_t subtreeSize; // just for debug 68 | }; 69 | 70 | // some conveniences 71 | typedef TreeNode SurfelNode; 72 | typedef std::vector SurfelNodeArray; 73 | 74 | class IlluminationSim 75 | { 76 | public: 77 | 78 | enum DrawMode 79 | { 80 | kDrawSurfels = 1, 81 | kDrawIrradiance = 2, 82 | kDrawRadiance = 3, 83 | kDrawEmissive = 4, 84 | kDrawMesh = 5 85 | }; 86 | 87 | IlluminationSim(Mesh* m); 88 | ~IlluminationSim(); 89 | 90 | // steps the simulation 91 | void Step(); 92 | 93 | // debug visualisation 94 | void DrawDebug(DrawMode mode, int treeDepth=0); 95 | 96 | private: 97 | 98 | // adds a mesh into the sim 99 | void AddMesh(Mesh* m); 100 | 101 | // propogates radiance between surfels in the sim 102 | void UpdateSurfels(); 103 | 104 | // hierarchical radiance update 105 | void UpdateSurfelsFast(); 106 | void UpdateSurfelsFastPreOrder(); 107 | void UpdateSurfelsGPU(); 108 | 109 | // apply irradiance values back to the control mesh 110 | void UpdateMesh(); 111 | 112 | // generate clusters 113 | size_t BuildLightTree(SurfelNode* inputs, size_t numInputs, SurfelNode* clusters, const size_t degree); 114 | 115 | // helper 116 | void DrawSurfel(const Surfel& s, const Colour& c, bool solid); 117 | 118 | // surfels in our simulation 119 | SurfelNodeArray m_surfels; 120 | 121 | SurfelArray m_lightTreePreOrder; 122 | 123 | // source mesh 124 | Mesh* m_mesh; 125 | 126 | void InitGPUBuffers(); 127 | void UpdateGPUBuffers(); 128 | 129 | // shaders 130 | GLuint m_fragmentShader; 131 | GLuint m_vertexShader; 132 | GLuint m_glslProgram; 133 | 134 | // fragment shader params 135 | GLuint m_paramRcpScreen; 136 | GLuint m_paramTexPosition; 137 | GLuint m_paramTexNormal; 138 | GLuint m_paramTexIrradiance; 139 | GLuint m_paramTexAlbedo; 140 | GLuint m_paramTexIndices; 141 | 142 | // fbos 143 | GLuint m_fboIrradiance; 144 | 145 | // textures 146 | GLsizei m_gpuBufferWidth; 147 | GLsizei m_gpuBufferHeight; 148 | 149 | GLuint m_texPosition; 150 | GLuint m_texNormal; 151 | GLuint m_texIrradiance[2]; 152 | GLuint m_texAlbedo; 153 | GLuint m_texIndices; 154 | 155 | Vec4* m_readBuffer; 156 | 157 | // stats 158 | float m_statAddMeshTime; 159 | float m_statStepTime; 160 | float m_statBakeTime; 161 | float m_statBuildTreeTime; 162 | size_t m_statMaxChildrenPerNode; 163 | }; -------------------------------------------------------------------------------- /projects/granular2d/armadillo.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/granular2d/armadillo.tga -------------------------------------------------------------------------------- /projects/granular2d/bunny.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/granular2d/bunny.tga -------------------------------------------------------------------------------- /projects/granular2d/granular2d.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Granular2D", "Granular2D.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/granular2d/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -m32 -Wall -I"../.." -O3 -ffast-math -msse -msse2 -msse3 -mfpmath=sse 5 | LDFLAGS = -g -m32 -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = granular2d 8 | 9 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../core/maths.cpp ../../core/mesh.cpp ../../core/aabbtree.cpp ../../core/tga.cpp 10 | HEADERS = $(wildcard *.h) 11 | 12 | OBJECTS = $(SOURCES:.cpp=.o) 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) makefile 17 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 18 | 19 | clean: 20 | -rm -f $(OBJECTS) 21 | -rm -f $(TARGET) 22 | 23 | %.o: %.cpp $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o $@ $< 25 | 26 | 27 | run: $(TARGET) 28 | ./$(TARGET) 29 | 30 | .PHONY : all clean 31 | -------------------------------------------------------------------------------- /projects/granular2d/solve.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef CUDA 4 | #include 5 | #include // includes cuda.h and cuda_runtime_api.h 6 | #else 7 | typedef Vec2 float2; 8 | typedef Vec3 float3; 9 | #endif 10 | 11 | 12 | struct GrainSystem; 13 | 14 | struct GrainParams 15 | { 16 | float2 mGravity; 17 | float mDamp; 18 | 19 | float mBaumgarte; 20 | float mFriction; 21 | float mRestitution; 22 | float mOverlap; 23 | 24 | float3 mPlanes[8]; 25 | int mNumPlanes; 26 | }; 27 | 28 | struct GrainTimers 29 | { 30 | GrainTimers() 31 | : mCreateCellIndices(0.0f) 32 | , mSortCellIndices(0.0f) 33 | , mCreateGrid(0.0f) 34 | , mCollide(0.0f) 35 | , mIntegrate(0.0f) 36 | , mReorder(0.0f) 37 | { 38 | } 39 | 40 | float mCreateCellIndices; 41 | float mSortCellIndices; 42 | float mCreateGrid; 43 | float mCollide; 44 | float mIntegrate; 45 | float mReorder; 46 | }; 47 | 48 | GrainSystem* grainCreateSystem(int numGrains); 49 | void grainDestroySystem(GrainSystem* s); 50 | 51 | void grainSetSprings(GrainSystem* s, const uint32_t* indices, const float* restLengths, uint32_t numSprings); 52 | 53 | void grainSetPositions(GrainSystem* s, float* p, int n); 54 | void grainSetVelocities(GrainSystem* s, float* v, int n); 55 | 56 | void grainGetPositions(GrainSystem* s, float* p); 57 | void grainGetVelocities(GrainSystem* s, float* v); 58 | 59 | void grainSetRadii(GrainSystem* s, float* r); 60 | void grainGetRadii(GrainSystem* s, float r); 61 | 62 | void grainGetMass(GrainSystem* s, float* r); 63 | 64 | void grainSetParams(GrainSystem* s, GrainParams* params); 65 | 66 | void grainUpdateSystem(GrainSystem* s, float dt, int iterations, GrainTimers* timers); 67 | -------------------------------------------------------------------------------- /projects/granular2d/sort.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | typedef unsigned int uint32_t; 5 | typedef unsigned short uint16_t; 6 | #endif 7 | 8 | //#include "b40c/radix_sort/enactor.cuh" 9 | 10 | void SortCellIndices(uint32_t* cellIds, uint32_t* particleIndices, uint32_t numGrains) 11 | { 12 | thrust::sort_by_key(thrust::device_ptr(cellIds), 13 | thrust::device_ptr(cellIds+numGrains), 14 | thrust::device_ptr(particleIndices)); 15 | } 16 | 17 | void SortCellIndices(float* cellIds, uint32_t* particleIndices, uint32_t numGrains) 18 | { 19 | thrust::sort_by_key(thrust::device_ptr(cellIds), 20 | thrust::device_ptr(cellIds+numGrains), 21 | thrust::device_ptr(particleIndices)); 22 | } 23 | -------------------------------------------------------------------------------- /projects/granular3d/granular.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Granular", "Granular.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/granular3d/shaders.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define STRINGIFY(A) #A 4 | 5 | #include 6 | #include 7 | 8 | void ShadowCreate(GLuint& texture, GLuint& frameBuffer); 9 | void ShadowBegin(GLuint texture, GLuint frameBuffer); 10 | void ShadowEnd(); 11 | 12 | void DrawPlanes(Vec4* planes, int n, Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, GLuint shadowTex); 13 | void DrawPoints(float* positions, int n, float radius, float screenWidth, float screenAspect, float fov, Vec3 lightPos, Vec3 lightTarget, Matrix44 lightTransform, GLuint shadowTex); 14 | 15 | -------------------------------------------------------------------------------- /projects/granular3d/solve.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/maths.h" 4 | 5 | struct GrainSystem; 6 | 7 | struct GrainParams 8 | { 9 | Vec3 mGravity; 10 | float mDamp; 11 | 12 | float mBaumgarte; 13 | float mFriction; 14 | float mRestitution; 15 | float mOverlap; 16 | float mDissipation; 17 | 18 | Vec4 mPlanes[8]; 19 | int mNumPlanes; 20 | }; 21 | 22 | struct GrainTimers 23 | { 24 | GrainTimers() 25 | : mCreateCellIndices(0.0f) 26 | , mSortCellIndices(0.0f) 27 | , mCreateGrid(0.0f) 28 | , mCollide(0.0f) 29 | , mIntegrate(0.0f) 30 | , mReorder(0.0f) 31 | { 32 | } 33 | 34 | float mCreateCellIndices; 35 | float mSortCellIndices; 36 | float mCreateGrid; 37 | float mCollide; 38 | float mIntegrate; 39 | float mReorder; 40 | }; 41 | 42 | GrainSystem* grainCreateSystem(int numGrains); 43 | void grainDestroySystem(GrainSystem* s); 44 | 45 | void grainSetSprings(GrainSystem* s, const uint32_t* springIndices, const float* springLengths, uint32_t numSprings); 46 | 47 | void grainSetPositions(GrainSystem* s, float* p, int n); 48 | void grainSetVelocities(GrainSystem* s, float* v, int n); 49 | 50 | void grainGetPositions(GrainSystem* s, float* p); 51 | void grainGetVelocities(GrainSystem* s, float* v); 52 | 53 | void grainSetRadii(GrainSystem* s, float* r); 54 | void grainGetRadii(GrainSystem* s, float* r); 55 | 56 | void grainSetParams(GrainSystem* s, GrainParams* params); 57 | 58 | void grainUpdateSystem(GrainSystem* s, float dt, int iterations, GrainTimers* timers); 59 | -------------------------------------------------------------------------------- /projects/granular3d/sort.cu: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _WIN32 4 | typedef unsigned int uint32_t; 5 | typedef unsigned short uint16_t; 6 | #endif 7 | 8 | void SortCellIndices(uint32_t* cellIds, uint32_t* particleIndices, uint32_t numGrains) 9 | { 10 | thrust::sort_by_key(thrust::device_ptr(cellIds), 11 | thrust::device_ptr(cellIds+numGrains), 12 | thrust::device_ptr(particleIndices)); 13 | } 14 | 15 | void SortCellIndices(float* cellIds, uint32_t* particleIndices, uint32_t numGrains) 16 | { 17 | thrust::sort_by_key(thrust::device_ptr(cellIds), 18 | thrust::device_ptr(cellIds+numGrains), 19 | thrust::device_ptr(particleIndices)); 20 | } 21 | -------------------------------------------------------------------------------- /projects/nanoray/camera.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/nanoray/camera.cpp -------------------------------------------------------------------------------- /projects/nanoray/camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Camera 4 | { 5 | public: 6 | 7 | Camera() : m_cameraToWorld(Matrix44::kIdentity), 8 | m_rasterToWorld(Matrix44::kIdentity) 9 | { 10 | } 11 | 12 | Camera(const Matrix44& cameraToWorld, 13 | float fov, 14 | float near, 15 | float far, 16 | uint32_t width, 17 | uint32_t height) : m_cameraToWorld(cameraToWorld) 18 | 19 | { 20 | Matrix44 rasterToScreen( 2.0f / width, 0.0f, 0.0f, 0.0f, 21 | 0.0f, -2.0f / height, 0.0f, 0.0f, 22 | 0.0f, 0.0f, 1.0f, 0.0f, 23 | -1.0f, 1.0f, 1.0f, 1.0f); 24 | 25 | float f = tanf(fov*0.5f); 26 | float aspect = float(width) / height; 27 | 28 | Matrix44 screenToCamera(f*aspect, 0.0f, 0.0f, 0.0f, 29 | 0.0f, f, 0.0f, 0.0f, 30 | 0.0f, 0.0f, -1.0f, 0.0f, 31 | 0.0f, 0.0f, 0.0f, 1.0f); 32 | 33 | m_rasterToWorld = cameraToWorld*screenToCamera*rasterToScreen; 34 | } 35 | 36 | void GenerateRay(uint32_t rasterX, uint32_t rasterY, Point3& origin, Vector3& dir) const 37 | { 38 | float xoff = Randf(-0.5f, 0.5f); 39 | float yoff = Randf(-0.5f, 0.5f); 40 | 41 | Point3 p = m_rasterToWorld * Point3(float(rasterX) + 0.5f + xoff, float(rasterY) + 0.5f + yoff, 0.0f); 42 | 43 | origin = m_cameraToWorld.GetTranslation(); 44 | dir = Normalize(p-m_cameraToWorld.GetTranslation()); 45 | } 46 | 47 | void GenerateRayNoJitter(uint32_t rasterX, uint32_t rasterY, Point3& origin, Vector3& dir) const 48 | { 49 | Point3 p = m_rasterToWorld * Point3(float(rasterX) + 0.5f, float(rasterY) + 0.5f, 0.0f); 50 | 51 | origin = m_cameraToWorld.GetTranslation(); 52 | dir = Normalize(p-m_cameraToWorld.GetTranslation()); 53 | } 54 | 55 | Matrix44 m_cameraToWorld; 56 | Matrix44 m_rasterToWorld; 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /projects/nanoray/integrators.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/core.h" 4 | #include "core/maths.h" 5 | 6 | #include "scene.h" 7 | 8 | Colour PathTrace(const Scene& s, const Point3& rayOrigin, const Vector3& rayDir); 9 | Colour ForwardTraceImportance(const Scene& scene, const Point3& startOrigin, const Vector3& startDir); 10 | Colour ForwardTraceUniform(const Scene& scene, const Point3& startOrigin, const Vector3& startDir); 11 | Colour Whitted(const Scene& s, const Point3& rayOrigin, const Vector3& rayDir); 12 | Colour Debug(const Scene& s, const Point3& rayOrigin, const Vector3& rayDir); 13 | 14 | -------------------------------------------------------------------------------- /projects/nanoray/lights.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/nanoray/lights.cpp -------------------------------------------------------------------------------- /projects/nanoray/lights.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/nanoray/lights.h -------------------------------------------------------------------------------- /projects/nanoray/material.cpp: -------------------------------------------------------------------------------- 1 | #include "materials.h" -------------------------------------------------------------------------------- /projects/nanoray/metaballs.cpp: -------------------------------------------------------------------------------- 1 | #include "metaballs.h" 2 | 3 | -------------------------------------------------------------------------------- /projects/nanoray/metaballs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/maths.h" 4 | #include "core/core.h" 5 | 6 | class Metaballs 7 | { 8 | public: 9 | 10 | struct Ball 11 | { 12 | Point3 m_pos; 13 | float m_radius; 14 | }; 15 | 16 | Metaballs(const Ball* balls, uint32_t n) 17 | { 18 | m_numBalls = n; 19 | m_balls = new Ball[n]; 20 | memcpy(m_balls, balls, sizeof(Ball)*n); 21 | 22 | // calculate the sum of the radii used to approximate the distance field 23 | for (uint32_t i=0; i < n; ++i) 24 | { 25 | m_radiiSum += balls[i].m_radius; 26 | } 27 | } 28 | 29 | ~Metaballs() 30 | { 31 | delete[] m_balls; 32 | } 33 | 34 | 35 | // evaluate the distance of a point to the iso-surface of the surface (lower-bound) 36 | float Distance(const Point3& p, float threshold) 37 | { 38 | float density = 0.0f; 39 | for (uint32_t i=0; i < m_numBalls; ++i) 40 | { 41 | density += Density(Length(m_balls[i].m_pos-p), m_balls[i].m_radius); 42 | } 43 | 44 | return 2.0f/3.0f * m_radiiSum * (threshold - density); 45 | } 46 | 47 | private: 48 | 49 | float Density(float r, float rmax) 50 | { 51 | if (r > rmax) 52 | return 0.0f; 53 | else 54 | { 55 | float t = (r/rmax); 56 | return 2.0f*(t*t*t) - 3.0f*(t*t) + 1.0f; 57 | } 58 | } 59 | 60 | float m_radiiSum; 61 | uint32_t m_numBalls; 62 | 63 | Ball* m_balls; 64 | }; -------------------------------------------------------------------------------- /projects/nanoray/nanoray.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NanoRay", "NanoRay.vcxproj", "{7EF7426A-05B6-4A5C-AB23-D417D081C6B2}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 7 | EndProjectSection 8 | EndProject 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{10587316-BB82-493F-B9CC-6B52AA88CEE9}" 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\core\core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Win32 = Debug|Win32 16 | Release|Win32 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {7EF7426A-05B6-4A5C-AB23-D417D081C6B2}.Debug|Win32.ActiveCfg = Debug|Win32 20 | {7EF7426A-05B6-4A5C-AB23-D417D081C6B2}.Debug|Win32.Build.0 = Debug|Win32 21 | {7EF7426A-05B6-4A5C-AB23-D417D081C6B2}.Release|Win32.ActiveCfg = Release|Win32 22 | {7EF7426A-05B6-4A5C-AB23-D417D081C6B2}.Release|Win32.Build.0 = Release|Win32 23 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 25 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 26 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /projects/nanoray/nanoray.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files 33 | 34 | 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | -------------------------------------------------------------------------------- /projects/nanoray/primitives.cpp: -------------------------------------------------------------------------------- 1 | #include "primitives.h" 2 | -------------------------------------------------------------------------------- /projects/nanoray/rendercl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void* RenderJobThreadFuncOpenCL(void* param); -------------------------------------------------------------------------------- /projects/nanoray/renderjob.cl: -------------------------------------------------------------------------------- 1 | /*! 2 | * Sample kernel which multiplies every element of the input array with 3 | * a constant and stores it at the corresponding output array 4 | */ 5 | 6 | #define PLATFORM_OPENCL 1 7 | 8 | #include "renderjob.h" 9 | 10 | 11 | __kernel void renderKernel(__global float4* output) 12 | { 13 | uint tid = get_global_id(0); 14 | 15 | output[tid] = (float4)(tid*0.00001f, tid*0.00001f, 0.0f, 1.0f); 16 | } 17 | -------------------------------------------------------------------------------- /projects/nanoray/renderjob.cpp: -------------------------------------------------------------------------------- 1 | #include "renderjob.h" 2 | 3 | #include "integrators.h" 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | extern _declspec(thread) MemoryArena* g_memArena; 10 | 11 | uint32_t RenderTileThreadFunc(void* data) 12 | { 13 | RenderJob& job = *(RenderJob*)(data); 14 | 15 | //TODO: this should just be a member 16 | SampleBuffer out(job.m_output, job.m_renderRect); 17 | 18 | const Point3 rayOrigin = job.m_camera.m_cameraToWorld.GetTranslation(); 19 | const Rect rect = job.m_renderRect; 20 | 21 | // take image samples 22 | for (uint32_t i=rect.Top(); i < rect.Bottom(); ++i) 23 | { 24 | for (uint32_t j=rect.Left(); j < rect.Right(); ++j) 25 | { 26 | Colour radiance(0.0f); 27 | 28 | for (uint32_t s=0; s < job.m_samplesPerPixel; ++s) 29 | { 30 | Vector3 rayDir; 31 | job.m_camera.GenerateRay(j, i, rayDir); 32 | 33 | #if _DEBUG 34 | if (j == 22 && i == 16 && s == 48) 35 | { 36 | cout << "Blah" << endl; 37 | } 38 | #endif 39 | Colour L = PathTrace(*job.m_scene, rayOrigin, rayDir); 40 | //Colour L = ForwardTraceImportance(*m_scene, rayOrigin, rayDir); 41 | //Colour L = Debug(*m_scene, rayOrigin, rayDir); 42 | 43 | #if _DEBUG 44 | if (!_finite(L.r) || _isnan(L.r) || 45 | !_finite(L.g) || _isnan(L.g) || 46 | !_finite(L.b) || _isnan(L.b)) 47 | { 48 | cout << "Error" << endl; 49 | } 50 | #endif 51 | radiance += L; 52 | 53 | // reset the memory arena 54 | g_memArena->Reset(); 55 | } 56 | 57 | out.AddSample(float(j), float(i), radiance * (1.0f / job.m_samplesPerPixel)); 58 | } 59 | } 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /projects/nanoray/renderjob.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "scene.h" 4 | #include "camera.h" 5 | 6 | 7 | // holds samples 8 | class SampleBuffer 9 | { 10 | public: 11 | 12 | SampleBuffer(Colour* memory, const Rect& r) : m_data(memory), m_rect(r) 13 | { 14 | 15 | } 16 | 17 | // accumulates samples specified in continuous raster space 18 | void AddSample(float x, float y, const Colour& c) 19 | { 20 | assert(m_rect.Contains(uint32_t(x), uint32_t(y))); 21 | 22 | // calculate offset into data 23 | const uint32_t row = uint32_t(y) - m_rect.Top(); 24 | const uint32_t col = uint32_t(x) - m_rect.Left(); 25 | 26 | const uint32_t i = (m_rect.Width() * row) + col; 27 | 28 | m_data[i] = c; 29 | } 30 | 31 | Rect m_rect; 32 | Colour* m_data; 33 | 34 | } ; 35 | 36 | 37 | // perform rendering 38 | struct RenderJob 39 | { 40 | 41 | // raster space sub rect to process 42 | Rect m_renderRect; 43 | // raster space rect to filter over 44 | Rect m_filterRect; 45 | 46 | // our view 47 | Camera m_camera; 48 | 49 | // scene description 50 | const Scene* m_scene; 51 | 52 | // output, executing process must supply filtered radiance values 53 | Colour* m_output; 54 | uint32_t m_outputPitch; 55 | 56 | // quality settings 57 | uint32_t m_samplesPerPixel; 58 | 59 | }; 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /projects/nanoray/renderspu.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/nanoray/renderspu.cpp -------------------------------------------------------------------------------- /projects/nanoray/renderspu.h: -------------------------------------------------------------------------------- 1 | #ifdef PLATFORM_PS3 2 | 3 | #include 4 | 5 | extern spe_program_handle_t gRenderJobSpuModule; 6 | 7 | // on SPU we need to kick create an SPU job context and wait for that 8 | void* RenderJobThreadFuncSPU(void* param) 9 | { 10 | int retval; 11 | unsigned int entry_point = SPE_DEFAULT_ENTRY; 12 | spe_context_ptr_t my_context; 13 | 14 | // create the SPE Context 15 | my_context = spe_context_create(0, 0); 16 | 17 | // load the embedded code into this context 18 | spe_program_load(my_context, &gRenderJobSpuModule); 19 | 20 | // Run the SPE program until completion 21 | do { 22 | retval = spe_context_run(my_context, &entry_point, 0, param, NULL, NULL); 23 | } while (retval > 0); // Run until exit or error 24 | 25 | pthread_exit(NULL); 26 | } 27 | 28 | #endif -------------------------------------------------------------------------------- /projects/nanoray/textures.cpp: -------------------------------------------------------------------------------- 1 | #include "textures.h" 2 | 3 | -------------------------------------------------------------------------------- /projects/nanoray/textures.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core/core.h" 4 | #include "core/maths.h" 5 | #include "core/perlin.h" 6 | 7 | class Texture 8 | { 9 | public: 10 | 11 | virtual ~Texture() {} 12 | virtual Colour Evaluate(const Point3& p) const = 0; 13 | 14 | }; 15 | 16 | class ConstantTexture : public Texture 17 | { 18 | public: 19 | 20 | ConstantTexture(const Colour& c) : m_colour(c) {} 21 | 22 | virtual Colour Evaluate(const Point3& p) const 23 | { 24 | return m_colour; 25 | } 26 | 27 | Colour m_colour; 28 | }; 29 | 30 | class MixTexture : public Texture 31 | { 32 | public: 33 | 34 | MixTexture(const Texture* tex1, const Texture* tex2, const Texture* mixTex) : m_tex1(tex1), m_tex2(tex2), m_mixTex(mixTex) {} 35 | 36 | virtual Colour Evaluate(const Point3& p) const 37 | { 38 | return Lerp(m_tex1->Evaluate(p), m_tex2->Evaluate(p), Clamp(Abs(m_mixTex->Evaluate(p).r), 0.0f, 1.0f)); 39 | } 40 | 41 | const Texture* m_tex1; 42 | const Texture* m_tex2; 43 | const Texture* m_mixTex; 44 | }; 45 | 46 | class PerlinTexture : public Texture 47 | { 48 | public: 49 | 50 | PerlinTexture(float frequency, float persistance=1.0f, uint32_t octaves=1) : m_frequency(frequency), 51 | m_persistance(persistance), 52 | m_octaves(octaves) 53 | { 54 | } 55 | 56 | virtual Colour Evaluate(const Point3& p) const 57 | { 58 | float n = 0.5f + 0.5f*(Perlin3D(p.x*m_frequency, p.y*m_frequency, p.z*m_frequency, m_octaves, m_persistance)); 59 | 60 | return Colour(n, n, n); 61 | } 62 | 63 | float m_frequency; 64 | float m_persistance; 65 | uint32_t m_octaves; 66 | 67 | }; 68 | 69 | class CheckerboardTexture : public Texture 70 | { 71 | public: 72 | 73 | CheckerboardTexture(float size, const Colour& c1, const Colour& c2) : m_invSize(1.0f/size), m_colour1(c1), m_colour2(c2) 74 | { 75 | } 76 | 77 | Colour Evaluate(const Point3& p) const 78 | { 79 | int x = (int)floorf(p.x*m_invSize); 80 | int y = (int)floorf(p.y*m_invSize); 81 | int z = (int)floorf(p.z*m_invSize); 82 | 83 | if ((x+y+z)&0x1) 84 | { 85 | return m_colour1; 86 | } 87 | else 88 | { 89 | return m_colour2; 90 | } 91 | } 92 | 93 | Colour m_colour1; 94 | Colour m_colour2; 95 | float m_invSize; 96 | }; 97 | -------------------------------------------------------------------------------- /projects/nanoray/todo.txt: -------------------------------------------------------------------------------- 1 | Add image reconstruction filter 2 | Add light source sampling 3 | Add material types 4 | Add volume types 5 | Add exposure control 6 | 7 | ***Add disc primitive with uniform sampling 8 | 9 | -------------------------------------------------------------------------------- /projects/pbd/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -m32 -Wall -I"../.." -O3 -ffast-math 5 | LDFLAGS = -g -m32 -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = pbd 8 | 9 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../core/maths.cpp ../../core/mesh.cpp ../../core/aabbtree.cpp ../../core/tga.cpp ../../core/pfm.cpp 10 | HEADERS = $(wildcard *.h) 11 | 12 | OBJECTS = $(SOURCES:.cpp=.o) 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) makefile 17 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 18 | 19 | clean: 20 | -rm -f $(OBJECTS) 21 | -rm -f $(TARGET) 22 | 23 | %.o: %.cpp $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o $@ $< 25 | 26 | 27 | run: $(TARGET) 28 | ./$(TARGET) 29 | 30 | .PHONY : all clean 31 | -------------------------------------------------------------------------------- /projects/pbd/pbd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/pbd/pbd.pdf -------------------------------------------------------------------------------- /projects/pbd/pbd.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Upsample", "Upsample.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/quadric/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -m32 -Wall -I"../.." -O3 -ffast-math 5 | LDFLAGS = -g -m32 -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = quadric 8 | 9 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../core/maths.cpp ../../core/mesh.cpp ../../core/aabbtree.cpp ../../core/tga.cpp ../../core/pfm.cpp 10 | HEADERS = $(wildcard *.h) 11 | 12 | OBJECTS = $(SOURCES:.cpp=.o) 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) makefile 17 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 18 | 19 | clean: 20 | -rm -f $(OBJECTS) 21 | -rm -f $(TARGET) 22 | 23 | %.o: %.cpp $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o $@ $< 25 | 26 | 27 | run: $(TARGET) 28 | ./$(TARGET) 29 | 30 | .PHONY : all clean 31 | -------------------------------------------------------------------------------- /projects/quadric/quadric: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/quadric/quadric -------------------------------------------------------------------------------- /projects/quadric/quadric.bib: -------------------------------------------------------------------------------- 1 | @inproceedings{Sigg:2006:GRQ:2386388.2386396, 2 | author = {Sigg, Christian and Weyrich, Tim and Botsch, Mario and Gross, Markus}, 3 | title = {GPU-based ray-casting of quadratic surfaces}, 4 | booktitle = {Proceedings of the 3rd Eurographics / IEEE VGTC conference on Point-Based Graphics}, 5 | series = {SPBG'06}, 6 | year = {2006}, 7 | isbn = {3-905673-32-0}, 8 | location = {Boston, Massachusetts}, 9 | pages = {59--65}, 10 | numpages = {7}, 11 | url = {http://dx.doi.org/10.2312/SPBG/SPBG06/059-065}, 12 | doi = {10.2312/SPBG/SPBG06/059-065}, 13 | acmid = {2386396}, 14 | publisher = {Eurographics Association}, 15 | address = {Aire-la-Ville, Switzerland, Switzerland}, 16 | } 17 | -------------------------------------------------------------------------------- /projects/quadric/quadric.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/quadric/quadric.pdf -------------------------------------------------------------------------------- /projects/quadric/quadric.tex: -------------------------------------------------------------------------------- 1 | \documentclass[11pt]{article} 2 | \usepackage{mathptmx} 3 | \usepackage[small,compact]{titlesec} 4 | \usepackage{geometry} % See geometry.pdf to learn the layout options. There are lots. 5 | \usepackage{url} 6 | \usepackage{hyperref} 7 | \usepackage{breakurl} 8 | \geometry{letterpaper} % ... or a4paper or a5paper or ... 9 | %\geometry{landscape} % Activate for for rotated page geometry 10 | \usepackage[parfill]{parskip} % Activate to begin paragraphs with an empty line rather than an indent 11 | \usepackage{graphicx} 12 | \usepackage{amssymb, amsmath} 13 | \usepackage{epstopdf} 14 | 15 | \DeclareGraphicsRule{.tif}{png}{.png}{`convert #1 `dirname #1`/`basename #1 .tif`.png} 16 | 17 | \title{Raytracing Quadrics} 18 | \author{Miles Macklin} 19 | %\date{} % Activate to display a given date or no date 20 | 21 | \renewcommand{\v}[1]{\ensuremath{\mathbf{#1}}} % for vectors 22 | \newcommand{\uv}[1]{\ensuremath{\mathbf{\hat{#1}}}} % for unit vectors 23 | \newcommand\ddx[1]{\frac{\partial#1}{\partial \v{x} }} 24 | \newcommand\dd[2]{\frac{\partial#1}{\partial #2}} 25 | 26 | 27 | \begin{document} 28 | \maketitle 29 | 30 | \section{Introduction} 31 | 32 | This short article shows how to define and manipulate quadric surface equations in matrix form and intersect rays against them for rendering. The treatment here is inspired by \cite{Sigg:2006:GRQ:2386388.2386396} and work by Simon Green at NVIDIA. 33 | 34 | 35 | \section{Quadrics} 36 | 37 | The quadratic equation in 3 variables can be written as: 38 | 39 | \begin{equation} 40 | f(x,y,z) = Ax^2 +2Bxy+2Cxz+2Dx+Ey^2+2Fyz+Gy+Hz^2 +2Iz+J = 0 41 | \end{equation} 42 | 43 | It can also be written in matrix form using homogenous coordinates: 44 | 45 | \begin{equation} 46 | \v{x}^T\v{Q}\v{x} = 0 47 | \end{equation} 48 | 49 | where $\v{Q}$ is the matrix of coefficients: 50 | 51 | \begin{equation} 52 | \v{Q} = 53 | \begin{bmatrix} 54 | A & B & C & D \\ 55 | B & E & F & G \\ 56 | C & F & H & I \\ 57 | D & G & I & J 58 | \end{bmatrix} 59 | \qquad 60 | \v{x} = 61 | \begin{bmatrix} 62 | x \\ y \\ z \\ 1 63 | \end{bmatrix} 64 | \end{equation} 65 | 66 | Because this matrix is symmetric it can be diagonalised by a matrix $\v{T}$. With appropriate scaling, our matrix $\v{Q}$ can be expressed as a diagonal matrix $\v{D}$ with entries $\pm 1$ or $0$: 67 | 68 | \begin{equation} 69 | \v{Q}= \v{T}^{-T}\v{D}\v{T}^{-1} 70 | \end{equation} 71 | 72 | We refer to the basis that diagonalises $\v{Q}$ as the parameter space. 73 | 74 | $\v{Q}$ can may be transformed to a different basis by any affine transformation $\v{M}$ by multiplying by $\v{M}^{-1}$ on both sides. This is equivalent to moving a point $\v{x}'$ back to the basis for $\v{Q}$, 75 | 76 | \begin{equation} 77 | \v{Q'} = \v{M}^{-T}\v{Q}\v{M}^{-1}. 78 | \end{equation} 79 | % 80 | \begin{equation} 81 | \v{x}' = \v{M}\v{x} 82 | \end{equation} 83 | % 84 | \begin{equation} 85 | \v{x'}^T\v{Q'}\v{x'} = \v{x'}^T\v{M}^{-T}\v{Q}\v{M}^{-1}\v{x'} = \v{x}^T\v{Q}\v{x} 86 | \end{equation} 87 | 88 | As we will soon see, view (or eye) space is a convenient space for ray-tracing. To transform our quadric equation to view space we multiply by the inverse model view matrix $\v{MV}$: 89 | 90 | \begin{equation} 91 | \v{Q'} = \v{MV}^{-T}\v{Q}\v{MV}^{-1} = \v{MV}^{-T}\v{T}^{-T}\v{D}\v{T}^{-1}\v{MV}^{-1} = (\v{MV}\cdot\v{T})^{-T}\v{D}(\v{MV}\cdot\v{T})^{-1} 92 | \end{equation} 93 | 94 | To ray trace the quadric we parameterise the view ray in the usual way, 95 | 96 | \begin{equation} 97 | \v{x}_v = \v{o} + t\v{d}, 98 | \end{equation} 99 | 100 | and transform this back to parameter space: 101 | 102 | \begin{equation} 103 | \v{x}_p = (\v{MV}\cdot\v{T})^{-1}\v{o} + t(\v{MV}\cdot\v{T})^{-1}\v{d} = \v{o}_p + t\v{d}_p 104 | \end{equation} 105 | 106 | Inserting this into our quadratic equation, 107 | 108 | \begin{equation} 109 | \v{x}^T_p\v{Q}\v{x}_p = (\v{o}_p + t\v{d}_p)^T\v{D}(\v{o}_p + t\v{d}_p) = 0, 110 | \end{equation} 111 | 112 | and expanding and gathering for $t$, we have: 113 | 114 | \begin{equation} 115 | t^2(\v{d}^T_p\v{D}\v{d}_p) + 2t(\v{o}^T_p\v{D}\v{d}_p) + \v{o}^T_p\v{D}\v{o}_p = 0 116 | \end{equation} 117 | 118 | which we can solve with the quadratic formula. 119 | 120 | The advantage of defining our rays in view space is that the ray origin, or eye position $\v{o}$ is simply the homogenous zero vector: 121 | 122 | \begin{equation} 123 | \v{o} = 124 | \begin{bmatrix} 125 | 0 \\ 126 | 0 \\ 127 | 0 \\ 128 | 1 129 | \end{bmatrix} 130 | \end{equation} 131 | 132 | Which simply extracts the last column of ($\v{MV}\cdot\v{T})^{-1}$ when we form $\v{o}_p$: 133 | 134 | \begin{equation} 135 | \v{o}_p = \v{c}_4 136 | \end{equation} 137 | 138 | 139 | \bibliographystyle{alpha} 140 | \bibliography{quadric} 141 | 142 | 143 | \end{document} 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /projects/sh/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -Wall -I"../.." -D_DEBUG 5 | LDFLAGS = -g -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = SHTest 8 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/maths.cpp ../../core/pfm.cpp ../../core/mesh.cpp ../../core/shader.cpp 9 | HEADERS = $(wildcard *.h) 10 | 11 | OBJECTS = $(SOURCES:.cpp=.o) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET): $(OBJECTS) Makefile 16 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 17 | 18 | clean: 19 | -rm -f $(OBJECTS) 20 | -rm -f $(TARGET) 21 | 22 | %.o: %.cpp $(HEADERS) 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | 25 | run: $(TARGET) 26 | ./$(TARGET) 27 | 28 | .PHONY : all clean 29 | -------------------------------------------------------------------------------- /projects/sh/sh.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/sh/sh.cpp -------------------------------------------------------------------------------- /projects/sh/sh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // The spherical harmonic basis functions are formed through the combination 6 | // of the Legrende polynomials (parameterized by cos(theta)) and the Fourier basis functions (based on sine and cosine). 7 | 8 | int factorial(int x) 9 | { 10 | int f = 1; 11 | 12 | while (x > 0) 13 | { 14 | f *= x; 15 | x -= 1; 16 | } 17 | 18 | return f; 19 | } 20 | 21 | int doubleFactorial(int x) 22 | { 23 | int f = 1; 24 | 25 | while (x > 0) 26 | { 27 | f *= x; 28 | x -= 2; 29 | } 30 | 31 | return f; 32 | } 33 | 34 | int pow(int x, int e) 35 | { 36 | int a = 1; 37 | 38 | for (int i=0; i < e; ++i) 39 | a *= x; 40 | 41 | return a; 42 | } 43 | 44 | 45 | double shK(int l, int m) 46 | { 47 | assert(l >= 0); 48 | assert(m >= 0); 49 | 50 | return sqrt((2.0*l+1.0)*factorial(l-m)/(4.0*kPi*factorial(l+m))); 51 | } 52 | 53 | double shL(int l, int m, double x) 54 | { 55 | assert(x >= -1.0 && x <= 1.0); 56 | assert(m >= 0 && m <= l); 57 | assert(l >= 0); 58 | 59 | if (m == l) 60 | { 61 | return pow(-1, m)*doubleFactorial(2*m-1)*pow(1.0-x*x, m*0.5); 62 | } 63 | else if (m == l-1) 64 | { 65 | return x*(2*m+1)*shL(m, m, x); 66 | } 67 | else 68 | { 69 | return 1.0/(l-m)*(x*(2*l-1)*shL(l-1, m, x)-(l+m-1)*shL(l-2, m, x)); 70 | } 71 | } 72 | 73 | double shY(int l, int m, double theta, double phi) 74 | { 75 | assert(l >= 0); 76 | assert(m <= l && m >= -l); 77 | 78 | if (m > 0) 79 | { 80 | return sqrt(2.0)*shK(l, m)*cos(m*phi)*shL(l, m, cos(theta)); 81 | } 82 | else if (m < 0) 83 | { 84 | return sqrt(2.0)*shK(l, -m)*sin(-m*phi)*shL(l, -m, cos(theta)); 85 | } 86 | else 87 | { 88 | return shK(l, 0)*shL(l, 0, cos(theta)); 89 | } 90 | } 91 | 92 | template 93 | double shY(double theta, double phi) { return shY(l, m, theta, phi); } 94 | 95 | // numerically integrate a 1 variable function over a range 96 | template 97 | double integrate1(func f, double xstart, double xend, int steps=8192) 98 | { 99 | double dx = (xend-xstart)/steps; 100 | double x = xstart; 101 | double r = 0.0; 102 | 103 | for (int i=0; i < steps; ++i) 104 | { 105 | r += f(x)*dx; 106 | x += dx; 107 | } 108 | 109 | return r; 110 | } 111 | 112 | // numerically integrate a 2 variable function over a range 113 | template 114 | double integrate2(func f, double xstart, double xend, double ystart, double yend, int steps=8192) 115 | { 116 | const double dx = (xend-xstart)/steps; 117 | const double dy = (yend-ystart)/steps; 118 | 119 | double y = ystart; 120 | double a = 0.0; 121 | 122 | for (int i=0; i < steps; ++i) 123 | { 124 | double x = xstart; 125 | 126 | for (int j=0; j < steps; ++j) 127 | { 128 | a += f(x, y)*dx*dy; 129 | x += dx; 130 | } 131 | 132 | y += dy; 133 | } 134 | 135 | return a; 136 | } 137 | 138 | int shIndex(int l, int m) 139 | { 140 | return (l*l)+m+l; 141 | } 142 | 143 | template 144 | void shProject(const Func& f, int lmax, Value* coefficients) 145 | { 146 | const int kSteps = 1024; 147 | 148 | const double dTheta = kPi/kSteps; 149 | const double dPhi = 2.0*kPi/(kSteps*2); 150 | 151 | for (int l=0; l < lmax; ++l) 152 | { 153 | for (int m=-l; m <=l; ++m) 154 | { 155 | int c = shIndex(l, m); 156 | 157 | double theta = 0.0; 158 | 159 | for (int i=0; i < kSteps; ++i) 160 | { 161 | double phi = 0.0; 162 | 163 | for (int j=0; j < kSteps*2; ++j) 164 | { 165 | coefficients[c] += f(theta, phi)*float(shY(l, m, theta, phi)*sin(theta)*dTheta*dPhi); 166 | phi += dPhi; 167 | } 168 | 169 | theta += dTheta; 170 | } 171 | } 172 | } 173 | } 174 | 175 | template 176 | void shReduceRinging(Value coefficient[], int lmax, double lambda) 177 | { 178 | for (int l=0; l < lmax; ++l) 179 | { 180 | for (int m=-l; m <= l; ++m) 181 | { 182 | coefficient[shIndex(l, m)] *= 1.0 / (1.0 + lambda*l*l*(l+1.0)*(l+1.0)); 183 | } 184 | } 185 | } 186 | 187 | template 188 | Value shExpand(Value coefficients[], int lmax, double theta, double phi) 189 | { 190 | Value x = Value(); 191 | 192 | for (int l=0; l < lmax; ++l) 193 | { 194 | for (int m=-l; m <= l; ++m) 195 | { 196 | x += shY(l, m, theta, phi)*coefficients[shIndex(l, m)]; 197 | } 198 | } 199 | 200 | return x; 201 | } 202 | 203 | template 204 | void shConvolve(Value out[], const Value f[], const double h[], int lmax) 205 | { 206 | for (int l=0; l < lmax; ++l) 207 | { 208 | double k = sqrt(4.0*kPi/(2.0*l+1.0)); 209 | 210 | for (int m=-l; m <= l; ++m) 211 | { 212 | out[shIndex(l, m)] = k*f[shIndex(l, m)]*h[shIndex(l, 0)]; 213 | } 214 | } 215 | } 216 | 217 | -------------------------------------------------------------------------------- /projects/sh/sh.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SH", "SH.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/sh/sh.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Surfel 17 | SH 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | true 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 54 | ../.. 55 | MultiThreadedDebug 56 | 57 | 58 | Console 59 | true 60 | ../../Core/Debug;../../External/glut;../../External/glew/lib 61 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | ../.. 74 | MultiThreaded 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | ../../Core/Release;../../External/glut;../../External/glew/lib 82 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /projects/smoke/blackbody.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // takes a temperature T in Kelvins and returns the XYZ color 4 | void BlackBodyXYZ(float T, float* xyz); -------------------------------------------------------------------------------- /projects/smoke/fluid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/smoke/fluid -------------------------------------------------------------------------------- /projects/smoke/fluid.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Fluid", "Fluid.vcxproj", "{406ED26A-C476-4FBB-B817-8A533A24C01A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 16 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 18 | {406ED26A-C476-4FBB-B817-8A533A24C01A}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {406ED26A-C476-4FBB-B817-8A533A24C01A}.Debug|Win32.Build.0 = Debug|Win32 20 | {406ED26A-C476-4FBB-B817-8A533A24C01A}.Release|Win32.ActiveCfg = Release|Win32 21 | {406ED26A-C476-4FBB-B817-8A533A24C01A}.Release|Win32.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /projects/smoke/fluid.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | 37 | 38 | Header Files 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | -------------------------------------------------------------------------------- /projects/smoke/raymarchshadowps.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | uniform sampler3D g_densityTexture; 4 | uniform vec3 g_lightPos; 5 | uniform vec3 g_lightIntensity; 6 | uniform vec3 g_absorption; 7 | uniform vec3 g_scatter; 8 | 9 | void main() 10 | { 11 | const int numLightSamples = 256; 12 | const float lscale = 8.0 / float(numLightSamples); 13 | 14 | vec3 pos = gl_TexCoord[0].xyz; 15 | vec3 eyePos = gl_ModelViewMatrixInverse[3].xyz; 16 | 17 | // attenuation 18 | float falloff = 1.0 / dot(pos-g_lightPos, pos-g_lightPos); 19 | 20 | // convert to texture space 21 | pos = pos*0.5 + vec3(0.5, 0.5, 0.5); 22 | vec3 lightPos = g_lightPos*0.5 +vec3(0.5, 0.5, 0.5); 23 | 24 | // convert to texture space (cube dimensions are -1, 1 in world space) 25 | vec3 transmittance = vec3(1.0, 1.0, 1.0); 26 | vec3 Lo = vec3(0.0, 0.0, 0.0); 27 | 28 | vec3 lightDir = normalize(lightPos - pos)*lscale*0.5; 29 | 30 | // sample light 31 | vec3 ltransmittance = vec3(1.0, 1.0, 1.0); 32 | vec3 lpos = pos + lightDir; 33 | 34 | for (int s=0; s < numLightSamples; ++s) 35 | { 36 | ltransmittance *= 1.0-g_scatter*lscale*texture3D(g_densityTexture, lpos).x; 37 | 38 | if (ltransmittance.x <= 0.01) 39 | break; 40 | 41 | lpos += lightDir; 42 | } 43 | 44 | vec3 Li = ltransmittance; 45 | Lo += Li*vec3(0.52f, 0.46f, 0.4f) + vec3(0.05, 0.05, 0.05); 46 | 47 | 48 | gl_FragColor.xyz = Lo*falloff*g_lightIntensity; 49 | gl_FragColor.w = 0.0f;//max(0.0, 1.0-dot(transmittance, vec3(0.33, 0.33, 0.33))); 50 | } -------------------------------------------------------------------------------- /projects/smoke/raymarchvolumeps.glsl_opt: -------------------------------------------------------------------------------- 1 | uniform float g_scatter; 2 | uniform float g_absorption; 3 | uniform float g_lightIntensity; 4 | uniform vec3 g_lightPos; 5 | uniform sampler3D g_noiseTexture; 6 | void main () 7 | { 8 | int i; 9 | vec3 Lo; 10 | vec3 transmittance; 11 | vec3 lightPos; 12 | vec3 eyeDir; 13 | vec3 pos; 14 | vec3 kScatter; 15 | vec3 kAbsorption; 16 | kAbsorption = (vec3(8.0, 8.0, 7.6) * g_absorption); 17 | kScatter = (vec3(2.4, 2.7, 3.0) * g_scatter); 18 | vec3 tmpvar_1; 19 | tmpvar_1 = gl_TexCoord[0].xyz; 20 | pos = ((tmpvar_1 * 0.5) + vec3(0.5, 0.5, 0.5)); 21 | eyeDir = (0.0104167 * normalize ((tmpvar_1 - gl_ModelViewMatrixInverse[3].xyz))); 22 | lightPos = ((g_lightPos * 0.5) + vec3(0.5, 0.5, 0.5)); 23 | transmittance = vec3(1.0, 1.0, 1.0); 24 | Lo = vec3(0.0, 0.0, 0.0); 25 | i = 0; 26 | for (int i = 0; i < 96; ) { 27 | vec3 lightDir; 28 | vec3 tmpvar_2; 29 | tmpvar_2 = (0.03125 * normalize ((lightPos - pos))); 30 | lightDir = tmpvar_2; 31 | float tmpvar_3; 32 | tmpvar_3 = texture3D (g_noiseTexture, pos).x; 33 | if ((tmpvar_3 > 0.0)) { 34 | int s; 35 | vec3 lpos; 36 | vec3 ltransmittance; 37 | ltransmittance = vec3(1.0, 1.0, 1.0); 38 | lpos = (pos + tmpvar_2); 39 | s = 0; 40 | while (true) { 41 | if ((s >= 16)) { 42 | break; 43 | }; 44 | vec3 tmpvar_4; 45 | tmpvar_4 = (ltransmittance * (1.0 - ((kScatter * 0.0625) * texture3D (g_noiseTexture, lpos).x))); 46 | ltransmittance = tmpvar_4; 47 | if ((tmpvar_4.x <= 0.01)) { 48 | break; 49 | }; 50 | lpos = (lpos + lightDir); 51 | s = (s + 1); 52 | }; 53 | Lo = (Lo + (((ltransmittance * tmpvar_3) * transmittance) * 0.0208333)); 54 | vec3 tmpvar_5; 55 | tmpvar_5 = (transmittance * (1.0 - ((tmpvar_3 * 0.0208333) * kAbsorption))); 56 | transmittance = tmpvar_5; 57 | if ((tmpvar_5.x <= 0.01)) { 58 | break; 59 | }; 60 | }; 61 | pos = (pos + eyeDir); 62 | i = (i + 1); 63 | }; 64 | gl_FragColor.xyz = ((Lo * vec3(8.0, 8.0, 8.0)) * g_lightIntensity); 65 | gl_FragColor.w = max (0.0, (1.0 - dot (transmittance, vec3(0.33, 0.33, 0.33)))); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /projects/smoke/raymarchvolumevs.glsl: -------------------------------------------------------------------------------- 1 | 2 | void main() 3 | { 4 | 5 | gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; 6 | gl_TexCoord[0] = gl_Vertex; 7 | gl_TexCoord[1].xyz = gl_Normal.xyz; 8 | gl_TexCoord[2].xy = gl_MultiTexCoord0.xy; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /projects/smoke/vencode.bat: -------------------------------------------------------------------------------- 1 | ffmpeg -r 60 -f image2 -i "./dump/frame%%d.tga" -threads 4 -vcodec libx264 -preset fast -crf 20 %1 -------------------------------------------------------------------------------- /projects/smoke/vencode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ffmpeg -r 60 -f image2 -i ./dump/frame%d.tga -threads 0 -vcodec libx264 -vpre slow -crf 20 $1 3 | -------------------------------------------------------------------------------- /projects/springs/cg.h: -------------------------------------------------------------------------------- 1 | #include "core/types.h" 2 | #include "core/maths.h" 3 | #include "core/mat22.h" 4 | 5 | #include 6 | 7 | 8 | typedef std::vector NodeRow; 9 | 10 | std::vector CgMul(const std::vector& A, const std::vector& x) 11 | { 12 | assert(A[0].size() == x.size()); 13 | 14 | std::vector b(A.size()); 15 | 16 | for (size_t i=0; i < A.size(); ++i) 17 | { 18 | for (size_t j=0; j < x.size(); ++j) 19 | { 20 | b[i] += A[i][j]*x[j]; 21 | } 22 | } 23 | 24 | return b; 25 | } 26 | 27 | std::vector CgMul(float c, const std::vector& x) 28 | { 29 | std::vector r(x.size()); 30 | 31 | for (size_t i=0; i < r.size(); ++i) 32 | r[i] = c*x[i]; 33 | 34 | return r; 35 | } 36 | 37 | std::vector CgAdd(const std::vector& a, const std::vector& b) 38 | { 39 | assert(a.size() == b.size()); 40 | 41 | std::vector c(a.size()); 42 | 43 | for (size_t i=0; i < a.size(); ++i) 44 | c[i] = a[i] + b[i]; 45 | 46 | return c; 47 | } 48 | 49 | std::vector CgSub(const std::vector& a, const std::vector& b) 50 | { 51 | assert(a.size() == b.size()); 52 | 53 | std::vector c(a.size()); 54 | 55 | for (size_t i=0; i < a.size(); ++i) 56 | c[i] = a[i] - b[i]; 57 | 58 | return c; 59 | } 60 | 61 | float CgDot(const std::vector& a, const std::vector& b) 62 | { 63 | assert(a.size() == b.size()); 64 | 65 | float d = 0.0f; 66 | 67 | for (size_t i=0; i < a.size(); ++i) 68 | { 69 | d += Dot(a[i], b[i]); 70 | } 71 | 72 | return d; 73 | } 74 | 75 | void CgDebug(const Matrix22& m) 76 | { 77 | printf("{ %f, %f }\n", m(0, 0), m(0, 1)); 78 | printf("{ %f, %f }\n", m(1, 0), m(1, 1)); 79 | } 80 | 81 | void CgDebug(const char* s, const std::vector& x) 82 | { 83 | for (size_t i=0; i < x.size(); ++i) 84 | printf("%s[%u] = {%f, %f}\n", s, uint32_t(i), x[i].x, x[i].y); 85 | } 86 | 87 | void CgDebug(const char* s, const std::vector& A) 88 | { 89 | for (size_t i=0; i < A.size(); ++i) 90 | { 91 | 92 | for (int r=0; r < 2; ++r) 93 | { 94 | for (size_t j=0; j < A[i].size(); ++j) 95 | { 96 | printf("%f, %f, ", A[i][j](r,0), A[i][j](r, 1)); 97 | } 98 | printf("\n"); 99 | } 100 | } 101 | } 102 | 103 | 104 | // returns x 105 | std::vector CgSolve(const std::vector& A, const std::vector& b, uint32_t imax, float e) 106 | { 107 | assert(A.size() == A[0].size()); 108 | 109 | uint32_t i=0; 110 | std::vector x(A[0].size()); 111 | std::vector r = CgSub(b, CgMul(A, x)); 112 | std::vector d = r; 113 | 114 | float sigmaNew = CgDot(r, r); 115 | const float sigma0 = sigmaNew; 116 | 117 | assert(A.size() == A[0].size()); 118 | assert(x.size() == A.size()); 119 | assert(r.size() == A.size()); 120 | assert(d.size() == A.size()); 121 | 122 | //CgDebug("b", b); 123 | std::vector q; 124 | 125 | while (i < imax && sigmaNew > e*e*sigma0) 126 | { 127 | q = CgMul(A, d); 128 | 129 | // CgDebug("q", q); 130 | 131 | float a = sigmaNew / CgDot(d, q); 132 | x = CgAdd(x, CgMul(a,d)); 133 | 134 | // could reseed residual here to account for numerical inaccuracy 135 | r = CgSub(r, CgMul(a, q)); 136 | 137 | float sigmaOld = sigmaNew; 138 | if (sigmaOld <= e) 139 | return x; 140 | sigmaNew = CgDot(r, r); 141 | 142 | //printf("%d %f\n", i, sigmaNew); 143 | 144 | float beta = sigmaNew / sigmaOld; 145 | 146 | d = CgAdd(r, CgMul(beta, d)); 147 | 148 | ++i; 149 | } 150 | 151 | return x; 152 | } 153 | 154 | 155 | -------------------------------------------------------------------------------- /projects/springs/implicitsprings.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmacklin/sandbox/f73d2902bfce3972b889c71f076c724063c180dd/projects/springs/implicitsprings.pdf -------------------------------------------------------------------------------- /projects/springs/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -m32 -Wall -I"../.." -D_DEBUG 5 | LDFLAGS = -g -m32 -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = Springs 8 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp 9 | HEADERS = $(wildcard *.h) 10 | 11 | OBJECTS = $(SOURCES:.cpp=.o) 12 | 13 | all: $(TARGET) 14 | 15 | $(TARGET): $(OBJECTS) Makefile 16 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 17 | 18 | clean: 19 | -rm -f $(OBJECTS) 20 | -rm -f $(TARGET) 21 | 22 | %.o: %.cpp $(HEADERS) 23 | $(CC) $(CFLAGS) -c -o $@ $< 24 | 25 | run: $(TARGET) 26 | ./$(TARGET) 27 | 28 | .PHONY : all clean 29 | -------------------------------------------------------------------------------- /projects/springs/springs.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Springs", "Springs.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/springs/springs.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Surfel 17 | Springs 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 54 | ../.. 55 | MultiThreadedDebug 56 | 57 | 58 | Console 59 | true 60 | ../../Core/Debug;../../External/glut;../../External/glew/lib 61 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | ../.. 74 | MultiThreaded 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | Core.lib;glew32.lib;glut32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | ../../Core/Release;../../External/glut;../../External/glew/lib 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /projects/surfel/surfel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Surfel", "Surfel.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 7 | EndProjectSection 8 | EndProject 9 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\Core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 19 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 20 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 21 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 23 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 24 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/surfel/surfel.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Surfel 17 | 18 | 19 | 20 | Application 21 | true 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | true 28 | MultiByte 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | true 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | Level3 51 | Disabled 52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 53 | ../.. 54 | 55 | 56 | Console 57 | true 58 | ../../Core/Debug;../../External/freeglut-2.6.0/lib;../../External/glew/lib 59 | Core.lib;glew32.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 71 | ../.. 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | ../../Core/Release;../../External/freeglut-2.6.0/lib;../../External/glew/lib 79 | Core.lib;glew32.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /projects/voxelize/makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | CC = g++ 3 | 4 | CFLAGS = -g -m32 -Wall -I"../.." -O3 -ffast-math 5 | LDFLAGS = -g -m32 -framework GLUT -framework OpenGL -framework Cocoa 6 | 7 | TARGET = quadric 8 | 9 | SOURCES = $(wildcard *.cpp) ../../core/platform.cpp ../../core/shader.cpp ../../core/maths.cpp ../../core/mesh.cpp ../../core/aabbtree.cpp ../../core/tga.cpp ../../core/pfm.cpp 10 | HEADERS = $(wildcard *.h) 11 | 12 | OBJECTS = $(SOURCES:.cpp=.o) 13 | 14 | all: $(TARGET) 15 | 16 | $(TARGET): $(OBJECTS) makefile 17 | $(CC) $(LDFLAGS) $(OBJECTS) -o $(TARGET) 18 | 19 | clean: 20 | -rm -f $(OBJECTS) 21 | -rm -f $(TARGET) 22 | 23 | %.o: %.cpp $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o $@ $< 25 | 26 | 27 | run: $(TARGET) 28 | ./$(TARGET) 29 | 30 | .PHONY : all clean 31 | -------------------------------------------------------------------------------- /projects/voxelize/voxelize.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "..\..\core\Core.vcxproj", "{81732CB7-6059-4E5C-8B57-5576137CE73D}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Voxelize", "voxelize.vcxproj", "{A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {81732CB7-6059-4E5C-8B57-5576137CE73D} = {81732CB7-6059-4E5C-8B57-5576137CE73D} 9 | EndProjectSection 10 | EndProject 11 | Global 12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 | Debug|Win32 = Debug|Win32 14 | Release|Win32 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.ActiveCfg = Debug|Win32 18 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Debug|Win32.Build.0 = Debug|Win32 19 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.ActiveCfg = Release|Win32 20 | {81732CB7-6059-4E5C-8B57-5576137CE73D}.Release|Win32.Build.0 = Release|Win32 21 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Debug|Win32.Build.0 = Debug|Win32 23 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.ActiveCfg = Release|Win32 24 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693}.Release|Win32.Build.0 = Release|Win32 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | EndGlobal 30 | -------------------------------------------------------------------------------- /projects/voxelize/voxelize.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A7D2A448-3C70-48E6-84F5-B1CDDEDD5693} 15 | Win32Proj 16 | Voxelize 17 | Voxelize 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | 25 | 26 | Application 27 | false 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | Level3 52 | Disabled 53 | _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 54 | ../.. 55 | MultiThreadedDebug 56 | 57 | 58 | Console 59 | true 60 | ../../Core/Debug;../../External/freeglut/lib;../../External/glew/lib 61 | Core.lib;glew32.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 62 | 63 | 64 | 65 | 66 | Level3 67 | 68 | 69 | MaxSpeed 70 | true 71 | true 72 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 73 | ../.. 74 | MultiThreaded 75 | 76 | 77 | Console 78 | true 79 | true 80 | true 81 | Core.lib;glew32.lib;freeglut.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | ../../Core/Release;../../External/freeglut/lib;../../External/glew/lib 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | --------------------------------------------------------------------------------