aboutsummaryrefslogtreecommitdiff
path: root/redist
diff options
context:
space:
mode:
authorultramn <dchapm2@umbc.edu>2017-05-14 18:54:49 -0700
committerultramn <dchapm2@umbc.edu>2017-05-14 18:54:49 -0700
commit0d83014f61489522b9b55f3966eaf4c9578a14e5 (patch)
tree65e36dddc8b212250c84fb0a159bb3bc97838152 /redist
parent006af3f9b168fcde6892a22ae914b5b55634b2ca (diff)
parent2e8bf907f46bcb98b3b482e957b98c52cacb6a4b (diff)
downloadlibsurvive-0d83014f61489522b9b55f3966eaf4c9578a14e5.tar.gz
libsurvive-0d83014f61489522b9b55f3966eaf4c9578a14e5.tar.bz2
Merge branch 'master' of https://github.com/cnlohr/libsurvive
Diffstat (limited to 'redist')
-rw-r--r--redist/CNFGFunctions.c (renamed from redist/DrawFunctions.c)97
-rw-r--r--redist/CNFGFunctions.h (renamed from redist/DrawFunctions.h)13
-rw-r--r--redist/CNFGNullDriver.c (renamed from redist/RawDrawNull.c)2
-rw-r--r--redist/CNFGRasterizer.h (renamed from redist/RawDrawRasterizer.c)33
-rw-r--r--redist/CNFGWinDriver.c (renamed from redist/WinDriver.c)299
-rw-r--r--redist/CNFGXDriver.c (renamed from redist/XDriver.c)90
-rw-r--r--redist/json_helpers.c62
-rw-r--r--redist/json_helpers.h4
-rw-r--r--redist/linmath.c36
-rw-r--r--redist/linmath.h1
-rw-r--r--redist/os_generic.c17
-rw-r--r--redist/svd.h450
12 files changed, 952 insertions, 152 deletions
diff --git a/redist/DrawFunctions.c b/redist/CNFGFunctions.c
index f4f27d2..25e9298 100644
--- a/redist/DrawFunctions.c
+++ b/redist/CNFGFunctions.c
@@ -21,14 +21,13 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "DrawFunctions.h"
+#include "CNFGFunctions.h"
#include <stdio.h>
int CNFGPenX, CNFGPenY;
uint32_t CNFGBGColor;
uint32_t CNFGLastColor;
uint32_t CNFGDialogColor; //background for boxes
-
const unsigned short FontCharMap[256] = {
65535, 0, 10, 20, 32, 44, 56, 68, 70, 65535, 65535, 80, 92, 65535, 104, 114,
126, 132, 138, 148, 156, 166, 180, 188, 200, 206, 212, 218, 224, 228, 238, 244,
@@ -68,7 +67,7 @@ const unsigned char FontCharData[1902] = {
0x23, 0x14, 0x14, 0x03, 0x10, 0x94, 0x00, 0x01, 0x23, 0x24, 0x04, 0x03, 0x03, 0x21, 0x21, 0xa0,
0x21, 0x10, 0x10, 0x01, 0x01, 0x12, 0x12, 0x03, 0x03, 0x14, 0x14, 0x23, 0x02, 0xa4, 0x10, 0x91,
0x10, 0x01, 0x01, 0x03, 0x03, 0x94, 0x10, 0x21, 0x21, 0x23, 0x23, 0x94, 0x01, 0x23, 0x11, 0x13,
- 0x21, 0x03, 0x02, 0xa2, 0x02, 0x22, 0x11, 0x93, 0x31, 0xc0, 0x03, 0xa1, 0x00, 0x20, 0x20, 0x24,
+ 0x21, 0x03, 0x02, 0xa2, 0x02, 0x22, 0x11, 0x93, 0x04, 0x93, 0x03, 0xa1, 0x00, 0x20, 0x20, 0x24,
0x24, 0x04, 0x04, 0x00, 0x12, 0x92, 0x01, 0x10, 0x10, 0x14, 0x04, 0xa4, 0x01, 0x10, 0x10, 0x21,
0x21, 0x22, 0x22, 0x04, 0x04, 0xa4, 0x00, 0x20, 0x20, 0x24, 0x24, 0x04, 0x12, 0xa2, 0x00, 0x02,
0x02, 0x22, 0x20, 0xa4, 0x20, 0x00, 0x00, 0x02, 0x02, 0x22, 0x22, 0x24, 0x24, 0x84, 0x20, 0x02,
@@ -208,11 +207,7 @@ void CNFGDrawText( const char * text, int scale )
int x2 = (int)((((*(lmap+1)) & 0x70)>>4)*scale + iox);
int y2 = (int)(((*(lmap+1)) & 0x0f)*scale + ioy);
lmap++;
- if(x1 == x2 && y1 == y2){
- CNFGTackPixel( x1, y1 );
- } else {
- CNFGTackSegment( x1, y1, x2, y2 );
- }
+ CNFGTackSegment( x1, y1, x2, y2 );
bQuit = *lmap & 0x80;
lmap++;
} while( !bQuit );
@@ -275,3 +270,89 @@ void CNFGDrawTextbox( int x, int y, const char * text, int textsize )
CNFGPenY = y + textsize;
CNFGDrawText( text, textsize );
}
+
+
+#ifdef CNFGOGL
+
+#ifdef _MSC_VER
+#include <windows.h>
+#pragma comment( lib, "OpenGL32.lib" )
+#endif
+#include <GL/gl.h>
+
+uint32_t CNFGColor( uint32_t RGB )
+{
+ unsigned char red = RGB & 0xFF;
+ unsigned char grn = ( RGB >> 8 ) & 0xFF;
+ unsigned char blu = ( RGB >> 16 ) & 0xFF;
+ glColor3ub( red, grn, blu );
+}
+
+void CNFGClearFrame()
+{
+ short w, h;
+ unsigned char red = CNFGBGColor & 0xFF;
+ unsigned char grn = ( CNFGBGColor >> 8 ) & 0xFF;
+ unsigned char blu = ( CNFGBGColor >> 16 ) & 0xFF;
+ glClearColor( red/255.0, grn/255.0, blu/255.0, 1.0 );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ CNFGGetDimensions( &w, &h );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glViewport( 0, 0, w, h );
+ glOrtho( 0, w, h, 0, 1, -1 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+}
+
+
+void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+{
+ if( x1 == x2 && y1 == y2 )
+ {
+ glBegin( GL_POINTS );
+ glVertex2f( x1+.5, y1+.5 );
+ glEnd();
+ }
+ else
+ {
+ glBegin( GL_LINES );
+ glVertex2f( x1+.5, y1+.5 );
+ glVertex2f( x2+.5, y2+.5 );
+ glEnd();
+ }
+}
+
+void CNFGTackPixel( short x1, short y1 )
+{
+ glBegin( GL_POINTS );
+ glVertex2f( x1, y1 );
+ glEnd();
+}
+
+void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
+{
+ glBegin( GL_QUADS );
+ glVertex2f( x1, y1 );
+ glVertex2f( x2, y1 );
+ glVertex2f( x2, y2 );
+ glVertex2f( x1, y2 );
+ glEnd();
+}
+
+void CNFGTackPoly( RDPoint * points, int verts )
+{
+ int i;
+ glBegin( GL_TRIANGLE_FAN );
+ glVertex2f( points[0].x, points[0].y );
+ for( i = 1; i < verts; i++ )
+ {
+ glVertex2f( points[i].x, points[i].y );
+ }
+ glEnd();
+}
+
+void CNFGInternalResize( short x, short y ) { }
+
+
+#endif
diff --git a/redist/DrawFunctions.h b/redist/CNFGFunctions.h
index 542fcf9..179a20b 100644
--- a/redist/DrawFunctions.h
+++ b/redist/CNFGFunctions.h
@@ -1,4 +1,4 @@
-//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
+//Copyright (c) 2011, 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
#ifndef _DRAWFUCNTIONS_H
#define _DRAWFUCNTIONS_H
@@ -34,7 +34,6 @@ void CNFGClearFrame();
void CNFGSwapBuffers();
void CNFGGetDimensions( short * x, short * y );
-void CNFGTearDown();
void CNFGSetup( const char * WindowName, int w, int h );
void CNFGSetupFullscreen( const char * WindowName, int screen_number );
void CNFGHandleInput();
@@ -44,8 +43,18 @@ void CNFGHandleInput();
void HandleKey( int keycode, int bDown );
void HandleButton( int x, int y, int button, int bDown );
void HandleMotion( int x, int y, int mask );
+void HandleDestroy();
+//Internal function for resizing rasterizer for rasterizer-mode.
+void CNFGInternalResize( short x, short y ); //don't call this.
+
+//Not available on all systems. Use The OGL portion with care.
+#ifdef CNFGOGL
+void CNFGSetVSync( int vson );
+void * CNFGGetExtension( const char * extname );
+#endif
+
#ifdef __cplusplus
};
#endif
diff --git a/redist/RawDrawNull.c b/redist/CNFGNullDriver.c
index 34346cc..c35884a 100644
--- a/redist/RawDrawNull.c
+++ b/redist/CNFGNullDriver.c
@@ -1,6 +1,6 @@
//Copyright (c) 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
-#include "DrawFunctions.h"
+#include "CNFGFunctions.h"
static int w, h;
void CNFGGetDimensions( short * x, short * y )
diff --git a/redist/RawDrawRasterizer.c b/redist/CNFGRasterizer.h
index af40588..1b8e2dd 100644
--- a/redist/RawDrawRasterizer.c
+++ b/redist/CNFGRasterizer.h
@@ -1,6 +1,7 @@
+//Don't call this file yourself. It is intended to be included in any drivers which want to support the rasterizer plugin.
+
#ifdef RASTERIZER
-#include "DrawFunctions.h"
-#include <stdio.h>
+#include "CNFGFunctions.h"
#include <stdlib.h>
#include <stdint.h>
@@ -8,6 +9,15 @@ static uint32_t * buffer = 0;
static short bufferx;
static short buffery;
+
+void CNFGInternalResize( short x, short y )
+{
+ bufferx = x;
+ buffery = y;
+ if( buffer ) free( buffer );
+ buffer = malloc( bufferx * buffery * 4 );
+}
+
static uint32_t SWAPS( uint32_t r )
{
uint32_t ret = (r&0xFF)<<16;
@@ -24,11 +34,6 @@ uint32_t CNFGColor( uint32_t RGB )
return CNFGLastColor;
}
-void CNFGTackPixel( short x, short y )
-{
- buffer[bufferx*y+x] = CNFGLastColor;
-}
-
void CNFGTackSegment( short x1, short y1, short x2, short y2 )
{
short tx, ty;
@@ -53,11 +58,11 @@ void CNFGTackSegment( short x1, short y1, short x2, short y2 )
for( tx = minx; tx <= maxx; tx++ )
{
- thisy += slope;
ty = thisy;
if( tx < 0 || ty < 0 || ty >= buffery ) continue;
if( tx >= bufferx ) break;
buffer[ty * bufferx + tx] = CNFGLastColor;
+ thisy += slope;
}
}
else
@@ -71,15 +76,14 @@ void CNFGTackSegment( short x1, short y1, short x2, short y2 )
for( ty = miny; ty <= maxy; ty++ )
{
- thisx += slope;
tx = thisx;
if( ty < 0 || tx < 0 || tx >= bufferx ) continue;
if( ty >= buffery ) break;
buffer[ty * bufferx + tx] = CNFGLastColor;
+ thisx += slope;
}
}
}
-
void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
{
short minx = (x1<x2)?x1:x2;
@@ -216,7 +220,6 @@ void CNFGClearFrame()
{
bufferx = x;
buffery = y;
- printf( "MALLOCING: %d\n", x * y );
buffer = malloc( x * y * 8 );
}
@@ -229,9 +232,15 @@ void CNFGClearFrame()
}
}
+void CNFGTackPixel( short x, short y )
+{
+ if( x < 0 || y < 0 || x >= bufferx || y >= buffery ) return;
+ buffer[x+bufferx*y] = CNFGLastColor;
+}
+
void CNFGSwapBuffers()
{
- CNFGUpdateScreenWithBitmap( buffer, bufferx, buffery );
+ CNFGUpdateScreenWithBitmap( (long unsigned int*)buffer, bufferx, buffery );
}
diff --git a/redist/WinDriver.c b/redist/CNFGWinDriver.c
index 3613150..b1c1eb0 100644
--- a/redist/WinDriver.c
+++ b/redist/CNFGWinDriver.c
@@ -2,80 +2,73 @@
//Portion from: http://en.wikibooks.org/wiki/Windows_Programming/Window_Creation
-#include "DrawFunctions.h"
+#include "CNFGFunctions.h"
#include <windows.h>
#include <stdlib.h>
#include <malloc.h> //for alloca
+static HBITMAP lsBitmap;
static HINSTANCE lhInstance;
static HWND lsHWND;
-static HDC lsHDC;
-static HBITMAP lsBackBitmap;
static HDC lsWindowHDC;
-static HBRUSH lsHBR;
-static HPEN lsHPEN;
-static HBRUSH lsClearBrush;
-static unsigned int lsLastWidth;
-static unsigned int lsLastHeight;
-
-static void InternalHandleResize()
-{
- DeleteObject( lsBackBitmap );
- lsBackBitmap = CreateCompatibleBitmap( lsHDC, lsLastWidth, lsLastHeight );
- SelectObject( lsHDC, lsBackBitmap );
+static HDC lsHDC;
-}
+#ifdef RASTERIZER
+#include "CNFGRasterizer.h"
-uint32_t CNFGColor( uint32_t RGB )
+void InternalHandleResize()
{
- CNFGLastColor = RGB;
-
- DeleteObject( lsHBR );
- lsHBR = CreateSolidBrush( RGB );
- SelectObject( lsHDC, lsHBR );
+ if( lsBitmap ) DeleteObject( lsBitmap );
- DeleteObject( lsHPEN );
- lsHPEN = CreatePen( PS_SOLID, 0, RGB );
- SelectObject( lsHDC, lsHPEN );
-
- return RGB;
+ CNFGInternalResize( bufferx, buffery );
+ lsBitmap = CreateBitmap( bufferx, buffery, 1, 32, buffer );
+ SelectObject( lsHDC, lsBitmap );
}
+#else
+static int bufferx, buffery;
+static int bufferx, buffery;
+static void InternalHandleResize();
+#endif
-void CNFGTackSegment( short x1, short y1, short x2, short y2 )
-{
- POINT pt[2] = { {x1, y1}, {x2, y2} };
- Polyline( lsHDC, pt, 2 );
- SetPixel( lsHDC, x1, y1, CNFGLastColor );
- SetPixel( lsHDC, x2, y2, CNFGLastColor );
-}
-void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
+#ifdef CNFGOGL
+#include <GL/gl.h>
+static HGLRC hRC=NULL;
+static void InternalHandleResize() { }
+void CNFGSwapBuffers()
{
- RECT r;
- if( x1 < x2 ) { r.left = x1; r.right = x2; }
- else { r.left = x2; r.right = x1; }
- if( y1 < y2 ) { r.top = y1; r.bottom = y2; }
- else { r.top = y2; r.bottom = y1; }
- FillRect( lsHDC, &r, lsHBR );
+ SwapBuffers(lsWindowHDC);
}
+#endif
-void CNFGClearFrame()
+void CNFGGetDimensions( short * x, short * y )
{
- RECT r = { 0, 0, lsLastWidth, lsLastHeight };
- DeleteObject( lsClearBrush );
- lsClearBrush = CreateSolidBrush( CNFGBGColor );
- SelectObject( lsHDC, lsClearBrush );
-
- FillRect( lsHDC, &r, lsClearBrush );
+ static int lastx, lasty;
+ RECT window;
+ GetClientRect( lsHWND, &window );
+ bufferx = ( window.right - window.left);
+ buffery = ( window.bottom - window.top);
+ if( bufferx != lastx || buffery != lasty )
+ {
+ lastx = bufferx;
+ lasty = buffery;
+ InternalHandleResize();
+ }
+ *x = bufferx;
+ *y = buffery;
}
-void CNFGSwapBuffers()
+
+void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
{
- int thisw, thish;
RECT r;
- BitBlt( lsWindowHDC, 0, 0, lsLastWidth, lsLastHeight, lsHDC, 0, 0, SRCCOPY );
+
+ int a = SetBitmapBits(lsBitmap,w*h*4,data);
+ a = BitBlt(lsWindowHDC, 0, 0, w, h, lsHDC, 0, 0, SRCCOPY);
UpdateWindow( lsHWND );
+ int thisw, thish;
+
//Check to see if the window is closed.
if( !IsWindow( lsHWND ) )
{
@@ -85,36 +78,18 @@ void CNFGSwapBuffers()
GetClientRect( lsHWND, &r );
thisw = r.right - r.left;
thish = r.bottom - r.top;
- if( thisw != lsLastWidth || thish != lsLastHeight )
+ if( thisw != bufferx || thish != buffery )
{
- lsLastWidth = thisw;
- lsLastHeight = thish;
+ bufferx = thisw;
+ buffery = thish;
InternalHandleResize();
}
}
-void CNFGTackPoly( RDPoint * points, int verts )
-{
- int i;
- POINT * t = (POINT*)alloca( sizeof( POINT ) * verts );
- for( i = 0; i < verts; i++ )
- {
- t[i].x = points[i].x;
- t[i].y = points[i].y;
- }
- Polygon( lsHDC, t, verts );
-}
-
-
-void CNFGTackPixel( short x1, short y1 )
-{
- SetPixel( lsHDC, x1, y1, CNFGLastColor );
-}
-void CNFGGetDimensions( short * x, short * y )
+void CNFGTearDown()
{
- *x = lsLastWidth;
- *y = lsLastHeight;
+ PostQuitMessage(0);
}
//This was from the article
@@ -123,17 +98,13 @@ LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
switch(msg)
{
case WM_DESTROY:
+ HandleDestroy();
CNFGTearDown();
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
-void CNFGTearDown()
-{
- PostQuitMessage(0);
-}
-
//This was from the article, too... well, mostly.
void CNFGSetup( const char * name_of_window, int width, int height )
{
@@ -143,8 +114,8 @@ void CNFGSetup( const char * name_of_window, int width, int height )
int w, h, wd, hd;
HINSTANCE hInstance = GetModuleHandle(NULL);
- lsLastWidth = width;
- lsLastHeight = height;
+ bufferx = width;
+ buffery = height;
wnd.style = CS_HREDRAW | CS_VREDRAW; //we will explain this later
wnd.lpfnWndProc = MyWndProc;
@@ -167,22 +138,63 @@ void CNFGSetup( const char * name_of_window, int width, int height )
WS_OVERLAPPEDWINDOW, //basic window style
CW_USEDEFAULT,
CW_USEDEFAULT, //set starting point to default value
- lsLastWidth,
- lsLastHeight, //set all the dimensions to default value
+ bufferx,
+ buffery, //set all the dimensions to default value
NULL, //no parent window
NULL, //no menu
hInstance,
NULL); //no parameters to pass
-
lsWindowHDC = GetDC( lsHWND );
+
+#ifdef CNFGOGL
+ //From NeHe
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR),
+ 1,
+ PFD_DRAW_TO_WINDOW |
+ PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER,
+ PFD_TYPE_RGBA,
+ 32,
+ 0, 0, 0, 0, 0, 0,
+ 0,
+ 0,
+ 0,
+ 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,
+ 0, 0, 0
+ };
+ GLuint PixelFormat = ChoosePixelFormat( lsWindowHDC, &pfd );
+ if( !SetPixelFormat( lsWindowHDC, PixelFormat, &pfd ) )
+ {
+ MessageBox( 0, "Could not create PFD for OpenGL Context\n", 0, 0 );
+ exit( -1 );
+ }
+ if (!(hRC=wglCreateContext(lsWindowHDC))) // Are We Able To Get A Rendering Context?
+ {
+ MessageBox( 0, "Could not create OpenGL Context\n", 0, 0 );
+ exit( -1 );
+ }
+ if(!wglMakeCurrent(lsWindowHDC,hRC)) // Try To Activate The Rendering Context
+ {
+ MessageBox( 0, "Could not current OpenGL Context\n", 0, 0 );
+ exit( -1 );
+ }
+#endif
+
lsHDC = CreateCompatibleDC( lsWindowHDC );
- lsBackBitmap = CreateCompatibleBitmap( lsWindowHDC, lsLastWidth, lsLastHeight );
- SelectObject( lsHDC, lsBackBitmap );
+ lsBitmap = CreateCompatibleBitmap( lsWindowHDC, bufferx, buffery );
+ SelectObject( lsHDC, lsBitmap );
- lsClearBrush = CreateSolidBrush( CNFGBGColor );
- lsHBR = CreateSolidBrush( 0xFFFFFF );
- lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF );
+ //lsClearBrush = CreateSolidBrush( CNFGBGColor );
+ //lsHBR = CreateSolidBrush( 0xFFFFFF );
+ //lsHPEN = CreatePen( PS_SOLID, 0, 0xFFFFFF );
ShowWindow(lsHWND, 1); //display the window on the screen
@@ -193,7 +205,7 @@ void CNFGSetup( const char * name_of_window, int width, int height )
h = ( window.bottom - window.top);
wd = w - client.right;
hd = h - client.bottom;
- MoveWindow( lsHWND, window.left, window.top, lsLastWidth + wd, lsLastHeight + hd, 1 );
+ MoveWindow( lsHWND, window.left, window.top, bufferx + wd, buffery + hd, 1 );
InternalHandleResize();
}
@@ -220,7 +232,7 @@ void CNFGHandleInput()
case WM_MBUTTONUP: HandleButton( (msg.lParam & 0xFFFF), (msg.lParam>>16) & 0xFFFF, 3, 0 ); break;
case WM_KEYDOWN:
case WM_KEYUP:
- HandleKey( tolower( (int)msg.wParam ), (msg.message==WM_KEYDOWN) );
+ HandleKey( tolower( (int)(msg.wParam) ), (msg.message==WM_KEYDOWN) );
break;
default:
DispatchMessage(&msg);
@@ -229,3 +241,110 @@ void CNFGHandleInput()
}
}
+#ifndef CNFGOGL
+
+#ifndef RASTERIZER
+
+static HBITMAP lsBackBitmap;
+static HDC lsWindowHDC;
+static HBRUSH lsHBR;
+static HPEN lsHPEN;
+static HBRUSH lsClearBrush;
+
+static void InternalHandleResize()
+{
+ DeleteObject( lsBackBitmap );
+ lsBackBitmap = CreateCompatibleBitmap( lsHDC, bufferx, buffery );
+ SelectObject( lsHDC, lsBackBitmap );
+}
+
+uint32_t CNFGColor( uint32_t RGB )
+{
+ CNFGLastColor = RGB;
+
+ DeleteObject( lsHBR );
+ lsHBR = CreateSolidBrush( RGB );
+ SelectObject( lsHDC, lsHBR );
+
+ DeleteObject( lsHPEN );
+ lsHPEN = CreatePen( PS_SOLID, 0, RGB );
+ SelectObject( lsHDC, lsHPEN );
+
+ return RGB;
+}
+
+void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+{
+ POINT pt[2] = { {x1, y1}, {x2, y2} };
+ Polyline( lsHDC, pt, 2 );
+ SetPixel( lsHDC, x1, y1, CNFGLastColor );
+ SetPixel( lsHDC, x2, y2, CNFGLastColor );
+}
+
+void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
+{
+ RECT r;
+ if( x1 < x2 ) { r.left = x1; r.right = x2; }
+ else { r.left = x2; r.right = x1; }
+ if( y1 < y2 ) { r.top = y1; r.bottom = y2; }
+ else { r.top = y2; r.bottom = y1; }
+ FillRect( lsHDC, &r, lsHBR );
+}
+
+void CNFGClearFrame()
+{
+ RECT r = { 0, 0, bufferx, buffery };
+ DeleteObject( lsClearBrush );
+ lsClearBrush = CreateSolidBrush( CNFGBGColor );
+ SelectObject( lsHDC, lsClearBrush );
+ FillRect( lsHDC, &r, lsClearBrush);
+}
+
+void CNFGTackPoly( RDPoint * points, int verts )
+{
+ int i;
+ POINT * t = (POINT*)alloca( sizeof( POINT ) * verts );
+ for( i = 0; i < verts; i++ )
+ {
+ t[i].x = points[i].x;
+ t[i].y = points[i].y;
+ }
+ Polygon( lsHDC, t, verts );
+}
+
+
+void CNFGTackPixel( short x1, short y1 )
+{
+ SetPixel( lsHDC, x1, y1, CNFGLastColor );
+}
+
+void CNFGSwapBuffers()
+{
+ int thisw, thish;
+
+ RECT r;
+ BitBlt( lsWindowHDC, 0, 0, bufferx, buffery, lsHDC, 0, 0, SRCCOPY );
+ UpdateWindow( lsHWND );
+ //Check to see if the window is closed.
+ if( !IsWindow( lsHWND ) )
+ {
+ exit( 0 );
+ }
+
+ GetClientRect( lsHWND, &r );
+ thisw = r.right - r.left;
+ thish = r.bottom - r.top;
+
+ if( thisw != bufferx || thish != buffery )
+ {
+ bufferx = thisw;
+ buffery = thish;
+ InternalHandleResize();
+ }
+}
+
+void CNFGInternalResize( short bufferx, short buffery ) { }
+#endif
+
+#endif
+
diff --git a/redist/XDriver.c b/redist/CNFGXDriver.c
index 507ca95..ebaed91 100644
--- a/redist/XDriver.c
+++ b/redist/CNFGXDriver.c
@@ -1,10 +1,10 @@
-//Copyright (c) 2011 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
+//Copyright (c) 2011, 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
//portions from
//http://www.xmission.com/~georgeps/documentation/tutorials/Xlib_Beginner.html
//#define HAS_XINERAMA
-#include "DrawFunctions.h"
+#include "CNFGFunctions.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -25,12 +25,33 @@ Window CNFGWindow;
Pixmap CNFGPixmap;
GC CNFGGC;
GC CNFGWindowGC;
+Visual * CNFGVisual;
+
+
+#ifdef CNFGOGL
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
+GLXContext CNFGCtx;
+void * CNFGGetExtension( const char * extname ) { return glXGetProcAddressARB((const GLubyte *) extname); }
+#endif
+
int FullScreen = 0;
void CNFGGetDimensions( short * x, short * y )
{
+ static int lastx;
+ static int lasty;
+
*x = CNFGWinAtt.width;
*y = CNFGWinAtt.height;
+
+ if( lastx != *x || lasty != *y )
+ {
+ lastx = *x;
+ lasty = *y;
+ CNFGInternalResize( lastx, lasty );
+ }
}
static void InternalLinkScreenAndGo( const char * WindowName )
@@ -76,7 +97,7 @@ void CNFGSetupFullscreen( const char * WindowName, int screen_no )
exit( 1 );
}
- Visual * visual = DefaultVisual(CNFGDisplay, screen);
+ CNFGVisual = DefaultVisual(CNFGDisplay, screen);
CNFGWinAtt.depth = DefaultDepth(CNFGDisplay, screen);
if (XineramaQueryExtension(CNFGDisplay, &a, &b ) &&
@@ -107,7 +128,9 @@ void CNFGSetupFullscreen( const char * WindowName, int screen_no )
CNFGWindow = XCreateWindow(CNFGDisplay, XRootWindow(CNFGDisplay, screen),
xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height,
- 0, CNFGWinAtt.depth, InputOutput, visual, CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder, &setwinattr);
+ 0, CNFGWinAtt.depth, InputOutput, CNFGVisual,
+ CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder,
+ &setwinattr);
XMapWindow(CNFGDisplay, CNFGWindow);
XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime );
@@ -145,7 +168,31 @@ void CNFGSetup( const char * WindowName, int w, int h )
XGetWindowAttributes( CNFGDisplay, RootWindow(CNFGDisplay, 0), &CNFGWinAtt );
int depth = CNFGWinAtt.depth;
- CNFGWindow = XCreateWindow(CNFGDisplay, RootWindow(CNFGDisplay, 0), 1, 1, w, h, 0, depth, InputOutput, CopyFromParent, 0, 0 );
+ int screen = DefaultScreen(CNFGDisplay);
+ CNFGVisual = DefaultVisual(CNFGDisplay, screen);
+
+#ifdef CNFGOGL
+ int attribs[] = { GLX_RGBA,
+ GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ None };
+ XVisualInfo * vis = glXChooseVisual(CNFGDisplay, screen, attribs);
+ CNFGVisual = vis->visual;
+ depth = vis->depth;
+ CNFGCtx = glXCreateContext( CNFGDisplay, vis, NULL, True );
+#endif
+
+ XSetWindowAttributes attr;
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap( CNFGDisplay, RootWindow(CNFGDisplay, 0), CNFGVisual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ int mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ CNFGWindow = XCreateWindow(CNFGDisplay, RootWindow(CNFGDisplay, 0), 1, 1, w, h, 0, depth, InputOutput, CNFGVisual, mask, &attr );
XMapWindow(CNFGDisplay, CNFGWindow);
XFlush(CNFGDisplay);
@@ -153,7 +200,12 @@ void CNFGSetup( const char * WindowName, int w, int h )
Atom WM_DELETE_WINDOW = XInternAtom( CNFGDisplay, "WM_DELETE_WINDOW", False );
XSetWMProtocols( CNFGDisplay, CNFGWindow, &WM_DELETE_WINDOW, 1 );
+
XSelectInput( CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask );
+
+#ifdef CNFGOGL
+ glXMakeCurrent( CNFGDisplay, CNFGWindow, CNFGCtx );
+#endif
}
void CNFGHandleInput()
@@ -216,7 +268,6 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
if( !xi )
{
int screen = DefaultScreen(CNFGDisplay);
- Visual * visual = DefaultVisual(CNFGDisplay, screen);
depth = DefaultDepth(CNFGDisplay, screen)/8;
// xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 );
// lw = w;
@@ -226,7 +277,7 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
if( lw != w || lh != h )
{
if( xi ) free( xi );
- xi = XCreateImage(CNFGDisplay, DefaultVisual( CNFGDisplay, DefaultScreen(CNFGDisplay) ), depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 );
+ xi = XCreateImage(CNFGDisplay, CNFGVisual, depth*8, ZPixmap, 0, (char*)data, w, h, 32, w*4 );
lw = w;
lh = h;
}
@@ -237,7 +288,25 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
}
-#ifndef RASTERIZER
+#ifdef CNFGOGL
+
+void CNFGSetVSync( int vson )
+{
+ void (*glfn)( int );
+ glfn = (void (*)( int ))CNFGGetExtension( "glXSwapIntervalMESA" ); if( glfn ) glfn( vson );
+ glfn = (void (*)( int ))CNFGGetExtension( "glXSwapIntervalSGI" ); if( glfn ) glfn( vson );
+ glfn = (void (*)( int ))CNFGGetExtension( "glXSwapIntervalEXT" ); if( glfn ) glfn( vson );
+}
+
+void CNFGSwapBuffers()
+{
+ glFlush();
+ glFinish();
+ glXSwapBuffers( CNFGDisplay, CNFGWindow );
+}
+#endif
+
+#if !defined( RASTERIZER ) && !defined( CNFGOGL)
uint32_t CNFGColor( uint32_t RGB )
@@ -286,5 +355,10 @@ void CNFGTackPoly( RDPoint * points, int verts )
XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin );
}
+void CNFGInternalResize( short x, short y ) { }
+
+#else
+#include "CNFGRasterizer.h"
#endif
+
diff --git a/redist/json_helpers.c b/redist/json_helpers.c
index 0267932..af7ddda 100644
--- a/redist/json_helpers.c
+++ b/redist/json_helpers.c
@@ -50,44 +50,46 @@ void json_write_float_array(FILE* f, const char* tag, float* v, uint8_t count) {
uint8_t i = 0;
char * str1 = NULL;
char * str2 = NULL;
- asprintf(&str1,"\"%s\":[", tag);
+ if( asprintf(&str1,"\"%s\":[", tag) < 0 ) goto giveup;
for (i=0;i<count;++i) {
if ( (i+1) < count) {
- asprintf(&str2, "%s\"%f\"", str1,v[i]);
+ if( asprintf(&str2, "%s\"%f\"", str1,v[i]) < 0 ) goto giveup;
} else {
- asprintf(&str2, "%s\"%f\",", str1,v[i]);
+ if( asprintf(&str2, "%s\"%f\",", str1,v[i]) < 0 ) goto giveup;
}
free(str1);
str1=str2;
str2=NULL;
}
- asprintf(&str2, "%s]", str1);
+ if( asprintf(&str2, "%s]", str1) < 0 ) goto giveup;
fputs(str2,f);
- free(str1);
- free(str2);
+giveup:
+ if( str1 ) free(str1);
+ if( str2 ) free(str2);
}
void json_write_double_array(FILE* f, const char* tag, double* v, uint8_t count) {
uint8_t i = 0;
char * str1 = NULL;
char * str2 = NULL;
- asprintf(&str1,"\"%s\":[", tag);
+ if( asprintf(&str1,"\"%s\":[", tag) < 0 ) goto giveup;
for (i=0;i<count;++i) {
if (i<(count-1)) {
- asprintf(&str2, "%s\"%f\",", str1,v[i]);
+ if( asprintf(&str2, "%s\"%f\",", str1,v[i]) < 0 ) goto giveup;
} else {
- asprintf(&str2, "%s\"%f\"", str1,v[i]);
+ if( asprintf(&str2, "%s\"%f\"", str1,v[i]) < 0 ) goto giveup;
}
free(str1);
str1=str2;
str2=NULL;
}
- asprintf(&str2, "%s]", str1);
+ if( asprintf(&str2, "%s]", str1) < 0 ) goto giveup;
fputs(str2,f);
- free(str1);
- free(str2);
+giveup:
+ if( str1 ) free(str1);
+ if( str2 ) free(str2);
}
void json_write_uint32(FILE* f, const char* tag, uint32_t v) {
@@ -117,8 +119,9 @@ char* load_file_to_mem(const char* path) {
fseek( f, 0, SEEK_END );
int len = ftell( f );
fseek( f, 0, SEEK_SET );
- char * JSON_STRING = malloc( len );
- fread( JSON_STRING, len, 1, f );
+ char * JSON_STRING = malloc( len + 1);
+ memset(JSON_STRING,0,len+1);
+ int i = fread( JSON_STRING, len, 1, f ); i = i; //Ignore return value.
fclose( f );
return JSON_STRING;
}
@@ -173,7 +176,7 @@ void json_load_file(const char* path) {
int16_t children = -1;
- for (i=0; i<(int)items; i+=2)
+ for (i=0; i<(unsigned int)items; i+=2)
{
//increment i on each successful tag + values combination, not individual tokens
jsmntok_t* tag_t = tokens+i;
@@ -213,3 +216,32 @@ void json_load_file(const char* path) {
free(JSON_STRING);
}
+int parse_float_array(char* str, jsmntok_t* token, FLT** f, uint8_t count) {
+ uint16_t i = 0;
+
+ if (count==0) return 0;
+
+ if (*f!=NULL) free(*f);
+ *f = malloc(sizeof(FLT) * count);
+
+ for(i=0;i<count;++i) {
+ char* end = str + token->end;
+ char* s = str+token->start;
+
+ #ifdef USE_DOUBLE
+ (*f)[i] = strtod(s, &end);
+ #else
+ (*f)[i] = strtof(s, &end);
+ #endif
+
+ if (s == end) {
+ free(*f);
+ *f=NULL;
+ return 0; //not a float
+ }
+ token++;
+ }
+
+
+ return count;
+} \ No newline at end of file
diff --git a/redist/json_helpers.h b/redist/json_helpers.h
index 1cccfe3..3ebf66b 100644
--- a/redist/json_helpers.h
+++ b/redist/json_helpers.h
@@ -4,6 +4,8 @@
#define JSON_HELPERS_H
#include <stdint.h>
+#include <jsmn.h>
+#include "survive_types.h"
void json_write_float_array(FILE* f, const char* tag, float* v, uint8_t count);
void json_write_double_array(FILE* f, const char* tag, double* v, uint8_t count);
@@ -11,6 +13,8 @@ void json_write_uint32(FILE* f, const char* tag, uint32_t v);
void json_write_float(FILE* f, const char* tag, float v);
void json_write_str(FILE* f, const char* tag, const char* v);
+int parse_float_array(char* str, jsmntok_t* token, FLT** values, uint8_t count);
+
void json_load_file(const char* path);
extern void (*json_begin_object)(char* tag);
extern void (*json_end_object)();
diff --git a/redist/linmath.c b/redist/linmath.c
index eefcd5f..5fefe1e 100644
--- a/redist/linmath.c
+++ b/redist/linmath.c
@@ -82,6 +82,28 @@ FLT anglebetween3d( FLT * a, FLT * b )
return FLT_ACOS(dot);
}
+// algorithm found here: http://inside.mines.edu/fs_home/gmurray/ArbitraryAxisRotation/
+void rotatearoundaxis(FLT *outvec3, FLT *invec3, FLT *axis, FLT angle)
+{
+ // TODO: this really should be external.
+ normalize3d(axis, axis);
+
+ FLT s = FLT_SIN(angle);
+ FLT c = FLT_COS(angle);
+
+ FLT u=axis[0];
+ FLT v=axis[1];
+ FLT w=axis[2];
+
+ FLT x=invec3[0];
+ FLT y=invec3[1];
+ FLT z=invec3[2];
+
+ outvec3[0] = u*(u*x + v*y + w*z)*(1-c) + x*c + (-w*y + v*z)*s;
+ outvec3[1] = v*(u*x + v*y + w*z)*(1-c) + y*c + ( w*x - u*z)*s;
+ outvec3[2] = w*(u*x + v*y + w*z)*(1-c) + z*c + (-v*x + u*y)*s;
+}
+
/////////////////////////////////////QUATERNIONS//////////////////////////////////////////
//Originally from Mercury (Copyright (C) 2009 by Joshua Allen, Charles Lohr, Adam Lowman)
//Under the mit/X11 license.
@@ -215,7 +237,7 @@ void quatfrommatrix( FLT * q, const FLT * matrix44 )
q[1] = (matrix44[9] - matrix44[6]) / S;
q[2] = (matrix44[2] - matrix44[8]) / S;
q[3] = (matrix44[4] - matrix44[1]) / S;
- } else if ((matrix44[0] > matrix44[5])&(matrix44[0] > matrix44[10])) {
+ } else if ((matrix44[0] > matrix44[5])&&(matrix44[0] > matrix44[10])) {
FLT S = FLT_SQRT(1.0 + matrix44[0] - matrix44[5] - matrix44[10]) * 2.; // S=4*qx
q[0] = (matrix44[9] - matrix44[6]) / S;
q[1] = 0.25f * S;
@@ -498,17 +520,15 @@ void quatfrom2vectors(FLT *q, const FLT *src, const FLT *dest)
FLT invs = 1 / s;
FLT c[3];
- //cross3d(c, v0, v1);
- cross3d(c, v1, v0);
+ cross3d(c, v0, v1);
- q[0] = c[0] * invs;
- q[1] = c[1] * invs;
- q[2] = c[2] * invs;
- q[3] = s * 0.5f;
+ q[0] = s * 0.5f;
+ q[1] = c[0] * invs;
+ q[2] = c[1] * invs;
+ q[3] = c[2] * invs;
quatnormalize(q, q);
}
-
}
void matrix44copy(FLT * mout, const FLT * minm )
diff --git a/redist/linmath.h b/redist/linmath.h
index 4e0cb77..6f0bf60 100644
--- a/redist/linmath.h
+++ b/redist/linmath.h
@@ -70,6 +70,7 @@ FLT magnitude3d(const FLT * a );
FLT anglebetween3d( FLT * a, FLT * b );
+void rotatearoundaxis(FLT *outvec3, FLT *invec3, FLT *axis, FLT angle);
//Quaternion things...
void quatsetnone( FLT * q );
diff --git a/redist/os_generic.c b/redist/os_generic.c
index 1ab4863..3191357 100644
--- a/redist/os_generic.c
+++ b/redist/os_generic.c
@@ -151,8 +151,9 @@ void OGDeleteSema( og_sema_t os )
#else
-#define _GNU_SOURCE
-
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
#include <sys/stat.h>
#include <stdlib.h>
@@ -198,7 +199,7 @@ double OGGetFileTime( const char * file )
og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter )
{
- pthread_t * ret = malloc( sizeof( pthread_t ) );
+ pthread_t * ret = (pthread_t *)malloc( sizeof( pthread_t ) );
int r = pthread_create( ret, 0, routine, parameter );
if( r )
{
@@ -277,7 +278,7 @@ void OGDeleteMutex( og_mutex_t om )
og_sema_t OGCreateSema()
{
- sem_t * sem = malloc( sizeof( sem_t ) );
+ sem_t * sem = (sem_t *)malloc( sizeof( sem_t ) );
sem_init( sem, 0, 0 );
return (og_sema_t)sem;
}
@@ -285,24 +286,24 @@ og_sema_t OGCreateSema()
int OGGetSema( og_sema_t os )
{
int valp;
- sem_getvalue( os, &valp );
+ sem_getvalue( (sem_t *)os, &valp );
return valp;
}
void OGLockSema( og_sema_t os )
{
- sem_wait( os );
+ sem_wait( (sem_t *)os );
}
void OGUnlockSema( og_sema_t os )
{
- sem_post( os );
+ sem_post( (sem_t *)os );
}
void OGDeleteSema( og_sema_t os )
{
- sem_destroy( os );
+ sem_destroy( (sem_t *)os );
free(os);
}
diff --git a/redist/svd.h b/redist/svd.h
new file mode 100644
index 0000000..41708da
--- /dev/null
+++ b/redist/svd.h
@@ -0,0 +1,450 @@
+/**************************************************************************
+**
+** svd3
+**
+** Quick singular value decomposition as described by:
+** A. McAdams, A. Selle, R. Tamstorf, J. Teran and E. Sifakis,
+** "Computing the Singular Value Decomposition of 3x3 matrices
+** with minimal branching and elementary floating point operations",
+** University of Wisconsin - Madison technical report TR1690, May 2011
+**
+** OPTIMIZED CPU VERSION
+** Implementation by: Eric Jang
+**
+** 13 Apr 2014
+**
+** This file originally retrieved from:
+** https://github.com/ericjang/svd3/blob/master/svd3.h 3/26/2017
+**
+** Original licesnse is MIT per:
+** https://github.com/ericjang/svd3/blob/master/LICENSE.md
+**
+** Ported from C++ to C by Mike Turvey. All modifications also released
+** under an MIT license.
+**************************************************************************/
+
+
+#ifndef SVD3_H
+#define SVD3_H
+
+#define _gamma 5.828427124 // FOUR_GAMMA_SQUARED = sqrt(8)+3;
+#define _cstar 0.923879532 // cos(pi/8)
+#define _sstar 0.3826834323 // sin(p/8)
+#define EPSILON 1e-6
+
+#include <math.h>
+
+/* This is a novel and fast routine for the reciprocal square root of an
+IEEE float (single precision).
+http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf
+http://playstation2-linux.com/download/p2lsd/fastrsqrt.pdf
+http://www.beyond3d.com/content/articles/8/
+*/
+inline float rsqrt(float x) {
+ // int ihalf = *(int *)&x - 0x00800000; // Alternative to next line,
+ // float xhalf = *(float *)&ihalf; // for sufficiently large nos.
+ float xhalf = 0.5f*x;
+ int i = *(int *)&x; // View x as an int.
+ // i = 0x5f3759df - (i >> 1); // Initial guess (traditional).
+ i = 0x5f375a82 - (i >> 1); // Initial guess (slightly better).
+ x = *(float *)&i; // View i as float.
+ x = x*(1.5f - xhalf*x*x); // Newton step.
+ // x = x*(1.5008908 - xhalf*x*x); // Newton step for a balanced error.
+ return x;
+}
+
+/* This is rsqrt with an additional step of the Newton iteration, for
+increased accuracy. The constant 0x5f37599e makes the relative error
+range from 0 to -0.00000463.
+You can't balance the error by adjusting the constant. */
+inline float rsqrt1(float x) {
+ float xhalf = 0.5f*x;
+ int i = *(int *)&x; // View x as an int.
+ i = 0x5f37599e - (i >> 1); // Initial guess.
+ x = *(float *)&i; // View i as float.
+ x = x*(1.5f - xhalf*x*x); // Newton step.
+ x = x*(1.5f - xhalf*x*x); // Newton step again.
+ return x;
+}
+
+inline float accurateSqrt(float x)
+{
+ return x * rsqrt1(x);
+}
+
+inline void condSwap(bool c, float *X, float *Y)
+{
+ // used in step 2
+ float Z = *X;
+ *X = c ? *Y : *X;
+ *Y = c ? Z : *Y;
+}
+
+inline void condNegSwap(bool c, float *X, float *Y)
+{
+ // used in step 2 and 3
+ float Z = -*X;
+ *X = c ? *Y : *X;
+ *Y = c ? Z : *Y;
+}
+
+// matrix multiplication M = A * B
+inline void multAB(float a11, float a12, float a13,
+ float a21, float a22, float a23,
+ float a31, float a32, float a33,
+ //
+ float b11, float b12, float b13,
+ float b21, float b22, float b23,
+ float b31, float b32, float b33,
+ //
+ float *m11, float *m12, float *m13,
+ float *m21, float *m22, float *m23,
+ float *m31, float *m32, float *m33)
+{
+
+ *m11 = a11*b11 + a12*b21 + a13*b31; *m12 = a11*b12 + a12*b22 + a13*b32; *m13 = a11*b13 + a12*b23 + a13*b33;
+ *m21 = a21*b11 + a22*b21 + a23*b31; *m22 = a21*b12 + a22*b22 + a23*b32; *m23 = a21*b13 + a22*b23 + a23*b33;
+ *m31 = a31*b11 + a32*b21 + a33*b31; *m32 = a31*b12 + a32*b22 + a33*b32; *m33 = a31*b13 + a32*b23 + a33*b33;
+}
+
+// matrix multiplication M = Transpose[A] * B
+inline void multAtB(float a11, float a12, float a13,
+ float a21, float a22, float a23,
+ float a31, float a32, float a33,
+ //
+ float b11, float b12, float b13,
+ float b21, float b22, float b23,
+ float b31, float b32, float b33,
+ //
+ float *m11, float *m12, float *m13,
+ float *m21, float *m22, float *m23,
+ float *m31, float *m32, float *m33)
+{
+ *m11 = a11*b11 + a21*b21 + a31*b31; *m12 = a11*b12 + a21*b22 + a31*b32; *m13 = a11*b13 + a21*b23 + a31*b33;
+ *m21 = a12*b11 + a22*b21 + a32*b31; *m22 = a12*b12 + a22*b22 + a32*b32; *m23 = a12*b13 + a22*b23 + a32*b33;
+ *m31 = a13*b11 + a23*b21 + a33*b31; *m32 = a13*b12 + a23*b22 + a33*b32; *m33 = a13*b13 + a23*b23 + a33*b33;
+}
+
+inline void quatToMat3(const float * qV,
+ float *m11, float *m12, float *m13,
+ float *m21, float *m22, float *m23,
+ float *m31, float *m32, float *m33
+)
+{
+ float w = qV[3];
+ float x = qV[0];
+ float y = qV[1];
+ float z = qV[2];
+
+ float qxx = x*x;
+ float qyy = y*y;
+ float qzz = z*z;
+ float qxz = x*z;
+ float qxy = x*y;
+ float qyz = y*z;
+ float qwx = w*x;
+ float qwy = w*y;
+ float qwz = w*z;
+
+ *m11 = 1 - 2 * (qyy + qzz); *m12 = 2 * (qxy - qwz); *m13 = 2 * (qxz + qwy);
+ *m21 = 2 * (qxy + qwz); *m22 = 1 - 2 * (qxx + qzz); *m23 = 2 * (qyz - qwx);
+ *m31 = 2 * (qxz - qwy); *m32 = 2 * (qyz + qwx); *m33 = 1 - 2 * (qxx + qyy);
+}
+
+inline void approximateGivensQuaternion(float a11, float a12, float a22, float *ch, float *sh)
+{
+ /*
+ * Given givens angle computed by approximateGivensAngles,
+ * compute the corresponding rotation quaternion.
+ */
+ *ch = 2 * (a11 - a22);
+ *sh = a12;
+ bool b = _gamma* (*sh)*(*sh) < (*ch)*(*ch);
+ // fast rsqrt function suffices
+ // rsqrt2 (https://code.google.com/p/lppython/source/browse/algorithm/HDcode/newCode/rsqrt.c?r=26)
+ // is even faster but results in too much error
+ float w = rsqrt((*ch)*(*ch) + (*sh)*(*sh));
+ *ch = b ? w*(*ch) : (float)_cstar;
+ *sh = b ? w*(*sh) : (float)_sstar;
+}
+
+inline void jacobiConjugation(const int x, const int y, const int z,
+ float *s11,
+ float *s21, float *s22,
+ float *s31, float *s32, float *s33,
+ float * qV)
+{
+ float ch, sh;
+ approximateGivensQuaternion(*s11, *s21, *s22, &ch, &sh);
+
+ float scale = ch*ch + sh*sh;
+ float a = (ch*ch - sh*sh) / scale;
+ float b = (2 * sh*ch) / scale;
+
+ // make temp copy of S
+ float _s11 = *s11;
+ float _s21 = *s21; float _s22 = *s22;
+ float _s31 = *s31; float _s32 = *s32; float _s33 = *s33;
+
+ // perform conjugation S = Q'*S*Q
+ // Q already implicitly solved from a, b
+ *s11 = a*(a*_s11 + b*_s21) + b*(a*_s21 + b*_s22);
+ *s21 = a*(-b*_s11 + a*_s21) + b*(-b*_s21 + a*_s22); *s22 = -b*(-b*_s11 + a*_s21) + a*(-b*_s21 + a*_s22);
+ *s31 = a*_s31 + b*_s32; *s32 = -b*_s31 + a*_s32; *s33 = _s33;
+
+ // update cumulative rotation qV
+ float tmp[3];
+ tmp[0] = qV[0] * sh;
+ tmp[1] = qV[1] * sh;
+ tmp[2] = qV[2] * sh;
+ sh *= qV[3];
+
+ qV[0] *= ch;
+ qV[1] *= ch;
+ qV[2] *= ch;
+ qV[3] *= ch;
+
+ // (x,y,z) corresponds to ((0,1,2),(1,2,0),(2,0,1))
+ // for (p,q) = ((0,1),(1,2),(0,2))
+ qV[z] += sh;
+ qV[3] -= tmp[z]; // w
+ qV[x] += tmp[y];
+ qV[y] -= tmp[x];
+
+ // re-arrange matrix for next iteration
+ _s11 = *s22;
+ _s21 = *s32; _s22 = *s33;
+ _s31 = *s21; _s32 = *s31; _s33 = *s11;
+ *s11 = _s11;
+ *s21 = _s21; *s22 = _s22;
+ *s31 = _s31; *s32 = _s32; *s33 = _s33;
+
+}
+
+inline float dist2(float x, float y, float z)
+{
+ return x*x + y*y + z*z;
+}
+
+// finds transformation that diagonalizes a symmetric matrix
+inline void jacobiEigenanlysis( // symmetric matrix
+ float *s11,
+ float *s21, float *s22,
+ float *s31, float *s32, float *s33,
+ // quaternion representation of V
+ float * qV)
+{
+ qV[3] = 1; qV[0] = 0; qV[1] = 0; qV[2] = 0; // follow same indexing convention as GLM
+ for (int i = 0; i<4; i++)
+ {
+ // we wish to eliminate the maximum off-diagonal element
+ // on every iteration, but cycling over all 3 possible rotations
+ // in fixed order (p,q) = (1,2) , (2,3), (1,3) still retains
+ // asymptotic convergence
+ jacobiConjugation(0, 1, 2, s11, s21, s22, s31, s32, s33, qV); // p,q = 0,1
+ jacobiConjugation(1, 2, 0, s11, s21, s22, s31, s32, s33, qV); // p,q = 1,2
+ jacobiConjugation(2, 0, 1, s11, s21, s22, s31, s32, s33, qV); // p,q = 0,2
+ }
+}
+
+
+inline void sortSingularValues(// matrix that we want to decompose
+ float *b11, float *b12, float *b13,
+ float *b21, float *b22, float *b23,
+ float *b31, float *b32, float *b33,
+ // sort V simultaneously
+ float *v11, float *v12, float *v13,
+ float *v21, float *v22, float *v23,
+ float *v31, float *v32, float *v33)
+{
+ float rho1 = dist2(*b11, *b21, *b31);
+ float rho2 = dist2(*b12, *b22, *b32);
+ float rho3 = dist2(*b13, *b23, *b33);
+ bool c;
+ c = rho1 < rho2;
+ condNegSwap(c, b11, b12); condNegSwap(c, v11, v12);
+ condNegSwap(c, b21, b22); condNegSwap(c, v21, v22);
+ condNegSwap(c, b31, b32); condNegSwap(c, v31, v32);
+ condSwap(c, &rho1, &rho2);
+ c = rho1 < rho3;
+ condNegSwap(c, b11, b13); condNegSwap(c, v11, v13);
+ condNegSwap(c, b21, b23); condNegSwap(c, v21, v23);
+ condNegSwap(c, b31, b33); condNegSwap(c, v31, v33);
+ condSwap(c, &rho1, &rho3);
+ c = rho2 < rho3;
+ condNegSwap(c, b12, b13); condNegSwap(c, v12, v13);
+ condNegSwap(c, b22, b23); condNegSwap(c, v22, v23);
+ condNegSwap(c, b32, b33); condNegSwap(c, v32, v33);
+}
+
+
+void QRGivensQuaternion(float a1, float a2, float *ch, float *sh)
+{
+ // a1 = pivot point on diagonal
+ // a2 = lower triangular entry we want to annihilate
+ float epsilon = (float)EPSILON;
+ float rho = accurateSqrt(a1*a1 + a2*a2);
+
+ *sh = rho > epsilon ? a2 : 0;
+ *ch = fabsf(a1) + fmaxf(rho, epsilon);
+ bool b = a1 < 0;
+ condSwap(b, sh, ch);
+ float w = rsqrt((*ch)*(*ch) + (*sh)*(*sh));
+ *ch *= w;
+ *sh *= w;
+}
+
+
+inline void QRDecomposition(// matrix that we want to decompose
+ float b11, float b12, float b13,
+ float b21, float b22, float b23,
+ float b31, float b32, float b33,
+ // output Q
+ float *q11, float *q12, float *q13,
+ float *q21, float *q22, float *q23,
+ float *q31, float *q32, float *q33,
+ // output R
+ float *r11, float *r12, float *r13,
+ float *r21, float *r22, float *r23,
+ float *r31, float *r32, float *r33)
+{
+ float ch1, sh1, ch2, sh2, ch3, sh3;
+ float a, b;
+
+ // first givens rotation (ch,0,0,sh)
+ QRGivensQuaternion(b11, b21, &ch1, &sh1);
+ a = 1 - 2 * sh1*sh1;
+ b = 2 * ch1*sh1;
+ // apply B = Q' * B
+ *r11 = a*b11 + b*b21; *r12 = a*b12 + b*b22; *r13 = a*b13 + b*b23;
+ *r21 = -b*b11 + a*b21; *r22 = -b*b12 + a*b22; *r23 = -b*b13 + a*b23;
+ *r31 = b31; *r32 = b32; *r33 = b33;
+
+ // second givens rotation (ch,0,-sh,0)
+ QRGivensQuaternion(*r11, *r31, &ch2, &sh2);
+ a = 1 - 2 * sh2*sh2;
+ b = 2 * ch2*sh2;
+ // apply B = Q' * B;
+ b11 = a*(*r11) + b*(*r31); b12 = a*(*r12) + b*(*r32); b13 = a*(*r13) + b*(*r33);
+ b21 = *r21; b22 = *r22; b23 = *r23;
+ b31 = -b*(*r11) + a*(*r31); b32 = -b*(*r12) + a*(*r32); b33 = -b*(*r13) + a*(*r33);
+
+ // third givens rotation (ch,sh,0,0)
+ QRGivensQuaternion(b22, b32, &ch3, &sh3);
+ a = 1 - 2 * sh3*sh3;
+ b = 2 * ch3*sh3;
+ // R is now set to desired value
+ *r11 = b11; *r12 = b12; *r13 = b13;
+ *r21 = a*b21 + b*b31; *r22 = a*b22 + b*b32; *r23 = a*b23 + b*b33;
+ *r31 = -b*b21 + a*b31; *r32 = -b*b22 + a*b32; *r33 = -b*b23 + a*b33;
+
+ // construct the cumulative rotation Q=Q1 * Q2 * Q3
+ // the number of floating point operations for three quaternion multiplications
+ // is more or less comparable to the explicit form of the joined matrix.
+ // certainly more memory-efficient!
+ float sh12 = sh1*sh1;
+ float sh22 = sh2*sh2;
+ float sh32 = sh3*sh3;
+
+ *q11 = (-1 + 2 * sh12)*(-1 + 2 * sh22);
+ *q12 = 4 * ch2*ch3*(-1 + 2 * sh12)*sh2*sh3 + 2 * ch1*sh1*(-1 + 2 * sh32);
+ *q13 = 4 * ch1*ch3*sh1*sh3 - 2 * ch2*(-1 + 2 * sh12)*sh2*(-1 + 2 * sh32);
+
+ *q21 = 2 * ch1*sh1*(1 - 2 * sh22);
+ *q22 = -8 * ch1*ch2*ch3*sh1*sh2*sh3 + (-1 + 2 * sh12)*(-1 + 2 * sh32);
+ *q23 = -2 * ch3*sh3 + 4 * sh1*(ch3*sh1*sh3 + ch1*ch2*sh2*(-1 + 2 * sh32));
+
+ *q31 = 2 * ch2*sh2;
+ *q32 = 2 * ch3*(1 - 2 * sh22)*sh3;
+ *q33 = (-1 + 2 * sh22)*(-1 + 2 * sh32);
+}
+
+void svd(// input A
+ float a11, float a12, float a13,
+ float a21, float a22, float a23,
+ float a31, float a32, float a33,
+ // output U
+ float *u11, float *u12, float *u13,
+ float *u21, float *u22, float *u23,
+ float *u31, float *u32, float *u33,
+ // output S
+ float *s11, float *s12, float *s13,
+ float *s21, float *s22, float *s23,
+ float *s31, float *s32, float *s33,
+ // output V
+ float *v11, float *v12, float *v13,
+ float *v21, float *v22, float *v23,
+ float *v31, float *v32, float *v33)
+{
+ // normal equations matrix
+ float ATA11, ATA12, ATA13;
+ float ATA21, ATA22, ATA23;
+ float ATA31, ATA32, ATA33;
+
+ multAtB(a11, a12, a13, a21, a22, a23, a31, a32, a33,
+ a11, a12, a13, a21, a22, a23, a31, a32, a33,
+ &ATA11, &ATA12, &ATA13, &ATA21, &ATA22, &ATA23, &ATA31, &ATA32, &ATA33);
+
+ // symmetric eigenalysis
+ float qV[4];
+ jacobiEigenanlysis(&ATA11, &ATA21, &ATA22, &ATA31, &ATA32, &ATA33, qV);
+ quatToMat3(qV, v11, v12, v13, v21, v22, v23, v31, v32, v33);
+
+ float b11, b12, b13;
+ float b21, b22, b23;
+ float b31, b32, b33;
+ multAB(a11, a12, a13, a21, a22, a23, a31, a32, a33,
+ *v11, *v12, *v13, *v21, *v22, *v23, *v31, *v32, *v33,
+ &b11, &b12, &b13, &b21, &b22, &b23, &b31, &b32, &b33);
+
+ // sort singular values and find V
+ sortSingularValues(&b11, &b12, &b13, &b21, &b22, &b23, &b31, &b32, &b33,
+ v11, v12, v13, v21, v22, v23, v31, v32, v33);
+
+ // QR decomposition
+ QRDecomposition(b11, b12, b13, b21, b22, b23, b31, b32, b33,
+ u11, u12, u13, u21, u22, u23, u31, u32, u33,
+ s11, s12, s13, s21, s22, s23, s31, s32, s33
+ );
+}
+
+/// polar decomposition can be reconstructed trivially from SVD result
+// A = UP
+void pd(float a11, float a12, float a13,
+ float a21, float a22, float a23,
+ float a31, float a32, float a33,
+ // output U
+ float *u11, float *u12, float *u13,
+ float *u21, float *u22, float *u23,
+ float *u31, float *u32, float *u33,
+ // output P
+ float *p11, float *p12, float *p13,
+ float *p21, float *p22, float *p23,
+ float *p31, float *p32, float *p33)
+{
+ float w11, w12, w13, w21, w22, w23, w31, w32, w33;
+ float s11, s12, s13, s21, s22, s23, s31, s32, s33;
+ float v11, v12, v13, v21, v22, v23, v31, v32, v33;
+
+ svd(a11, a12, a13, a21, a22, a23, a31, a32, a33,
+ &w11, &w12, &w13, &w21, &w22, &w23, &w31, &w32, &w33,
+ &s11, &s12, &s13, &s21, &s22, &s23, &s31, &s32, &s33,
+ &v11, &v12, &v13, &v21, &v22, &v23, &v31, &v32, &v33);
+
+ // P = VSV'
+ float t11, t12, t13, t21, t22, t23, t31, t32, t33;
+ multAB(v11, v12, v13, v21, v22, v23, v31, v32, v33,
+ s11, s12, s13, s21, s22, s23, s31, s32, s33,
+ &t11, &t12, &t13, &t21, &t22, &t23, &t31, &t32, &t33);
+
+ multAB(t11, t12, t13, t21, t22, t23, t31, t32, t33,
+ v11, v21, v31, v12, v22, v32, v13, v23, v33,
+ p11, p12, p13, p21, p22, p23, p31, p32, p33);
+
+ // U = WV'
+ multAB(w11, w12, w13, w21, w22, w23, w31, w32, w33,
+ v11, v21, v31, v12, v22, v32, v13, v23, v33,
+ u11, u12, u13, u21, u22, u23, u31, u32, u33);
+}
+
+#endif \ No newline at end of file