├── README.md ├── Source ├── Biconvex.h ├── Board.h ├── Collision.cpp ├── CollisionDetection.h ├── CollisionResponse.h ├── Common.h ├── Config.h ├── Dynamics.cpp ├── InertiaTensor.h ├── Intersection.h ├── Mesh.h ├── Platform.cpp ├── Platform.h ├── Render.h ├── RigidBody.h ├── Stone.h ├── Support.cpp ├── Tessellation.cpp ├── UnitTest.cpp ├── stb_image.c └── stb_image.h ├── UnitTest++ ├── AssertException.cpp ├── AssertException.h ├── CheckMacros.h ├── Checks.cpp ├── Checks.h ├── Config.h ├── CurrentTest.cpp ├── CurrentTest.h ├── DeferredTestReporter.cpp ├── DeferredTestReporter.h ├── DeferredTestResult.cpp ├── DeferredTestResult.h ├── ExecuteTest.h ├── MemoryOutStream.cpp ├── MemoryOutStream.h ├── Posix │ ├── SignalTranslator.cpp │ ├── SignalTranslator.h │ ├── TimeHelpers.cpp │ └── TimeHelpers.h ├── ReportAssert.cpp ├── ReportAssert.h ├── Test.cpp ├── Test.h ├── TestDetails.cpp ├── TestDetails.h ├── TestList.cpp ├── TestList.h ├── TestMacros.h ├── TestReporter.cpp ├── TestReporter.h ├── TestReporterStdout.cpp ├── TestReporterStdout.h ├── TestResults.cpp ├── TestResults.h ├── TestRunner.cpp ├── TestRunner.h ├── TestSuite.h ├── TimeConstraint.cpp ├── TimeConstraint.h ├── TimeHelpers.h ├── UnitTest++.h ├── Win32 │ ├── TimeHelpers.cpp │ └── TimeHelpers.h ├── XmlTestReporter.cpp └── XmlTestReporter.h ├── premake4.lua ├── vectorial ├── config.h ├── mat4f.h ├── simd4f.h ├── simd4f_common.h ├── simd4f_gnu.h ├── simd4f_neon.h ├── simd4f_scalar.h ├── simd4f_sse.h ├── simd4x4f.h ├── simd4x4f_gnu.h ├── simd4x4f_neon.h ├── simd4x4f_scalar.h ├── simd4x4f_sse.h ├── vec2f.h ├── vec3f.h └── vec4f.h └── xcode ├── Default-Landscape@2x~ipad.png ├── Default-Landscape~ipad.png ├── Default-Portrait@2x~ipad.png ├── Default-Portrait~ipad.png ├── Virtual Go.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── gaffer.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── gaffer.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ ├── Virtual Go.xcscheme │ └── xcschememanagement.plist ├── Virtual Go ├── AppDelegate.h ├── AppDelegate.m ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── Shaders │ ├── BoardShader.fragment │ ├── BoardShader.vertex │ ├── FloorShader.fragment │ ├── FloorShader.vertex │ ├── GridShader.fragment │ ├── GridShader.vertex │ ├── PointShader.fragment │ ├── PointShader.vertex │ ├── ShadowShader.fragment │ ├── ShadowShader.vertex │ ├── StoneShader.fragment │ └── StoneShader.vertex ├── ViewController.h ├── ViewController.m ├── Virtual Go-Info.plist ├── Virtual Go-Prefix.pch ├── en.lproj │ ├── InfoPlist.strings │ ├── MainStoryboard_iPad.storyboard │ └── MainStoryboard_iPhone.storyboard ├── main.m ├── testflight │ ├── README.md │ ├── TestFlight.h │ ├── libTestFlight.a │ └── release_notes.md └── textures │ ├── floor.jpg │ ├── line.jpg │ ├── point.jpg │ └── wood.jpg ├── virtual go ipad.png ├── virtual go retina ipad.png ├── virtual go retina.png └── virtual go.png /README.md: -------------------------------------------------------------------------------- 1 | virtualgo 2 | ========= 3 | 4 | A simulation of a go board and stones 5 | 6 | https://www.gdcvault.com/play/1017647/Physics-for-Game-Programmers-Virtual 7 | -------------------------------------------------------------------------------- /Source/Board.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARD_H 2 | #define BOARD_H 3 | 4 | /* 5 | Go board. 6 | 7 | We model the go board as an axis aligned rectangular prism. 8 | 9 | Since the floor is the plane z = 0, the top surface of the board 10 | is the plane z = thickness. 11 | 12 | Go board dimensions: 13 | 14 | Board width 424.2mm 15 | Board length 454.5mm 16 | Board thickness 151.5mm 17 | Line spacing width-wise 22mm 18 | Line spacing length-wise 23.7mm 19 | Line width 1mm 20 | Star point marker diameter 4mm 21 | Border 15mm 22 | 23 | https://en.wikipedia.org/wiki/Go_equipment#Board 24 | */ 25 | 26 | struct BoardParams 27 | { 28 | BoardParams() 29 | { 30 | cellWidth = 2.2f; 31 | cellHeight = 2.37f; 32 | border = 1.5f; 33 | thickness = 1.0f; 34 | lineWidth = 0.1; 35 | starPointRadius = 0.2f; 36 | } 37 | 38 | float cellWidth; 39 | float cellHeight; 40 | float border; 41 | float thickness; 42 | float lineWidth; 43 | float starPointRadius; 44 | }; 45 | 46 | class Board 47 | { 48 | public: 49 | 50 | Board() 51 | { 52 | size = 0; 53 | width = 0; 54 | height = 0; 55 | halfWidth = 0; 56 | halfHeight = 0; 57 | } 58 | 59 | void Initialize( int size, const BoardParams & params = BoardParams() ) 60 | { 61 | this->size = size; 62 | this->params = params; 63 | 64 | this->width = ( size - 1 ) * params.cellWidth + params.border * 2; 65 | this->height = ( size - 1 ) * params.cellHeight + params.border * 2; 66 | 67 | halfWidth = width / 2; 68 | halfHeight = height / 2; 69 | } 70 | 71 | int GetSize() const 72 | { 73 | return size; 74 | } 75 | 76 | float GetWidth() const 77 | { 78 | return width; 79 | } 80 | 81 | float GetHeight() const 82 | { 83 | return height; 84 | } 85 | 86 | void SetThickness( float thickness ) 87 | { 88 | this->params.thickness = thickness; 89 | } 90 | 91 | float GetThickness() const 92 | { 93 | return params.thickness; 94 | } 95 | 96 | float GetHalfWidth() const 97 | { 98 | return halfWidth; 99 | } 100 | 101 | float GetHalfHeight() const 102 | { 103 | return halfHeight; 104 | } 105 | 106 | float GetCellHeight() const 107 | { 108 | return params.cellHeight; 109 | } 110 | 111 | float GetCellWidth() const 112 | { 113 | return params.cellWidth; 114 | } 115 | 116 | void GetBounds( float & bx, float & by ) 117 | { 118 | bx = halfWidth; 119 | by = halfHeight; 120 | } 121 | 122 | vec3f GetPointPosition( int row, int column ) 123 | { 124 | assert( row >= 1 ); 125 | assert( column >= 1 ); 126 | assert( row <= size ); 127 | assert( column <= size ); 128 | 129 | const float w = params.cellWidth; 130 | const float h = params.cellHeight; 131 | const float z = params.thickness; 132 | 133 | const int n = ( GetSize() - 1 ) / 2; 134 | 135 | return vec3f( ( -n + column - 1 ) * w, ( -n + row - 1 ) * h, z ); 136 | } 137 | 138 | const BoardParams & GetParams() const 139 | { 140 | return params; 141 | } 142 | 143 | private: 144 | 145 | int size; 146 | 147 | BoardParams params; 148 | 149 | float width; // width of board (along x-axis) 150 | float height; // height of board (along y-axis) 151 | 152 | float halfWidth; 153 | float halfHeight; 154 | }; 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /Source/CollisionResponse.h: -------------------------------------------------------------------------------- 1 | #ifndef COLLISION_RESPONSE_H 2 | #define COLLISION_RESPONSE_H 3 | 4 | #include "RigidBody.h" 5 | #include "CollisionDetection.h" 6 | 7 | void ApplyLinearCollisionImpulse( StaticContact & contact, float e ) 8 | { 9 | vec3f velocityAtPoint; 10 | contact.rigidBody->GetVelocityAtWorldPoint( contact.point, velocityAtPoint ); 11 | const float k = contact.rigidBody->inverseMass; 12 | const float j = max( - ( 1 + e ) * dot( velocityAtPoint, contact.normal ) / k, 0 ); 13 | contact.rigidBody->linearMomentum += j * contact.normal; 14 | } 15 | 16 | void ApplyCollisionImpulseWithFriction( StaticContact & contact, float e, float u, float epsilon = 0.001f ) 17 | { 18 | RigidBody & rigidBody = *contact.rigidBody; 19 | 20 | vec3f velocityAtPoint; 21 | rigidBody.GetVelocityAtWorldPoint( contact.point, velocityAtPoint ); 22 | 23 | const float vn = min( 0, dot( velocityAtPoint, contact.normal ) ); 24 | 25 | const mat4f & i = rigidBody.inverseInertiaTensorWorld; 26 | 27 | // apply collision impulse 28 | 29 | const vec3f r = contact.point - rigidBody.position; 30 | 31 | const float k = rigidBody.inverseMass + 32 | dot( cross( r, contact.normal ), 33 | transformVector( i, cross( r, contact.normal ) ) ); 34 | 35 | const float j = - ( 1 + e ) * vn / k; 36 | 37 | rigidBody.linearMomentum += j * contact.normal; 38 | rigidBody.angularMomentum += j * cross( r, contact.normal ); 39 | 40 | // apply friction impulse 41 | 42 | rigidBody.GetVelocityAtWorldPoint( contact.point, velocityAtPoint ); 43 | 44 | vec3f tangentVelocity = velocityAtPoint - contact.normal * dot( velocityAtPoint, contact.normal ); 45 | 46 | if ( length_squared( tangentVelocity ) > epsilon * epsilon ) 47 | { 48 | vec3f tangent = normalize( tangentVelocity ); 49 | 50 | const float vt = dot( velocityAtPoint, tangent ); 51 | 52 | const float kt = rigidBody.inverseMass + 53 | dot( cross( r, tangent ), 54 | transformVector( i, cross( r, tangent ) ) ); 55 | 56 | const float jt = clamp( -vt / kt, -u * j, u * j ); 57 | 58 | rigidBody.linearMomentum += jt * tangent; 59 | rigidBody.angularMomentum += jt * cross( r, tangent ); 60 | } 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Source/Config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | #define LETTERBOX 5 | #define WIDESCREEN 6 | #define SHADOWS 7 | //#define MULTISAMPLING 8 | //#define MULTITHREADED 9 | #define THREAD_STACK_SIZE 8 * 1024 * 1024 10 | 11 | //#define USE_SECONDARY_DISPLAY_IF_EXISTS 12 | //#define DEBUG_SHADOW_VOLUMES 13 | //#define FRUSTUM_CULLING 14 | //#define DISCOVER_KEY_CODES 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /Source/InertiaTensor.h: -------------------------------------------------------------------------------- 1 | #ifndef INERTIA_TENSOR_H 2 | #define INERTIA_TENSOR_H 3 | 4 | void CalculateSphereInertiaTensor( float mass, float r, mat4f & inertiaTensor, mat4f & inverseInertiaTensor ) 5 | { 6 | const float i = 2.0f / 5.0f * mass * r * r; 7 | float values[] = { i, 0, 0, 0, 8 | 0, i, 0, 0, 9 | 0, 0, i, 0, 10 | 0, 0, 0, 1 }; 11 | float inverse_values[] = { 1/i, 0, 0, 0, 12 | 0, 1/i, 0, 0, 13 | 0, 0, 1/i, 0, 14 | 0, 0, 0, 1 }; 15 | inertiaTensor.load( values ); 16 | inverseInertiaTensor.load( inverse_values ); 17 | } 18 | 19 | void CalculateEllipsoidInertiaTensor( float mass, float a, float b, float c, mat4f & inertiaTensor, mat4f & inverseInertiaTensor ) 20 | { 21 | const float i_a = 1.0f/5.0f * mass * ( b*b + c*c ); 22 | const float i_b = 1.0f/5.0f * mass * ( a*a + c*c ); 23 | const float i_c = 1.0f/5.0f * mass * ( a*a + b*b ); 24 | float values[] = { i_a, 0, 0, 0, 25 | 0, i_b, 0, 0, 26 | 0, 0, i_c, 0, 27 | 0, 0, 0, 1 }; 28 | float inverse_values[] = { 1/i_a, 0, 0, 0, 29 | 0, 1/i_b, 0, 0, 30 | 0, 0, 1/i_c, 0, 31 | 0, 0, 0, 1 }; 32 | inertiaTensor.load( values ); 33 | inverseInertiaTensor.load( inverse_values ); 34 | } 35 | 36 | float CalculateBiconvexVolume( const Biconvex & biconvex ) 37 | { 38 | const float r = biconvex.GetSphereRadius(); 39 | const float h = r - biconvex.GetHeight() / 2; 40 | return h*h + ( pi * r / 4 + pi * h / 24 ); 41 | } 42 | 43 | void CalculateBiconvexInertiaTensor( float mass, const Biconvex & biconvex, vec3f & inertia, mat4f & inertiaTensor, mat4f & inverseInertiaTensor ) 44 | { 45 | const float resolution = 0.1; 46 | const float width = biconvex.GetWidth(); 47 | const float height = biconvex.GetHeight(); 48 | const float xy_steps = ceil( width / resolution ); 49 | const float z_steps = ceil( height / resolution ); 50 | const float dx = width / xy_steps; 51 | const float dy = width / xy_steps; 52 | const float dz = height / xy_steps; 53 | float sx = -width / 2; 54 | float sy = -width / 2; 55 | float sz = -height / 2; 56 | float ix = 0.0; 57 | float iy = 0.0; 58 | float iz = 0.0; 59 | const float v = CalculateBiconvexVolume( biconvex ); 60 | const float p = mass / v; 61 | const float m = dx*dy*dz * p; 62 | for ( int index_z = 0; index_z <= z_steps; ++index_z ) 63 | { 64 | for ( int index_y = 0; index_y <= xy_steps; ++index_y ) 65 | { 66 | for ( int index_x = 0; index_x <= xy_steps; ++index_x ) 67 | { 68 | const float x = sx + index_x * dx; 69 | const float y = sy + index_y * dy; 70 | const float z = sz + index_z * dz; 71 | 72 | vec3f point(x,y,z); 73 | 74 | if ( PointInsideBiconvex_LocalSpace( point, biconvex ) ) 75 | { 76 | const float rx2 = z*z + y*y; 77 | const float ry2 = x*x + z*z; 78 | const float rz2 = x*x + y*y; 79 | 80 | ix += rx2 * m; 81 | iy += ry2 * m; 82 | iz += rz2 * m; 83 | } 84 | } 85 | } 86 | } 87 | 88 | // todo: i fucked this up. fix it! 89 | 90 | /* 91 | // http://wolframalpha.com 92 | // integrate ( r^2 - ( y + r - h/2 ) ^ 2 ) ^ 2 dy from y = 0 to h/2 93 | // => 1/480 h^3 (3 h^2-30 h r+80 r^2) 94 | const float h = height; 95 | const float r = biconvex.GetSphereRadius(); 96 | const float exact_iz = pi * p * ( 1/480.0f * h*h*h * ( 3*h*h - 30*h*r + 80*r*r ) ); 97 | 98 | iz = exact_iz; 99 | 100 | printf( "inertia tensor: %f, %f,%f\n", ix, iy, iz ); 101 | */ 102 | 103 | const float inertiaValues[] = { ix, iy, iz }; 104 | 105 | const float inertiaTensorValues[] = { ix, 0, 0, 0, 106 | 0, iy, 0, 0, 107 | 0, 0, iz, 0, 108 | 0, 0, 0, 1 }; 109 | 110 | const float inverseInertiaTensorValues[] = { 1/ix, 0, 0, 0, 111 | 0, 1/iy, 0, 0, 112 | 0, 0, 1/iz, 0, 113 | 0, 0, 0, 1 }; 114 | 115 | inertia.load( inertiaValues ); 116 | inertiaTensor.load( inertiaTensorValues ); 117 | inverseInertiaTensor.load( inverseInertiaTensorValues ); 118 | } 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /Source/Platform.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_H 2 | #define PLATFORM_H 3 | 4 | // platform detection 5 | 6 | #define PLATFORM_WINDOWS 1 7 | #define PLATFORM_MAC 2 8 | #define PLATFORM_LINUX 3 9 | #define PLATFORM_UNIX 4 10 | #define PLATFORM_PS3 5 11 | 12 | #if defined(_WIN32) 13 | #define PLATFORM PLATFORM_WINDOWS 14 | #elif defined(__APPLE__) 15 | #define PLATFORM PLATFORM_MAC 16 | #elif defined(linux) 17 | #define PLATFORM PLATFORM_LINUX 18 | #else 19 | #define PLATFORM PLATFORM_UNIX 20 | #endif 21 | 22 | #if PLATFORM == PLATFORM_WINDOWS || PLATFORM == PLATFORM_MAC 23 | #define HAS_OPENGL 24 | #endif 25 | 26 | #ifndef PLATFORM 27 | #error unknown platform! 28 | #endif 29 | 30 | #if PLATFORM == PLATFORM_MAC 31 | #include 32 | #endif 33 | 34 | #include 35 | #include 36 | 37 | namespace platform 38 | { 39 | // display stuff 40 | 41 | void GetDisplayResolution( int & width, int & height ); 42 | bool OpenDisplay( const char title[], int width, int height, int bits = 32, int refresh = 60 ); 43 | void UpdateEvents(); 44 | void UpdateDisplay( int interval = 1 ); 45 | void CloseDisplay(); 46 | 47 | void HideMouseCursor(); 48 | void ShowMouseCursor(); 49 | void GetMousePosition( int & x, int & y ); 50 | 51 | // basic keyboard input 52 | 53 | struct Input 54 | { 55 | static Input Sample(); 56 | 57 | Input() 58 | { 59 | memset( this, 0, sizeof( Input ) ); 60 | } 61 | 62 | // todo: this is shitty. do an array indexed by keycodes instead 63 | 64 | bool quit; 65 | bool left; 66 | bool right; 67 | bool up; 68 | bool down; 69 | bool space; 70 | bool escape; 71 | bool tab; 72 | bool backslash; 73 | bool enter; 74 | bool del; 75 | bool pageUp; 76 | bool pageDown; 77 | bool q; 78 | bool w; 79 | bool e; 80 | bool r; 81 | bool a; 82 | bool s; 83 | bool d; 84 | bool z; 85 | bool tilde; 86 | bool one; 87 | bool two; 88 | bool three; 89 | bool four; 90 | bool five; 91 | bool six; 92 | bool seven; 93 | bool eight; 94 | bool nine; 95 | bool zero; 96 | bool f1; 97 | bool f2; 98 | bool f3; 99 | bool f4; 100 | bool f5; 101 | bool f6; 102 | bool f7; 103 | bool f8; 104 | bool control; 105 | bool alt; 106 | }; 107 | 108 | // timing related stuff 109 | 110 | void wait_seconds( float seconds ); 111 | 112 | class Timer 113 | { 114 | public: 115 | 116 | Timer(); 117 | 118 | void reset(); 119 | float time(); 120 | float delta(); 121 | float resolution(); 122 | 123 | private: 124 | 125 | uint64_t _startTime; // start time (to avoid accumulating a float) 126 | uint64_t _deltaTime; // last time delta was called 127 | }; 128 | 129 | // worker thread 130 | 131 | class WorkerThread 132 | { 133 | public: 134 | 135 | WorkerThread(); 136 | virtual ~WorkerThread(); 137 | 138 | bool Start(); 139 | bool Join(); 140 | 141 | protected: 142 | 143 | static void * StaticRun( void * data ); 144 | 145 | virtual void Run() = 0; // note: override this to implement your thread task 146 | 147 | private: 148 | 149 | pthread_t thread; 150 | }; 151 | } 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /Source/Render.h: -------------------------------------------------------------------------------- 1 | #ifndef RENDER_H 2 | #define RENDER_H 3 | 4 | #include "Stone.h" 5 | #include "Board.h" 6 | #include "Mesh.h" 7 | 8 | #define GL_SILENCE_DEPRECATION 9 | 10 | #if PLATFORM == PLATFORM_MAC 11 | #include 12 | #include 13 | #include 14 | #include 15 | #endif 16 | 17 | void ClearScreen( int displayWidth, int displayHeight, float r = 0, float g = 0, float b = 0 ) 18 | { 19 | glViewport( 0, 0, displayWidth, displayHeight ); 20 | glDisable( GL_SCISSOR_TEST ); 21 | glClearStencil( 0 ); 22 | glClearColor( r, g, b, 1 ); 23 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); 24 | } 25 | 26 | void RenderBiconvexNaive( const Biconvex & biconvex, int numSegments = 128, int numRings = 32 ) 27 | { 28 | glBegin( GL_TRIANGLES ); 29 | 30 | const float sphereRadius = biconvex.GetSphereRadius(); 31 | const float segmentAngle = 2*pi / numSegments; 32 | 33 | // bottom surface of biconvex 34 | { 35 | const float center_y = biconvex.GetSphereOffset(); 36 | const float delta_y = biconvex.GetHeight() / 2 / numRings; 37 | 38 | for ( int i = 0; i < numRings; ++i ) 39 | { 40 | const float y1 = -i * delta_y; 41 | const float s1 = y1 - center_y; 42 | const float r1 = sqrt( sphereRadius*sphereRadius - (s1*s1) ); 43 | const float y2 = -(i+1) * delta_y; 44 | const float s2 = y2 - center_y; 45 | const float r2 = sqrt( sphereRadius*sphereRadius - (s2*s2) ); 46 | 47 | for ( int j = 0; j < numSegments; ++j ) 48 | { 49 | const float angle1 = j * segmentAngle; 50 | const float angle2 = angle1 + segmentAngle; 51 | 52 | const float top_x1 = cos( angle1 ) * r1; 53 | const float top_z1 = sin( angle1 ) * r1; 54 | const float top_x2 = cos( angle2 ) * r1; 55 | const float top_z2 = sin( angle2 ) * r1; 56 | 57 | const float bottom_x1 = cos( angle1 ) * r2; 58 | const float bottom_z1 = sin( angle1 ) * r2; 59 | const float bottom_x2 = cos( angle2 ) * r2; 60 | const float bottom_z2 = sin( angle2 ) * r2; 61 | 62 | vec3f a( top_x1, y1, top_z1 ); 63 | vec3f b( bottom_x1, y2, bottom_z1 ); 64 | vec3f c( bottom_x2, y2, bottom_z2 ); 65 | vec3f d( top_x2, y1, top_z2 ); 66 | 67 | vec3f center( 0, center_y, 0 ); 68 | 69 | vec3f na = normalize( a - center ); 70 | vec3f nb = normalize( b - center ); 71 | vec3f nc = normalize( c - center ); 72 | vec3f nd = normalize( d - center ); 73 | 74 | glNormal3f( na.x(), na.y(), na.z() ); 75 | glVertex3f( a.x(), a.y(), a.z() ); 76 | 77 | glNormal3f( nb.x(), nb.y(), nb.z() ); 78 | glVertex3f( b.x(), b.y(), b.z() ); 79 | 80 | glNormal3f( nc.x(), nc.y(), nc.z() ); 81 | glVertex3f( c.x(), c.y(), c.z() ); 82 | 83 | glNormal3f( na.x(), na.y(), na.z() ); 84 | glVertex3f( a.x(), a.y(), a.z() ); 85 | 86 | glNormal3f( nc.x(), nc.y(), nc.z() ); 87 | glVertex3f( c.x(), c.y(), c.z() ); 88 | 89 | glNormal3f( nd.x(), nd.y(), nd.z() ); 90 | glVertex3f( d.x(), d.y(), d.z() ); 91 | } 92 | } 93 | } 94 | 95 | // top surface of biconvex 96 | { 97 | const float center_y = -biconvex.GetSphereOffset(); 98 | const float delta_y = biconvex.GetHeight() / 2 / numRings; 99 | 100 | for ( int i = 0; i < numRings; ++i ) 101 | { 102 | const float y1 = i * delta_y; 103 | const float s1 = y1 - center_y; 104 | const float r1 = sqrt( sphereRadius*sphereRadius - (s1*s1) ); 105 | const float y2 = (i+1) * delta_y; 106 | const float s2 = y2 - center_y; 107 | const float r2 = sqrt( sphereRadius*sphereRadius - (s2*s2) ); 108 | 109 | for ( int j = 0; j < numSegments; ++j ) 110 | { 111 | const float angle1 = j * segmentAngle; 112 | const float angle2 = angle1 + segmentAngle; 113 | 114 | const float top_x1 = cos( angle1 ) * r1; 115 | const float top_z1 = sin( angle1 ) * r1; 116 | const float top_x2 = cos( angle2 ) * r1; 117 | const float top_z2 = sin( angle2 ) * r1; 118 | 119 | const float bottom_x1 = cos( angle1 ) * r2; 120 | const float bottom_z1 = sin( angle1 ) * r2; 121 | const float bottom_x2 = cos( angle2 ) * r2; 122 | const float bottom_z2 = sin( angle2 ) * r2; 123 | 124 | vec3f a( bottom_x1, y2, bottom_z1 ); 125 | vec3f b( top_x1, y1, top_z1 ); 126 | vec3f c( top_x2, y1, top_z2 ); 127 | vec3f d( bottom_x2, y2, bottom_z2 ); 128 | 129 | vec3f center( 0, center_y, 0 ); 130 | 131 | vec3f na = normalize( a - center ); 132 | vec3f nb = normalize( b - center ); 133 | vec3f nc = normalize( c - center ); 134 | vec3f nd = normalize( d - center ); 135 | 136 | glNormal3f( na.x(), na.y(), na.z() ); 137 | glVertex3f( a.x(), a.y(), a.z() ); 138 | 139 | glNormal3f( nb.x(), nb.y(), nb.z() ); 140 | glVertex3f( b.x(), b.y(), b.z() ); 141 | 142 | glNormal3f( nc.x(), nc.y(), nc.z() ); 143 | glVertex3f( c.x(), c.y(), c.z() ); 144 | 145 | glNormal3f( na.x(), na.y(), na.z() ); 146 | glVertex3f( a.x(), a.y(), a.z() ); 147 | 148 | glNormal3f( nc.x(), nc.y(), nc.z() ); 149 | glVertex3f( c.x(), c.y(), c.z() ); 150 | 151 | glNormal3f( nd.x(), nd.y(), nd.z() ); 152 | glVertex3f( d.x(), d.y(), d.z() ); 153 | } 154 | } 155 | } 156 | 157 | glEnd(); 158 | } 159 | 160 | void RenderGrid( float z, float size, float gridWidth, float gridHeight ) 161 | { 162 | glBegin( GL_QUADS ); 163 | 164 | const float dx = gridWidth; 165 | const float dy = gridHeight; 166 | 167 | float x = - ( size - 1 ) * 0.5f * gridWidth; 168 | 169 | for ( int i = 0; i < size - 1; ++i ) 170 | { 171 | float y = - ( size - 1 ) * 0.5f * gridHeight; 172 | 173 | for ( int j = 0; j < size - 1; ++j ) 174 | { 175 | glVertex3f( x + dx, y, z ); 176 | glVertex3f( x + dx, y + dy, z ); 177 | glVertex3f( x, y + dy, z ); 178 | glVertex3f( x, y, z ); 179 | 180 | y += dy; 181 | } 182 | 183 | x += dx; 184 | } 185 | 186 | glEnd(); 187 | } 188 | 189 | void RenderBoard( const Board & board ) 190 | { 191 | glBegin( GL_QUADS ); 192 | 193 | const float width = board.GetWidth(); 194 | const float height = board.GetHeight(); 195 | const float thickness = board.GetThickness(); 196 | 197 | // top of board 198 | 199 | glNormal3f( 0,0,1 ); 200 | 201 | glTexCoord2f( 1, 0 ); glVertex3f( width/2, -height/2, thickness ); 202 | glTexCoord2f( 1, 1 ); glVertex3f( width/2, height/2, thickness ); 203 | glTexCoord2f( 0, 1 ); glVertex3f( -width/2, height/2, thickness ); 204 | glTexCoord2f( 0, 0 ); glVertex3f( -width/2, -height/2, thickness ); 205 | 206 | // front side 207 | 208 | glNormal3f( 0,-1,0 ); 209 | 210 | glVertex3f( width/2, -height/2, 0 ); 211 | glVertex3f( width/2, -height/2, thickness ); 212 | glVertex3f( -width/2, -height/2, thickness ); 213 | glVertex3f( -width/2, -height/2, 0 ); 214 | 215 | // back side 216 | 217 | glNormal3f( 0,+1,0 ); 218 | glVertex3f( width/2, height/2, thickness ); 219 | glVertex3f( width/2, height/2, 0 ); 220 | glVertex3f( -width/2, height/2, 0 ); 221 | glVertex3f( -width/2, height/2, thickness ); 222 | 223 | // left side 224 | 225 | glNormal3f( -1,0,0 ); 226 | glVertex3f( -width/2, -height/2, 0 ); 227 | glVertex3f( -width/2, -height/2, thickness ); 228 | glVertex3f( -width/2, +height/2, thickness ); 229 | glVertex3f( -width/2, +height/2, 0 ); 230 | 231 | // right side 232 | 233 | glNormal3f( +1,0,0 ); 234 | glVertex3f( width/2, -height/2, thickness ); 235 | glVertex3f( width/2, -height/2, 0 ); 236 | glVertex3f( width/2, +height/2, 0 ); 237 | glVertex3f( width/2, +height/2, thickness ); 238 | 239 | glEnd(); 240 | } 241 | 242 | void RenderMesh( Mesh & mesh ) 243 | { 244 | glBegin( GL_TRIANGLES ); 245 | 246 | int numTriangles = mesh.GetNumTriangles(); 247 | int * indexBuffer = mesh.GetIndexBuffer(); 248 | Vertex * vertexBuffer = mesh.GetVertexBuffer(); 249 | 250 | for ( int i = 0; i < numTriangles; ++i ) 251 | { 252 | const int index_a = indexBuffer[i*3]; 253 | const int index_b = indexBuffer[i*3+1]; 254 | const int index_c = indexBuffer[i*3+2]; 255 | 256 | const Vertex & a = vertexBuffer[index_a]; 257 | const Vertex & b = vertexBuffer[index_b]; 258 | const Vertex & c = vertexBuffer[index_c]; 259 | 260 | glNormal3f( a.normal.x(), a.normal.y(), a.normal.z() ); 261 | glVertex3f( a.position.x(), a.position.y(), a.position.z() ); 262 | 263 | glNormal3f( b.normal.x(), b.normal.y(), b.normal.z() ); 264 | glVertex3f( b.position.x(), b.position.y(), b.position.z() ); 265 | 266 | glNormal3f( c.normal.x(), c.normal.y(), c.normal.z() ); 267 | glVertex3f( c.position.x(), c.position.y(), c.position.z() ); 268 | } 269 | 270 | glEnd(); 271 | } 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /Source/RigidBody.h: -------------------------------------------------------------------------------- 1 | #ifndef RIGID_BODY_H 2 | #define RIGID_BODY_H 3 | 4 | /* 5 | Rigid body class and support functions. 6 | We need a nice way to cache the local -> world, 7 | world -> local and position for a given rigid body. 8 | */ 9 | 10 | struct RigidBody 11 | { 12 | mat4f inertiaTensor; 13 | mat4f inverseInertiaTensor; 14 | 15 | // IMPORTANT: these are secondary quantities calculated in "UpdateTransform" 16 | RigidBodyTransform transform; 17 | mat4f rotation, transposeRotation; 18 | mat4f inertiaTensorWorld; 19 | mat4f inverseInertiaTensorWorld; 20 | 21 | quat4f orientation; 22 | 23 | vec3f inertia; 24 | vec3f position; 25 | vec3f linearMomentum, angularMomentum; 26 | 27 | // IMPORTANT: these are secondary quantities calculated in "UpdateMomentum" 28 | vec3f linearVelocity, angularVelocity; 29 | 30 | float mass; 31 | float inverseMass; 32 | float deactivateTimer; 33 | 34 | bool active; 35 | 36 | RigidBody() 37 | { 38 | active = true; 39 | deactivateTimer = 0.0f; 40 | position = vec3f(0,0,0); 41 | orientation = quat4f::identity(); 42 | linearMomentum = vec3f(0,0,0); 43 | angularMomentum = vec3f(0,0,0); 44 | mass = 1.0f; 45 | inverseMass = 1.0f / mass; 46 | inertia = vec3f(1,1,1); 47 | inertiaTensor = mat4f::identity(); 48 | inverseInertiaTensor = mat4f::identity(); 49 | 50 | UpdateTransform(); 51 | UpdateMomentum(); 52 | } 53 | 54 | void UpdateTransform() 55 | { 56 | orientation.toMatrix( rotation ); 57 | transposeRotation = transpose( rotation ); 58 | 59 | inertiaTensorWorld = rotation * inertiaTensor * transposeRotation; 60 | inverseInertiaTensorWorld = rotation * inverseInertiaTensor * transposeRotation; 61 | 62 | transform.Initialize( position, rotation, transposeRotation ); 63 | } 64 | 65 | void UpdateMomentum() 66 | { 67 | if ( active ) 68 | { 69 | const float MaxAngularMomentum = 10; 70 | 71 | // todo: I'd like to clamp at maximum angular VELOCITY not momentum 72 | // i only care how fast it is rotating, not how much mass it has 73 | 74 | float x = clamp( angularMomentum.x(), -MaxAngularMomentum, MaxAngularMomentum ); 75 | float y = clamp( angularMomentum.y(), -MaxAngularMomentum, MaxAngularMomentum ); 76 | float z = clamp( angularMomentum.z(), -MaxAngularMomentum, MaxAngularMomentum ); 77 | 78 | angularMomentum = vec3f( x,y,z ); 79 | 80 | linearVelocity = linearMomentum * inverseMass; 81 | angularVelocity = transformVector( inverseInertiaTensorWorld, angularMomentum ); 82 | } 83 | else 84 | { 85 | linearMomentum = vec3f( 0,0,0 ); 86 | linearVelocity = vec3f( 0,0,0 ); 87 | angularMomentum = vec3f( 0,0,0 ); 88 | angularVelocity = vec3f( 0,0,0 ); 89 | } 90 | } 91 | 92 | void GetVelocityAtWorldPoint( const vec3f & point, vec3f & velocity ) const 93 | { 94 | vec3f angularVelocity = transformVector( inverseInertiaTensorWorld, angularMomentum ); 95 | velocity = linearVelocity + cross( angularVelocity, point - position ); 96 | } 97 | 98 | float GetKineticEnergy() const 99 | { 100 | // IMPORTANT: please refer to http://people.rit.edu/vwlsps/IntermediateMechanics2/Ch9v5.pdf 101 | // for the derivation of angular kinetic energy from angular velocity + inertia tensor 102 | 103 | const float linearKE = length_squared( linearMomentum ) / ( 2 * mass ); 104 | 105 | vec3f angularMomentumLocal = transformVector( transposeRotation, angularMomentum ); 106 | vec3f angularVelocityLocal = transformVector( inverseInertiaTensor, angularMomentumLocal ); 107 | 108 | const float ix = inertia.x(); 109 | const float iy = inertia.y(); 110 | const float iz = inertia.z(); 111 | 112 | const float wx = angularVelocityLocal.x(); 113 | const float wy = angularVelocityLocal.y(); 114 | const float wz = angularVelocityLocal.z(); 115 | 116 | const float angularKE = 0.5f * ( ix * wx * wx + 117 | iy * wy * wy + 118 | iz * wz * wz ); 119 | 120 | return linearKE + angularKE; 121 | } 122 | 123 | void Activate() 124 | { 125 | if ( !active ) 126 | active = true; 127 | } 128 | 129 | void Deactivate() 130 | { 131 | if ( active ) 132 | { 133 | active = false; 134 | deactivateTimer = 0; 135 | linearMomentum = vec3f(0,0,0); 136 | linearVelocity = vec3f(0,0,0); 137 | angularMomentum = vec3f(0,0,0); 138 | angularVelocity = vec3f(0,0,0); 139 | } 140 | } 141 | 142 | void ApplyImpulse( const vec3f & impulse ) 143 | { 144 | Activate(); 145 | linearMomentum += impulse; 146 | UpdateMomentum(); // todo: can this be avoided? 147 | } 148 | 149 | void ApplyImpulseAtWorldPoint( const vec3f & point, const vec3f & impulse ) 150 | { 151 | Activate(); 152 | vec3f r = point - position; 153 | linearMomentum += impulse; 154 | angularMomentum += cross( r, impulse ); 155 | UpdateMomentum(); // todo: can this be avoided? 156 | } 157 | }; 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /Source/Stone.h: -------------------------------------------------------------------------------- 1 | #ifndef STONE_H 2 | #define STONE_H 3 | 4 | #include "Biconvex.h" 5 | #include "RigidBody.h" 6 | #include "InertiaTensor.h" 7 | 8 | // stone sizes from http://www.kurokigoishi.co.jp/english/seihin/goishi/index.html 9 | 10 | enum StoneSize 11 | { 12 | STONE_SIZE_22, 13 | STONE_SIZE_25, 14 | STONE_SIZE_28, 15 | STONE_SIZE_30, 16 | STONE_SIZE_31, 17 | STONE_SIZE_32, 18 | STONE_SIZE_33, 19 | STONE_SIZE_34, 20 | STONE_SIZE_35, 21 | STONE_SIZE_36, 22 | STONE_SIZE_37, 23 | STONE_SIZE_38, 24 | STONE_SIZE_39, 25 | STONE_SIZE_40, 26 | STONE_SIZE_NumValues 27 | }; 28 | 29 | const float StoneHeight[] = 30 | { 31 | 0.63f, 32 | 0.70f, 33 | 0.75f, 34 | 0.80f, 35 | 0.84f, 36 | 0.88f, 37 | 0.92f, 38 | 0.95f, 39 | 0.98f, 40 | 1.01f, 41 | 1.04f, 42 | 1.07f, 43 | 1.10f, 44 | 1.13f 45 | }; 46 | 47 | inline float GetStoneWidth( StoneSize stoneSize, bool black = false ) 48 | { 49 | return 2.2f + ( black ? 0.3f : 0 ); 50 | } 51 | 52 | inline float GetStoneHeight( StoneSize stoneSize, bool black = false ) 53 | { 54 | return StoneHeight[stoneSize] + ( black ? 0.3f : 0 ); 55 | } 56 | 57 | struct Stone 58 | { 59 | void Initialize( StoneSize stoneSize, 60 | float bevel = 0.1f, 61 | float mass = 1.0f, 62 | bool black = false ) 63 | { 64 | biconvex = Biconvex( GetStoneWidth( stoneSize, black ), GetStoneHeight( stoneSize, black ), bevel ); 65 | rigidBody.mass = mass; 66 | rigidBody.inverseMass = 1.0f / mass; 67 | CalculateBiconvexInertiaTensor( mass, biconvex, rigidBody.inertia, rigidBody.inertiaTensor, rigidBody.inverseInertiaTensor ); 68 | } 69 | 70 | Biconvex biconvex; 71 | RigidBody rigidBody; 72 | }; 73 | 74 | inline vec3f NearestPointOnStone( const Biconvex & biconvex, 75 | const RigidBodyTransform & biconvexTransform, 76 | vec3f point ) 77 | { 78 | vec3f localPoint = TransformPoint( biconvexTransform.worldToLocal, point ); 79 | vec3f nearestLocal = GetNearestPointOnBiconvexSurface_LocalSpace( localPoint, biconvex ); 80 | return TransformPoint( biconvexTransform.localToWorld, nearestLocal ); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /Source/Support.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Biconvex Support demo 3 | Copyright (c) 2005-2013, Glenn Fiedler. All rights reserved. 4 | */ 5 | 6 | #include "Common.h" 7 | #include "Render.h" 8 | #include "Stone.h" 9 | #include "Platform.h" 10 | #include "Biconvex.h" 11 | #include "RigidBody.h" 12 | #include "Intersection.h" 13 | #include "CollisionDetection.h" 14 | 15 | using namespace platform; 16 | 17 | int main( int argc, char * argv[] ) 18 | { 19 | bool playback = false; 20 | bool video = false; 21 | 22 | for ( int i = 1; i < argc; ++i ) 23 | { 24 | if ( strcmp( argv[i], "playback" ) == 0 ) 25 | { 26 | printf( "playback\n" ); 27 | playback = true; 28 | } 29 | else if ( strcmp( argv[i], "video" ) == 0 ) 30 | { 31 | printf( "video\n" ); 32 | video = true; 33 | } 34 | } 35 | 36 | printf( "[support demo]\n" ); 37 | 38 | Biconvex biconvex( 2.2f, 1.13f ); 39 | 40 | Mesh mesh; 41 | GenerateBiconvexMesh( mesh, biconvex ); 42 | 43 | int displayWidth, displayHeight; 44 | GetDisplayResolution( displayWidth, displayHeight ); 45 | 46 | #ifdef LETTERBOX 47 | displayWidth = 1280; 48 | displayHeight = 800; 49 | #endif 50 | 51 | printf( "display resolution is %d x %d\n", displayWidth, displayHeight ); 52 | 53 | if ( !OpenDisplay( "Support Demo", displayWidth, displayHeight, 32 ) ) 54 | { 55 | printf( "error: failed to open display" ); 56 | return 1; 57 | } 58 | 59 | HideMouseCursor(); 60 | 61 | glEnable( GL_LINE_SMOOTH ); 62 | glEnable( GL_POLYGON_SMOOTH ); 63 | glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); 64 | glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST ); 65 | 66 | // create 2 pixel buffer objects, you need to delete them when program exits. 67 | // glBufferDataARB with NULL pointer reserves only memory space. 68 | const int NumPBOs = 2; 69 | GLuint pboIds[NumPBOs]; 70 | int index = 0; 71 | const int dataSize = displayWidth * displayHeight * 3; 72 | if ( video ) 73 | { 74 | glGenBuffersARB( NumPBOs, pboIds ); 75 | for ( int i = 0; i < NumPBOs; ++i ) 76 | { 77 | glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[i] ); 78 | glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, dataSize, 0, GL_STREAM_DRAW_ARB ); 79 | } 80 | glBindBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, 0 ); 81 | } 82 | 83 | // record input to a file 84 | // read it back in playback mode for recording video 85 | FILE * inputFile = fopen( "output/recordedInputs", playback ? "rb" : "wb" ); 86 | if ( !inputFile ) 87 | { 88 | printf( "failed to open input file\n" ); 89 | return 1; 90 | } 91 | 92 | mat4f rotation = mat4f::identity(); 93 | 94 | double t = 0.0f; 95 | 96 | bool quit = false; 97 | 98 | bool prevSpace = false; 99 | 100 | bool rotating = true; 101 | 102 | float smoothedRotation = 0.0f; 103 | 104 | const float dt = 1.0f / 60.0f; 105 | 106 | unsigned int frame = 0; 107 | 108 | while ( !quit ) 109 | { 110 | UpdateEvents(); 111 | 112 | Input input; 113 | 114 | if ( !playback ) 115 | { 116 | input = platform::Input::Sample(); 117 | fwrite( &input, sizeof( platform::Input ), 1, inputFile ); 118 | fflush( inputFile ); 119 | } 120 | else 121 | { 122 | const int size = sizeof( platform::Input ); 123 | if ( !fread( &input, size, 1, inputFile ) ) 124 | quit = true; 125 | } 126 | 127 | if ( input.quit ) 128 | quit = true; 129 | 130 | if ( input.space && !prevSpace ) 131 | rotating = !rotating; 132 | prevSpace = input.space; 133 | 134 | ClearScreen( displayWidth, displayHeight ); 135 | 136 | if ( frame > 20 ) 137 | { 138 | glMatrixMode( GL_PROJECTION ); 139 | glLoadIdentity(); 140 | glOrtho( -1.5, +1.5f, -1.0f, +1.0f, 0.1f, 100.0f ); 141 | 142 | float flipX[] = { -1,0,0,0, 143 | 0,1,0,0, 144 | 0,0,1,0, 145 | 0,0,0,1 }; 146 | 147 | glMultMatrixf( flipX ); 148 | 149 | glScalef( 0.6f, 0.6f, 0.6f ); 150 | 151 | vec3f lightPosition( -1, +2, -5 ); 152 | 153 | GLfloat light_ambient[] = { 0.7, 0.7, 0.7, 1.0 }; 154 | GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 155 | GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 156 | 157 | glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient ); 158 | glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse ); 159 | glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular ); 160 | 161 | glMatrixMode( GL_MODELVIEW ); 162 | glLoadIdentity(); 163 | gluLookAt( 0, 0, -5, 164 | 0, 0, 0, 165 | 0, 1, 0 ); 166 | 167 | // render stone 168 | 169 | const float targetRotation = rotating ? 0.28f : 0; 170 | smoothedRotation += ( targetRotation - smoothedRotation ) * 0.15f; 171 | mat4f deltaRotation = mat4f::axisRotation( smoothedRotation, vec3f(1,2,3) ); 172 | rotation = rotation * deltaRotation; 173 | mat4f inverseRotation = transpose( rotation ); 174 | 175 | RigidBodyTransform biconvexTransform; 176 | biconvexTransform.Initialize( vec3f(0,0,0), rotation, inverseRotation ); 177 | 178 | glEnable( GL_LIGHTING ); 179 | glEnable( GL_LIGHT0 ); 180 | 181 | glShadeModel( GL_SMOOTH ); 182 | 183 | GLfloat lightAmbientColor[] = { 1, 1, 1, 1.0 }; 184 | glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lightAmbientColor ); 185 | 186 | GLfloat position[4]; 187 | position[0] = lightPosition.x(); 188 | position[1] = lightPosition.y(); 189 | position[2] = lightPosition.z(); 190 | position[3] = 1.0f; 191 | glLightfv( GL_LIGHT0, GL_POSITION, position ); 192 | 193 | glEnable( GL_CULL_FACE ); 194 | glCullFace( GL_BACK ); 195 | 196 | glPushMatrix(); 197 | 198 | float opengl_transform[16]; 199 | biconvexTransform.localToWorld.store( opengl_transform ); 200 | glMultMatrixf( opengl_transform ); 201 | 202 | glColor4f(1,1,1,1); 203 | 204 | RenderMesh( mesh ); 205 | 206 | glPopMatrix(); 207 | 208 | // visualize biconvex support 209 | 210 | vec3f biconvexCenter; 211 | vec3f biconvexUp; 212 | biconvexTransform.GetPosition( biconvexCenter ); 213 | biconvexTransform.GetUp( biconvexUp ); 214 | float s1,s2; 215 | BiconvexSupport_WorldSpace( biconvex, biconvexCenter, biconvexUp, vec3f(1,0,0), s1, s2 ); 216 | 217 | glDisable( GL_LIGHTING ); 218 | 219 | glEnable( GL_BLEND ); 220 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 221 | 222 | glLineStipple( 10, 0xAAAA ); 223 | glEnable( GL_LINE_STIPPLE ); 224 | glColor4f( 0.8,0.8,0.8,1 ); 225 | glLineWidth( 5 ); 226 | 227 | glBegin( GL_LINES ); 228 | glVertex3f( s1, -10, 0 ); 229 | glVertex3f( s1, +10, 0 ); 230 | glVertex3f( s2, -10, 0 ); 231 | glVertex3f( s2, +10, 0 ); 232 | glEnd(); 233 | 234 | glDisable( GL_LINE_STIPPLE ); 235 | glColor4f( 1,0,0,1 ); 236 | glLineWidth( 20 ); 237 | 238 | glBegin( GL_LINES ); 239 | glVertex3f( s1 - 0.01f, -1.65, 0 ); 240 | glVertex3f( s2 + 0.01f, -1.65, 0 ); 241 | glEnd(); 242 | } 243 | 244 | // record to video 245 | 246 | if ( video ) 247 | { 248 | // "index" is used to read pixels from framebuffer to a PBO 249 | // "nextIndex" is used to update pixels in the other PBO 250 | index = ( index + 1 ) % NumPBOs; 251 | int prevIndex = ( index + NumPBOs - 1 ) % NumPBOs; 252 | 253 | // set the target framebuffer to read 254 | glReadBuffer( GL_FRONT ); 255 | 256 | // read pixels from framebuffer to PBO 257 | // glReadPixels() should return immediately. 258 | glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[index] ); 259 | glReadPixels( 0, 0, displayWidth, displayHeight, GL_BGR, GL_UNSIGNED_BYTE, 0 ); 260 | if ( frame > (unsigned) NumPBOs ) 261 | { 262 | // map the PBO to process its data by CPU 263 | glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, pboIds[prevIndex] ); 264 | GLubyte * ptr = (GLubyte*) glMapBufferARB( GL_PIXEL_PACK_BUFFER_ARB, 265 | GL_READ_ONLY_ARB ); 266 | if ( ptr ) 267 | { 268 | char filename[256]; 269 | snprintf( filename, sizeof(filename), "output/frame-%05d.tga", frame - NumPBOs ); 270 | #ifdef LETTERBOX 271 | WriteTGA( filename, displayWidth, displayHeight - 80, ptr + displayWidth * 3 * 40 ); 272 | #else 273 | WriteTGA( filename, displayWidth, displayHeight, ptr ); 274 | #endif 275 | glUnmapBufferARB( GL_PIXEL_PACK_BUFFER_ARB ); 276 | } 277 | } 278 | 279 | // back to conventional pixel operation 280 | glBindBufferARB( GL_PIXEL_PACK_BUFFER_ARB, 0 ); 281 | } 282 | 283 | // update the display 284 | 285 | UpdateDisplay( video ? 0 : 1 ); 286 | 287 | // update time 288 | 289 | t += dt; 290 | 291 | frame++; 292 | } 293 | 294 | CloseDisplay(); 295 | 296 | return 0; 297 | } 298 | -------------------------------------------------------------------------------- /Source/Tessellation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Go stone tessellation demo. 3 | Copyright (c) 2004-2013, Glenn Fiedler. All rights reserved. 4 | */ 5 | 6 | #include "Common.h" 7 | #include "Render.h" 8 | #include "Stone.h" 9 | #include "Mesh.h" 10 | #include "Platform.h" 11 | #include "Biconvex.h" 12 | #include "RigidBody.h" 13 | #include "Intersection.h" 14 | #include "CollisionDetection.h" 15 | 16 | using namespace platform; 17 | 18 | static Biconvex biconvex( 2.2f, 1.13f ); 19 | 20 | static Biconvex biconvexWithBevel( 2.2f, 1.13f, 0.1f ); 21 | 22 | enum Mode 23 | { 24 | Naive, 25 | Subdivision, 26 | SubdivisionWithBevel, 27 | Render 28 | }; 29 | 30 | struct TessellationData 31 | { 32 | Mode mode; 33 | int subdivisions; 34 | 35 | TessellationData() 36 | { 37 | mode = Naive; 38 | subdivisions = 5; 39 | } 40 | }; 41 | 42 | TessellationData tessellation; 43 | 44 | void UpdateTessellation( Mesh & mesh, Mode mode, int subdivisions ) 45 | { 46 | if ( mode == tessellation.mode && subdivisions == tessellation.subdivisions ) 47 | return; 48 | 49 | mesh.Clear(); 50 | 51 | if ( mode == SubdivisionWithBevel || mode == Render ) 52 | GenerateBiconvexMesh( mesh, biconvexWithBevel, subdivisions ); 53 | else 54 | GenerateBiconvexMesh( mesh, biconvex, subdivisions ); 55 | 56 | tessellation.mode = mode; 57 | tessellation.subdivisions = subdivisions; 58 | } 59 | 60 | int main() 61 | { 62 | srand( time( NULL ) ); 63 | 64 | printf( "[tessellation]\n" ); 65 | 66 | Mode mode = Naive; 67 | 68 | int subdivisions = 5; 69 | 70 | RigidBody rigidBody; 71 | rigidBody.mass = 1.0f; 72 | rigidBody.inverseMass = 1.0f / rigidBody.mass; 73 | CalculateBiconvexInertiaTensor( rigidBody.mass, biconvex, rigidBody.inertia, rigidBody.inertiaTensor, rigidBody.inverseInertiaTensor ); 74 | 75 | Mesh mesh; 76 | 77 | int displayWidth, displayHeight; 78 | GetDisplayResolution( displayWidth, displayHeight ); 79 | 80 | #ifdef LETTERBOX 81 | displayWidth = 1280; 82 | displayHeight = 800; 83 | #endif 84 | 85 | printf( "display resolution is %d x %d\n", displayWidth, displayHeight ); 86 | 87 | if ( !OpenDisplay( "Tessellation Demo", displayWidth, displayHeight, 32 ) ) 88 | { 89 | printf( "error: failed to open display" ); 90 | return 1; 91 | } 92 | 93 | HideMouseCursor(); 94 | 95 | // setup for render 96 | 97 | glEnable( GL_LINE_SMOOTH ); 98 | glEnable( GL_POLYGON_SMOOTH ); 99 | glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); 100 | glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST ); 101 | 102 | glEnable( GL_LIGHTING ); 103 | 104 | glEnable( GL_LIGHT0 ); 105 | glEnable( GL_LIGHT1 ); 106 | glEnable( GL_LIGHT2 ); 107 | glEnable( GL_LIGHT3 ); 108 | 109 | glShadeModel( GL_SMOOTH ); 110 | 111 | GLfloat lightAmbientColor[] = { 0.2, 0.2, 0.2, 1.0 }; 112 | glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lightAmbientColor ); 113 | 114 | GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; 115 | GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 116 | GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 117 | 118 | glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient ); 119 | glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse ); 120 | glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular ); 121 | 122 | glLightfv( GL_LIGHT1, GL_AMBIENT, light_ambient ); 123 | glLightfv( GL_LIGHT1, GL_DIFFUSE, light_diffuse ); 124 | glLightfv( GL_LIGHT1, GL_SPECULAR, light_specular ); 125 | 126 | glLightfv( GL_LIGHT2, GL_AMBIENT, light_ambient ); 127 | glLightfv( GL_LIGHT2, GL_DIFFUSE, light_diffuse ); 128 | glLightfv( GL_LIGHT2, GL_SPECULAR, light_specular ); 129 | 130 | glLightfv( GL_LIGHT3, GL_AMBIENT, light_ambient ); 131 | glLightfv( GL_LIGHT3, GL_DIFFUSE, light_diffuse ); 132 | glLightfv( GL_LIGHT3, GL_SPECULAR, light_specular ); 133 | 134 | glEnable( GL_BLEND ); 135 | glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 136 | glLineWidth( 4 ); 137 | glColor4f( 1,1,1,1 ); 138 | glEnable( GL_CULL_FACE ); 139 | glCullFace( GL_BACK ); 140 | 141 | mat4f rotation = mat4f::identity(); 142 | 143 | bool prevLeft = false; 144 | bool prevRight = false; 145 | bool prevSpace = false; 146 | bool rotating = true; 147 | bool quit = false; 148 | 149 | float smoothedRotation = 0.0f; 150 | 151 | const float dt = 1.0f / 60.0f; 152 | 153 | uint64_t frame = 0; 154 | 155 | while ( true ) 156 | { 157 | glPolygonMode( GL_FRONT_AND_BACK, mode != Render ? GL_LINE : GL_FILL ); 158 | 159 | UpdateEvents(); 160 | 161 | platform::Input input; 162 | 163 | input = platform::Input::Sample(); 164 | 165 | if ( input.escape || input.quit ) 166 | break; 167 | 168 | if ( input.one ) 169 | { 170 | mode = Naive; 171 | } 172 | else if ( input.two ) 173 | { 174 | mode = Subdivision; 175 | } 176 | else if ( input.three ) 177 | { 178 | mode = SubdivisionWithBevel; 179 | } 180 | else if ( input.four ) 181 | { 182 | mode = Render; 183 | } 184 | 185 | if ( input.space && !prevSpace ) 186 | rotating = !rotating; 187 | prevSpace = input.space; 188 | 189 | if ( input.right && !prevRight ) 190 | { 191 | subdivisions++; 192 | if ( subdivisions > 5 ) 193 | subdivisions = 5; 194 | } 195 | prevRight = input.right; 196 | 197 | if ( input.left && !prevLeft ) 198 | { 199 | subdivisions--; 200 | if ( subdivisions < 0 ) 201 | subdivisions = 0; 202 | } 203 | prevLeft = input.left; 204 | 205 | UpdateTessellation( mesh, mode, subdivisions ); 206 | 207 | ClearScreen( displayWidth, displayHeight ); 208 | 209 | if ( frame > 20 ) 210 | { 211 | const float fov = 25.0f; 212 | glMatrixMode( GL_PROJECTION ); 213 | glLoadIdentity(); 214 | gluPerspective( fov, (float) displayWidth / (float) displayHeight, 0.1f, 100.0f ); 215 | 216 | glMatrixMode( GL_MODELVIEW ); 217 | glLoadIdentity(); 218 | gluLookAt( 0, 0, -5, 219 | 0, 0, 0, 220 | 0, 1, 0 ); 221 | 222 | // set light position 223 | 224 | GLfloat lightPosition0[] = { 250, 1000, -500, 1 }; 225 | GLfloat lightPosition1[] = { -250, 0, -250, 1 }; 226 | GLfloat lightPosition2[] = { 100, 0, -100, 1 }; 227 | GLfloat lightPosition3[] = { 0, +1000, +1000, 1 }; 228 | 229 | glLightfv( GL_LIGHT0, GL_POSITION, lightPosition0 ); 230 | glLightfv( GL_LIGHT1, GL_POSITION, lightPosition1 ); 231 | glLightfv( GL_LIGHT2, GL_POSITION, lightPosition2 ); 232 | glLightfv( GL_LIGHT3, GL_POSITION, lightPosition3 ); 233 | 234 | // render stone 235 | 236 | GLfloat mat_ambient[] = { 0.25, 0.25, 0.25, 1.0 }; 237 | GLfloat mat_diffuse[] = { 0.45, 0.45, 0.45, 1.0 }; 238 | GLfloat mat_specular[] = { 0.1, 0.1, 0.1, 1.0 }; 239 | GLfloat mat_shininess[] = { 100.0 }; 240 | 241 | glMaterialfv( GL_FRONT, GL_AMBIENT, mat_ambient ); 242 | glMaterialfv( GL_FRONT, GL_DIFFUSE, mat_diffuse ); 243 | glMaterialfv( GL_FRONT, GL_SPECULAR, mat_specular ); 244 | glMaterialfv( GL_FRONT, GL_SHININESS, mat_shininess ); 245 | 246 | const float targetRotation = rotating ? 0.28f : 0.0f; 247 | smoothedRotation += ( targetRotation - smoothedRotation ) * 0.15f; 248 | mat4f deltaRotation = mat4f::axisRotation( smoothedRotation, vec3f(-3,-2,1) ); 249 | rotation = rotation * deltaRotation; 250 | mat4f inverseRotation = transpose( rotation ); 251 | 252 | RigidBodyTransform biconvexTransform; 253 | biconvexTransform.Initialize( vec3f(0,0,0), rotation, inverseRotation ); 254 | 255 | glPushMatrix(); 256 | 257 | float opengl_transform[16]; 258 | biconvexTransform.localToWorld.store( opengl_transform ); 259 | glMultMatrixf( opengl_transform ); 260 | 261 | glEnable( GL_LIGHTING ); 262 | 263 | if ( mode == Naive ) 264 | { 265 | float i = pow( subdivisions, 1.5f ); 266 | int numSegments = 15 * i; 267 | int numRings = 1.75f * i + 1; 268 | if ( numSegments < 5 ) 269 | numSegments = 5; 270 | if ( numRings < 1 ) 271 | numRings = 1; 272 | RenderBiconvexNaive( biconvex, numSegments, numRings ); 273 | } 274 | else 275 | RenderMesh( mesh ); 276 | 277 | glPopMatrix(); 278 | } 279 | 280 | // update the display 281 | 282 | UpdateDisplay( 1 ); 283 | 284 | // update time 285 | 286 | frame++; 287 | } 288 | 289 | CloseDisplay(); 290 | 291 | return 0; 292 | } 293 | -------------------------------------------------------------------------------- /Source/stb_image.h: -------------------------------------------------------------------------------- 1 | #define STBI_HEADER_FILE_ONLY 2 | #include "stb_image.c" 3 | -------------------------------------------------------------------------------- /UnitTest++/AssertException.cpp: -------------------------------------------------------------------------------- 1 | #include "AssertException.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | #ifdef _MSC_VER 7 | #pragma warning(disable: 4786) // 'identifier' : identifier was truncated to 'number' characters 8 | #pragma warning(disable: 4996) // disable security warnings about sprintf etc. 9 | #pragma warning(disable: 4800) // forcing value to bool true or false (fuckers) 10 | #endif 11 | 12 | AssertException::AssertException(char const* description, char const* filename, int lineNumber) 13 | : m_lineNumber(lineNumber) 14 | { 15 | using namespace std; 16 | 17 | strcpy(m_description, description); 18 | strcpy(m_filename, filename); 19 | } 20 | 21 | AssertException::~AssertException() throw() 22 | { 23 | } 24 | 25 | char const* AssertException::what() const throw() 26 | { 27 | return m_description; 28 | } 29 | 30 | char const* AssertException::Filename() const 31 | { 32 | return m_filename; 33 | } 34 | 35 | int AssertException::LineNumber() const 36 | { 37 | return m_lineNumber; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /UnitTest++/AssertException.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_ASSERTEXCEPTION_H 2 | #define UNITTEST_ASSERTEXCEPTION_H 3 | 4 | #include 5 | 6 | 7 | namespace UnitTest { 8 | 9 | class AssertException : public std::exception 10 | { 11 | public: 12 | AssertException(char const* description, char const* filename, int lineNumber); 13 | virtual ~AssertException() throw(); 14 | 15 | virtual char const* what() const throw(); 16 | 17 | char const* Filename() const; 18 | int LineNumber() const; 19 | 20 | private: 21 | char m_description[512]; 22 | char m_filename[256]; 23 | int m_lineNumber; 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /UnitTest++/CheckMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CHECKMACROS_H 2 | #define UNITTEST_CHECKMACROS_H 3 | 4 | #include "Checks.h" 5 | #include "AssertException.h" 6 | #include "MemoryOutStream.h" 7 | #include "TestDetails.h" 8 | #include "CurrentTest.h" 9 | 10 | #ifdef CHECK 11 | #error UnitTest++ redefines CHECK 12 | #endif 13 | 14 | #ifdef CHECK_EQUAL 15 | #error UnitTest++ redefines CHECK_EQUAL 16 | #endif 17 | 18 | #ifdef CHECK_CLOSE 19 | #error UnitTest++ redefines CHECK_CLOSE 20 | #endif 21 | 22 | #ifdef CHECK_ARRAY_EQUAL 23 | #error UnitTest++ redefines CHECK_ARRAY_EQUAL 24 | #endif 25 | 26 | #ifdef CHECK_ARRAY_CLOSE 27 | #error UnitTest++ redefines CHECK_ARRAY_CLOSE 28 | #endif 29 | 30 | #ifdef CHECK_ARRAY2D_CLOSE 31 | #error UnitTest++ redefines CHECK_ARRAY2D_CLOSE 32 | #endif 33 | 34 | #define CHECK(value) \ 35 | do \ 36 | { \ 37 | try { \ 38 | if (!UnitTest::Check(value)) \ 39 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), #value); \ 40 | } \ 41 | catch (...) { \ 42 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 43 | "Unhandled exception in CHECK(" #value ")"); \ 44 | } \ 45 | } while (0) 46 | 47 | #define CHECK_EQUAL(expected, actual) \ 48 | do \ 49 | { \ 50 | try { \ 51 | UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 52 | } \ 53 | catch (...) { \ 54 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 55 | "Unhandled exception in CHECK_EQUAL(" #expected ", " #actual ")"); \ 56 | } \ 57 | } while (0) 58 | 59 | #define CHECK_CLOSE(expected, actual, tolerance) \ 60 | do \ 61 | { \ 62 | try { \ 63 | UnitTest::CheckClose(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 64 | } \ 65 | catch (...) { \ 66 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 67 | "Unhandled exception in CHECK_CLOSE(" #expected ", " #actual ")"); \ 68 | } \ 69 | } while (0) 70 | 71 | #define CHECK_ARRAY_EQUAL(expected, actual, count) \ 72 | do \ 73 | { \ 74 | try { \ 75 | UnitTest::CheckArrayEqual(*UnitTest::CurrentTest::Results(), expected, actual, count, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 76 | } \ 77 | catch (...) { \ 78 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 79 | "Unhandled exception in CHECK_ARRAY_EQUAL(" #expected ", " #actual ")"); \ 80 | } \ 81 | } while (0) 82 | 83 | #define CHECK_ARRAY_CLOSE(expected, actual, count, tolerance) \ 84 | do \ 85 | { \ 86 | try { \ 87 | UnitTest::CheckArrayClose(*UnitTest::CurrentTest::Results(), expected, actual, count, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 88 | } \ 89 | catch (...) { \ 90 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 91 | "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ 92 | } \ 93 | } while (0) 94 | 95 | #define CHECK_ARRAY2D_CLOSE(expected, actual, rows, columns, tolerance) \ 96 | do \ 97 | { \ 98 | try { \ 99 | UnitTest::CheckArray2DClose(*UnitTest::CurrentTest::Results(), expected, actual, rows, columns, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ 100 | } \ 101 | catch (...) { \ 102 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ 103 | "Unhandled exception in CHECK_ARRAY_CLOSE(" #expected ", " #actual ")"); \ 104 | } \ 105 | } while (0) 106 | 107 | 108 | #define CHECK_THROW(expression, ExpectedExceptionType) \ 109 | do \ 110 | { \ 111 | bool caught_ = false; \ 112 | try { expression; } \ 113 | catch (ExpectedExceptionType const&) { caught_ = true; } \ 114 | catch (...) {} \ 115 | if (!caught_) \ 116 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "Expected exception: \"" #ExpectedExceptionType "\" not thrown"); \ 117 | } while(0) 118 | 119 | #define CHECK_ASSERT(expression) \ 120 | CHECK_THROW(expression, UnitTest::AssertException); 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /UnitTest++/Checks.cpp: -------------------------------------------------------------------------------- 1 | #include "Checks.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | namespace { 7 | 8 | void CheckStringsEqual(TestResults& results, char const* expected, char const* actual, 9 | TestDetails const& details) 10 | { 11 | using namespace std; 12 | 13 | if (strcmp(expected, actual)) 14 | { 15 | UnitTest::MemoryOutStream stream; 16 | stream << "Expected " << expected << " but was " << actual; 17 | 18 | results.OnTestFailure(details, stream.GetText()); 19 | } 20 | } 21 | 22 | } 23 | 24 | 25 | void CheckEqual(TestResults& results, char const* expected, char const* actual, 26 | TestDetails const& details) 27 | { 28 | CheckStringsEqual(results, expected, actual, details); 29 | } 30 | 31 | void CheckEqual(TestResults& results, char* expected, char* actual, 32 | TestDetails const& details) 33 | { 34 | CheckStringsEqual(results, expected, actual, details); 35 | } 36 | 37 | void CheckEqual(TestResults& results, char* expected, char const* actual, 38 | TestDetails const& details) 39 | { 40 | CheckStringsEqual(results, expected, actual, details); 41 | } 42 | 43 | void CheckEqual(TestResults& results, char const* expected, char* actual, 44 | TestDetails const& details) 45 | { 46 | CheckStringsEqual(results, expected, actual, details); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /UnitTest++/Checks.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CHECKS_H 2 | #define UNITTEST_CHECKS_H 3 | 4 | #include "Config.h" 5 | #include "TestResults.h" 6 | #include "MemoryOutStream.h" 7 | 8 | namespace UnitTest { 9 | 10 | 11 | template< typename Value > 12 | bool Check(Value const value) 13 | { 14 | return !!value; // doing double negative to avoid silly VS warnings 15 | } 16 | 17 | 18 | template< typename Expected, typename Actual > 19 | void CheckEqual(TestResults& results, Expected const& expected, Actual const& actual, TestDetails const& details) 20 | { 21 | if (!(expected == actual)) 22 | { 23 | UnitTest::MemoryOutStream stream; 24 | stream << "Expected " << expected << " but was " << actual; 25 | 26 | results.OnTestFailure(details, stream.GetText()); 27 | } 28 | } 29 | 30 | void CheckEqual(TestResults& results, char const* expected, char const* actual, TestDetails const& details); 31 | 32 | void CheckEqual(TestResults& results, char* expected, char* actual, TestDetails const& details); 33 | 34 | void CheckEqual(TestResults& results, char* expected, char const* actual, TestDetails const& details); 35 | 36 | void CheckEqual(TestResults& results, char const* expected, char* actual, TestDetails const& details); 37 | 38 | template< typename Expected, typename Actual, typename Tolerance > 39 | bool AreClose(Expected const& expected, Actual const& actual, Tolerance const& tolerance) 40 | { 41 | return (actual >= (expected - tolerance)) && (actual <= (expected + tolerance)); 42 | } 43 | 44 | template< typename Expected, typename Actual, typename Tolerance > 45 | void CheckClose(TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance, 46 | TestDetails const& details) 47 | { 48 | if (!AreClose(expected, actual, tolerance)) 49 | { 50 | UnitTest::MemoryOutStream stream; 51 | stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual; 52 | 53 | results.OnTestFailure(details, stream.GetText()); 54 | } 55 | } 56 | 57 | 58 | template< typename Expected, typename Actual > 59 | void CheckArrayEqual(TestResults& results, Expected const& expected, Actual const& actual, 60 | int const count, TestDetails const& details) 61 | { 62 | bool equal = true; 63 | for (int i = 0; i < count; ++i) 64 | equal &= (expected[i] == actual[i]); 65 | 66 | if (!equal) 67 | { 68 | UnitTest::MemoryOutStream stream; 69 | 70 | stream << "Expected [ "; 71 | 72 | for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) 73 | stream << expected[expectedIndex] << " "; 74 | 75 | stream << "] but was [ "; 76 | 77 | for (int actualIndex = 0; actualIndex < count; ++actualIndex) 78 | stream << actual[actualIndex] << " "; 79 | 80 | stream << "]"; 81 | 82 | results.OnTestFailure(details, stream.GetText()); 83 | } 84 | } 85 | 86 | template< typename Expected, typename Actual, typename Tolerance > 87 | bool ArrayAreClose(Expected const& expected, Actual const& actual, int const count, Tolerance const& tolerance) 88 | { 89 | bool equal = true; 90 | for (int i = 0; i < count; ++i) 91 | equal &= AreClose(expected[i], actual[i], tolerance); 92 | return equal; 93 | } 94 | 95 | template< typename Expected, typename Actual, typename Tolerance > 96 | void CheckArrayClose(TestResults& results, Expected const& expected, Actual const& actual, 97 | int const count, Tolerance const& tolerance, TestDetails const& details) 98 | { 99 | bool equal = ArrayAreClose(expected, actual, count, tolerance); 100 | 101 | if (!equal) 102 | { 103 | UnitTest::MemoryOutStream stream; 104 | 105 | stream << "Expected [ "; 106 | for (int expectedIndex = 0; expectedIndex < count; ++expectedIndex) 107 | stream << expected[expectedIndex] << " "; 108 | stream << "] +/- " << tolerance << " but was [ "; 109 | 110 | for (int actualIndex = 0; actualIndex < count; ++actualIndex) 111 | stream << actual[actualIndex] << " "; 112 | stream << "]"; 113 | 114 | results.OnTestFailure(details, stream.GetText()); 115 | } 116 | } 117 | 118 | template< typename Expected, typename Actual, typename Tolerance > 119 | void CheckArray2DClose(TestResults& results, Expected const& expected, Actual const& actual, 120 | int const rows, int const columns, Tolerance const& tolerance, TestDetails const& details) 121 | { 122 | bool equal = true; 123 | for (int i = 0; i < rows; ++i) 124 | equal &= ArrayAreClose(expected[i], actual[i], columns, tolerance); 125 | 126 | if (!equal) 127 | { 128 | UnitTest::MemoryOutStream stream; 129 | 130 | stream << "Expected [ "; 131 | 132 | for (int expectedRow = 0; expectedRow < rows; ++expectedRow) 133 | { 134 | stream << "[ "; 135 | for (int expectedColumn = 0; expectedColumn < columns; ++expectedColumn) 136 | stream << expected[expectedRow][expectedColumn] << " "; 137 | stream << "] "; 138 | } 139 | 140 | stream << "] +/- " << tolerance << " but was [ "; 141 | 142 | for (int actualRow = 0; actualRow < rows; ++actualRow) 143 | { 144 | stream << "[ "; 145 | for (int actualColumn = 0; actualColumn < columns; ++actualColumn) 146 | stream << actual[actualRow][actualColumn] << " "; 147 | stream << "] "; 148 | } 149 | 150 | stream << "]"; 151 | 152 | results.OnTestFailure(details, stream.GetText()); 153 | } 154 | } 155 | 156 | } 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /UnitTest++/Config.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CONFIG_H 2 | #define UNITTEST_CONFIG_H 3 | 4 | // Standard defines documented here: http://predef.sourceforge.net 5 | 6 | #if defined(_MSC_VER) 7 | #pragma warning(disable:4127) // conditional expression is constant 8 | #pragma warning(disable:4702) // unreachable code 9 | #pragma warning(disable:4722) // destructor never returns, potential memory leak 10 | 11 | #if (_MSC_VER == 1200) // VC6 12 | #pragma warning(disable:4786) 13 | #pragma warning(disable:4290) 14 | #endif 15 | #endif 16 | 17 | #if defined(unix) || defined(__unix__) || defined(__unix) || defined(linux) || \ 18 | defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 19 | #define UNITTEST_POSIX 20 | #endif 21 | 22 | #if defined(__MINGW32__) 23 | #define UNITTEST_MINGW 24 | #endif 25 | 26 | // by default, MemoryOutStream is implemented in terms of std::ostringstream, which can be expensive. 27 | // uncomment this line to use the custom MemoryOutStream (no deps on std::ostringstream). 28 | 29 | //#define UNITTEST_USE_CUSTOM_STREAMS 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /UnitTest++/CurrentTest.cpp: -------------------------------------------------------------------------------- 1 | #include "CurrentTest.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | TestResults*& CurrentTest::Results() 7 | { 8 | static TestResults* testResults = NULL; 9 | return testResults; 10 | } 11 | 12 | const TestDetails*& CurrentTest::Details() 13 | { 14 | static const TestDetails* testDetails = NULL; 15 | return testDetails; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /UnitTest++/CurrentTest.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_CURRENTTESTRESULTS_H 2 | #define UNITTEST_CURRENTTESTRESULTS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestResults; 7 | class TestDetails; 8 | 9 | namespace CurrentTest 10 | { 11 | TestResults*& Results(); 12 | const TestDetails*& Details(); 13 | } 14 | 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /UnitTest++/DeferredTestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "DeferredTestReporter.h" 2 | #include "TestDetails.h" 3 | #include "Config.h" 4 | 5 | using namespace UnitTest; 6 | 7 | void DeferredTestReporter::ReportTestStart(TestDetails const& details) 8 | { 9 | m_results.push_back(DeferredTestResult(details.suiteName, details.testName)); 10 | } 11 | 12 | void DeferredTestReporter::ReportFailure(TestDetails const& details, char const* failure) 13 | { 14 | DeferredTestResult& r = m_results.back(); 15 | r.failed = true; 16 | r.failures.push_back(DeferredTestResult::Failure(details.lineNumber, failure)); 17 | r.failureFile = details.filename; 18 | } 19 | 20 | void DeferredTestReporter::ReportTestFinish(TestDetails const&, float secondsElapsed) 21 | { 22 | DeferredTestResult& r = m_results.back(); 23 | r.timeElapsed = secondsElapsed; 24 | } 25 | 26 | DeferredTestReporter::DeferredTestResultList& DeferredTestReporter::GetResults() 27 | { 28 | return m_results; 29 | } 30 | -------------------------------------------------------------------------------- /UnitTest++/DeferredTestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_DEFERREDTESTREPORTER_H 2 | #define UNITTEST_DEFERREDTESTREPORTER_H 3 | 4 | #include "TestReporter.h" 5 | #include "DeferredTestResult.h" 6 | 7 | #include 8 | 9 | namespace UnitTest 10 | { 11 | 12 | class DeferredTestReporter : public TestReporter 13 | { 14 | public: 15 | virtual void ReportTestStart(TestDetails const& details); 16 | virtual void ReportFailure(TestDetails const& details, char const* failure); 17 | virtual void ReportTestFinish(TestDetails const& details, float secondsElapsed); 18 | 19 | typedef std::vector< DeferredTestResult > DeferredTestResultList; 20 | DeferredTestResultList& GetResults(); 21 | 22 | private: 23 | DeferredTestResultList m_results; 24 | }; 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /UnitTest++/DeferredTestResult.cpp: -------------------------------------------------------------------------------- 1 | #include "DeferredTestResult.h" 2 | #include "Config.h" 3 | 4 | namespace UnitTest 5 | { 6 | 7 | DeferredTestResult::DeferredTestResult() 8 | : suiteName("") 9 | , testName("") 10 | , failureFile("") 11 | , timeElapsed(0.0f) 12 | , failed(false) 13 | { 14 | } 15 | 16 | DeferredTestResult::DeferredTestResult(char const* suite, char const* test) 17 | : suiteName(suite) 18 | , testName(test) 19 | , failureFile("") 20 | , timeElapsed(0.0f) 21 | , failed(false) 22 | { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /UnitTest++/DeferredTestResult.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_DEFERREDTESTRESULT_H 2 | #define UNITTEST_DEFERREDTESTRESULT_H 3 | 4 | #include 5 | #include 6 | 7 | namespace UnitTest 8 | { 9 | 10 | struct DeferredTestResult 11 | { 12 | DeferredTestResult(); 13 | DeferredTestResult(char const* suite, char const* test); 14 | 15 | std::string suiteName; 16 | std::string testName; 17 | std::string failureFile; 18 | 19 | typedef std::pair< int, std::string > Failure; 20 | typedef std::vector< Failure > FailureVec; 21 | FailureVec failures; 22 | 23 | float timeElapsed; 24 | bool failed; 25 | }; 26 | 27 | } 28 | 29 | #endif //UNITTEST_DEFERREDTESTRESULT_H 30 | -------------------------------------------------------------------------------- /UnitTest++/ExecuteTest.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_EXECUTE_TEST_H 2 | #define UNITTEST_EXECUTE_TEST_H 3 | 4 | #include "TestDetails.h" 5 | #include "MemoryOutStream.h" 6 | #include "AssertException.h" 7 | #include "CurrentTest.h" 8 | 9 | #ifdef UNITTEST_POSIX 10 | #include "Posix/SignalTranslator.h" 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | template< typename T > 16 | void ExecuteTest(T& testObject, TestDetails const& details) 17 | { 18 | CurrentTest::Details() = &details; 19 | 20 | try 21 | { 22 | #ifdef UNITTEST_POSIX 23 | UNITTEST_THROW_SIGNALS 24 | #endif 25 | testObject.RunImpl(); 26 | } 27 | catch (AssertException const& e) 28 | { 29 | CurrentTest::Results()->OnTestFailure( 30 | TestDetails(details.testName, details.suiteName, e.Filename(), e.LineNumber()), e.what()); 31 | } 32 | catch (std::exception const& e) 33 | { 34 | MemoryOutStream stream; 35 | stream << "Unhandled exception: " << e.what(); 36 | CurrentTest::Results()->OnTestFailure(details, stream.GetText()); 37 | } 38 | catch (...) 39 | { 40 | CurrentTest::Results()->OnTestFailure(details, "Unhandled exception: Crash!"); 41 | } 42 | } 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /UnitTest++/MemoryOutStream.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryOutStream.h" 2 | 3 | #ifndef UNITTEST_USE_CUSTOM_STREAMS 4 | 5 | 6 | namespace UnitTest { 7 | 8 | char const* MemoryOutStream::GetText() const 9 | { 10 | m_text = this->str(); 11 | return m_text.c_str(); 12 | } 13 | 14 | 15 | } 16 | 17 | 18 | #else 19 | 20 | 21 | #include 22 | #include 23 | 24 | namespace UnitTest { 25 | 26 | namespace { 27 | 28 | template 29 | void FormatToStream(MemoryOutStream& stream, char const* format, ValueType const& value) 30 | { 31 | using namespace std; 32 | 33 | char txt[32]; 34 | sprintf(txt, format, value); 35 | stream << txt; 36 | } 37 | 38 | int RoundUpToMultipleOfPow2Number (int n, int pow2Number) 39 | { 40 | return (n + (pow2Number - 1)) & ~(pow2Number - 1); 41 | } 42 | 43 | } 44 | 45 | 46 | MemoryOutStream::MemoryOutStream(int const size) 47 | : m_capacity (0) 48 | , m_buffer (0) 49 | 50 | { 51 | GrowBuffer(size); 52 | } 53 | 54 | MemoryOutStream::~MemoryOutStream() 55 | { 56 | delete [] m_buffer; 57 | } 58 | 59 | char const* MemoryOutStream::GetText() const 60 | { 61 | return m_buffer; 62 | } 63 | 64 | MemoryOutStream& MemoryOutStream::operator << (char const* txt) 65 | { 66 | using namespace std; 67 | 68 | int const bytesLeft = m_capacity - (int)strlen(m_buffer); 69 | int const bytesRequired = (int)strlen(txt) + 1; 70 | 71 | if (bytesRequired > bytesLeft) 72 | { 73 | int const requiredCapacity = bytesRequired + m_capacity - bytesLeft; 74 | GrowBuffer(requiredCapacity); 75 | } 76 | 77 | strcat(m_buffer, txt); 78 | return *this; 79 | } 80 | 81 | MemoryOutStream& MemoryOutStream::operator << (int const n) 82 | { 83 | FormatToStream(*this, "%i", n); 84 | return *this; 85 | } 86 | 87 | MemoryOutStream& MemoryOutStream::operator << (long const n) 88 | { 89 | FormatToStream(*this, "%li", n); 90 | return *this; 91 | } 92 | 93 | MemoryOutStream& MemoryOutStream::operator << (unsigned long const n) 94 | { 95 | FormatToStream(*this, "%lu", n); 96 | return *this; 97 | } 98 | 99 | MemoryOutStream& MemoryOutStream::operator << (float const f) 100 | { 101 | FormatToStream(*this, "%ff", f); 102 | return *this; 103 | } 104 | 105 | MemoryOutStream& MemoryOutStream::operator << (void const* p) 106 | { 107 | FormatToStream(*this, "%p", p); 108 | return *this; 109 | } 110 | 111 | MemoryOutStream& MemoryOutStream::operator << (unsigned int const s) 112 | { 113 | FormatToStream(*this, "%u", s); 114 | return *this; 115 | } 116 | 117 | MemoryOutStream& MemoryOutStream::operator <<(double const d) 118 | { 119 | FormatToStream(*this, "%f", d); 120 | return *this; 121 | } 122 | 123 | int MemoryOutStream::GetCapacity() const 124 | { 125 | return m_capacity; 126 | } 127 | 128 | 129 | void MemoryOutStream::GrowBuffer(int const desiredCapacity) 130 | { 131 | int const newCapacity = RoundUpToMultipleOfPow2Number(desiredCapacity, GROW_CHUNK_SIZE); 132 | 133 | using namespace std; 134 | 135 | char* buffer = new char[newCapacity]; 136 | if (m_buffer) 137 | strcpy(buffer, m_buffer); 138 | else 139 | strcpy(buffer, ""); 140 | 141 | delete [] m_buffer; 142 | m_buffer = buffer; 143 | m_capacity = newCapacity; 144 | } 145 | 146 | } 147 | 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /UnitTest++/MemoryOutStream.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_MEMORYOUTSTREAM_H 2 | #define UNITTEST_MEMORYOUTSTREAM_H 3 | 4 | #include "Config.h" 5 | 6 | #ifndef UNITTEST_USE_CUSTOM_STREAMS 7 | 8 | #include 9 | 10 | namespace UnitTest 11 | { 12 | 13 | class MemoryOutStream : public std::ostringstream 14 | { 15 | public: 16 | MemoryOutStream() {} 17 | char const* GetText() const; 18 | 19 | private: 20 | MemoryOutStream(MemoryOutStream const&); 21 | void operator =(MemoryOutStream const&); 22 | 23 | mutable std::string m_text; 24 | }; 25 | 26 | } 27 | 28 | #else 29 | 30 | #include 31 | 32 | namespace UnitTest 33 | { 34 | 35 | class MemoryOutStream 36 | { 37 | public: 38 | explicit MemoryOutStream(int const size = 256); 39 | ~MemoryOutStream(); 40 | 41 | char const* GetText() const; 42 | 43 | MemoryOutStream& operator << (char const* txt); 44 | MemoryOutStream& operator << (int n); 45 | MemoryOutStream& operator << (long n); 46 | MemoryOutStream& operator << (unsigned long n); 47 | MemoryOutStream& operator << (float f); 48 | MemoryOutStream& operator << (double d); 49 | MemoryOutStream& operator << (void const* p); 50 | MemoryOutStream& operator << (unsigned int s); 51 | 52 | enum { GROW_CHUNK_SIZE = 32 }; 53 | int GetCapacity() const; 54 | 55 | private: 56 | void operator= (MemoryOutStream const&); 57 | void GrowBuffer(int capacity); 58 | 59 | int m_capacity; 60 | char* m_buffer; 61 | }; 62 | 63 | } 64 | 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /UnitTest++/Posix/SignalTranslator.cpp: -------------------------------------------------------------------------------- 1 | #include "SignalTranslator.h" 2 | 3 | namespace UnitTest { 4 | 5 | sigjmp_buf* SignalTranslator::s_jumpTarget = 0; 6 | 7 | namespace { 8 | 9 | void SignalHandler(int sig) 10 | { 11 | siglongjmp(*SignalTranslator::s_jumpTarget, sig ); 12 | } 13 | 14 | } 15 | 16 | 17 | SignalTranslator::SignalTranslator() 18 | { 19 | m_oldJumpTarget = s_jumpTarget; 20 | s_jumpTarget = &m_currentJumpTarget; 21 | 22 | struct sigaction action; 23 | action.sa_flags = 0; 24 | action.sa_handler = SignalHandler; 25 | sigemptyset( &action.sa_mask ); 26 | 27 | sigaction( SIGSEGV, &action, &m_old_SIGSEGV_action ); 28 | sigaction( SIGFPE , &action, &m_old_SIGFPE_action ); 29 | sigaction( SIGTRAP, &action, &m_old_SIGTRAP_action ); 30 | sigaction( SIGBUS , &action, &m_old_SIGBUS_action ); 31 | sigaction( SIGILL , &action, &m_old_SIGBUS_action ); 32 | } 33 | 34 | SignalTranslator::~SignalTranslator() 35 | { 36 | sigaction( SIGILL , &m_old_SIGBUS_action , 0 ); 37 | sigaction( SIGBUS , &m_old_SIGBUS_action , 0 ); 38 | sigaction( SIGTRAP, &m_old_SIGTRAP_action, 0 ); 39 | sigaction( SIGFPE , &m_old_SIGFPE_action , 0 ); 40 | sigaction( SIGSEGV, &m_old_SIGSEGV_action, 0 ); 41 | 42 | s_jumpTarget = m_oldJumpTarget; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /UnitTest++/Posix/SignalTranslator.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_SIGNALTRANSLATOR_H 2 | #define UNITTEST_SIGNALTRANSLATOR_H 3 | 4 | #include 5 | #include 6 | 7 | namespace UnitTest { 8 | 9 | class SignalTranslator 10 | { 11 | public: 12 | SignalTranslator(); 13 | ~SignalTranslator(); 14 | 15 | static sigjmp_buf* s_jumpTarget; 16 | 17 | private: 18 | sigjmp_buf m_currentJumpTarget; 19 | sigjmp_buf* m_oldJumpTarget; 20 | 21 | struct sigaction m_old_SIGFPE_action; 22 | struct sigaction m_old_SIGTRAP_action; 23 | struct sigaction m_old_SIGSEGV_action; 24 | struct sigaction m_old_SIGBUS_action; 25 | struct sigaction m_old_SIGABRT_action; 26 | struct sigaction m_old_SIGALRM_action; 27 | }; 28 | 29 | #if !defined (__GNUC__) 30 | #define UNITTEST_EXTENSION 31 | #else 32 | #define UNITTEST_EXTENSION __extension__ 33 | #endif 34 | 35 | #define UNITTEST_THROW_SIGNALS \ 36 | UnitTest::SignalTranslator sig; \ 37 | if (UNITTEST_EXTENSION sigsetjmp(*UnitTest::SignalTranslator::s_jumpTarget, 1) != 0) \ 38 | throw ("Unhandled system exception"); 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /UnitTest++/Posix/TimeHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeHelpers.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | Timer::Timer() 7 | { 8 | m_startTime.tv_sec = 0; 9 | m_startTime.tv_usec = 0; 10 | } 11 | 12 | void Timer::Start() 13 | { 14 | gettimeofday(&m_startTime, 0); 15 | } 16 | 17 | 18 | int Timer::GetTimeInMs() const 19 | { 20 | struct timeval currentTime; 21 | gettimeofday(¤tTime, 0); 22 | int const dsecs = currentTime.tv_sec - m_startTime.tv_sec; 23 | int const dus = currentTime.tv_usec - m_startTime.tv_usec; 24 | return dsecs*1000 + dus/1000; 25 | } 26 | 27 | 28 | void TimeHelpers::SleepMs (int ms) 29 | { 30 | usleep(ms * 1000); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /UnitTest++/Posix/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMEHELPERS_H 2 | #define UNITTEST_TIMEHELPERS_H 3 | 4 | #include 5 | 6 | namespace UnitTest { 7 | 8 | class Timer 9 | { 10 | public: 11 | Timer(); 12 | void Start(); 13 | int GetTimeInMs() const; 14 | 15 | private: 16 | struct timeval m_startTime; 17 | }; 18 | 19 | 20 | namespace TimeHelpers 21 | { 22 | void SleepMs (int ms); 23 | } 24 | 25 | 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /UnitTest++/ReportAssert.cpp: -------------------------------------------------------------------------------- 1 | #include "AssertException.h" 2 | 3 | namespace UnitTest { 4 | 5 | void ReportAssert(char const* description, char const* filename, int lineNumber) 6 | { 7 | throw AssertException(description, filename, lineNumber); 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /UnitTest++/ReportAssert.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_ASSERT_H 2 | #define UNITTEST_ASSERT_H 3 | 4 | namespace UnitTest { 5 | 6 | void ReportAssert(char const* description, char const* filename, int lineNumber); 7 | 8 | } 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /UnitTest++/Test.cpp: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | #include "Test.h" 3 | #include "TestList.h" 4 | #include "TestResults.h" 5 | #include "AssertException.h" 6 | #include "MemoryOutStream.h" 7 | #include "ExecuteTest.h" 8 | 9 | #ifdef UNITTEST_POSIX 10 | #include "Posix/SignalTranslator.h" 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | TestList& Test::GetTestList() 16 | { 17 | static TestList s_list; 18 | return s_list; 19 | } 20 | 21 | Test::Test(char const* testName, char const* suiteName, char const* filename, int lineNumber) 22 | : m_details(testName, suiteName, filename, lineNumber) 23 | , next(0) 24 | , m_timeConstraintExempt(false) 25 | { 26 | } 27 | 28 | Test::~Test() 29 | { 30 | } 31 | 32 | void Test::Run() 33 | { 34 | ExecuteTest(*this, m_details); 35 | } 36 | 37 | void Test::RunImpl() const 38 | { 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /UnitTest++/Test.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TEST_H 2 | #define UNITTEST_TEST_H 3 | 4 | #include "TestDetails.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestResults; 9 | class TestList; 10 | 11 | class Test 12 | { 13 | public: 14 | explicit Test(char const* testName, char const* suiteName = "DefaultSuite", char const* filename = "", int lineNumber = 0); 15 | virtual ~Test(); 16 | void Run(); 17 | 18 | TestDetails const m_details; 19 | Test* next; 20 | mutable bool m_timeConstraintExempt; 21 | 22 | static TestList& GetTestList(); 23 | 24 | virtual void RunImpl() const; 25 | 26 | private: 27 | Test(Test const&); 28 | Test& operator =(Test const&); 29 | }; 30 | 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /UnitTest++/TestDetails.cpp: -------------------------------------------------------------------------------- 1 | #include "TestDetails.h" 2 | 3 | namespace UnitTest { 4 | 5 | TestDetails::TestDetails(char const* testName_, char const* suiteName_, char const* filename_, int lineNumber_) 6 | : suiteName(suiteName_) 7 | , testName(testName_) 8 | , filename(filename_) 9 | , lineNumber(lineNumber_) 10 | { 11 | } 12 | 13 | TestDetails::TestDetails(const TestDetails& details, int lineNumber_) 14 | : suiteName(details.suiteName) 15 | , testName(details.testName) 16 | , filename(details.filename) 17 | , lineNumber(lineNumber_) 18 | { 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /UnitTest++/TestDetails.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTDETAILS_H 2 | #define UNITTEST_TESTDETAILS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestDetails 7 | { 8 | public: 9 | TestDetails(char const* testName, char const* suiteName, char const* filename, int lineNumber); 10 | TestDetails(const TestDetails& details, int lineNumber); 11 | 12 | char const* const suiteName; 13 | char const* const testName; 14 | char const* const filename; 15 | int const lineNumber; 16 | 17 | TestDetails(TestDetails const&); // Why is it public? --> http://gcc.gnu.org/bugs.html#cxx_rvalbind 18 | private: 19 | TestDetails& operator=(TestDetails const&); 20 | }; 21 | 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /UnitTest++/TestList.cpp: -------------------------------------------------------------------------------- 1 | #include "TestList.h" 2 | #include "Test.h" 3 | 4 | #include 5 | 6 | namespace UnitTest { 7 | 8 | TestList::TestList() 9 | : m_head(0) 10 | , m_tail(0) 11 | { 12 | } 13 | 14 | void TestList::Add(Test* test) 15 | { 16 | if (m_tail == 0) 17 | { 18 | assert(m_head == 0); 19 | m_head = test; 20 | m_tail = test; 21 | } 22 | else 23 | { 24 | m_tail->next = test; 25 | m_tail = test; 26 | } 27 | } 28 | 29 | Test* TestList::GetHead() const 30 | { 31 | return m_head; 32 | } 33 | 34 | ListAdder::ListAdder(TestList& list, Test* test) 35 | { 36 | list.Add(test); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /UnitTest++/TestList.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTLIST_H 2 | #define UNITTEST_TESTLIST_H 3 | 4 | 5 | namespace UnitTest { 6 | 7 | class Test; 8 | 9 | class TestList 10 | { 11 | public: 12 | TestList(); 13 | void Add (Test* test); 14 | 15 | Test* GetHead() const; 16 | 17 | private: 18 | Test* m_head; 19 | Test* m_tail; 20 | }; 21 | 22 | 23 | class ListAdder 24 | { 25 | public: 26 | ListAdder(TestList& list, Test* test); 27 | }; 28 | 29 | } 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /UnitTest++/TestMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTMACROS_H 2 | #define UNITTEST_TESTMACROS_H 3 | 4 | #include "Config.h" 5 | #include "ExecuteTest.h" 6 | #include "AssertException.h" 7 | #include "TestDetails.h" 8 | #include "MemoryOutStream.h" 9 | 10 | #ifndef UNITTEST_POSIX 11 | #define UNITTEST_THROW_SIGNALS 12 | #else 13 | #include "Posix/SignalTranslator.h" 14 | #endif 15 | 16 | #ifdef TEST 17 | #error UnitTest++ redefines TEST 18 | #endif 19 | 20 | #ifdef TEST_EX 21 | #error UnitTest++ redefines TEST_EX 22 | #endif 23 | 24 | #ifdef TEST_FIXTURE_EX 25 | #error UnitTest++ redefines TEST_FIXTURE_EX 26 | #endif 27 | 28 | #define SUITE(Name) \ 29 | namespace Suite##Name { \ 30 | namespace UnitTestSuite { \ 31 | inline char const* GetSuiteName () { \ 32 | return #Name ; \ 33 | } \ 34 | } \ 35 | } \ 36 | namespace Suite##Name 37 | 38 | #define TEST_EX(Name, List) \ 39 | class Test##Name : public UnitTest::Test \ 40 | { \ 41 | public: \ 42 | Test##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ 43 | private: \ 44 | virtual void RunImpl() const; \ 45 | } test##Name##Instance; \ 46 | \ 47 | UnitTest::ListAdder adder##Name (List, &test##Name##Instance); \ 48 | \ 49 | void Test##Name::RunImpl() const 50 | 51 | 52 | #define TEST(Name) TEST_EX(Name, UnitTest::Test::GetTestList()) 53 | 54 | 55 | #define TEST_FIXTURE_EX(Fixture, Name, List) \ 56 | class Fixture##Name##Helper : public Fixture \ 57 | { \ 58 | public: \ 59 | explicit Fixture##Name##Helper(UnitTest::TestDetails const& details) : m_details(details) {} \ 60 | void RunImpl(); \ 61 | UnitTest::TestDetails const& m_details; \ 62 | private: \ 63 | Fixture##Name##Helper(Fixture##Name##Helper const&); \ 64 | Fixture##Name##Helper& operator =(Fixture##Name##Helper const&); \ 65 | }; \ 66 | \ 67 | class Test##Fixture##Name : public UnitTest::Test \ 68 | { \ 69 | public: \ 70 | Test##Fixture##Name() : Test(#Name, UnitTestSuite::GetSuiteName(), __FILE__, __LINE__) {} \ 71 | private: \ 72 | virtual void RunImpl() const; \ 73 | } test##Fixture##Name##Instance; \ 74 | \ 75 | UnitTest::ListAdder adder##Fixture##Name (List, &test##Fixture##Name##Instance); \ 76 | \ 77 | void Test##Fixture##Name::RunImpl() const \ 78 | { \ 79 | bool ctorOk = false; \ 80 | try { \ 81 | Fixture##Name##Helper fixtureHelper(m_details); \ 82 | ctorOk = true; \ 83 | UnitTest::ExecuteTest(fixtureHelper, m_details); \ 84 | } \ 85 | catch (UnitTest::AssertException const& e) \ 86 | { \ 87 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details.testName, m_details.suiteName, e.Filename(), e.LineNumber()), e.what()); \ 88 | } \ 89 | catch (std::exception const& e) \ 90 | { \ 91 | UnitTest::MemoryOutStream stream; \ 92 | stream << "Unhandled exception: " << e.what(); \ 93 | UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText()); \ 94 | } \ 95 | catch (...) { \ 96 | if (ctorOk) \ 97 | { \ 98 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ 99 | "Unhandled exception while destroying fixture " #Fixture); \ 100 | } \ 101 | else \ 102 | { \ 103 | UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(m_details, __LINE__), \ 104 | "Unhandled exception while constructing fixture " #Fixture); \ 105 | } \ 106 | } \ 107 | } \ 108 | void Fixture##Name##Helper::RunImpl() 109 | 110 | #define TEST_FIXTURE(Fixture,Name) TEST_FIXTURE_EX(Fixture, Name, UnitTest::Test::GetTestList()) 111 | 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /UnitTest++/TestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "TestReporter.h" 2 | 3 | namespace UnitTest { 4 | 5 | 6 | TestReporter::~TestReporter() 7 | { 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /UnitTest++/TestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTREPORTER_H 2 | #define UNITTEST_TESTREPORTER_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestDetails; 7 | 8 | class TestReporter 9 | { 10 | public: 11 | virtual ~TestReporter(); 12 | 13 | virtual void ReportTestStart(TestDetails const& test) = 0; 14 | virtual void ReportFailure(TestDetails const& test, char const* failure) = 0; 15 | virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed) = 0; 16 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) = 0; 17 | }; 18 | 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /UnitTest++/TestReporterStdout.cpp: -------------------------------------------------------------------------------- 1 | #include "TestReporterStdout.h" 2 | #include 3 | 4 | #include "TestDetails.h" 5 | 6 | namespace UnitTest { 7 | 8 | void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure) 9 | { 10 | #if defined(__APPLE__) || defined(__GNUG__) 11 | char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n"; 12 | #else 13 | char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n"; 14 | #endif 15 | 16 | using namespace std; 17 | printf(errorFormat, details.filename, details.lineNumber, details.testName, failure); 18 | } 19 | 20 | void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/) 21 | { 22 | } 23 | 24 | void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float) 25 | { 26 | } 27 | 28 | void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount, 29 | int const failureCount, float secondsElapsed) 30 | { 31 | using namespace std; 32 | 33 | if (failureCount > 0) 34 | printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount); 35 | else 36 | printf("Success: %d tests passed.\n", totalTestCount); 37 | 38 | printf("Test time: %.2f seconds.\n", secondsElapsed); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /UnitTest++/TestReporterStdout.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTREPORTERSTDOUT_H 2 | #define UNITTEST_TESTREPORTERSTDOUT_H 3 | 4 | #include "TestReporter.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestReporterStdout : public TestReporter 9 | { 10 | private: 11 | virtual void ReportTestStart(TestDetails const& test); 12 | virtual void ReportFailure(TestDetails const& test, char const* failure); 13 | virtual void ReportTestFinish(TestDetails const& test, float secondsElapsed); 14 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 15 | }; 16 | 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /UnitTest++/TestResults.cpp: -------------------------------------------------------------------------------- 1 | #include "TestResults.h" 2 | #include "TestReporter.h" 3 | 4 | #include "TestDetails.h" 5 | 6 | namespace UnitTest { 7 | 8 | TestResults::TestResults(TestReporter* testReporter) 9 | : m_testReporter(testReporter) 10 | , m_totalTestCount(0) 11 | , m_failedTestCount(0) 12 | , m_failureCount(0) 13 | , m_currentTestFailed(false) 14 | { 15 | } 16 | 17 | void TestResults::OnTestStart(TestDetails const& test) 18 | { 19 | ++m_totalTestCount; 20 | m_currentTestFailed = false; 21 | if (m_testReporter) 22 | m_testReporter->ReportTestStart(test); 23 | } 24 | 25 | void TestResults::OnTestFailure(TestDetails const& test, char const* failure) 26 | { 27 | ++m_failureCount; 28 | if (!m_currentTestFailed) 29 | { 30 | ++m_failedTestCount; 31 | m_currentTestFailed = true; 32 | } 33 | 34 | if (m_testReporter) 35 | m_testReporter->ReportFailure(test, failure); 36 | } 37 | 38 | void TestResults::OnTestFinish(TestDetails const& test, float secondsElapsed) 39 | { 40 | if (m_testReporter) 41 | m_testReporter->ReportTestFinish(test, secondsElapsed); 42 | } 43 | 44 | int TestResults::GetTotalTestCount() const 45 | { 46 | return m_totalTestCount; 47 | } 48 | 49 | int TestResults::GetFailedTestCount() const 50 | { 51 | return m_failedTestCount; 52 | } 53 | 54 | int TestResults::GetFailureCount() const 55 | { 56 | return m_failureCount; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /UnitTest++/TestResults.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTRESULTS_H 2 | #define UNITTEST_TESTRESULTS_H 3 | 4 | namespace UnitTest { 5 | 6 | class TestReporter; 7 | class TestDetails; 8 | 9 | class TestResults 10 | { 11 | public: 12 | explicit TestResults(TestReporter* reporter = 0); 13 | 14 | void OnTestStart(TestDetails const& test); 15 | void OnTestFailure(TestDetails const& test, char const* failure); 16 | void OnTestFinish(TestDetails const& test, float secondsElapsed); 17 | 18 | int GetTotalTestCount() const; 19 | int GetFailedTestCount() const; 20 | int GetFailureCount() const; 21 | 22 | private: 23 | TestReporter* m_testReporter; 24 | int m_totalTestCount; 25 | int m_failedTestCount; 26 | int m_failureCount; 27 | 28 | bool m_currentTestFailed; 29 | 30 | TestResults(TestResults const&); 31 | TestResults& operator =(TestResults const&); 32 | }; 33 | 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /UnitTest++/TestRunner.cpp: -------------------------------------------------------------------------------- 1 | #include "TestRunner.h" 2 | #include "TestResults.h" 3 | #include "TestReporter.h" 4 | #include "TestReporterStdout.h" 5 | #include "TimeHelpers.h" 6 | #include "MemoryOutStream.h" 7 | 8 | #include 9 | 10 | 11 | namespace UnitTest { 12 | 13 | int RunAllTests() 14 | { 15 | TestReporterStdout reporter; 16 | TestRunner runner(reporter); 17 | return runner.RunTestsIf(Test::GetTestList(), NULL, True(), 0); 18 | } 19 | 20 | 21 | TestRunner::TestRunner(TestReporter& reporter) 22 | : m_reporter(&reporter) 23 | , m_result(new TestResults(&reporter)) 24 | , m_timer(new Timer) 25 | { 26 | m_timer->Start(); 27 | } 28 | 29 | TestRunner::~TestRunner() 30 | { 31 | delete m_result; 32 | delete m_timer; 33 | } 34 | 35 | int TestRunner::Finish() const 36 | { 37 | float const secondsElapsed = m_timer->GetTimeInMs() / 1000.0f; 38 | m_reporter->ReportSummary(m_result->GetTotalTestCount(), 39 | m_result->GetFailedTestCount(), 40 | m_result->GetFailureCount(), 41 | secondsElapsed); 42 | 43 | return m_result->GetFailureCount(); 44 | } 45 | 46 | bool TestRunner::IsTestInSuite(const Test* const curTest, char const* suiteName) const 47 | { 48 | using namespace std; 49 | return (suiteName == NULL) || !strcmp(curTest->m_details.suiteName, suiteName); 50 | } 51 | 52 | void TestRunner::RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const 53 | { 54 | CurrentTest::Results() = result; 55 | 56 | Timer testTimer; 57 | testTimer.Start(); 58 | 59 | result->OnTestStart(curTest->m_details); 60 | 61 | curTest->Run(); 62 | 63 | int const testTimeInMs = testTimer.GetTimeInMs(); 64 | if (maxTestTimeInMs > 0 && testTimeInMs > maxTestTimeInMs && !curTest->m_timeConstraintExempt) 65 | { 66 | MemoryOutStream stream; 67 | stream << "Global time constraint failed. Expected under " << maxTestTimeInMs << 68 | "ms but took " << testTimeInMs << "ms."; 69 | 70 | result->OnTestFailure(curTest->m_details, stream.GetText()); 71 | } 72 | 73 | result->OnTestFinish(curTest->m_details, testTimeInMs/1000.0f); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /UnitTest++/TestRunner.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTRUNNER_H 2 | #define UNITTEST_TESTRUNNER_H 3 | 4 | #include "Test.h" 5 | #include "TestList.h" 6 | #include "CurrentTest.h" 7 | 8 | namespace UnitTest { 9 | 10 | class TestReporter; 11 | class TestResults; 12 | class Timer; 13 | 14 | int RunAllTests(); 15 | 16 | struct True 17 | { 18 | bool operator()(const Test* const) const 19 | { 20 | return true; 21 | } 22 | }; 23 | 24 | class TestRunner 25 | { 26 | public: 27 | explicit TestRunner(TestReporter& reporter); 28 | ~TestRunner(); 29 | 30 | template 31 | int RunTestsIf(TestList const& list, char const* suiteName, 32 | const Predicate& predicate, int maxTestTimeInMs) const 33 | { 34 | Test* curTest = list.GetHead(); 35 | 36 | while (curTest != 0) 37 | { 38 | if (IsTestInSuite(curTest,suiteName) && predicate(curTest)) 39 | { 40 | RunTest(m_result, curTest, maxTestTimeInMs); 41 | } 42 | 43 | curTest = curTest->next; 44 | } 45 | 46 | return Finish(); 47 | } 48 | 49 | private: 50 | TestReporter* m_reporter; 51 | TestResults* m_result; 52 | Timer* m_timer; 53 | 54 | int Finish() const; 55 | bool IsTestInSuite(const Test* const curTest, char const* suiteName) const; 56 | void RunTest(TestResults* const result, Test* const curTest, int const maxTestTimeInMs) const; 57 | }; 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /UnitTest++/TestSuite.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TESTSUITE_H 2 | #define UNITTEST_TESTSUITE_H 3 | 4 | namespace UnitTestSuite { 5 | 6 | inline char const* GetSuiteName () 7 | { 8 | return "DefaultSuite"; 9 | } 10 | 11 | } 12 | 13 | #endif 14 | 15 | -------------------------------------------------------------------------------- /UnitTest++/TimeConstraint.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeConstraint.h" 2 | #include "TestResults.h" 3 | #include "MemoryOutStream.h" 4 | #include "CurrentTest.h" 5 | 6 | namespace UnitTest { 7 | 8 | 9 | TimeConstraint::TimeConstraint(int ms, TestDetails const& details) 10 | : m_details(details) 11 | , m_maxMs(ms) 12 | { 13 | m_timer.Start(); 14 | } 15 | 16 | TimeConstraint::~TimeConstraint() 17 | { 18 | int const totalTimeInMs = m_timer.GetTimeInMs(); 19 | if (totalTimeInMs > m_maxMs) 20 | { 21 | MemoryOutStream stream; 22 | stream << "Time constraint failed. Expected to run test under " << m_maxMs << 23 | "ms but took " << totalTimeInMs << "ms."; 24 | 25 | UnitTest::CurrentTest::Results()->OnTestFailure(m_details, stream.GetText()); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /UnitTest++/TimeConstraint.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMECONSTRAINT_H 2 | #define UNITTEST_TIMECONSTRAINT_H 3 | 4 | #include "TimeHelpers.h" 5 | 6 | namespace UnitTest { 7 | 8 | class TestResults; 9 | class TestDetails; 10 | 11 | class TimeConstraint 12 | { 13 | public: 14 | TimeConstraint(int ms, TestDetails const& details); 15 | ~TimeConstraint(); 16 | 17 | private: 18 | void operator=(TimeConstraint const&); 19 | TimeConstraint(TimeConstraint const&); 20 | 21 | Timer m_timer; 22 | TestDetails const& m_details; 23 | int const m_maxMs; 24 | }; 25 | 26 | #define UNITTEST_TIME_CONSTRAINT(ms) \ 27 | UnitTest::TimeConstraint unitTest__timeConstraint__(ms, UnitTest::TestDetails(m_details, __LINE__)) 28 | 29 | #define UNITTEST_TIME_CONSTRAINT_EXEMPT() do { m_timeConstraintExempt = true; } while (0) 30 | 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /UnitTest++/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #include "Config.h" 2 | 3 | #if defined UNITTEST_POSIX 4 | #include "Posix/TimeHelpers.h" 5 | #else 6 | #include "Win32/TimeHelpers.h" 7 | #endif 8 | -------------------------------------------------------------------------------- /UnitTest++/UnitTest++.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTESTCPP_H 2 | #define UNITTESTCPP_H 3 | 4 | //lint -esym(1509,*Fixture) 5 | 6 | #include "Config.h" 7 | #include "Test.h" 8 | #include "TestList.h" 9 | #include "TestSuite.h" 10 | #include "TestResults.h" 11 | 12 | #include "TestMacros.h" 13 | 14 | #include "CheckMacros.h" 15 | #include "TestRunner.h" 16 | #include "TimeConstraint.h" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /UnitTest++/Win32/TimeHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeHelpers.h" 2 | #include 3 | 4 | namespace UnitTest { 5 | 6 | Timer::Timer() 7 | : m_startTime(0) 8 | , m_threadHandle(::GetCurrentThread()) 9 | { 10 | #if defined(_MSC_VER) && (_MSC_VER == 1200) // VC6 doesn't have DWORD_PTR? 11 | typedef unsigned long DWORD_PTR; 12 | #endif 13 | 14 | DWORD_PTR systemMask; 15 | ::GetProcessAffinityMask(GetCurrentProcess(), &m_processAffinityMask, &systemMask); 16 | 17 | ::SetThreadAffinityMask(m_threadHandle, 1); 18 | ::QueryPerformanceFrequency(reinterpret_cast< LARGE_INTEGER* >(&m_frequency)); 19 | ::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask); 20 | } 21 | 22 | void Timer::Start() 23 | { 24 | m_startTime = GetTime(); 25 | } 26 | 27 | int Timer::GetTimeInMs() const 28 | { 29 | __int64 const elapsedTime = GetTime() - m_startTime; 30 | double const seconds = double(elapsedTime) / double(m_frequency); 31 | return int(seconds * 1000.0f); 32 | } 33 | 34 | __int64 Timer::GetTime() const 35 | { 36 | LARGE_INTEGER curTime; 37 | ::SetThreadAffinityMask(m_threadHandle, 1); 38 | ::QueryPerformanceCounter(&curTime); 39 | ::SetThreadAffinityMask(m_threadHandle, m_processAffinityMask); 40 | return curTime.QuadPart; 41 | } 42 | 43 | 44 | 45 | void TimeHelpers::SleepMs(int const ms) 46 | { 47 | ::Sleep(ms); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /UnitTest++/Win32/TimeHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_TIMEHELPERS_H 2 | #define UNITTEST_TIMEHELPERS_H 3 | 4 | #include "../Config.h" 5 | 6 | 7 | #ifdef UNITTEST_MINGW 8 | #ifndef __int64 9 | #define __int64 long long 10 | #endif 11 | #endif 12 | 13 | namespace UnitTest { 14 | 15 | class Timer 16 | { 17 | public: 18 | Timer(); 19 | void Start(); 20 | int GetTimeInMs() const; 21 | 22 | private: 23 | __int64 GetTime() const; 24 | 25 | void* m_threadHandle; 26 | 27 | #if defined(_WIN64) 28 | unsigned __int64 m_processAffinityMask; 29 | #else 30 | unsigned long m_processAffinityMask; 31 | #endif 32 | 33 | __int64 m_startTime; 34 | __int64 m_frequency; 35 | }; 36 | 37 | 38 | namespace TimeHelpers 39 | { 40 | void SleepMs (int ms); 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /UnitTest++/XmlTestReporter.cpp: -------------------------------------------------------------------------------- 1 | #include "XmlTestReporter.h" 2 | #include "Config.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using std::string; 9 | using std::ostringstream; 10 | using std::ostream; 11 | 12 | namespace { 13 | 14 | void ReplaceChar(string& str, char c, string const& replacement) 15 | { 16 | for (size_t pos = str.find(c); pos != string::npos; pos = str.find(c, pos + 1)) 17 | str.replace(pos, 1, replacement); 18 | } 19 | 20 | string XmlEscape(string const& value) 21 | { 22 | string escaped = value; 23 | 24 | ReplaceChar(escaped, '&', "&"); 25 | ReplaceChar(escaped, '<', "<"); 26 | ReplaceChar(escaped, '>', ">"); 27 | ReplaceChar(escaped, '\'', "'"); 28 | ReplaceChar(escaped, '\"', """); 29 | 30 | return escaped; 31 | } 32 | 33 | string BuildFailureMessage(string const& file, int line, string const& message) 34 | { 35 | ostringstream failureMessage; 36 | failureMessage << file << "(" << line << ") : " << message; 37 | return failureMessage.str(); 38 | } 39 | 40 | } 41 | 42 | namespace UnitTest { 43 | 44 | XmlTestReporter::XmlTestReporter(ostream& ostream) 45 | : m_ostream(ostream) 46 | { 47 | } 48 | 49 | void XmlTestReporter::ReportSummary(int totalTestCount, int failedTestCount, 50 | int failureCount, float secondsElapsed) 51 | { 52 | AddXmlElement(m_ostream, NULL); 53 | 54 | BeginResults(m_ostream, totalTestCount, failedTestCount, failureCount, secondsElapsed); 55 | 56 | DeferredTestResultList const& results = GetResults(); 57 | for (DeferredTestResultList::const_iterator i = results.begin(); i != results.end(); ++i) 58 | { 59 | BeginTest(m_ostream, *i); 60 | 61 | if (i->failed) 62 | AddFailure(m_ostream, *i); 63 | 64 | EndTest(m_ostream, *i); 65 | } 66 | 67 | EndResults(m_ostream); 68 | } 69 | 70 | void XmlTestReporter::AddXmlElement(ostream& os, char const* encoding) 71 | { 72 | os << ""; 78 | } 79 | 80 | void XmlTestReporter::BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, 81 | int failureCount, float secondsElapsed) 82 | { 83 | os << ""; 89 | } 90 | 91 | void XmlTestReporter::EndResults(std::ostream& os) 92 | { 93 | os << ""; 94 | } 95 | 96 | void XmlTestReporter::BeginTest(std::ostream& os, DeferredTestResult const& result) 97 | { 98 | os << ""; 108 | else 109 | os << "/>"; 110 | } 111 | 112 | void XmlTestReporter::AddFailure(std::ostream& os, DeferredTestResult const& result) 113 | { 114 | os << ">"; // close element 115 | 116 | for (DeferredTestResult::FailureVec::const_iterator it = result.failures.begin(); 117 | it != result.failures.end(); 118 | ++it) 119 | { 120 | string const escapedMessage = XmlEscape(it->second); 121 | string const message = BuildFailureMessage(result.failureFile, it->first, escapedMessage); 122 | 123 | os << ""; 124 | } 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /UnitTest++/XmlTestReporter.h: -------------------------------------------------------------------------------- 1 | #ifndef UNITTEST_XMLTESTREPORTER_H 2 | #define UNITTEST_XMLTESTREPORTER_H 3 | 4 | #include "DeferredTestReporter.h" 5 | 6 | #include 7 | 8 | namespace UnitTest 9 | { 10 | 11 | class XmlTestReporter : public DeferredTestReporter 12 | { 13 | public: 14 | explicit XmlTestReporter(std::ostream& ostream); 15 | 16 | virtual void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 17 | 18 | private: 19 | XmlTestReporter(XmlTestReporter const&); 20 | XmlTestReporter& operator=(XmlTestReporter const&); 21 | 22 | void AddXmlElement(std::ostream& os, char const* encoding); 23 | void BeginResults(std::ostream& os, int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed); 24 | void EndResults(std::ostream& os); 25 | void BeginTest(std::ostream& os, DeferredTestResult const& result); 26 | void AddFailure(std::ostream& os, DeferredTestResult const& result); 27 | void EndTest(std::ostream& os, DeferredTestResult const& result); 28 | 29 | std::ostream& m_ostream; 30 | }; 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /premake4.lua: -------------------------------------------------------------------------------- 1 | solution "VirtualGo" 2 | language "C++" 3 | includedirs { ".", "Source" } 4 | configurations { "Debug", "Release" } 5 | configuration "Debug" 6 | flags { "Symbols" } 7 | defines { "_DEBUG" } 8 | configuration "Release" 9 | flags { "Optimize" } 10 | defines { "NDEBUG" } 11 | 12 | project "UnitTest++" 13 | kind "StaticLib" 14 | files { "UnitTest++/**.h", "UnitTest++/**.cpp" } 15 | configuration { "windows" } 16 | excludes { "**/Posix/**" } 17 | configuration { "not windows" } 18 | excludes { "**/Win32/**" } 19 | targetdir "lib" 20 | location "build" 21 | 22 | project "Support" 23 | kind "ConsoleApp" 24 | files { "Source/*.h", "Source/Support.cpp", "Source/Platform.cpp" } 25 | configuration { "macosx" } 26 | links { "OpenGL.framework", "AGL.framework", "Carbon.framework" } 27 | 28 | project "Tessellation" 29 | kind "ConsoleApp" 30 | files { "Source/*.h", "Source/Tessellation.cpp", "Source/Platform.cpp" } 31 | configuration { "macosx" } 32 | links { "OpenGL.framework", "AGL.framework", "Carbon.framework" } 33 | 34 | project "Dynamics" 35 | kind "ConsoleApp" 36 | files { "Source/*.h", "Source/Dynamics.cpp", "Source/Platform.cpp" } 37 | configuration { "macosx" } 38 | links { "OpenGL.framework", "AGL.framework", "Carbon.framework" } 39 | 40 | project "Collision" 41 | kind "ConsoleApp" 42 | files { "Source/*.h", "Source/Collision.cpp", "Source/Platform.cpp", "Source/stb_image.c" } 43 | configuration { "macosx" } 44 | links { "OpenGL.framework", "AGL.framework", "Carbon.framework" } 45 | 46 | project "UnitTest" 47 | kind "ConsoleApp" 48 | files { "UnitTest.cpp" } 49 | links { "UnitTest++" } 50 | 51 | if _ACTION == "clean" then 52 | os.rmdir "obj" 53 | os.rmdir "output" 54 | end 55 | 56 | if not os.is "windows" then 57 | 58 | newaction 59 | { 60 | trigger = "support", 61 | description = "Build and run support demo", 62 | valid_kinds = premake.action.get("gmake").valid_kinds, 63 | valid_languages = premake.action.get("gmake").valid_languages, 64 | valid_tools = premake.action.get("gmake").valid_tools, 65 | 66 | execute = function () 67 | os.rmdir "output" 68 | os.mkdir "output" 69 | if os.execute "make -j32 Support" == 0 then 70 | os.execute "./Support" 71 | end 72 | end 73 | } 74 | 75 | newaction 76 | { 77 | trigger = "tessellation", 78 | description = "Build and run tessellation demo", 79 | valid_kinds = premake.action.get("gmake").valid_kinds, 80 | valid_languages = premake.action.get("gmake").valid_languages, 81 | valid_tools = premake.action.get("gmake").valid_tools, 82 | 83 | execute = function () 84 | if os.execute "make -j32 Tessellation" == 0 then 85 | os.execute "./Tessellation" 86 | end 87 | end 88 | } 89 | 90 | newaction 91 | { 92 | trigger = "dynamics", 93 | description = "Build and run dynamics demo", 94 | valid_kinds = premake.action.get("gmake").valid_kinds, 95 | valid_languages = premake.action.get("gmake").valid_languages, 96 | valid_tools = premake.action.get("gmake").valid_tools, 97 | 98 | execute = function () 99 | os.rmdir "output" 100 | os.mkdir "output" 101 | if os.execute "make -j32 Dynamics" == 0 then 102 | os.execute "./Dynamics" 103 | end 104 | end 105 | } 106 | 107 | newaction 108 | { 109 | trigger = "collision", 110 | description = "Build and run collision demo", 111 | valid_kinds = premake.action.get("gmake").valid_kinds, 112 | valid_languages = premake.action.get("gmake").valid_languages, 113 | valid_tools = premake.action.get("gmake").valid_tools, 114 | 115 | execute = function () 116 | os.rmdir "output" 117 | os.mkdir "output" 118 | if os.execute "make -j32 Collision" == 0 then 119 | os.execute "./Collision" 120 | end 121 | end 122 | } 123 | 124 | newaction 125 | { 126 | trigger = "test", 127 | description = "Build and run unit tests", 128 | valid_kinds = premake.action.get("gmake").valid_kinds, 129 | valid_languages = premake.action.get("gmake").valid_languages, 130 | valid_tools = premake.action.get("gmake").valid_tools, 131 | 132 | execute = function () 133 | if os.execute "make -j32 UnitTest" == 0 then 134 | os.execute "./UnitTest" 135 | end 136 | end 137 | } 138 | 139 | end 140 | -------------------------------------------------------------------------------- /vectorial/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_CONFIG_H 7 | #define VECTORIAL_CONFIG_H 8 | 9 | 10 | #ifndef VECTORIAL_FORCED 11 | #if defined(__SSE__) 12 | 13 | #define VECTORIAL_SSE 14 | 15 | #elif defined(__ARM_NEON__) 16 | 17 | #define VECTORIAL_NEON 18 | 19 | // Don't use gnu extension for arm, buggy with some gccs with armv6 and -Os, 20 | // Also doesn't seem perform as well 21 | #elif defined(__GNUC__) && !defined(__arm__) 22 | 23 | #define VECTORIAL_GNU 24 | 25 | #else 26 | 27 | #define VECTORIAL_SCALAR 28 | 29 | #endif 30 | #endif 31 | 32 | 33 | 34 | #ifdef VECTORIAL_SCALAR 35 | #define VECTORIAL_SIMD_TYPE "scalar" 36 | #endif 37 | 38 | #ifdef VECTORIAL_SSE 39 | #define VECTORIAL_SIMD_TYPE "sse" 40 | #endif 41 | 42 | #ifdef VECTORIAL_NEON 43 | #define VECTORIAL_SIMD_TYPE "neon" 44 | #endif 45 | 46 | #ifdef VECTORIAL_GNU 47 | #define VECTORIAL_SIMD_TYPE "gnu" 48 | #endif 49 | 50 | 51 | 52 | #if defined(VECTORIAL_FORCED) && !defined(VECTORIAL_SIMD_TYPE) 53 | #error VECTORIAL_FORCED set but no simd-type found, try f.ex. VECTORIAL_SCALAR 54 | #endif 55 | 56 | 57 | #define vectorial_inline static inline 58 | 59 | #if defined(__GNUC__) 60 | #if defined(__cplusplus) 61 | #define vectorial_restrict __restrict 62 | #endif 63 | #elif defined(_WIN32) 64 | #define vectorial_restrict 65 | #else 66 | #define vectorial_restrict restrict 67 | #endif 68 | // #define vectorial_restrict 69 | 70 | #ifdef __GNUC__ 71 | #define vectorial_pure __attribute__((pure)) 72 | #else 73 | #define vectorial_pure 74 | #endif 75 | 76 | 77 | #ifdef __cplusplus 78 | // Hack around msvc badness 79 | #define SIMD_PARAM(t, p) const t& p 80 | #else 81 | #define SIMD_PARAM(t, p) t p 82 | #endif 83 | 84 | #define VECTORIAL_PI 3.14159265f 85 | #define VECTORIAL_HALFPI 1.57079633f 86 | 87 | 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /vectorial/mat4f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_MAT4F_H 7 | #define VECTORIAL_MAT4F_H 8 | 9 | #ifndef VECTORIAL_SIMD4X4F_H 10 | #include "simd4x4f.h" 11 | #endif 12 | 13 | #ifndef VECTORIAL_VEC4F_H 14 | #include "vectorial/vec4f.h" 15 | #endif 16 | 17 | 18 | namespace vectorial { 19 | 20 | 21 | class mat4f { 22 | public: 23 | 24 | simd4x4f value; 25 | 26 | inline mat4f() {} 27 | inline mat4f(const simd4x4f& v) : value(v) {} 28 | inline mat4f(vec4f v0, vec4f v1, vec4f v2, vec4f v3) : value(simd4x4f_create(v0.value, v1.value, v2.value, v3.value)) {} 29 | 30 | inline void load(const float *ary) { 31 | value.x = simd4f_uload4(ary); 32 | value.y = simd4f_uload4(ary+4); 33 | value.z = simd4f_uload4(ary+8); 34 | value.w = simd4f_uload4(ary+12); 35 | } 36 | 37 | inline void store(float *ary) const { 38 | simd4f_ustore4(value.x, ary); 39 | simd4f_ustore4(value.y, ary+4); 40 | simd4f_ustore4(value.z, ary+8); 41 | simd4f_ustore4(value.w, ary+12); 42 | } 43 | 44 | static mat4f identity() { mat4f m; simd4x4f_identity(&m.value); return m; } 45 | 46 | static mat4f perspective(float fovy, float aspect, float znear, float zfar) { 47 | simd4x4f m; 48 | simd4x4f_perspective(&m, fovy, aspect, znear, zfar); 49 | return m; 50 | } 51 | 52 | static mat4f ortho(float left, float right, float bottom, float top, float znear, float zfar) { 53 | simd4x4f m; 54 | simd4x4f_ortho(&m, left, right, bottom, top, znear, zfar); 55 | return m; 56 | } 57 | 58 | static mat4f lookAt(vec3f eye, vec3f center, vec3f up) { 59 | simd4x4f m; 60 | simd4x4f_lookat(&m, eye.value, center.value, up.value); 61 | return m; 62 | } 63 | 64 | static mat4f translation(vec3f pos) { 65 | simd4x4f m; 66 | simd4x4f_translation(&m, pos.x(), pos.y(), pos.z()); 67 | return m; 68 | } 69 | 70 | static mat4f axisRotation(float angle, vec3f axis) { 71 | simd4x4f m; 72 | simd4x4f_axis_rotation(&m, angle, axis.value); 73 | return m; 74 | } 75 | 76 | }; 77 | 78 | 79 | vectorial_inline mat4f operator*(const mat4f& lhs, const mat4f& rhs) { 80 | mat4f ret; 81 | simd4x4f_matrix_mul(&lhs.value, &rhs.value, &ret.value); 82 | return ret; 83 | } 84 | 85 | vectorial_inline vec4f operator*(const mat4f& lhs, const vec4f& rhs) { 86 | vec4f ret; 87 | simd4x4f_matrix_vector_mul(&lhs.value, &rhs.value, &ret.value); 88 | return ret; 89 | } 90 | 91 | vectorial_inline vec3f transformVector(const mat4f& lhs, const vec3f& rhs) { 92 | vec3f ret; 93 | simd4x4f_matrix_vector3_mul(&lhs.value, &rhs.value, &ret.value); 94 | return ret; 95 | } 96 | 97 | vectorial_inline vec3f transformPoint(const mat4f& lhs, const vec3f& rhs) { 98 | vec3f ret; 99 | simd4x4f_matrix_point3_mul(&lhs.value, &rhs.value, &ret.value); 100 | return ret; 101 | } 102 | 103 | vectorial_inline mat4f transpose(const mat4f& m) { 104 | mat4f ret; 105 | simd4x4f_transpose(&m.value, &ret.value); 106 | return ret; 107 | } 108 | 109 | 110 | 111 | } 112 | 113 | 114 | 115 | #ifdef VECTORIAL_OSTREAM 116 | //#include 117 | 118 | vectorial_inline std::ostream& operator<<(std::ostream& os, const vectorial::mat4f& v) { 119 | 120 | os << "[ "; 121 | os << simd4f_get_x(v.value.x) << ", "; 122 | os << simd4f_get_x(v.value.y) << ", "; 123 | os << simd4f_get_x(v.value.z) << ", "; 124 | os << simd4f_get_x(v.value.w) << " ; "; 125 | 126 | os << simd4f_get_y(v.value.x) << ", "; 127 | os << simd4f_get_y(v.value.y) << ", "; 128 | os << simd4f_get_y(v.value.z) << ", "; 129 | os << simd4f_get_y(v.value.w) << " ; "; 130 | 131 | os << simd4f_get_z(v.value.x) << ", "; 132 | os << simd4f_get_z(v.value.y) << ", "; 133 | os << simd4f_get_z(v.value.z) << ", "; 134 | os << simd4f_get_z(v.value.w) << " ; "; 135 | 136 | os << simd4f_get_w(v.value.x) << ", "; 137 | os << simd4f_get_w(v.value.y) << ", "; 138 | os << simd4f_get_w(v.value.z) << ", "; 139 | os << simd4f_get_w(v.value.w) << " ]"; 140 | 141 | return os; 142 | } 143 | #endif 144 | 145 | 146 | 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /vectorial/simd4f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | 7 | #ifndef VECTORIAL_SIMD4F_H 8 | #define VECTORIAL_SIMD4F_H 9 | 10 | #ifndef VECTORIAL_CONFIG_H 11 | #include "config.h" 12 | #endif 13 | 14 | 15 | #ifdef VECTORIAL_SCALAR 16 | #include "simd4f_scalar.h" 17 | #elif defined(VECTORIAL_SSE) 18 | #include "simd4f_sse.h" 19 | #elif defined(VECTORIAL_GNU) 20 | #include "simd4f_gnu.h" 21 | #elif defined(VECTORIAL_NEON) 22 | #include "simd4f_neon.h" 23 | #else 24 | #error No implementation defined 25 | #endif 26 | 27 | #include "simd4f_common.h" 28 | 29 | 30 | 31 | #ifdef __cplusplus 32 | 33 | #ifdef VECTORIAL_OSTREAM 34 | #include 35 | 36 | vectorial_inline std::ostream& operator<<(std::ostream& os, const simd4f& v) { 37 | os << "simd4f(" << simd4f_get_x(v) << ", " 38 | << simd4f_get_y(v) << ", " 39 | << simd4f_get_z(v) << ", " 40 | << simd4f_get_w(v) << ")"; 41 | return os; 42 | } 43 | #endif 44 | 45 | #endif 46 | 47 | 48 | 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /vectorial/simd4f_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4F_COMMON_H 7 | #define VECTORIAL_SIMD4F_COMMON_H 8 | 9 | 10 | vectorial_inline simd4f simd4f_sum(simd4f v) { 11 | const simd4f s1 = simd4f_add(simd4f_splat_x(v), simd4f_splat_y(v)); 12 | const simd4f s2 = simd4f_add(s1, simd4f_splat_z(v)); 13 | const simd4f s3 = simd4f_add(s2, simd4f_splat_w(v)); 14 | return s3; 15 | } 16 | 17 | vectorial_inline simd4f simd4f_dot4(simd4f lhs, simd4f rhs) { 18 | return simd4f_sum( simd4f_mul(lhs, rhs) ); 19 | } 20 | 21 | vectorial_inline simd4f simd4f_dot3(simd4f lhs, simd4f rhs) { 22 | const simd4f m = simd4f_mul(lhs, rhs); 23 | const simd4f s1 = simd4f_add(simd4f_splat_x(m), simd4f_splat_y(m)); 24 | const simd4f s2 = simd4f_add(s1, simd4f_splat_z(m)); 25 | return s2; 26 | } 27 | 28 | vectorial_inline simd4f simd4f_dot2(simd4f lhs, simd4f rhs) { 29 | const simd4f m = simd4f_mul(lhs, rhs); 30 | const simd4f s1 = simd4f_add(simd4f_splat_x(m), simd4f_splat_y(m)); 31 | return s1; 32 | } 33 | 34 | 35 | vectorial_inline simd4f simd4f_length4(simd4f v) { 36 | return simd4f_sqrt( simd4f_dot4(v,v) ); 37 | } 38 | 39 | vectorial_inline simd4f simd4f_length3(simd4f v) { 40 | return simd4f_sqrt( simd4f_dot3(v,v) ); 41 | } 42 | 43 | vectorial_inline simd4f simd4f_length2(simd4f v) { 44 | return simd4f_sqrt( simd4f_dot2(v,v) ); 45 | } 46 | 47 | vectorial_inline simd4f simd4f_length4_squared(simd4f v) { 48 | return simd4f_dot4(v,v); 49 | } 50 | 51 | vectorial_inline simd4f simd4f_length3_squared(simd4f v) { 52 | return simd4f_dot3(v,v); 53 | } 54 | 55 | vectorial_inline simd4f simd4f_length2_squared(simd4f v) { 56 | return simd4f_dot2(v,v); 57 | } 58 | 59 | 60 | vectorial_inline simd4f simd4f_normalize4(simd4f a) { 61 | simd4f invlen = simd4f_rsqrt( simd4f_dot4(a,a) ); 62 | return simd4f_mul(a, invlen); 63 | } 64 | 65 | vectorial_inline simd4f simd4f_normalize3(simd4f a) { 66 | simd4f invlen = simd4f_rsqrt( simd4f_dot3(a,a) ); 67 | return simd4f_mul(a, invlen); 68 | } 69 | 70 | vectorial_inline simd4f simd4f_normalize2(simd4f a) { 71 | simd4f invlen = simd4f_rsqrt( simd4f_dot2(a,a) ); 72 | return simd4f_mul(a, invlen); 73 | } 74 | 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /vectorial/simd4f_gnu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4F_GNU_H 7 | #define VECTORIAL_SIMD4F_GNU_H 8 | 9 | #include 10 | #include // memcpy 11 | 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | 18 | typedef float simd4f __attribute__ ((vector_size (16))); 19 | 20 | typedef union { 21 | simd4f s ; 22 | float f[4]; 23 | } _simd4f_union; 24 | 25 | vectorial_inline float simd4f_get_x(simd4f s) { _simd4f_union u={s}; return u.f[0]; } 26 | vectorial_inline float simd4f_get_y(simd4f s) { _simd4f_union u={s}; return u.f[1]; } 27 | vectorial_inline float simd4f_get_z(simd4f s) { _simd4f_union u={s}; return u.f[2]; } 28 | vectorial_inline float simd4f_get_w(simd4f s) { _simd4f_union u={s}; return u.f[3]; } 29 | 30 | 31 | vectorial_inline simd4f simd4f_create(float x, float y, float z, float w) { 32 | simd4f s = { x, y, z, w }; 33 | return s; 34 | } 35 | 36 | vectorial_inline simd4f simd4f_zero() { return simd4f_create(0.0f, 0.0f, 0.0f, 0.0f); } 37 | 38 | vectorial_inline simd4f simd4f_uload4(const float *ary) { 39 | simd4f s = { ary[0], ary[1], ary[2], ary[3] }; 40 | return s; 41 | } 42 | 43 | vectorial_inline simd4f simd4f_uload3(const float *ary) { 44 | simd4f s = { ary[0], ary[1], ary[2], 0 }; 45 | return s; 46 | } 47 | 48 | vectorial_inline simd4f simd4f_uload2(const float *ary) { 49 | simd4f s = { ary[0], ary[1], 0, 0 }; 50 | return s; 51 | } 52 | 53 | 54 | vectorial_inline void simd4f_ustore4(const simd4f val, float *ary) { 55 | memcpy(ary, &val, sizeof(float) * 4); 56 | } 57 | 58 | vectorial_inline void simd4f_ustore3(const simd4f val, float *ary) { 59 | memcpy(ary, &val, sizeof(float) * 3); 60 | } 61 | 62 | vectorial_inline void simd4f_ustore2(const simd4f val, float *ary) { 63 | memcpy(ary, &val, sizeof(float) * 2); 64 | } 65 | 66 | 67 | vectorial_inline simd4f simd4f_splat(float v) { 68 | simd4f s = { v, v, v, v }; 69 | return s; 70 | } 71 | 72 | vectorial_inline simd4f simd4f_splat_x(simd4f v) { 73 | float s = simd4f_get_x(v); 74 | simd4f ret = { s, s, s, s }; 75 | return ret; 76 | } 77 | 78 | vectorial_inline simd4f simd4f_splat_y(simd4f v) { 79 | float s = simd4f_get_y(v); 80 | simd4f ret = { s, s, s, s }; 81 | return ret; 82 | } 83 | 84 | vectorial_inline simd4f simd4f_splat_z(simd4f v) { 85 | float s = simd4f_get_z(v); 86 | simd4f ret = { s, s, s, s }; 87 | return ret; 88 | } 89 | 90 | vectorial_inline simd4f simd4f_splat_w(simd4f v) { 91 | float s = simd4f_get_w(v); 92 | simd4f ret = { s, s, s, s }; 93 | return ret; 94 | } 95 | 96 | vectorial_inline simd4f simd4f_reciprocal(simd4f v) { 97 | return simd4f_splat(1.0f) / v; 98 | } 99 | 100 | vectorial_inline simd4f simd4f_sqrt(simd4f v) { 101 | simd4f ret = { sqrtf(simd4f_get_x(v)), sqrtf(simd4f_get_y(v)), sqrtf(simd4f_get_z(v)), sqrtf(simd4f_get_w(v)) }; 102 | return ret; 103 | } 104 | 105 | vectorial_inline simd4f simd4f_rsqrt(simd4f v) { 106 | return simd4f_splat(1.0f) / simd4f_sqrt(v); 107 | } 108 | 109 | 110 | 111 | vectorial_inline simd4f simd4f_add(simd4f lhs, simd4f rhs) { 112 | simd4f ret = lhs + rhs; 113 | return ret; 114 | } 115 | 116 | vectorial_inline simd4f simd4f_sub(simd4f lhs, simd4f rhs) { 117 | simd4f ret = lhs - rhs; 118 | return ret; 119 | } 120 | 121 | vectorial_inline simd4f simd4f_mul(simd4f lhs, simd4f rhs) { 122 | simd4f ret = lhs * rhs; 123 | return ret; 124 | } 125 | 126 | vectorial_inline simd4f simd4f_div(simd4f lhs, simd4f rhs) { 127 | simd4f ret = lhs / rhs; 128 | return ret; 129 | } 130 | 131 | 132 | vectorial_inline simd4f simd4f_cross3(simd4f l, simd4f r) { 133 | _simd4f_union lhs = {l}; 134 | _simd4f_union rhs = {r}; 135 | 136 | return simd4f_create( lhs.f[1] * rhs.f[2] - lhs.f[2] * rhs.f[1], 137 | lhs.f[2] * rhs.f[0] - lhs.f[0] * rhs.f[2], 138 | lhs.f[0] * rhs.f[1] - lhs.f[1] * rhs.f[0], 0); 139 | } 140 | 141 | 142 | 143 | #ifdef __cplusplus 144 | } 145 | #endif 146 | 147 | 148 | #endif 149 | 150 | -------------------------------------------------------------------------------- /vectorial/simd4f_neon.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4F_NEON_H 7 | #define VECTORIAL_SIMD4F_NEON_H 8 | 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | 16 | typedef float32x4_t simd4f; 17 | 18 | typedef union { 19 | simd4f s ; 20 | float f[4]; 21 | } _simd4f_union; 22 | 23 | 24 | 25 | vectorial_inline simd4f simd4f_create(float x, float y, float z, float w) { 26 | const float32_t d[4] = { x,y,z,w }; 27 | simd4f s = vld1q_f32(d); 28 | return s; 29 | } 30 | 31 | vectorial_inline simd4f simd4f_zero() { return vdupq_n_f32(0.0f); } 32 | 33 | vectorial_inline simd4f simd4f_uload4(const float *ary) { 34 | const float32_t* ary32 = (const float32_t*)ary; 35 | simd4f s = vld1q_f32(ary32); 36 | return s; 37 | } 38 | 39 | vectorial_inline simd4f simd4f_uload3(const float *ary) { 40 | simd4f s = simd4f_create(ary[0], ary[1], ary[2], 0); 41 | return s; 42 | } 43 | 44 | vectorial_inline simd4f simd4f_uload2(const float *ary) { 45 | const float32_t* ary32 = (const float32_t*)ary; 46 | float32x2_t low = vld1_f32(ary32); 47 | const float32_t zero = 0; 48 | float32x2_t high = vld1_dup_f32(&zero); // { 0,0 } but stupid warnings from llvm-gcc 49 | return vcombine_f32(low, high); 50 | } 51 | 52 | 53 | vectorial_inline void simd4f_ustore4(const simd4f val, float *ary) { 54 | vst1q_f32( (float32_t*)ary, val); 55 | } 56 | 57 | vectorial_inline void simd4f_ustore3(const simd4f val, float *ary) { 58 | _simd4f_union u = { val }; 59 | ary[0] = u.f[0]; 60 | ary[1] = u.f[1]; 61 | ary[2] = u.f[2]; 62 | } 63 | 64 | vectorial_inline void simd4f_ustore2(const simd4f val, float *ary) { 65 | const float32x2_t low = vget_low_f32(val); 66 | vst1_f32( (float32_t*)ary, low); 67 | } 68 | 69 | 70 | 71 | 72 | vectorial_inline simd4f simd4f_splat(float v) { 73 | simd4f s = vdupq_n_f32(v); 74 | return s; 75 | } 76 | 77 | // todo: or is simd4f_splat(simd4f_get_x(v)) better? 78 | 79 | vectorial_inline simd4f simd4f_splat_x(simd4f v) { 80 | float32x2_t o = vget_low_f32(v); 81 | simd4f ret = vdupq_lane_f32(o, 0); 82 | return ret; 83 | } 84 | 85 | vectorial_inline simd4f simd4f_splat_y(simd4f v) { 86 | float32x2_t o = vget_low_f32(v); 87 | simd4f ret = vdupq_lane_f32(o, 1); 88 | return ret; 89 | } 90 | 91 | vectorial_inline simd4f simd4f_splat_z(simd4f v) { 92 | float32x2_t o = vget_high_f32(v); 93 | simd4f ret = vdupq_lane_f32(o, 0); 94 | return ret; 95 | } 96 | 97 | vectorial_inline simd4f simd4f_splat_w(simd4f v) { 98 | float32x2_t o = vget_high_f32(v); 99 | simd4f ret = vdupq_lane_f32(o, 1); 100 | return ret; 101 | } 102 | 103 | vectorial_inline simd4f simd4f_reciprocal(simd4f v) { 104 | simd4f estimate = vrecpeq_f32(v); 105 | estimate = vmulq_f32(vrecpsq_f32(estimate, v), estimate); 106 | estimate = vmulq_f32(vrecpsq_f32(estimate, v), estimate); 107 | return estimate; 108 | } 109 | 110 | vectorial_inline simd4f simd4f_rsqrt(simd4f v) { 111 | simd4f estimate = vrsqrteq_f32(v); 112 | simd4f estimate2 = vmulq_f32(estimate, v); 113 | estimate = vmulq_f32(estimate, vrsqrtsq_f32(estimate2, estimate)); 114 | estimate2 = vmulq_f32(estimate, v); 115 | estimate = vmulq_f32(estimate, vrsqrtsq_f32(estimate2, estimate)); 116 | estimate2 = vmulq_f32(estimate, v); 117 | estimate = vmulq_f32(estimate, vrsqrtsq_f32(estimate2, estimate)); 118 | return estimate; 119 | } 120 | 121 | vectorial_inline simd4f simd4f_sqrt(simd4f v) { 122 | return simd4f_reciprocal(simd4f_rsqrt(v)); 123 | } 124 | 125 | 126 | 127 | // arithmetics 128 | 129 | vectorial_inline simd4f simd4f_add(simd4f lhs, simd4f rhs) { 130 | simd4f ret = vaddq_f32(lhs, rhs); 131 | return ret; 132 | } 133 | 134 | vectorial_inline simd4f simd4f_sub(simd4f lhs, simd4f rhs) { 135 | simd4f ret = vsubq_f32(lhs, rhs); 136 | return ret; 137 | } 138 | 139 | vectorial_inline simd4f simd4f_mul(simd4f lhs, simd4f rhs) { 140 | simd4f ret = vmulq_f32(lhs, rhs); 141 | return ret; 142 | } 143 | 144 | vectorial_inline simd4f simd4f_div(simd4f lhs, simd4f rhs) { 145 | simd4f recip = simd4f_reciprocal( rhs ); 146 | simd4f ret = vmulq_f32(lhs, recip); 147 | return ret; 148 | } 149 | 150 | 151 | vectorial_inline float simd4f_get_x(simd4f s) { return vgetq_lane_f32(s, 0); } 152 | vectorial_inline float simd4f_get_y(simd4f s) { return vgetq_lane_f32(s, 1); } 153 | vectorial_inline float simd4f_get_z(simd4f s) { return vgetq_lane_f32(s, 2); } 154 | vectorial_inline float simd4f_get_w(simd4f s) { return vgetq_lane_f32(s, 3); } 155 | 156 | 157 | vectorial_inline simd4f simd4f_cross3(simd4f lhs, simd4f rhs) { 158 | 159 | const simd4f lyzx = simd4f_create(simd4f_get_y(lhs), simd4f_get_z(lhs), simd4f_get_x(lhs), simd4f_get_w(lhs)); 160 | const simd4f lzxy = simd4f_create(simd4f_get_z(lhs), simd4f_get_x(lhs), simd4f_get_y(lhs), simd4f_get_w(lhs)); 161 | 162 | const simd4f ryzx = simd4f_create(simd4f_get_y(rhs), simd4f_get_z(rhs), simd4f_get_x(rhs), simd4f_get_w(rhs)); 163 | const simd4f rzxy = simd4f_create(simd4f_get_z(rhs), simd4f_get_x(rhs), simd4f_get_y(rhs), simd4f_get_w(rhs)); 164 | 165 | return vmlsq_f32(vmulq_f32(lyzx, rzxy), lzxy, ryzx); 166 | 167 | } 168 | 169 | 170 | 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | 176 | 177 | #endif 178 | 179 | -------------------------------------------------------------------------------- /vectorial/simd4f_scalar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4F_SCALAR_H 7 | #define VECTORIAL_SIMD4F_SCALAR_H 8 | 9 | #include 10 | #include // memcpy 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | typedef struct { 18 | float x; 19 | float y; 20 | float z; 21 | float w; 22 | } simd4f; 23 | 24 | 25 | 26 | vectorial_inline simd4f simd4f_create(float x, float y, float z, float w) { 27 | simd4f s = { x, y, z, w }; 28 | return s; 29 | } 30 | 31 | vectorial_inline simd4f simd4f_zero() { return simd4f_create(0.0f, 0.0f, 0.0f, 0.0f); } 32 | 33 | vectorial_inline simd4f simd4f_uload4(const float *ary) { 34 | simd4f s = { ary[0], ary[1], ary[2], ary[3] }; 35 | return s; 36 | } 37 | 38 | vectorial_inline simd4f simd4f_uload3(const float *ary) { 39 | simd4f s = { ary[0], ary[1], ary[2], 0 }; 40 | return s; 41 | } 42 | 43 | vectorial_inline simd4f simd4f_uload2(const float *ary) { 44 | simd4f s = { ary[0], ary[1], 0, 0 }; 45 | return s; 46 | } 47 | 48 | 49 | vectorial_inline void simd4f_ustore4(const simd4f val, float *ary) { 50 | memcpy(ary, &val, sizeof(float) * 4); 51 | } 52 | 53 | vectorial_inline void simd4f_ustore3(const simd4f val, float *ary) { 54 | memcpy(ary, &val, sizeof(float) * 3); 55 | } 56 | 57 | vectorial_inline void simd4f_ustore2(const simd4f val, float *ary) { 58 | memcpy(ary, &val, sizeof(float) * 2); 59 | } 60 | 61 | 62 | 63 | // utilities 64 | vectorial_inline simd4f simd4f_splat(float v) { 65 | simd4f s = { v, v, v, v }; 66 | return s; 67 | } 68 | 69 | vectorial_inline simd4f simd4f_splat_x(simd4f v) { 70 | simd4f s = { v.x, v.x, v.x, v.x }; 71 | return s; 72 | } 73 | 74 | vectorial_inline simd4f simd4f_splat_y(simd4f v) { 75 | simd4f s = { v.y, v.y, v.y, v.y }; 76 | return s; 77 | } 78 | 79 | vectorial_inline simd4f simd4f_splat_z(simd4f v) { 80 | simd4f s = { v.z, v.z, v.z, v.z }; 81 | return s; 82 | } 83 | 84 | vectorial_inline simd4f simd4f_splat_w(simd4f v) { 85 | simd4f s = { v.w, v.w, v.w, v.w }; 86 | return s; 87 | } 88 | 89 | vectorial_inline simd4f simd4f_reciprocal(simd4f v) { 90 | simd4f s = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z, 1.0f/v.w }; 91 | return s; 92 | } 93 | 94 | vectorial_inline simd4f simd4f_sqrt(simd4f v) { 95 | simd4f s = { sqrtf(v.x), sqrtf(v.y), sqrtf(v.z), sqrtf(v.w) }; 96 | return s; 97 | } 98 | 99 | vectorial_inline simd4f simd4f_rsqrt(simd4f v) { 100 | simd4f s = { 1.0f/sqrtf(v.x), 1.0f/sqrtf(v.y), 1.0f/sqrtf(v.z), 1.0f/sqrtf(v.w) }; 101 | return s; 102 | } 103 | 104 | 105 | // arithmetic 106 | 107 | vectorial_inline simd4f simd4f_add(simd4f lhs, simd4f rhs) { 108 | simd4f ret = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w }; 109 | return ret; 110 | } 111 | 112 | vectorial_inline simd4f simd4f_sub(simd4f lhs, simd4f rhs) { 113 | simd4f ret = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w }; 114 | return ret; 115 | } 116 | 117 | vectorial_inline simd4f simd4f_mul(simd4f lhs, simd4f rhs) { 118 | simd4f ret = { lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w }; 119 | return ret; 120 | } 121 | 122 | vectorial_inline simd4f simd4f_div(simd4f lhs, simd4f rhs) { 123 | simd4f ret = { lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w }; 124 | return ret; 125 | } 126 | 127 | 128 | vectorial_inline simd4f simd4f_cross3(simd4f lhs, simd4f rhs) { 129 | return simd4f_create( lhs.y * rhs.z - lhs.z * rhs.y, 130 | lhs.z * rhs.x - lhs.x * rhs.z, 131 | lhs.x * rhs.y - lhs.y * rhs.x, 0); 132 | } 133 | 134 | 135 | vectorial_inline float simd4f_get_x(simd4f s) { return s.x; } 136 | vectorial_inline float simd4f_get_y(simd4f s) { return s.y; } 137 | vectorial_inline float simd4f_get_z(simd4f s) { return s.z; } 138 | vectorial_inline float simd4f_get_w(simd4f s) { return s.w; } 139 | 140 | 141 | #ifdef __cplusplus 142 | } 143 | #endif 144 | 145 | 146 | #endif 147 | 148 | -------------------------------------------------------------------------------- /vectorial/simd4f_sse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4F_SSE_H 7 | #define VECTORIAL_SIMD4F_SSE_H 8 | 9 | #include 10 | #include // memcpy 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | 17 | typedef __m128 simd4f; 18 | 19 | typedef union { 20 | simd4f s ; 21 | float f[4]; 22 | } _simd4f_union; 23 | 24 | // creating 25 | 26 | vectorial_inline simd4f simd4f_create(float x, float y, float z, float w) { 27 | simd4f s = { x, y, z, w }; 28 | return s; 29 | } 30 | 31 | vectorial_inline simd4f simd4f_zero() { return _mm_setzero_ps(); } 32 | 33 | vectorial_inline simd4f simd4f_uload4(const float *ary) { 34 | simd4f s = _mm_loadu_ps(ary); 35 | return s; 36 | } 37 | 38 | vectorial_inline simd4f simd4f_uload3(const float *ary) { 39 | simd4f s = simd4f_create(ary[0], ary[1], ary[2], 0); 40 | return s; 41 | } 42 | 43 | vectorial_inline simd4f simd4f_uload2(const float *ary) { 44 | simd4f s = simd4f_create(ary[0], ary[1], 0, 0); 45 | return s; 46 | } 47 | 48 | 49 | vectorial_inline void simd4f_ustore4(const simd4f val, float *ary) { 50 | _mm_storeu_ps(ary, val); 51 | } 52 | 53 | vectorial_inline void simd4f_ustore3(const simd4f val, float *ary) { 54 | memcpy(ary, &val, sizeof(float) * 3); 55 | } 56 | 57 | vectorial_inline void simd4f_ustore2(const simd4f val, float *ary) { 58 | memcpy(ary, &val, sizeof(float) * 2); 59 | } 60 | 61 | 62 | // utilites 63 | 64 | vectorial_inline simd4f simd4f_splat(float v) { 65 | simd4f s = _mm_set1_ps(v); 66 | return s; 67 | } 68 | 69 | vectorial_inline simd4f simd4f_splat_x(simd4f v) { 70 | simd4f s = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0,0,0,0)); 71 | return s; 72 | } 73 | 74 | vectorial_inline simd4f simd4f_splat_y(simd4f v) { 75 | simd4f s = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1,1,1,1)); 76 | return s; 77 | } 78 | 79 | vectorial_inline simd4f simd4f_splat_z(simd4f v) { 80 | simd4f s = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2,2,2,2)); 81 | return s; 82 | } 83 | 84 | vectorial_inline simd4f simd4f_splat_w(simd4f v) { 85 | simd4f s = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3,3,3,3)); 86 | return s; 87 | } 88 | 89 | vectorial_inline simd4f simd4f_reciprocal(simd4f v) { 90 | simd4f s = _mm_rcp_ps(v); 91 | return s; 92 | } 93 | 94 | vectorial_inline simd4f simd4f_sqrt(simd4f v) { 95 | simd4f s = _mm_sqrt_ps(v); 96 | return s; 97 | } 98 | 99 | vectorial_inline simd4f simd4f_rsqrt(simd4f v) { 100 | simd4f s = _mm_rsqrt_ps(v); 101 | return s; 102 | } 103 | 104 | 105 | // arithmetic 106 | 107 | vectorial_inline simd4f simd4f_add(simd4f lhs, simd4f rhs) { 108 | simd4f ret = _mm_add_ps(lhs, rhs); 109 | return ret; 110 | } 111 | 112 | vectorial_inline simd4f simd4f_sub(simd4f lhs, simd4f rhs) { 113 | simd4f ret = _mm_sub_ps(lhs, rhs); 114 | return ret; 115 | } 116 | 117 | vectorial_inline simd4f simd4f_mul(simd4f lhs, simd4f rhs) { 118 | simd4f ret = _mm_mul_ps(lhs, rhs); 119 | return ret; 120 | } 121 | 122 | vectorial_inline simd4f simd4f_div(simd4f lhs, simd4f rhs) { 123 | simd4f ret = _mm_div_ps(lhs, rhs); 124 | return ret; 125 | } 126 | 127 | 128 | vectorial_inline simd4f simd4f_cross3(simd4f lhs, simd4f rhs) { 129 | 130 | const simd4f lyzx = _mm_shuffle_ps(lhs, lhs, _MM_SHUFFLE(3,0,2,1)); 131 | const simd4f lzxy = _mm_shuffle_ps(lhs, lhs, _MM_SHUFFLE(3,1,0,2)); 132 | 133 | const simd4f ryzx = _mm_shuffle_ps(rhs, rhs, _MM_SHUFFLE(3,0,2,1)); 134 | const simd4f rzxy = _mm_shuffle_ps(rhs, rhs, _MM_SHUFFLE(3,1,0,2)); 135 | 136 | return _mm_sub_ps(_mm_mul_ps(lyzx, rzxy), _mm_mul_ps(lzxy, ryzx)); 137 | 138 | } 139 | 140 | 141 | 142 | vectorial_inline float simd4f_get_x(simd4f s) { _simd4f_union u={s}; return u.f[0]; } 143 | vectorial_inline float simd4f_get_y(simd4f s) { _simd4f_union u={s}; return u.f[1]; } 144 | vectorial_inline float simd4f_get_z(simd4f s) { _simd4f_union u={s}; return u.f[2]; } 145 | vectorial_inline float simd4f_get_w(simd4f s) { _simd4f_union u={s}; return u.f[3]; } 146 | 147 | 148 | #ifdef __cplusplus 149 | } 150 | #endif 151 | 152 | 153 | #endif 154 | 155 | -------------------------------------------------------------------------------- /vectorial/simd4x4f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4X4F_H 7 | #define VECTORIAL_SIMD4X4F_H 8 | 9 | 10 | #include "simd4f.h" 11 | 12 | #include 13 | 14 | /* 15 | Note, x,y,z,w are conceptually columns with matrix math. 16 | */ 17 | 18 | typedef struct { 19 | simd4f x,y,z,w; 20 | } simd4x4f; 21 | 22 | 23 | 24 | vectorial_inline simd4x4f simd4x4f_create(simd4f x, simd4f y, simd4f z, SIMD_PARAM(simd4f, w)) { 25 | simd4x4f s = { x, y, z, w }; 26 | return s; 27 | } 28 | 29 | 30 | vectorial_inline void simd4x4f_identity(simd4x4f* m) { 31 | *m = simd4x4f_create( simd4f_create(1.0f, 0.0f, 0.0f, 0.0f), 32 | simd4f_create(0.0f, 1.0f, 0.0f, 0.0f), 33 | simd4f_create(0.0f, 0.0f, 1.0f, 0.0f), 34 | simd4f_create(0.0f, 0.0f, 0.0f, 1.0f)); 35 | } 36 | 37 | 38 | 39 | vectorial_inline void simd4x4f_uload(simd4x4f* m, float *f) { 40 | 41 | m->x = simd4f_uload4(f + 0); 42 | m->y = simd4f_uload4(f + 4); 43 | m->z = simd4f_uload4(f + 8); 44 | m->w = simd4f_uload4(f + 12); 45 | 46 | } 47 | 48 | 49 | 50 | 51 | 52 | #ifdef VECTORIAL_SCALAR 53 | #include "simd4x4f_scalar.h" 54 | #elif defined(VECTORIAL_SSE) 55 | #include "simd4x4f_sse.h" 56 | #elif defined(VECTORIAL_GNU) 57 | #include "simd4x4f_gnu.h" 58 | #elif defined(VECTORIAL_NEON) 59 | #include "simd4x4f_neon.h" 60 | #else 61 | #error No implementation defined 62 | #endif 63 | 64 | vectorial_inline void simd4x4f_sum(const simd4x4f* a, simd4f* out) { 65 | simd4f t; 66 | t = simd4f_add(a->x, a->y); 67 | t = simd4f_add(t, a->z); 68 | t = simd4f_add(t, a->w); 69 | *out = t; 70 | } 71 | 72 | vectorial_inline void simd4x4f_matrix_vector_mul(const simd4x4f* a, const simd4f * b, simd4f* out) { 73 | 74 | simd4x4f bbbb = simd4x4f_create( simd4f_splat_x(*b), 75 | simd4f_splat_y(*b), 76 | simd4f_splat_z(*b), 77 | simd4f_splat_w(*b) ); 78 | 79 | simd4x4f ab = simd4x4f_create( simd4f_mul(a->x, bbbb.x), 80 | simd4f_mul(a->y, bbbb.y), 81 | simd4f_mul(a->z, bbbb.z), 82 | simd4f_mul(a->w, bbbb.w) ); 83 | 84 | simd4x4f_sum(&ab, out); 85 | 86 | } 87 | 88 | vectorial_inline void simd4x4f_matrix_vector3_mul(const simd4x4f* a, const simd4f * b, simd4f* out) { 89 | 90 | *out = simd4f_add( simd4f_add( simd4f_mul(a->x, simd4f_splat_x(*b)), 91 | simd4f_mul(a->y, simd4f_splat_y(*b)) ), 92 | simd4f_mul(a->z, simd4f_splat_z(*b)) ); 93 | 94 | } 95 | 96 | vectorial_inline void simd4x4f_matrix_point3_mul(const simd4x4f* a, const simd4f * b, simd4f* out) { 97 | 98 | *out = simd4f_add( simd4f_add( simd4f_mul(a->x, simd4f_splat_x(*b)), 99 | simd4f_mul(a->y, simd4f_splat_y(*b)) ), 100 | simd4f_add( simd4f_mul(a->z, simd4f_splat_z(*b)), 101 | a->w) ); 102 | 103 | } 104 | 105 | 106 | vectorial_inline void simd4x4f_matrix_mul(const simd4x4f* a, const simd4x4f* b, simd4x4f* out) { 107 | 108 | simd4x4f_matrix_vector_mul(a, &b->x, &out->x); 109 | simd4x4f_matrix_vector_mul(a, &b->y, &out->y); 110 | simd4x4f_matrix_vector_mul(a, &b->z, &out->z); 111 | simd4x4f_matrix_vector_mul(a, &b->w, &out->w); 112 | 113 | } 114 | 115 | 116 | 117 | 118 | vectorial_inline void simd4x4f_perspective(simd4x4f *m, float fovy, float aspect, float znear, float zfar) { 119 | 120 | float radians = fovy * VECTORIAL_HALFPI / 180.0f; 121 | float deltaz = zfar - znear; 122 | float sine = sinf(radians); 123 | float cotangent = cosf(radians) / sine; 124 | 125 | float a = cotangent / aspect; 126 | float b = cotangent; 127 | float c = -(zfar + znear) / deltaz; 128 | float d = -2 * znear * zfar / deltaz; 129 | 130 | m->x = simd4f_create( a, 0, 0, 0); 131 | m->y = simd4f_create( 0, b, 0, 0); 132 | m->z = simd4f_create( 0, 0, c, -1); 133 | m->w = simd4f_create( 0, 0, d, 0); 134 | 135 | } 136 | 137 | vectorial_inline void simd4x4f_ortho(simd4x4f *m, float left, float right, float bottom, float top, float znear, float zfar) { 138 | 139 | float deltax = right - left; 140 | float deltay = top - bottom; 141 | float deltaz = zfar - znear; 142 | 143 | float a = 2.0f / deltax; 144 | float b = -(right + left) / deltax; 145 | float c = 2.0f / deltay; 146 | float d = -(top + bottom) / deltay; 147 | float e = -2.0f / deltaz; 148 | float f = -(zfar + znear) / deltaz; 149 | 150 | m->x = simd4f_create( a, 0, 0, 0); 151 | m->y = simd4f_create( 0, c, 0, 0); 152 | m->z = simd4f_create( 0, 0, e, 0); 153 | m->w = simd4f_create( b, d, f, 1); 154 | 155 | } 156 | 157 | 158 | vectorial_inline void simd4x4f_lookat(simd4x4f *m, simd4f eye, simd4f center, simd4f up) { 159 | 160 | simd4f zaxis = simd4f_normalize3( simd4f_sub(center, eye) ); 161 | simd4f xaxis = simd4f_normalize3( simd4f_cross3( zaxis, up ) ); 162 | simd4f yaxis = simd4f_cross3(xaxis, zaxis); 163 | 164 | zaxis = simd4f_sub( simd4f_zero(), zaxis); 165 | 166 | float x = -simd4f_get_x( simd4f_dot3(xaxis, eye) ); 167 | float y = -simd4f_get_x( simd4f_dot3(yaxis, eye) ); 168 | float z = -simd4f_get_x( simd4f_dot3(zaxis, eye) ); 169 | 170 | m->x = xaxis; 171 | m->y = yaxis; 172 | m->z = zaxis; 173 | 174 | m->w = simd4f_create( 0,0,0, 1); 175 | simd4x4f_transpose_inplace(m); 176 | m->w = simd4f_create( x,y,z,1); 177 | 178 | } 179 | 180 | 181 | vectorial_inline void simd4x4f_translation(simd4x4f* m, float x, float y, float z) { 182 | *m = simd4x4f_create( simd4f_create(1.0f, 0.0f, 0.0f, 0.0f), 183 | simd4f_create(0.0f, 1.0f, 0.0f, 0.0f), 184 | simd4f_create(0.0f, 0.0f, 1.0f, 0.0f), 185 | simd4f_create( x, y, z, 1.0f)); 186 | } 187 | 188 | 189 | vectorial_inline void simd4x4f_axis_rotation(simd4x4f* m, float angle, simd4f axis) { 190 | 191 | angle = -angle; 192 | 193 | axis = simd4f_normalize3(axis); 194 | 195 | const float radians = angle * M_PI / 180; 196 | const float sine = sinf(radians); 197 | const float cosine = cosf(radians); 198 | 199 | const float x = simd4f_get_x(axis); 200 | const float y = simd4f_get_y(axis); 201 | const float z = simd4f_get_z(axis); 202 | 203 | const float ab = x * y * (1 - cosine); 204 | const float bc = y * z * (1 - cosine); 205 | const float ca = z * x * (1 - cosine); 206 | 207 | const float tx = x * x; 208 | const float ty = y * y; 209 | const float tz = z * z; 210 | 211 | const simd4f i = simd4f_create( tx + cosine * (1 - tx), ab - z * sine, ca + y * sine, 0); 212 | const simd4f j = simd4f_create( ab + z * sine, ty + cosine * (1 - ty), bc - x * sine, 0); 213 | const simd4f k = simd4f_create( ca - y * sine, bc + x * sine, tz + cosine * (1 - tz), 0); 214 | 215 | *m = simd4x4f_create( i,j,k, simd4f_create(0, 0, 0, 1) ); 216 | 217 | } 218 | 219 | 220 | 221 | vectorial_inline void simd4x4f_add(simd4x4f* a, simd4x4f* b, simd4x4f* out) { 222 | 223 | out->x = simd4f_add(a->x, b->x); 224 | out->y = simd4f_add(a->y, b->y); 225 | out->z = simd4f_add(a->z, b->z); 226 | out->w = simd4f_add(a->w, b->w); 227 | 228 | } 229 | 230 | vectorial_inline void simd4x4f_sub(simd4x4f* a, simd4x4f* b, simd4x4f* out) { 231 | 232 | out->x = simd4f_sub(a->x, b->x); 233 | out->y = simd4f_sub(a->y, b->y); 234 | out->z = simd4f_sub(a->z, b->z); 235 | out->w = simd4f_sub(a->w, b->w); 236 | 237 | } 238 | 239 | vectorial_inline void simd4x4f_mul(simd4x4f* a, simd4x4f* b, simd4x4f* out) { 240 | 241 | out->x = simd4f_mul(a->x, b->x); 242 | out->y = simd4f_mul(a->y, b->y); 243 | out->z = simd4f_mul(a->z, b->z); 244 | out->w = simd4f_mul(a->w, b->w); 245 | 246 | } 247 | 248 | vectorial_inline void simd4x4f_div(simd4x4f* a, simd4x4f* b, simd4x4f* out) { 249 | 250 | out->x = simd4f_div(a->x, b->x); 251 | out->y = simd4f_div(a->y, b->y); 252 | out->z = simd4f_div(a->z, b->z); 253 | out->w = simd4f_div(a->w, b->w); 254 | 255 | } 256 | 257 | 258 | #ifdef __cplusplus 259 | 260 | #ifdef VECTORIAL_OSTREAM 261 | #include 262 | 263 | vectorial_inline std::ostream& operator<<(std::ostream& os, const simd4x4f& v) { 264 | os << "simd4x4f(simd4f(" << simd4f_get_x(v.x) << ", " 265 | << simd4f_get_y(v.x) << ", " 266 | << simd4f_get_z(v.x) << ", " 267 | << simd4f_get_w(v.x) << "),\n" 268 | << " simd4f(" << simd4f_get_x(v.y) << ", " 269 | << simd4f_get_y(v.y) << ", " 270 | << simd4f_get_z(v.y) << ", " 271 | << simd4f_get_w(v.y) << "),\n" 272 | << " simd4f(" << simd4f_get_x(v.z) << ", " 273 | << simd4f_get_y(v.z) << ", " 274 | << simd4f_get_z(v.z) << ", " 275 | << simd4f_get_w(v.z) << "),\n" 276 | << " simd4f(" << simd4f_get_x(v.w) << ", " 277 | << simd4f_get_y(v.w) << ", " 278 | << simd4f_get_z(v.w) << ", " 279 | << simd4f_get_w(v.w) << "))"; 280 | return os; 281 | } 282 | #endif 283 | 284 | #endif 285 | 286 | 287 | 288 | 289 | 290 | #endif 291 | -------------------------------------------------------------------------------- /vectorial/simd4x4f_gnu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4X4F_GNU_H 7 | #define VECTORIAL_SIMD4X4F_GNU_H 8 | 9 | 10 | 11 | vectorial_inline void simd4x4f_transpose_inplace(simd4x4f* s) { 12 | const _simd4f_union sx = { s->x }; 13 | const _simd4f_union sy = { s->y }; 14 | const _simd4f_union sz = { s->z }; 15 | const _simd4f_union sw = { s->w }; 16 | 17 | const simd4f dx = { sx.f[0], sy.f[0], sz.f[0], sw.f[0] }; 18 | const simd4f dy = { sx.f[1], sy.f[1], sz.f[1], sw.f[1] }; 19 | const simd4f dz = { sx.f[2], sy.f[2], sz.f[2], sw.f[2] }; 20 | const simd4f dw = { sx.f[3], sy.f[3], sz.f[3], sw.f[3] }; 21 | 22 | s->x = dx; 23 | s->y = dy; 24 | s->z = dz; 25 | s->w = dw; 26 | 27 | } 28 | 29 | vectorial_inline void simd4x4f_transpose(const simd4x4f *s, simd4x4f *out) { 30 | *out=*s; 31 | simd4x4f_transpose_inplace(out); 32 | } 33 | 34 | 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /vectorial/simd4x4f_neon.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4X4F_NEON_H 7 | #define VECTORIAL_SIMD4X4F_NEON_H 8 | 9 | 10 | vectorial_inline void simd4x4f_transpose_inplace(simd4x4f* s) { 11 | const _simd4f_union sx = { s->x }; 12 | const _simd4f_union sy = { s->y }; 13 | const _simd4f_union sz = { s->z }; 14 | const _simd4f_union sw = { s->w }; 15 | 16 | const simd4f dx = simd4f_create( sx.f[0], sy.f[0], sz.f[0], sw.f[0] ); 17 | const simd4f dy = simd4f_create( sx.f[1], sy.f[1], sz.f[1], sw.f[1] ); 18 | const simd4f dz = simd4f_create( sx.f[2], sy.f[2], sz.f[2], sw.f[2] ); 19 | const simd4f dw = simd4f_create( sx.f[3], sy.f[3], sz.f[3], sw.f[3] ); 20 | 21 | s->x = dx; 22 | s->y = dy; 23 | s->z = dz; 24 | s->w = dw; 25 | 26 | } 27 | 28 | vectorial_inline void simd4x4f_transpose(const simd4x4f *s, simd4x4f *out) { 29 | *out=*s; 30 | simd4x4f_transpose_inplace(out); 31 | } 32 | 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /vectorial/simd4x4f_scalar.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4X4F_SCALAR_H 7 | #define VECTORIAL_SIMD4X4F_SCALAR_H 8 | 9 | 10 | vectorial_inline void simd4x4f_transpose_inplace(simd4x4f *s) { 11 | simd4x4f d=*s; 12 | s->x.x = d.x.x; 13 | s->x.y = d.y.x; 14 | s->x.z = d.z.x; 15 | s->x.w = d.w.x; 16 | 17 | s->y.x = d.x.y; 18 | s->y.y = d.y.y; 19 | s->y.z = d.z.y; 20 | s->y.w = d.w.y; 21 | 22 | s->z.x = d.x.z; 23 | s->z.y = d.y.z; 24 | s->z.z = d.z.z; 25 | s->z.w = d.w.z; 26 | 27 | s->w.x = d.x.w; 28 | s->w.y = d.y.w; 29 | s->w.z = d.z.w; 30 | s->w.w = d.w.w; 31 | 32 | } 33 | 34 | vectorial_inline void simd4x4f_transpose(const simd4x4f *s, simd4x4f *out) { 35 | *out=*s; 36 | simd4x4f_transpose_inplace(out); 37 | } 38 | 39 | 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /vectorial/simd4x4f_sse.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_SIMD4X4F_SSE_H 7 | #define VECTORIAL_SIMD4X4F_SSE_H 8 | 9 | 10 | 11 | vectorial_inline void simd4x4f_transpose_inplace(simd4x4f *s) { 12 | _MM_TRANSPOSE4_PS(s->x, s->y, s->z, s->w); 13 | } 14 | 15 | vectorial_inline void simd4x4f_transpose(const simd4x4f *s, simd4x4f *out) { 16 | *out=*s; 17 | simd4x4f_transpose_inplace(out); 18 | } 19 | 20 | 21 | 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /vectorial/vec2f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_VEC2F_H 7 | 8 | #ifndef VECTORIAL_SIMD4F_H 9 | #include "simd4f.h" 10 | #endif 11 | 12 | 13 | 14 | namespace vectorial { 15 | 16 | 17 | class vec2f { 18 | public: 19 | 20 | simd4f value; 21 | 22 | inline vec2f() {} 23 | inline vec2f(const vec2f& v) : value(v.value) {} 24 | inline vec2f(const simd4f& v) : value(v) {} 25 | inline vec2f(float x, float y) : value( simd4f_create(x,y,0,0) ) {} 26 | inline vec2f(const float *ary) : value( simd4f_uload2(ary) ) { } 27 | 28 | inline float x() const { return simd4f_get_x(value); } 29 | inline float y() const { return simd4f_get_y(value); } 30 | 31 | inline void load(const float *ary) { value = simd4f_uload2(ary); } 32 | inline void store(float *ary) const { simd4f_ustore2(value, ary); } 33 | 34 | enum { elements = 2 }; 35 | 36 | static vec2f zero() { return vec2f(simd4f_zero()); } 37 | static vec2f one() { return vec2f(1.0f, 1.0f); } 38 | static vec2f xAxis() { return vec2f(1.0f, 0.0f); } 39 | static vec2f yAxis() { return vec2f(0.0f, 1.0f); } 40 | 41 | }; 42 | 43 | vectorial_inline vec2f operator-(const vec2f& lhs) { 44 | return vec2f( simd4f_sub(simd4f_zero(), lhs.value) ); 45 | } 46 | 47 | 48 | vectorial_inline vec2f operator+(const vec2f& lhs, const vec2f& rhs) { 49 | return vec2f( simd4f_add(lhs.value, rhs.value) ); 50 | } 51 | 52 | vectorial_inline vec2f operator-(const vec2f& lhs, const vec2f& rhs) { 53 | return vec2f( simd4f_sub(lhs.value, rhs.value) ); 54 | } 55 | 56 | vectorial_inline vec2f operator*(const vec2f& lhs, const vec2f& rhs) { 57 | return vec2f( simd4f_mul(lhs.value, rhs.value) ); 58 | } 59 | 60 | vectorial_inline vec2f operator/(const vec2f& lhs, const vec2f& rhs) { 61 | return vec2f( simd4f_div(lhs.value, rhs.value) ); 62 | } 63 | 64 | 65 | vectorial_inline vec2f operator+=(vec2f& lhs, const vec2f& rhs) { 66 | return lhs = vec2f( simd4f_add(lhs.value, rhs.value) ); 67 | } 68 | 69 | vectorial_inline vec2f operator-=(vec2f& lhs, const vec2f& rhs) { 70 | return lhs = vec2f( simd4f_sub(lhs.value, rhs.value) ); 71 | } 72 | 73 | vectorial_inline vec2f operator*=(vec2f& lhs, const vec2f& rhs) { 74 | return lhs = vec2f( simd4f_mul(lhs.value, rhs.value) ); 75 | } 76 | 77 | vectorial_inline vec2f operator/=(vec2f& lhs, const vec2f& rhs) { 78 | return lhs = vec2f( simd4f_div(lhs.value, rhs.value) ); 79 | } 80 | 81 | 82 | 83 | vectorial_inline vec2f operator+(const vec2f& lhs, float rhs) { 84 | return vec2f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 85 | } 86 | 87 | vectorial_inline vec2f operator-(const vec2f& lhs, float rhs) { 88 | return vec2f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 89 | } 90 | 91 | vectorial_inline vec2f operator*(const vec2f& lhs, float rhs) { 92 | return vec2f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 93 | } 94 | 95 | vectorial_inline vec2f operator/(const vec2f& lhs, float rhs) { 96 | return vec2f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 97 | } 98 | 99 | vectorial_inline vec2f operator+(float lhs, const vec2f& rhs) { 100 | return vec2f( simd4f_add(simd4f_splat(lhs), rhs.value) ); 101 | } 102 | 103 | vectorial_inline vec2f operator-(float lhs, const vec2f& rhs) { 104 | return vec2f( simd4f_sub(simd4f_splat(lhs), rhs.value) ); 105 | } 106 | 107 | vectorial_inline vec2f operator*(float lhs, const vec2f& rhs) { 108 | return vec2f( simd4f_mul(simd4f_splat(lhs), rhs.value) ); 109 | } 110 | 111 | vectorial_inline vec2f operator/(float lhs, const vec2f& rhs) { 112 | return vec2f( simd4f_div(simd4f_splat(lhs), rhs.value) ); 113 | } 114 | 115 | 116 | vectorial_inline vec2f operator+=(vec2f& lhs, float rhs) { 117 | return lhs = vec2f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 118 | } 119 | 120 | vectorial_inline vec2f operator-=(vec2f& lhs, float rhs) { 121 | return lhs = vec2f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 122 | } 123 | 124 | vectorial_inline vec2f operator*=(vec2f& lhs, float rhs) { 125 | return lhs = vec2f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 126 | } 127 | 128 | vectorial_inline vec2f operator/=(vec2f& lhs, float rhs) { 129 | return lhs = vec2f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 130 | } 131 | 132 | 133 | vectorial_inline float dot(const vec2f& lhs, const vec2f& rhs) { 134 | return simd4f_get_x( simd4f_dot2(lhs.value, rhs.value) ); 135 | } 136 | 137 | 138 | vectorial_inline float length(const vec2f& v) { 139 | return simd4f_get_x( simd4f_length2(v.value) ); 140 | } 141 | 142 | vectorial_inline float length_squared(const vec2f& v) { 143 | return simd4f_get_x( simd4f_length2_squared(v.value) ); 144 | } 145 | 146 | vectorial_inline vec2f normalize(const vec2f& v) { 147 | return vec2f( simd4f_normalize2(v.value) ); 148 | } 149 | 150 | 151 | } 152 | 153 | 154 | 155 | #ifdef VECTORIAL_OSTREAM 156 | #include 157 | 158 | vectorial_inline std::ostream& operator<<(std::ostream& os, const vectorial::vec2f& v) { 159 | os << "[ " << v.x() << ", " 160 | << v.y() << " ]"; 161 | return os; 162 | } 163 | #endif 164 | 165 | 166 | 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /vectorial/vec3f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_VEC3F_H 7 | 8 | #ifndef VECTORIAL_SIMD4F_H 9 | #include "vectorial/simd4f.h" 10 | #endif 11 | 12 | 13 | 14 | namespace vectorial { 15 | 16 | 17 | class vec3f { 18 | public: 19 | 20 | simd4f value; 21 | 22 | inline vec3f() {} 23 | inline vec3f(const vec3f& v) : value(v.value) {} 24 | inline vec3f(const simd4f& v) : value(v) {} 25 | inline vec3f(float x, float y, float z) : value( simd4f_create(x,y,z,0) ) {} 26 | inline vec3f(const float *ary) : value( simd4f_uload3(ary) ) { } 27 | 28 | inline float x() const { return simd4f_get_x(value); } 29 | inline float y() const { return simd4f_get_y(value); } 30 | inline float z() const { return simd4f_get_z(value); } 31 | 32 | inline void load(const float *ary) { value = simd4f_uload3(ary); } 33 | inline void store(float *ary) const { simd4f_ustore3(value, ary); } 34 | 35 | enum { elements = 3 }; 36 | 37 | static vec3f zero() { return vec3f(simd4f_zero()); } 38 | static vec3f one() { return vec3f(1.0f, 1.0f, 1.0f); } 39 | static vec3f xAxis() { return vec3f(1.0f, 0.0f, 0.0f); } 40 | static vec3f yAxis() { return vec3f(0.0f, 1.0f, 0.0f); } 41 | static vec3f zAxis() { return vec3f(0.0f, 0.0f, 1.0f); } 42 | 43 | }; 44 | 45 | vectorial_inline vec3f operator-(const vec3f& lhs) { 46 | return vec3f( simd4f_sub(simd4f_zero(), lhs.value) ); 47 | } 48 | 49 | 50 | vectorial_inline vec3f operator+(const vec3f& lhs, const vec3f& rhs) { 51 | return vec3f( simd4f_add(lhs.value, rhs.value) ); 52 | } 53 | 54 | vectorial_inline vec3f operator-(const vec3f& lhs, const vec3f& rhs) { 55 | return vec3f( simd4f_sub(lhs.value, rhs.value) ); 56 | } 57 | 58 | vectorial_inline vec3f operator*(const vec3f& lhs, const vec3f& rhs) { 59 | return vec3f( simd4f_mul(lhs.value, rhs.value) ); 60 | } 61 | 62 | vectorial_inline vec3f operator/(const vec3f& lhs, const vec3f& rhs) { 63 | return vec3f( simd4f_div(lhs.value, rhs.value) ); 64 | } 65 | 66 | 67 | vectorial_inline vec3f operator+=(vec3f& lhs, const vec3f& rhs) { 68 | return lhs = vec3f( simd4f_add(lhs.value, rhs.value) ); 69 | } 70 | 71 | vectorial_inline vec3f operator-=(vec3f& lhs, const vec3f& rhs) { 72 | return lhs = vec3f( simd4f_sub(lhs.value, rhs.value) ); 73 | } 74 | 75 | vectorial_inline vec3f operator*=(vec3f& lhs, const vec3f& rhs) { 76 | return lhs = vec3f( simd4f_mul(lhs.value, rhs.value) ); 77 | } 78 | 79 | vectorial_inline vec3f operator/=(vec3f& lhs, const vec3f& rhs) { 80 | return lhs = vec3f( simd4f_div(lhs.value, rhs.value) ); 81 | } 82 | 83 | 84 | 85 | vectorial_inline vec3f operator+(const vec3f& lhs, float rhs) { 86 | return vec3f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 87 | } 88 | 89 | vectorial_inline vec3f operator-(const vec3f& lhs, float rhs) { 90 | return vec3f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 91 | } 92 | 93 | vectorial_inline vec3f operator*(const vec3f& lhs, float rhs) { 94 | return vec3f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 95 | } 96 | 97 | vectorial_inline vec3f operator/(const vec3f& lhs, float rhs) { 98 | return vec3f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 99 | } 100 | 101 | vectorial_inline vec3f operator+(float lhs, const vec3f& rhs) { 102 | return vec3f( simd4f_add(simd4f_splat(lhs), rhs.value) ); 103 | } 104 | 105 | vectorial_inline vec3f operator-(float lhs, const vec3f& rhs) { 106 | return vec3f( simd4f_sub(simd4f_splat(lhs), rhs.value) ); 107 | } 108 | 109 | vectorial_inline vec3f operator*(float lhs, const vec3f& rhs) { 110 | return vec3f( simd4f_mul(simd4f_splat(lhs), rhs.value) ); 111 | } 112 | 113 | vectorial_inline vec3f operator/(float lhs, const vec3f& rhs) { 114 | return vec3f( simd4f_div(simd4f_splat(lhs), rhs.value) ); 115 | } 116 | 117 | 118 | vectorial_inline vec3f operator+=(vec3f& lhs, float rhs) { 119 | return lhs = vec3f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 120 | } 121 | 122 | vectorial_inline vec3f operator-=(vec3f& lhs, float rhs) { 123 | return lhs = vec3f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 124 | } 125 | 126 | vectorial_inline vec3f operator*=(vec3f& lhs, float rhs) { 127 | return lhs = vec3f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 128 | } 129 | 130 | vectorial_inline vec3f operator/=(vec3f& lhs, float rhs) { 131 | return lhs = vec3f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 132 | } 133 | 134 | 135 | vectorial_inline float dot(const vec3f& lhs, const vec3f& rhs) { 136 | return simd4f_get_x( simd4f_dot3(lhs.value, rhs.value) ); 137 | } 138 | 139 | vectorial_inline vec3f cross(const vec3f& lhs, const vec3f& rhs) { 140 | return simd4f_cross3(lhs.value, rhs.value); 141 | } 142 | 143 | 144 | vectorial_inline float length(const vec3f& v) { 145 | return simd4f_get_x( simd4f_length3(v.value) ); 146 | } 147 | 148 | vectorial_inline float length_squared(const vec3f& v) { 149 | return simd4f_get_x( simd4f_length3_squared(v.value) ); 150 | } 151 | 152 | vectorial_inline vec3f normalize(const vec3f& v) { 153 | return vec3f( simd4f_normalize3(v.value) ); 154 | } 155 | 156 | 157 | } 158 | 159 | 160 | 161 | #ifdef VECTORIAL_OSTREAM 162 | #include 163 | 164 | vectorial_inline std::ostream& operator<<(std::ostream& os, const vectorial::vec3f& v) { 165 | os << "[ " << v.x() << ", " 166 | << v.y() << ", " 167 | << v.z() << " ]"; 168 | return os; 169 | } 170 | #endif 171 | 172 | 173 | 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /vectorial/vec4f.h: -------------------------------------------------------------------------------- 1 | /* 2 | Vectorial 3 | Copyright (c) 2010 Mikko Lehtonen 4 | Licensed under the terms of the two-clause BSD License (see LICENSE) 5 | */ 6 | #ifndef VECTORIAL_VEC4F_H 7 | #define VECTORIAL_VEC4F_H 8 | 9 | #ifndef VECTORIAL_SIMD4F_H 10 | #include "vectorial/simd4f.h" 11 | #endif 12 | 13 | 14 | 15 | namespace vectorial { 16 | 17 | 18 | class vec4f { 19 | public: 20 | 21 | simd4f value; 22 | 23 | inline vec4f() {} 24 | inline vec4f(const vec4f& v) : value(v.value) {} 25 | inline vec4f(const simd4f& v) : value(v) {} 26 | inline vec4f(float x, float y, float z, float w) : value( simd4f_create(x,y,z,w) ) {} 27 | inline vec4f(const float *ary) : value( simd4f_uload4(ary) ) { } 28 | 29 | inline float x() const { return simd4f_get_x(value); } 30 | inline float y() const { return simd4f_get_y(value); } 31 | inline float z() const { return simd4f_get_z(value); } 32 | inline float w() const { return simd4f_get_w(value); } 33 | 34 | inline void load(const float *ary) { value = simd4f_uload4(ary); } 35 | inline void store(float *ary) const { simd4f_ustore4(value, ary); } 36 | 37 | enum { elements = 4 }; 38 | 39 | 40 | static vec4f zero() { return vec4f(simd4f_zero()); } 41 | static vec4f one() { return vec4f(1.0f, 1.0f, 1.0f, 1.0f); } 42 | static vec4f xAxis() { return vec4f(1.0f, 0.0f, 0.0f, 0.0f); } 43 | static vec4f yAxis() { return vec4f(0.0f, 1.0f, 0.0f, 0.0f); } 44 | static vec4f zAxis() { return vec4f(0.0f, 0.0f, 1.0f, 0.0f); } 45 | static vec4f wAxis() { return vec4f(0.0f, 0.0f, 0.0f, 1.0f); } 46 | 47 | }; 48 | 49 | 50 | vectorial_inline vec4f operator-(const vec4f& lhs) { 51 | return vec4f( simd4f_sub(simd4f_zero(), lhs.value) ); 52 | } 53 | 54 | 55 | vectorial_inline vec4f operator+(const vec4f& lhs, const vec4f& rhs) { 56 | return vec4f( simd4f_add(lhs.value, rhs.value) ); 57 | } 58 | 59 | vectorial_inline vec4f operator-(const vec4f& lhs, const vec4f& rhs) { 60 | return vec4f( simd4f_sub(lhs.value, rhs.value) ); 61 | } 62 | 63 | vectorial_inline vec4f operator*(const vec4f& lhs, const vec4f& rhs) { 64 | return vec4f( simd4f_mul(lhs.value, rhs.value) ); 65 | } 66 | 67 | vectorial_inline vec4f operator/(const vec4f& lhs, const vec4f& rhs) { 68 | return vec4f( simd4f_div(lhs.value, rhs.value) ); 69 | } 70 | 71 | 72 | vectorial_inline vec4f operator+=(vec4f& lhs, const vec4f& rhs) { 73 | return lhs = vec4f( simd4f_add(lhs.value, rhs.value) ); 74 | } 75 | 76 | vectorial_inline vec4f operator-=(vec4f& lhs, const vec4f& rhs) { 77 | return lhs = vec4f( simd4f_sub(lhs.value, rhs.value) ); 78 | } 79 | 80 | vectorial_inline vec4f operator*=(vec4f& lhs, const vec4f& rhs) { 81 | return lhs = vec4f( simd4f_mul(lhs.value, rhs.value) ); 82 | } 83 | 84 | vectorial_inline vec4f operator/=(vec4f& lhs, const vec4f& rhs) { 85 | return lhs = vec4f( simd4f_div(lhs.value, rhs.value) ); 86 | } 87 | 88 | 89 | 90 | vectorial_inline vec4f operator+(const vec4f& lhs, float rhs) { 91 | return vec4f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 92 | } 93 | 94 | vectorial_inline vec4f operator-(const vec4f& lhs, float rhs) { 95 | return vec4f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 96 | } 97 | 98 | vectorial_inline vec4f operator*(const vec4f& lhs, float rhs) { 99 | return vec4f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 100 | } 101 | 102 | vectorial_inline vec4f operator/(const vec4f& lhs, float rhs) { 103 | return vec4f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 104 | } 105 | 106 | vectorial_inline vec4f operator+(float lhs, const vec4f& rhs) { 107 | return vec4f( simd4f_add(simd4f_splat(lhs), rhs.value) ); 108 | } 109 | 110 | vectorial_inline vec4f operator-(float lhs, const vec4f& rhs) { 111 | return vec4f( simd4f_sub(simd4f_splat(lhs), rhs.value) ); 112 | } 113 | 114 | vectorial_inline vec4f operator*(float lhs, const vec4f& rhs) { 115 | return vec4f( simd4f_mul(simd4f_splat(lhs), rhs.value) ); 116 | } 117 | 118 | vectorial_inline vec4f operator/(float lhs, const vec4f& rhs) { 119 | return vec4f( simd4f_div(simd4f_splat(lhs), rhs.value) ); 120 | } 121 | 122 | 123 | vectorial_inline vec4f operator+=(vec4f& lhs, float rhs) { 124 | return lhs = vec4f( simd4f_add(lhs.value, simd4f_splat(rhs)) ); 125 | } 126 | 127 | vectorial_inline vec4f operator-=(vec4f& lhs, float rhs) { 128 | return lhs = vec4f( simd4f_sub(lhs.value, simd4f_splat(rhs)) ); 129 | } 130 | 131 | vectorial_inline vec4f operator*=(vec4f& lhs, float rhs) { 132 | return lhs = vec4f( simd4f_mul(lhs.value, simd4f_splat(rhs)) ); 133 | } 134 | 135 | vectorial_inline vec4f operator/=(vec4f& lhs, float rhs) { 136 | return lhs = vec4f( simd4f_div(lhs.value, simd4f_splat(rhs)) ); 137 | } 138 | 139 | 140 | vectorial_inline float dot(const vec4f& lhs, const vec4f& rhs) { 141 | return simd4f_get_x( simd4f_dot4(lhs.value, rhs.value) ); 142 | } 143 | 144 | 145 | vectorial_inline float length(const vec4f& v) { 146 | return simd4f_get_x( simd4f_length4(v.value) ); 147 | } 148 | 149 | vectorial_inline float length_squared(const vec4f& v) { 150 | return simd4f_get_x( simd4f_length4_squared(v.value) ); 151 | } 152 | 153 | vectorial_inline vec4f normalize(const vec4f& v) { 154 | return vec4f( simd4f_normalize4(v.value) ); 155 | } 156 | 157 | 158 | } 159 | 160 | 161 | 162 | #ifdef VECTORIAL_OSTREAM 163 | //#include 164 | 165 | vectorial_inline std::ostream& operator<<(std::ostream& os, const vectorial::vec4f& v) { 166 | os << "[ " << v.x() << ", " 167 | << v.y() << ", " 168 | << v.z() << ", " 169 | << v.w() << " ]"; 170 | return os; 171 | } 172 | #endif 173 | 174 | 175 | 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /xcode/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /xcode/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /xcode/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /xcode/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/project.xcworkspace/xcuserdata/gaffer.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go.xcodeproj/project.xcworkspace/xcuserdata/gaffer.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/project.xcworkspace/xcuserdata/gaffer.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | SnapshotAutomaticallyBeforeSignificantChanges 16 | 17 | SnapshotLocationStyle 18 | Default 19 | 20 | 21 | -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/xcuserdata/gaffer.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/xcuserdata/gaffer.xcuserdatad/xcschemes/Virtual Go.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /xcode/Virtual Go.xcodeproj/xcuserdata/gaffer.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Virtual Go.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | F26653EA171A205400CFB131 16 | 17 | primary 18 | 19 | 20 | F266541B171A205500CFB131 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /xcode/Virtual Go/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /xcode/Virtual Go/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "testflight/TestFlight.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | [TestFlight takeOff:@"39573e86-9e45-400c-a6aa-4fa932d5890e"]; 17 | return YES; 18 | } 19 | 20 | - (void)applicationWillResignActive:(UIApplication *)application 21 | { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | - (void)applicationDidEnterBackground:(UIApplication *)application 27 | { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | - (void)applicationWillEnterForeground:(UIApplication *)application 33 | { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application 38 | { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | - (void)applicationWillTerminate:(UIApplication *)application 43 | { 44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/Default-568h@2x.png -------------------------------------------------------------------------------- /xcode/Virtual Go/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/Default.png -------------------------------------------------------------------------------- /xcode/Virtual Go/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/Default@2x.png -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/BoardShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // BoardShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | uniform sampler2D uniformTexture; 10 | 11 | varying lowp vec4 colorVarying; 12 | varying lowp vec2 texCoordsVarying; 13 | 14 | void main() 15 | { 16 | gl_FragColor = colorVarying * texture2D( uniformTexture, texCoordsVarying ); 17 | } 18 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/BoardShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // BoardShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec3 normal; 11 | attribute vec2 texCoords; 12 | 13 | varying lowp vec4 colorVarying; 14 | varying lowp vec2 texCoordsVarying; 15 | 16 | uniform mat4 modelViewProjectionMatrix; 17 | uniform mat3 normalMatrix; 18 | uniform vec3 lightPosition; 19 | 20 | void main() 21 | { 22 | vec3 eyeNormal = normalMatrix * normal; 23 | vec4 diffuseColor = vec4( 0.5, 0.5, 0.5, 1.0 ); 24 | vec4 ambientColor = vec4( 0.5, 0.5, 0.5, 1.0 ); 25 | 26 | float nDotVP = max( 0.0, dot( eyeNormal, normalize( lightPosition ) ) ); 27 | 28 | colorVarying = ambientColor + diffuseColor * nDotVP; 29 | 30 | texCoordsVarying = texCoords; 31 | 32 | gl_Position = modelViewProjectionMatrix * position; 33 | } 34 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/FloorShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // FloorShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | uniform sampler2D uniformTexture; 10 | 11 | varying lowp vec4 colorVarying; 12 | varying lowp vec2 texCoordsVarying; 13 | 14 | void main() 15 | { 16 | gl_FragColor = colorVarying * texture2D( uniformTexture, texCoordsVarying ); 17 | } 18 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/FloorShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // FloorShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec3 normal; 11 | attribute vec2 texCoords; 12 | 13 | varying lowp vec4 colorVarying; 14 | varying vec2 texCoordsVarying; 15 | 16 | uniform mat4 modelViewProjectionMatrix; 17 | uniform mat3 normalMatrix; 18 | uniform vec3 lightPosition; 19 | 20 | void main() 21 | { 22 | colorVarying = vec4( 1.0, 1.0, 1.0, 1.0 ); 23 | texCoordsVarying = texCoords; 24 | gl_Position = modelViewProjectionMatrix * position; 25 | } 26 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/GridShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // GridShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | uniform sampler2D uniformTexture; 10 | 11 | varying lowp vec2 texCoordsVarying; 12 | 13 | void main() 14 | { 15 | gl_FragColor = texture2D( uniformTexture, texCoordsVarying ); 16 | } 17 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/GridShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // GridShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec2 texCoords; 11 | 12 | varying lowp vec2 texCoordsVarying; 13 | 14 | uniform mat4 modelViewProjectionMatrix; 15 | 16 | void main() 17 | { 18 | texCoordsVarying = texCoords; 19 | gl_Position = modelViewProjectionMatrix * position; 20 | } 21 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/PointShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // PointShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | uniform sampler2D uniformTexture; 10 | 11 | varying lowp vec2 texCoordsVarying; 12 | 13 | void main() 14 | { 15 | gl_FragColor = texture2D( uniformTexture, texCoordsVarying ); 16 | } 17 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/PointShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // PointShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec2 texCoords; 11 | 12 | varying lowp vec2 texCoordsVarying; 13 | 14 | uniform mat4 modelViewProjectionMatrix; 15 | 16 | void main() 17 | { 18 | texCoordsVarying = texCoords; 19 | gl_Position = modelViewProjectionMatrix * position; 20 | } 21 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/ShadowShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // ShadowShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | varying lowp vec4 colorVarying; 10 | 11 | void main() 12 | { 13 | gl_FragColor = colorVarying; 14 | } 15 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/ShadowShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // ShadowShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec3 normal; 11 | attribute vec2 texCoords; 12 | 13 | varying lowp vec4 colorVarying; 14 | 15 | uniform mat4 modelViewProjectionMatrix; 16 | uniform mat3 normalMatrix; 17 | uniform vec3 lightPosition; 18 | uniform float alpha; 19 | 20 | void main() 21 | { 22 | colorVarying = vec4( 0, 0, 0, 0.25 * alpha ); 23 | 24 | gl_Position = modelViewProjectionMatrix * position; 25 | } 26 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/StoneShader.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // StoneShader.fsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | varying lowp vec4 colorVarying; 10 | 11 | void main() 12 | { 13 | gl_FragColor = colorVarying; 14 | } 15 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Shaders/StoneShader.vertex: -------------------------------------------------------------------------------- 1 | // 2 | // StoneShader.vsh 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | attribute vec4 position; 10 | attribute vec3 normal; 11 | attribute vec2 texCoords; 12 | 13 | varying lowp vec4 colorVarying; 14 | 15 | uniform mat4 modelViewProjectionMatrix; 16 | uniform mat3 normalMatrix; 17 | uniform vec3 lightPosition; 18 | 19 | void main() 20 | { 21 | vec3 eyeNormal = normalMatrix * normal; 22 | 23 | vec4 diffuseColor = vec4( 0.5, 0.5, 0.5, 1.0 ); 24 | vec4 ambientColor = vec4( 0.5, 0.5, 0.5, 1.0 ); 25 | 26 | float nDotVP = max( 0.0, dot( eyeNormal, normalize( lightPosition ) ) ); 27 | 28 | colorVarying = ambientColor + diffuseColor * nDotVP; 29 | 30 | gl_Position = modelViewProjectionMatrix * position; 31 | } 32 | -------------------------------------------------------------------------------- /xcode/Virtual Go/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ViewController : GLKViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Virtual Go-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundlePrimaryIcon 14 | 15 | CFBundleIconFiles 16 | 17 | virtual go.png 18 | virtual go retina.png 19 | virtual go retina ipad.png 20 | virtual go ipad.png 21 | 22 | 23 | 24 | CFBundleIdentifier 25 | com.gafferongames.virtualgo 26 | CFBundleInfoDictionaryVersion 27 | 6.0 28 | CFBundleName 29 | ${PRODUCT_NAME} 30 | CFBundlePackageType 31 | APPL 32 | CFBundleShortVersionString 33 | 1.0 34 | CFBundleSignature 35 | ???? 36 | CFBundleVersion 37 | 1.0 38 | LSRequiresIPhoneOS 39 | 40 | UIMainStoryboardFile 41 | MainStoryboard_iPhone 42 | UIMainStoryboardFile~ipad 43 | MainStoryboard_iPad 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UIStatusBarHidden 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | 54 | UISupportedInterfaceOrientations~ipad 55 | 56 | UIInterfaceOrientationPortrait 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /xcode/Virtual Go/Virtual Go-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Virtual Go' target in the 'Virtual Go' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /xcode/Virtual Go/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /xcode/Virtual Go/en.lproj/MainStoryboard_iPad.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /xcode/Virtual Go/en.lproj/MainStoryboard_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /xcode/Virtual Go/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Virtual Go 4 | // 5 | // Created by Glenn Fiedler on 4/13/13. 6 | // Copyright (c) 2013 Glenn Fiedler. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /xcode/Virtual Go/testflight/TestFlight.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestFlight.h 3 | // libTestFlight 4 | // 5 | // Created by Jonathan Janzen on 06/11/11. 6 | // Copyright 2011 TestFlight. All rights reserved. 7 | 8 | #import 9 | #define TESTFLIGHT_SDK_VERSION @"1.2.4" 10 | #undef TFLog 11 | 12 | #if __cplusplus 13 | extern "C" { 14 | #endif 15 | void TFLog(NSString *format, ...); 16 | void TFLogv(NSString *format, va_list arg_list); 17 | #if __cplusplus 18 | } 19 | #endif 20 | 21 | /** 22 | * TestFlight object 23 | * All methods are class level 24 | */ 25 | @interface TestFlight : NSObject { 26 | 27 | } 28 | 29 | /** 30 | * Add custom environment information 31 | * If you want to track custom information such as a user name from your application you can add it here 32 | * 33 | * @param information A string containing the environment you are storing 34 | * @param key The key to store the information with 35 | */ 36 | + (void)addCustomEnvironmentInformation:(NSString *)information forKey:(NSString*)key; 37 | 38 | 39 | /** 40 | * Starts a TestFlight session using the Application Token for this Application 41 | * 42 | * @param applicationToken Will be the application token for the current application. 43 | * The token for this application can be retrieved by going to https://testflightapp.com/dashboard/applications/ 44 | * selecting this application from the list then selecting SDK. 45 | */ 46 | 47 | + (void)takeOff:(NSString *)applicationToken; 48 | 49 | /** 50 | * Sets custom options 51 | * 52 | * @param options NSDictionary containing the options you want to set. Available options are described below at "TestFlight Option Keys" 53 | * 54 | */ 55 | + (void)setOptions:(NSDictionary*)options; 56 | 57 | /** 58 | * Track when a user has passed a checkpoint after the flight has taken off. Eg. passed level 1, posted high score 59 | * 60 | * @param checkpointName The name of the checkpoint, this should be a static string 61 | */ 62 | + (void)passCheckpoint:(NSString *)checkpointName; 63 | 64 | /** 65 | * Opens a feedback window that is not attached to a checkpoint 66 | */ 67 | + (void)openFeedbackView; 68 | 69 | /** 70 | * Submits custom feedback to the site. Sends the data in feedback to the site. This is to be used as the method to submit 71 | * feedback from custom feedback forms. 72 | * 73 | * @param feedback Your users feedback, method does nothing if feedback is nil 74 | */ 75 | + (void)submitFeedback:(NSString*)feedback; 76 | 77 | /** 78 | * Sets the Device Identifier. 79 | * 80 | * !! DO NOT CALL IN SUBMITTED APP STORE APP. 81 | * 82 | * !! MUST BE CALLED BEFORE +takeOff: 83 | * 84 | * This method should only be used during testing so that you can identify a testers test data with them. 85 | * If you do not provide the identifier you will still see all session data, with checkpoints 86 | * and logs, but the data will be anonymized. 87 | * 88 | * It is recommended that you only use this method during testing. 89 | * Apple may reject your app if left in a submitted app. 90 | * 91 | * Use: 92 | * Only use this with the Apple device UDID. DO NOT use Open ID or your own identifier. 93 | * [TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]]; 94 | * 95 | * @param deviceIdentifer The current devices device identifier 96 | */ 97 | + (void)setDeviceIdentifier:(NSString*)deviceIdentifer; 98 | 99 | @end 100 | 101 | 102 | /** 103 | * TestFlight Option Keys 104 | * 105 | * Pass these as keys to the dictionary you pass to +`[TestFlight setOptions:]`. 106 | * The values should be NSNumber BOOLs (`[NSNumber numberWithBool:YES]` or `@YES`) 107 | */ 108 | extern NSString *const TFOptionAttachBacktraceToFeedback; // Defaults to @NO. Setting to @YES attaches the current backtrace, with symbols, to the feedback. 109 | extern NSString *const TFOptionDisableInAppUpdates; // Defaults to @NO. Setting to @YES, disables the in app update screen shown in BETA apps when there is a new version available on TestFlight. 110 | extern NSString *const TFOptionLogToConsole; // Defaults to @YES. Prints remote logs to Apple System Log. 111 | extern NSString *const TFOptionLogToSTDERR; // Defaults to @YES. Sends remote logs to STDERR when debugger is attached. 112 | extern NSString *const TFOptionReinstallCrashHandlers; // If set to @YES: Reinstalls crash handlers, to be used if a third party library installs crash handlers overtop of the TestFlight Crash Handlers. 113 | extern NSString *const TFOptionSendLogOnlyOnCrash; // Defaults to @NO. Setting to @YES stops remote logs from being sent when sessions end. They would only be sent in the event of a crash. 114 | 115 | -------------------------------------------------------------------------------- /xcode/Virtual Go/testflight/libTestFlight.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/testflight/libTestFlight.a -------------------------------------------------------------------------------- /xcode/Virtual Go/testflight/release_notes.md: -------------------------------------------------------------------------------- 1 | ## 1.2.4 - February 19, 2013 2 | 3 | - Fixed bug that caused crash reports to sometimes not send immediately (they would be resent later) 4 | 5 | ## 1.2.3 - January 8, 2013 6 | 7 | - Fixed typos in readme 8 | - Fixed bug where logs not sent on crash 9 | - Fixed bug where empty crash files were created (but not sent) 10 | - Cache cache path 11 | - Use consts for `setOptions:` 12 | - Updated `setDeviceIdentifier:` comments to make them clearer 13 | - Remove potentially conflicting function name `UIColorFromRGB` 14 | - Fixed crash on bad in app update data 15 | 16 | ## 1.2.2 - December 26, 2012 17 | 18 | - Fix typo in app token error message 19 | 20 | ## 1.2.1 - December 26, 2012 21 | 22 | - The max number of concurrent network connections has been reduced from 4 to 2. 23 | 24 | ##1.2 - November 12, 2012 25 | 26 | * Removed Team Token support. As of version 1.2 takeOff must be called with the Application Token, https://testflightapp.com/dashboard/applications/, choose your application, select SDK, get the Token for this Application. 27 | 28 | ##1.2 BETA 3 - October 11, 2012 29 | 30 | * Added application token support. Application Tokens are currently optional if you do not have one you do not need one 31 | 32 | ##1.2 BETA 2 - October 9, 2012 33 | 34 | * Resolved an instance of close_file being called on a bad file descriptor 35 | 36 | ##1.2 BETA 1 - October 1, 2012 37 | 38 | * Removed support for armv6 39 | * Exception handler now returns instead of raising a SIGTRAP 40 | 41 | ##1.1 - September 13, 2012 42 | 43 | * armv7s and iOS 6 support 44 | * Updated for general release 45 | 46 | ##1.1 BETA 3 - September 12, 2012 47 | 48 | * armv7s slice added to library 49 | * fixed typo for in application updates, inAppUdates changed to inAppUpdates 50 | 51 | ##1.1 BETA 2 - September 6, 2012 52 | 53 | * Re-enabled armv6 support 54 | * Added option to disable in application updates 55 | 56 | ##1.1 BETA 1 - July 13, 2012 57 | 58 | * Added TFLogv to allow for log customizations. Check the README or online docs for more information. 59 | * Added option attachBacktraceToFeedback, which attaches a backtrace to feedback sent from the SDK. For users who use feedback in more than one location in the application. 60 | * Resolved issue where other exception handlers would not be called during an exception. 61 | * SDK now sends the device language for a session. 62 | * Documentation fixes. 63 | * Stability fixes. 64 | 65 | ###1.0 - March 29, 2012 66 | 67 | * Resolved occurrences of exceptions with the message "No background task exists with identifier 0" 68 | 69 | ###1.0 BETA 1 - March 23, 2012 70 | 71 | * Privacy Updates 72 | * UDID is no longer collected by the SDK. During testing please use `[TestFlight setDeviceIdentifier:[[UIDevice currentDevice] uniqueIdentifier]];` to send the UDID so you can identify your testers. For release do not set `+setDeviceIdentifier`. See Beta Testing and Release Differentiation in the README or online at [https://testflightapp.com/sdk/doc/1.0beta1/](http://testflightapp.com/sdk/doc/1.0beta1/) 73 | 74 | ###0.8.3 - February 14, 2012 75 | 76 | * Rolled previous beta code into release builds 77 | * No longer allow in application updates to occur in applications that were obtained from the app store. 78 | 79 | **Tested compiled library with:** 80 | 81 | * Xcode 4.3 82 | * Xcode 4.2 83 | * Xcode 4.1 84 | * Xcode 3.2.6 85 | 86 | ###0.8.3 BETA 5 - February 10, 2012 87 | 88 | * Changed logging from asynchronous to synchronous. 89 | * Resolved crash when looking for a log path failed. 90 | * Added submitFeedback to the TestFlight class to allow for custom feedback forms. 91 | 92 | ###0.8.3 BETA 4 - January 20, 2012 93 | 94 | * Resolved an issue that occured when an application was upgraded from 0.8.3 BETA 1 to 0.8.3 BETA 3+ with unsent data from 0.8.3 BETA 1 95 | 96 | ###0.8.3 BETA 3 - January 19, 2012 97 | 98 | * On crash log files over 64k will not be sent until next launch. 99 | 100 | **Known Issues:** 101 | 102 | * Logging massive amounts of data at the end of a session may prevent the application from launching in time on next launch 103 | 104 | ###0.8.3 BETA 2 - January 13, 2012 105 | 106 | * libz.dylib is now required to be added to your "Link Binary with Libraries" build phase 107 | * Log file compression, The compression is done on an as needed basis rather than before sending 108 | * Changed all outgoing data from JSON to MessagePack 109 | * Added option `logToSTDERR` to disable the `STDERR` logger 110 | 111 | ###0.8.3 BETA 1 - December 29, 2011 112 | 113 | * In rare occurrences old session data that had not been sent to our server may have been discarded or attached to the wrong build. It is now no longer discarded 114 | * Made sending of Session End events more robust 115 | * Network queuing system does better bursting of unsent data 116 | * Log files that are larger than 64K are now sent sometime after the next launch 117 | * Log files that are larger than 16MB are no longer supported and will be replaced with a message indicating the log file was too large 118 | * Fixed crashes while resuming from background 119 | 120 | ###0.8.2 - December 20, 2011 121 | 122 | * Promoted 0.8.2 BETA 4 to stable 123 | 124 | **Known Issues:** 125 | 126 | * Under some circumstances Session End events may not be sent until the next launch. 127 | * With large log files Session End events may take a long time to show up. 128 | 129 | **Tested compiled library with:** 130 | 131 | * Xcode 4.3 132 | * Xcode 4.2 133 | * Xcode 4.1 134 | * Xcode 3.2.6 135 | 136 | ###0.8.2 BETA 4 - December 12, 2011 137 | 138 | * Prevented "The string argument is NULL" from occuring during finishedHandshake in rare cases 139 | * Resolved issue where data recorded while offline may not be sent 140 | 141 | ###0.8.2 BETA 3 - December 8, 2011 142 | 143 | * Added auto-release pools to background setup and tear down 144 | 145 | ###0.8.2 BETA 2 - December 5, 2011 146 | 147 | * Fixed the "pointer being freed was not allocated" bug 148 | 149 | ###0.8.1 - November 18, 2011 150 | 151 | * Implemented TFLog logging system, see README for more information 152 | * Fixed an issue where Session End events may not be sent until next launch 153 | * Fixed an issue where duplicate events could be sent 154 | * Fixed an issue with Session End events not being sent from some iPod touch models 155 | 156 | **Tested compiled library with:** 157 | 158 | * Xcode 4.2 159 | * Xcode 4.1 160 | * Xcode 3.2.6 161 | 162 | ###0.8 - November 8, 2011 163 | 164 | * Added `SIGTRAP` as a signal type that we catch 165 | * Removed all Objective-c from crash reporting 166 | * Removed the use of non signal safe functions from signal handling 167 | * Created a signal safe way to get symbols from a stack trace 168 | * Changed the keyboardType for Long Answer Questions and Feedback to allow for international character input 169 | * Changed `TESTFLIGHT_SDK_VERSION` string to be an `NSString` 170 | * Changed cache folder from Library/Caches/TestFlight to Library/Caches/com.testflight.testflightsdk 171 | * Fixed issue with saving data when device is offline 172 | * Fixed compability issues with iOS 3 173 | * Added calling into the rootViewController shouldAutorotateToInterfaceOrientation if a rootViewController is set 174 | * Made the comments in TestFlight.h compatible with Appledoc 175 | 176 | Tested compiled library with: 177 | 178 | * Xcode 4.2 179 | * Xcode 4.1 180 | * Xcode 3.2 181 | 182 | ###0.7.2 - September 29, 2011 183 | 184 | * Changed `TESTFLIGHT_SDK_VERSION` string to be an `NSString` 185 | * Fixed an issue where exiting an application while the SDK is active caused modal views to be dismissed 186 | 187 | ###0.7.1 - September 22, 2011 188 | 189 | * Internal release 190 | * Refactoring 191 | 192 | ###0.7 - September 21, 2011 193 | 194 | * Moved TestFlight images and data to the Library/Caches folder 195 | * Resolved an issue where sometimes the rootViewController could not be found and feedback, questions and upgrade views would not be displayed 196 | * In application upgrade changed to allow skipping until the next version is installed and allows upgrades to be forced 197 | * Fixed a memory leak when launching questions 198 | 199 | ###0.6 - September 2, 2011 200 | 201 | * Renamed base64_encode to testflight_base64_encode to remove a conflict with other third party libraries 202 | * Added ability to reinstall crash handlers when they are overwritten using the setOptions API 203 | * Fixed an issue where crash reports might not get sent under certain circumstances 204 | * Fixed a deadlock when the application is put in the background and then resumed before all information can be sent 205 | * Fixed an issue when attempting to un-install all signal handlers during a signal 206 | * Added support for landscape mode on the iPad to the Questions and Feedback views 207 | * Crash reporting now works in versions of Xcode earlier than 4.2 208 | * Fixed a memory leak during handshake 209 | 210 | ###0.5 - August 19, 2011 211 | 212 | * Feedback that is not attached to a checkpoint [TestFlight openFeedbackView] 213 | * Usability changes to question views 214 | * Removed pause and resume sessions, replaced with sessions being stopped and started 215 | * Added text auto correction to the Long Answer question type 216 | * Crash reports now send on crash instead of next launch 217 | 218 | ###0.4 - August 15, 2011 219 | 220 | * In Application Feedback with Questions 221 | * In application updates 222 | * Custom Environment Information added 223 | * Networking stack reimplementation 224 | * Exception handling fixes 225 | 226 | ###0.3 - June 15, 2011 227 | 228 | * Removed all mention of JSONKit from the README 229 | * Added support for using both the Bundle Version and the Bundle Short Version string 230 | 231 | ###0.2 - June 14, 2011 232 | 233 | * Removed all categories this allows users to use the SDK without having to set -ObjC and -load_all 234 | * Prefixed JSONKit for use in TestFlight to remove reported issues where some users were already using JSONKit 235 | * Added support for armv6 again 236 | 237 | ###0.1 - June 11, 2011 238 | 239 | * Initial Version 240 | -------------------------------------------------------------------------------- /xcode/Virtual Go/textures/floor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/textures/floor.jpg -------------------------------------------------------------------------------- /xcode/Virtual Go/textures/line.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/textures/line.jpg -------------------------------------------------------------------------------- /xcode/Virtual Go/textures/point.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/textures/point.jpg -------------------------------------------------------------------------------- /xcode/Virtual Go/textures/wood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/Virtual Go/textures/wood.jpg -------------------------------------------------------------------------------- /xcode/virtual go ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/virtual go ipad.png -------------------------------------------------------------------------------- /xcode/virtual go retina ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/virtual go retina ipad.png -------------------------------------------------------------------------------- /xcode/virtual go retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/virtual go retina.png -------------------------------------------------------------------------------- /xcode/virtual go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mas-bandwidth/virtualgo/9f3db98887f675cc02ca333ef30e3de13a8b4664/xcode/virtual go.png --------------------------------------------------------------------------------